Author: sephe
Date: Thu Oct 13 01:51:49 2016
New Revision: 307161
URL: https://svnweb.freebsd.org/changeset/base/307161

Log:
  MFC 303867,303901
  
  303867
      hyperv/hn: Move gpa array out of netvsc_packet.
  
      Prepare to deprecate the netvsc_packet.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7436
  
  303901
      hyperv/hn: Reorganize send done callback.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7450

Added:
  stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
     - copied unchanged from r303901, head/sys/dev/hyperv/netvsc/if_hnvar.h
Modified:
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c        Thu Oct 13 01:43:15 
2016        (r307160)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c        Thu Oct 13 01:51:49 
2016        (r307161)
@@ -67,6 +67,12 @@ static void hv_nv_on_receive_completion(
 static void hv_nv_on_receive(netvsc_dev *net_dev,
     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,
+    const struct nvsp_msg_ *msg);
+
+static struct hn_send_ctx      hn_send_ctx_none =
+    HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL);
 
 /*
  *
@@ -140,6 +146,7 @@ hv_nv_get_next_send_section(netvsc_dev *
 static int 
 hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc)
 {
+       struct hn_send_ctx sndc;
        netvsc_dev *net_dev;
        nvsp_msg *init_pkt;
        int ret = 0;
@@ -188,9 +195,10 @@ hv_nv_init_rx_buffer_with_net_vsp(struct
 
        /* Send the gpadl notification request */
 
+       hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
        ret = vmbus_chan_send(sc->hn_prichan,
            VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt);
+           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
        if (ret != 0) {
                goto cleanup;
        }
@@ -239,6 +247,7 @@ exit:
 static int 
 hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc)
 {
+       struct hn_send_ctx sndc;
        netvsc_dev *net_dev;
        nvsp_msg *init_pkt;
        int ret = 0;
@@ -286,9 +295,10 @@ hv_nv_init_send_buffer_with_net_vsp(stru
 
        /* Send the gpadl notification request */
 
+       hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
        ret = vmbus_chan_send(sc->hn_prichan,
            VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-           init_pkt, sizeof(nvsp_msg), (uint64_t)init_pkt);
+           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
        if (ret != 0) {
                goto cleanup;
        }
@@ -347,8 +357,7 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_
 
                ret = vmbus_chan_send(net_dev->sc->hn_prichan,
                    VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg),
-                   (uint64_t)(uintptr_t)revoke_pkt);
-
+                   (uint64_t)(uintptr_t)&hn_send_ctx_none);
                /*
                 * If we failed here, we might as well return and have a leak 
                 * rather than continue and a bugchk
@@ -413,9 +422,8 @@ hv_nv_destroy_send_buffer(netvsc_dev *ne
                    NETVSC_SEND_BUFFER_ID;
 
                ret = vmbus_chan_send(net_dev->sc->hn_prichan,
-                   VMBUS_CHANPKT_TYPE_INBAND, 0,
-                   revoke_pkt, sizeof(nvsp_msg),
-                   (uint64_t)(uintptr_t)revoke_pkt);
+                   VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg),
+                   (uint64_t)(uintptr_t)&hn_send_ctx_none);
                /*
                 * If we failed here, we might as well return and have a leak 
                 * rather than continue and a bugchk
@@ -465,6 +473,7 @@ static int
 hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev,
     uint32_t nvsp_ver)
 {
+       struct hn_send_ctx sndc;
        nvsp_msg *init_pkt;
        int ret;
 
@@ -479,9 +488,10 @@ hv_nv_negotiate_nvsp_protocol(struct hn_
        init_pkt->msgs.init_msgs.init.protocol_version_2 = nvsp_ver;
 
        /* Send the init request */
+       hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
        ret = vmbus_chan_send(sc->hn_prichan,
            VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt);
+           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
        if (ret != 0)
                return (-1);
 
@@ -523,7 +533,7 @@ hv_nv_send_ndis_config(struct hn_softc *
 
        /* Send the configuration packet */
        ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0,
-           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt);
+           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&hn_send_ctx_none);
        if (ret != 0)
                return (-EINVAL);
 
@@ -601,7 +611,7 @@ hv_nv_connect_to_vsp(struct hn_softc *sc
        /* Send the init request */
 
        ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0,
-           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt);
+           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&hn_send_ctx_none);
        if (ret != 0) {
                goto cleanup;
        }
@@ -730,6 +740,43 @@ hv_nv_on_device_remove(struct hn_softc *
        return (0);
 }
 
+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)
+{
+       /* Copy the response back */
+       memcpy(&net_dev->channel_init_packet, msg, sizeof(nvsp_msg));
+       sema_post(&net_dev->channel_init_sema);
+}
+
+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)
+{
+       /* EMPTY */
+}
+
+void
+hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx)
+{
+       u_long mask;
+       uint32_t idx;
+
+       idx = chim_idx / BITS_PER_LONG;
+       KASSERT(idx < net_dev->bitsmap_words,
+           ("invalid chimney index 0x%x", chim_idx));
+
+       mask = 1UL << (chim_idx % BITS_PER_LONG);
+       KASSERT(net_dev->send_section_bitsmap[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));
+
+       atomic_clear_long(&net_dev->send_section_bitsmap[idx], mask);
+}
+
 /*
  * Net VSC on send completion
  */
@@ -737,59 +784,15 @@ static void
 hv_nv_on_send_completion(netvsc_dev *net_dev, struct vmbus_channel *chan,
     const struct vmbus_chanpkt_hdr *pkt)
 {
-       const nvsp_msg *nvsp_msg_pkt;
-       netvsc_packet *net_vsc_pkt;
+       struct hn_send_ctx *sndc;
 
-       nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkt);
-
-       if (nvsp_msg_pkt->hdr.msg_type == nvsp_msg_type_init_complete
-               || nvsp_msg_pkt->hdr.msg_type
-                       == nvsp_msg_1_type_send_rx_buf_complete
-               || nvsp_msg_pkt->hdr.msg_type
-                       == nvsp_msg_1_type_send_send_buf_complete
-               || nvsp_msg_pkt->hdr.msg_type
-                       == nvsp_msg5_type_subchannel) {
-               /* Copy the response back */
-               memcpy(&net_dev->channel_init_packet, nvsp_msg_pkt,
-                   sizeof(nvsp_msg));
-               sema_post(&net_dev->channel_init_sema);
-       } else if (nvsp_msg_pkt->hdr.msg_type ==
-                   nvsp_msg_1_type_send_rndis_pkt_complete) {
-               /* Get the send context */
-               net_vsc_pkt =
-                   (netvsc_packet *)(unsigned long)pkt->cph_xactid;
-               if (NULL != net_vsc_pkt) {
-                       if (net_vsc_pkt->send_buf_section_idx !=
-                           NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
-                               u_long mask;
-                               int idx;
-
-                               idx = net_vsc_pkt->send_buf_section_idx /
-                                   BITS_PER_LONG;
-                               KASSERT(idx < net_dev->bitsmap_words,
-                                   ("invalid section index %u",
-                                    net_vsc_pkt->send_buf_section_idx));
-                               mask = 1UL <<
-                                   (net_vsc_pkt->send_buf_section_idx %
-                                    BITS_PER_LONG);
-
-                               KASSERT(net_dev->send_section_bitsmap[idx] &
-                                   mask,
-                                   ("index bitmap 0x%lx, section index %u, "
-                                    "bitmap idx %d, bitmask 0x%lx",
-                                    net_dev->send_section_bitsmap[idx],
-                                    net_vsc_pkt->send_buf_section_idx,
-                                    idx, mask));
-                               atomic_clear_long(
-                                   &net_dev->send_section_bitsmap[idx], mask);
-                       }
-                       
-                       /* Notify the layer above us */
-                       net_vsc_pkt->compl.send.on_send_completion(chan,
-                           net_vsc_pkt->compl.send.send_completion_context);
-
-               }
-       }
+       sndc = (struct hn_send_ctx *)(uintptr_t)pkt->cph_xactid;
+       sndc->hn_cb(sndc, net_dev, chan, VMBUS_CHANPKT_CONST_DATA(pkt));
+       /*
+        * NOTE:
+        * 'sndc' CAN NOT be accessed anymore, since it can be freed by
+        * its callback.
+        */
 }
 
 /*
@@ -798,13 +801,14 @@ hv_nv_on_send_completion(netvsc_dev *net
  * Returns 0 on success, non-zero on failure.
  */
 int
-hv_nv_on_send(struct vmbus_channel *chan, netvsc_packet *pkt)
+hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt,
+    struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt)
 {
        nvsp_msg send_msg;
        int ret;
 
        send_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt;
-       if (pkt->is_data_pkt) {
+       if (is_data_pkt) {
                /* 0 is RMC_DATA */
                send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 0;
        } else {
@@ -813,17 +817,17 @@ hv_nv_on_send(struct vmbus_channel *chan
        }
 
        send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_idx =
-           pkt->send_buf_section_idx;
+           sndc->hn_chim_idx;
        send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size =
-           pkt->send_buf_section_size;
+           sndc->hn_chim_sz;
 
-       if (pkt->gpa_cnt) {
-               ret = vmbus_chan_send_sglist(chan, pkt->gpa, pkt->gpa_cnt,
-                   &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt);
+       if (gpa_cnt) {
+               ret = vmbus_chan_send_sglist(chan, gpa, gpa_cnt,
+                   &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)sndc);
        } else {
                ret = vmbus_chan_send(chan,
                    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-                   &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt);
+                   &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)sndc);
        }
 
        return (ret);

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h        Thu Oct 13 01:43:15 
2016        (r307160)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h        Thu Oct 13 01:51:49 
2016        (r307161)
@@ -1112,33 +1112,10 @@ typedef void (*pfn_on_send_rx_completion
 #endif
 
 typedef struct netvsc_packet_ {
-       uint8_t                    is_data_pkt;      /* One byte */
-       uint16_t                   vlan_tci;
-       uint32_t status;
-
-       /* Completion */
-       union {
-               struct {
-                       uint64_t   rx_completion_tid;
-                       void       *rx_completion_context;
-                       /* This is no longer used */
-                       pfn_on_send_rx_completion   on_rx_completion;
-               } rx;
-               struct {
-                       uint64_t    send_completion_tid;
-                       void        *send_completion_context;
-                       /* Still used in netvsc and filter code */
-                       pfn_on_send_rx_completion   on_send_completion;
-               } send;
-       } compl;
-       uint32_t        send_buf_section_idx;
-       uint32_t        send_buf_section_size;
-
-       void            *rndis_mesg;
+       uint16_t        vlan_tci;
+       uint32_t        status;
        uint32_t        tot_data_buf_len;
        void            *data;
-       uint32_t        gpa_cnt;
-       struct vmbus_gpa gpa[NETVSC_PACKET_MAXPAGE];
 } netvsc_packet;
 
 typedef struct {
@@ -1216,6 +1193,9 @@ struct hn_tx_ring {
        bus_dma_tag_t   hn_tx_data_dtag;
        uint64_t        hn_csum_assist;
 
+       int             hn_gpa_cnt;
+       struct vmbus_gpa hn_gpa[NETVSC_PACKET_MAXPAGE];
+
        u_long          hn_no_txdescs;
        u_long          hn_send_failed;
        u_long          hn_txdma_failed;
@@ -1270,13 +1250,15 @@ typedef struct hn_softc {
  * Externs
  */
 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_remove(struct hn_softc *sc,
     boolean_t destroy_channel);
-int hv_nv_on_send(struct vmbus_channel *chan, netvsc_packet *pkt);
+int hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt,
+       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/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Thu Oct 13 
01:43:15 2016        (r307160)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Thu Oct 13 
01:51:49 2016        (r307161)
@@ -168,7 +168,7 @@ struct hn_txdesc {
        struct hn_tx_ring *txr;
        int             refs;
        uint32_t        flags;          /* HN_TXD_FLAG_ */
-       netvsc_packet   netvsc_pkt;     /* XXX to be removed */
+       struct hn_send_ctx send_ctx;
 
        bus_dmamap_t    data_dmap;
 
@@ -793,14 +793,14 @@ hn_txeof(struct hn_tx_ring *txr)
 }
 
 static void
-hn_tx_done(struct vmbus_channel *chan, void *xpkt)
+hn_tx_done(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
+    struct vmbus_channel *chan, const struct nvsp_msg_ *msg __unused)
 {
-       netvsc_packet *packet = xpkt;
-       struct hn_txdesc *txd;
+       struct hn_txdesc *txd = sndc->hn_cbarg;
        struct hn_tx_ring *txr;
 
-       txd = (struct hn_txdesc *)(uintptr_t)
-           packet->compl.send.send_completion_tid;
+       if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
+               hn_chim_free(net_dev, sndc->hn_chim_idx);
 
        txr = txd->txr;
        KASSERT(txr->hn_chan == chan,
@@ -853,16 +853,14 @@ hn_encap(struct hn_tx_ring *txr, struct 
        bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX];
        int error, nsegs, i;
        struct mbuf *m_head = *m_head0;
-       netvsc_packet *packet;
        rndis_msg *rndis_mesg;
        rndis_packet *rndis_pkt;
        rndis_per_packet_info *rppi;
        struct rndis_hash_value *hash_value;
-       uint32_t rndis_msg_size;
+       uint32_t rndis_msg_size, tot_data_buf_len, send_buf_section_idx;
+       int send_buf_section_size;
 
-       packet = &txd->netvsc_pkt;
-       packet->is_data_pkt = TRUE;
-       packet->tot_data_buf_len = m_head->m_pkthdr.len;
+       tot_data_buf_len = m_head->m_pkthdr.len;
 
        /*
         * extension points to the area reserved for the
@@ -877,7 +875,7 @@ hn_encap(struct hn_tx_ring *txr, struct 
 
        rndis_pkt = &rndis_mesg->msg.packet;
        rndis_pkt->data_offset = sizeof(rndis_packet);
-       rndis_pkt->data_length = packet->tot_data_buf_len;
+       rndis_pkt->data_length = tot_data_buf_len;
        rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet);
 
        rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet);
@@ -985,15 +983,14 @@ hn_encap(struct hn_tx_ring *txr, struct 
                }
        }
 
-       rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size;
-       packet->tot_data_buf_len = rndis_mesg->msg_len;
+       rndis_mesg->msg_len = tot_data_buf_len + rndis_msg_size;
+       tot_data_buf_len = rndis_mesg->msg_len;
 
        /*
         * Chimney send, if the packet could fit into one chimney buffer.
         */
-       if (packet->tot_data_buf_len < txr->hn_tx_chimney_size) {
+       if (tot_data_buf_len < txr->hn_tx_chimney_size) {
                netvsc_dev *net_dev = txr->hn_sc->net_dev;
-               uint32_t send_buf_section_idx;
 
                txr->hn_tx_chimney_tried++;
                send_buf_section_idx =
@@ -1008,10 +1005,8 @@ hn_encap(struct hn_tx_ring *txr, struct 
                        dest += rndis_msg_size;
                        m_copydata(m_head, 0, m_head->m_pkthdr.len, dest);
 
-                       packet->send_buf_section_idx = send_buf_section_idx;
-                       packet->send_buf_section_size =
-                           packet->tot_data_buf_len;
-                       packet->gpa_cnt = 0;
+                       send_buf_section_size = tot_data_buf_len;
+                       txr->hn_gpa_cnt = 0;
                        txr->hn_tx_chimney++;
                        goto done;
                }
@@ -1037,19 +1032,19 @@ hn_encap(struct hn_tx_ring *txr, struct 
        }
        *m_head0 = m_head;
 
-       packet->gpa_cnt = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS;
+       txr->hn_gpa_cnt = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS;
 
        /* send packet with page buffer */
-       packet->gpa[0].gpa_page = atop(txd->rndis_msg_paddr);
-       packet->gpa[0].gpa_ofs = txd->rndis_msg_paddr & PAGE_MASK;
-       packet->gpa[0].gpa_len = rndis_msg_size;
+       txr->hn_gpa[0].gpa_page = atop(txd->rndis_msg_paddr);
+       txr->hn_gpa[0].gpa_ofs = txd->rndis_msg_paddr & PAGE_MASK;
+       txr->hn_gpa[0].gpa_len = rndis_msg_size;
 
        /*
         * Fill the page buffers with mbuf info starting at index
         * HV_RF_NUM_TX_RESERVED_PAGE_BUFS.
         */
        for (i = 0; i < nsegs; ++i) {
-               struct vmbus_gpa *gpa = &packet->gpa[
+               struct vmbus_gpa *gpa = &txr->hn_gpa[
                    i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS];
 
                gpa->gpa_page = atop(segs[i].ds_addr);
@@ -1057,16 +1052,14 @@ hn_encap(struct hn_tx_ring *txr, struct 
                gpa->gpa_len = segs[i].ds_len;
        }
 
-       packet->send_buf_section_idx =
-           NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
-       packet->send_buf_section_size = 0;
+       send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
+       send_buf_section_size = 0;
 done:
        txd->m = m_head;
 
        /* Set the completion routine */
-       packet->compl.send.on_send_completion = hn_tx_done;
-       packet->compl.send.send_completion_context = packet;
-       packet->compl.send.send_completion_tid = (uint64_t)(uintptr_t)txd;
+       hn_send_ctx_init(&txd->send_ctx, hn_tx_done, txd,
+           send_buf_section_idx, send_buf_section_size);
 
        return 0;
 }
@@ -1086,7 +1079,8 @@ again:
         * Make sure that txd is not freed before ETHER_BPF_MTAP.
         */
        hn_txdesc_hold(txd);
-       error = hv_nv_on_send(txr->hn_chan, &txd->netvsc_pkt);
+       error = hv_nv_on_send(txr->hn_chan, true, &txd->send_ctx,
+           txr->hn_gpa, txr->hn_gpa_cnt);
        if (!error) {
                ETHER_BPF_MTAP(ifp, txd->m);
                if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c   Thu Oct 13 01:43:15 
2016        (r307160)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c   Thu Oct 13 01:51:49 
2016        (r307161)
@@ -86,11 +86,17 @@ static int  hv_rf_set_packet_filter(rndi
 static int  hv_rf_init_device(rndis_device *device);
 static int  hv_rf_open_device(rndis_device *device);
 static int  hv_rf_close_device(rndis_device *device);
-static void hv_rf_on_send_request_completion(struct vmbus_channel *, void 
*context);
-static void hv_rf_on_send_request_halt_completion(struct vmbus_channel *, void 
*context);
 int
 hv_rf_send_offload_request(struct hn_softc *sc,
     rndis_offload_params *offloads);
+
+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);
+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);
+
 /*
  * Set the Per-Packet-Info with the specified type
  */
@@ -239,45 +245,36 @@ static int
 hv_rf_send_request(rndis_device *device, rndis_request *request,
     uint32_t message_type)
 {
-       int ret;
-       netvsc_packet *packet;
        netvsc_dev      *net_dev = device->net_dev;
-       int send_buf_section_idx;
+       uint32_t send_buf_section_idx, tot_data_buf_len;
+       struct vmbus_gpa gpa[2];
+       int gpa_cnt, send_buf_section_size;
+       hn_sent_callback_t cb;
 
        /* Set up the packet to send it */
-       packet = &request->pkt;
-       
-       packet->is_data_pkt = FALSE;
-       packet->tot_data_buf_len = request->request_msg.msg_len;
-       packet->gpa_cnt = 1;
-
-       packet->gpa[0].gpa_page =
-           hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
-       packet->gpa[0].gpa_len = request->request_msg.msg_len;
-       packet->gpa[0].gpa_ofs =
-           (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
-
-       if (packet->gpa[0].gpa_ofs + packet->gpa[0].gpa_len > PAGE_SIZE) {
-               packet->gpa_cnt = 2;
-               packet->gpa[0].gpa_len = PAGE_SIZE - packet->gpa[0].gpa_ofs;
-               packet->gpa[1].gpa_page =
-                       hv_get_phys_addr((char*)&request->request_msg +
-                               packet->gpa[0].gpa_len) >> PAGE_SHIFT;
-               packet->gpa[1].gpa_ofs = 0;
-               packet->gpa[1].gpa_len = request->request_msg.msg_len -
-                   packet->gpa[0].gpa_len;
-       }
-
-       packet->compl.send.send_completion_context = request; /* packet */
-       if (message_type != REMOTE_NDIS_HALT_MSG) {
-               packet->compl.send.on_send_completion =
-                   hv_rf_on_send_request_completion;
-       } else {
-               packet->compl.send.on_send_completion =
-                   hv_rf_on_send_request_halt_completion;
+       tot_data_buf_len = request->request_msg.msg_len;
+
+       gpa_cnt = 1;
+       gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
+       gpa[0].gpa_len = request->request_msg.msg_len;
+       gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
+
+       if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) {
+               gpa_cnt = 2;
+               gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs;
+               gpa[1].gpa_page =
+                   hv_get_phys_addr((char*)&request->request_msg +
+                   gpa[0].gpa_len) >> PAGE_SHIFT;
+               gpa[1].gpa_ofs = 0;
+               gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
        }
-       packet->compl.send.send_completion_tid = (unsigned long)device;
-       if (packet->tot_data_buf_len < net_dev->send_section_size) {
+
+       if (message_type != REMOTE_NDIS_HALT_MSG)
+               cb = hn_rndis_sent_cb;
+       else
+               cb = hn_rndis_sent_halt;
+
+       if (tot_data_buf_len < net_dev->send_section_size) {
                send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
                if (send_buf_section_idx !=
                        NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
@@ -285,20 +282,20 @@ hv_rf_send_request(rndis_device *device,
                                send_buf_section_idx * 
net_dev->send_section_size);
 
                        memcpy(dest, &request->request_msg, 
request->request_msg.msg_len);
-                       packet->send_buf_section_idx = send_buf_section_idx;
-                       packet->send_buf_section_size = 
packet->tot_data_buf_len;
-                       packet->gpa_cnt = 0;
+                       send_buf_section_size = tot_data_buf_len;
+                       gpa_cnt = 0;
                        goto sendit;
                }
                /* Failed to allocate chimney send buffer; move on */
        }
-       packet->send_buf_section_idx = 
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
-       packet->send_buf_section_size = 0;
+       send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
+       send_buf_section_size = 0;
 
 sendit:
-       ret = hv_nv_on_send(device->net_dev->sc->hn_prichan, packet);
-
-       return (ret);
+       hn_send_ctx_init(&request->send_ctx, cb, request,
+           send_buf_section_idx, send_buf_section_size);
+       return hv_nv_on_send(device->net_dev->sc->hn_prichan, false,
+           &request->send_ctx, gpa, gpa_cnt);
 }
 
 /*
@@ -1060,6 +1057,7 @@ int
 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
     int nchan, struct hn_rx_ring *rxr)
 {
+       struct hn_send_ctx sndc;
        int ret;
        netvsc_dev *net_dev;
        rndis_device *rndis_dev;
@@ -1166,9 +1164,10 @@ hv_rf_on_device_add(struct hn_softc *sc,
        init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
            net_dev->num_channel - 1;
 
+       hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
        ret = vmbus_chan_send(sc->hn_prichan,
            VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt);
+           init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
        if (ret != 0) {
                device_printf(dev, "Fail to allocate subchannel\n");
                goto out;
@@ -1239,23 +1238,22 @@ hv_rf_on_close(struct hn_softc *sc)
        return (hv_rf_close_device((rndis_device *)net_dev->extension));
 }
 
-/*
- * RNDIS filter on send request completion callback
- */
-static void 
-hv_rf_on_send_request_completion(struct vmbus_channel *chan __unused,
-    void *context __unused)
+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)
 {
+       if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
+               hn_chim_free(net_dev, sndc->hn_chim_idx);
 }
 
-/*
- * RNDIS filter on send request (halt only) completion callback
- */
-static void 
-hv_rf_on_send_request_halt_completion(struct vmbus_channel *chan __unused,
-    void *context)
+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)
 {
-       rndis_request *request = context;
+       rndis_request *request = sndc->hn_cbarg;
+
+       if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
+               hn_chim_free(net_dev, sndc->hn_chim_idx);
 
        /*
         * Notify hv_rf_halt_device() about halt completion.

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h   Thu Oct 13 01:43:15 
2016        (r307160)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h   Thu Oct 13 01:51:49 
2016        (r307161)
@@ -33,6 +33,7 @@
 
 #include <sys/param.h>
 #include <net/ethernet.h>
+#include <dev/hyperv/netvsc/if_hnvar.h>
 
 /*
  * Defines
@@ -75,7 +76,7 @@ typedef struct rndis_request_ {
        uint8_t                         buf_resp[PAGE_SIZE];
 
        /* Simplify allocation by having a netvsc packet inline */
-       netvsc_packet                   pkt;
+       struct hn_send_ctx              send_ctx;
 
        /*
         * The max request size is sizeof(rndis_msg) + PAGE_SIZE.

Copied: stable/10/sys/dev/hyperv/netvsc/if_hnvar.h (from r303901, 
head/sys/dev/hyperv/netvsc/if_hnvar.h)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/10/sys/dev/hyperv/netvsc/if_hnvar.h  Thu Oct 13 01:51:49 2016        
(r307161, copy of r303901, head/sys/dev/hyperv/netvsc/if_hnvar.h)
@@ -0,0 +1,83 @@
+/*-
+ * 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_HNVAR_H_
+#define _IF_HNVAR_H_
+
+#include <sys/param.h>
+#include <dev/hyperv/netvsc/hv_net_vsc.h>
+
+struct netvsc_dev_;
+struct nvsp_msg_;
+
+struct vmbus_channel;
+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 hn_send_ctx {
+       hn_sent_callback_t      hn_cb;
+       void                    *hn_cbarg;
+       uint32_t                hn_chim_idx;
+       int                     hn_chim_sz;
+};
+
+#define HN_SEND_CTX_INITIALIZER(cb, cbarg)                             \
+{                                                                      \
+       .hn_cb          = cb,                                           \
+       .hn_cbarg       = cbarg,                                        \
+       .hn_chim_idx    = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX,    \
+       .hn_chim_sz     = 0                                             \
+}
+
+static __inline void
+hn_send_ctx_init(struct hn_send_ctx *sndc, hn_sent_callback_t cb,
+    void *cbarg, uint32_t chim_idx, int chim_sz)
+{
+       sndc->hn_cb = cb;
+       sndc->hn_cbarg = cbarg;
+       sndc->hn_chim_idx = chim_idx;
+       sndc->hn_chim_sz = chim_sz;
+}
+
+static __inline void
+hn_send_ctx_init_simple(struct hn_send_ctx *sndc, hn_sent_callback_t cb,
+    void *cbarg)
+{
+       hn_send_ctx_init(sndc, cb, cbarg,
+           NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX, 0);
+}
+
+void           hn_nvs_sent_wakeup(struct hn_send_ctx *sndc,
+                   struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
+                   const struct nvsp_msg_ *msg);
+void           hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx);
+
+#endif /* !_IF_HNVAR_H_ */
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to