Author: sephe
Date: Mon Jun 13 06:09:02 2016
New Revision: 301857
URL: https://svnweb.freebsd.org/changeset/base/301857

Log:
  MFC 295302,295303
  
  295302
      hyperv/hn: Factor out hn_encap() from hn_start_locked()
  
      It will be shared w/ upcoming ifnet.if_transmit implementaion.
  
      No functional changes.
  
      Reviewed by:        adrian
      Approved by:        adrian (mentor)
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5158
  
  295303
      hyperv/hn: Recover half of the chimney sending space
  
      We lost half of the chimney sending space, because we mis-used
      ffs() on a 64 bits mask, where ffsl() should be used.
  
      While I'm here:
      - Use system atomic operation instead.
      - Stringent chimney sending index assertion.
  
      Reviewed by:        adrian
      Approved by:        adrian (mentor)
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5159

Modified:
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
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        Mon Jun 13 05:43:42 
2016        (r301856)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c        Mon Jun 13 06:09:02 
2016        (r301857)
@@ -135,15 +135,15 @@ hv_nv_get_next_send_section(netvsc_dev *
        int i;
 
        for (i = 0; i < bitsmap_words; i++) {
-               idx = ffs(~bitsmap[i]);
+               idx = ffsl(~bitsmap[i]);
                if (0 == idx)
                        continue;
 
                idx--;
-               if (i * BITS_PER_LONG + idx >= net_dev->send_section_count)
-                       return (ret);
+               KASSERT(i * BITS_PER_LONG + idx < net_dev->send_section_count,
+                   ("invalid i %d and idx %lu", i, idx));
 
-               if (synch_test_and_set_bit(idx, &bitsmap[i]))
+               if (atomic_testandset_long(&bitsmap[i], idx))
                        continue;
 
                ret = i * BITS_PER_LONG + idx;
@@ -788,8 +788,27 @@ hv_nv_on_send_completion(netvsc_dev *net
                if (NULL != net_vsc_pkt) {
                        if (net_vsc_pkt->send_buf_section_idx !=
                            NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
-                               
synch_change_bit(net_vsc_pkt->send_buf_section_idx,
-                                   net_dev->send_section_bitsmap);
+                               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 */

Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Mon Jun 13 
05:43:42 2016        (r301856)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Mon Jun 13 
06:09:02 2016        (r301857)
@@ -254,6 +254,7 @@ static int hn_create_tx_ring(struct hn_s
 static void hn_destroy_tx_ring(struct hn_softc *sc);
 static void hn_start_taskfunc(void *xsc, int pending);
 static void hn_txeof_taskfunc(void *xsc, int pending);
+static int hn_encap(struct hn_softc *, struct hn_txdesc *, struct mbuf **);
 
 static __inline void
 hn_set_lro_hiwat(struct hn_softc *sc, int hiwat)
@@ -744,31 +745,235 @@ netvsc_channel_rollup(struct hv_device *
 }
 
 /*
- * Start a transmit of one or more packets
+ * NOTE:
+ * This this function fails, then both txd and m_head0 will be freed
  */
 static int
-hn_start_locked(struct ifnet *ifp, int len)
+hn_encap(struct hn_softc *sc, struct hn_txdesc *txd, struct mbuf **m_head0)
 {
-       hn_softc_t *sc = ifp->if_softc;
-       struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev);
-       netvsc_dev *net_dev = sc->net_dev;
+       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;
-       ndis_8021q_info *rppi_vlan_info;
-       rndis_tcp_ip_csum_info *csum_info;
-       rndis_tcp_tso_info *tso_info;   
-       uint32_t rndis_msg_size = 0;
+       uint32_t rndis_msg_size;
+
+       packet = &txd->netvsc_pkt;
+       packet->is_data_pkt = TRUE;
+       packet->tot_data_buf_len = m_head->m_pkthdr.len;
+
+       /*
+        * extension points to the area reserved for the
+        * rndis_filter_packet, which is placed just after
+        * the netvsc_packet (and rppi struct, if present;
+        * length is updated later).
+        */
+       rndis_mesg = txd->rndis_msg;
+       /* XXX not necessary */
+       memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN);
+       rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
+
+       rndis_pkt = &rndis_mesg->msg.packet;
+       rndis_pkt->data_offset = sizeof(rndis_packet);
+       rndis_pkt->data_length = packet->tot_data_buf_len;
+       rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet);
+
+       rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet);
+
+       if (m_head->m_flags & M_VLANTAG) {
+               ndis_8021q_info *rppi_vlan_info;
+
+               rndis_msg_size += RNDIS_VLAN_PPI_SIZE;
+               rppi = hv_set_rppi_data(rndis_mesg, RNDIS_VLAN_PPI_SIZE,
+                   ieee_8021q_info);
+
+               rppi_vlan_info = (ndis_8021q_info *)((uint8_t *)rppi +
+                   rppi->per_packet_info_offset);
+               rppi_vlan_info->u1.s1.vlan_id =
+                   m_head->m_pkthdr.ether_vtag & 0xfff;
+       }
+
+       if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
+               rndis_tcp_tso_info *tso_info;   
+               struct ether_vlan_header *eh;
+               int ether_len;
+
+               /*
+                * XXX need m_pullup and use mtodo
+                */
+               eh = mtod(m_head, struct ether_vlan_header*);
+               if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))
+                       ether_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
+               else
+                       ether_len = ETHER_HDR_LEN;
+
+               rndis_msg_size += RNDIS_TSO_PPI_SIZE;
+               rppi = hv_set_rppi_data(rndis_mesg, RNDIS_TSO_PPI_SIZE,
+                   tcp_large_send_info);
+
+               tso_info = (rndis_tcp_tso_info *)((uint8_t *)rppi +
+                   rppi->per_packet_info_offset);
+               tso_info->lso_v2_xmit.type =
+                   RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
+
+#ifdef INET
+               if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) {
+                       struct ip *ip =
+                           (struct ip *)(m_head->m_data + ether_len);
+                       unsigned long iph_len = ip->ip_hl << 2;
+                       struct tcphdr *th =
+                           (struct tcphdr *)((caddr_t)ip + iph_len);
+
+                       tso_info->lso_v2_xmit.ip_version =
+                           RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4;
+                       ip->ip_len = 0;
+                       ip->ip_sum = 0;
+
+                       th->th_sum = in_pseudo(ip->ip_src.s_addr,
+                           ip->ip_dst.s_addr, htons(IPPROTO_TCP));
+               }
+#endif
+#if defined(INET6) && defined(INET)
+               else
+#endif
+#ifdef INET6
+               {
+                       struct ip6_hdr *ip6 = (struct ip6_hdr *)
+                           (m_head->m_data + ether_len);
+                       struct tcphdr *th = (struct tcphdr *)(ip6 + 1);
+
+                       tso_info->lso_v2_xmit.ip_version =
+                           RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV6;
+                       ip6->ip6_plen = 0;
+                       th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0);
+               }
+#endif
+               tso_info->lso_v2_xmit.tcp_header_offset = 0;
+               tso_info->lso_v2_xmit.mss = m_head->m_pkthdr.tso_segsz;
+       } else if (m_head->m_pkthdr.csum_flags & sc->hn_csum_assist) {
+               rndis_tcp_ip_csum_info *csum_info;
+
+               rndis_msg_size += RNDIS_CSUM_PPI_SIZE;
+               rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE,
+                   tcpip_chksum_info);
+               csum_info = (rndis_tcp_ip_csum_info *)((uint8_t *)rppi +
+                   rppi->per_packet_info_offset);
+
+               csum_info->xmit.is_ipv4 = 1;
+               if (m_head->m_pkthdr.csum_flags & CSUM_IP)
+                       csum_info->xmit.ip_header_csum = 1;
+
+               if (m_head->m_pkthdr.csum_flags & CSUM_TCP) {
+                       csum_info->xmit.tcp_csum = 1;
+                       csum_info->xmit.tcp_header_offset = 0;
+               } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) {
+                       csum_info->xmit.udp_csum = 1;
+               }
+       }
+
+       rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size;
+       packet->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 < sc->hn_tx_chimney_size) {
+               netvsc_dev *net_dev = sc->net_dev;
+               uint32_t send_buf_section_idx;
+
+               send_buf_section_idx =
+                   hv_nv_get_next_send_section(net_dev);
+               if (send_buf_section_idx !=
+                   NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
+                       uint8_t *dest = ((uint8_t *)net_dev->send_buf +
+                           (send_buf_section_idx *
+                            net_dev->send_section_size));
+
+                       memcpy(dest, rndis_mesg, rndis_msg_size);
+                       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->page_buf_count = 0;
+                       sc->hn_tx_chimney++;
+                       goto done;
+               }
+       }
+
+       error = hn_txdesc_dmamap_load(sc, txd, &m_head, segs, &nsegs);
+       if (error) {
+               int freed;
+
+               /*
+                * This mbuf is not linked w/ the txd yet, so free it now.
+                */
+               m_freem(m_head);
+               *m_head0 = NULL;
+
+               freed = hn_txdesc_put(sc, txd);
+               KASSERT(freed != 0,
+                   ("fail to free txd upon txdma error"));
+
+               sc->hn_txdma_failed++;
+               if_inc_counter(sc->hn_ifp, IFCOUNTER_OERRORS, 1);
+               return error;
+       }
+       *m_head0 = m_head;
+
+       packet->page_buf_count = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS;
+
+       /* send packet with page buffer */
+       packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr);
+       packet->page_buffers[0].offset = txd->rndis_msg_paddr & PAGE_MASK;
+       packet->page_buffers[0].length = 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) {
+               hv_vmbus_page_buffer *pb = &packet->page_buffers[
+                   i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS];
+
+               pb->pfn = atop(segs[i].ds_addr);
+               pb->offset = segs[i].ds_addr & PAGE_MASK;
+               pb->length = segs[i].ds_len;
+       }
+
+       packet->send_buf_section_idx =
+           NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
+       packet->send_buf_section_size = 0;
+done:
+       txd->m = m_head;
+
+       /* Set the completion routine */
+       packet->compl.send.on_send_completion = netvsc_xmit_completion;
+       packet->compl.send.send_completion_context = packet;
+       packet->compl.send.send_completion_tid = (uint64_t)(uintptr_t)txd;
+
+       return 0;
+}
+
+/*
+ * Start a transmit of one or more packets
+ */
+static int
+hn_start_locked(struct ifnet *ifp, int len)
+{
+       struct hn_softc *sc = ifp->if_softc;
+       struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev);
 
        if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
            IFF_DRV_RUNNING)
                return 0;
 
        while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
-               bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX];
-               int error, nsegs, i, send_failed = 0;
+               int error, send_failed = 0;
                struct hn_txdesc *txd;
-               netvsc_packet *packet;
                struct mbuf *m_head;
 
                IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
@@ -793,216 +998,17 @@ hn_start_locked(struct ifnet *ifp, int l
                        break;
                }
 
-               packet = &txd->netvsc_pkt;
-               packet->is_data_pkt = TRUE;
-               /* Initialize it from the mbuf */
-               packet->tot_data_buf_len = m_head->m_pkthdr.len;
-
-               /*
-                * extension points to the area reserved for the
-                * rndis_filter_packet, which is placed just after
-                * the netvsc_packet (and rppi struct, if present;
-                * length is updated later).
-                */
-               rndis_mesg = txd->rndis_msg;
-               /* XXX not necessary */
-               memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN);
-               rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
-
-               rndis_pkt = &rndis_mesg->msg.packet;
-               rndis_pkt->data_offset = sizeof(rndis_packet);
-               rndis_pkt->data_length = packet->tot_data_buf_len;
-               rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet);
-
-               rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet);
-
-               /*
-                * If the Hyper-V infrastructure needs to embed a VLAN tag,
-                * initialize netvsc_packet and rppi struct values as needed.
-                */
-               if (m_head->m_flags & M_VLANTAG) {
-                       /*
-                        * set up some additional fields so the Hyper-V 
infrastructure will stuff the VLAN tag
-                        * into the frame.
-                        */
-                       rndis_msg_size += RNDIS_VLAN_PPI_SIZE;
-
-                       rppi = hv_set_rppi_data(rndis_mesg, RNDIS_VLAN_PPI_SIZE,
-                           ieee_8021q_info);
-               
-                       /* VLAN info immediately follows rppi struct */
-                       rppi_vlan_info = (ndis_8021q_info *)((char*)rppi + 
-                           rppi->per_packet_info_offset);
-                       /* FreeBSD does not support CFI or priority */
-                       rppi_vlan_info->u1.s1.vlan_id =
-                           m_head->m_pkthdr.ether_vtag & 0xfff;
-               }
-
-               if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
-                       struct ether_vlan_header *eh;
-                       int ether_len;
-
-                       eh = mtod(m_head, struct ether_vlan_header*);
-                       if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
-                               ether_len = ETHER_HDR_LEN +
-                                   ETHER_VLAN_ENCAP_LEN;
-                       } else {
-                               ether_len = ETHER_HDR_LEN;
-                       }
-
-                       rndis_msg_size += RNDIS_TSO_PPI_SIZE;
-                       rppi = hv_set_rppi_data(rndis_mesg, RNDIS_TSO_PPI_SIZE,
-                           tcp_large_send_info);
-
-                       tso_info = (rndis_tcp_tso_info *)((char *)rppi +
-                           rppi->per_packet_info_offset);
-                       tso_info->lso_v2_xmit.type =
-                           RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
-
-#ifdef INET
-                       if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) {
-                               struct ip *ip =
-                                   (struct ip *)(m_head->m_data + ether_len);
-                               unsigned long iph_len = ip->ip_hl << 2;
-                               struct tcphdr *th =
-                                   (struct tcphdr *)((caddr_t)ip + iph_len);
-                       
-                               tso_info->lso_v2_xmit.ip_version =
-                                   RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4;
-                               ip->ip_len = 0;
-                               ip->ip_sum = 0;
-                       
-                               th->th_sum = in_pseudo(ip->ip_src.s_addr,
-                                   ip->ip_dst.s_addr, htons(IPPROTO_TCP));
-                       }
-#endif
-#if defined(INET6) && defined(INET)
-                       else
-#endif
-#ifdef INET6
-                       {
-                               struct ip6_hdr *ip6 = (struct ip6_hdr *)
-                                   (m_head->m_data + ether_len);
-                               struct tcphdr *th = (struct tcphdr *)(ip6 + 1);
-
-                               tso_info->lso_v2_xmit.ip_version =
-                                   RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV6;
-                               ip6->ip6_plen = 0;
-                               th->th_sum =
-                                   in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0);
-                       }
-#endif
-                       tso_info->lso_v2_xmit.tcp_header_offset = 0;
-                       tso_info->lso_v2_xmit.mss = m_head->m_pkthdr.tso_segsz;
-               } else if (m_head->m_pkthdr.csum_flags & sc->hn_csum_assist) {
-                       rndis_msg_size += RNDIS_CSUM_PPI_SIZE;
-                       rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE,
-                           tcpip_chksum_info);
-                       csum_info = (rndis_tcp_ip_csum_info *)((char*)rppi +
-                           rppi->per_packet_info_offset);
-
-                       csum_info->xmit.is_ipv4 = 1;
-                       if (m_head->m_pkthdr.csum_flags & CSUM_IP)
-                               csum_info->xmit.ip_header_csum = 1;
-
-                       if (m_head->m_pkthdr.csum_flags & CSUM_TCP) {
-                               csum_info->xmit.tcp_csum = 1;
-                               csum_info->xmit.tcp_header_offset = 0;
-                       } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) {
-                               csum_info->xmit.udp_csum = 1;
-                       }
-               }
-
-               rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size;
-               packet->tot_data_buf_len = rndis_mesg->msg_len;
-
-               /* send packet with send buffer */
-               if (packet->tot_data_buf_len < sc->hn_tx_chimney_size) {
-                       uint32_t send_buf_section_idx;
-
-                       send_buf_section_idx =
-                           hv_nv_get_next_send_section(net_dev);
-                       if (send_buf_section_idx !=
-                           NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
-                               uint8_t *dest = ((uint8_t *)net_dev->send_buf +
-                                   (send_buf_section_idx *
-                                    net_dev->send_section_size));
-
-                               memcpy(dest, rndis_mesg, rndis_msg_size);
-                               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->page_buf_count = 0;
-                               sc->hn_tx_chimney++;
-                               goto do_send;
-                       }
-               }
-
-               error = hn_txdesc_dmamap_load(sc, txd, &m_head, segs, &nsegs);
+               error = hn_encap(sc, txd, &m_head);
                if (error) {
-                       int freed;
-
-                       /*
-                        * This mbuf is not linked w/ the txd yet, so free
-                        * it now.
-                        */
-                       m_freem(m_head);
-                       freed = hn_txdesc_put(sc, txd);
-                       KASSERT(freed != 0,
-                           ("fail to free txd upon txdma error"));
-
-                       sc->hn_txdma_failed++;
-                       if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+                       /* Both txd and m_head are freed */
                        continue;
                }
-
-               packet->page_buf_count = nsegs +
-                   HV_RF_NUM_TX_RESERVED_PAGE_BUFS;
-
-               /* send packet with page buffer */
-               packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr);
-               packet->page_buffers[0].offset =
-                   txd->rndis_msg_paddr & PAGE_MASK;
-               packet->page_buffers[0].length = 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) {
-                       hv_vmbus_page_buffer *pb = &packet->page_buffers[
-                           i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS];
-
-                       pb->pfn = atop(segs[i].ds_addr);
-                       pb->offset = segs[i].ds_addr & PAGE_MASK;
-                       pb->length = segs[i].ds_len;
-               }
-
-               packet->send_buf_section_idx = 
-                   NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
-               packet->send_buf_section_size = 0;
-
-do_send:
-               txd->m = m_head;
-
-               /* Set the completion routine */
-               packet->compl.send.on_send_completion = netvsc_xmit_completion;
-               packet->compl.send.send_completion_context = packet;
-               packet->compl.send.send_completion_tid =
-                   (uint64_t)(uintptr_t)txd;
-
 again:
                /*
                 * Make sure that txd is not freed before ETHER_BPF_MTAP.
                 */
                hn_txdesc_hold(txd);
-               error = hv_nv_on_send(device_ctx, packet);
+               error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt);
                if (!error) {
                        ETHER_BPF_MTAP(ifp, m_head);
                        if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "[email protected]"

Reply via email to