X-Git-Url: https://git.archive.openwrt.org/?p=openwrt.git;a=blobdiff_plain;f=package%2Fkernel%2Fmac80211%2Fpatches%2F300-pending_work.patch;h=548f3040248377d8826a35a89e669ac767a92178;hp=b0037da71c70ddac45ef3184aa02e892951d5ab9;hb=b5cc8e51ffb83c08d74d203534c68bdcd8156c36;hpb=83f3a178a32f736e5d67ea014b774a61b0a3a5e9 diff --git a/package/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch index b0037da71c..548f304024 100644 --- a/package/kernel/mac80211/patches/300-pending_work.patch +++ b/package/kernel/mac80211/patches/300-pending_work.patch @@ -1,3 +1,206 @@ +commit 31959d8df39319e32c6d5ba9c135727be90cfad7 +Author: Michal Kazior +Date: Fri Mar 7 08:09:38 2014 +0100 + + mac80211: fix possible NULL dereference + + If chanctx is missing on a given vif then the band + is assumed to be 2GHz. However if hw doesn't + support 2GHz band then mac80211 ended up with a + NULL dereference. + + This fixes a splat: + + [ 4605.207223] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 + [ 4605.210789] IP: [] ieee80211_parse_bitrates+0x65/0x110 [mac80211] + + The splat was preceeded by WARN_ON(!chanctx_conf) + in ieee80211_get_sdata_band(). + + Signed-off-by: Michal Kazior + +commit 6c5a3ffa0a2d22c091a2717f427259bacf77ac5e +Author: Michael Braun +Date: Thu Mar 6 15:08:43 2014 +0100 + + mac80211: fix WPA with VLAN on AP side with ps-sta again + + commit de74a1d9032f4d37ea453ad2a647e1aff4cd2591 + "mac80211: fix WPA with VLAN on AP side with ps-sta" + fixed an issue where queued multicast packets would + be sent out encrypted with the key of an other bss. + + commit "7cbf9d017dbb5e3276de7d527925d42d4c11e732" + "mac80211: fix oops on mesh PS broadcast forwarding" + essentially reverted it, because vif.type cannot be AP_VLAN + due to the check to vif.type in ieee80211_get_buffered_bc before. + + As the later commit intended to fix the MESH case, fix it + by checking for IFTYPE_AP instead of IFTYPE_AP_VLAN. + + Fixes: 7cbf9d017dbb + Cc: # 3.10.x + Cc: # 3.11.x + Cc: # 3.12.x + Cc: # 3.13.x + Cc: + Cc: + Signed-off-by: Michael Braun + +commit 9d6ab9bdb9b368a6cf9519f0f92509b5b2c297ec +Author: Johannes Berg +Date: Mon Mar 3 14:19:08 2014 +0100 + + cfg80211: remove racy beacon_interval assignment + + In case of AP mode, the beacon interval is already reset to + zero inside cfg80211_stop_ap(), and in the other modes it + isn't relevant. Remove the assignment to remove a potential + race since the assignment isn't properly locked. + + Reported-by: Michal Kazior + Signed-off-by: Johannes Berg + +commit 1abdeca3c6fb9cf1f84f85e78ed8d1c33bd69db0 +Author: Felix Fietkau +Date: Fri Feb 28 18:52:56 2014 +0100 + + ath9k_hw: tweak noise immunity thresholds for older chipsets + + Older chipsets are more sensitive to high PHY error counts, and the + current noise immunity thresholds were based on tests run at QCA with + newer chipsets. + + This patch brings back the values from the old ANI implementation for + old chipsets, and it also disables weak signal detection on an earlier + noise immunity level, to improve overall radio stability on affected + devices. + + Signed-off-by: Felix Fietkau + +commit 431e506da5953adc3b65af25f4b90873d528c115 +Author: Felix Fietkau +Date: Fri Feb 28 18:44:13 2014 +0100 + + ath9k_hw: toggle weak signal detection in AP mode on older chipsets + + The commit 80b4205b "ath9k: Fix OFDM weak signal detection for AP mode" + prevented weak signal detection changes from taking effect in AP mode on + all chipsets, claiming it is "not allowed". + + The main reason for not disabling weak signal detection in AP mode is + that typically beacon RSSI is used to track whether it is needed to + boost range, and this is unavailable in AP mode for obvious reasons. + + The problem with not disabling weak signal detection is that older + chipsets are very sensitive to high PHY error counts. When faced with + heavy noise, this can lead to an excessive amount of "Failed to stop + TX DMA" errors in the field. + + Signed-off-by: Felix Fietkau + +commit 98d1a6c5b14688ed030e81b889f607be308e0df9 +Author: Felix Fietkau +Date: Mon Feb 24 22:20:32 2014 +0100 + + ath9k: fix invalid descriptor discarding + + Only set sc->rx.discard_next to rx_stats->rs_more when actually + discarding the current descriptor. + + Also, fix a detection of broken descriptors: + First the code checks if the current descriptor is not done. + Then it checks if the next descriptor is done. + Add a check that afterwards checks the first descriptor again, because + it might have been completed in the mean time. + + This fixes a regression introduced in + commit 723e711356b5a8a95728a890e254e8b0d47b55cf + "ath9k: fix handling of broken descriptors" + + Cc: stable@vger.kernel.org + Reported-by: Marco André Dinis + Signed-off-by: Felix Fietkau + +commit 52a46300e782fe6994466523eb2b0b59091ea59f +Author: Felix Fietkau +Date: Mon Feb 24 11:43:50 2014 +0100 + + ath9k: reduce baseband hang detection false positive rate + + Check if the baseband state remains stable, and add a small delay + between register reads. + + Signed-off-by: Felix Fietkau + +commit 118945bb12082e9d4edddc868d88143164e0f440 +Author: Felix Fietkau +Date: Sat Feb 22 14:55:23 2014 +0100 + + ath5k: set SURVEY_INFO_IN_USE on get_survey + + Only one channel is returned - the one currently being used. + + Signed-off-by: Felix Fietkau + +commit ee41f72476e1ea44283dfe1cbf75b9543a1e15c8 +Author: Felix Fietkau +Date: Sat Feb 22 14:44:52 2014 +0100 + + ath9k: make some hardware reset log messages debug-only + + On some chips, baseband watchdog hangs are more common than others, and + the driver has support for handling them. + Interrupts even after a watchdog hang are also quite common, so there's + not much point in spamming the user's logfiles. + + Signed-off-by: Felix Fietkau + +commit b14fbb554fc65a2e0b5c41a319269b0350f187e7 +Author: Felix Fietkau +Date: Sat Feb 22 14:35:25 2014 +0100 + + ath9k: do not set half/quarter channel flags in AR_PHY_MODE + + 5/10 MHz channel bandwidth is configured via the PLL clock, instead of + the AR_PHY_MODE register. Using that register is AR93xx specific, and + makes the mode incompatible with earlier chipsets. + + In some early versions, these flags were apparently applied at the wrong + point in time and thus did not cause connectivity issues, however now + they are causing problems, as pointed out in this OpenWrt ticket: + + https://dev.openwrt.org/ticket/14916 + + Signed-off-by: Felix Fietkau + +commit 0f1cb7be2551b30b02cd54c897e0e29e483cfda5 +Author: Felix Fietkau +Date: Sat Feb 22 13:43:29 2014 +0100 + + ath9k: fix ps-poll responses under a-mpdu sessions + + When passing tx frames to the U-APSD queue for powersave poll responses, + the ath_atx_tid pointer needs to be passed to ath_tx_setup_buffer for + proper sequence number accounting. + + This fixes high latency and connection stability issues with ath9k + running as AP and a few kinds of mobile phones as client, when PS-Poll + is heavily used + + Cc: stable@vger.kernel.org + Signed-off-by: Felix Fietkau + +commit d5d87a37bbd6066b2c3c5d0bd0fe2a6e2ea45cc5 +Author: Felix Fietkau +Date: Fri Feb 21 11:39:59 2014 +0100 + + ath9k: list more reset causes in debugfs + + Number of MAC hangs and stuck beacons were missing + + Signed-off-by: Felix Fietkau + commit d84856012e0f10fe598a5ad3b7b869397a089e07 Author: Johannes Berg Date: Thu Feb 20 11:19:58 2014 +0100 @@ -985,7 +1188,39 @@ Date: Thu Jan 23 20:06:34 2014 +0100 else udelay(100); -@@ -2051,9 +2051,8 @@ static bool ath9k_hw_set_power_awake(str +@@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav); + bool ath9k_hw_check_alive(struct ath_hw *ah) + { + int count = 50; +- u32 reg; ++ u32 reg, last_val; + + if (AR_SREV_9300(ah)) + return !ath9k_hw_detect_mac_hang(ah); +@@ -1542,9 +1542,13 @@ bool ath9k_hw_check_alive(struct ath_hw + if (AR_SREV_9285_12_OR_LATER(ah)) + return true; + ++ last_val = REG_READ(ah, AR_OBS_BUS_1); + do { + reg = REG_READ(ah, AR_OBS_BUS_1); ++ if (reg != last_val) ++ return true; + ++ last_val = reg; + if ((reg & 0x7E7FFFEF) == 0x00702400) + continue; + +@@ -1556,6 +1560,8 @@ bool ath9k_hw_check_alive(struct ath_hw + default: + return true; + } ++ ++ udelay(1); + } while (count-- > 0); + + return false; +@@ -2051,9 +2057,8 @@ static bool ath9k_hw_set_power_awake(str REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); @@ -998,6 +1233,33 @@ Date: Thu Jan 23 20:06:34 2014 +0100 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -451,7 +451,7 @@ void ath9k_tasklet(unsigned long data) + * interrupts are enabled in the reset routine. + */ + atomic_inc(&ah->intr_ref_cnt); +- ath_dbg(common, ANY, "FATAL: Skipping interrupts\n"); ++ ath_dbg(common, RESET, "FATAL: Skipping interrupts\n"); + goto out; + } + +@@ -471,7 +471,7 @@ void ath9k_tasklet(unsigned long data) + * interrupts are enabled in the reset routine. + */ + atomic_inc(&ah->intr_ref_cnt); +- ath_dbg(common, ANY, ++ ath_dbg(common, RESET, + "BB_WATCHDOG: Skipping interrupts\n"); + goto out; + } +@@ -484,7 +484,7 @@ void ath9k_tasklet(unsigned long data) + type = RESET_TYPE_TX_GTT; + ath9k_queue_reset(sc, type); + atomic_inc(&ah->intr_ref_cnt); +- ath_dbg(common, ANY, ++ ath_dbg(common, RESET, + "GTT: Skipping interrupts\n"); + goto out; + } @@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str static bool ath9k_has_tx_pending(struct ath_softc *sc) @@ -1288,7 +1550,17 @@ Date: Thu Jan 23 20:06:34 2014 +0100 __sta_info_flush(sdata, true); ieee80211_free_keys(sdata, true); -@@ -2638,6 +2643,24 @@ static int ieee80211_start_roc_work(stru +@@ -1988,6 +1993,9 @@ static int ieee80211_change_bss(struct w + + band = ieee80211_get_sdata_band(sdata); + ++ if (WARN_ON(!wiphy->bands[band])) ++ return -EINVAL; ++ + if (params->use_cts_prot >= 0) { + sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; + changed |= BSS_CHANGED_ERP_CTS_PROT; +@@ -2638,6 +2646,24 @@ static int ieee80211_start_roc_work(stru INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); INIT_LIST_HEAD(&roc->dependents); @@ -1313,7 +1585,7 @@ Date: Thu Jan 23 20:06:34 2014 +0100 /* if there's one pending or we're scanning, queue this one */ if (!list_empty(&local->roc_list) || local->scanning || local->radar_detect_enabled) -@@ -2772,24 +2795,6 @@ static int ieee80211_start_roc_work(stru +@@ -2772,24 +2798,6 @@ static int ieee80211_start_roc_work(stru if (!queued) list_add_tail(&roc->list, &local->roc_list); @@ -1338,7 +1610,7 @@ Date: Thu Jan 23 20:06:34 2014 +0100 return 0; } -@@ -3004,8 +3009,10 @@ void ieee80211_csa_finalize_work(struct +@@ -3004,8 +3012,10 @@ void ieee80211_csa_finalize_work(struct if (!ieee80211_sdata_running(sdata)) goto unlock; @@ -1350,7 +1622,7 @@ Date: Thu Jan 23 20:06:34 2014 +0100 err = ieee80211_vif_change_channel(sdata, &changed); mutex_unlock(&local->mtx); if (WARN_ON(err < 0)) -@@ -3022,13 +3029,13 @@ void ieee80211_csa_finalize_work(struct +@@ -3022,13 +3032,13 @@ void ieee80211_csa_finalize_work(struct switch (sdata->vif.type) { case NL80211_IFTYPE_AP: err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); @@ -1367,7 +1639,7 @@ Date: Thu Jan 23 20:06:34 2014 +0100 ieee80211_bss_info_change_notify(sdata, err); break; case NL80211_IFTYPE_ADHOC: -@@ -3066,7 +3073,7 @@ int ieee80211_channel_switch(struct wiph +@@ -3066,7 +3076,7 @@ int ieee80211_channel_switch(struct wiph struct ieee80211_if_mesh __maybe_unused *ifmsh; int err, num_chanctx; @@ -1607,6 +1879,15 @@ Date: Thu Jan 23 20:06:34 2014 +0100 return 0; } +@@ -2900,7 +2912,7 @@ ieee80211_get_buffered_bc(struct ieee802 + cpu_to_le16(IEEE80211_FCTL_MOREDATA); + } + +- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ++ if (sdata->vif.type == NL80211_IFTYPE_AP) + sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); + if (!ieee80211_tx_prepare(sdata, &tx, skb)) + break; --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -499,7 +499,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee @@ -1658,7 +1939,16 @@ Date: Thu Jan 23 20:06:34 2014 +0100 /* * There are major locking problems in nl80211/mac80211 for CSA, * disable for all drivers until this has been reworked. -@@ -875,8 +875,11 @@ static int cfg80211_netdev_notifier_call +@@ -795,8 +795,6 @@ void cfg80211_leave(struct cfg80211_regi + default: + break; + } +- +- wdev->beacon_interval = 0; + } + + static int cfg80211_netdev_notifier_call(struct notifier_block *nb, +@@ -875,8 +873,11 @@ static int cfg80211_netdev_notifier_call break; case NETDEV_DOWN: cfg80211_update_iface_num(rdev, wdev->iftype, -1); @@ -2991,6 +3281,24 @@ Date: Thu Jan 23 20:06:34 2014 +0100 buffered = ath_tid_has_buffered(tid); tid->sched = false; +@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw + txq->stopped = true; + } + ++ if (txctl->an) ++ tid = ath_get_skb_tid(sc, txctl->an, skb); ++ + if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) { + ath_txq_unlock(sc, txq); + txq = sc->tx.uapsdq; + ath_txq_lock(sc, txq); + } else if (txctl->an && + ieee80211_is_data_present(hdr->frame_control)) { +- tid = ath_get_skb_tid(sc, txctl->an, skb); +- + WARN_ON(tid->ac->txq != txctl->txq); + + if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -943,6 +943,7 @@ static void ath9k_set_hw_capab(struct at @@ -3236,3 +3544,257 @@ Date: Thu Jan 23 20:06:34 2014 +0100 treatment == REG_REQ_ALREADY_SET) return; schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -866,6 +866,12 @@ static ssize_t read_file_reset(struct fi + "%17s: %2d\n", "PLL RX Hang", + sc->debug.stats.reset[RESET_TYPE_PLL_HANG]); + len += scnprintf(buf + len, sizeof(buf) - len, ++ "%17s: %2d\n", "MAC Hang", ++ sc->debug.stats.reset[RESET_TYPE_MAC_HANG]); ++ len += scnprintf(buf + len, sizeof(buf) - len, ++ "%17s: %2d\n", "Stuck Beacon", ++ sc->debug.stats.reset[RESET_TYPE_BEACON_STUCK]); ++ len += scnprintf(buf + len, sizeof(buf) - len, + "%17s: %2d\n", "MCI Reset", + sc->debug.stats.reset[RESET_TYPE_MCI]); + +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -868,10 +868,6 @@ static void ar9003_hw_set_rfmode(struct + + if (IS_CHAN_A_FAST_CLOCK(ah, chan)) + rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); +- if (IS_CHAN_QUARTER_RATE(chan)) +- rfMode |= AR_PHY_MODE_QUARTER; +- if (IS_CHAN_HALF_RATE(chan)) +- rfMode |= AR_PHY_MODE_HALF; + + if (rfMode & (AR_PHY_MODE_QUARTER | AR_PHY_MODE_HALF)) + REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -706,6 +706,7 @@ ath5k_get_survey(struct ieee80211_hw *hw + survey->channel = conf->chandef.chan; + survey->noise = ah->ah_noise_floor; + survey->filled = SURVEY_INFO_NOISE_DBM | ++ SURVEY_INFO_IN_USE | + SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_RX | +--- a/drivers/net/wireless/ath/ath9k/recv.c ++++ b/drivers/net/wireless/ath/ath9k/recv.c +@@ -732,11 +732,18 @@ static struct ath_rxbuf *ath_get_next_rx + return NULL; + + /* +- * mark descriptor as zero-length and set the 'more' +- * flag to ensure that both buffers get discarded ++ * Re-check previous descriptor, in case it has been filled ++ * in the mean time. + */ +- rs->rs_datalen = 0; +- rs->rs_more = true; ++ ret = ath9k_hw_rxprocdesc(ah, ds, rs); ++ if (ret == -EINPROGRESS) { ++ /* ++ * mark descriptor as zero-length and set the 'more' ++ * flag to ensure that both buffers get discarded ++ */ ++ rs->rs_datalen = 0; ++ rs->rs_more = true; ++ } + } + + list_del(&bf->list); +@@ -985,32 +992,32 @@ static int ath9k_rx_skb_preprocess(struc + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_hdr *hdr; + bool discard_current = sc->rx.discard_next; +- int ret = 0; + + /* + * Discard corrupt descriptors which are marked in + * ath_get_next_rx_buf(). + */ +- sc->rx.discard_next = rx_stats->rs_more; + if (discard_current) +- return -EINVAL; ++ goto corrupt; ++ ++ sc->rx.discard_next = false; + + /* + * Discard zero-length packets. + */ + if (!rx_stats->rs_datalen) { + RX_STAT_INC(rx_len_err); +- return -EINVAL; ++ goto corrupt; + } + +- /* +- * rs_status follows rs_datalen so if rs_datalen is too large +- * we can take a hint that hardware corrupted it, so ignore +- * those frames. +- */ ++ /* ++ * rs_status follows rs_datalen so if rs_datalen is too large ++ * we can take a hint that hardware corrupted it, so ignore ++ * those frames. ++ */ + if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) { + RX_STAT_INC(rx_len_err); +- return -EINVAL; ++ goto corrupt; + } + + /* Only use status info from the last fragment */ +@@ -1024,10 +1031,8 @@ static int ath9k_rx_skb_preprocess(struc + * This is different from the other corrupt descriptor + * condition handled above. + */ +- if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) { +- ret = -EINVAL; +- goto exit; +- } ++ if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) ++ goto corrupt; + + hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len); + +@@ -1043,18 +1048,15 @@ static int ath9k_rx_skb_preprocess(struc + if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime)) + RX_STAT_INC(rx_spectral); + +- ret = -EINVAL; +- goto exit; ++ return -EINVAL; + } + + /* + * everything but the rate is checked here, the rate check is done + * separately to avoid doing two lookups for a rate for each frame. + */ +- if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) { +- ret = -EINVAL; +- goto exit; +- } ++ if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) ++ return -EINVAL; + + if (ath_is_mybeacon(common, hdr)) { + RX_STAT_INC(rx_beacons); +@@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struc + /* + * This shouldn't happen, but have a safety check anyway. + */ +- if (WARN_ON(!ah->curchan)) { +- ret = -EINVAL; +- goto exit; +- } ++ if (WARN_ON(!ah->curchan)) ++ return -EINVAL; + +- if (ath9k_process_rate(common, hw, rx_stats, rx_status)) { +- ret =-EINVAL; +- goto exit; +- } ++ if (ath9k_process_rate(common, hw, rx_stats, rx_status)) ++ return -EINVAL; + + ath9k_process_rssi(common, hw, rx_stats, rx_status); + +@@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struc + sc->rx.num_pkts++; + #endif + +-exit: +- sc->rx.discard_next = false; +- return ret; ++ return 0; ++ ++corrupt: ++ sc->rx.discard_next = rx_stats->rs_more; ++ return -EINVAL; + } + + static void ath9k_rx_skb_postprocess(struct ath_common *common, +--- a/drivers/net/wireless/ath/ath9k/ani.c ++++ b/drivers/net/wireless/ath/ath9k/ani.c +@@ -176,16 +176,26 @@ static void ath9k_hw_set_ofdm_nil(struct + if (ah->opmode == NL80211_IFTYPE_STATION && + BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH) + weak_sig = true; +- + /* +- * OFDM Weak signal detection is always enabled for AP mode. ++ * Newer chipsets are better at dealing with high PHY error counts - ++ * keep weak signal detection enabled when no RSSI threshold is ++ * available to determine if it is needed (mode != STA) + */ +- if (ah->opmode != NL80211_IFTYPE_AP && +- aniState->ofdmWeakSigDetect != weak_sig) { +- ath9k_hw_ani_control(ah, +- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, +- entry_ofdm->ofdm_weak_signal_on); +- } ++ else if (AR_SREV_9300_20_OR_LATER(ah) && ++ ah->opmode != NL80211_IFTYPE_STATION) ++ weak_sig = true; ++ ++ /* Older chipsets are more sensitive to high PHY error counts */ ++ else if (!AR_SREV_9300_20_OR_LATER(ah) && ++ aniState->ofdmNoiseImmunityLevel >= 8) ++ weak_sig = false; ++ ++ if (aniState->ofdmWeakSigDetect != weak_sig) ++ ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, ++ weak_sig); ++ ++ if (!AR_SREV_9300_20_OR_LATER(ah)) ++ return; + + if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) { + ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; +@@ -483,10 +493,17 @@ void ath9k_hw_ani_init(struct ath_hw *ah + + ath_dbg(common, ANI, "Initialize ANI\n"); + +- ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; +- ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW; +- ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH; +- ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW; ++ if (AR_SREV_9300_20_OR_LATER(ah)) { ++ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; ++ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW; ++ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH; ++ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW; ++ } else { ++ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; ++ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD; ++ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD; ++ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD; ++ } + + ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; + ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; +--- a/drivers/net/wireless/ath/ath9k/ani.h ++++ b/drivers/net/wireless/ath/ath9k/ani.h +@@ -22,12 +22,16 @@ + /* units are errors per second */ + #define ATH9K_ANI_OFDM_TRIG_HIGH 3500 + #define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000 ++#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500 + + #define ATH9K_ANI_OFDM_TRIG_LOW 400 + #define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900 ++#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200 + + #define ATH9K_ANI_CCK_TRIG_HIGH 600 ++#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200 + #define ATH9K_ANI_CCK_TRIG_LOW 300 ++#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100 + + #define ATH9K_ANI_SPUR_IMMUNE_LVL 3 + #define ATH9K_ANI_FIRSTEP_LVL 2