Date: Thu, 22 May 2014 15:29:25 +0000 (UTC) From: Edward Tomasz Napierala <trasz@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r266546 - head/sys/dev/iwn Message-ID: <201405221529.s4MFTPxv010213@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: trasz Date: Thu May 22 15:29:25 2014 New Revision: 266546 URL: http://svnweb.freebsd.org/changeset/base/266546 Log: 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 Modified: head/sys/dev/iwn/if_iwn.c head/sys/dev/iwn/if_iwnvar.h Modified: head/sys/dev/iwn/if_iwn.c ============================================================================== --- head/sys/dev/iwn/if_iwn.c Thu May 22 15:00:32 2014 (r266545) +++ head/sys/dev/iwn/if_iwn.c Thu May 22 15:29:25 2014 (r266546) @@ -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)) || @@ -8412,6 +8426,38 @@ iwn_radio_off(void *arg0, int pending) } 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) { struct ifnet *ifp = sc->sc_ifp; Modified: head/sys/dev/iwn/if_iwnvar.h ============================================================================== --- head/sys/dev/iwn/if_iwnvar.h Thu May 22 15:00:32 2014 (r266545) +++ head/sys/dev/iwn/if_iwnvar.h Thu May 22 15:29:25 2014 (r266546) @@ -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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405221529.s4MFTPxv010213>