svn commit: r307608 - stable/11/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Wed Oct 19 06:57:20 UTC 2016
Author: sephe
Date: Wed Oct 19 06:57:18 2016
New Revision: 307608
URL: https://svnweb.freebsd.org/changeset/base/307608
Log:
MFC 306431,306432
306431
hyperv/hn: Move TX tasks' draining into hn_suspend().
This prepares to consolidate hn_stop() and netvsc_detach().
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8055
306432
hyperv/hn: Consolidate hn_init() and hn_stop()
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8056
Modified:
stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Wed Oct 19 06:45:53 2016 (r307607)
+++ stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Wed Oct 19 06:57:18 2016 (r307608)
@@ -334,7 +334,6 @@ static void hn_fixup_tx_data(struct hn_s
static void hn_destroy_tx_data(struct hn_softc *);
static void hn_start_taskfunc(void *, int);
static void hn_start_txeof_taskfunc(void *, int);
-static void hn_stop_tx_tasks(struct hn_softc *);
static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **);
static int hn_create_rx_data(struct hn_softc *sc, int);
static void hn_destroy_rx_data(struct hn_softc *sc);
@@ -350,6 +349,8 @@ static void hn_synth_detach(struct hn_so
static bool hn_tx_ring_pending(struct hn_tx_ring *);
static void hn_suspend(struct hn_softc *);
static void hn_resume(struct hn_softc *);
+static void hn_rx_drain(struct vmbus_channel *);
+static void hn_tx_resume(struct hn_softc *, int);
static void hn_tx_ring_qflush(struct hn_tx_ring *);
static void hn_nvs_handle_notify(struct hn_softc *sc,
@@ -757,8 +758,6 @@ netvsc_detach(device_t dev)
hn_synth_detach(sc);
HN_UNLOCK(sc);
- hn_stop_tx_tasks(sc);
-
ifmedia_removeall(&sc->hn_media);
hn_destroy_rx_data(sc);
hn_destroy_tx_data(sc);
@@ -1776,25 +1775,19 @@ hn_ioctl(struct ifnet *ifp, u_long cmd,
static void
hn_stop(struct hn_softc *sc)
{
- struct ifnet *ifp;
+ struct ifnet *ifp = sc->hn_ifp;
int i;
HN_LOCK_ASSERT(sc);
- ifp = sc->hn_ifp;
-
- if (bootverbose)
- printf(" Closing Device ...\n");
+ /* Clear RUNNING bit _before_ hn_suspend() */
+ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_RUNNING);
+ hn_suspend(sc);
- atomic_clear_int(&ifp->if_drv_flags,
- (IFF_DRV_RUNNING | IFF_DRV_OACTIVE));
+ /* Clear OACTIVE bit. */
+ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
for (i = 0; i < sc->hn_tx_ring_inuse; ++i)
sc->hn_tx_ring[i].hn_oactive = 0;
-
- if_link_state_change(ifp, LINK_STATE_DOWN);
-
- /* Disable RX by clearing RX filter. */
- hn_rndis_set_rxfilter(sc, 0);
}
/*
@@ -1858,27 +1851,29 @@ do_sched:
static void
hn_init_locked(struct hn_softc *sc)
{
- struct ifnet *ifp;
- int ret, i;
+ struct ifnet *ifp = sc->hn_ifp;
+ int i;
HN_LOCK_ASSERT(sc);
- ifp = sc->hn_ifp;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
return;
- }
/* TODO: add hn_rx_filter */
- ret = hn_rndis_set_rxfilter(sc, NDIS_PACKET_TYPE_PROMISCUOUS);
- if (ret != 0)
- return;
+ hn_rndis_set_rxfilter(sc, NDIS_PACKET_TYPE_PROMISCUOUS);
+ /* Clear OACTIVE bit. */
atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
for (i = 0; i < sc->hn_tx_ring_inuse; ++i)
sc->hn_tx_ring[i].hn_oactive = 0;
+ /* Clear TX 'suspended' bit. */
+ hn_tx_resume(sc, sc->hn_tx_ring_inuse);
+
+ /* Everything is ready; unleash! */
atomic_set_int(&ifp->if_drv_flags, IFF_DRV_RUNNING);
+
+ /* TODO: check RNDIS link status. */
if_link_state_change(ifp, LINK_STATE_UP);
}
@@ -2971,19 +2966,6 @@ hn_start_txeof_taskfunc(void *xtxr, int
mtx_unlock(&txr->hn_tx_lock);
}
-static void
-hn_stop_tx_tasks(struct hn_softc *sc)
-{
- int i;
-
- for (i = 0; i < sc->hn_tx_ring_inuse; ++i) {
- struct hn_tx_ring *txr = &sc->hn_tx_ring[i];
-
- taskqueue_drain(txr->hn_tx_taskq, &txr->hn_tx_task);
- taskqueue_drain(txr->hn_tx_taskq, &txr->hn_txeof_task);
- }
-}
-
static int
hn_xmit(struct hn_tx_ring *txr, int len)
{
@@ -3571,6 +3553,9 @@ hn_suspend(struct hn_softc *sc)
/* Wait for all pending sends to finish. */
while (hn_tx_ring_pending(txr))
pause("hnwtx", 1 /* 1 tick */);
+
+ taskqueue_drain(txr->hn_tx_taskq, &txr->hn_tx_task);
+ taskqueue_drain(txr->hn_tx_taskq, &txr->hn_txeof_task);
}
/*
@@ -3601,9 +3586,25 @@ hn_suspend(struct hn_softc *sc)
}
static void
+hn_tx_resume(struct hn_softc *sc, int tx_ring_cnt)
+{
+ int i;
+
+ KASSERT(tx_ring_cnt <= sc->hn_tx_ring_cnt,
+ ("invalid TX ring count %d", tx_ring_cnt));
+
+ for (i = 0; i < tx_ring_cnt; ++i) {
+ struct hn_tx_ring *txr = &sc->hn_tx_ring[i];
+
+ mtx_lock(&txr->hn_tx_lock);
+ txr->hn_suspended = 0;
+ mtx_unlock(&txr->hn_tx_lock);
+ }
+}
+
+static void
hn_resume(struct hn_softc *sc)
{
- struct hn_tx_ring *txr;
int i;
HN_LOCK_ASSERT(sc);
@@ -3618,13 +3619,7 @@ hn_resume(struct hn_softc *sc)
* Make sure to clear suspend status on "all" TX rings,
* since hn_tx_ring_inuse can be changed after hn_suspend().
*/
- for (i = 0; i < sc->hn_tx_ring_cnt; ++i) {
- txr = &sc->hn_tx_ring[i];
-
- mtx_lock(&txr->hn_tx_lock);
- txr->hn_suspended = 0;
- mtx_unlock(&txr->hn_tx_lock);
- }
+ hn_tx_resume(sc, sc->hn_tx_ring_cnt);
if (!hn_use_if_start) {
/*
@@ -3639,7 +3634,8 @@ hn_resume(struct hn_softc *sc)
* Kick start TX.
*/
for (i = 0; i < sc->hn_tx_ring_inuse; ++i) {
- txr = &sc->hn_tx_ring[i];
+ struct hn_tx_ring *txr = &sc->hn_tx_ring[i];
+
/*
* Use txeof task, so that any pending oactive can be
* cleared properly.
More information about the svn-src-stable-11
mailing list