Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/wpi/if_wpi.c
Show First 20 Lines • Show All 278 Lines • ▼ Show 20 Lines | |||||
static int wpi_init(struct wpi_softc *); | static int wpi_init(struct wpi_softc *); | ||||
static void wpi_stop_locked(struct wpi_softc *); | static void wpi_stop_locked(struct wpi_softc *); | ||||
static void wpi_stop(struct wpi_softc *); | static void wpi_stop(struct wpi_softc *); | ||||
static void wpi_scan_start(struct ieee80211com *); | static void wpi_scan_start(struct ieee80211com *); | ||||
static void wpi_scan_end(struct ieee80211com *); | static void wpi_scan_end(struct ieee80211com *); | ||||
static void wpi_set_channel(struct ieee80211com *); | static void wpi_set_channel(struct ieee80211com *); | ||||
static void wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long); | static void wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long); | ||||
static void wpi_scan_mindwell(struct ieee80211_scan_state *); | static void wpi_scan_mindwell(struct ieee80211_scan_state *); | ||||
static void wpi_hw_reset(void *, int); | |||||
static device_method_t wpi_methods[] = { | static device_method_t wpi_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, wpi_probe), | DEVMETHOD(device_probe, wpi_probe), | ||||
DEVMETHOD(device_attach, wpi_attach), | DEVMETHOD(device_attach, wpi_attach), | ||||
DEVMETHOD(device_detach, wpi_detach), | DEVMETHOD(device_detach, wpi_detach), | ||||
DEVMETHOD(device_shutdown, wpi_shutdown), | DEVMETHOD(device_shutdown, wpi_shutdown), | ||||
DEVMETHOD(device_suspend, wpi_suspend), | DEVMETHOD(device_suspend, wpi_suspend), | ||||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | #endif | ||||
sc->sc_update_tx_ring = wpi_update_tx_ring; | sc->sc_update_tx_ring = wpi_update_tx_ring; | ||||
wpi_radiotap_attach(sc); | wpi_radiotap_attach(sc); | ||||
callout_init_mtx(&sc->calib_to, &sc->rxon_mtx, 0); | callout_init_mtx(&sc->calib_to, &sc->rxon_mtx, 0); | ||||
callout_init_mtx(&sc->scan_timeout, &sc->rxon_mtx, 0); | callout_init_mtx(&sc->scan_timeout, &sc->rxon_mtx, 0); | ||||
callout_init_mtx(&sc->tx_timeout, &sc->txq_state_mtx, 0); | callout_init_mtx(&sc->tx_timeout, &sc->txq_state_mtx, 0); | ||||
callout_init_mtx(&sc->watchdog_rfkill, &sc->sc_mtx, 0); | callout_init_mtx(&sc->watchdog_rfkill, &sc->sc_mtx, 0); | ||||
TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc); | |||||
TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc); | TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc); | ||||
TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc); | TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc); | ||||
sc->sc_tq = taskqueue_create("wpi_taskq", M_WAITOK, | |||||
taskqueue_thread_enqueue, &sc->sc_tq); | |||||
error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "wpi_taskq"); | |||||
if (error != 0) { | |||||
device_printf(dev, "can't start threads, error %d\n", error); | |||||
goto fail; | |||||
} | |||||
wpi_sysctlattach(sc); | wpi_sysctlattach(sc); | ||||
/* | /* | ||||
* Hook our interrupt after all initialization is complete. | * Hook our interrupt after all initialization is complete. | ||||
*/ | */ | ||||
error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, | error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, | ||||
NULL, wpi_intr, sc, &sc->sc_ih); | NULL, wpi_intr, sc, &sc->sc_ih); | ||||
if (error != 0) { | if (error != 0) { | ||||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | wpi_detach(device_t dev) | ||||
struct wpi_softc *sc = device_get_softc(dev); | struct wpi_softc *sc = device_get_softc(dev); | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
uint8_t qid; | uint8_t qid; | ||||
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); | DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); | ||||
if (ic->ic_vap_create == wpi_vap_create) { | if (ic->ic_vap_create == wpi_vap_create) { | ||||
ieee80211_draintask(ic, &sc->sc_radioon_task); | ieee80211_draintask(ic, &sc->sc_radioon_task); | ||||
ieee80211_draintask(ic, &sc->sc_radiooff_task); | |||||
wpi_stop(sc); | wpi_stop(sc); | ||||
if (sc->sc_tq != NULL) { | |||||
taskqueue_drain_all(sc->sc_tq); | |||||
taskqueue_free(sc->sc_tq); | |||||
} | |||||
callout_drain(&sc->watchdog_rfkill); | callout_drain(&sc->watchdog_rfkill); | ||||
callout_drain(&sc->tx_timeout); | callout_drain(&sc->tx_timeout); | ||||
callout_drain(&sc->scan_timeout); | callout_drain(&sc->scan_timeout); | ||||
callout_drain(&sc->calib_to); | callout_drain(&sc->calib_to); | ||||
ieee80211_ifdetach(ic); | ieee80211_ifdetach(ic); | ||||
} | } | ||||
/* Uninstall interrupt handler. */ | /* Uninstall interrupt handler. */ | ||||
▲ Show 20 Lines • Show All 1,613 Lines • ▼ Show 20 Lines | case WPI_STATE_CHANGED: | ||||
DPRINTF(sc, WPI_DEBUG_STATE, "state changed to %x\n", | DPRINTF(sc, WPI_DEBUG_STATE, "state changed to %x\n", | ||||
le32toh(*status)); | le32toh(*status)); | ||||
if (le32toh(*status) & 1) { | if (le32toh(*status) & 1) { | ||||
WPI_NT_LOCK(sc); | WPI_NT_LOCK(sc); | ||||
wpi_clear_node_table(sc); | wpi_clear_node_table(sc); | ||||
WPI_NT_UNLOCK(sc); | WPI_NT_UNLOCK(sc); | ||||
taskqueue_enqueue(sc->sc_tq, | ieee80211_runtask(ic, | ||||
&sc->sc_radiooff_task); | &sc->sc_radiooff_task); | ||||
return; | return; | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
#ifdef WPI_DEBUG | #ifdef WPI_DEBUG | ||||
case WPI_START_SCAN: | case WPI_START_SCAN: | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 220 Lines • ▼ Show 20 Lines | wpi_intr(void *arg) | ||||
if (r1 == 0 && r2 == 0) | if (r1 == 0 && r2 == 0) | ||||
goto done; /* Interrupt not for us. */ | goto done; /* Interrupt not for us. */ | ||||
/* Acknowledge interrupts. */ | /* Acknowledge interrupts. */ | ||||
WPI_WRITE(sc, WPI_INT, r1); | WPI_WRITE(sc, WPI_INT, r1); | ||||
WPI_WRITE(sc, WPI_FH_INT, r2); | WPI_WRITE(sc, WPI_FH_INT, r2); | ||||
if (__predict_false(r1 & (WPI_INT_SW_ERR | WPI_INT_HW_ERR))) { | if (__predict_false(r1 & (WPI_INT_SW_ERR | WPI_INT_HW_ERR))) { | ||||
struct ieee80211com *ic = &sc->sc_ic; | |||||
device_printf(sc->sc_dev, "fatal firmware error\n"); | device_printf(sc->sc_dev, "fatal firmware error\n"); | ||||
#ifdef WPI_DEBUG | #ifdef WPI_DEBUG | ||||
wpi_debug_registers(sc); | wpi_debug_registers(sc); | ||||
#endif | #endif | ||||
wpi_fatal_intr(sc); | wpi_fatal_intr(sc); | ||||
DPRINTF(sc, WPI_DEBUG_HW, | DPRINTF(sc, WPI_DEBUG_HW, | ||||
"(%s)\n", (r1 & WPI_INT_SW_ERR) ? "(Software Error)" : | "(%s)\n", (r1 & WPI_INT_SW_ERR) ? "(Software Error)" : | ||||
"(Hardware Error)"); | "(Hardware Error)"); | ||||
taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); | ieee80211_restart_all(ic); | ||||
goto end; | goto end; | ||||
} | } | ||||
if ((r1 & (WPI_INT_FH_RX | WPI_INT_SW_RX)) || | if ((r1 & (WPI_INT_FH_RX | WPI_INT_SW_RX)) || | ||||
(r2 & WPI_FH_INT_RX)) | (r2 & WPI_FH_INT_RX)) | ||||
wpi_notif_intr(sc); | wpi_notif_intr(sc); | ||||
if (r1 & WPI_INT_ALIVE) | if (r1 & WPI_INT_ALIVE) | ||||
▲ Show 20 Lines • Show All 606 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
wpi_scan_timeout(void *arg) | wpi_scan_timeout(void *arg) | ||||
{ | { | ||||
struct wpi_softc *sc = arg; | struct wpi_softc *sc = arg; | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
ic_printf(ic, "scan timeout\n"); | ic_printf(ic, "scan timeout\n"); | ||||
taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); | ieee80211_restart_all(ic); | ||||
} | } | ||||
static void | static void | ||||
wpi_tx_timeout(void *arg) | wpi_tx_timeout(void *arg) | ||||
{ | { | ||||
struct wpi_softc *sc = arg; | struct wpi_softc *sc = arg; | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
ic_printf(ic, "device timeout\n"); | ic_printf(ic, "device timeout\n"); | ||||
taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); | ieee80211_restart_all(ic); | ||||
} | } | ||||
static void | static void | ||||
wpi_parent(struct ieee80211com *ic) | wpi_parent(struct ieee80211com *ic) | ||||
{ | { | ||||
struct wpi_softc *sc = ic->ic_softc; | struct wpi_softc *sc = ic->ic_softc; | ||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
if (ic->ic_nrunning > 0) { | if (ic->ic_nrunning > 0) { | ||||
if (wpi_init(sc) == 0) { | if (wpi_init(sc) == 0) { | ||||
ieee80211_notify_radio(ic, 1); | ieee80211_notify_radio(ic, 1); | ||||
ieee80211_start_all(ic); | ieee80211_start_all(ic); | ||||
} else { | } else { | ||||
ieee80211_notify_radio(ic, 0); | ieee80211_notify_radio(ic, 0); | ||||
ieee80211_stop(vap); | ieee80211_stop(vap); | ||||
} | } | ||||
} else | } else { | ||||
ieee80211_notify_radio(ic, 0); | |||||
wpi_stop(sc); | wpi_stop(sc); | ||||
} | } | ||||
} | |||||
/* | /* | ||||
* Send a command to the firmware. | * Send a command to the firmware. | ||||
*/ | */ | ||||
static int | static int | ||||
wpi_cmd(struct wpi_softc *sc, uint8_t code, const void *buf, uint16_t size, | wpi_cmd(struct wpi_softc *sc, uint8_t code, const void *buf, uint16_t size, | ||||
int async) | int async) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 2,407 Lines • ▼ Show 20 Lines | |||||
* the minimum dwell time has been met, terminate the scan. | * the minimum dwell time has been met, terminate the scan. | ||||
* We don't actually terminate the scan as the firmware will notify | * We don't actually terminate the scan as the firmware will notify | ||||
* us when it's finished and we have no way to interrupt it. | * us when it's finished and we have no way to interrupt it. | ||||
*/ | */ | ||||
static void | static void | ||||
wpi_scan_mindwell(struct ieee80211_scan_state *ss) | wpi_scan_mindwell(struct ieee80211_scan_state *ss) | ||||
{ | { | ||||
/* NB: don't try to abort scan; wait for firmware to finish */ | /* NB: don't try to abort scan; wait for firmware to finish */ | ||||
} | |||||
static void | |||||
wpi_hw_reset(void *arg, int pending) | |||||
{ | |||||
struct wpi_softc *sc = arg; | |||||
struct ieee80211com *ic = &sc->sc_ic; | |||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | |||||
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); | |||||
ieee80211_notify_radio(ic, 0); | |||||
if (vap != NULL && (ic->ic_flags & IEEE80211_F_SCAN)) | |||||
ieee80211_cancel_scan(vap); | |||||
wpi_stop(sc); | |||||
if (vap != NULL) { | |||||
ieee80211_stop(vap); | |||||
ieee80211_init(vap); | |||||
} | |||||
} | } |