Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Nov 2016 05:46:00 +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: r309229 - head/sys/dev/hyperv/netvsc
Message-ID:  <201611280546.uAS5k0nT097641@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Mon Nov 28 05:46:00 2016
New Revision: 309229
URL: https://svnweb.freebsd.org/changeset/base/309229

Log:
  hyperv/hn: Fix attach error handling
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D8620

Modified:
  head/sys/dev/hyperv/netvsc/hn_nvs.c
  head/sys/dev/hyperv/netvsc/hn_rndis.c
  head/sys/dev/hyperv/netvsc/if_hn.c

Modified: head/sys/dev/hyperv/netvsc/hn_nvs.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hn_nvs.c	Mon Nov 28 05:31:36 2016	(r309228)
+++ head/sys/dev/hyperv/netvsc/hn_nvs.c	Mon Nov 28 05:46:00 2016	(r309229)
@@ -273,8 +273,14 @@ hn_nvs_conn_chim(struct hn_softc *sc)
 		goto cleanup;
 	}
 	if (sectsz == 0) {
+		/*
+		 * Can't use chimney sending buffer; done!
+		 */
 		if_printf(sc->hn_ifp, "zero chimney sending buffer "
 		    "section size\n");
+		sc->hn_chim_szmax = 0;
+		sc->hn_chim_cnt = 0;
+		sc->hn_flags |= HN_FLAG_CHIM_CONNECTED;
 		return (0);
 	}
 
@@ -431,6 +437,7 @@ hn_nvs_disconn_chim(struct hn_softc *sc)
 	if (sc->hn_chim_bmap != NULL) {
 		free(sc->hn_chim_bmap, M_DEVBUF);
 		sc->hn_chim_bmap = NULL;
+		sc->hn_chim_bmap_cnt = 0;
 	}
 }
 
@@ -620,8 +627,10 @@ hn_nvs_attach(struct hn_softc *sc, int m
 	 * Connect chimney sending buffer.
 	 */
 	error = hn_nvs_conn_chim(sc);
-	if (error)
+	if (error) {
+		hn_nvs_disconn_rxbuf(sc);
 		return (error);
+	}
 	return (0);
 }
 

Modified: head/sys/dev/hyperv/netvsc/hn_rndis.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hn_rndis.c	Mon Nov 28 05:31:36 2016	(r309228)
+++ head/sys/dev/hyperv/netvsc/hn_rndis.c	Mon Nov 28 05:46:00 2016	(r309229)
@@ -979,7 +979,6 @@ hn_rndis_attach(struct hn_softc *sc, int
 
 	/*
 	 * Configure NDIS offload settings.
-	 * XXX no offloading, if error happened?
 	 */
 	hn_rndis_conf_offload(sc, mtu);
 	return (0);

Modified: head/sys/dev/hyperv/netvsc/if_hn.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hn.c	Mon Nov 28 05:31:36 2016	(r309228)
+++ head/sys/dev/hyperv/netvsc/if_hn.c	Mon Nov 28 05:46:00 2016	(r309229)
@@ -4215,11 +4215,14 @@ hn_chan_attach(struct hn_softc *sc, stru
 	cbr.cbr_rxsz = HN_RXBR_SIZE;
 	error = vmbus_chan_open_br(chan, &cbr, NULL, 0, hn_chan_callback, rxr);
 	if (error) {
-		if_printf(sc->hn_ifp, "open chan%u failed: %d\n",
-		    vmbus_chan_id(chan), error);
-		rxr->hn_rx_flags &= ~HN_RX_FLAG_ATTACHED;
-		if (txr != NULL)
-			txr->hn_tx_flags &= ~HN_TX_FLAG_ATTACHED;
+		if (error == EISCONN) {
+			if_printf(sc->hn_ifp, "bufring is connected after "
+			    "chan%u open failure\n", vmbus_chan_id(chan));
+			rxr->hn_rx_flags |= HN_RX_FLAG_BR_REF;
+		} else {
+			if_printf(sc->hn_ifp, "open chan%u failed: %d\n",
+			    vmbus_chan_id(chan), error);
+		}
 	}
 	return (error);
 }
@@ -4276,15 +4279,18 @@ hn_attach_subchans(struct hn_softc *sc)
 	int subchan_cnt = sc->hn_rx_ring_inuse - 1;
 	int i, error = 0;
 
-	if (subchan_cnt == 0)
-		return (0);
+	KASSERT(subchan_cnt > 0, ("no sub-channels"));
 
 	/* Attach the sub-channels. */
 	subchans = vmbus_subchan_get(sc->hn_prichan, subchan_cnt);
 	for (i = 0; i < subchan_cnt; ++i) {
-		error = hn_chan_attach(sc, subchans[i]);
-		if (error)
-			break;
+		int error1;
+
+		error1 = hn_chan_attach(sc, subchans[i]);
+		if (error1) {
+			error = error1;
+			/* Move on; all channels will be detached later. */
+		}
 	}
 	vmbus_subchan_rel(subchans, subchan_cnt);
 
@@ -4416,9 +4422,12 @@ hn_synth_attachable(const struct hn_soft
 static int
 hn_synth_attach(struct hn_softc *sc, int mtu)
 {
+#define ATTACHED_NVS		0x0002
+#define ATTACHED_RNDIS		0x0004
+
 	struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
 	int error, nsubch, nchan, i;
-	uint32_t old_caps;
+	uint32_t old_caps, attached = 0;
 
 	KASSERT((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0,
 	    ("synthetic parts were attached"));
@@ -4439,21 +4448,23 @@ hn_synth_attach(struct hn_softc *sc, int
 	 */
 	error = hn_chan_attach(sc, sc->hn_prichan);
 	if (error)
-		return (error);
+		goto failed;
 
 	/*
 	 * Attach NVS.
 	 */
 	error = hn_nvs_attach(sc, mtu);
 	if (error)
-		return (error);
+		goto failed;
+	attached |= ATTACHED_NVS;
 
 	/*
 	 * Attach RNDIS _after_ NVS is attached.
 	 */
 	error = hn_rndis_attach(sc, mtu);
 	if (error)
-		return (error);
+		goto failed;
+	attached |= ATTACHED_RNDIS;
 
 	/*
 	 * Make sure capabilities are not changed.
@@ -4461,9 +4472,8 @@ hn_synth_attach(struct hn_softc *sc, int
 	if (device_is_attached(sc->hn_dev) && old_caps != sc->hn_caps) {
 		if_printf(sc->hn_ifp, "caps mismatch old 0x%08x, new 0x%08x\n",
 		    old_caps, sc->hn_caps);
-		/* Restore old capabilities and abort. */
-		sc->hn_caps = old_caps;
-		return ENXIO;
+		error = ENXIO;
+		goto failed;
 	}
 
 	/*
@@ -4476,19 +4486,32 @@ hn_synth_attach(struct hn_softc *sc, int
 	nsubch = sc->hn_rx_ring_cnt - 1;
 	error = hn_synth_alloc_subchans(sc, &nsubch);
 	if (error)
-		return (error);
+		goto failed;
+	/* NOTE: _Full_ synthetic parts detach is required now. */
+	sc->hn_flags |= HN_FLAG_SYNTH_ATTACHED;
 
+	/*
+	 * Set the # of TX/RX rings that could be used according to
+	 * the # of channels that NVS offered.
+	 */
 	nchan = nsubch + 1;
+	hn_set_ring_inuse(sc, nchan);
 	if (nchan == 1) {
 		/* Only the primary channel can be used; done */
 		goto back;
 	}
 
 	/*
-	 * Configure RSS key and indirect table _after_ all sub-channels
-	 * are allocated.
+	 * Attach the sub-channels.
 	 */
+	error = hn_attach_subchans(sc);
+	if (error)
+		goto failed;
 
+	/*
+	 * Configure RSS key and indirect table _after_ all sub-channels
+	 * are attached.
+	 */
 	if ((sc->hn_flags & HN_FLAG_HAS_RSSKEY) == 0) {
 		/*
 		 * RSS key is not set yet; set it to the default RSS key.
@@ -4521,34 +4544,31 @@ hn_synth_attach(struct hn_softc *sc, int
 	}
 
 	error = hn_rndis_conf_rss(sc, NDIS_RSS_FLAG_NONE);
-	if (error) {
-		/*
-		 * Failed to configure RSS key or indirect table; only
-		 * the primary channel can be used.
-		 */
-		nchan = 1;
-	}
-back:
-	/*
-	 * Set the # of TX/RX rings that could be used according to
-	 * the # of channels that NVS offered.
-	 */
-	hn_set_ring_inuse(sc, nchan);
-
-	/*
-	 * Attach the sub-channels, if any.
-	 */
-	error = hn_attach_subchans(sc);
 	if (error)
-		return (error);
-
+		goto failed;
+back:
 	/*
 	 * Fixup transmission aggregation setup.
 	 */
 	hn_set_txagg(sc);
-
-	sc->hn_flags |= HN_FLAG_SYNTH_ATTACHED;
 	return (0);
+
+failed:
+	if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) {
+		hn_synth_detach(sc);
+	} else {
+		if (attached & ATTACHED_RNDIS)
+			hn_rndis_detach(sc);
+		if (attached & ATTACHED_NVS)
+			hn_nvs_detach(sc);
+		hn_chan_detach(sc, sc->hn_prichan);
+		/* Restore old capabilities. */
+		sc->hn_caps = old_caps;
+	}
+	return (error);
+
+#undef ATTACHED_RNDIS
+#undef ATTACHED_NVS
 }
 
 /*
@@ -4559,7 +4579,6 @@ back:
 static void
 hn_synth_detach(struct hn_softc *sc)
 {
-	HN_LOCK_ASSERT(sc);
 
 	KASSERT(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED,
 	    ("synthetic parts were not attached"));



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