mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-29 16:44:03 +00:00
Make iwn(4) able to get itself back into working condition after
"fatal firmware error" happens. Previously it was neccessary to reset it manually, using "/etc/rc.d/netif restart". Approved by: adrian@ MFC after: 1 month Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
43c2aa0f86
commit
8acd0be199
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=266546
@ -332,6 +332,7 @@ static int iwn_hw_init(struct iwn_softc *);
|
||||
static void iwn_hw_stop(struct iwn_softc *);
|
||||
static void iwn_radio_on(void *, int);
|
||||
static void iwn_radio_off(void *, int);
|
||||
static void iwn_panicked(void *, int);
|
||||
static void iwn_init_locked(struct iwn_softc *);
|
||||
static void iwn_init(void *);
|
||||
static void iwn_stop_locked(struct iwn_softc *);
|
||||
@ -671,6 +672,15 @@ iwn_attach(device_t dev)
|
||||
TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc);
|
||||
TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc);
|
||||
TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc);
|
||||
TASK_INIT(&sc->sc_panic_task, 0, iwn_panicked, sc);
|
||||
|
||||
sc->sc_tq = taskqueue_create("iwn_taskq", M_WAITOK,
|
||||
taskqueue_thread_enqueue, &sc->sc_tq);
|
||||
error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "iwn_taskq");
|
||||
if (error != 0) {
|
||||
device_printf(dev, "can't start threads, error %d\n", error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
iwn_sysctlattach(sc);
|
||||
|
||||
@ -1334,6 +1344,10 @@ iwn_detach(device_t dev)
|
||||
ieee80211_draintask(ic, &sc->sc_radiooff_task);
|
||||
|
||||
iwn_stop(sc);
|
||||
|
||||
taskqueue_drain_all(sc->sc_tq);
|
||||
taskqueue_free(sc->sc_tq);
|
||||
|
||||
callout_drain(&sc->watchdog_to);
|
||||
callout_drain(&sc->calib_to);
|
||||
ieee80211_ifdetach(ic);
|
||||
@ -3944,8 +3958,8 @@ iwn_intr(void *arg)
|
||||
#endif
|
||||
/* Dump firmware error log and stop. */
|
||||
iwn_fatal_intr(sc);
|
||||
ifp->if_flags &= ~IFF_UP;
|
||||
iwn_stop_locked(sc);
|
||||
|
||||
taskqueue_enqueue(sc->sc_tq, &sc->sc_panic_task);
|
||||
goto done;
|
||||
}
|
||||
if ((r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX | IWN_INT_RX_PERIODIC)) ||
|
||||
@ -8411,6 +8425,38 @@ iwn_radio_off(void *arg0, int pending)
|
||||
IWN_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
iwn_panicked(void *arg0, int pending)
|
||||
{
|
||||
struct iwn_softc *sc = arg0;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
int error;
|
||||
|
||||
if (vap == NULL) {
|
||||
printf("%s: null vap\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
device_printf(sc->sc_dev, "%s: controller panicked, iv_state = %d; "
|
||||
"resetting...\n", __func__, vap->iv_state);
|
||||
|
||||
iwn_stop(sc);
|
||||
iwn_init(sc);
|
||||
iwn_start(sc->sc_ifp);
|
||||
if (vap->iv_state >= IEEE80211_S_AUTH &&
|
||||
(error = iwn_auth(sc, vap)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: could not move to auth state\n", __func__);
|
||||
}
|
||||
if (vap->iv_state >= IEEE80211_S_RUN &&
|
||||
(error = iwn_run(sc, vap)) != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: could not move to run state\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iwn_init_locked(struct iwn_softc *sc)
|
||||
{
|
||||
|
@ -308,6 +308,10 @@ struct iwn_softc {
|
||||
struct task sc_reinit_task;
|
||||
struct task sc_radioon_task;
|
||||
struct task sc_radiooff_task;
|
||||
struct task sc_panic_task;
|
||||
|
||||
/* Taskqueue */
|
||||
struct taskqueue *sc_tq;
|
||||
|
||||
/* Calibration information */
|
||||
struct callout calib_to;
|
||||
|
Loading…
Reference in New Issue
Block a user