Now that wpi(4) does 802.11a, and I'm using my old laptop to test
inteldrm(4) diffs, I got annoyed that from time to time wpi(4) craps
out and I have to get out of my lazy chair to bring the interface back
up.  So here's a diff that automatically reinitializes the hardware if
this happens. 

ok?

P.S. I'm planning to make similar changes to the related drivers for
      other Intel wireless chips once this has been reviewed.

Index: if_wpi.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_wpi.c,v
retrieving revision 1.115
diff -u -p -r1.115 if_wpi.c
--- if_wpi.c    16 Nov 2013 12:46:29 -0000      1.115
+++ if_wpi.c    21 Nov 2013 20:10:21 -0000
@@ -75,7 +75,8 @@ void          wpi_radiotap_attach(struct wpi_sof
 #endif
 int            wpi_detach(struct device *, int);
 int            wpi_activate(struct device *, int);
-void           wpi_resume(void *, void *);
+void           wpi_resume(struct wpi_softc *);
+void           wpi_init_task(void *, void *);
 int            wpi_nic_lock(struct wpi_softc *);
 int            wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int);
 int            wpi_dma_contig_alloc(bus_dma_tag_t, struct wpi_dma_info *,
@@ -189,8 +190,6 @@ wpi_attach(struct device *parent, struct
        sc->sc_pcitag = pa->pa_tag;
        sc->sc_dmat = pa->pa_dmat;
 
-       task_set(&sc->sc_resume_t, wpi_resume, sc, NULL);
-
        /*
         * Get the offset of the PCI Express Capability Structure in PCI
         * Configuration Space (the vendor driver hard-codes it as E0h.)
@@ -327,6 +326,7 @@ wpi_attach(struct device *parent, struct
        wpi_radiotap_attach(sc);
 #endif
        timeout_set(&sc->calib_to, wpi_calib_timeout, sc);
+       task_set(&sc->init_task, wpi_init_task, sc, NULL);
        return;
 
        /* Free allocated memory if something failed during attachment. */
@@ -364,6 +364,7 @@ wpi_detach(struct device *self, int flag
        int qid;
 
        timeout_del(&sc->calib_to);
+       task_del(systq, &sc->init_task);
 
        /* Uninstall interrupt handler. */
        if (sc->sc_ih != NULL)
@@ -396,7 +397,7 @@ wpi_activate(struct device *self, int ac
                        wpi_stop(ifp, 0);
                break;
        case DVACT_RESUME:
-               task_add(systq, &sc->sc_resume_t);
+               wpi_resume(sc);
                break;
        }
 
@@ -404,24 +405,31 @@ wpi_activate(struct device *self, int ac
 }
 
 void
-wpi_resume(void *arg1, void *arg2)
+wpi_resume(struct wpi_softc *sc)
 {
-       struct wpi_softc *sc = arg1;
-       struct ifnet *ifp = &sc->sc_ic.ic_if;
        pcireg_t reg;
-       int s;
 
        /* Clear device-specific "PCI retry timeout" register (41h). */
        reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
        reg &= ~0xff00;
        pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg);
 
+       task_add(systq, &sc->init_task);
+}
+
+void
+wpi_init_task(void *arg1, void *args2)
+{
+       struct wpi_softc *sc = arg1;
+       struct ifnet *ifp = &sc->sc_ic.ic_if;
+       int s;
+
        s = splnet();
        while (sc->sc_flags & WPI_FLAG_BUSY)
                tsleep(&sc->sc_flags, 0, "wpipwr", 0);
        sc->sc_flags |= WPI_FLAG_BUSY;
 
-       if (ifp->if_flags & IFF_UP)
+       if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
                wpi_init(ifp);
 
        sc->sc_flags &= ~WPI_FLAG_BUSY;
@@ -1620,8 +1628,8 @@ wpi_intr(void *arg)
                printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
                /* Dump firmware error log and stop. */
                wpi_fatal_intr(sc);
-               ifp->if_flags &= ~IFF_UP;
                wpi_stop(ifp, 1);
+               task_add(systq, &sc->init_task);
                return 1;
        }
        if ((r1 & (WPI_INT_FH_RX | WPI_INT_SW_RX)) ||
Index: if_wpivar.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_wpivar.h,v
retrieving revision 1.24
diff -u -p -r1.24 if_wpivar.h
--- if_wpivar.h 14 Nov 2013 12:34:30 -0000      1.24
+++ if_wpivar.h 21 Nov 2013 20:10:21 -0000
@@ -166,6 +166,8 @@ struct wpi_softc {
        struct timeout          calib_to;
        int                     calib_cnt;
 
+       struct task             init_task;
+
        struct wpi_fw_info      fw;
        uint32_t                errptr;
 
@@ -180,7 +182,6 @@ struct wpi_softc {
        int8_t                  maxpwr[IEEE80211_CHAN_MAX];
 
        int                     sc_tx_timer;
-       struct task             sc_resume_t;
 
 #if NBPFILTER > 0
        caddr_t                 sc_drvbpf;

Reply via email to