Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 14 Jul 2016 07:31:43 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r302815 - head/sys/dev/hyperv/vmbus
Message-ID:  <201607140731.u6E7VhTs083913@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Thu Jul 14 07:31:43 2016
New Revision: 302815
URL: https://svnweb.freebsd.org/changeset/base/302815

Log:
  hyperv/vmbus: Only add primary channels to vmbus channel list
  
  - Make the vmbus_chan_add more straightforward.
  - Partially fix the hv_vmbus_release_unattached_channels().
  
  MFC after:	1 week
  Sponsored by:	Microsoft OSTC
  Differential Revision:	https://reviews.freebsd.org/D7109

Modified:
  head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c

Modified: head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Thu Jul 14 07:24:03 2016	(r302814)
+++ head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Thu Jul 14 07:31:43 2016	(r302815)
@@ -142,52 +142,55 @@ vmbus_chan_add(struct hv_vmbus_channel *
 		    sizeof(struct hyperv_guid)) == 0)
 			break;
 	}
-	if (prichan == NULL) {
-		/* Install the new primary channel */
-		TAILQ_INSERT_TAIL(&sc->vmbus_chlist, newchan, ch_link);
-	}
-	mtx_unlock(&sc->vmbus_chlist_lock);
-
-	if (prichan != NULL) {
-		if (newchan->ch_subidx == 0) {
+	if (VMBUS_CHAN_ISPRIMARY(newchan)) {
+		if (prichan == NULL) {
+			/* Install the new primary channel */
+			TAILQ_INSERT_TAIL(&sc->vmbus_chlist, newchan, ch_link);
+			mtx_unlock(&sc->vmbus_chlist_lock);
+			return 0;
+		} else {
+			mtx_unlock(&sc->vmbus_chlist_lock);
 			device_printf(sc->vmbus_dev, "duplicated primary "
 			    "chan%u\n", newchan->ch_id);
 			return EINVAL;
 		}
-
-		/*
-		 * This is a sub-channel.
-		 */
-		newchan->primary_channel = prichan;
-		newchan->ch_dev = prichan->ch_dev;
-		mtx_lock(&prichan->sc_lock);
-		TAILQ_INSERT_TAIL(&prichan->sc_list_anchor, newchan,
-		    sc_list_entry);
-		mtx_unlock(&prichan->sc_lock);
-
+	} else { /* Sub-channel */
+		if (prichan == NULL) {
+			mtx_unlock(&sc->vmbus_chlist_lock);
+			device_printf(sc->vmbus_dev, "no primary chan for "
+			    "chan%u\n", newchan->ch_id);
+			return EINVAL;
+		}
 		/*
-		 * Insert the new channel to the end of the global
-		 * channel list.
+		 * Found the primary channel for this sub-channel and
+		 * move on.
 		 *
-		 * NOTE:
-		 * The new sub-channel MUST be inserted AFTER it's
-		 * primary channel, so that the primary channel will
-		 * be found in the above loop for its baby siblings.
-		 */
-		mtx_lock(&sc->vmbus_chlist_lock);
-		TAILQ_INSERT_TAIL(&sc->vmbus_chlist, newchan, ch_link);
-		mtx_unlock(&sc->vmbus_chlist_lock);
-
-		/*
-		 * Bump up sub-channel count and notify anyone that is
-		 * interested in this sub-channel, after this sub-channel
-		 * is setup.
+		 * XXX refcnt prichan
 		 */
-		mtx_lock(&prichan->sc_lock);
-		prichan->subchan_cnt++;
-		mtx_unlock(&prichan->sc_lock);
-		wakeup(prichan);
 	}
+	mtx_unlock(&sc->vmbus_chlist_lock);
+
+	/*
+	 * This is a sub-channel; link it with the primary channel.
+	 */
+	KASSERT(!VMBUS_CHAN_ISPRIMARY(newchan),
+	    ("new channel is not sub-channel"));
+	KASSERT(prichan != NULL, ("no primary channel"));
+
+	newchan->primary_channel = prichan;
+	newchan->ch_dev = prichan->ch_dev;
+
+	mtx_lock(&prichan->sc_lock);
+	TAILQ_INSERT_TAIL(&prichan->sc_list_anchor, newchan, sc_list_entry);
+	/*
+	 * Bump up sub-channel count and notify anyone that is
+	 * interested in this sub-channel, after this sub-channel
+	 * is setup.
+	 */
+	prichan->subchan_cnt++;
+	mtx_unlock(&prichan->sc_lock);
+	wakeup(prichan);
+
 	return 0;
 }
 
@@ -370,10 +373,6 @@ vmbus_chan_detach_task(void *xchan, int 
 			}
 		}
 remove:
-		mtx_lock(&sc->vmbus_chlist_lock);
-		TAILQ_REMOVE(&sc->vmbus_chlist, chan, ch_link);
-		mtx_unlock(&sc->vmbus_chlist_lock);
-
 		mtx_lock(&pri_chan->sc_lock);
 		TAILQ_REMOVE(&pri_chan->sc_list_anchor, chan, sc_list_entry);
 		KASSERT(pri_chan->subchan_cnt > 0,
@@ -411,12 +410,10 @@ hv_vmbus_release_unattached_channels(str
 
 	while (!TAILQ_EMPTY(&sc->vmbus_chlist)) {
 	    channel = TAILQ_FIRST(&sc->vmbus_chlist);
+	    KASSERT(VMBUS_CHAN_ISPRIMARY(channel), ("not primary channel"));
 	    TAILQ_REMOVE(&sc->vmbus_chlist, channel, ch_link);
 
-	    if (VMBUS_CHAN_ISPRIMARY(channel)) {
-		/* Only primary channel owns the device */
-		hv_vmbus_child_device_unregister(channel);
-	    }
+	    hv_vmbus_child_device_unregister(channel);
 	    vmbus_chan_free(channel);
 	}
 	bzero(sc->vmbus_chmap,



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