diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2013-11-30 19:41:22 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2013-11-30 19:41:22 +0000 |
commit | 7b6445aafa1c4366013ff4a2988474a50e31b7e5 (patch) | |
tree | d01407f9ce35c0d640dfb9b5e6f86b85d6920204 /sys/dev/pci | |
parent | 4ad92e8943e0a32aa0c5358cca55e59c020f033e (diff) |
Seems we simply have to live with fatal firmware errors. Even Linux, with its
driver written by Intel engineers occasionally gets them. So when we get one,
simply reset the chip, reload the firware and bring the interface up again.
tested by stsp@, pascal@
ok stsp@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_iwn.c | 30 | ||||
-rw-r--r-- | sys/dev/pci/if_iwnvar.h | 5 |
2 files changed, 22 insertions, 13 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index f62f80cca12..623c409d5c4 100644 --- a/sys/dev/pci/if_iwn.c +++ b/sys/dev/pci/if_iwn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwn.c,v 1.125 2013/11/14 12:40:00 dlg Exp $ */ +/* $OpenBSD: if_iwn.c,v 1.126 2013/11/30 19:41:21 kettenis Exp $ */ /*- * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> @@ -105,7 +105,8 @@ void iwn_radiotap_attach(struct iwn_softc *); #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 device *self, void *aux) 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 device *self, void *aux) 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 flags) 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 act) 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 act) } 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)) || diff --git a/sys/dev/pci/if_iwnvar.h b/sys/dev/pci/if_iwnvar.h index 954fb1e0882..17914eba599 100644 --- a/sys/dev/pci/if_iwnvar.h +++ b/sys/dev/pci/if_iwnvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwnvar.h,v 1.25 2013/11/14 12:40:00 dlg Exp $ */ +/* $OpenBSD: if_iwnvar.h,v 1.26 2013/11/30 19:41:21 kettenis Exp $ */ /*- * Copyright (c) 2007, 2008 @@ -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; |