Just committed the wpi(4) version I mailed out last week.  And here is
the version for iwi(4) and iwn(4) as promised.  I believe both suffer
from the problem, although I think it is a long time ago since my
iwn(4) had issues.

Please test if you can still suspend and resume with this diff, and if
you are experiencing fatal firmware errors, check whether it does
indeed help to keep your wireless interface working.


Index: if_iwi.c
===================================================================
RCS file: /home/cvs/src/sys/dev/pci/if_iwi.c,v
retrieving revision 1.114
diff -u -p -r1.114 if_iwi.c
--- if_iwi.c    14 Nov 2013 12:39:14 -0000      1.114
+++ if_iwi.c    28 Nov 2013 20:19:27 -0000
@@ -74,7 +74,8 @@ const struct pci_matchid iwi_devices[] =
 int            iwi_match(struct device *, void *, void *);
 void           iwi_attach(struct device *, struct device *, void *);
 int            iwi_activate(struct device *, int);
-void           iwi_resume(void *, void *);
+void           iwi_resume(struct iwi_softc *);
+void           iwi_init_task(void *, void *);
 int            iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
 void           iwi_reset_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
 void           iwi_free_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
@@ -174,8 +175,6 @@ iwi_attach(struct device *parent, struct
        sc->sc_pct = pa->pa_pc;
        sc->sc_pcitag = pa->pa_tag;
 
-       task_set(&sc->sc_resume_t, iwi_resume, sc, NULL);
-
        /* clear device specific PCI configuration register 0x41 */
        data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
        data &= ~0x0000ff00;
@@ -326,6 +325,7 @@ iwi_attach(struct device *parent, struct
        sc->sc_txtap.wt_ihdr.it_present = htole32(IWI_TX_RADIOTAP_PRESENT);
 #endif
 
+       task_set(&sc->init_task, iwi_init_task, sc, NULL);
        return;
 
 fail:  while (--ac >= 0)
@@ -345,7 +345,7 @@ iwi_activate(struct device *self, int ac
                        iwi_stop(ifp, 0);
                break;
        case DVACT_RESUME:
-               task_add(systq, &sc->sc_resume_t);
+               iwi_resume(sc);
                break;
        }
 
@@ -353,24 +353,31 @@ iwi_activate(struct device *self, int ac
 }
 
 void
-iwi_resume(void *arg1, void *arg2)
+iwi_resume(struct iwi_softc *sc)
 {
-       struct iwi_softc *sc = arg1;
-       struct ifnet *ifp = &sc->sc_ic.ic_if;
        pcireg_t data;
-       int s;
 
        /* clear device specific PCI configuration register 0x41 */
        data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
        data &= ~0x0000ff00;
        pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data);
 
+       task_add(systq, &sc->init_task);
+}
+
+void
+iwi_init_task(void *arg1, void *arg2)
+{
+       struct iwi_softc *sc = arg1;
+       struct ifnet *ifp = &sc->sc_ic.ic_if;
+       int s;
+
        s = splnet();
        while (sc->sc_flags & IWI_FLAG_BUSY)
                tsleep(&sc->sc_flags, 0, "iwipwr", 0);
        sc->sc_flags |= IWI_FLAG_BUSY;
 
-       if (ifp->if_flags & IFF_UP)
+       if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
                iwi_init(ifp);
 
        sc->sc_flags &= ~IWI_FLAG_BUSY;
@@ -1159,8 +1166,8 @@ iwi_intr(void *arg)
 
        if (r & IWI_INTR_FATAL_ERROR) {
                printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
-               ifp->if_flags &= ~IFF_UP;
                iwi_stop(ifp, 1);
+               task_add(systq, &sc->init_task);
                return 1;
        }
 
Index: if_iwivar.h
===================================================================
RCS file: /home/cvs/src/sys/dev/pci/if_iwivar.h,v
retrieving revision 1.24
diff -u -p -r1.24 if_iwivar.h
--- if_iwivar.h 14 Nov 2013 12:39:14 -0000      1.24
+++ if_iwivar.h 28 Nov 2013 20:17:43 -0000
@@ -112,9 +112,9 @@ struct iwi_softc {
        pcitag_t                sc_pcitag;
        bus_size_t              sc_sz;
 
-       int                     sc_tx_timer;
+       struct task             init_task;
 
-       struct task             sc_resume_t;
+       int                     sc_tx_timer;
 
 #if NBPFILTER > 0
        caddr_t                 sc_drvbpf;
Index: if_iwn.c
===================================================================
RCS file: /home/cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.125
diff -u -p -r1.125 if_iwn.c
--- if_iwn.c    14 Nov 2013 12:40:00 -0000      1.125
+++ if_iwn.c    28 Nov 2013 20:15:56 -0000
@@ -105,7 +105,8 @@ void                iwn_radiotap_attach(struct iwn_sof
 #endif
 int            iwn_detach(struct device *, int);
 int            iwn_activate(struct device *, int);
-void           iwn_resume(void *, void *);
+void           iwn_resume(struct iwn_softc *);
+void           iwn_init_task(void *, void *);
 int            iwn_nic_lock(struct iwn_softc *);
 int            iwn_eeprom_lock(struct iwn_softc *);
 int            iwn_init_otprom(struct iwn_softc *);
@@ -309,8 +310,6 @@ iwn_attach(struct device *parent, struct
        sc->sc_pcitag = pa->pa_tag;
        sc->sc_dmat = pa->pa_dmat;
 
-       task_set(&sc->sc_resume_t, iwn_resume, sc, NULL);
-
        /*
         * Get the offset of the PCI Express Capability Structure in PCI
         * Configuration Space.
@@ -524,6 +523,7 @@ iwn_attach(struct device *parent, struct
        iwn_radiotap_attach(sc);
 #endif
        timeout_set(&sc->calib_to, iwn_calib_timeout, sc);
+       task_set(&sc->init_task, iwn_init_task, sc, NULL);
        return;
 
        /* Free allocated memory if something failed during attachment. */
@@ -686,6 +686,7 @@ iwn_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)
@@ -721,7 +722,7 @@ iwn_activate(struct device *self, int ac
                        iwn_stop(ifp, 0);
                break;
        case DVACT_RESUME:
-               task_add(systq, &sc->sc_resume_t);
+               iwn_resume(sc);
                break;
        }
 
@@ -729,24 +730,31 @@ iwn_activate(struct device *self, int ac
 }
 
 void
-iwn_resume(void *arg1, void *arg2)
+iwn_resume(struct iwn_softc *sc)
 {
-       struct iwn_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);
        if (reg & 0xff00)
                pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
 
+       task_add(systq, &sc->init_task);
+}
+
+void
+iwn_init_task(void *arg1, void *arg2)
+{
+       struct iwn_softc *sc = arg1;
+       struct ifnet *ifp = &sc->sc_ic.ic_if;
+       int s;
+
        s = splnet();
        while (sc->sc_flags & IWN_FLAG_BUSY)
                tsleep(&sc->sc_flags, 0, "iwnpwr", 0);
        sc->sc_flags |= IWN_FLAG_BUSY;
 
-       if (ifp->if_flags & IFF_UP)
+       if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
                iwn_init(ifp);
 
        sc->sc_flags &= ~IWN_FLAG_BUSY;
@@ -2593,8 +2601,8 @@ iwn_intr(void *arg)
                printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
                /* Dump firmware error log and stop. */
                iwn_fatal_intr(sc);
-               ifp->if_flags &= ~IFF_UP;
                iwn_stop(ifp, 1);
+               task_add(systq, &sc->init_task);
                return 1;
        }
        if ((r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX | IWN_INT_RX_PERIODIC)) ||
Index: if_iwnvar.h
===================================================================
RCS file: /home/cvs/src/sys/dev/pci/if_iwnvar.h,v
retrieving revision 1.25
diff -u -p -r1.25 if_iwnvar.h
--- if_iwnvar.h 14 Nov 2013 12:40:00 -0000      1.25
+++ if_iwnvar.h 28 Nov 2013 20:03:02 -0000
@@ -251,6 +251,8 @@ struct iwn_softc {
        int                     calib_cnt;
        struct iwn_calib_state  calib;
 
+       struct task             init_task;
+
        struct iwn_fw_info      fw;
        struct iwn_calib_info   calibcmd[5];
        uint32_t                errptr;
@@ -287,7 +289,6 @@ struct iwn_softc {
        uint8_t                 chainmask;
 
        int                     sc_tx_timer;
-       struct task             sc_resume_t;
 
 #if NBPFILTER > 0
        caddr_t                 sc_drvbpf;

Reply via email to