summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv/netvsc
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2017-01-05 03:35:51 +0000
committersephe <sephe@FreeBSD.org>2017-01-05 03:35:51 +0000
commit3560073bb1bf15dae5f1dcff925e01dfa3a6417c (patch)
treec92e5ec8b5116911a0cb3b18f6a6f5cae72cb335 /sys/dev/hyperv/netvsc
parentd42d5fd1b299de728708c1ec2a8cdb475ce129e5 (diff)
downloadFreeBSD-src-3560073bb1bf15dae5f1dcff925e01dfa3a6417c.zip
FreeBSD-src-3560073bb1bf15dae5f1dcff925e01dfa3a6417c.tar.gz
MFC 308907
hyperv/hn: Fix WITNESS warnings And re-enable SIOCADDMULTI/SIOCDELMULTI, after WITNESS warning is fixed. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8489
Diffstat (limited to 'sys/dev/hyperv/netvsc')
-rw-r--r--sys/dev/hyperv/netvsc/hn_nvs.c5
-rw-r--r--sys/dev/hyperv/netvsc/hn_rndis.c5
-rw-r--r--sys/dev/hyperv/netvsc/if_hn.c46
-rw-r--r--sys/dev/hyperv/netvsc/if_hnvar.h14
4 files changed, 45 insertions, 25 deletions
diff --git a/sys/dev/hyperv/netvsc/hn_nvs.c b/sys/dev/hyperv/netvsc/hn_nvs.c
index 0d8c75c..37f0cee 100644
--- a/sys/dev/hyperv/netvsc/hn_nvs.c
+++ b/sys/dev/hyperv/netvsc/hn_nvs.c
@@ -109,7 +109,10 @@ hn_nvs_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact,
vmbus_xact_deactivate(xact);
return (NULL);
}
- hdr = vmbus_xact_wait(xact, &resplen);
+ if (HN_CAN_SLEEP(sc))
+ hdr = vmbus_xact_wait(xact, &resplen);
+ else
+ hdr = vmbus_xact_busywait(xact, &resplen);
/*
* Check this NVS response message.
diff --git a/sys/dev/hyperv/netvsc/hn_rndis.c b/sys/dev/hyperv/netvsc/hn_rndis.c
index e308e79..1c140f9 100644
--- a/sys/dev/hyperv/netvsc/hn_rndis.c
+++ b/sys/dev/hyperv/netvsc/hn_rndis.c
@@ -232,7 +232,10 @@ hn_rndis_xact_exec1(struct hn_softc *sc, struct vmbus_xact *xact, size_t reqlen,
if_printf(sc->hn_ifp, "RNDIS ctrl send failed: %d\n", error);
return (NULL);
}
- return (vmbus_xact_wait(xact, comp_len));
+ if (HN_CAN_SLEEP(sc))
+ return (vmbus_xact_wait(xact, comp_len));
+ else
+ return (vmbus_xact_busywait(xact, comp_len));
}
static const void *
diff --git a/sys/dev/hyperv/netvsc/if_hn.c b/sys/dev/hyperv/netvsc/if_hn.c
index d496228..be5aafa 100644
--- a/sys/dev/hyperv/netvsc/if_hn.c
+++ b/sys/dev/hyperv/netvsc/if_hn.c
@@ -149,7 +149,11 @@ __FBSDID("$FreeBSD$");
sx_init(&(sc)->hn_lock, device_get_nameunit((sc)->hn_dev))
#define HN_LOCK_DESTROY(sc) sx_destroy(&(sc)->hn_lock)
#define HN_LOCK_ASSERT(sc) sx_assert(&(sc)->hn_lock, SA_XLOCKED)
-#define HN_LOCK(sc) sx_xlock(&(sc)->hn_lock)
+#define HN_LOCK(sc) \
+do { \
+ while (sx_try_xlock(&(sc)->hn_lock) == 0) \
+ DELAY(1000); \
+} while (0)
#define HN_UNLOCK(sc) sx_xunlock(&(sc)->hn_lock)
#define HN_CSUM_IP_MASK (CSUM_IP | CSUM_IP_TCP | CSUM_IP_UDP)
@@ -667,18 +671,10 @@ hn_set_rxfilter(struct hn_softc *sc)
filter = NDIS_PACKET_TYPE_DIRECTED;
if (ifp->if_flags & IFF_BROADCAST)
filter |= NDIS_PACKET_TYPE_BROADCAST;
-#ifdef notyet
- /*
- * See the comment in SIOCADDMULTI/SIOCDELMULTI.
- */
/* TODO: support multicast list */
if ((ifp->if_flags & IFF_ALLMULTI) ||
!TAILQ_EMPTY(&ifp->if_multiaddrs))
filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
-#else
- /* Always enable ALLMULTI */
- filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
-#endif
}
if (sc->hn_rx_filter != filter) {
@@ -2338,10 +2334,18 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
if (ifp->if_flags & IFF_UP) {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ /*
+ * Caller meight hold mutex, e.g.
+ * bpf; use busy-wait for the RNDIS
+ * reply.
+ */
+ HN_NO_SLEEPING(sc);
hn_set_rxfilter(sc);
- else
+ HN_SLEEPING_OK(sc);
+ } else {
hn_init_locked(sc);
+ }
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
hn_stop(sc);
@@ -2402,27 +2406,23 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCADDMULTI:
case SIOCDELMULTI:
-#ifdef notyet
- /*
- * XXX
- * Multicast uses mutex, while RNDIS RX filter setting
- * sleeps. We workaround this by always enabling
- * ALLMULTI. ALLMULTI would actually always be on, even
- * if we supported the SIOCADDMULTI/SIOCDELMULTI, since
- * we don't support multicast address list configuration
- * for this driver.
- */
HN_LOCK(sc);
if ((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0) {
HN_UNLOCK(sc);
break;
}
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ /*
+ * Multicast uses mutex; use busy-wait for
+ * the RNDIS reply.
+ */
+ HN_NO_SLEEPING(sc);
hn_set_rxfilter(sc);
+ HN_SLEEPING_OK(sc);
+ }
HN_UNLOCK(sc);
-#endif
break;
case SIOCSIFMEDIA:
diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h
index acb924d..9b27d17 100644
--- a/sys/dev/hyperv/netvsc/if_hnvar.h
+++ b/sys/dev/hyperv/netvsc/if_hnvar.h
@@ -236,6 +236,20 @@ struct hn_softc {
#define HN_FLAG_HAS_RSSKEY 0x0004
#define HN_FLAG_HAS_RSSIND 0x0008
#define HN_FLAG_SYNTH_ATTACHED 0x0010
+#define HN_FLAG_NO_SLEEPING 0x0020
+
+#define HN_NO_SLEEPING(sc) \
+do { \
+ (sc)->hn_flags |= HN_FLAG_NO_SLEEPING; \
+} while (0)
+
+#define HN_SLEEPING_OK(sc) \
+do { \
+ (sc)->hn_flags &= ~HN_FLAG_NO_SLEEPING; \
+} while (0)
+
+#define HN_CAN_SLEEP(sc) \
+ (((sc)->hn_flags & HN_FLAG_NO_SLEEPING) == 0)
#define HN_CAP_VLAN 0x0001
#define HN_CAP_MTU 0x0002
OpenPOWER on IntegriCloud