X-Git-Url: https://git.archive.openwrt.org/?p=openwrt.git;a=blobdiff_plain;f=package%2Fkernel%2Fmac80211%2Fpatches%2F300-pending_work.patch;h=15c04cd6aa5402180eabc6deff49602142a89cde;hp=b3986cfa4085d2b1707938d6dc2739c5a66c6872;hb=48198491496a719dab3d0a0d6cb54153a7682898;hpb=65c7813eae09a183e5554af204b71562900925d2 diff --git a/package/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch index b3986cfa40..15c04cd6aa 100644 --- a/package/kernel/mac80211/patches/300-pending_work.patch +++ b/package/kernel/mac80211/patches/300-pending_work.patch @@ -1,3 +1,188 @@ +commit 8d804f1af11e4e058b1e8453327777d73a585cb8 +Author: Felix Fietkau +Date: Sun Mar 9 11:25:43 2014 +0100 + + ath9k: clean up and enhance ANI debugfs file + + Unify scnprintf calls and include the current OFDM/CCK immunity level. + + Signed-off-by: Felix Fietkau + +commit 22e298b5a3a8a49e33805d4e351965123dede35b +Author: Felix Fietkau +Date: Sun Mar 9 10:58:47 2014 +0100 + + ath9k: fix ready time of the multicast buffer queue + + qi->tqi_readyTime is written directly to registers that expect + microseconds as unit instead of TU. + When setting the CABQ ready time, cur_conf->beacon_interval is in TU, so + convert it to microseconds before passing it to ath9k_hw. + + This should hopefully fix some Tx DMA issues with buffered multicast + frames in AP mode. + + Cc: stable@vger.kernel.org + Signed-off-by: Felix Fietkau + +commit fcb064fdd5a27bec8d24099bc0172468f34c97cb +Author: Felix Fietkau +Date: Sun Mar 9 09:43:09 2014 +0100 + + ath9k_hw: fix unreachable code in baseband hang detection code + + The commit "ath9k: reduce baseband hang detection false positive rate" + added a delay in the loop checking the baseband state, however it was + unreachable due to previous 'continue' statements. + + Reported-by: Dan Carpenter + Signed-off-by: Felix Fietkau + +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 @@ -1043,7 +1228,31 @@ 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,14 @@ 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; + ++ udelay(1); ++ last_val = reg; + if ((reg & 0x7E7FFFEF) == 0x00702400) + continue; + +@@ -2051,9 +2056,8 @@ static bool ath9k_hw_set_power_awake(str REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); @@ -1373,7 +1582,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); @@ -1398,7 +1617,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); @@ -1423,7 +1642,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; @@ -1435,7 +1654,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); @@ -1452,7 +1671,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; @@ -1692,6 +1911,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 @@ -1743,7 +1971,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); @@ -3076,6 +3313,15 @@ Date: Thu Jan 23 20:06:34 2014 +0100 buffered = ath_tid_has_buffered(tid); tid->sched = false; +@@ -1696,7 +1698,7 @@ int ath_cabq_update(struct ath_softc *sc + + ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); + +- qi.tqi_readyTime = (cur_conf->beacon_interval * ++ qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) * + ATH_CABQ_READY_TIME) / 100; + ath_txq_update(sc, qnum, &qi); + @@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw txq->stopped = true; } @@ -3341,7 +3587,79 @@ Date: Thu Jan 23 20:06:34 2014 +0100 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 +@@ -138,43 +138,41 @@ static ssize_t read_file_ani(struct file + unsigned int len = 0, size = 1024; + ssize_t retval = 0; + char *buf; ++ int i; ++ struct { ++ const char *name; ++ unsigned int val; ++ } ani_info[] = { ++ { "ANI RESET", ah->stats.ast_ani_reset }, ++ { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel }, ++ { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel }, ++ { "SPUR UP", ah->stats.ast_ani_spurup }, ++ { "SPUR DOWN", ah->stats.ast_ani_spurup }, ++ { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon }, ++ { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff }, ++ { "MRC-CCK ON", ah->stats.ast_ani_ccklow }, ++ { "MRC-CCK OFF", ah->stats.ast_ani_cckhigh }, ++ { "FIR-STEP UP", ah->stats.ast_ani_stepup }, ++ { "FIR-STEP DOWN", ah->stats.ast_ani_stepdown }, ++ { "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero }, ++ { "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs }, ++ { "CCK ERRORS", ah->stats.ast_ani_cckerrs }, ++ }; + + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + +- if (common->disable_ani) { +- len += scnprintf(buf + len, size - len, "%s: %s\n", +- "ANI", "DISABLED"); ++ len += scnprintf(buf + len, size - len, "%15s: %s\n", "ANI", ++ common->disable_ani ? "DISABLED" : "ENABLED"); ++ ++ if (common->disable_ani) + goto exit; +- } + +- len += scnprintf(buf + len, size - len, "%15s: %s\n", +- "ANI", "ENABLED"); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "ANI RESET", ah->stats.ast_ani_reset); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "SPUR UP", ah->stats.ast_ani_spurup); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "SPUR DOWN", ah->stats.ast_ani_spurup); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "MRC-CCK ON", ah->stats.ast_ani_ccklow); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "MRC-CCK OFF", ah->stats.ast_ani_cckhigh); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "FIR-STEP UP", ah->stats.ast_ani_stepup); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "FIR-STEP DOWN", ah->stats.ast_ani_stepdown); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs); +- len += scnprintf(buf + len, size - len, "%15s: %u\n", +- "CCK ERRORS", ah->stats.ast_ani_cckerrs); ++ for (i = 0; i < ARRAY_SIZE(ani_info); i++) ++ len += scnprintf(buf + len, size - len, "%15s: %u\n", ++ ani_info[i].name, ani_info[i].val); ++ + exit: + if (len > size) + len = size; +@@ -866,6 +864,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, @@ -3367,3 +3685,229 @@ Date: Thu Jan 23 20:06:34 2014 +0100 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