Author: sephe
Date: Mon Oct 17 06:47:34 2016
New Revision: 307480
URL: https://svnweb.freebsd.org/changeset/base/307480

Log:
  MFC 304441,304444,304446,304447,304591,304593-304595
  
  304441
      hyperv/hn: Move NVS version to softc
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7553
  
  304444
      hyperv/hn: Remove assign-only struct field
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7554
  
  304446
      hyperv/hn: Remove the useless num_channel
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7555
  
  304447
      hyperv/hn: Move RXBUF to hn_softc
  
      And don't recreate RXBUF for each primary channel open, it is now
      created in device_attach DEVMETHOD and destroyed in device_detach
      DEVMETHOD.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7556
  
  304591
      hyperv/hn: Move chimney sending buffer to hn_softc
  
      And don't recreate chimney sending buffer for each primary channel
      open, it is now created in device_attach DEVMETHOD and destroyed
      in device_detach DEVMETHOD.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7574
  
  304593
      hyperv/hn: Get rid of netvsc_dev
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7575
  
  304594
      hyperv/hn: Factor out function to execute NVS transactions.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7577
  
  304595
      hyperv/hn: Factor out function to simplify NVS request sending
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7578

Modified:
  stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.h
  stable/11/sys/dev/hyperv/netvsc/if_hnvar.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c        Mon Oct 17 06:18:10 
2016        (r307479)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c        Mon Oct 17 06:47:34 
2016        (r307480)
@@ -37,6 +37,7 @@
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/socket.h>
+#include <sys/limits.h>
 #include <sys/lock.h>
 #include <net/if.h>
 #include <net/if_var.h>
@@ -59,85 +60,78 @@ MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper
 static void hv_nv_on_channel_callback(struct vmbus_channel *chan,
     void *xrxr);
 static int  hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc);
-static int  hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *);
-static int  hv_nv_destroy_send_buffer(netvsc_dev *net_dev);
-static int  hv_nv_destroy_rx_buffer(netvsc_dev *net_dev);
+static int  hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *, int);
+static int  hv_nv_destroy_send_buffer(struct hn_softc *sc);
+static int  hv_nv_destroy_rx_buffer(struct hn_softc *sc);
 static int  hv_nv_connect_to_vsp(struct hn_softc *sc);
-static void hv_nv_on_send_completion(netvsc_dev *net_dev,
+static void hv_nv_on_send_completion(struct hn_softc *sc,
     struct vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt);
 static void hv_nv_on_receive_completion(struct vmbus_channel *chan,
     uint64_t tid);
-static void hv_nv_on_receive(netvsc_dev *net_dev,
+static void hv_nv_on_receive(struct hn_softc *sc,
     struct hn_rx_ring *rxr, struct vmbus_channel *chan,
     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,
+    struct hn_softc *, struct vmbus_channel *chan,
     const void *, int);
+static void hn_nvs_sent_xact(struct hn_send_ctx *, struct hn_softc *sc,
+    struct vmbus_channel *, const void *, int);
 
 static struct hn_send_ctx      hn_send_ctx_none =
     HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL);
 
-/*
- *
- */
-static inline netvsc_dev *
-hv_nv_alloc_net_device(struct hn_softc *sc)
+uint32_t
+hn_chim_alloc(struct hn_softc *sc)
 {
-       netvsc_dev *net_dev;
+       int i, bmap_cnt = sc->hn_chim_bmap_cnt;
+       u_long *bmap = sc->hn_chim_bmap;
+       uint32_t ret = HN_NVS_CHIM_IDX_INVALID;
 
-       net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_WAITOK | M_ZERO);
+       for (i = 0; i < bmap_cnt; ++i) {
+               int idx;
 
-       net_dev->sc = sc;
-       net_dev->destroy = FALSE;
-       sc->net_dev = net_dev;
+               idx = ffsl(~bmap[i]);
+               if (idx == 0)
+                       continue;
 
-       return (net_dev);
-}
+               --idx; /* ffsl is 1-based */
+               KASSERT(i * LONG_BIT + idx < sc->hn_chim_cnt,
+                   ("invalid i %d and idx %d", i, idx));
 
-/*
- * XXX unnecessary; nuke it.
- */
-static inline netvsc_dev *
-hv_nv_get_outbound_net_device(struct hn_softc *sc)
-{
-       return sc->net_dev;
-}
+               if (atomic_testandset_long(&bmap[i], idx))
+                       continue;
 
-/*
- * XXX unnecessary; nuke it.
- */
-static inline netvsc_dev *
-hv_nv_get_inbound_net_device(struct hn_softc *sc)
-{
-       return sc->net_dev;
+               ret = i * LONG_BIT + idx;
+               break;
+       }
+       return (ret);
 }
 
-int
-hv_nv_get_next_send_section(netvsc_dev *net_dev)
+const void *
+hn_nvs_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact,
+    void *req, int reqlen, size_t *resp_len)
 {
-       unsigned long bitsmap_words = net_dev->bitsmap_words;
-       unsigned long *bitsmap = net_dev->send_section_bitsmap;
-       unsigned long idx;
-       int ret = HN_NVS_CHIM_IDX_INVALID;
-       int i;
-
-       for (i = 0; i < bitsmap_words; i++) {
-               idx = ffsl(~bitsmap[i]);
-               if (0 == idx)
-                       continue;
-
-               idx--;
-               KASSERT(i * BITS_PER_LONG + idx < net_dev->send_section_count,
-                   ("invalid i %d and idx %lu", i, idx));
+       struct hn_send_ctx sndc;
+       int error;
 
-               if (atomic_testandset_long(&bitsmap[i], idx))
-                       continue;
+       hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
+       vmbus_xact_activate(xact);
 
-               ret = i * BITS_PER_LONG + idx;
-               break;
+       error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC,
+           req, reqlen, &sndc);
+       if (error) {
+               vmbus_xact_deactivate(xact);
+               return NULL;
        }
+       return (vmbus_xact_wait(xact, resp_len));
+}
 
-       return (ret);
+static __inline int
+hn_nvs_req_send(struct hn_softc *sc, void *req, int reqlen)
+{
+
+       return (hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE,
+           req, reqlen, &hn_send_ctx_none));
 }
 
 /*
@@ -147,29 +141,17 @@ hv_nv_get_next_send_section(netvsc_dev *
  *     Hyper-V extensible switch and the synthetic data path.
  */
 static int 
-hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc)
+hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc, int rxbuf_size)
 {
-       struct vmbus_xact *xact;
+       struct vmbus_xact *xact = NULL;
        struct hn_nvs_rxbuf_conn *conn;
        const struct hn_nvs_rxbuf_connresp *resp;
        size_t resp_len;
-       struct hn_send_ctx sndc;
-       netvsc_dev *net_dev;
        uint32_t status;
        int error;
 
-       net_dev = hv_nv_get_outbound_net_device(sc);
-       if (!net_dev) {
-               return (ENODEV);
-       }
-
-       net_dev->rx_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev),
-           PAGE_SIZE, 0, net_dev->rx_buf_size, &net_dev->rxbuf_dma,
-           BUS_DMA_WAITOK | BUS_DMA_ZERO);
-       if (net_dev->rx_buf == NULL) {
-               device_printf(sc->hn_dev, "allocate rxbuf failed\n");
-               return (ENOMEM);
-       }
+       KASSERT(rxbuf_size <= NETVSC_RECEIVE_BUFFER_SIZE,
+           ("invalid rxbuf size %d", rxbuf_size));
 
        /*
         * Connect the RXBUF GPADL to the primary channel.
@@ -179,8 +161,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct
         * just share this RXBUF.
         */
        error = vmbus_chan_gpadl_connect(sc->hn_prichan,
-           net_dev->rxbuf_dma.hv_paddr, net_dev->rx_buf_size,
-           &net_dev->rx_buf_gpadl_handle);
+           sc->hn_rxbuf_dma.hv_paddr, rxbuf_size, &sc->hn_rxbuf_gpadl);
        if (error) {
                if_printf(sc->hn_ifp, "rxbuf gpadl connect failed: %d\n",
                    error);
@@ -197,55 +178,47 @@ hv_nv_init_rx_buffer_with_net_vsp(struct
                error = ENXIO;
                goto cleanup;
        }
-
        conn = vmbus_xact_req_data(xact);
        conn->nvs_type = HN_NVS_TYPE_RXBUF_CONN;
-       conn->nvs_gpadl = net_dev->rx_buf_gpadl_handle;
+       conn->nvs_gpadl = sc->hn_rxbuf_gpadl;
        conn->nvs_sig = HN_NVS_RXBUF_SIG;
 
-       hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
-       vmbus_xact_activate(xact);
-
-       error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC,
-           conn, sizeof(*conn), &sndc);
-       if (error != 0) {
-               if_printf(sc->hn_ifp, "send nvs rxbuf conn failed: %d\n",
-                   error);
-               vmbus_xact_deactivate(xact);
-               vmbus_xact_put(xact);
+       resp = hn_nvs_xact_execute(sc, xact, conn, sizeof(*conn), &resp_len);
+       if (resp == NULL) {
+               if_printf(sc->hn_ifp, "exec rxbuf conn failed\n");
+               error = EIO;
                goto cleanup;
        }
-
-       resp = vmbus_xact_wait(xact, &resp_len);
        if (resp_len < sizeof(*resp)) {
                if_printf(sc->hn_ifp, "invalid rxbuf conn resp length %zu\n",
                    resp_len);
-               vmbus_xact_put(xact);
                error = EINVAL;
                goto cleanup;
        }
        if (resp->nvs_type != HN_NVS_TYPE_RXBUF_CONNRESP) {
                if_printf(sc->hn_ifp, "not rxbuf conn resp, type %u\n",
                    resp->nvs_type);
-               vmbus_xact_put(xact);
                error = EINVAL;
                goto cleanup;
        }
 
        status = resp->nvs_status;
        vmbus_xact_put(xact);
+       xact = NULL;
 
        if (status != HN_NVS_STATUS_OK) {
                if_printf(sc->hn_ifp, "rxbuf conn failed: %x\n", status);
                error = EIO;
                goto cleanup;
        }
-       net_dev->rx_section_count = 1;
+       sc->hn_flags |= HN_FLAG_RXBUF_CONNECTED;
 
        return (0);
 
 cleanup:
-       hv_nv_destroy_rx_buffer(net_dev);
+       if (xact != NULL)
+               vmbus_xact_put(xact);
+       hv_nv_destroy_rx_buffer(sc);
        return (error);
 }
 
@@ -255,28 +228,13 @@ cleanup:
 static int 
 hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc)
 {
-       struct hn_send_ctx sndc;
-       struct vmbus_xact *xact;
+       struct vmbus_xact *xact = NULL;
        struct hn_nvs_chim_conn *chim;
        const struct hn_nvs_chim_connresp *resp;
        size_t resp_len;
        uint32_t status, sectsz;
-       netvsc_dev *net_dev;
        int error;
 
-       net_dev = hv_nv_get_outbound_net_device(sc);
-       if (!net_dev) {
-               return (ENODEV);
-       }
-
-       net_dev->send_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev),
-           PAGE_SIZE, 0, net_dev->send_buf_size, &net_dev->txbuf_dma,
-           BUS_DMA_WAITOK | BUS_DMA_ZERO);
-       if (net_dev->send_buf == NULL) {
-               device_printf(sc->hn_dev, "allocate chimney txbuf failed\n");
-               return (ENOMEM);
-       }
-
        /*
         * Connect chimney sending buffer GPADL to the primary channel.
         *
@@ -285,8 +243,8 @@ hv_nv_init_send_buffer_with_net_vsp(stru
         * Sub-channels just share this chimney sending buffer.
         */
        error = vmbus_chan_gpadl_connect(sc->hn_prichan,
-           net_dev->txbuf_dma.hv_paddr, net_dev->send_buf_size,
-           &net_dev->send_buf_gpadl_handle);
+           sc->hn_chim_dma.hv_paddr, NETVSC_SEND_BUFFER_SIZE,
+           &sc->hn_chim_gpadl);
        if (error) {
                if_printf(sc->hn_ifp, "chimney sending buffer gpadl "
                    "connect failed: %d\n", error);
@@ -303,37 +261,26 @@ hv_nv_init_send_buffer_with_net_vsp(stru
                error = ENXIO;
                goto cleanup;
        }
-
        chim = vmbus_xact_req_data(xact);
        chim->nvs_type = HN_NVS_TYPE_CHIM_CONN;
-       chim->nvs_gpadl = net_dev->send_buf_gpadl_handle;
+       chim->nvs_gpadl = sc->hn_chim_gpadl;
        chim->nvs_sig = HN_NVS_CHIM_SIG;
 
-       hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
-       vmbus_xact_activate(xact);
-
-       error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC,
-           chim, sizeof(*chim), &sndc);
-       if (error) {
-               if_printf(sc->hn_ifp, "send nvs chim conn failed: %d\n",
-                   error);
-               vmbus_xact_deactivate(xact);
-               vmbus_xact_put(xact);
+       resp = hn_nvs_xact_execute(sc, xact, chim, sizeof(*chim), &resp_len);
+       if (resp == NULL) {
+               if_printf(sc->hn_ifp, "exec chim conn failed\n");
+               error = EIO;
                goto cleanup;
        }
-
-       resp = vmbus_xact_wait(xact, &resp_len);
        if (resp_len < sizeof(*resp)) {
                if_printf(sc->hn_ifp, "invalid chim conn resp length %zu\n",
                    resp_len);
-               vmbus_xact_put(xact);
                error = EINVAL;
                goto cleanup;
        }
        if (resp->nvs_type != HN_NVS_TYPE_CHIM_CONNRESP) {
                if_printf(sc->hn_ifp, "not chim conn resp, type %u\n",
                    resp->nvs_type);
-               vmbus_xact_put(xact);
                error = EINVAL;
                goto cleanup;
        }
@@ -341,6 +288,7 @@ hv_nv_init_send_buffer_with_net_vsp(stru
        status = resp->nvs_status;
        sectsz = resp->nvs_sectsz;
        vmbus_xact_put(xact);
+       xact = NULL;
 
        if (status != HN_NVS_STATUS_OK) {
                if_printf(sc->hn_ifp, "chim conn failed: %x\n", status);
@@ -353,23 +301,33 @@ hv_nv_init_send_buffer_with_net_vsp(stru
                return 0;
        }
 
-       net_dev->send_section_size = sectsz;
-       net_dev->send_section_count =
-           net_dev->send_buf_size / net_dev->send_section_size;
-       net_dev->bitsmap_words = howmany(net_dev->send_section_count,
-           BITS_PER_LONG);
-       net_dev->send_section_bitsmap =
-           malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC,
-           M_WAITOK | M_ZERO);
+       sc->hn_chim_szmax = sectsz;
+       sc->hn_chim_cnt = NETVSC_SEND_BUFFER_SIZE / sc->hn_chim_szmax;
+       if (NETVSC_SEND_BUFFER_SIZE % sc->hn_chim_szmax != 0) {
+               if_printf(sc->hn_ifp, "chimney sending sections are "
+                   "not properly aligned\n");
+       }
+       if (sc->hn_chim_cnt % LONG_BIT != 0) {
+               if_printf(sc->hn_ifp, "discard %d chimney sending sections\n",
+                   sc->hn_chim_cnt % LONG_BIT);
+       }
+
+       sc->hn_chim_bmap_cnt = sc->hn_chim_cnt / LONG_BIT;
+       sc->hn_chim_bmap = malloc(sc->hn_chim_bmap_cnt * sizeof(u_long),
+           M_NETVSC, M_WAITOK | M_ZERO);
 
+       /* Done! */
+       sc->hn_flags |= HN_FLAG_CHIM_CONNECTED;
        if (bootverbose) {
-               if_printf(sc->hn_ifp, "chimney sending buffer %u/%u\n",
-                   net_dev->send_section_size, net_dev->send_section_count);
+               if_printf(sc->hn_ifp, "chimney sending buffer %d/%d\n",
+                   sc->hn_chim_szmax, sc->hn_chim_cnt);
        }
        return 0;
 
 cleanup:
-       hv_nv_destroy_send_buffer(net_dev);
+       if (xact != NULL)
+               vmbus_xact_put(xact);
+       hv_nv_destroy_send_buffer(sc);
        return (error);
 }
 
@@ -377,11 +335,11 @@ cleanup:
  * Net VSC destroy receive buffer
  */
 static int
-hv_nv_destroy_rx_buffer(netvsc_dev *net_dev)
+hv_nv_destroy_rx_buffer(struct hn_softc *sc)
 {
        int ret = 0;
 
-       if (net_dev->rx_section_count) {
+       if (sc->hn_flags & HN_FLAG_RXBUF_CONNECTED) {
                struct hn_nvs_rxbuf_disconn disconn;
 
                /*
@@ -392,37 +350,28 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_
                disconn.nvs_sig = HN_NVS_RXBUF_SIG;
 
                /* NOTE: No response. */
-               ret = hn_nvs_send(net_dev->sc->hn_prichan,
-                   VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn),
-                   &hn_send_ctx_none);
+               ret = hn_nvs_req_send(sc, &disconn, sizeof(disconn));
                if (ret != 0) {
-                       if_printf(net_dev->sc->hn_ifp,
+                       if_printf(sc->hn_ifp,
                            "send rxbuf disconn failed: %d\n", ret);
                        return (ret);
                }
-               net_dev->rx_section_count = 0;
+               sc->hn_flags &= ~HN_FLAG_RXBUF_CONNECTED;
        }
                
-       /* Tear down the gpadl on the vsp end */
-       if (net_dev->rx_buf_gpadl_handle) {
-               ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan,
-                   net_dev->rx_buf_gpadl_handle);
+       if (sc->hn_rxbuf_gpadl != 0) {
                /*
-                * If we failed here, we might as well return and have a leak 
-                * rather than continue and a bugchk
+                * Disconnect RXBUF from primary channel.
                 */
+               ret = vmbus_chan_gpadl_disconnect(sc->hn_prichan,
+                   sc->hn_rxbuf_gpadl);
                if (ret != 0) {
+                       if_printf(sc->hn_ifp,
+                           "rxbuf disconn failed: %d\n", ret);
                        return (ret);
                }
-               net_dev->rx_buf_gpadl_handle = 0;
-       }
-
-       if (net_dev->rx_buf) {
-               /* Free up the receive buffer */
-               hyperv_dmamem_free(&net_dev->rxbuf_dma, net_dev->rx_buf);
-               net_dev->rx_buf = NULL;
+               sc->hn_rxbuf_gpadl = 0;
        }
-
        return (ret);
 }
 
@@ -430,11 +379,11 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_
  * Net VSC destroy send buffer
  */
 static int
-hv_nv_destroy_send_buffer(netvsc_dev *net_dev)
+hv_nv_destroy_send_buffer(struct hn_softc *sc)
 {
        int ret = 0;
 
-       if (net_dev->send_section_size) {
+       if (sc->hn_flags & HN_FLAG_CHIM_CONNECTED) {
                struct hn_nvs_chim_disconn disconn;
 
                /*
@@ -445,80 +394,62 @@ hv_nv_destroy_send_buffer(netvsc_dev *ne
                disconn.nvs_sig = HN_NVS_CHIM_SIG;
 
                /* NOTE: No response. */
-               ret = hn_nvs_send(net_dev->sc->hn_prichan,
-                   VMBUS_CHANPKT_FLAG_NONE, &disconn, sizeof(disconn),
-                   &hn_send_ctx_none);
+               ret = hn_nvs_req_send(sc, &disconn, sizeof(disconn));
                if (ret != 0) {
-                       if_printf(net_dev->sc->hn_ifp,
+                       if_printf(sc->hn_ifp,
                            "send chim disconn failed: %d\n", ret);
                        return (ret);
                }
+               sc->hn_flags &= ~HN_FLAG_CHIM_CONNECTED;
        }
                
-       /* Tear down the gpadl on the vsp end */
-       if (net_dev->send_buf_gpadl_handle) {
-               ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan,
-                   net_dev->send_buf_gpadl_handle);
-
+       if (sc->hn_chim_gpadl != 0) {
                /*
-                * If we failed here, we might as well return and have a leak 
-                * rather than continue and a bugchk
+                * Disconnect chimney sending buffer from primary channel.
                 */
+               ret = vmbus_chan_gpadl_disconnect(sc->hn_prichan,
+                   sc->hn_chim_gpadl);
                if (ret != 0) {
+                       if_printf(sc->hn_ifp,
+                           "chim disconn failed: %d\n", ret);
                        return (ret);
                }
-               net_dev->send_buf_gpadl_handle = 0;
-       }
-
-       if (net_dev->send_buf) {
-               /* Free up the receive buffer */
-               hyperv_dmamem_free(&net_dev->txbuf_dma, net_dev->send_buf);
-               net_dev->send_buf = NULL;
+               sc->hn_chim_gpadl = 0;
        }
 
-       if (net_dev->send_section_bitsmap) {
-               free(net_dev->send_section_bitsmap, M_NETVSC);
+       if (sc->hn_chim_bmap != NULL) {
+               free(sc->hn_chim_bmap, M_NETVSC);
+               sc->hn_chim_bmap = NULL;
        }
 
        return (ret);
 }
 
 static int
-hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev,
-    uint32_t nvs_ver)
+hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, uint32_t nvs_ver)
 {
-       struct hn_send_ctx sndc;
        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;
 
-       vmbus_xact_activate(xact);
-       hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
-
-       error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC,
-           init, sizeof(*init), &sndc);
-       if (error) {
-               if_printf(sc->hn_ifp, "send nvs init failed: %d\n", error);
-               vmbus_xact_deactivate(xact);
+       resp = hn_nvs_xact_execute(sc, xact, init, sizeof(*init), &resp_len);
+       if (resp == NULL) {
+               if_printf(sc->hn_ifp, "exec init failed\n");
                vmbus_xact_put(xact);
-               return (error);
+               return (EIO);
        }
-
-       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);
@@ -560,8 +491,7 @@ hv_nv_send_ndis_config(struct hn_softc *
        conf.nvs_caps = HN_NVS_NDIS_CONF_VLAN;
 
        /* NOTE: No response. */
-       error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE,
-           &conf, sizeof(conf), &hn_send_ctx_none);
+       error = hn_nvs_req_send(sc, &conf, sizeof(conf));
        if (error)
                if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error);
        return (error);
@@ -573,7 +503,6 @@ hv_nv_send_ndis_config(struct hn_softc *
 static int
 hv_nv_connect_to_vsp(struct hn_softc *sc)
 {
-       netvsc_dev *net_dev;
        uint32_t protocol_list[] = { NVSP_PROTOCOL_VERSION_1,
            NVSP_PROTOCOL_VERSION_2,
            NVSP_PROTOCOL_VERSION_4,
@@ -584,19 +513,18 @@ hv_nv_connect_to_vsp(struct hn_softc *sc
        device_t dev = sc->hn_dev;
        struct ifnet *ifp = sc->hn_ifp;
        struct hn_nvs_ndis_init ndis;
-
-       net_dev = hv_nv_get_outbound_net_device(sc);
+       int rxbuf_size;
 
        /*
         * Negotiate the NVSP version.  Try the latest NVSP first.
         */
        for (i = protocol_number - 1; i >= 0; i--) {
-               if (hv_nv_negotiate_nvsp_protocol(sc, net_dev,
-                   protocol_list[i]) == 0) {
-                       net_dev->nvsp_version = protocol_list[i];
-                       if (bootverbose)
-                               device_printf(dev, "Netvsc: got version 0x%x\n",
-                                   net_dev->nvsp_version);
+               if (hv_nv_negotiate_nvsp_protocol(sc, protocol_list[i]) == 0) {
+                       sc->hn_nvs_ver = protocol_list[i];
+                       if (bootverbose) {
+                               device_printf(dev, "NVS version 0x%x\n",
+                                   sc->hn_nvs_ver);
+                       }
                        break;
                }
        }
@@ -612,7 +540,7 @@ hv_nv_connect_to_vsp(struct hn_softc *sc
         * Set the MTU if supported by this NVSP protocol version
         * This needs to be right after the NVSP init message per Haiyang
         */
-       if (net_dev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
+       if (sc->hn_nvs_ver >= NVSP_PROTOCOL_VERSION_2)
                ret = hv_nv_send_ndis_config(sc, ifp->if_mtu);
 
        /*
@@ -622,27 +550,25 @@ hv_nv_connect_to_vsp(struct hn_softc *sc
        memset(&ndis, 0, sizeof(ndis));
        ndis.nvs_type = HN_NVS_TYPE_NDIS_INIT;
        ndis.nvs_ndis_major = NDIS_VERSION_MAJOR_6;
-       if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_4)
+       if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4)
                ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_1;
        else
                ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_30;
 
        /* NOTE: No response. */
-       ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_NONE,
-           &ndis, sizeof(ndis), &hn_send_ctx_none);
+       ret = hn_nvs_req_send(sc, &ndis, sizeof(ndis));
        if (ret != 0) {
                if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", ret);
                goto cleanup;
        }
 
        /* Post the big receive buffer to NetVSP */
-       if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_2)
-               net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY;
+       if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_2)
+               rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY;
        else
-               net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
-       net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
+               rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE;
 
-       ret = hv_nv_init_rx_buffer_with_net_vsp(sc);
+       ret = hv_nv_init_rx_buffer_with_net_vsp(sc, rxbuf_size);
        if (ret == 0)
                ret = hv_nv_init_send_buffer_with_net_vsp(sc);
 
@@ -654,10 +580,10 @@ cleanup:
  * Net VSC disconnect from VSP
  */
 static void
-hv_nv_disconnect_from_vsp(netvsc_dev *net_dev)
+hv_nv_disconnect_from_vsp(struct hn_softc *sc)
 {
-       hv_nv_destroy_rx_buffer(net_dev);
-       hv_nv_destroy_send_buffer(net_dev);
+       hv_nv_destroy_rx_buffer(sc);
+       hv_nv_destroy_send_buffer(sc);
 }
 
 void
@@ -676,20 +602,12 @@ hv_nv_subchan_attach(struct vmbus_channe
  * 
  * Callback when the device belonging to this driver is added
  */
-netvsc_dev *
-hv_nv_on_device_add(struct hn_softc *sc, void *additional_info,
-    struct hn_rx_ring *rxr)
+int
+hv_nv_on_device_add(struct hn_softc *sc, struct hn_rx_ring *rxr)
 {
        struct vmbus_channel *chan = sc->hn_prichan;
-       netvsc_dev *net_dev;
        int ret = 0;
 
-       net_dev = hv_nv_alloc_net_device(sc);
-       if (net_dev == NULL)
-               return NULL;
-
-       /* Initialize the NetVSC channel extension */
-
        /*
         * Open the channel
         */
@@ -709,20 +627,13 @@ hv_nv_on_device_add(struct hn_softc *sc,
        if (ret != 0)
                goto close;
 
-       return (net_dev);
+       return (0);
 
 close:
        /* Now, we can close the channel safely */
        vmbus_chan_close(chan);
-
 cleanup:
-       /*
-        * Free the packet buffers on the netvsc device packet queue.
-        * Release other resources.
-        */
-       free(net_dev, M_NETVSC);
-
-       return (NULL);
+       return (ret);
 }
 
 /*
@@ -731,27 +642,19 @@ cleanup:
 int
 hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
 {
-       netvsc_dev *net_dev = sc->net_dev;;
        
-       /* Stop outbound traffic ie sends and receives completions */
-       net_dev->destroy = TRUE;
-
-       hv_nv_disconnect_from_vsp(net_dev);
-
-       /* At this point, no one should be accessing net_dev except in here */
+       hv_nv_disconnect_from_vsp(sc);
 
        /* Now, we can close the channel safely */
 
        vmbus_chan_close(sc->hn_prichan);
 
-       free(net_dev, M_NETVSC);
-
        return (0);
 }
 
-void
+static void
 hn_nvs_sent_xact(struct hn_send_ctx *sndc,
-    struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused,
+    struct hn_softc *sc __unused, struct vmbus_channel *chan __unused,
     const void *data, int dlen)
 {
 
@@ -760,42 +663,42 @@ hn_nvs_sent_xact(struct hn_send_ctx *snd
 
 static void
 hn_nvs_sent_none(struct hn_send_ctx *sndc __unused,
-    struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused,
+    struct hn_softc *sc __unused, struct vmbus_channel *chan __unused,
     const void *data __unused, int dlen __unused)
 {
        /* EMPTY */
 }
 
 void
-hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx)
+hn_chim_free(struct hn_softc *sc, uint32_t chim_idx)
 {
        u_long mask;
        uint32_t idx;
 
-       idx = chim_idx / BITS_PER_LONG;
-       KASSERT(idx < net_dev->bitsmap_words,
+       idx = chim_idx / LONG_BIT;
+       KASSERT(idx < sc->hn_chim_bmap_cnt,
            ("invalid chimney index 0x%x", chim_idx));
 
-       mask = 1UL << (chim_idx % BITS_PER_LONG);
-       KASSERT(net_dev->send_section_bitsmap[idx] & mask,
+       mask = 1UL << (chim_idx % LONG_BIT);
+       KASSERT(sc->hn_chim_bmap[idx] & mask,
            ("index bitmap 0x%lx, chimney index %u, "
             "bitmap idx %d, bitmask 0x%lx",
-            net_dev->send_section_bitsmap[idx], chim_idx, idx, mask));
+            sc->hn_chim_bmap[idx], chim_idx, idx, mask));
 
-       atomic_clear_long(&net_dev->send_section_bitsmap[idx], mask);
+       atomic_clear_long(&sc->hn_chim_bmap[idx], mask);
 }
 
 /*
  * Net VSC on send completion
  */
 static void
-hv_nv_on_send_completion(netvsc_dev *net_dev, struct vmbus_channel *chan,
+hv_nv_on_send_completion(struct hn_softc *sc, struct vmbus_channel *chan,
     const struct vmbus_chanpkt_hdr *pkt)
 {
        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, sc, chan, VMBUS_CHANPKT_CONST_DATA(pkt),
            VMBUS_CHANPKT_DATALEN(pkt));
        /*
         * NOTE:
@@ -839,7 +742,7 @@ hv_nv_on_send(struct vmbus_channel *chan
  * with virtual addresses.
  */
 static void
-hv_nv_on_receive(netvsc_dev *net_dev, struct hn_rx_ring *rxr,
+hv_nv_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
     struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr)
 {
        const struct vmbus_chanpkt_rxbuf *pkt;
@@ -867,8 +770,8 @@ hv_nv_on_receive(netvsc_dev *net_dev, st
 
        /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */
        for (i = 0; i < count; i++) {
-               hv_rf_on_receive(net_dev, rxr,
-                   (const uint8_t *)net_dev->rx_buf + pkt->cp_rxbuf[i].rb_ofs,
+               hv_rf_on_receive(sc, rxr,
+                   rxr->hn_rxbuf + pkt->cp_rxbuf[i].rb_ofs,
                    pkt->cp_rxbuf[i].rb_len);
        }
        
@@ -934,14 +837,9 @@ hv_nv_on_channel_callback(struct vmbus_c
 {
        struct hn_rx_ring *rxr = xrxr;
        struct hn_softc *sc = rxr->hn_ifp->if_softc;
-       netvsc_dev *net_dev;
        void *buffer;
        int bufferlen = NETVSC_PACKET_SIZE;
 
-       net_dev = hv_nv_get_inbound_net_device(sc);
-       if (net_dev == NULL)
-               return;
-
        buffer = rxr->hn_rdbuf;
        do {
                struct vmbus_chanpkt_hdr *pkt = buffer;
@@ -954,11 +852,10 @@ hv_nv_on_channel_callback(struct vmbus_c
                        if (bytes_rxed > 0) {
                                switch (pkt->cph_type) {
                                case VMBUS_CHANPKT_TYPE_COMP:
-                                       hv_nv_on_send_completion(net_dev, chan,
-                                           pkt);
+                                       hv_nv_on_send_completion(sc, chan, pkt);
                                        break;
                                case VMBUS_CHANPKT_TYPE_RXBUF:
-                                       hv_nv_on_receive(net_dev, rxr, chan, 
pkt);
+                                       hv_nv_on_receive(sc, rxr, chan, pkt);
                                        break;
                                case VMBUS_CHANPKT_TYPE_INBAND:
                                        hn_proc_notify(sc, pkt);

Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h        Mon Oct 17 06:18:10 
2016        (r307479)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h        Mon Oct 17 06:47:34 
2016        (r307480)
@@ -212,40 +212,6 @@ typedef struct rndis_recv_scale_param_ {
  * Data types
  */
 
-/*
- * Per netvsc channel-specific
- */
-typedef struct netvsc_dev_ {
-       struct hn_softc                         *sc;
-
-       /* Send buffer allocated by us but manages by NetVSP */
-       void                                    *send_buf;
-       uint32_t                                send_buf_size;
-       uint32_t                                send_buf_gpadl_handle;
-       uint32_t                                send_section_size;
-       uint32_t                                send_section_count;
-       unsigned long                           bitsmap_words;
-       unsigned long                           *send_section_bitsmap;
-
-       /* Receive buffer allocated by us but managed by NetVSP */
-       void                                    *rx_buf;
-       uint32_t                                rx_buf_size;
-       uint32_t                                rx_buf_gpadl_handle;
-       uint32_t                                rx_section_count;
-
-       /* Holds rndis device info */
-       void                                    *extension;
-
-       uint8_t                                 destroy;
-       /* Negotiated NVSP version */
-       uint32_t                                nvsp_version;
-
-       uint32_t                                num_channel;
-
-       struct hyperv_dma                       rxbuf_dma;
-       struct hyperv_dma                       txbuf_dma;
-} netvsc_dev;
-
 struct vmbus_channel;
 
 typedef void (*pfn_on_send_rx_completion)(struct vmbus_channel *, void *);
@@ -268,12 +234,6 @@ typedef void (*pfn_on_send_rx_completion
 #define TRANSPORT_TYPE_IPV6_TCP                ((TYPE_IPV6 << 16) | TYPE_TCP)
 #define TRANSPORT_TYPE_IPV6_UDP                ((TYPE_IPV6 << 16) | TYPE_UDP)
 
-#ifdef __LP64__
-#define BITS_PER_LONG 64
-#else
-#define BITS_PER_LONG 32
-#endif
-
 typedef struct {
        uint8_t         mac_addr[6];  /* Assumption unsigned long */
        uint8_t         link_state;
@@ -292,6 +252,7 @@ struct hn_rx_ring {
        struct ifnet    *hn_ifp;
        struct hn_tx_ring *hn_txr;
        void            *hn_rdbuf;
+       uint8_t         *hn_rxbuf;      /* shadow sc->hn_rxbuf */
        int             hn_rx_idx;
 
        /* Trust csum verification on host side */
@@ -345,7 +306,7 @@ struct hn_tx_ring {
        struct vmbus_channel *hn_chan;
 
        int             hn_direct_tx_size;
-       int             hn_tx_chimney_size;
+       int             hn_chim_size;
        bus_dma_tag_t   hn_tx_data_dtag;
        uint64_t        hn_csum_assist;
 
@@ -383,7 +344,7 @@ typedef struct hn_softc {
        int             hn_initdone;
        /* See hv_netvsc_drv_freebsd.c for rules on how to use */
        int             temp_unusable;
-       netvsc_dev      *net_dev;
+       struct rndis_device_ *rndis_dev;
        struct vmbus_channel *hn_prichan;
 
        int             hn_rx_ring_cnt;
@@ -394,14 +355,31 @@ typedef struct hn_softc {
        int             hn_tx_ring_inuse;
        struct hn_tx_ring *hn_tx_ring;
 
+       uint8_t         *hn_chim;
+       u_long          *hn_chim_bmap;
+       int             hn_chim_bmap_cnt;
+       int             hn_chim_cnt;
+       int             hn_chim_szmax;
+
        int             hn_cpu;
-       int             hn_tx_chimney_max;
        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;
+       uint32_t        hn_nvs_ver;
+
+       uint32_t                hn_flags;
+       void                    *hn_rxbuf;
+       uint32_t                hn_rxbuf_gpadl;
+       struct hyperv_dma       hn_rxbuf_dma;
+
+       uint32_t                hn_chim_gpadl;
+       struct hyperv_dma       hn_chim_dma;
 } hn_softc_t;
 
+#define HN_FLAG_RXBUF_CONNECTED                0x0001
+#define HN_FLAG_CHIM_CONNECTED         0x0002
+
 /*
  * Externs
  */
@@ -409,13 +387,11 @@ extern int hv_promisc_mode;
 struct hn_send_ctx;
 
 void netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status);
-netvsc_dev *hv_nv_on_device_add(struct hn_softc *sc,
-    void *additional_info, struct hn_rx_ring *rxr);
+int hv_nv_on_device_add(struct hn_softc *sc, struct hn_rx_ring *rxr);
 int hv_nv_on_device_remove(struct hn_softc *sc,
     boolean_t destroy_channel);
 int hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype,
        struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt);
-int hv_nv_get_next_send_section(netvsc_dev *net_dev);
 void hv_nv_subchan_attach(struct vmbus_channel *chan,
     struct hn_rx_ring *rxr);
 

Modified: stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Mon Oct 17 
06:18:10 2016        (r307479)
+++ stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Mon Oct 17 
06:47:34 2016        (r307480)
@@ -328,7 +328,7 @@ static int hn_lro_lenlim_sysctl(SYSCTL_H
 static int hn_lro_ackcnt_sysctl(SYSCTL_HANDLER_ARGS);
 #endif
 static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS);
-static int hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS);
+static int hn_chim_size_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_rx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_rx_stat_u64_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
@@ -342,9 +342,9 @@ static void hn_start_taskfunc(void *, in
 static void hn_start_txeof_taskfunc(void *, int);
 static void hn_stop_tx_tasks(struct hn_softc *);
 static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **);
-static void hn_create_rx_data(struct hn_softc *sc, int);
+static int hn_create_rx_data(struct hn_softc *sc, int);
 static void hn_destroy_rx_data(struct hn_softc *sc);
-static void hn_set_tx_chimney_size(struct hn_softc *, int);
+static void hn_set_chim_size(struct hn_softc *, int);
 static void hn_channel_attach(struct hn_softc *, struct vmbus_channel *);
 static void hn_subchan_attach(struct hn_softc *, struct vmbus_channel *);
 static void hn_subchan_setup(struct hn_softc *);
@@ -504,7 +504,9 @@ netvsc_attach(device_t dev)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
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