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_ */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to