Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Jun 2016 03:48:56 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r301912 - in stable/10/sys/dev/hyperv: include netvsc storvsc vmbus
Message-ID:  <201606150348.u5F3musq062852@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Wed Jun 15 03:48:55 2016
New Revision: 301912
URL: https://svnweb.freebsd.org/changeset/base/301912

Log:
  MFC 296083,296084,296085,296086,296087,296088,296089
  
  296083
      hyperv: Remove useless channel inbound_lock
  
      It serves no purpose.
  
      Reviewed by:        Hongjiang Zhang <honzhan microsoft com>
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5450
  
  296084
      hyperv: Always set device for channels
  
      And unregister hv_device only for primary channels, who own the hv_device.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5451
  
  296085
      hyperv/hn: Pass channel as the channel callback argument
  
      This is the preamble to pass channel back to hn(4) upon TX/RX done.
  
      Reviewed by:        Hongjiang Zhang <honzhan microsoft com>
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5452
  
  296086
      hyperv/hn: Pass channel to TX/RX done
  
      This is preamble to associate the TX/RX rings to their channel.
  
      While I'm here, revoke unused netvsc_recv_rollup.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5453
  
  296087
      hyperv/hn: Associate TX/RX ring with channel
  
      This fixes the TX/RX ring selection for TX/RX done.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5454
  
  296088
      hyperv/hn: Remove the useless num_outstanding_sends
  
      We rely on taskqueue draining now.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5456
  
  296089
      hyperv/hn: Make transmission path channel aware
  
      Chimney sending buffer still needs conversion, which will be done
      along with the upcoming vRSS support.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5457

Modified:
  stable/10/sys/dev/hyperv/include/hyperv.h
  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.h
  stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h
  stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
  stable/10/sys/dev/hyperv/vmbus/hv_channel.c
  stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/hyperv.h	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/include/hyperv.h	Wed Jun 15 03:48:55 2016	(r301912)
@@ -753,8 +753,6 @@ typedef struct hv_vmbus_channel {
 	 */
 	hv_vmbus_ring_buffer_info	inbound;
 
-	struct mtx			inbound_lock;
-
 	struct taskqueue *		rxq;
 	struct task			channel_task;
 	hv_vmbus_pfn_channel_callback	on_channel_callback;
@@ -824,12 +822,16 @@ typedef struct hv_vmbus_channel {
 	 * This will be NULL for the primary channel.
 	 */
 	struct hv_vmbus_channel		*primary_channel;
+
 	/*
-	 * Support per channel state for use by vmbus drivers.
+	 * Driver private data
 	 */
-	void				*per_channel_state;
+	void				*hv_chan_priv1;
+	void				*hv_chan_priv2;
 } hv_vmbus_channel;
 
+#define HV_VMBUS_CHAN_ISPRIMARY(chan)	((chan)->primary_channel == NULL)
+
 static inline void
 hv_set_channel_read_state(hv_vmbus_channel* channel, boolean_t state)
 {

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Wed Jun 15 03:48:55 2016	(r301912)
@@ -62,7 +62,8 @@ static int  hv_nv_connect_to_vsp(struct 
 static void hv_nv_on_send_completion(netvsc_dev *net_dev,
     struct hv_device *device, hv_vm_packet_descriptor *pkt);
 static void hv_nv_on_receive(netvsc_dev *net_dev,
-    struct hv_device *device, hv_vm_packet_descriptor *pkt);
+    struct hv_device *device, struct hv_vmbus_channel *chan,
+    hv_vm_packet_descriptor *pkt);
 
 /*
  *
@@ -115,7 +116,7 @@ hv_nv_get_inbound_net_device(struct hv_d
 	 * permit incoming packets if and only if there
 	 * are outstanding sends.
 	 */
-	if (net_dev->destroy && net_dev->num_outstanding_sends == 0) {
+	if (net_dev->destroy) {
 		return (NULL);
 	}
 
@@ -678,7 +679,7 @@ hv_nv_on_device_add(struct hv_device *de
 	 */
 	ret = hv_vmbus_channel_open(device->channel,
 	    NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE,
-	    NULL, 0, hv_nv_on_channel_callback, device);
+	    NULL, 0, hv_nv_on_channel_callback, device->channel);
 	if (ret != 0)
 		goto cleanup;
 
@@ -719,14 +720,7 @@ hv_nv_on_device_remove(struct hv_device 
 	netvsc_dev *net_dev = sc->net_dev;;
 	
 	/* Stop outbound traffic ie sends and receives completions */
-	mtx_lock(&device->channel->inbound_lock);
 	net_dev->destroy = TRUE;
-	mtx_unlock(&device->channel->inbound_lock);
-
-	/* Wait for all send completions */
-	while (net_dev->num_outstanding_sends) {
-		DELAY(100);
-	}
 
 	hv_nv_disconnect_from_vsp(net_dev);
 
@@ -805,8 +799,6 @@ hv_nv_on_send_completion(netvsc_dev *net
 			    net_vsc_pkt->compl.send.send_completion_context);
 
 		}
-
-		atomic_subtract_int(&net_dev->num_outstanding_sends, 1);
 	}
 }
 
@@ -816,16 +808,11 @@ hv_nv_on_send_completion(netvsc_dev *net
  * Returns 0 on success, non-zero on failure.
  */
 int
-hv_nv_on_send(struct hv_device *device, netvsc_packet *pkt)
+hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt)
 {
-	netvsc_dev *net_dev;
 	nvsp_msg send_msg;
 	int ret;
 
-	net_dev = hv_nv_get_outbound_net_device(device);
-	if (!net_dev)
-		return (ENODEV);
-
 	send_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt;
 	if (pkt->is_data_pkt) {
 		/* 0 is RMC_DATA */
@@ -841,20 +828,16 @@ hv_nv_on_send(struct hv_device *device, 
 	    pkt->send_buf_section_size;
 
 	if (pkt->page_buf_count) {
-		ret = hv_vmbus_channel_send_packet_pagebuffer(device->channel,
+		ret = hv_vmbus_channel_send_packet_pagebuffer(chan,
 		    pkt->page_buffers, pkt->page_buf_count,
 		    &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt);
 	} else {
-		ret = hv_vmbus_channel_send_packet(device->channel,
+		ret = hv_vmbus_channel_send_packet(chan,
 		    &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt,
 		    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
 		    HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 	}
 
-	/* Record outstanding send only if send_packet() succeeded */
-	if (ret == 0)
-		atomic_add_int(&net_dev->num_outstanding_sends, 1);
-
 	return (ret);
 }
 
@@ -866,7 +849,7 @@ hv_nv_on_send(struct hv_device *device, 
  */
 static void
 hv_nv_on_receive(netvsc_dev *net_dev, struct hv_device *device,
-    hv_vm_packet_descriptor *pkt)
+    struct hv_vmbus_channel *chan, hv_vm_packet_descriptor *pkt)
 {
 	hv_vm_transfer_page_packet_header *vm_xfer_page_pkt;
 	nvsp_msg *nvsp_msg_pkt;
@@ -916,7 +899,7 @@ hv_nv_on_receive(netvsc_dev *net_dev, st
 		net_vsc_pkt->tot_data_buf_len = 
 		    vm_xfer_page_pkt->ranges[i].byte_count;
 
-		hv_rf_on_receive(net_dev, device, net_vsc_pkt);
+		hv_rf_on_receive(net_dev, device, chan, net_vsc_pkt);
 		if (net_vsc_pkt->status != nvsp_status_success) {
 			status = nvsp_status_failure;
 		}
@@ -929,7 +912,6 @@ hv_nv_on_receive(netvsc_dev *net_dev, st
 	 */
 	hv_nv_on_receive_completion(device, vm_xfer_page_pkt->d.transaction_id,
 	    status);
-	hv_rf_receive_rollup(net_dev);
 }
 
 /*
@@ -973,9 +955,10 @@ retry_send_cmplt:
  * Net VSC on channel callback
  */
 static void
-hv_nv_on_channel_callback(void *context)
+hv_nv_on_channel_callback(void *xchan)
 {
-	struct hv_device *device = (struct hv_device *)context;
+	struct hv_vmbus_channel *chan = xchan;
+	struct hv_device *device = chan->device;
 	netvsc_dev *net_dev;
 	device_t dev = device->device;
 	uint32_t bytes_rxed;
@@ -992,7 +975,7 @@ hv_nv_on_channel_callback(void *context)
 	buffer = net_dev->callback_buf;
 
 	do {
-		ret = hv_vmbus_channel_recv_packet_raw(device->channel,
+		ret = hv_vmbus_channel_recv_packet_raw(chan,
 		    buffer, bufferlen, &bytes_rxed, &request_id);
 		if (ret == 0) {
 			if (bytes_rxed > 0) {
@@ -1002,7 +985,7 @@ hv_nv_on_channel_callback(void *context)
 					hv_nv_on_send_completion(net_dev, device, desc);
 					break;
 				case HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES:
-					hv_nv_on_receive(net_dev, device, desc);
+					hv_nv_on_receive(net_dev, device, chan, desc);
 					break;
 				default:
 					device_printf(dev,
@@ -1036,5 +1019,5 @@ hv_nv_on_channel_callback(void *context)
 	if (bufferlen > NETVSC_PACKET_SIZE)
 		free(buffer, M_NETVSC);
 
-	hv_rf_channel_rollup(net_dev);
+	hv_rf_channel_rollup(chan);
 }

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Wed Jun 15 03:48:55 2016	(r301912)
@@ -893,7 +893,6 @@ typedef struct nvsp_msg_ {
  */
 typedef struct netvsc_dev_ {
 	struct hv_device			*dev;
-	int					num_outstanding_sends;
 
 	/* Send buffer allocated by us but manages by NetVSP */
 	void					*send_buf;
@@ -1000,6 +999,7 @@ struct buf_ring;
 #endif
 
 struct hn_rx_ring {
+	struct ifnet	*hn_ifp;
 	struct lro_ctrl	hn_lro;
 
 	/* Trust csum verification on host side */
@@ -1017,6 +1017,8 @@ struct hn_rx_ring {
 #define HN_TRUST_HCSUM_TCP	0x0002
 #define HN_TRUST_HCSUM_UDP	0x0004
 
+struct hv_vmbus_channel;
+
 struct hn_tx_ring {
 #ifndef HN_USE_TXDESC_BUFRING
 	struct mtx	hn_txlist_spin;
@@ -1039,6 +1041,7 @@ struct hn_tx_ring {
 
 	struct mtx	hn_tx_lock;
 	struct hn_softc	*hn_sc;
+	struct hv_vmbus_channel *hn_chan;
 
 	int		hn_direct_tx_size;
 	int		hn_tx_chimney_size;
@@ -1097,7 +1100,7 @@ netvsc_dev *hv_nv_on_device_add(struct h
     void *additional_info);
 int hv_nv_on_device_remove(struct hv_device *device,
     boolean_t destroy_channel);
-int hv_nv_on_send(struct hv_device *device, netvsc_packet *pkt);
+int hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt);
 int hv_nv_get_next_send_section(netvsc_dev *net_dev);
 
 #endif  /* __HV_NET_VSC_H__ */

Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Wed Jun 15 03:48:55 2016	(r301912)
@@ -119,6 +119,8 @@ __FBSDID("$FreeBSD$");
 #include "hv_rndis.h"
 #include "hv_rndis_filter.h"
 
+#define hv_chan_rxr	hv_chan_priv1
+#define hv_chan_txr	hv_chan_priv2
 
 /* Short for Hyper-V network interface */
 #define NETVSC_DEVNAME    "hn"
@@ -397,6 +399,7 @@ static int
 netvsc_attach(device_t dev)
 {
 	struct hv_device *device_ctx = vmbus_get_devctx(dev);
+	struct hv_vmbus_channel *chan;
 	netvsc_device_info device_info;
 	hn_softc_t *sc;
 	int unit = device_get_unit(dev);
@@ -449,6 +452,14 @@ netvsc_attach(device_t dev)
 
 	hn_create_rx_data(sc);
 
+	/*
+	 * Associate the first TX/RX ring w/ the primary channel.
+	 */
+	chan = device_ctx->channel;
+	chan->hv_chan_rxr = &sc->hn_rx_ring[0];
+	chan->hv_chan_txr = &sc->hn_tx_ring[0];
+	sc->hn_tx_ring[0].hn_chan = chan;
+
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_dunit = unit;
 	ifp->if_dname = NETVSC_DEVNAME;
@@ -706,12 +717,11 @@ hn_tx_done(void *xpkt)
 }
 
 void
-netvsc_channel_rollup(struct hv_device *device_ctx)
+netvsc_channel_rollup(struct hv_vmbus_channel *chan)
 {
-	struct hn_softc *sc = device_get_softc(device_ctx->device);
-	struct hn_tx_ring *txr = &sc->hn_tx_ring[0]; /* TODO: vRSS */
+	struct hn_tx_ring *txr = chan->hv_chan_txr;
 #if defined(INET) || defined(INET6)
-	struct hn_rx_ring *rxr = &sc->hn_rx_ring[0]; /* TODO: vRSS */
+	struct hn_rx_ring *rxr = chan->hv_chan_rxr;
 	struct lro_ctrl *lro = &rxr->hn_lro;
 	struct lro_entry *queued;
 
@@ -721,7 +731,12 @@ netvsc_channel_rollup(struct hv_device *
 	}
 #endif
 
-	if (!txr->hn_has_txeof)
+	/*
+	 * NOTE:
+	 * 'txr' could be NULL, if multiple channels and
+	 * ifnet.if_start method are enabled.
+	 */
+	if (txr == NULL || !txr->hn_has_txeof)
 		return;
 
 	txr->hn_has_txeof = 0;
@@ -862,6 +877,8 @@ hn_encap(struct hn_tx_ring *txr, struct 
 
 	/*
 	 * Chimney send, if the packet could fit into one chimney buffer.
+	 *
+	 * TODO: vRSS, chimney buffer should be per-channel.
 	 */
 	if (packet->tot_data_buf_len < txr->hn_tx_chimney_size) {
 		netvsc_dev *net_dev = txr->hn_sc->net_dev;
@@ -948,8 +965,7 @@ done:
  * associated w/ the txd will _not_ be freed.
  */
 static int
-hn_send_pkt(struct ifnet *ifp, struct hv_device *device_ctx,
-    struct hn_tx_ring *txr, struct hn_txdesc *txd)
+hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd)
 {
 	int error, send_failed = 0;
 
@@ -958,7 +974,7 @@ again:
 	 * Make sure that txd is not freed before ETHER_BPF_MTAP.
 	 */
 	hn_txdesc_hold(txd);
-	error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt);
+	error = hv_nv_on_send(txr->hn_chan, &txd->netvsc_pkt);
 	if (!error) {
 		ETHER_BPF_MTAP(ifp, txd->m);
 		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
@@ -1018,7 +1034,6 @@ hn_start_locked(struct hn_tx_ring *txr, 
 {
 	struct hn_softc *sc = txr->hn_sc;
 	struct ifnet *ifp = sc->hn_ifp;
-	struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev);
 
 	KASSERT(hn_use_if_start,
 	    ("hn_start_locked is called, when if_start is disabled"));
@@ -1062,7 +1077,7 @@ hn_start_locked(struct hn_tx_ring *txr, 
 			continue;
 		}
 
-		error = hn_send_pkt(ifp, device_ctx, txr, txd);
+		error = hn_send_pkt(ifp, txr, txd);
 		if (__predict_false(error)) {
 			/* txd is freed, but m_head is not */
 			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
@@ -1157,26 +1172,16 @@ hv_m_append(struct mbuf *m0, int len, c_
  * Note:  This is no longer used as a callback
  */
 int
-netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
+netvsc_recv(struct hv_vmbus_channel *chan, netvsc_packet *packet,
     rndis_tcp_ip_csum_info *csum_info)
 {
-	struct hn_softc *sc = device_get_softc(device_ctx->device);
-	struct hn_rx_ring *rxr = &sc->hn_rx_ring[0]; /* TODO: vRSS */
+	struct hn_rx_ring *rxr = chan->hv_chan_rxr;
+	struct ifnet *ifp = rxr->hn_ifp;
 	struct mbuf *m_new;
-	struct ifnet *ifp;
 	int size, do_lro = 0, do_csum = 1;
 
-	if (sc == NULL) {
-		return (0); /* TODO: KYS how can this be! */
-	}
-
-	ifp = sc->hn_ifp;
-	
-	ifp = sc->arpcom.ac_ifp;
-
-	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
 		return (0);
-	}
 
 	/*
 	 * Bail out if packet contains more data than configured MTU.
@@ -1329,11 +1334,6 @@ skip:
 	return (0);
 }
 
-void
-netvsc_recv_rollup(struct hv_device *device_ctx __unused)
-{
-}
-
 /*
  * Rules for using sc->temp_unusable:
  * 1.  sc->temp_unusable can only be read or written while holding NV_LOCK()
@@ -2084,6 +2084,7 @@ hn_create_rx_data(struct hn_softc *sc)
 			rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_UDP;
 		if (hn_trust_hostip)
 			rxr->hn_trust_hcsum |= HN_TRUST_HCSUM_IP;
+		rxr->hn_ifp = sc->hn_ifp;
 
 		/*
 		 * Initialize LRO.
@@ -2567,7 +2568,6 @@ hn_xmit(struct hn_tx_ring *txr, int len)
 {
 	struct hn_softc *sc = txr->hn_sc;
 	struct ifnet *ifp = sc->hn_ifp;
-	struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev);
 	struct mbuf *m_head;
 
 	mtx_assert(&txr->hn_tx_lock, MA_OWNED);
@@ -2606,7 +2606,7 @@ hn_xmit(struct hn_tx_ring *txr, int len)
 			continue;
 		}
 
-		error = hn_send_pkt(ifp, device_ctx, txr, txd);
+		error = hn_send_pkt(ifp, txr, txd);
 		if (__predict_false(error)) {
 			/* txd is freed, but m_head is not */
 			drbr_putback(ifp, txr->hn_mbuf_br, m_head);

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis.h	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis.h	Wed Jun 15 03:48:55 2016	(r301912)
@@ -1046,11 +1046,11 @@ typedef struct rndismp_rx_bufs_info_ {
 /*
  * Externs
  */
-int netvsc_recv(struct hv_device *device_ctx, 
-    netvsc_packet *packet, 
-    rndis_tcp_ip_csum_info *csum_info);
-void netvsc_recv_rollup(struct hv_device *device_ctx);
-void netvsc_channel_rollup(struct hv_device *device_ctx);
+struct hv_vmbus_channel;
+
+int netvsc_recv(struct hv_vmbus_channel *chan,
+    netvsc_packet *packet, rndis_tcp_ip_csum_info *csum_info);
+void netvsc_channel_rollup(struct hv_vmbus_channel *chan);
 
 void* hv_set_rppi_data(rndis_msg *rndis_mesg,
     uint32_t rppi_size,

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Wed Jun 15 03:48:55 2016	(r301912)
@@ -59,6 +59,7 @@ static void hv_rf_receive_response(rndis
 static void hv_rf_receive_indicate_status(rndis_device *device,
 					  rndis_msg *response);
 static void hv_rf_receive_data(rndis_device *device, rndis_msg *message,
+			       struct hv_vmbus_channel *chan,
 			       netvsc_packet *pkt);
 static int  hv_rf_query_device(rndis_device *device, uint32_t oid,
 			       void *result, uint32_t *result_size);
@@ -250,7 +251,7 @@ hv_rf_send_request(rndis_device *device,
 	    NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
 	packet->send_buf_section_size = 0;
 
-	ret = hv_nv_on_send(device->net_dev->dev, packet);
+	ret = hv_nv_on_send(device->net_dev->dev->channel, packet);
 
 	return (ret);
 }
@@ -406,7 +407,8 @@ hv_rf_receive_indicate_status(rndis_devi
  * RNDIS filter receive data
  */
 static void
-hv_rf_receive_data(rndis_device *device, rndis_msg *message, netvsc_packet *pkt)
+hv_rf_receive_data(rndis_device *device, rndis_msg *message,
+    struct hv_vmbus_channel *chan, netvsc_packet *pkt)
 {
 	rndis_packet *rndis_pkt;
 	ndis_8021q_info *rppi_vlan_info;
@@ -444,14 +446,15 @@ hv_rf_receive_data(rndis_device *device,
 	}
 
 	csum_info = hv_get_ppi_data(rndis_pkt, tcpip_chksum_info);
-	netvsc_recv(device->net_dev->dev, pkt, csum_info);
+	netvsc_recv(chan, pkt, csum_info);
 }
 
 /*
  * RNDIS filter on receive
  */
 int
-hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device, netvsc_packet *pkt)
+hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device,
+    struct hv_vmbus_channel *chan, netvsc_packet *pkt)
 {
 	rndis_device *rndis_dev;
 	rndis_msg *rndis_hdr;
@@ -474,7 +477,7 @@ hv_rf_on_receive(netvsc_dev *net_dev, st
 
 	/* data message */
 	case REMOTE_NDIS_PACKET_MSG:
-		hv_rf_receive_data(rndis_dev, rndis_hdr, pkt);
+		hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt);
 		break;
 	/* completion messages */
 	case REMOTE_NDIS_INITIALIZE_CMPLT:
@@ -958,32 +961,9 @@ hv_rf_on_send_request_halt_completion(vo
 	request->halt_complete_flag = 1;
 }
 
-/*
- * RNDIS filter when "all" reception is done
- */
 void
-hv_rf_receive_rollup(netvsc_dev *net_dev)
+hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
 {
-	rndis_device *rndis_dev;
-
-	rndis_dev = (rndis_device *)net_dev->extension;
-	netvsc_recv_rollup(rndis_dev->net_dev->dev);
-}
 
-void
-hv_rf_channel_rollup(netvsc_dev *net_dev)
-{
-	rndis_device *rndis_dev;
-
-	rndis_dev = (rndis_device *)net_dev->extension;
-
-	/*
-	 * This could be called pretty early, so we need
-	 * to make sure everything has been setup.
-	 */
-	if (rndis_dev == NULL ||
-	    rndis_dev->net_dev == NULL ||
-	    rndis_dev->net_dev->dev == NULL)
-		return;
-	netvsc_channel_rollup(rndis_dev->net_dev->dev);
+	netvsc_channel_rollup(chan);
 }

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h	Wed Jun 15 03:48:55 2016	(r301912)
@@ -95,11 +95,12 @@ typedef struct rndis_device_ {
 /*
  * Externs
  */
+struct hv_vmbus_channel;
 
-int hv_rf_on_receive(netvsc_dev *net_dev,
-    struct hv_device *device, netvsc_packet *pkt);
+int hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device,
+    struct hv_vmbus_channel *chan, netvsc_packet *pkt);
 void hv_rf_receive_rollup(netvsc_dev *net_dev);
-void hv_rf_channel_rollup(netvsc_dev *net_dev);
+void hv_rf_channel_rollup(struct hv_vmbus_channel *chan);
 int hv_rf_on_device_add(struct hv_device *device, void *additl_info);
 int hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel);
 int hv_rf_on_open(struct hv_device *device);

Modified: stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c	Wed Jun 15 03:48:55 2016	(r301912)
@@ -365,7 +365,7 @@ storvsc_handle_sc_creation(void *context
 	int ret = 0;
 
 	new_channel = (hv_vmbus_channel *)context;
-	device = new_channel->primary_channel->device;
+	device = new_channel->device;
 	sc = get_stor_device(device, TRUE);
 	if (sc == NULL)
 		return;
@@ -883,12 +883,7 @@ hv_storvsc_on_channel_callback(void *con
 	struct hv_storvsc_request *request;
 	struct vstor_packet *vstor_packet;
 
-	if (channel->primary_channel != NULL){
-		device = channel->primary_channel->device;
-	} else {
-		device = channel->device;
-	}
-
+	device = channel->device;
 	KASSERT(device, ("device is NULL"));
 
 	sc = get_stor_device(device, FALSE);
@@ -1186,9 +1181,7 @@ storvsc_detach(device_t dev)
 	struct hv_sgl_node *sgl_node = NULL;
 	int j = 0;
 
-	mtx_lock(&hv_device->channel->inbound_lock);
 	sc->hs_destroy = TRUE;
-	mtx_unlock(&hv_device->channel->inbound_lock);
 
 	/*
 	 * At this point, all outbound traffic should be disabled. We

Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Wed Jun 15 03:48:55 2016	(r301912)
@@ -537,13 +537,7 @@ hv_vmbus_channel_close_internal(hv_vmbus
 	 */
 	channel->rxq = NULL;
 	taskqueue_drain(rxq, &channel->channel_task);
-	/*
-	 * Grab the lock to prevent race condition when a packet received
-	 * and unloading driver is in the process.
-	 */
-	mtx_lock(&channel->inbound_lock);
 	channel->on_channel_callback = NULL;
-	mtx_unlock(&channel->inbound_lock);
 
 	/**
 	 * Send a closing message
@@ -920,12 +914,6 @@ VmbusProcessChannelEvent(void* context, 
 	 * callback to NULL. This closes the window.
 	 */
 
-	/*
-	 * Disable the lock due to newly added WITNESS check in r277723.
-	 * Will seek other way to avoid race condition.
-	 * -- whu
-	 */
-	// mtx_lock(&channel->inbound_lock);
 	if (channel->on_channel_callback != NULL) {
 		arg = channel->channel_callback_context;
 		is_batched_reading = channel->batched_reading;
@@ -952,5 +940,4 @@ VmbusProcessChannelEvent(void* context, 
 				bytes_to_read = 0;
 		} while (is_batched_reading && (bytes_to_read != 0));
 	}
-	// mtx_unlock(&channel->inbound_lock);
 }

Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Wed Jun 15 03:17:05 2016	(r301911)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Wed Jun 15 03:48:55 2016	(r301912)
@@ -143,9 +143,7 @@ hv_vmbus_allocate_channel(void)
 					M_DEVBUF,
 					M_WAITOK | M_ZERO);
 
-	mtx_init(&channel->inbound_lock, "channel inbound", NULL, MTX_DEF);
 	mtx_init(&channel->sc_lock, "vmbus multi channel", NULL, MTX_DEF);
-
 	TAILQ_INIT(&channel->sc_list_anchor);
 
 	return (channel);
@@ -158,8 +156,6 @@ void
 hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel)
 {
 	mtx_destroy(&channel->sc_lock);
-	mtx_destroy(&channel->inbound_lock);
-
 	free(channel, M_DEVBUF);
 }
 
@@ -218,6 +214,7 @@ vmbus_channel_process_offer(hv_vmbus_cha
 			 * It is a sub channel offer, process it.
 			 */
 			new_channel->primary_channel = channel;
+			new_channel->device = channel->device;
 			mtx_lock(&channel->sc_lock);
 			TAILQ_INSERT_TAIL(
 			    &channel->sc_list_anchor,
@@ -458,7 +455,10 @@ vmbus_channel_on_offer_rescind_internal(
 	hv_vmbus_channel*               channel;
 
 	channel = (hv_vmbus_channel*)context;
-	hv_vmbus_child_device_unregister(channel->device);
+	if (HV_VMBUS_CHAN_ISPRIMARY(channel)) {
+		/* Only primary channel owns the hv_device */
+		hv_vmbus_child_device_unregister(channel->device);
+	}
 }
 
 /**
@@ -679,7 +679,10 @@ hv_vmbus_release_unattached_channels(voi
 	    TAILQ_REMOVE(&hv_vmbus_g_connection.channel_anchor,
 			    channel, list_entry);
 
-	    hv_vmbus_child_device_unregister(channel->device);
+	    if (HV_VMBUS_CHAN_ISPRIMARY(channel)) {
+		/* Only primary channel owns the hv_device */
+		hv_vmbus_child_device_unregister(channel->device);
+	    }
 	    hv_vmbus_free_vmbus_channel(channel);
 	}
 	bzero(hv_vmbus_g_connection.channels, 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606150348.u5F3musq062852>