diff options
author | Ryan Zezeski <rpz@joyent.com> | 2019-09-27 07:03:24 -0600 |
---|---|---|
committer | Ryan Zezeski <rpz@joyent.com> | 2019-10-01 11:36:51 -0600 |
commit | e4b201171637339e9c582457e461fb99e6a4cc56 (patch) | |
tree | 1264fe7c1d699b310390ac17a556581ce01cac69 | |
parent | 2ae9c4827fce220d14433c796b18141d48a597d9 (diff) | |
download | illumos-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.h | 1 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/viona/viona_main.c | 10 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/viona/viona_ring.c | 2 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/viona/viona_rx.c | 11 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/viona/viona_tx.c | 1 |
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); } |