diff options
| author | christos <christos@NetBSD.org> | 2021-02-05 16:06:24 +0000 |
|---|---|---|
| committer | christos <christos@NetBSD.org> | 2021-02-05 16:06:24 +0000 |
| commit | 894be6061b3072dc421d8a0ed6ad83484b7d2b47 (patch) | |
| tree | bf75f481e8950fecace9e7a76e79bd454d90cb15 /sys/dev | |
| parent | 30ef91d5e36eed569ca49762b221c5ca17390152 (diff) | |
PR/55975: Riccardo Mottola: Don't try to lock a mutex from an interrupt context.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/pci/if_wpi.c | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c index 7ecef5b0ec8..d3217400a47 100644 --- a/sys/dev/pci/if_wpi.c +++ b/sys/dev/pci/if_wpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_wpi.c,v 1.89 2020/03/20 17:19:25 sevan Exp $ */ +/* $NetBSD: if_wpi.c,v 1.90 2021/02/05 16:06:24 christos Exp $ */ /*- * Copyright (c) 2006, 2007 @@ -18,7 +18,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.89 2020/03/20 17:19:25 sevan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.90 2021/02/05 16:06:24 christos Exp $"); /* * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters. @@ -158,6 +158,8 @@ static bool wpi_resume(device_t, const pmf_qual_t *); static int wpi_getrfkill(struct wpi_softc *); static void wpi_sysctlattach(struct wpi_softc *); static void wpi_rsw_thread(void *); +static void wpi_rsw_suspend(struct wpi_softc *); +static void wpi_stop_intr(struct ifnet *, int); #ifdef WPI_DEBUG #define DPRINTF(x) do { if (wpi_debug > 0) printf x; } while (0) @@ -1769,7 +1771,7 @@ wpi_notif_intr(struct wpi_softc *sc) "Radio transmitter is off\n"); /* turn the interface down */ ifp->if_flags &= ~IFF_UP; - wpi_stop(ifp, 1); + wpi_stop_intr(ifp, 1); splx(s); return; /* no further processing */ } @@ -1853,7 +1855,7 @@ wpi_softintr(void *arg) /* SYSTEM FAILURE, SYSTEM FAILURE */ aprint_error_dev(sc->sc_dev, "fatal firmware error\n"); ifp->if_flags &= ~IFF_UP; - wpi_stop(ifp, 1); + wpi_stop_intr(ifp, 1); return; } @@ -2203,7 +2205,7 @@ wpi_watchdog(struct ifnet *ifp) if (--sc->sc_tx_timer == 0) { aprint_error_dev(sc->sc_dev, "device timeout\n"); ifp->if_flags &= ~IFF_UP; - wpi_stop(ifp, 1); + wpi_stop_intr(ifp, 1); if_statinc(ifp, if_oerrors); return; } @@ -3200,7 +3202,7 @@ wpi_init(struct ifnet *ifp) uint32_t tmp; int qid, ntries, error; - wpi_stop(ifp,1); + wpi_stop(ifp, 1); (void)wpi_reset(sc); wpi_mem_lock(sc); @@ -3311,7 +3313,7 @@ fail1: wpi_stop(ifp, 1); } static void -wpi_stop(struct ifnet *ifp, int disable) +wpi_stop1(struct ifnet *ifp, int disable, bool fromintr) { struct wpi_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; @@ -3323,13 +3325,11 @@ wpi_stop(struct ifnet *ifp, int disable) ieee80211_new_state(ic, IEEE80211_S_INIT, -1); - /* suspend rfkill test thread */ - mutex_enter(&sc->sc_rsw_mtx); - sc->sc_rsw_suspend = true; - cv_broadcast(&sc->sc_rsw_cv); - while (!sc->sc_rsw_suspended) - cv_wait(&sc->sc_rsw_cv, &sc->sc_rsw_mtx); - mutex_exit(&sc->sc_rsw_mtx); + if (fromintr) { + sc->sc_rsw_suspend = true; // XXX: without mutex or wait + } else { + wpi_rsw_suspend(sc); + } /* disable interrupts */ WPI_WRITE(sc, WPI_MASK, 0); @@ -3361,6 +3361,18 @@ wpi_stop(struct ifnet *ifp, int disable) WPI_WRITE(sc, WPI_RESET, tmp | WPI_SW_RESET); } +static void +wpi_stop(struct ifnet *ifp, int disable) +{ + wpi_stop1(ifp, disable, false); +} + +static void +wpi_stop_intr(struct ifnet *ifp, int disable) +{ + wpi_stop1(ifp, disable, true); +} + static bool wpi_resume(device_t dv, const pmf_qual_t *qual) { @@ -3463,6 +3475,18 @@ err: } static void +wpi_rsw_suspend(struct wpi_softc *sc) +{ + /* suspend rfkill test thread */ + mutex_enter(&sc->sc_rsw_mtx); + sc->sc_rsw_suspend = true; + cv_broadcast(&sc->sc_rsw_cv); + while (!sc->sc_rsw_suspended) + cv_wait(&sc->sc_rsw_cv, &sc->sc_rsw_mtx); + mutex_exit(&sc->sc_rsw_mtx); +} + +static void wpi_rsw_thread(void *arg) { struct wpi_softc *sc = (struct wpi_softc *)arg; |
