Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160704974
D7858.id20290.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D7858.id20290.diff
View Options
Index: head/sys/dev/hyperv/netvsc/hv_net_vsc.c
===================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.c
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.c
@@ -582,11 +582,6 @@
{
hv_nv_disconnect_from_vsp(sc);
-
- /* Now, we can close the channel safely */
-
- vmbus_chan_close(sc->hn_prichan);
-
return (0);
}
Index: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
===================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -345,8 +345,11 @@
static void hn_destroy_rx_data(struct hn_softc *sc);
static void hn_set_chim_size(struct hn_softc *, int);
static int hn_chan_attach(struct hn_softc *, struct vmbus_channel *);
+static void hn_chan_detach(struct hn_softc *, struct vmbus_channel *);
static int hn_attach_subchans(struct hn_softc *);
+static void hn_detach_allchans(struct hn_softc *);
static void hn_chan_callback(struct vmbus_channel *chan, void *xrxr);
+static void hn_set_ring_inuse(struct hn_softc *, int);
static void hn_nvs_handle_notify(struct hn_softc *sc,
const struct vmbus_chanpkt_hdr *pkt);
@@ -520,7 +523,7 @@
goto failed;
/*
- * Associate the first TX/RX ring w/ the primary channel.
+ * Attach the primary channel before attaching NVS and RNDIS.
*/
error = hn_chan_attach(sc, sc->hn_prichan);
if (error)
@@ -576,17 +579,14 @@
* Set the # of TX/RX rings that could be used according to
* the # of channels that host offered.
*/
- if (sc->hn_tx_ring_inuse > ring_cnt)
- sc->hn_tx_ring_inuse = ring_cnt;
- sc->hn_rx_ring_inuse = ring_cnt;
- device_printf(dev, "%d TX ring, %d RX ring\n",
- sc->hn_tx_ring_inuse, sc->hn_rx_ring_inuse);
+ hn_set_ring_inuse(sc, ring_cnt);
- if (sc->hn_rx_ring_inuse > 1) {
- error = hn_attach_subchans(sc);
- if (error)
- goto failed;
- }
+ /*
+ * Attach the sub-channels, if any.
+ */
+ error = hn_attach_subchans(sc);
+ if (error)
+ goto failed;
#if __FreeBSD_version >= 1100099
if (sc->hn_rx_ring_inuse > 1) {
@@ -669,6 +669,7 @@
*/
hv_rf_on_device_remove(sc);
+ hn_detach_allchans(sc);
hn_stop_tx_tasks(sc);
@@ -1580,14 +1581,17 @@
break;
}
- /* Wait for subchannels to be destroyed */
- vmbus_subchan_drain(sc->hn_prichan);
+ /*
+ * Detach all of the channels.
+ */
+ hn_detach_allchans(sc);
- sc->hn_rx_ring[0].hn_rx_flags &= ~HN_RX_FLAG_ATTACHED;
- sc->hn_tx_ring[0].hn_tx_flags &= ~HN_TX_FLAG_ATTACHED;
- hn_chan_attach(sc, sc->hn_prichan); /* XXX check error */
+ /*
+ * Attach the primary channel before attaching NVS and RNDIS.
+ */
+ hn_chan_attach(sc, sc->hn_prichan);
- ring_cnt = sc->hn_rx_ring_inuse;
+ ring_cnt = sc->hn_rx_ring_cnt;
error = hv_rf_on_device_add(sc, &ring_cnt, ifr->ifr_mtu);
if (error) {
NV_LOCK(sc);
@@ -1595,27 +1599,17 @@
NV_UNLOCK(sc);
break;
}
- /* # of channels can _not_ be changed */
- KASSERT(sc->hn_rx_ring_inuse == ring_cnt,
- ("RX ring count %d and channel count %u mismatch",
- sc->hn_rx_ring_cnt, ring_cnt));
- if (sc->hn_rx_ring_inuse > 1) {
- int r;
- /*
- * Skip the rings on primary channel; they are
- * handled by the hv_rf_on_device_add() above.
- */
- for (r = 1; r < sc->hn_rx_ring_cnt; ++r) {
- sc->hn_rx_ring[r].hn_rx_flags &=
- ~HN_RX_FLAG_ATTACHED;
- }
- for (r = 1; r < sc->hn_tx_ring_cnt; ++r) {
- sc->hn_tx_ring[r].hn_tx_flags &=
- ~HN_TX_FLAG_ATTACHED;
- }
- hn_attach_subchans(sc); /* XXX check error */
- }
+ /*
+ * Set the # of TX/RX rings that could be used according to
+ * the # of channels that host offered.
+ */
+ hn_set_ring_inuse(sc, ring_cnt);
+
+ /*
+ * Attach the sub-channels, if any.
+ */
+ hn_attach_subchans(sc); /* XXX check error */
if (sc->hn_tx_ring[0].hn_chim_size > sc->hn_chim_szmax)
hn_set_chim_size(sc, sc->hn_chim_szmax);
@@ -3022,6 +3016,42 @@
return (error);
}
+static void
+hn_chan_detach(struct hn_softc *sc, struct vmbus_channel *chan)
+{
+ struct hn_rx_ring *rxr;
+ int idx;
+
+ idx = vmbus_chan_subidx(chan);
+
+ /*
+ * Link this channel to RX/TX ring.
+ */
+ KASSERT(idx >= 0 && idx < sc->hn_rx_ring_inuse,
+ ("invalid channel index %d, should > 0 && < %d",
+ idx, sc->hn_rx_ring_inuse));
+ rxr = &sc->hn_rx_ring[idx];
+ KASSERT((rxr->hn_rx_flags & HN_RX_FLAG_ATTACHED),
+ ("RX ring %d is not attached", idx));
+ rxr->hn_rx_flags &= ~HN_RX_FLAG_ATTACHED;
+
+ if (idx < sc->hn_tx_ring_inuse) {
+ struct hn_tx_ring *txr = &sc->hn_tx_ring[idx];
+
+ KASSERT((txr->hn_tx_flags & HN_TX_FLAG_ATTACHED),
+ ("TX ring %d is not attached attached", idx));
+ txr->hn_tx_flags &= ~HN_TX_FLAG_ATTACHED;
+ }
+
+ /*
+ * Close this channel.
+ *
+ * NOTE:
+ * Channel closing does _not_ destroy the target channel.
+ */
+ vmbus_chan_close(chan);
+}
+
static int
hn_attach_subchans(struct hn_softc *sc)
{
@@ -3029,6 +3059,9 @@
int subchan_cnt = sc->hn_rx_ring_inuse - 1;
int i, error = 0;
+ if (subchan_cnt == 0)
+ return (0);
+
/* Wait for sub-channels setup to complete. */
subchans = vmbus_subchan_get(sc->hn_prichan, subchan_cnt);
@@ -3054,6 +3087,64 @@
}
static void
+hn_detach_allchans(struct hn_softc *sc)
+{
+ struct vmbus_channel **subchans;
+ int subchan_cnt = sc->hn_rx_ring_inuse - 1;
+ int i;
+
+ if (subchan_cnt == 0)
+ goto back;
+
+ /* Detach the sub-channels. */
+ subchans = vmbus_subchan_get(sc->hn_prichan, subchan_cnt);
+ for (i = 0; i < subchan_cnt; ++i)
+ hn_chan_detach(sc, subchans[i]);
+ vmbus_subchan_rel(subchans, subchan_cnt);
+
+back:
+ /*
+ * Detach the primary channel, _after_ all sub-channels
+ * are detached.
+ */
+ hn_chan_detach(sc, sc->hn_prichan);
+
+ /* Wait for sub-channels to be destroyed, if any. */
+ vmbus_subchan_drain(sc->hn_prichan);
+
+#ifdef INVARIANTS
+ for (i = 0; i < sc->hn_rx_ring_cnt; ++i) {
+ KASSERT((sc->hn_rx_ring[i].hn_rx_flags &
+ HN_RX_FLAG_ATTACHED) == 0,
+ ("%dth RX ring is still attached", i));
+ }
+ for (i = 0; i < sc->hn_tx_ring_cnt; ++i) {
+ KASSERT((sc->hn_tx_ring[i].hn_tx_flags &
+ HN_TX_FLAG_ATTACHED) == 0,
+ ("%dth TX ring is still attached", i));
+ }
+#endif
+}
+
+static void
+hn_set_ring_inuse(struct hn_softc *sc, int ring_cnt)
+{
+ KASSERT(ring_cnt > 0 && ring_cnt <= sc->hn_rx_ring_cnt,
+ ("invalid ring count %d", ring_cnt));
+
+ if (sc->hn_tx_ring_cnt > ring_cnt)
+ sc->hn_tx_ring_inuse = ring_cnt;
+ else
+ sc->hn_tx_ring_inuse = sc->hn_tx_ring_cnt;
+ sc->hn_rx_ring_inuse = ring_cnt;
+
+ if (bootverbose) {
+ if_printf(sc->hn_ifp, "%d TX ring, %d RX ring\n",
+ sc->hn_tx_ring_inuse, sc->hn_rx_ring_inuse);
+ }
+}
+
+static void
hn_nvs_handle_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt)
{
const struct hn_nvs_hdr *hdr;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jun 28, 12:02 AM (9 m, 3 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34419817
Default Alt Text
D7858.id20290.diff (6 KB)
Attached To
Mode
D7858: hyperv/hn: Reorganize channel attach/detach code.
Attached
Detach File
Event Timeline
Log In to Comment