On Thu, Nov 28, 2013 at 09:24:32PM +0100, Mark Kettenis wrote:
> 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.

No regressions on:
iwn0 at pci3 dev 0 function 0 "Intel Centrino Advanced-N 6200" rev 0x35
and
iwn0 at pci2 dev 0 function 0 "Intel WiFi Link 1000" rev 0x00

Suspend/resume still works, wifi comes back as expected.
I've never seen fatal firmware errors with either adapter.
I don't have iwi so I cannot test that.

Diff is OK by me.
 
> 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