Module Name:    src
Committed By:   christos
Date:           Fri Feb  5 16:06:25 UTC 2021

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

Log Message:
PR/55975: Riccardo Mottola: Don't try to lock a mutex from an interrupt context.


To generate a diff of this commit:
cvs rdiff -u -r1.89 -r1.90 src/sys/dev/pci/if_wpi.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/if_wpi.c
diff -u src/sys/dev/pci/if_wpi.c:1.89 src/sys/dev/pci/if_wpi.c:1.90
--- src/sys/dev/pci/if_wpi.c:1.89	Fri Mar 20 13:19:25 2020
+++ src/sys/dev/pci/if_wpi.c	Fri Feb  5 11:06:24 2021
@@ -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 p
 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;

Reply via email to