summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Zezeski <rpz@joyent.com>2019-09-27 07:03:24 -0600
committerRyan Zezeski <rpz@joyent.com>2019-10-01 11:36:51 -0600
commite4b201171637339e9c582457e461fb99e6a4cc56 (patch)
tree1264fe7c1d699b310390ac17a556581ce01cac69
parent2ae9c4827fce220d14433c796b18141d48a597d9 (diff)
downloadillumos-joyent-e4b201171637339e9c582457e461fb99e6a4cc56.tar.gz
OS-8000 viona ring reset can race with Rx packets
Reviewed by: Mike Zeller <mike.zeller@joyent.com> Reviewed by: Patrick Mooney <pmooney@pfmooney.com> Reviewed by: Dan McDonald <danmcd@joyent.com> Approved by: Mike Zeller <mike.zeller@joyent.com>
-rw-r--r--usr/src/uts/i86pc/io/viona/viona_impl.h1
-rw-r--r--usr/src/uts/i86pc/io/viona/viona_main.c10
-rw-r--r--usr/src/uts/i86pc/io/viona/viona_ring.c2
-rw-r--r--usr/src/uts/i86pc/io/viona/viona_rx.c11
-rw-r--r--usr/src/uts/i86pc/io/viona/viona_tx.c1
5 files changed, 23 insertions, 2 deletions
diff --git a/usr/src/uts/i86pc/io/viona/viona_impl.h b/usr/src/uts/i86pc/io/viona/viona_impl.h
index ee31c4d4ce..5471b611a4 100644
--- a/usr/src/uts/i86pc/io/viona/viona_impl.h
+++ b/usr/src/uts/i86pc/io/viona/viona_impl.h
@@ -70,6 +70,7 @@ enum viona_ring_state {
VRS_SETUP = 0x1, /* addrs setup and starting worker thread */
VRS_INIT = 0x2, /* worker thread started & waiting to run */
VRS_RUN = 0x3, /* running work routine */
+ VRS_STOP = 0x4, /* worker is exiting */
};
enum viona_ring_state_flags {
VRSF_REQ_START = 0x1, /* start running from INIT state */
diff --git a/usr/src/uts/i86pc/io/viona/viona_main.c b/usr/src/uts/i86pc/io/viona/viona_main.c
index e3c9b90a57..d30f525586 100644
--- a/usr/src/uts/i86pc/io/viona/viona_main.c
+++ b/usr/src/uts/i86pc/io/viona/viona_main.c
@@ -133,8 +133,14 @@
* +-----------+
* | ^
* |---* ioctl(VNA_IOC_RING_RESET) issued |
- * | (or bhyve process begins exit) |
- * V |
+ * | (or bhyve process begins exit) ^
+ * |
+ * +-----------+ The worker thread associated with the ring is in the
+ * | VRS_STOP | process of exiting. All outstanding TX and RX
+ * +-----------+ requests are allowed to complete, but new requests
+ * | must be ignored.
+ * | ^
+ * | |
* +-------------------------------------------->+
*
*
diff --git a/usr/src/uts/i86pc/io/viona/viona_ring.c b/usr/src/uts/i86pc/io/viona/viona_ring.c
index e535bfaa1a..5ba6fad963 100644
--- a/usr/src/uts/i86pc/io/viona/viona_ring.c
+++ b/usr/src/uts/i86pc/io/viona/viona_ring.c
@@ -389,6 +389,8 @@ viona_worker(void *arg)
panic("unexpected ring: %p", (void *)ring);
}
+ VERIFY3U(ring->vr_state, ==, VRS_STOP);
+
cleanup:
if (ring->vr_txdesb != NULL) {
/*
diff --git a/usr/src/uts/i86pc/io/viona/viona_rx.c b/usr/src/uts/i86pc/io/viona/viona_rx.c
index b354b201cb..63beaba662 100644
--- a/usr/src/uts/i86pc/io/viona/viona_rx.c
+++ b/usr/src/uts/i86pc/io/viona/viona_rx.c
@@ -123,6 +123,17 @@ viona_worker_rx(viona_vring_t *ring, viona_link_t *link)
(void) cv_wait_sig(&ring->vr_cv, &ring->vr_lock);
} while (!VRING_NEED_BAIL(ring, p));
+ ring->vr_state = VRS_STOP;
+
+ /*
+ * The RX ring is stopping, before we start tearing it down it
+ * is imperative that we perform an RX barrier so that
+ * incoming packets are dropped at viona_rx_classified().
+ */
+ mutex_exit(&ring->vr_lock);
+ mac_rx_barrier(link->l_mch);
+ mutex_enter(&ring->vr_lock);
+
*ring->vr_used_flags &= ~VRING_USED_F_NO_NOTIFY;
}
diff --git a/usr/src/uts/i86pc/io/viona/viona_tx.c b/usr/src/uts/i86pc/io/viona/viona_tx.c
index 843435c67d..5dc645723c 100644
--- a/usr/src/uts/i86pc/io/viona/viona_tx.c
+++ b/usr/src/uts/i86pc/io/viona/viona_tx.c
@@ -283,6 +283,7 @@ viona_worker_tx(viona_vring_t *ring, viona_link_t *link)
ASSERT(MUTEX_HELD(&ring->vr_lock));
+ ring->vr_state = VRS_STOP;
viona_tx_wait_outstanding(ring);
}