Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci/ixgbe Fix race between ixgbe_msix_admin() and ix...
details: https://anonhg.NetBSD.org/src/rev/b2d7b0482e17
branches: trunk
changeset: 943655:b2d7b0482e17
user: knakahara <knakahara%NetBSD.org@localhost>
date: Mon Sep 07 09:14:53 2020 +0000
description:
Fix race between ixgbe_msix_admin() and ixgbe_handle_admin(), pointed out by ozaki-r@n.o.
The race is caused by the following.
CPU#A processes workqueue, CPU#B processes admin interrupt.
(0) one of CPUs already calls ixgbe_schedule_admin_tasklet()
such as ixgbe_handle_timer()
(1) CPU#A: read adapter->task_requests
(2) CPU#B: set adapter->task_requests
(3) CPU#B: read(and try to set) adapter->admin_pending
but adapter->admin_pending is set, so does not
call workqueue_enqueue()
(4) CPU#A: clear adapter->admin_pending
that is, the tasks set by (2) is not processed as missfire workqueue by (3).
diffstat:
sys/dev/pci/ixgbe/ixgbe.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diffs (31 lines):
diff -r ba635c85c93e -r b2d7b0482e17 sys/dev/pci/ixgbe/ixgbe.c
--- a/sys/dev/pci/ixgbe/ixgbe.c Mon Sep 07 09:14:47 2020 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.c Mon Sep 07 09:14:53 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.257 2020/09/07 05:50:58 msaitoh Exp $ */
+/* $NetBSD: ixgbe.c,v 1.258 2020/09/07 09:14:53 knakahara Exp $ */
/******************************************************************************
@@ -4805,6 +4805,13 @@
*/
IFNET_LOCK(ifp);
IXGBE_CORE_LOCK(adapter);
+ /*
+ * Clear the admin_pending flag before reading task_requests to avoid
+ * missfiring workqueue though setting task_request.
+ * Hmm, ixgbe_schedule_admin_tasklet() can extra-fire though
+ * task_requests are done by prior workqueue, but it is harmless.
+ */
+ atomic_store_relaxed(&adapter->admin_pending, 0);
while ((req =
(adapter->task_requests & ~IXGBE_REQUEST_TASK_NEED_ACKINTR))
!= 0) {
@@ -4841,7 +4848,6 @@
}
#endif
}
- atomic_store_relaxed(&adapter->admin_pending, 0);
if ((adapter->task_requests & IXGBE_REQUEST_TASK_NEED_ACKINTR) != 0) {
atomic_and_32(&adapter->task_requests,
~IXGBE_REQUEST_TASK_NEED_ACKINTR);
Home |
Main Index |
Thread Index |
Old Index