From d1434ef661d62560566e54affe32871c634f08c0 Mon Sep 17 00:00:00 2001 From: sephe Date: Fri, 14 Oct 2016 04:53:52 +0000 Subject: [PATCH] MFC 306482,306483 306482 hyperv/hn: If synthetic parts are detached, don't touch them. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8065 306483 hyperv/hn: Fix detach and attach error handling. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8066 git-svn-id: svn://svn.freebsd.org/base/stable/10@307259 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/hyperv/netvsc/hv_net_vsc.h | 1 + sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 65 ++++++++++++++----- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index c2bad841b..c2c5d0a65 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -253,6 +253,7 @@ struct hn_softc { #define HN_FLAG_CHIM_CONNECTED 0x0002 #define HN_FLAG_HAS_RSSKEY 0x0004 #define HN_FLAG_HAS_RSSIND 0x0008 +#define HN_FLAG_SYNTH_ATTACHED 0x0010 #define HN_CAP_VLAN 0x0001 #define HN_CAP_MTU 0x0002 diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index be09d51d9..7fa829264 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -354,6 +354,7 @@ 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 int netvsc_detach(device_t dev); static void hn_nvs_handle_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt); @@ -407,6 +408,9 @@ hn_rss_reconfig(struct hn_softc *sc) HN_LOCK_ASSERT(sc); + if ((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0) + return (ENXIO); + /* * Disable RSS first. * @@ -752,27 +756,28 @@ netvsc_attach(device_t dev) return (0); failed: - /* TODO: reuse netvsc_detach() */ - hn_destroy_tx_data(sc); - if (ifp != NULL) - if_free(ifp); + if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) + hn_synth_detach(sc); + netvsc_detach(dev); return (error); } -/* - * TODO: Use this for error handling on attach path. - */ static int netvsc_detach(device_t dev) { struct hn_softc *sc = device_get_softc(dev); + struct ifnet *ifp = sc->hn_ifp; - /* TODO: ether_ifdetach */ - - HN_LOCK(sc); - /* TODO: hn_stop */ - hn_synth_detach(sc); - HN_UNLOCK(sc); + if (device_is_attached(dev)) { + HN_LOCK(sc); + if (sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) { + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + hn_stop(sc); + hn_synth_detach(sc); + } + HN_UNLOCK(sc); + ether_ifdetach(ifp); + } ifmedia_removeall(&sc->hn_media); hn_destroy_rx_data(sc); @@ -781,10 +786,12 @@ netvsc_detach(device_t dev) if (sc->hn_tx_taskq != hn_tx_taskq) taskqueue_free(sc->hn_tx_taskq); - vmbus_xact_ctx_destroy(sc->hn_xact); - HN_LOCK_DESTROY(sc); + if (sc->hn_xact != NULL) + vmbus_xact_ctx_destroy(sc->hn_xact); + + if_free(ifp); - /* TODO: if_free */ + HN_LOCK_DESTROY(sc); return (0); } @@ -1638,6 +1645,11 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) HN_LOCK(sc); + if ((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0) { + HN_UNLOCK(sc); + break; + } + if ((sc->hn_caps & HN_CAP_MTU) == 0) { /* Can't change MTU */ HN_UNLOCK(sc); @@ -1691,6 +1703,11 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCSIFFLAGS: HN_LOCK(sc); + if ((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0) { + HN_UNLOCK(sc); + break; + } + if (ifp->if_flags & IFF_UP) { /* * If only the state of the PROMISC flag changed, @@ -1802,6 +1819,9 @@ hn_stop(struct hn_softc *sc) HN_LOCK_ASSERT(sc); + KASSERT(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED, + ("synthetic parts were not attached")); + /* Clear RUNNING bit _before_ hn_suspend() */ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_RUNNING); hn_suspend(sc); @@ -1878,6 +1898,9 @@ hn_init_locked(struct hn_softc *sc) HN_LOCK_ASSERT(sc); + if ((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0) + return; + if (ifp->if_drv_flags & IFF_DRV_RUNNING) return; @@ -3397,6 +3420,9 @@ hn_synth_attach(struct hn_softc *sc, int mtu) int error, nsubch, nchan, i; uint32_t old_caps; + KASSERT((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0, + ("synthetic parts were attached")); + /* Save capabilities for later verification. */ old_caps = sc->hn_caps; sc->hn_caps = 0; @@ -3509,6 +3535,8 @@ hn_synth_attach(struct hn_softc *sc, int mtu) error = hn_attach_subchans(sc); if (error) return (error); + + sc->hn_flags |= HN_FLAG_SYNTH_ATTACHED; return (0); } @@ -3522,6 +3550,9 @@ hn_synth_detach(struct hn_softc *sc) { HN_LOCK_ASSERT(sc); + KASSERT(sc->hn_flags & HN_FLAG_SYNTH_ATTACHED, + ("synthetic parts were not attached")); + /* Detach the RNDIS first. */ hn_rndis_detach(sc); @@ -3530,6 +3561,8 @@ hn_synth_detach(struct hn_softc *sc) /* Detach all of the channels. */ hn_detach_allchans(sc); + + sc->hn_flags &= ~HN_FLAG_SYNTH_ATTACHED; } static void -- 2.45.0