Replace the ioctl tsleep/wakeup BUSY flag dance with an rwlock.

ok?

Index: if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.124
diff -u -p -r1.124 if_iwm.c
--- if_iwm.c    4 Sep 2016 17:01:59 -0000       1.124
+++ if_iwm.c    4 Sep 2016 18:12:34 -0000
@@ -114,6 +114,7 @@
 #include <sys/mbuf.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
+#include <sys/rwlock.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/systm.h>
@@ -6204,19 +6205,16 @@ iwm_ioctl(struct ifnet *ifp, u_long cmd,
        struct ifreq *ifr;
        int s, err = 0;
 
-       s = splnet();
 
        /*
         * Prevent processes from entering this function while another
         * process is tsleep'ing in it.
         */
-       while ((sc->sc_flags & IWM_FLAG_BUSY) && err == 0)
-               err = tsleep(&sc->sc_flags, PCATCH, "iwmioc", 0);
-       if (err) {
-               splx(s);
+       err = rw_enter(&sc->ioctl_rwl, RW_WRITE | RW_INTR);
+       if (err)
                return err;
-       }
-       sc->sc_flags |= IWM_FLAG_BUSY;
+
+       s = splnet();
 
        switch (cmd) {
        case SIOCSIFADDR:
@@ -6258,9 +6256,9 @@ iwm_ioctl(struct ifnet *ifp, u_long cmd,
                }
        }
 
-       sc->sc_flags &= ~IWM_FLAG_BUSY;
-       wakeup(&sc->sc_flags);
        splx(s);
+       rw_exit(&sc->ioctl_rwl);
+
        return err;
 }
 
@@ -7041,6 +7039,7 @@ iwm_attach(struct device *parent, struct
        sc->sc_dmat = pa->pa_dmat;
 
        task_set(&sc->sc_eswk, iwm_endscan_cb, sc);
+       rw_init(&sc->ioctl_rwl, "iwmioctl");
 
        err = pci_get_capability(sc->sc_pct, sc->sc_pcitag,
            PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);
@@ -7359,18 +7358,15 @@ iwm_init_task(void *arg1)
        struct ifnet *ifp = &sc->sc_ic.ic_if;
        int s;
 
+       rw_enter_write(&sc->ioctl_rwl);
        s = splnet();
-       while (sc->sc_flags & IWM_FLAG_BUSY)
-               tsleep(&sc->sc_flags, 0, "iwmpwr", 0);
-       sc->sc_flags |= IWM_FLAG_BUSY;
 
        iwm_stop(ifp, 0);
        if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
                iwm_init(ifp);
 
-       sc->sc_flags &= ~IWM_FLAG_BUSY;
-       wakeup(&sc->sc_flags);
        splx(s);
+       rw_exit(&sc->ioctl_rwl);
 }
 
 void
Index: if_iwmvar.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwmvar.h,v
retrieving revision 1.20
diff -u -p -r1.20 if_iwmvar.h
--- if_iwmvar.h 2 Sep 2016 15:45:17 -0000       1.20
+++ if_iwmvar.h 4 Sep 2016 17:58:40 -0000
@@ -283,8 +283,7 @@ struct iwm_rx_ring {
 #define IWM_FLAG_HW_INITED     0x02
 #define IWM_FLAG_STOPPED       0x04
 #define IWM_FLAG_RFKILL                0x08
-#define IWM_FLAG_BUSY          0x10
-#define IWM_FLAG_SCANNING      0x20
+#define IWM_FLAG_SCANNING      0x10
 
 struct iwm_ucode_status {
        uint32_t uc_error_event_table;
@@ -439,6 +438,8 @@ struct iwm_softc {
         * don't have the luxury of waiting for quiescense.
         */
        int sc_generation;
+
+       struct rwlock ioctl_rwl;
 
        int sc_cap_off; /* PCIe caps */
 

Reply via email to