Module Name:    src
Committed By:   knakahara
Date:           Mon Sep  7 09:14:54 UTC 2020

Modified Files:
        src/sys/dev/pci/ixgbe: ixgbe.c

Log Message:
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).


To generate a diff of this commit:
cvs rdiff -u -r1.257 -r1.258 src/sys/dev/pci/ixgbe/ixgbe.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/ixgbe/ixgbe.c
diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.257 src/sys/dev/pci/ixgbe/ixgbe.c:1.258
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.257	Mon Sep  7 05:50:58 2020
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Mon Sep  7 09:14:53 2020
@@ -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 @@ ixgbe_handle_admin(struct work *wk, void
 	 */
 	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 @@ ixgbe_handle_admin(struct work *wk, void
 		}
 #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);

Reply via email to