Revert "ath9k: fix crashes when using shared IRQs"

This backport seems to be incomplete and causing some IRQ related
issues.

This reverts commit r43240

git-svn-id: svn://svn.openwrt.org/openwrt/branches/barrier_breaker@43276 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
nbd 2014-11-15 21:17:21 +00:00
parent fa74ff9964
commit 3818debcd0
11 changed files with 18 additions and 140 deletions

View File

@ -1,38 +1,3 @@
commit 24028dc203af73088ab969c2b4236bf9bee99d85
Author: Felix Fietkau <nbd@openwrt.org>
Date: Thu Nov 13 18:29:26 2014 +0100
ath9k: do not access hardware on IRQs during reset
Instead of killing interrupts during reset when the first one happens,
kill them before issuing the reset.
This fixes an easy to reproduce crash with multiple cards sharing the
same IRQ.
Cc: stable@vger.kernel.org
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
commit 8115a0d774754a1a01feb25fb436832d4f3be41b
Author: Felix Fietkau <nbd@openwrt.org>
Date: Thu Nov 13 18:29:00 2014 +0100
ath9k: set ATH_OP_INVALID before disabling hardware
Closes another small IRQ handler race
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
commit d10478d3983574c2bae11146ef6b01d0103a777d
Author: Felix Fietkau <nbd@openwrt.org>
Date: Thu Nov 13 18:27:47 2014 +0100
ath9k: prevent early IRQs from accessing hardware
IRQs are suppressed if ah == NULL and ATH_OP_INVALID being set in
common->op_flags. Close a short time window between those two.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
commit 77980bee5f1f743b46f8749185aca28b8ec69741
Author: Johannes Berg <johannes.berg@intel.com>
Date: Mon Nov 3 14:29:09 2014 +0100
@ -1723,66 +1688,7 @@ Date: Mon May 19 21:20:49 2014 +0200
ENTRY_DATA_IO_FAILED,
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -582,16 +582,13 @@ irqreturn_t ath_isr(int irq, void *dev)
if (test_bit(ATH_OP_INVALID, &common->op_flags))
return IRQ_NONE;
- /* shared irq, not for us */
+ if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
+ return IRQ_NONE;
+ /* shared irq, not for us */
if (!ath9k_hw_intrpend(ah))
return IRQ_NONE;
- if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) {
- ath9k_hw_kill_interrupts(ah);
- return IRQ_HANDLED;
- }
-
/*
* Figure out the reason(s) for the interrupt. Note
* that the hal returns a pseudo-ISR that may include
@@ -677,8 +674,12 @@ chip_reset:
int ath_reset(struct ath_softc *sc)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int r;
+ ath9k_hw_kill_interrupts(sc->sc_ah);
+ set_bit(ATH_OP_HW_RESET, &common->op_flags);
+
ath9k_ps_wakeup(sc);
r = ath_reset_internal(sc, NULL);
ath9k_ps_restore(sc);
@@ -692,6 +693,7 @@ void ath9k_queue_reset(struct ath_softc
#ifdef CPTCFG_ATH9K_DEBUGFS
RESET_STAT_INC(sc, type);
#endif
+ ath9k_hw_kill_interrupts(sc->sc_ah);
set_bit(ATH_OP_HW_RESET, &common->op_flags);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
@@ -937,6 +939,9 @@ static void ath9k_stop(struct ieee80211_
ah->curchan = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+
+ set_bit(ATH_OP_INVALID, &common->op_flags);
+
ath9k_hw_phy_disable(ah);
ath9k_hw_configpcipowersave(ah, true);
@@ -945,7 +950,6 @@ static void ath9k_stop(struct ieee80211_
ath9k_ps_restore(sc);
- set_bit(ATH_OP_INVALID, &common->op_flags);
sc->ps_idle = prev_idle;
mutex_unlock(&sc->mutex);
@@ -1757,7 +1761,6 @@ out:
@@ -1757,7 +1757,6 @@ out:
void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ath_vif *avp = (void *)vif->drv_priv;
@ -1790,7 +1696,7 @@ Date: Mon May 19 21:20:49 2014 +0200
u32 tsf;
if (!sc->p2p_ps_timer)
@@ -1767,14 +1770,9 @@ void ath9k_update_p2p_ps(struct ath_soft
@@ -1767,14 +1766,9 @@ void ath9k_update_p2p_ps(struct ath_soft
return;
sc->p2p_ps_vif = avp;
@ -1808,7 +1714,7 @@ Date: Mon May 19 21:20:49 2014 +0200
}
static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
@@ -1791,6 +1789,7 @@ static void ath9k_bss_info_changed(struc
@@ -1791,6 +1785,7 @@ static void ath9k_bss_info_changed(struc
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath_vif *avp = (void *)vif->drv_priv;
@ -1816,7 +1722,7 @@ Date: Mon May 19 21:20:49 2014 +0200
int slottime;
ath9k_ps_wakeup(sc);
@@ -1853,7 +1852,10 @@ static void ath9k_bss_info_changed(struc
@@ -1853,7 +1848,10 @@ static void ath9k_bss_info_changed(struc
if (changed & BSS_CHANGED_P2P_PS) {
spin_lock_bh(&sc->sc_pcu_lock);
@ -1828,7 +1734,7 @@ Date: Mon May 19 21:20:49 2014 +0200
spin_unlock_bh(&sc->sc_pcu_lock);
}
@@ -2232,14 +2234,6 @@ static void ath9k_sw_scan_complete(struc
@@ -2232,14 +2230,6 @@ static void ath9k_sw_scan_complete(struc
clear_bit(ATH_OP_SCANNING, &common->op_flags);
}
@ -1843,7 +1749,7 @@ Date: Mon May 19 21:20:49 2014 +0200
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@@ -2287,5 +2281,4 @@ struct ieee80211_ops ath9k_ops = {
@@ -2287,5 +2277,4 @@ struct ieee80211_ops ath9k_ops = {
#endif
.sw_scan_start = ath9k_sw_scan_start,
.sw_scan_complete = ath9k_sw_scan_complete,
@ -3589,31 +3495,3 @@ Date: Mon May 19 21:20:49 2014 +0200
}
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -500,10 +500,14 @@ static int ath9k_init_softc(u16 devid, s
ah->reg_ops.read = ath9k_ioread32;
ah->reg_ops.write = ath9k_iowrite32;
ah->reg_ops.rmw = ath9k_reg_rmw;
- sc->sc_ah = ah;
pCap = &ah->caps;
common = ath9k_hw_common(ah);
+
+ /* Will be cleared in ath9k_start() */
+ set_bit(ATH_OP_INVALID, &common->op_flags);
+
+ sc->sc_ah = ah;
sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
sc->tx99_power = MAX_RATE_POWER + 1;
init_waitqueue_head(&sc->tx_wait);
@@ -787,9 +791,6 @@ int ath9k_init_device(u16 devid, struct
common = ath9k_hw_common(ah);
ath9k_set_hw_capab(sc, hw);
- /* Will be cleared in ath9k_start() */
- set_bit(ATH_OP_INVALID, &common->op_flags);
-
/* Initialize regulatory */
error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
ath9k_reg_notifier);

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -659,6 +659,7 @@ static const struct ieee80211_iface_limi
@@ -655,6 +655,7 @@ static const struct ieee80211_iface_limi
BIT(NL80211_IFTYPE_AP) },
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO) },

View File

@ -81,7 +81,7 @@
struct ath_ops reg_ops;
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -522,6 +522,8 @@ static int ath9k_init_softc(u16 devid, s
@@ -518,6 +518,8 @@ static int ath9k_init_softc(u16 devid, s
ah->is_clk_25mhz = pdata->is_clk_25mhz;
ah->get_mac_revision = pdata->get_mac_revision;
ah->external_reset = pdata->external_reset;

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -905,23 +905,23 @@ static int __init ath9k_init(void)
@@ -904,23 +904,23 @@ static int __init ath9k_init(void)
{
int error;

View File

@ -14,7 +14,7 @@
out:
spin_unlock_bh(&sc->sc_pcu_lock);
@@ -1409,6 +1413,7 @@ static int ath9k_config(struct ieee80211
@@ -1405,6 +1409,7 @@ static int ath9k_config(struct ieee80211
sc->config.txpowlimit = 2 * conf->power_level;
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);

View File

@ -21,7 +21,7 @@
if (ant_gain > max_gain)
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1409,7 +1409,10 @@ static int ath9k_config(struct ieee80211
@@ -1405,7 +1405,10 @@ static int ath9k_config(struct ieee80211
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {

View File

@ -162,7 +162,7 @@
void ath_fill_led_pin(struct ath_softc *sc)
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -816,7 +816,7 @@ int ath9k_init_device(u16 devid, struct
@@ -815,7 +815,7 @@ int ath9k_init_device(u16 devid, struct
#ifdef CPTCFG_MAC80211_LEDS
/* must be initialized before ieee80211_register_hw */

View File

@ -125,7 +125,7 @@
REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -603,6 +603,11 @@ irqreturn_t ath_isr(int irq, void *dev)
@@ -606,6 +606,11 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_debug_sync_cause(sc, sync_cause);
status &= ah->imask; /* discard unasked-for bits */

View File

@ -58,7 +58,7 @@
};
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -522,6 +522,8 @@ static int ath9k_init_softc(u16 devid, s
@@ -518,6 +518,8 @@ static int ath9k_init_softc(u16 devid, s
ah->is_clk_25mhz = pdata->is_clk_25mhz;
ah->get_mac_revision = pdata->get_mac_revision;
ah->external_reset = pdata->external_reset;

View File

@ -55,7 +55,7 @@
ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -650,7 +650,8 @@ static void ath9k_init_txpower_limits(st
@@ -646,7 +646,8 @@ static void ath9k_init_txpower_limits(st
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
@ -65,7 +65,7 @@
}
static const struct ieee80211_iface_limit if_limits[] = {
@@ -778,6 +779,18 @@ static void ath9k_set_hw_capab(struct at
@@ -774,6 +775,18 @@ static void ath9k_set_hw_capab(struct at
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
}
@ -84,7 +84,7 @@
int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
@@ -823,6 +836,8 @@ int ath9k_init_device(u16 devid, struct
@@ -822,6 +835,8 @@ int ath9k_init_device(u16 devid, struct
ARRAY_SIZE(ath9k_tpt_blink));
#endif

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -625,8 +625,7 @@ irqreturn_t ath_isr(int irq, void *dev)
@@ -628,8 +628,7 @@ irqreturn_t ath_isr(int irq, void *dev)
* If a FATAL or RXORN interrupt is received, we have to reset the
* chip immediately.
*/