Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Fix locking against myself reported by rin@n.o.



details:   https://anonhg.NetBSD.org/src/rev/3363f3048e0c
branches:  trunk
changeset: 984979:3363f3048e0c
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Tue Aug 03 01:08:18 2021 +0000

description:
Fix locking against myself reported by rin@n.o.

In some machine, INTx interrupts occurs for some reason while holding
txq_lock in softint context.
e.g. https://dmesgd.nycbug.org/index.cgi?do=view&id=6139

The panic message is the following.
====================
[  50.1699480] panic: LOCKDEBUG: Mutex error: mutex_vector_enter,467: locking against myself
[  50.1800188] cpu0: Begin traceback...
[  50.1800188] 0xc7a29ac4: netbsd:db_panic+0xc
[  50.1900018] 0xc7a29adc: netbsd:vpanic+0x120
[  50.1999533] 0xc7a29af4: netbsd:aprint_debug
[  50.1999533] 0xc7a29b34: netbsd:lockdebug_abort1+0x18c
[  50.2099719] 0xc7a29b74: netbsd:lockdebug_wantlock+0x1e8
[  50.2199525] 0xc7a29bb4: netbsd:mutex_enter+0x288
[  50.2299642] 0xc7a29be4: netbsd:wm_intr_legacy+0x9c
[  50.2299642] 0xc7a29c2c: netbsd:i80321_intr_dispatch+0x138
[  50.2399631] 0xc7a29de4: netbsd:irq_entry+0x98
[  50.2499452] 0xc7a29e24: netbsd:entropy_enter+0x88
[  50.2599996] 0xc7a29e6c: netbsd:rnd_add_data_1+0x50
[  50.2699565] 0xc7a29ebc: netbsd:rnd_add_data+0x10c
[  50.2699565] 0xc7a29ed4: netbsd:rnd_add_uint32+0x28
[  50.2799524] 0xc7a29f1c: netbsd:wm_txeof+0x2c0
[  50.2899527] 0xc7a29f5c: netbsd:wm_handle_queue+0x44
[  50.3000257] 0xc7a29fac: netbsd:softint_thread+0x130
[  50.3100119] cpu0: End traceback...
====================

To fix this panic, stop wm(4) interrupts before calling softint.
This behavior is similar to MSI-X polling mode.

Reviewed by msaitoh@n.o, tested by rin@n.o, thanks.

diffstat:

 sys/dev/pci/if_wm.c |  34 +++++++++++++++++++++++++++++-----
 1 files changed, 29 insertions(+), 5 deletions(-)

diffs (98 lines):

diff -r a32e65526d2a -r 3363f3048e0c sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Mon Aug 02 23:49:26 2021 +0000
+++ b/sys/dev/pci/if_wm.c       Tue Aug 03 01:08:18 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.705 2021/06/16 00:21:18 riastradh Exp $    */
+/*     $NetBSD: if_wm.c,v 1.706 2021/08/03 01:08:18 knakahara Exp $    */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -82,7 +82,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.705 2021/06/16 00:21:18 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.706 2021/08/03 01:08:18 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -9774,6 +9774,20 @@
                softint_schedule(wmq->wmq_si);
 }
 
+static inline void
+wm_legacy_intr_disable(struct wm_softc *sc)
+{
+
+       CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
+}
+
+static inline void
+wm_legacy_intr_enable(struct wm_softc *sc)
+{
+
+       CSR_WRITE(sc, WMREG_IMS, sc->sc_icr);
+}
+
 /*
  * wm_intr_legacy:
  *
@@ -9788,6 +9802,7 @@
        struct wm_rxqueue *rxq = &wmq->wmq_rxq;
        uint32_t icr, rndval = 0;
        int handled = 0;
+       bool more = false;
 
        while (1 /* CONSTCOND */) {
                icr = CSR_READ(sc, WMREG_ICR);
@@ -9822,7 +9837,7 @@
                 * as if_percpuq_enqueue() just call softint_schedule().
                 * So, we can call wm_rxeof() in interrupt context.
                 */
-               wm_rxeof(rxq, UINT_MAX);
+               more = wm_rxeof(rxq, UINT_MAX);
 
                mutex_exit(rxq->rxq_lock);
                mutex_enter(txq->txq_lock);
@@ -9840,7 +9855,7 @@
                        WM_Q_EVCNT_INCR(txq, txdw);
                }
 #endif
-               wm_txeof(txq, UINT_MAX);
+               more |= wm_txeof(txq, UINT_MAX);
 
                mutex_exit(txq->txq_lock);
                WM_CORE_LOCK(sc);
@@ -9869,8 +9884,9 @@
 
        rnd_add_uint32(&sc->rnd_source, rndval);
 
-       if (handled) {
+       if (more) {
                /* Try to get more packets going. */
+               wm_legacy_intr_disable(sc);
                wmq->wmq_txrx_use_workqueue = sc->sc_txrx_use_workqueue;
                wm_sched_handle_queue(sc, wmq);
        }
@@ -9883,6 +9899,10 @@
 {
        struct wm_softc *sc = wmq->wmq_txq.txq_sc;
 
+       if (__predict_false(!wm_is_using_msix(sc))) {
+               return wm_legacy_intr_disable(sc);
+       }
+
        if (sc->sc_type == WM_T_82574)
                CSR_WRITE(sc, WMREG_IMC,
                    ICR_TXQ(wmq->wmq_id) | ICR_RXQ(wmq->wmq_id));
@@ -9900,6 +9920,10 @@
 
        wm_itrs_calculate(sc, wmq);
 
+       if (__predict_false(!wm_is_using_msix(sc))) {
+               return wm_legacy_intr_enable(sc);
+       }
+
        /*
         * ICR_OTHER which is disabled in wm_linkintr_msix() is enabled here.
         * There is no need to care about which of RXQ(0) and RXQ(1) enable



Home | Main Index | Thread Index | Old Index