diff options
Diffstat (limited to 'package/mac80211/patches/582-ath9k_merge_reset_functions.patch')
-rw-r--r-- | package/mac80211/patches/582-ath9k_merge_reset_functions.patch | 448 |
1 files changed, 0 insertions, 448 deletions
diff --git a/package/mac80211/patches/582-ath9k_merge_reset_functions.patch b/package/mac80211/patches/582-ath9k_merge_reset_functions.patch deleted file mode 100644 index 54d0eafc89..0000000000 --- a/package/mac80211/patches/582-ath9k_merge_reset_functions.patch +++ /dev/null @@ -1,448 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/main.c -+++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -212,84 +212,57 @@ static int ath_update_survey_stats(struc - return ret; - } - --/* -- * Set/change channels. If the channel is really being changed, it's done -- * by reseting the chip. To accomplish this we must first cleanup any pending -- * DMA, then restart stuff. --*/ --static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, -- struct ath9k_channel *hchan) -+static void __ath_cancel_work(struct ath_softc *sc) - { -- struct ath_hw *ah = sc->sc_ah; -- struct ath_common *common = ath9k_hw_common(ah); -- struct ieee80211_conf *conf = &common->hw->conf; -- bool fastcc = true, stopped; -- struct ieee80211_channel *channel = hw->conf.channel; -- struct ath9k_hw_cal_data *caldata = NULL; -- int r; -- -- if (sc->sc_flags & SC_OP_INVALID) -- return -EIO; -- -- sc->hw_busy_count = 0; -- -- del_timer_sync(&common->ani.timer); - cancel_work_sync(&sc->paprd_work); - cancel_work_sync(&sc->hw_check_work); -- cancel_work_sync(&sc->hw_reset_work); - cancel_delayed_work_sync(&sc->tx_complete_work); - cancel_delayed_work_sync(&sc->hw_pll_work); -+} - -- ath9k_ps_wakeup(sc); -+static void ath_cancel_work(struct ath_softc *sc) -+{ -+ __ath_cancel_work(sc); -+ cancel_work_sync(&sc->hw_reset_work); -+} - -- spin_lock_bh(&sc->sc_pcu_lock); -+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) -+{ -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ bool ret; - -- /* -- * This is only performed if the channel settings have -- * actually changed. -- * -- * To switch channels clear any pending DMA operations; -- * wait long enough for the RX fifo to drain, reset the -- * hardware at the new frequency, and then re-enable -- * the relevant bits of the h/w. -- */ -- ath9k_hw_disable_interrupts(ah); -- stopped = ath_drain_all_txq(sc, false); -+ ieee80211_stop_queues(sc->hw); - -- if (!ath_stoprecv(sc)) -- stopped = false; -+ sc->hw_busy_count = 0; -+ del_timer_sync(&common->ani.timer); - -- if (!ath9k_hw_check_alive(ah)) -- stopped = false; -+ ath9k_hw_disable_interrupts(ah); - -- /* XXX: do not flush receive queue here. We don't want -- * to flush data frames already in queue because of -- * changing channel. */ -+ ret = ath_drain_all_txq(sc, retry_tx); - -- if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL)) -- fastcc = false; -+ if (!ath_stoprecv(sc)) -+ ret = false; - -- if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) -- caldata = &sc->caldata; -+ if (!flush) { -+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) -+ ath_rx_tasklet(sc, 0, true); -+ ath_rx_tasklet(sc, 0, false); -+ } else { -+ ath_flushrecv(sc); -+ } - -- ath_dbg(common, ATH_DBG_CONFIG, -- "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", -- sc->sc_ah->curchan->channel, -- channel->center_freq, conf_is_ht40(conf), -- fastcc); -+ return ret; -+} - -- r = ath9k_hw_reset(ah, hchan, caldata, fastcc); -- if (r) { -- ath_err(common, -- "Unable to reset channel (%u MHz), reset status %d\n", -- channel->center_freq, r); -- goto ps_restore; -- } -+static bool ath_complete_reset(struct ath_softc *sc, bool start) -+{ -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); - - if (ath_startrecv(sc) != 0) { - ath_err(common, "Unable to restart recv logic\n"); -- r = -EIO; -- goto ps_restore; -+ return false; - } - - ath9k_cmn_update_txpow(ah, sc->curtxpow, -@@ -297,21 +270,93 @@ static int ath_set_channel(struct ath_so - ath9k_hw_set_interrupts(ah, ah->imask); - ath9k_hw_enable_interrupts(ah); - -- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { -+ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) { - if (sc->sc_flags & SC_OP_BEACONS) - ath_set_beacon(sc); -+ - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); - ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); - if (!common->disable_ani) - ath_start_ani(common); - } - -- ps_restore: -- ieee80211_wake_queues(hw); -+ ieee80211_wake_queues(sc->hw); -+ -+ return true; -+} -+ -+static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, -+ bool retry_tx) -+{ -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ath9k_hw_cal_data *caldata = NULL; -+ bool fastcc = true; -+ bool flush = false; -+ int r; -+ -+ __ath_cancel_work(sc); -+ -+ spin_lock_bh(&sc->sc_pcu_lock); - -+ if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) { -+ fastcc = false; -+ caldata = &sc->caldata; -+ } -+ -+ if (!hchan) { -+ fastcc = false; -+ flush = true; -+ hchan = ah->curchan; -+ } -+ -+ if (fastcc && !ath9k_hw_check_alive(ah)) -+ fastcc = false; -+ -+ if (!ath_prepare_reset(sc, retry_tx, flush)) -+ fastcc = false; -+ -+ ath_dbg(common, ATH_DBG_CONFIG, -+ "Reset to %u MHz, HT40: %d fastcc: %d\n", -+ hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS | -+ CHANNEL_HT40PLUS)), -+ fastcc); -+ -+ r = ath9k_hw_reset(ah, hchan, caldata, fastcc); -+ if (r) { -+ ath_err(common, -+ "Unable to reset channel, reset status %d\n", r); -+ goto out; -+ } -+ -+ if (!ath_complete_reset(sc, true)) -+ r = -EIO; -+ -+out: - spin_unlock_bh(&sc->sc_pcu_lock); -+ return r; -+} -+ -+ -+/* -+ * Set/change channels. If the channel is really being changed, it's done -+ * by reseting the chip. To accomplish this we must first cleanup any pending -+ * DMA, then restart stuff. -+*/ -+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, -+ struct ath9k_channel *hchan) -+{ -+ int r; -+ -+ if (sc->sc_flags & SC_OP_INVALID) -+ return -EIO; -+ -+ ath9k_ps_wakeup(sc); -+ -+ r = ath_reset_internal(sc, hchan, false); - - ath9k_ps_restore(sc); -+ - return r; - } - -@@ -824,28 +869,13 @@ static void ath_radio_enable(struct ath_ - channel->center_freq, r); - } - -- ath9k_cmn_update_txpow(ah, sc->curtxpow, -- sc->config.txpowlimit, &sc->curtxpow); -- if (ath_startrecv(sc) != 0) { -- ath_err(common, "Unable to restart recv logic\n"); -- goto out; -- } -- if (sc->sc_flags & SC_OP_BEACONS) -- ath_set_beacon(sc); /* restart beacons */ -- -- /* Re-Enable interrupts */ -- ath9k_hw_set_interrupts(ah, ah->imask); -- ath9k_hw_enable_interrupts(ah); -+ ath_complete_reset(sc, true); - - /* Enable LED */ - ath9k_hw_cfg_output(ah, ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ah->led_pin, 0); - -- ieee80211_wake_queues(hw); -- ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2); -- --out: - spin_unlock_bh(&sc->sc_pcu_lock); - - ath9k_ps_restore(sc); -@@ -858,11 +888,10 @@ void ath_radio_disable(struct ath_softc - int r; - - ath9k_ps_wakeup(sc); -- cancel_delayed_work_sync(&sc->hw_pll_work); - -- spin_lock_bh(&sc->sc_pcu_lock); -+ ath_cancel_work(sc); - -- ieee80211_stop_queues(hw); -+ spin_lock_bh(&sc->sc_pcu_lock); - - /* - * Keep the LED on when the radio is disabled -@@ -873,13 +902,7 @@ void ath_radio_disable(struct ath_softc - ath9k_hw_cfg_gpio_input(ah, ah->led_pin); - } - -- /* Disable interrupts */ -- ath9k_hw_disable_interrupts(ah); -- -- ath_drain_all_txq(sc, false); /* clear pending tx frames */ -- -- ath_stoprecv(sc); /* turn off frame recv */ -- ath_flushrecv(sc); /* flush recv queue */ -+ ath_prepare_reset(sc, false, true); - - if (!ah->curchan) - ah->curchan = ath9k_cmn_get_curchannel(hw, ah); -@@ -901,48 +924,11 @@ void ath_radio_disable(struct ath_softc - - static int ath_reset(struct ath_softc *sc, bool retry_tx) - { -- struct ath_hw *ah = sc->sc_ah; -- struct ath_common *common = ath9k_hw_common(ah); -- struct ieee80211_hw *hw = sc->hw; - int r; - -- sc->hw_busy_count = 0; -- -- /* Stop ANI */ -- -- del_timer_sync(&common->ani.timer); -- - ath9k_ps_wakeup(sc); - -- ieee80211_stop_queues(hw); -- -- ath9k_hw_disable_interrupts(ah); -- ath_drain_all_txq(sc, retry_tx); -- -- ath_stoprecv(sc); -- ath_flushrecv(sc); -- -- r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); -- if (r) -- ath_err(common, -- "Unable to reset hardware; reset status %d\n", r); -- -- if (ath_startrecv(sc) != 0) -- ath_err(common, "Unable to start recv logic\n"); -- -- /* -- * We may be doing a reset in response to a request -- * that changes the channel so update any state that -- * might change as a result. -- */ -- ath9k_cmn_update_txpow(ah, sc->curtxpow, -- sc->config.txpowlimit, &sc->curtxpow); -- -- if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) -- ath_set_beacon(sc); /* restart beacons */ -- -- ath9k_hw_set_interrupts(ah, ah->imask); -- ath9k_hw_enable_interrupts(ah); -+ r = ath_reset_internal(sc, NULL, retry_tx); - - if (retry_tx) { - int i; -@@ -955,12 +941,6 @@ static int ath_reset(struct ath_softc *s - } - } - -- ieee80211_wake_queues(hw); -- -- /* Start ANI */ -- if (!common->disable_ani) -- ath_start_ani(common); -- - ath9k_ps_restore(sc); - - return r; -@@ -970,9 +950,7 @@ void ath_reset_work(struct work_struct * - { - struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); - -- spin_lock_bh(&sc->sc_pcu_lock); - ath_reset(sc, true); -- spin_unlock_bh(&sc->sc_pcu_lock); - } - - void ath_hw_check(struct work_struct *work) -@@ -993,11 +971,8 @@ void ath_hw_check(struct work_struct *wo - ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " - "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); - if (busy >= 99) { -- if (++sc->hw_busy_count >= 3) { -- spin_lock_bh(&sc->sc_pcu_lock); -- ath_reset(sc, true); -- spin_unlock_bh(&sc->sc_pcu_lock); -- } -+ if (++sc->hw_busy_count >= 3) -+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work); - - } else if (busy >= 0) - sc->hw_busy_count = 0; -@@ -1017,9 +992,7 @@ static void ath_hw_pll_rx_hang_check(str - /* Rx is hung for more than 500ms. Reset it */ - ath_dbg(common, ATH_DBG_RESET, - "Possible RX hang, resetting"); -- spin_lock_bh(&sc->sc_pcu_lock); -- ath_reset(sc, true); -- spin_unlock_bh(&sc->sc_pcu_lock); -+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work); - count = 0; - } - } else -@@ -1090,28 +1063,6 @@ static int ath9k_start(struct ieee80211_ - goto mutex_unlock; - } - -- /* -- * This is needed only to setup initial state -- * but it's best done after a reset. -- */ -- ath9k_cmn_update_txpow(ah, sc->curtxpow, -- sc->config.txpowlimit, &sc->curtxpow); -- -- /* -- * Setup the hardware after reset: -- * The receive engine is set going. -- * Frame transmit is handled entirely -- * in the frame output path; there's nothing to do -- * here except setup the interrupt mask. -- */ -- if (ath_startrecv(sc) != 0) { -- ath_err(common, "Unable to start recv logic\n"); -- r = -EIO; -- spin_unlock_bh(&sc->sc_pcu_lock); -- goto mutex_unlock; -- } -- spin_unlock_bh(&sc->sc_pcu_lock); -- - /* Setup our intr mask. */ - ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | - ATH9K_INT_RXORN | ATH9K_INT_FATAL | -@@ -1134,12 +1085,14 @@ static int ath9k_start(struct ieee80211_ - - /* Disable BMISS interrupt when we're not associated */ - ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); -- ath9k_hw_set_interrupts(ah, ah->imask); -- ath9k_hw_enable_interrupts(ah); - -- ieee80211_wake_queues(hw); -+ if (!ath_complete_reset(sc, false)) { -+ r = -EIO; -+ spin_unlock_bh(&sc->sc_pcu_lock); -+ goto mutex_unlock; -+ } - -- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); -+ spin_unlock_bh(&sc->sc_pcu_lock); - - if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && - !ah->btcoex_hw.enabled) { -@@ -1232,11 +1185,7 @@ static void ath9k_stop(struct ieee80211_ - - mutex_lock(&sc->mutex); - -- cancel_delayed_work_sync(&sc->tx_complete_work); -- cancel_delayed_work_sync(&sc->hw_pll_work); -- cancel_work_sync(&sc->paprd_work); -- cancel_work_sync(&sc->hw_check_work); -- cancel_work_sync(&sc->hw_reset_work); -+ ath_cancel_work(sc); - - if (sc->sc_flags & SC_OP_INVALID) { - ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); -@@ -2353,9 +2302,11 @@ static void ath9k_flush(struct ieee80211 - ath9k_ps_wakeup(sc); - spin_lock_bh(&sc->sc_pcu_lock); - drain_txq = ath_drain_all_txq(sc, false); -+ spin_unlock_bh(&sc->sc_pcu_lock); -+ - if (!drain_txq) - ath_reset(sc, false); -- spin_unlock_bh(&sc->sc_pcu_lock); -+ - ath9k_ps_restore(sc); - ieee80211_wake_queues(hw); - |