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"));
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to