diff --git a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath.c b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath.c index f3d217eed3..33af3fb215 100644 --- a/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath.c +++ b/src/add-ons/kernel/drivers/network/wlan/atheroswifi/dev/ath/if_ath.c @@ -160,7 +160,6 @@ static int ath_init(struct ath_softc *); static void ath_stop(struct ath_softc *); static int ath_reset_vap(struct ieee80211vap *, u_long); static int ath_transmit(struct ieee80211com *, struct mbuf *); -static int ath_media_change(struct ifnet *); static void ath_watchdog(void *); static void ath_parent(struct ieee80211com *); static void ath_fatal_proc(void *, int); @@ -1769,8 +1768,8 @@ ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, ATH_UNLOCK(sc); /* complete setup */ - ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status, - mac); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); return vap; bad2: reclaim_address(sc, mac); @@ -3550,14 +3549,6 @@ finish: return (retval); } -static int -ath_media_change(struct ifnet *ifp) -{ - int error = ieee80211_media_change(ifp); - /* NB: only the fixed rate can change and that doesn't need a reset */ - return (error == ENETRESET ? 0 : error); -} - /* * Block/unblock tx+rx processing while a key change is done. * We assume the caller serializes key management operations diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c index 46d532cd4d..5a1369429c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c @@ -118,7 +118,6 @@ static void bwi_set_channel(struct ieee80211com *); static void bwi_scan_end(struct ieee80211com *); static int bwi_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void bwi_updateslot(struct ieee80211com *); -static int bwi_media_change(struct ifnet *); static void bwi_calibrate(void *); @@ -610,8 +609,8 @@ bwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, ieee80211_ratectl_init(vap); /* complete setup */ - ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status, - mac); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -1825,14 +1824,6 @@ back: return error; } -static int -bwi_media_change(struct ifnet *ifp) -{ - int error = ieee80211_media_change(ifp); - /* NB: only the fixed rate can change and that doesn't need a reset */ - return (error == ENETRESET ? 0 : error); -} - static int bwi_dma_alloc(struct bwi_softc *sc) { diff --git a/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/iwm/if_iwm.c b/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/iwm/if_iwm.c index 625b83595c..53a5319c24 100644 --- a/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/iwm/if_iwm.c +++ b/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/iwm/if_iwm.c @@ -354,7 +354,6 @@ static struct ieee80211_node * static uint8_t iwm_rate_from_ucode_rate(uint32_t); static int iwm_rate2ridx(struct iwm_softc *, uint8_t); static void iwm_setrates(struct iwm_softc *, struct iwm_node *, int); -static int iwm_media_change(struct ifnet *); static int iwm_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void iwm_endscan_cb(void *, int); static int iwm_send_bt_init_conf(struct iwm_softc *); @@ -4418,27 +4417,6 @@ iwm_setrates(struct iwm_softc *sc, struct iwm_node *in, int rix) } } -static int -iwm_media_change(struct ifnet *ifp) -{ - struct ieee80211vap *vap = ifp->if_softc; - struct ieee80211com *ic = vap->iv_ic; - struct iwm_softc *sc = ic->ic_softc; - int error; - - error = ieee80211_media_change(ifp); - if (error != ENETRESET) - return error; - - IWM_LOCK(sc); - if (ic->ic_nrunning > 0) { - iwm_stop(sc); - iwm_init(sc); - } - IWM_UNLOCK(sc); - return error; -} - static void iwm_bring_down_firmware(struct iwm_softc *sc, struct ieee80211vap *vap) { @@ -5067,18 +5045,46 @@ iwm_parent(struct ieee80211com *ic) { struct iwm_softc *sc = ic->ic_softc; int startall = 0; + int rfkill = 0; IWM_LOCK(sc); if (ic->ic_nrunning > 0) { if (!(sc->sc_flags & IWM_FLAG_HW_INITED)) { iwm_init(sc); - startall = 1; + rfkill = iwm_check_rfkill(sc); + if (!rfkill) + startall = 1; } } else if (sc->sc_flags & IWM_FLAG_HW_INITED) iwm_stop(sc); IWM_UNLOCK(sc); if (startall) ieee80211_start_all(ic); + else if (rfkill) + taskqueue_enqueue(sc->sc_tq, &sc->sc_rftoggle_task); +} + +static void +iwm_rftoggle_task(void *arg, int npending __unused) +{ + struct iwm_softc *sc = arg; + struct ieee80211com *ic = &sc->sc_ic; + int rfkill; + + IWM_LOCK(sc); + rfkill = iwm_check_rfkill(sc); + IWM_UNLOCK(sc); + if (rfkill) { + device_printf(sc->sc_dev, + "%s: rfkill switch, disabling interface\n", __func__); + ieee80211_suspend_all(ic); + ieee80211_notify_radio(ic, 0); + } else { + device_printf(sc->sc_dev, + "%s: rfkill cleared, re-enabling interface\n", __func__); + ieee80211_resume_all(ic); + ieee80211_notify_radio(ic, 1); + } } /* @@ -5822,12 +5828,7 @@ iwm_intr(void *arg) if (r1 & IWM_CSR_INT_BIT_RF_KILL) { handled |= IWM_CSR_INT_BIT_RF_KILL; - if (iwm_check_rfkill(sc)) { - device_printf(sc->sc_dev, - "%s: rfkill switch, disabling interface\n", - __func__); - iwm_stop(sc); - } + taskqueue_enqueue(sc->sc_tq, &sc->sc_rftoggle_task); } /* @@ -5885,6 +5886,7 @@ iwm_intr(void *arg) #define PCI_PRODUCT_INTEL_WL_8265_1 0x24fd #define PCI_PRODUCT_INTEL_WL_9560_1 0x9df0 #define PCI_PRODUCT_INTEL_WL_9560_2 0xa370 +#define PCI_PRODUCT_INTEL_WL_9560_3 0x31dc #define PCI_PRODUCT_INTEL_WL_9260_1 0x2526 static const struct iwm_devices { @@ -5905,6 +5907,7 @@ static const struct iwm_devices { { PCI_PRODUCT_INTEL_WL_8265_1, &iwm8265_cfg }, { PCI_PRODUCT_INTEL_WL_9560_1, &iwm9560_cfg }, { PCI_PRODUCT_INTEL_WL_9560_2, &iwm9560_cfg }, + { PCI_PRODUCT_INTEL_WL_9560_3, &iwm9560_cfg }, { PCI_PRODUCT_INTEL_WL_9260_1, &iwm9260_cfg }, }; @@ -6032,6 +6035,16 @@ iwm_attach(device_t dev) callout_init_mtx(&sc->sc_watchdog_to, &sc->sc_mtx, 0); callout_init_mtx(&sc->sc_led_blink_to, &sc->sc_mtx, 0); TASK_INIT(&sc->sc_es_task, 0, iwm_endscan_cb, sc); + TASK_INIT(&sc->sc_rftoggle_task, 0, iwm_rftoggle_task, sc); + + sc->sc_tq = taskqueue_create("iwm_taskq", M_WAITOK, + taskqueue_thread_enqueue, &sc->sc_tq); + error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "iwm_taskq"); + if (error != 0) { + device_printf(dev, "can't start taskq thread, error %d\n", + error); + goto fail; + } error = iwm_dev_check(dev); if (error != 0) @@ -6409,8 +6422,8 @@ iwm_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, ieee80211_ratectl_init(vap); /* Complete setup. */ - ieee80211_vap_attach(vap, iwm_media_change, ieee80211_media_status, - mac); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; @@ -6600,6 +6613,8 @@ iwm_detach_local(struct iwm_softc *sc, int do_net80211) ieee80211_draintask(&sc->sc_ic, &sc->sc_es_task); } iwm_stop_device(sc); + taskqueue_drain_all(sc->sc_tq); + taskqueue_free(sc->sc_tq); if (do_net80211) { IWM_LOCK(sc); iwm_xmit_queue_drain(sc); diff --git a/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/iwm/if_iwmvar.h b/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/iwm/if_iwmvar.h index a2452b1e46..320f030c61 100644 --- a/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/iwm/if_iwmvar.h +++ b/src/add-ons/kernel/drivers/network/wlan/idualwifi7260/dev/iwm/if_iwmvar.h @@ -499,7 +499,9 @@ struct iwm_softc { uint8_t sc_cmd_resp[IWM_CMD_RESP_MAX]; int sc_wantresp; + struct taskqueue *sc_tq; struct task sc_es_task; + struct task sc_rftoggle_task; struct iwm_rx_phy_info sc_last_phy_info; int sc_ampdu_ref; diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c index 08c4ff0cd5..c7ef86455e 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c @@ -190,7 +190,6 @@ static void iwn_read_eeprom_enhinfo(struct iwn_softc *); static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *, const uint8_t mac[IEEE80211_ADDR_LEN]); static void iwn_newassoc(struct ieee80211_node *, int); -static int iwn_media_change(struct ifnet *); static int iwn_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void iwn_calib_timeout(void *); static void iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *); @@ -1357,8 +1356,8 @@ iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, ieee80211_ratectl_init(vap); /* Complete setup. */ - ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status, - mac); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -2848,16 +2847,6 @@ iwn_newassoc(struct ieee80211_node *ni, int isnew) /* Doesn't do anything at the moment */ } -static int -iwn_media_change(struct ifnet *ifp) -{ - int error; - - error = ieee80211_media_change(ifp); - /* NB: only the fixed rate can change and that doesn't need a reset */ - return (error == ENETRESET ? 0 : error); -} - static int iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { diff --git a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl.c b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl.c index 3bc625da28..19a628a26b 100644 --- a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl.c +++ b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl.c @@ -1473,16 +1473,17 @@ mwl_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, static int mwl_media_change(struct ifnet *ifp) { - struct ieee80211vap *vap = ifp->if_softc; + struct ieee80211vap *vap; int error; - error = ieee80211_media_change(ifp); /* NB: only the fixed rate can change and that doesn't need a reset */ - if (error == ENETRESET) { - mwl_setrates(vap); - error = 0; - } - return error; + error = ieee80211_media_change(ifp); + if (error != 0) + return (error); + + vap = ifp->if_softc; + mwl_setrates(vap); + return (0); } #ifdef MWL_DEBUG