svn commit: r303948 - head/sys/dev/hyperv/netvsc

Sepherosa Ziehau sephe at FreeBSD.org
Thu Aug 11 06:14:56 UTC 2016


Author: sephe
Date: Thu Aug 11 06:14:54 2016
New Revision: 303948
URL: https://svnweb.freebsd.org/changeset/base/303948

Log:
  hyperv/hn: Switch to vmbus xact APIs for NVS initialization
  
  Reviewed by:	Jun Su <junsu microsoft com>
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D7457

Added:
  head/sys/dev/hyperv/netvsc/if_hnreg.h   (contents, props changed)
Modified:
  head/sys/dev/hyperv/netvsc/hv_net_vsc.c
  head/sys/dev/hyperv/netvsc/hv_net_vsc.h
  head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  head/sys/dev/hyperv/netvsc/if_hnvar.h

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.c	Thu Aug 11 05:49:49 2016	(r303947)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.c	Thu Aug 11 06:14:54 2016	(r303948)
@@ -45,9 +45,11 @@
 #include <machine/atomic.h>
 
 #include <dev/hyperv/include/hyperv.h>
-#include "hv_net_vsc.h"
-#include "hv_rndis.h"
-#include "hv_rndis_filter.h"
+#include <dev/hyperv/include/vmbus_xact.h>
+#include <dev/hyperv/netvsc/hv_net_vsc.h>
+#include <dev/hyperv/netvsc/hv_rndis.h>
+#include <dev/hyperv/netvsc/hv_rndis_filter.h>
+#include <dev/hyperv/netvsc/if_hnreg.h>
 
 MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver");
 
@@ -70,7 +72,10 @@ static void hv_nv_on_receive(netvsc_dev 
     const struct vmbus_chanpkt_hdr *pkt);
 static void hn_nvs_sent_none(struct hn_send_ctx *sndc,
     struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
-    const struct nvsp_msg_ *msg);
+    const struct nvsp_msg_ *msg, int);
+static void hn_nvs_sent_xact(struct hn_send_ctx *sndc,
+    struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
+    const struct nvsp_msg_ *msg, int dlen);
 
 static struct hn_send_ctx	hn_send_ctx_none =
     HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL);
@@ -462,45 +467,64 @@ hv_nv_destroy_send_buffer(netvsc_dev *ne
 	return (ret);
 }
 
-
-/*
- * Attempt to negotiate the caller-specified NVSP version
- *
- * For NVSP v2, Server 2008 R2 does not set
- * init_pkt->msgs.init_msgs.init_compl.negotiated_prot_vers
- * to the negotiated version, so we cannot rely on that.
- */
 static int
 hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev,
-    uint32_t nvsp_ver)
+    uint32_t nvs_ver)
 {
 	struct hn_send_ctx sndc;
-	nvsp_msg *init_pkt;
-	int ret;
-
-	init_pkt = &net_dev->channel_init_packet;
-	memset(init_pkt, 0, sizeof(nvsp_msg));
-	init_pkt->hdr.msg_type = nvsp_msg_type_init;
+	struct vmbus_xact *xact;
+	struct hn_nvs_init *init;
+	const struct hn_nvs_init_resp *resp;
+	size_t resp_len;
+	uint32_t status;
+	int error;
+
+	xact = vmbus_xact_get(sc->hn_xact, sizeof(*init));
+	if (xact == NULL) {
+		if_printf(sc->hn_ifp, "no xact for nvs init\n");
+		return (ENXIO);
+	}
+
+	init = vmbus_xact_req_data(xact);
+	init->nvs_type = HN_NVS_TYPE_INIT;
+	init->nvs_ver_min = nvs_ver;
+	init->nvs_ver_max = nvs_ver;
 
-	/*
-	 * Specify parameter as the only acceptable protocol version
-	 */
-	init_pkt->msgs.init_msgs.init.p1.protocol_version = nvsp_ver;
-	init_pkt->msgs.init_msgs.init.protocol_version_2 = nvsp_ver;
+	vmbus_xact_activate(xact);
+	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
 
-	/* Send the init request */
-	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
-	ret = vmbus_chan_send(sc->hn_prichan,
+	error = vmbus_chan_send(sc->hn_prichan,
 	    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-	    init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
-	if (ret != 0)
-		return (-1);
-
-	sema_wait(&net_dev->channel_init_sema);
+	    init, sizeof(*init), (uint64_t)(uintptr_t)&sndc);
+	if (error) {
+		if_printf(sc->hn_ifp, "send nvs init failed: %d\n", error);
+		vmbus_xact_deactivate(xact);
+		vmbus_xact_put(xact);
+		return (error);
+	}
 
-	if (init_pkt->msgs.init_msgs.init_compl.status != nvsp_status_success)
+	resp = vmbus_xact_wait(xact, &resp_len);
+	if (resp_len < sizeof(*resp)) {
+		if_printf(sc->hn_ifp, "invalid init resp length %zu\n",
+		    resp_len);
+		vmbus_xact_put(xact);
 		return (EINVAL);
+	}
+	if (resp->nvs_type != HN_NVS_TYPE_INIT_RESP) {
+		if_printf(sc->hn_ifp, "not init resp, type %u\n",
+		    resp->nvs_type);
+		vmbus_xact_put(xact);
+		return (EINVAL);
+	}
+
+	status = resp->nvs_status;
+	vmbus_xact_put(xact);
 
+	if (status != HN_NVS_STATUS_OK) {
+		if_printf(sc->hn_ifp, "nvs init failed for ver 0x%x\n",
+		    nvs_ver);
+		return (EINVAL);
+	}
 	return (0);
 }
 
@@ -744,7 +768,7 @@ hv_nv_on_device_remove(struct hn_softc *
 void
 hn_nvs_sent_wakeup(struct hn_send_ctx *sndc __unused,
     struct netvsc_dev_ *net_dev, struct vmbus_channel *chan __unused,
-    const struct nvsp_msg_ *msg)
+    const struct nvsp_msg_ *msg, int dlen __unused)
 {
 	/* Copy the response back */
 	memcpy(&net_dev->channel_init_packet, msg, sizeof(nvsp_msg));
@@ -752,9 +776,18 @@ hn_nvs_sent_wakeup(struct hn_send_ctx *s
 }
 
 static void
+hn_nvs_sent_xact(struct hn_send_ctx *sndc,
+    struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused,
+    const struct nvsp_msg_ *msg, int dlen)
+{
+
+	vmbus_xact_wakeup(sndc->hn_cbarg, msg, dlen);
+}
+
+static void
 hn_nvs_sent_none(struct hn_send_ctx *sndc __unused,
     struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused,
-    const struct nvsp_msg_ *msg __unused)
+    const struct nvsp_msg_ *msg __unused, int dlen __unused)
 {
 	/* EMPTY */
 }
@@ -788,7 +821,8 @@ hv_nv_on_send_completion(netvsc_dev *net
 	struct hn_send_ctx *sndc;
 
 	sndc = (struct hn_send_ctx *)(uintptr_t)pkt->cph_xactid;
-	sndc->hn_cb(sndc, net_dev, chan, VMBUS_CHANPKT_CONST_DATA(pkt));
+	sndc->hn_cb(sndc, net_dev, chan, VMBUS_CHANPKT_CONST_DATA(pkt),
+	    VMBUS_CHANPKT_DATALEN(pkt));
 	/*
 	 * NOTE:
 	 * 'sndc' CAN NOT be accessed anymore, since it can be freed by

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.h	Thu Aug 11 05:49:49 2016	(r303947)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h	Thu Aug 11 06:14:54 2016	(r303948)
@@ -1243,6 +1243,7 @@ typedef struct hn_softc {
 	struct taskqueue *hn_tx_taskq;
 	struct sysctl_oid *hn_tx_sysctl_tree;
 	struct sysctl_oid *hn_rx_sysctl_tree;
+	struct vmbus_xact_ctx *hn_xact;
 } hn_softc_t;
 
 /*

Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Thu Aug 11 05:49:49 2016	(r303947)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Thu Aug 11 06:14:54 2016	(r303948)
@@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/hyperv/include/hyperv.h>
 #include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/hyperv/include/vmbus_xact.h>
 
 #include "hv_net_vsc.h"
 #include "hv_rndis.h"
@@ -124,6 +125,9 @@ __FBSDID("$FreeBSD$");
 /* Short for Hyper-V network interface */
 #define NETVSC_DEVNAME    "hn"
 
+#define HN_XACT_REQ_SIZE		(2 * PAGE_SIZE)
+#define HN_XACT_RESP_SIZE		(2 * PAGE_SIZE)
+
 /*
  * It looks like offset 0 of buf is reserved to hold the softc pointer.
  * The sc pointer evidently not needed, and is not presently populated.
@@ -542,6 +546,11 @@ netvsc_attach(device_t dev)
 	    IFCAP_LRO;
 	ifp->if_hwassist = sc->hn_tx_ring[0].hn_csum_assist | CSUM_TSO;
 
+	sc->hn_xact = vmbus_xact_ctx_create(bus_get_dma_tag(dev),
+	    HN_XACT_REQ_SIZE, HN_XACT_RESP_SIZE);
+	if (sc->hn_xact == NULL)
+		goto failed;
+
 	error = hv_rf_on_device_add(sc, &device_info, ring_cnt,
 	    &sc->hn_rx_ring[0]);
 	if (error)
@@ -643,6 +652,7 @@ netvsc_detach(device_t dev)
 	if (sc->hn_tx_taskq != hn_tx_taskq)
 		taskqueue_free(sc->hn_tx_taskq);
 
+	vmbus_xact_ctx_destroy(sc->hn_xact);
 	return (0);
 }
 
@@ -782,7 +792,8 @@ hn_txeof(struct hn_tx_ring *txr)
 
 static void
 hn_tx_done(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
-    struct vmbus_channel *chan, const struct nvsp_msg_ *msg __unused)
+    struct vmbus_channel *chan, const struct nvsp_msg_ *msg __unused,
+    int dlen __unused)
 {
 	struct hn_txdesc *txd = sndc->hn_cbarg;
 	struct hn_tx_ring *txr;

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Thu Aug 11 05:49:49 2016	(r303947)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Thu Aug 11 06:14:54 2016	(r303948)
@@ -91,10 +91,10 @@ hv_rf_send_offload_request(struct hn_sof
 
 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
     struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
-    const struct nvsp_msg_ *msg);
+    const struct nvsp_msg_ *msg, int dlen);
 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
     struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
-    const struct nvsp_msg_ *msg);
+    const struct nvsp_msg_ *msg, int dlen);
 
 /*
  * Set the Per-Packet-Info with the specified type
@@ -1239,7 +1239,8 @@ hv_rf_on_close(struct hn_softc *sc)
 
 static void
 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
-    struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused)
+    struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused,
+    int dlen __unused)
 {
 	if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
 		hn_chim_free(net_dev, sndc->hn_chim_idx);
@@ -1247,7 +1248,8 @@ hn_rndis_sent_cb(struct hn_send_ctx *snd
 
 static void
 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
-    struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused)
+    struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused,
+    int dlen __unused)
 {
 	rndis_request *request = sndc->hn_cbarg;
 

Added: head/sys/dev/hyperv/netvsc/if_hnreg.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/hyperv/netvsc/if_hnreg.h	Thu Aug 11 06:14:54 2016	(r303948)
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2016 Microsoft Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _IF_HNREG_H_
+#define _IF_HNREG_H_
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#define HN_NVS_STATUS_OK		1
+
+#define HN_NVS_TYPE_INIT		1
+#define HN_NVS_TYPE_INIT_RESP		2
+
+/*
+ * Any size less than this one will _not_ work, e.g. hn_nvs_init
+ * only has 12B valid data, however, if only 12B data were sent,
+ * Hypervisor would never reply.
+ */
+#define HN_NVS_REQSIZE_MIN		32
+
+struct hn_nvs_init {
+	uint32_t	nvs_type;	/* HN_NVS_TYPE_INIT */
+	uint32_t	nvs_ver_min;
+	uint32_t	nvs_ver_max;
+	uint8_t		nvs_rsvd[20];
+} __packed;
+CTASSERT(sizeof(struct hn_nvs_init) >= HN_NVS_REQSIZE_MIN);
+
+struct hn_nvs_init_resp {
+	uint32_t	nvs_type;	/* HN_NVS_TYPE_INIT_RESP */
+	uint32_t	nvs_ver;	/* deprecated */
+	uint32_t	nvs_rsvd;
+	uint32_t	nvs_status;	/* HN_NVS_STATUS_ */
+} __packed;
+
+#endif	/* !_IF_HNREG_H_ */

Modified: head/sys/dev/hyperv/netvsc/if_hnvar.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hnvar.h	Thu Aug 11 05:49:49 2016	(r303947)
+++ head/sys/dev/hyperv/netvsc/if_hnvar.h	Thu Aug 11 06:14:54 2016	(r303948)
@@ -40,7 +40,7 @@ struct hn_send_ctx;
 
 typedef void		(*hn_sent_callback_t)
 			(struct hn_send_ctx *, struct netvsc_dev_ *,
-			 struct vmbus_channel *, const struct nvsp_msg_ *);
+			 struct vmbus_channel *, const struct nvsp_msg_ *, int);
 
 struct hn_send_ctx {
 	hn_sent_callback_t	hn_cb;
@@ -77,7 +77,7 @@ hn_send_ctx_init_simple(struct hn_send_c
 
 void		hn_nvs_sent_wakeup(struct hn_send_ctx *sndc,
 		    struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
-		    const struct nvsp_msg_ *msg);
+		    const struct nvsp_msg_ *msg, int dlen);
 void		hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx);
 
 #endif	/* !_IF_HNVAR_H_ */


More information about the svn-src-head mailing list