Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Jun 2016 06:18:41 +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: r302048 - in stable/10/sys/dev/hyperv: include netvsc storvsc vmbus
Message-ID:  <201606210618.u5L6IfA0013039@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Tue Jun 21 06:18:41 2016
New Revision: 302048
URL: https://svnweb.freebsd.org/changeset/base/302048

Log:
  MFC 298569,298570,298571,298572,298574,298575,298613,298614,298615,298616,298617
  
  298569
      hyperv/channel: Remove the unnecessary 'new' flag
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298570
      hyperv/channel: Minor style changes; no functional changes.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298571
      hyperv/channel: Remove unapplied comment
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298572
      hyperv/channel: Log a warning about duplicated primary channel offer
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298574
      hyperv/channel: Add functions to synchronize sub-channel offers
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298575
      hyperv/hn: Synchronize sub-channel offers
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298613
      hyperv/stor: Remove the useless hs_open_multi_channel
  
      This fixes the sub-channel offer race after Hyper-V device probe/attach
      is moved to vmbus SYSINIT/attach.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298614
      hyperv/stor: Synchronize sub-channel offers
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298615
      hyperv/hn: Avoid sub-channel creation callback.
  
      Since the sub-channel offers are synchronized, we can do our own
      channel setup without using the sub-channel creation callback.
  
      This paves the way to whack the sub-channel creation callback.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298616
      hyperv/stor: Avoid sub-channel creation callback.
  
      Since the sub-channel offers are synchronized, we can do our own
      channel setup without using the sub-channel creation callback.
  
      This paves the way to whack the sub-channel creation callback.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
  
  298617
      hyperv/channel: Git rid of the sub-channel creation callback
  
      It is no longer used.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC

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/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	Tue Jun 21 05:49:07 2016	(r302047)
+++ stable/10/sys/dev/hyperv/include/hyperv.h	Tue Jun 21 06:18:41 2016	(r302048)
@@ -691,7 +691,6 @@ typedef struct {
 } hv_vmbus_ring_buffer_info;
 
 typedef void (*hv_vmbus_pfn_channel_callback)(void *context);
-typedef void (*hv_vmbus_sc_creation_callback)(void *context);
 
 typedef enum {
 	HV_CHANNEL_OFFER_STATE,
@@ -804,13 +803,6 @@ typedef struct hv_vmbus_channel {
 	 * response on the same channel.
 	 */
 
-	/*
-	 * Multi-channel creation callback. This callback will be called in
-	 * process context when a Multi-channel offer is received from the host.
-	 * The guest can open the Multi-channel in the context of this callback.
-	 */
-	hv_vmbus_sc_creation_callback	sc_creation_callback;
-
 	struct mtx			sc_lock;
 
 	/*
@@ -818,6 +810,7 @@ typedef struct hv_vmbus_channel {
 	 */
 	TAILQ_HEAD(, hv_vmbus_channel)	sc_list_anchor;
 	TAILQ_ENTRY(hv_vmbus_channel)	sc_list_entry;
+	int				subchan_cnt;
 
 	/*
 	 * The primary channel this sub-channle belongs to.
@@ -914,6 +907,9 @@ int		hv_vmbus_channel_teardown_gpdal(
 struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary);
 
 void		vmbus_channel_cpu_set(struct hv_vmbus_channel *chan, int cpu);
+struct hv_vmbus_channel **
+		vmbus_get_subchan(struct hv_vmbus_channel *pri_chan, int subchan_cnt);
+void		vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt);
 
 /**
  * @brief Get physical address from virtual

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Tue Jun 21 05:49:07 2016	(r302047)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Tue Jun 21 06:18:41 2016	(r302048)
@@ -660,30 +660,12 @@ hv_nv_disconnect_from_vsp(netvsc_dev *ne
 	hv_nv_destroy_send_buffer(net_dev);
 }
 
-/*
- * Callback handler for subchannel offer
- * @@param context new subchannel
- */
-static void
-hv_nv_subchan_callback(void *xchan)
+void
+hv_nv_subchan_attach(struct hv_vmbus_channel *chan)
 {
-	struct hv_vmbus_channel *chan = xchan;
-	netvsc_dev *net_dev;
-	uint16_t chn_index = chan->offer_msg.offer.sub_channel_index;
-	struct hv_device *device = chan->device;
-	hn_softc_t *sc = device_get_softc(device->device);
-	int ret;
-
-	net_dev = sc->net_dev;
-
-	if (chn_index >= net_dev->num_channel) {
-		/* Would this ever happen? */
-		return;
-	}
-	netvsc_subchan_callback(sc, chan);
 
 	chan->hv_chan_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK);
-	ret = hv_vmbus_channel_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
+	hv_vmbus_channel_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE,
 	    NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0,
 	    hv_nv_on_channel_callback, chan);
 }
@@ -720,7 +702,6 @@ hv_nv_on_device_add(struct hv_device *de
 		free(chan->hv_chan_rdbuf, M_NETVSC);
 		goto cleanup;
 	}
-	chan->sc_creation_callback = hv_nv_subchan_callback;
 
 	/*
 	 * Connect with the NetVsp

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Tue Jun 21 05:49:07 2016	(r302047)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Tue Jun 21 06:18:41 2016	(r302048)
@@ -1267,6 +1267,7 @@ int hv_nv_on_device_remove(struct hv_dev
     boolean_t destroy_channel);
 int hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt);
 int hv_nv_get_next_send_section(netvsc_dev *net_dev);
+void hv_nv_subchan_attach(struct hv_vmbus_channel *chan);
 
 #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	Tue Jun 21 05:49:07 2016	(r302047)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Tue Jun 21 06:18:41 2016	(r302048)
@@ -336,6 +336,7 @@ static void hn_create_rx_data(struct hn_
 static void hn_destroy_rx_data(struct hn_softc *sc);
 static void hn_set_tx_chimney_size(struct hn_softc *, int);
 static void hn_channel_attach(struct hn_softc *, struct hv_vmbus_channel *);
+static void hn_subchan_attach(struct hn_softc *, struct hv_vmbus_channel *);
 
 static int hn_transmit(struct ifnet *, struct mbuf *);
 static void hn_xmit_qflush(struct ifnet *);
@@ -438,7 +439,7 @@ static int
 netvsc_attach(device_t dev)
 {
 	struct hv_device *device_ctx = vmbus_get_devctx(dev);
-	struct hv_vmbus_channel *chan;
+	struct hv_vmbus_channel *pri_chan;
 	netvsc_device_info device_info;
 	hn_softc_t *sc;
 	int unit = device_get_unit(dev);
@@ -518,12 +519,12 @@ netvsc_attach(device_t dev)
 	/*
 	 * Associate the first TX/RX ring w/ the primary channel.
 	 */
-	chan = device_ctx->channel;
-	KASSERT(HV_VMBUS_CHAN_ISPRIMARY(chan), ("not primary channel"));
-	KASSERT(chan->offer_msg.offer.sub_channel_index == 0,
+	pri_chan = device_ctx->channel;
+	KASSERT(HV_VMBUS_CHAN_ISPRIMARY(pri_chan), ("not primary channel"));
+	KASSERT(pri_chan->offer_msg.offer.sub_channel_index == 0,
 	    ("primary channel subidx %u",
-	     chan->offer_msg.offer.sub_channel_index));
-	hn_channel_attach(sc, chan);
+	     pri_chan->offer_msg.offer.sub_channel_index));
+	hn_channel_attach(sc, pri_chan);
 
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
 	ifp->if_ioctl = hn_ioctl;
@@ -578,6 +579,26 @@ netvsc_attach(device_t dev)
 	device_printf(dev, "%d TX ring, %d RX ring\n",
 	    sc->hn_tx_ring_inuse, sc->hn_rx_ring_inuse);
 
+	if (sc->net_dev->num_channel > 1) {
+		struct hv_vmbus_channel **subchan;
+		int subchan_cnt = sc->net_dev->num_channel - 1;
+		int i;
+
+		/* Wait for sub-channels setup to complete. */
+		subchan = vmbus_get_subchan(pri_chan, subchan_cnt);
+
+		/* Attach the sub-channels. */
+		for (i = 0; i < subchan_cnt; ++i) {
+			/* NOTE: Calling order is critical. */
+			hn_subchan_attach(sc, subchan[i]);
+			hv_nv_subchan_attach(subchan[i]);
+		}
+
+		/* Release the sub-channels */
+		vmbus_rel_subchan(subchan, subchan_cnt);
+		device_printf(dev, "%d sub-channels setup done\n", subchan_cnt);
+	}
+
 #if __FreeBSD_version >= 1100099
 	if (sc->hn_rx_ring_inuse > 1) {
 		/*
@@ -2910,8 +2931,8 @@ hn_channel_attach(struct hn_softc *sc, s
 	vmbus_channel_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus);
 }
 
-void
-netvsc_subchan_callback(struct hn_softc *sc, struct hv_vmbus_channel *chan)
+static void
+hn_subchan_attach(struct hn_softc *sc, struct hv_vmbus_channel *chan)
 {
 
 	KASSERT(!HV_VMBUS_CHAN_ISPRIMARY(chan),

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis.h	Tue Jun 21 05:49:07 2016	(r302047)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis.h	Tue Jun 21 06:18:41 2016	(r302048)
@@ -1068,8 +1068,6 @@ 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 netvsc_subchan_callback(struct hn_softc *sc,
-    struct hv_vmbus_channel *chan);
 
 void* hv_set_rppi_data(rndis_msg *rndis_mesg,
     uint32_t rppi_size,

Modified: stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c	Tue Jun 21 05:49:07 2016	(r302047)
+++ stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c	Tue Jun 21 06:18:41 2016	(r302048)
@@ -134,7 +134,6 @@ struct storvsc_softc {
 	uint32_t			hs_num_out_reqs;
 	boolean_t			hs_destroy;
 	boolean_t			hs_drain_notify;
-	boolean_t			hs_open_multi_channel;
 	struct sema 			hs_drain_sema;	
 	struct hv_storvsc_request	hs_init_req;
 	struct hv_storvsc_request	hs_reset_req;
@@ -347,29 +346,19 @@ get_stor_device(struct hv_device *device
 	return sc;
 }
 
-/**
- * @brief Callback handler, will be invoked when receive mutil-channel offer
- *
- * @param context  new multi-channel
- */
 static void
-storvsc_handle_sc_creation(void *context)
+storvsc_subchan_attach(struct hv_vmbus_channel *new_channel)
 {
-	hv_vmbus_channel *new_channel;
 	struct hv_device *device;
 	struct storvsc_softc *sc;
 	struct vmstor_chan_props props;
 	int ret = 0;
 
-	new_channel = (hv_vmbus_channel *)context;
 	device = new_channel->device;
 	sc = get_stor_device(device, TRUE);
 	if (sc == NULL)
 		return;
 
-	if (FALSE == sc->hs_open_multi_channel)
-		return;
-	
 	memset(&props, 0, sizeof(props));
 
 	ret = hv_vmbus_channel_open(new_channel,
@@ -392,11 +381,12 @@ storvsc_handle_sc_creation(void *context
 static void
 storvsc_send_multichannel_request(struct hv_device *dev, int max_chans)
 {
+	struct hv_vmbus_channel **subchan;
 	struct storvsc_softc *sc;
 	struct hv_storvsc_request *request;
 	struct vstor_packet *vstor_packet;	
 	int request_channels_cnt = 0;
-	int ret;
+	int ret, i;
 
 	/* get multichannels count that need to create */
 	request_channels_cnt = MIN(max_chans, mp_ncpus);
@@ -410,9 +400,6 @@ storvsc_send_multichannel_request(struct
 
 	request = &sc->hs_init_req;
 
-	/* Establish a handler for multi-channel */
-	dev->channel->sc_creation_callback = storvsc_handle_sc_creation;
-
 	/* request the host to create multi-channel */
 	memset(request, 0, sizeof(struct hv_storvsc_request));
 	
@@ -448,7 +435,15 @@ storvsc_send_multichannel_request(struct
 		return;
 	}
 
-	sc->hs_open_multi_channel = TRUE;
+	/* Wait for sub-channels setup to complete. */
+	subchan = vmbus_get_subchan(dev->channel, request_channels_cnt);
+
+	/* Attach the sub-channels. */
+	for (i = 0; i < request_channels_cnt; ++i)
+		storvsc_subchan_attach(subchan[i]);
+
+	/* Release the sub-channels. */
+	vmbus_rel_subchan(subchan, request_channels_cnt);
 
 	if (bootverbose)
 		printf("Storvsc create multi-channel success!\n");
@@ -1067,7 +1062,6 @@ storvsc_attach(device_t dev)
 
 	sc->hs_destroy = FALSE;
 	sc->hs_drain_notify = FALSE;
-	sc->hs_open_multi_channel = FALSE;
 	sema_init(&sc->hs_drain_sema, 0, "Store Drain Sema");
 
 	ret = hv_storvsc_connect_vsp(hv_dev);

Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Tue Jun 21 05:49:07 2016	(r302047)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Tue Jun 21 06:18:41 2016	(r302048)
@@ -618,7 +618,6 @@ hv_vmbus_channel_close_internal(hv_vmbus
 	hv_vmbus_channel_msg_info* info;
 
 	channel->state = HV_CHANNEL_OPEN_STATE;
-	channel->sc_creation_callback = NULL;
 
 	/*
 	 * set rxq to NULL to avoid more requests be scheduled

Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Tue Jun 21 05:49:07 2016	(r302047)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Tue Jun 21 06:18:41 2016	(r302048)
@@ -177,13 +177,10 @@ hv_vmbus_free_vmbus_channel(hv_vmbus_cha
 static void
 vmbus_channel_process_offer(hv_vmbus_channel *new_channel)
 {
-	boolean_t		f_new;
 	hv_vmbus_channel*	channel;
 	int			ret;
 	uint32_t                relid;
 
-	f_new = TRUE;
-	channel = NULL;
 	relid = new_channel->offer_msg.child_rel_id;
 	/*
 	 * Make sure this is a new offer
@@ -192,31 +189,24 @@ vmbus_channel_process_offer(hv_vmbus_cha
 	hv_vmbus_g_connection.channels[relid] = new_channel;
 
 	TAILQ_FOREACH(channel, &hv_vmbus_g_connection.channel_anchor,
-	    list_entry)
-	{
+	    list_entry) {
 		if (memcmp(&channel->offer_msg.offer.interface_type,
 		    &new_channel->offer_msg.offer.interface_type,
 		    sizeof(hv_guid)) == 0 &&
 		    memcmp(&channel->offer_msg.offer.interface_instance,
 		    &new_channel->offer_msg.offer.interface_instance,
-		    sizeof(hv_guid)) == 0) {
-			f_new = FALSE;
+		    sizeof(hv_guid)) == 0)
 			break;
-		}
 	}
 
-	if (f_new) {
-		/* Insert at tail */
-		TAILQ_INSERT_TAIL(
-		    &hv_vmbus_g_connection.channel_anchor,
-		    new_channel,
-		    list_entry);
+	if (channel == NULL) {
+		/* Install the new primary channel */
+		TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_anchor,
+		    new_channel, list_entry);
 	}
 	mtx_unlock(&hv_vmbus_g_connection.channel_lock);
 
-	/*XXX add new channel to percpu_list */
-
-	if (!f_new) {
+	if (channel != NULL) {
 		/*
 		 * Check if this is a sub channel.
 		 */
@@ -227,10 +217,8 @@ vmbus_channel_process_offer(hv_vmbus_cha
 			new_channel->primary_channel = channel;
 			new_channel->device = channel->device;
 			mtx_lock(&channel->sc_lock);
-			TAILQ_INSERT_TAIL(
-			    &channel->sc_list_anchor,
-			    new_channel,
-			    sc_list_entry);
+			TAILQ_INSERT_TAIL(&channel->sc_list_anchor,
+			    new_channel, sc_list_entry);
 			mtx_unlock(&channel->sc_lock);
 
 			if (bootverbose) {
@@ -251,17 +239,25 @@ vmbus_channel_process_offer(hv_vmbus_cha
 				    "its primary channel is <%p>.\n",
 				    new_channel, new_channel->primary_channel);
 
-			/*XXX add it to percpu_list */
-
 			new_channel->state = HV_CHANNEL_OPEN_STATE;
-			if (channel->sc_creation_callback != NULL) {
-				channel->sc_creation_callback(new_channel);
-			}
+
+			/*
+			 * Bump up sub-channel count and notify anyone that is
+			 * interested in this sub-channel, after this sub-channel
+			 * is setup.
+			 */
+			mtx_lock(&channel->sc_lock);
+			channel->subchan_cnt++;
+			mtx_unlock(&channel->sc_lock);
+			wakeup(channel);
+
 			return;
 		}
 
-	    hv_vmbus_free_vmbus_channel(new_channel);
-	    return;
+		printf("VMBUS: duplicated primary channel%u\n",
+		    new_channel->offer_msg.child_rel_id);
+		hv_vmbus_free_vmbus_channel(new_channel);
+		return;
 	}
 
 	new_channel->state = HV_CHANNEL_OPEN_STATE;
@@ -283,10 +279,8 @@ vmbus_channel_process_offer(hv_vmbus_cha
 	ret = hv_vmbus_child_device_register(new_channel->device);
 	if (ret != 0) {
 		mtx_lock(&hv_vmbus_g_connection.channel_lock);
-		TAILQ_REMOVE(
-		    &hv_vmbus_g_connection.channel_anchor,
-		    new_channel,
-		    list_entry);
+		TAILQ_REMOVE(&hv_vmbus_g_connection.channel_anchor,
+		    new_channel, list_entry);
 		mtx_unlock(&hv_vmbus_g_connection.channel_lock);
 		hv_vmbus_free_vmbus_channel(new_channel);
 	}
@@ -793,3 +787,41 @@ vmbus_scan(void)
 		mtx_sleep(&vmbus_devcnt, &vmbus_chwait_lock, 0, "waitdev", 0);
 	mtx_unlock(&vmbus_chwait_lock);
 }
+
+struct hv_vmbus_channel **
+vmbus_get_subchan(struct hv_vmbus_channel *pri_chan, int subchan_cnt)
+{
+	struct hv_vmbus_channel **ret, *chan;
+	int i;
+
+	ret = malloc(subchan_cnt * sizeof(struct hv_vmbus_channel *), M_TEMP,
+	    M_WAITOK);
+
+	mtx_lock(&pri_chan->sc_lock);
+
+	while (pri_chan->subchan_cnt < subchan_cnt)
+		mtx_sleep(pri_chan, &pri_chan->sc_lock, 0, "subch", 0);
+
+	i = 0;
+	TAILQ_FOREACH(chan, &pri_chan->sc_list_anchor, sc_list_entry) {
+		/* TODO: refcnt chan */
+		ret[i] = chan;
+
+		++i;
+		if (i == subchan_cnt)
+			break;
+	}
+	KASSERT(i == subchan_cnt, ("invalid subchan count %d, should be %d",
+	    pri_chan->subchan_cnt, subchan_cnt));
+
+	mtx_unlock(&pri_chan->sc_lock);
+
+	return ret;
+}
+
+void
+vmbus_rel_subchan(struct hv_vmbus_channel **subchan, int subchan_cnt __unused)
+{
+
+	free(subchan, M_TEMP);
+}



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