diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 8d49d7ee91..40f08e218c 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -10,11 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 -PKG_VERSION:=2014-01-23.1 -PKG_RELEASE:=4 +PKG_VERSION:=2014-03-31 +PKG_RELEASE:=1 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources PKG_BACKPORT_VERSION:= -PKG_MD5SUM:=8db16edbdaf4abc2e9c2f3b6c86736a6 +PKG_MD5SUM:=8b5cf82d6defc5867511014af4afc0b6 PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION) diff --git a/package/kernel/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch b/package/kernel/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch index 584fb05ff5..8d97224a6a 100644 --- a/package/kernel/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch +++ b/package/kernel/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch @@ -18,8 +18,8 @@ Signed-off-by: Hauke Mehrtens --- a/backport-include/backport/leds-disabled.h +++ b/backport-include/backport/leds-disabled.h -@@ -163,6 +163,19 @@ static inline void led_trigger_event(str - enum led_brightness event) +@@ -176,6 +176,19 @@ static inline void led_trigger_blink_one + int invert) { } + diff --git a/package/kernel/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch b/package/kernel/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch index 5ee2d14b18..55bffbc451 100644 --- a/package/kernel/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch +++ b/package/kernel/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch @@ -32,10 +32,10 @@ Signed-off-by: Luis R. Rodriguez + units = $7 sub(/\)/, "", units) sub(/,/, "", units) - if (units == "mW") { -@@ -80,7 +77,7 @@ function parse_reg_rule() - } - } + dfs_cac = $9 +@@ -86,7 +83,7 @@ function parse_reg_rule() + sub(/\(/, "", dfs_cac) + sub(/\)/, "", dfs_cac) flagstr = "" - for (i=8; i<=NF; i++) + for (i=7; i<=NF; i++) diff --git a/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch index f4b9470627..95f14f436e 100644 --- a/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch +++ b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch @@ -1,6 +1,6 @@ --- a/.local-symbols +++ b/.local-symbols -@@ -379,42 +379,6 @@ USB_CDC_PHONET= +@@ -402,42 +402,6 @@ USB_CDC_PHONET= USB_IPHETH= USB_SIERRA_NET= USB_VL600= diff --git a/package/kernel/mac80211/patches/100-revert_aes_ccm_port.patch b/package/kernel/mac80211/patches/100-revert_aes_ccm_port.patch index 4654bc8ea4..ac7d6b3495 100644 --- a/package/kernel/mac80211/patches/100-revert_aes_ccm_port.patch +++ b/package/kernel/mac80211/patches/100-revert_aes_ccm_port.patch @@ -1,3 +1,104 @@ +--- a/net/mac80211/wpa.c ++++ b/net/mac80211/wpa.c +@@ -301,15 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee + } + + +-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) ++static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, ++ int encrypted) + { + __le16 mask_fc; + int a4_included, mgmt; + u8 qos_tid; +- u16 len_a; ++ u8 *b_0, *aad; ++ u16 data_len, len_a; + unsigned int hdrlen; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + ++ memset(scratch, 0, 6 * AES_BLOCK_SIZE); ++ ++ b_0 = scratch + 3 * AES_BLOCK_SIZE; ++ aad = scratch + 4 * AES_BLOCK_SIZE; ++ + /* + * Mask FC: zero subtype b4 b5 b6 (if not mgmt) + * Retry, PwrMgt, MoreData; set Protected +@@ -331,21 +338,20 @@ static void ccmp_special_blocks(struct s + else + qos_tid = 0; + +- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC +- * mode authentication are not allowed to collide, yet both are derived +- * from this vector b_0. We only set L := 1 here to indicate that the +- * data size can be represented in (L+1) bytes. The CCM layer will take +- * care of storing the data length in the top (L+1) bytes and setting +- * and clearing the other bits as is required to derive the two IVs. +- */ +- b_0[0] = 0x1; ++ data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN; ++ if (encrypted) ++ data_len -= IEEE80211_CCMP_MIC_LEN; + ++ /* First block, b_0 */ ++ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ + /* Nonce: Nonce Flags | A2 | PN + * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) + */ + b_0[1] = qos_tid | (mgmt << 4); + memcpy(&b_0[2], hdr->addr2, ETH_ALEN); + memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); ++ /* l(m) */ ++ put_unaligned_be16(data_len, &b_0[14]); + + /* AAD (extra authenticate-only data) / masked 802.11 header + * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ +@@ -401,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8 + u8 *pos; + u8 pn[6]; + u64 pn64; +- u8 aad[2 * AES_BLOCK_SIZE]; +- u8 b_0[AES_BLOCK_SIZE]; ++ u8 scratch[6 * AES_BLOCK_SIZE]; + + if (info->control.hw_key && + !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && +@@ -455,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8 + return 0; + + pos += IEEE80211_CCMP_HDR_LEN; +- ccmp_special_blocks(skb, pn, b_0, aad); +- ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, +- skb_put(skb, IEEE80211_CCMP_MIC_LEN)); ++ ccmp_special_blocks(skb, pn, scratch, 0); ++ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, ++ pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN)); + + return 0; + } +@@ -520,16 +525,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee + } + + if (!(status->flag & RX_FLAG_DECRYPTED)) { +- u8 aad[2 * AES_BLOCK_SIZE]; +- u8 b_0[AES_BLOCK_SIZE]; ++ u8 scratch[6 * AES_BLOCK_SIZE]; + /* hardware didn't decrypt/verify MIC */ +- ccmp_special_blocks(skb, pn, b_0, aad); ++ ccmp_special_blocks(skb, pn, scratch, 1); + + if (ieee80211_aes_ccm_decrypt( +- key->u.ccmp.tfm, b_0, aad, ++ key->u.ccmp.tfm, scratch, + skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, + data_len, +- skb->data + skb->len - IEEE80211_CCMP_MIC_LEN)) ++ skb->data + skb->len - IEEE80211_CCMP_MIC_LEN, ++ skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN)) + return RX_DROP_UNUSABLE; + } + --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -5,7 +5,6 @@ config MAC80211 @@ -244,104 +345,3 @@ u32 replays; /* dot11RSNAStatsCCMPReplays */ } ccmp; struct { ---- a/net/mac80211/wpa.c -+++ b/net/mac80211/wpa.c -@@ -301,16 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee - } - - --static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, -+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, - int encrypted) - { - __le16 mask_fc; - int a4_included, mgmt; - u8 qos_tid; -- u16 len_a; -+ u8 *b_0, *aad; -+ u16 data_len, len_a; - unsigned int hdrlen; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - -+ memset(scratch, 0, 6 * AES_BLOCK_SIZE); -+ -+ b_0 = scratch + 3 * AES_BLOCK_SIZE; -+ aad = scratch + 4 * AES_BLOCK_SIZE; -+ - /* - * Mask FC: zero subtype b4 b5 b6 (if not mgmt) - * Retry, PwrMgt, MoreData; set Protected -@@ -332,21 +338,20 @@ static void ccmp_special_blocks(struct s - else - qos_tid = 0; - -- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC -- * mode authentication are not allowed to collide, yet both are derived -- * from this vector b_0. We only set L := 1 here to indicate that the -- * data size can be represented in (L+1) bytes. The CCM layer will take -- * care of storing the data length in the top (L+1) bytes and setting -- * and clearing the other bits as is required to derive the two IVs. -- */ -- b_0[0] = 0x1; -+ data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN; -+ if (encrypted) -+ data_len -= IEEE80211_CCMP_MIC_LEN; - -+ /* First block, b_0 */ -+ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ - /* Nonce: Nonce Flags | A2 | PN - * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) - */ - b_0[1] = qos_tid | (mgmt << 4); - memcpy(&b_0[2], hdr->addr2, ETH_ALEN); - memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); -+ /* l(m) */ -+ put_unaligned_be16(data_len, &b_0[14]); - - /* AAD (extra authenticate-only data) / masked 802.11 header - * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ -@@ -402,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8 - u8 *pos; - u8 pn[6]; - u64 pn64; -- u8 aad[2 * AES_BLOCK_SIZE]; -- u8 b_0[AES_BLOCK_SIZE]; -+ u8 scratch[6 * AES_BLOCK_SIZE]; - - if (info->control.hw_key && - !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && -@@ -456,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8 - return 0; - - pos += IEEE80211_CCMP_HDR_LEN; -- ccmp_special_blocks(skb, pn, b_0, aad, 0); -- ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, -- skb_put(skb, IEEE80211_CCMP_MIC_LEN)); -+ ccmp_special_blocks(skb, pn, scratch, 0); -+ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, -+ pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN)); - - return 0; - } -@@ -521,16 +525,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee - } - - if (!(status->flag & RX_FLAG_DECRYPTED)) { -- u8 aad[2 * AES_BLOCK_SIZE]; -- u8 b_0[AES_BLOCK_SIZE]; -+ u8 scratch[6 * AES_BLOCK_SIZE]; - /* hardware didn't decrypt/verify MIC */ -- ccmp_special_blocks(skb, pn, b_0, aad, 1); -+ ccmp_special_blocks(skb, pn, scratch, 1); - - if (ieee80211_aes_ccm_decrypt( -- key->u.ccmp.tfm, b_0, aad, -+ key->u.ccmp.tfm, scratch, - skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, - data_len, -- skb->data + skb->len - IEEE80211_CCMP_MIC_LEN)) -+ skb->data + skb->len - IEEE80211_CCMP_MIC_LEN, -+ skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN)) - return RX_DROP_UNUSABLE; - } - diff --git a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch index 7b50154e86..3f749e9bfd 100644 --- a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch +++ b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch @@ -18,7 +18,7 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb, unsigned long data, void *arg) { -@@ -1031,14 +1031,14 @@ int ieee80211_register_hw(struct ieee802 +@@ -1036,14 +1036,14 @@ int ieee80211_register_hw(struct ieee802 goto fail_pm_qos; } @@ -35,7 +35,7 @@ local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; result = register_inet6addr_notifier(&local->ifa6_notifier); if (result) -@@ -1047,13 +1047,13 @@ int ieee80211_register_hw(struct ieee802 +@@ -1052,13 +1052,13 @@ int ieee80211_register_hw(struct ieee802 return 0; @@ -52,7 +52,7 @@ fail_ifa: pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); -@@ -1086,10 +1086,10 @@ void ieee80211_unregister_hw(struct ieee +@@ -1103,10 +1103,10 @@ void ieee80211_unregister_hw(struct ieee pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); diff --git a/package/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch index 1da7941d21..e69de29bb2 100644 --- a/package/kernel/mac80211/patches/300-pending_work.patch +++ b/package/kernel/mac80211/patches/300-pending_work.patch @@ -1,4142 +0,0 @@ -commit 584d297fd29fb39c76af25ae74ff9d5fe74c8a14 -Author: Helmut Schaa -Date: Wed Mar 12 10:37:55 2014 +0100 - - ath9k: Fix sequence number assignment for non-data frames - - Since commit 558ff225de80ac95b132d3a115ddadcd64498b4f (ath9k: fix - ps-poll responses under a-mpdu sessions) non-data frames would have - gotten a sequence number from a TIDs sequence counter instead of - using the global sequence counter. - - This can lead to instable connections. - - To fix this only select the correct TID if we are processing a - data frame. Furthermore, prevent non-data frames to get a sequence - number from a TID sequence counter by adding a check to - ath_tx_setup_buffer. - - Cc: Felix Fietkau - Signed-off-by: Helmut Schaa - -commit 3a0f984b1cdcd6a9f8c441635ef3b05d58547f4e -Author: Felix Fietkau -Date: Tue Mar 11 14:03:32 2014 +0100 - - ath9k_hw: set ANI firstep as absolute values instead of relative - - On older chips, the INI value differ in similar ways as cycpwr_thr1, so - convert it to absolute values as well. - - Since the ANI algorithm is different here compared to the old - implementation (fewer steps, controlled at a different point in time), - it makes sense to use values similar to what would be applied for newer - chips, just without relying on INI defaults. - - Signed-off-by: Felix Fietkau - -commit 91d70d40400c569b49605b78fd7c43e9405694f4 -Author: Felix Fietkau -Date: Tue Mar 11 14:00:37 2014 +0100 - - ath9k_hw: set ANI cycpwr_thr1 as absolute values instead of relative - - The table was copied from the ANI implementation of AR9300. It assumes - that the INI values contain a baseline value that is usable as reference - from which to increase/decrease based on the noise immunity value. - - On older chips, the differences are bigger and especially AR5008/AR9001 - are configured to much more sensitive values than what is useful. - - Improve ANI behavior by reverting to the absolute values used in the - previous implementation (expressed as a simple formula instead of the - old table). - - Signed-off-by: Felix Fietkau - -commit c977493766310a825f406836636ffd66e1447783 -Author: Felix Fietkau -Date: Mon Mar 10 19:52:56 2014 +0100 - - ath9k_hw: remove ANI function restrictions for AP mode - - The primary purpose of this piece of code was to selectively disable - OFDM weak signal detection. The checks for this are elsewhere, and an - earlier commit relaxed the restrictions for older chips, which are more - sensitive to interference. - - Signed-off-by: Felix Fietkau - -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 - - 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 - - mac80211: fix station wakeup powersave race - - Consider the following (relatively unlikely) scenario: - 1) station goes to sleep while frames are buffered in driver - 2) driver blocks wakeup (until no more frames are buffered) - 3) station wakes up again - 4) driver unblocks wakeup - - In this case, the current mac80211 code will do the following: - 1) WLAN_STA_PS_STA set - 2) WLAN_STA_PS_DRIVER set - 3) - nothing - - 4) WLAN_STA_PS_DRIVER cleared - - As a result, no frames will be delivered to the client, even - though it is awake, until it sends another frame to us that - triggers ieee80211_sta_ps_deliver_wakeup() in sta_ps_end(). - - Since we now take the PS spinlock, we can fix this while at - the same time removing the complexity with the pending skb - queue function. This was broken since my commit 50a9432daeec - ("mac80211: fix powersaving clients races") due to removing - the clearing of WLAN_STA_PS_STA in the RX path. - - While at it, fix a cleanup path issue when a station is - removed while the driver is still blocking its wakeup. - - Signed-off-by: Johannes Berg - -commit 798f2786602cbe93e6b928299614aa36ebf50692 -Author: Johannes Berg -Date: Mon Feb 17 20:49:03 2014 +0100 - - mac80211: insert stations before adding to driver - - There's a race condition in mac80211 because we add stations - to the internal lists after adding them to the driver, which - means that (for example) the following can happen: - 1. a station connects and is added - 2. first, it is added to the driver - 3. then, it is added to the mac80211 lists - - If the station goes to sleep between steps 2 and 3, and the - firmware/hardware records it as being asleep, mac80211 will - never instruct the driver to wake it up again as it never - realized it went to sleep since the RX path discarded the - frame as a "spurious class 3 frame", no station entry was - present yet. - - Fix this by adding the station in software first, and only - then adding it to the driver. That way, any state that the - driver changes will be reflected properly in mac80211's - station state. The problematic part is the roll-back if the - driver fails to add the station, in that case a bit more is - needed. To not make that overly complex prevent starting BA - sessions in the meantime. - - Signed-off-by: Johannes Berg - -commit b9ba6a520cb07ab3aa7aaaf9ce4a0bc7a6bc06fe -Author: Emmanuel Grumbach -Date: Thu Feb 20 09:22:11 2014 +0200 - - mac80211: fix AP powersave TX vs. wakeup race - - There is a race between the TX path and the STA wakeup: while - a station is sleeping, mac80211 buffers frames until it wakes - up, then the frames are transmitted. However, the RX and TX - path are concurrent, so the packet indicating wakeup can be - processed while a packet is being transmitted. - - This can lead to a situation where the buffered frames list - is emptied on the one side, while a frame is being added on - the other side, as the station is still seen as sleeping in - the TX path. - - As a result, the newly added frame will not be send anytime - soon. It might be sent much later (and out of order) when the - station goes to sleep and wakes up the next time. - - Additionally, it can lead to the crash below. - - Fix all this by synchronising both paths with a new lock. - Both path are not fastpath since they handle PS situations. - - In a later patch we'll remove the extra skb queue locks to - reduce locking overhead. - - BUG: unable to handle kernel - NULL pointer dereference at 000000b0 - IP: [] ieee80211_report_used_skb+0x11/0x3e0 [mac80211] - *pde = 00000000 - Oops: 0000 [#1] SMP DEBUG_PAGEALLOC - EIP: 0060:[] EFLAGS: 00210282 CPU: 1 - EIP is at ieee80211_report_used_skb+0x11/0x3e0 [mac80211] - EAX: e5900da0 EBX: 00000000 ECX: 00000001 EDX: 00000000 - ESI: e41d00c0 EDI: e5900da0 EBP: ebe458e4 ESP: ebe458b0 - DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 - CR0: 8005003b CR2: 000000b0 CR3: 25a78000 CR4: 000407d0 - DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 - DR6: ffff0ff0 DR7: 00000400 - Process iperf (pid: 3934, ti=ebe44000 task=e757c0b0 task.ti=ebe44000) - iwlwifi 0000:02:00.0: I iwl_pcie_enqueue_hcmd Sending command LQ_CMD (#4e), seq: 0x0903, 92 bytes at 3[3]:9 - Stack: - e403b32c ebe458c4 00200002 00200286 e403b338 ebe458cc c10960bb e5900da0 - ff76a6ec ebe458d8 00000000 e41d00c0 e5900da0 ebe458f0 ff6f1b75 e403b210 - ebe4598c ff723dc1 00000000 ff76a6ec e597c978 e403b758 00000002 00000002 - Call Trace: - [] ieee80211_free_txskb+0x15/0x20 [mac80211] - [] invoke_tx_handlers+0x1661/0x1780 [mac80211] - [] ieee80211_tx+0x75/0x100 [mac80211] - [] ieee80211_xmit+0x8f/0xc0 [mac80211] - [] ieee80211_subif_start_xmit+0x4fe/0xe20 [mac80211] - [] dev_hard_start_xmit+0x450/0x950 - [] sch_direct_xmit+0xa9/0x250 - [] __qdisc_run+0x4b/0x150 - [] dev_queue_xmit+0x2c2/0xca0 - - Cc: stable@vger.kernel.org - Reported-by: Yaara Rozenblum - Signed-off-by: Emmanuel Grumbach - Reviewed-by: Stanislaw Gruszka - [reword commit log, use a separate lock] - Signed-off-by: Johannes Berg - -commit 80e419de0dff38436b30d363311c625766193f86 -Author: Inbal Hacohen -Date: Wed Feb 12 09:32:27 2014 +0200 - - cfg80211: bugfix in regulatory user hint process - - After processing hint_user, we would want to schedule the - timeout work only if we are actually waiting to CRDA. This happens - when the status is not "IGNORE" nor "ALREADY_SET". - - Signed-off-by: Inbal Hacohen - Signed-off-by: Johannes Berg - -commit 6514c93afede55284e2cb63359aadedb85884c80 -Author: Jouni Malinen -Date: Tue Feb 18 20:41:08 2014 +0200 - - ath9k: Enable U-APSD AP mode support - - mac80211 handles the actual operations, so ath9k can just indicate - support for this. Based on initial tests, this combination seems to - work fine. - - Signed-off-by: Jouni Malinen - -commit a63caf0a357ad5c1f08d6b7827dc76c451445017 -Author: Stanislaw Gruszka -Date: Wed Feb 19 13:15:17 2014 +0100 - - ath9k: protect tid->sched check - - We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That - is race condition which can result of doing list_del(&tid->list) twice - (second time with poisoned list node) and cause crash like shown below: - - [424271.637220] BUG: unable to handle kernel paging request at 00100104 - [424271.637328] IP: [] ath_tx_aggr_sleep+0x62/0xe0 [ath9k] - ... - [424271.639953] Call Trace: - [424271.639998] [] ? ath9k_get_survey+0x110/0x110 [ath9k] - [424271.640083] [] ath9k_sta_notify+0x42/0x50 [ath9k] - [424271.640177] [] sta_ps_start+0x8f/0x1c0 [mac80211] - [424271.640258] [] ? free_compound_page+0x2e/0x40 - [424271.640346] [] ieee80211_rx_handlers+0x9d5/0x2340 [mac80211] - [424271.640437] [] ? kmem_cache_free+0x1d8/0x1f0 - [424271.640510] [] ? kfree_skbmem+0x34/0x90 - [424271.640578] [] ? put_page+0x2c/0x40 - [424271.640640] [] ? kfree_skbmem+0x34/0x90 - [424271.640706] [] ? kfree_skbmem+0x34/0x90 - [424271.640787] [] ? ieee80211_rx_handlers_result+0x73/0x1d0 [mac80211] - [424271.640897] [] ieee80211_prepare_and_rx_handle+0x520/0xad0 [mac80211] - [424271.641009] [] ? ieee80211_rx_handlers+0x2ed/0x2340 [mac80211] - [424271.641104] [] ? ip_output+0x7e/0xd0 - [424271.641182] [] ieee80211_rx+0x307/0x7c0 [mac80211] - [424271.641266] [] ath_rx_tasklet+0x88e/0xf70 [ath9k] - [424271.641358] [] ? ieee80211_rx+0x1dc/0x7c0 [mac80211] - [424271.641445] [] ath9k_tasklet+0xcb/0x130 [ath9k] - - Bug report: - https://bugzilla.kernel.org/show_bug.cgi?id=70551 - - Reported-and-tested-by: Max Sydorenko - Cc: stable@vger.kernel.org - Signed-off-by: Stanislaw Gruszka - -commit 82ed9e3ccc02797df2ffe4b78127c4cd5f799a41 -Author: Felix Fietkau -Date: Tue Feb 11 15:54:13 2014 +0100 - - mac80211: send control port protocol frames to the VO queue - - Improves reliability of wifi connections with WPA, since authentication - frames are prioritized over normal traffic and also typically exempt - from aggregation. - - Cc: stable@vger.kernel.org - Signed-off-by: Felix Fietkau - -commit d4426800f71e972feaa33e04c5801fc730627bdd -Author: Stanislaw Gruszka -Date: Mon Feb 10 22:38:28 2014 +0100 - - rtl8187: fix regression on MIPS without coherent DMA - - This patch fixes regression caused by commit a16dad77634 "MIPS: Fix - potencial corruption". That commit fixes one corruption scenario in - cost of adding another one, which actually start to cause crashes - on Yeeloong laptop when rtl8187 driver is used. - - For correct DMA read operation on machines without DMA coherence, kernel - have to invalidate cache, such it will refill later with new data that - device wrote to memory, when that data is needed to process. We can only - invalidate full cache line. Hence when cache line includes both dma - buffer and some other data (written in cache, but not yet in main - memory), the other data can not hit memory due to invalidation. That - happen on rtl8187 where struct rtl8187_priv fields are located just - before and after small buffers that are passed to USB layer and DMA - is performed on them. - - To fix the problem we align buffers and reserve space after them to make - them match cache line. - - This patch does not resolve all possible MIPS problems entirely, for - that we have to assure that we always map cache aligned buffers for DMA, - what can be complex or even not possible. But patch fixes visible and - reproducible regression and seems other possible corruptions do not - happen in practice, since Yeeloong laptop works stable without rtl8187 - driver. - - Bug report: - https://bugzilla.kernel.org/show_bug.cgi?id=54391 - - Reported-by: Petr Pisar - Bisected-by: Tom Li - Reported-and-tested-by: Tom Li - Cc: stable@vger.kernel.org - Signed-off-by: Stanislaw Gruszka - -commit e2f141d67ad1e7fe10aaab61811e8a409dfb2442 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:55 2014 +0530 - - ath9k: Calculate IQ-CAL median - - This patch adds a routine to calculate the median IQ correction - values for AR955x, which is used for outlier detection. - The normal method which is used for all other chips is - bypassed for AR955x. - - Signed-off-by: Sujith Manoharan - -commit c52a6fce0820c8d0687443ab86058ae03b478c8f -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:54 2014 +0530 - - ath9k: Expand the IQ coefficient array - - This will be used for storing data for mutiple - IQ calibration runs, for AR955x. - - Signed-off-by: Sujith Manoharan - -commit 034969ff5c2b6431d10e07c1938f0b916da85cc3 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:53 2014 +0530 - - ath9k: Modify IQ calibration for AR955x - - IQ calibration post-processing for AR955x is different - from other chips - instead of just doing it as part - of AGC calibration once, it is triggered 3 times and - a median is determined. This patch adds initial support - for changing the calibration behavior for AR955x. - - Also, to simplify things, a helper routine to issue/poll - AGC calibration is used. - - For non-AR955x chips, the iqcal_idx (which will be used - in subsequent patches) is set to zero. - - Signed-off-by: Sujith Manoharan - -commit 9b1ed6454e6f3511f24266be99b4e403f243f6a8 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:52 2014 +0530 - - ath9k: Fix magnitude/phase calculation - - Incorrect values are programmed in the registers - containing the IQ correction coefficients by the IQ-CAL - post-processing code. Fix this. - - Signed-off-by: Sujith Manoharan - -commit 36f93484f96f79171dcecb67c5ef0c3de22531a6 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:51 2014 +0530 - - ath9k: Rename ar9003_hw_tx_iqcal_load_avg_2_passes - - Use ar9003_hw_tx_iq_cal_outlier_detection instead. - - Signed-off-by: Sujith Manoharan - -commit 3af09a7f5d21dd5fd15b973ce6a91a575da30417 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:50 2014 +0530 - - ath9k: Check explicitly for IQ calibration - - In chips like AR955x, the initvals contain the information - whether IQ calibration is to be done in the HW when an - AGC calibration is triggered. Check if IQ-CAL is enabled - in the initvals before flagging 'txiqcal_done' as true. - - Signed-off-by: Sujith Manoharan - -commit cb4969634b93c4643a32cc3fbd27d2b288b25771 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:49 2014 +0530 - - ath9k: Fix IQ cal post processing for SoC - - Calibration data is not reused for SoC chips, so - call ar9003_hw_tx_iq_cal_post_proc() with the correct - argument. The 'is_reusable' flag is currently used - only for PC-OEM chips, but it makes things clearer to - specify it explicity. - - Signed-off-by: Sujith Manoharan - -commit e138e0ef9560c46ce93dbb22a728a57888e94d1c -Author: Sujith Manoharan -Date: Mon Feb 3 13:31:37 2014 +0530 - - ath9k: Fix TX power calculation - - The commit, "ath9k_hw: Fix incorrect Tx control power in AR9003 template" - fixed the incorrect values in the eeprom templates, but if - boards have already been calibrated with incorrect values, - they would still be using the wrong TX power. Fix this by assigning - a default value in such cases. - - Cc: Rajkumar Manoharan - Signed-off-by: Sujith Manoharan - -commit b9f268b5b01331c3c82179abca551429450e9417 -Author: Michal Kazior -Date: Wed Jan 29 14:22:27 2014 +0100 - - cfg80211: consider existing DFS interfaces - - It was possible to break interface combinations in - the following way: - - combo 1: iftype = AP, num_ifaces = 2, num_chans = 2, - combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20 - - With the above interface combinations it was - possible to: - - step 1. start AP on DFS channel by matching combo 2 - step 2. start AP on non-DFS channel by matching combo 1 - - This was possible beacuse (step 2) did not consider - if other interfaces require radar detection. - - The patch changes how cfg80211 tracks channels - - instead of channel itself now a complete chandef - is stored. - - Signed-off-by: Michal Kazior - Signed-off-by: Johannes Berg - -commit bc9c62f5f511cc395c62dbf4cdd437f23db53b28 -Author: Antonio Quartulli -Date: Wed Jan 29 17:53:43 2014 +0100 - - cfg80211: fix channel configuration in IBSS join - - When receiving an IBSS_JOINED event select the BSS object - based on the {bssid, channel} couple rather than the bssid - only. - With the current approach if another cell having the same - BSSID (but using a different channel) exists then cfg80211 - picks up the wrong BSS object. - The result is a mismatching channel configuration between - cfg80211 and the driver, that can lead to any sort of - problem. - - The issue can be triggered by having an IBSS sitting on - given channel and then asking the driver to create a new - cell using the same BSSID but with a different frequency. - By passing the channel to cfg80211_get_bss() we can solve - this ambiguity and retrieve/create the correct BSS object. - All the users of cfg80211_ibss_joined() have been changed - accordingly. - - Moreover WARN when cfg80211_ibss_joined() gets a NULL - channel as argument and remove a bogus call of the same - function in ath6kl (it does not make sense to call - cfg80211_ibss_joined() with a zero BSSID on ibss-leave). - - Cc: Kalle Valo - Cc: Arend van Spriel - Cc: Bing Zhao - Cc: Jussi Kivilinna - Cc: libertas-dev@lists.infradead.org - Acked-by: Kalle Valo - Signed-off-by: Antonio Quartulli - [minor code cleanup in ath6kl] - Signed-off-by: Johannes Berg - -commit 7e0c41cb41f215aba2c39b1c237bb4d42ec49a85 -Author: Johannes Berg -Date: Fri Jan 24 14:41:44 2014 +0100 - - mac80211: fix bufferable MMPDU RX handling - - Action, disassoc and deauth frames are bufferable, and as such don't - have the PM bit in the frame control field reserved which means we - need to react to the bit when receiving in such a frame. - - Fix this by introducing a new helper ieee80211_is_bufferable_mmpdu() - and using it for the RX path that currently ignores the PM bit in - any non-data frames for doze->wake transitions, but listens to it in - all frames for wake->doze transitions, both of which are wrong. - - Also use the new helper in the TX path to clean up the code. - - Signed-off-by: Johannes Berg - -commit fc0df6d2343636e3f48a069330d5b972e3d8659d -Author: Janusz Dziedzic -Date: Fri Jan 24 14:29:21 2014 +0100 - - cfg80211: set preset_chandef after channel switch - - Set preset_chandef in channel switch notification. - In other case we will have old preset_chandef. - - Signed-off-by: Janusz Dziedzic - Signed-off-by: Johannes Berg - -commit cdec895e2344987ff171cece96e25d7407a3ebf6 -Author: Simon Wunderlich -Date: Fri Jan 24 23:48:29 2014 +0100 - - mac80211: send ibss probe responses with noack flag - - Responding to probe requests for scanning clients will often create - excessive retries, as it happens quite often that the scanning client - already left the channel. Therefore do it like hostapd and send probe - responses for wildcard SSID only once by using the noack flag. - - Signed-off-by: Simon Wunderlich - [fix typo & 'wildcard SSID' in commit log] - Signed-off-by: Johannes Berg - -commit 0b865d1e6b9c05052adae9315df7cb195dc60c3b -Author: Luciano Coelho -Date: Tue Jan 28 17:09:08 2014 +0200 - - mac80211: ibss: remove unnecessary call to release channel - - The ieee80211_vif_use_channel() function calls - ieee80211_vif_release_channel(), so there's no need to call it - explicitly in __ieee80211_sta_join_ibss(). - - Signed-off-by: Luciano Coelho - Signed-off-by: Johannes Berg - -commit e1b6c17e971f0a51ff86c2dac2584c63cd999cd7 -Author: Michal Kazior -Date: Wed Jan 29 07:56:21 2014 +0100 - - mac80211: add missing CSA locking - - The patch adds a missing sdata lock and adds a few - lockdeps for easier maintenance. - - Signed-off-by: Michal Kazior - Signed-off-by: Johannes Berg - -commit ad17ba7d14d225b109b73c177cd446afb8050598 -Author: Michal Kazior -Date: Wed Jan 29 07:56:20 2014 +0100 - - mac80211: fix sdata->radar_required locking - - radar_required setting wasn't protected by - local->mtx in some places. This should prevent - from scanning/radar detection/roc colliding. - - Signed-off-by: Michal Kazior - Signed-off-by: Johannes Berg - -commit 5fcd5f1808813a3d9e502fd756e01bee8a79c85d -Author: Michal Kazior -Date: Wed Jan 29 07:56:19 2014 +0100 - - mac80211: move csa_active setting in STA CSA - - The sdata->vif.csa_active could be left set after, - e.g. channel context constraints check fail in STA - mode leaving the interface in a strange state for - a brief period of time until it is disconnected. - This was harmless but ugly. - - Signed-off-by: Michal Kazior - Reviewed-by: Luciano Coelho - Signed-off-by: Johannes Berg - -commit e486da4b7eed71821c6b4c1bb9ac62ffd3ab13e9 -Author: Michal Kazior -Date: Wed Jan 29 07:56:18 2014 +0100 - - mac80211: fix possible memory leak on AP CSA failure - - If CSA for AP interface failed and the interface - was not stopped afterwards another CSA request - would leak sdata->u.ap.next_beacon. - - Signed-off-by: Michal Kazior - Reviewed-by: Luciano Coelho - Signed-off-by: Johannes Berg - -commit 3a77ba08940682bf3d52cf14f980337324af9d4a -Author: Johannes Berg -Date: Sat Feb 1 00:33:29 2014 +0100 - - mac80211: fix fragmentation code, particularly for encryption - - The "new" fragmentation code (since my rewrite almost 5 years ago) - erroneously sets skb->len rather than using skb_trim() to adjust - the length of the first fragment after copying out all the others. - This leaves the skb tail pointer pointing to after where the data - originally ended, and thus causes the encryption MIC to be written - at that point, rather than where it belongs: immediately after the - data. - - The impact of this is that if software encryption is done, then - a) encryption doesn't work for the first fragment, the connection - becomes unusable as the first fragment will never be properly - verified at the receiver, the MIC is practically guaranteed to - be wrong - b) we leak up to 8 bytes of plaintext (!) of the packet out into - the air - - This is only mitigated by the fact that many devices are capable - of doing encryption in hardware, in which case this can't happen - as the tail pointer is irrelevant in that case. Additionally, - fragmentation is not used very frequently and would normally have - to be configured manually. - - Fix this by using skb_trim() properly. - - Cc: stable@vger.kernel.org - Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation") - Reported-by: Jouni Malinen - Signed-off-by: Johannes Berg - -commit de5f242e0c10e841017e37eb8c38974a642dbca8 -Author: Sujith Manoharan -Date: Tue Jan 28 06:21:59 2014 +0530 - - ath9k: Fix build error on ARM - - Use mdelay instead of udelay to fix this error: - - ERROR: "__bad_udelay" [drivers/net/wireless/ath/ath9k/ath9k_hw.ko] undefined! - make[1]: *** [__modpost] Error 1 - make: *** [modules] Error 2 - - Reported-by: Josh Boyer - Signed-off-by: Sujith Manoharan - -commit 8e3ea7a51dfc61810fcefd947f6edcf61125252a -Author: Geert Uytterhoeven -Date: Sun Jan 26 11:53:21 2014 +0100 - - ath9k: Fix uninitialized variable in ath9k_has_tx_pending() - - drivers/net/wireless/ath/ath9k/main.c: In function ‘ath9k_has_tx_pending’: - drivers/net/wireless/ath/ath9k/main.c:1869: warning: ‘npend’ may be used uninitialized in this function - - Introduced by commit 10e2318103f5941aa70c318afe34bc41f1b98529 ("ath9k: - optimize ath9k_flush"). - - Signed-off-by: Geert Uytterhoeven - -commit a4a634a6937ebdd827fa58e8fcdb8ca49a3769f6 -Author: Emmanuel Grumbach -Date: Mon Jan 27 11:07:42 2014 +0200 - - mac80211: release the channel in error path in start_ap - - When the driver cannot start the AP or when the assignement - of the beacon goes wrong, we need to unassign the vif. - - Cc: stable@vger.kernel.org - Signed-off-by: Emmanuel Grumbach - Signed-off-by: Johannes Berg - -commit dfb6889a75c601aedb7450b7e606668e77da6679 -Author: Johannes Berg -Date: Wed Jan 22 11:14:19 2014 +0200 - - cfg80211: send scan results from work queue - - Due to the previous commit, when a scan finishes, it is in theory - possible to hit the following sequence: - 1. interface starts being removed - 2. scan is cancelled by driver and cfg80211 is notified - 3. scan done work is scheduled - 4. interface is removed completely, rdev->scan_req is freed, - event sent to userspace but scan done work remains pending - 5. new scan is requested on another virtual interface - 6. scan done work runs, freeing the still-running scan - - To fix this situation, hang on to the scan done message and block - new scans while that is the case, and only send the message from - the work function, regardless of whether the scan_req is already - freed from interface removal. This makes step 5 above impossible - and changes step 6 to be - 5. scan done work runs, sending the scan done message - - As this can't work for wext, so we send the message immediately, - but this shouldn't be an issue since we still return -EBUSY. - - Signed-off-by: Johannes Berg - -commit 45b7ab41fc08627d9a8428cb413d5d84662a9707 -Author: Johannes Berg -Date: Wed Jan 22 11:14:18 2014 +0200 - - cfg80211: fix scan done race - - When an interface/wdev is removed, any ongoing scan should be - cancelled by the driver. This will make it call cfg80211, which - only queues a work struct. If interface/wdev removal is quick - enough, this can leave the scan request pending and processed - only after the interface is gone, causing a use-after-free. - - Fix this by making sure the scan request is not pending after - the interface is destroyed. We can't flush or cancel the work - item due to locking concerns, but when it'll run it shouldn't - find anything to do. This leaves a potential issue, if a new - scan gets requested before the work runs, it prematurely stops - the running scan, potentially causing another crash. I'll fix - that in the next patch. - - This was particularly observed with P2P_DEVICE wdevs, likely - because freeing them is quicker than freeing netdevs. - - Reported-by: Andrei Otcheretianski - Fixes: 4a58e7c38443 ("cfg80211: don't "leak" uncompleted scans") - Signed-off-by: Johannes Berg - -commit ae04fa489ab31b5a10d3cc8399f52761175d4321 -Author: Emmanuel Grumbach -Date: Thu Jan 23 14:28:16 2014 +0200 - - mac80211: avoid deadlock revealed by lockdep - - sdata->u.ap.request_smps_work can’t be flushed synchronously - under wdev_lock(wdev) since ieee80211_request_smps_ap_work - itself locks the same lock. - While at it, reset the driver_smps_mode when the ap is - stopped to its default: OFF. - - This solves: - - ====================================================== - [ INFO: possible circular locking dependency detected ] - 3.12.0-ipeer+ #2 Tainted: G O - ------------------------------------------------------- - rmmod/2867 is trying to acquire lock: - ((&sdata->u.ap.request_smps_work)){+.+...}, at: [] flush_work+0x0/0x90 - - but task is already holding lock: - (&wdev->mtx){+.+.+.}, at: [] cfg80211_stop_ap+0x26/0x230 [cfg80211] - - which lock already depends on the new lock. - - the existing dependency chain (in reverse order) is: - - -> #1 (&wdev->mtx){+.+.+.}: - [] lock_acquire+0x79/0xe0 - [] mutex_lock_nested+0x4a/0x360 - [] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211] - [] process_one_work+0x198/0x450 - [] worker_thread+0xf9/0x320 - [] kthread+0x9f/0xb0 - [] ret_from_kernel_thread+0x1b/0x28 - - -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}: - [] __lock_acquire+0x183f/0x1910 - [] lock_acquire+0x79/0xe0 - [] flush_work+0x47/0x90 - [] __cancel_work_timer+0x67/0xe0 - [] cancel_work_sync+0xf/0x20 - [] ieee80211_stop_ap+0x8c/0x340 [mac80211] - [] cfg80211_stop_ap+0x8c/0x230 [cfg80211] - [] cfg80211_leave+0x79/0x100 [cfg80211] - [] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211] - [] notifier_call_chain+0x59/0x130 - [] __raw_notifier_call_chain+0x1e/0x30 - [] raw_notifier_call_chain+0x1f/0x30 - [] call_netdevice_notifiers_info+0x33/0x70 - [] call_netdevice_notifiers+0x13/0x20 - [] __dev_close_many+0x34/0xb0 - [] dev_close_many+0x6e/0xc0 - [] rollback_registered_many+0xa7/0x1f0 - [] unregister_netdevice_many+0x14/0x60 - [] ieee80211_remove_interfaces+0xe9/0x170 [mac80211] - [] ieee80211_unregister_hw+0x56/0x110 [mac80211] - [] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm] - [] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi] - [] iwl_opmode_deregister+0x6f/0x90 [iwlwifi] - [] __exit_compat+0xd/0x19 [iwlmvm] - [] SyS_delete_module+0x179/0x2b0 - [] sysenter_do_call+0x12/0x32 - - Fixes: 687da132234f ("mac80211: implement SMPS for AP") - Cc: [3.13] - Reported-by: Ilan Peer - Signed-off-by: Emmanuel Grumbach - Signed-off-by: Johannes Berg - -commit 178b205e96217164fd7c30113464250d0b6f5eca -Author: Johannes Berg -Date: Thu Jan 23 16:32:29 2014 +0100 - - cfg80211: re-enable 5/10 MHz support - - Unfortunately I forgot this during the merge window, but the - patch seems small enough to go in as a fix. The userspace API - bug that was the reason for disabling it has long been fixed. - - Signed-off-by: Johannes Berg - -commit 110a1c79acda14edc83b7c8dc5af9c7ddd23eb61 -Author: Pontus Fuchs -Date: Thu Jan 16 15:00:40 2014 +0100 - - nl80211: Reset split_start when netlink skb is exhausted - - When the netlink skb is exhausted split_start is left set. In the - subsequent retry, with a larger buffer, the dump is continued from the - failing point instead of from the beginning. - - This was causing my rt28xx based USB dongle to now show up when - running "iw list" with an old iw version without split dump support. - - Cc: stable@vger.kernel.org - Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps") - Signed-off-by: Pontus Fuchs - [avoid the entire workaround when state->split is set] - Signed-off-by: Johannes Berg - -commit b4c31b45ffc7ef110fa9ecc34d7878fe7c5b9da4 -Author: Eliad Peller -Date: Sun Jan 12 11:06:37 2014 +0200 - - mac80211: move roc cookie assignment earlier - - ieee80211_start_roc_work() might add a new roc - to existing roc, and tell cfg80211 it has already - started. - - However, this might happen before the roc cookie - was set, resulting in REMAIN_ON_CHANNEL (started) - event with null cookie. Consequently, it can make - wpa_supplicant go out of sync. - - Fix it by setting the roc cookie earlier. - - Cc: stable@vger.kernel.org - Signed-off-by: Eliad Peller - Signed-off-by: Johannes Berg - -commit cfdc9157bfd7bcf88ab4dae08873a9907eba984c -Author: Johannes Berg -Date: Fri Jan 24 14:06:29 2014 +0100 - - nl80211: send event when AP operation is stopped - - There are a few cases, e.g. suspend, where an AP interface is - stopped by the kernel rather than by userspace request, most - commonly when suspending. To let userspace know about this, - send the NL80211_CMD_STOP_AP command as an event every time - an AP interface is stopped. This also happens when userspace - did in fact request the AP stop, but that's not a problem. - - For full-MAC drivers this may need to be extended to also - cover cases where the device stopped the AP operation for - some reason, this a bit more complicated because then all - cfg80211 state also needs to be reset; such API is not part - of this patch. - - Signed-off-by: Johannes Berg - -commit d5d567eda7704f190379ca852a8f9a4112e3eee3 -Author: Johannes Berg -Date: Thu Jan 23 16:20:29 2014 +0100 - - mac80211: add length check in ieee80211_is_robust_mgmt_frame() - - A few places weren't checking that the frame passed to the - function actually has enough data even though the function - clearly documents it must have a payload byte. Make this - safer by changing the function to take an skb and checking - the length inside. The old version is preserved for now as - the rtl* drivers use it and don't have a correct skb. - - Signed-off-by: Johannes Berg - -commit f8f6d212a047fc65c7d3442dfc038f65517236fc -Author: Johannes Berg -Date: Fri Jan 24 10:53:53 2014 +0100 - - nl80211: fix scheduled scan RSSI matchset attribute confusion - - The scheduled scan matchsets were intended to be a list of filters, - with the found BSS having to pass at least one of them to be passed - to the host. When the RSSI attribute was added, however, this was - broken and currently wpa_supplicant adds that attribute in its own - matchset; however, it doesn't intend that to mean that anything - that passes the RSSI filter should be passed to the host, instead - it wants it to mean that everything needs to also have higher RSSI. - - This is semantically problematic because we have a list of filters - like [ SSID1, SSID2, SSID3, RSSI ] with no real indication which - one should be OR'ed and which one AND'ed. - - To fix this, move the RSSI filter attribute into each matchset. As - we need to stay backward compatible, treat a matchset with only the - RSSI attribute as a "default RSSI filter" for all other matchsets, - but only if there are other matchsets (an RSSI-only matchset by - itself is still desirable.) - - To make driver implementation easier, keep a global min_rssi_thold - for the entire request as well. The only affected driver is ath6kl. - - I found this when I looked into the code after Raja Mani submitted - a patch fixing the n_match_sets calculation to disregard the RSSI, - but that patch didn't address the semantic issue. - - Reported-by: Raja Mani - Acked-by: Luciano Coelho - Signed-off-by: Johannes Berg - -commit de553e8545e65a6dc4e45f43df7e1443d4291922 -Author: Johannes Berg -Date: Fri Jan 24 10:17:47 2014 +0100 - - nl80211: check nla_parse() return values - - If there's a policy, then nla_parse() return values must be - checked, otherwise the policy is useless and there's nothing - that ensures the attributes are actually what we expect them - to be. - - Signed-off-by: Johannes Berg - -commit 652204a0733e9e1c54661d6f9d36e2e1e3b22bb1 -Author: Karl Beldan -Date: Thu Jan 23 20:06:34 2014 +0100 - - mac80211: send {ADD,DEL}BA on AC_VO like other mgmt frames, as per spec - - ATM, {ADD,DEL}BA and BAR frames are sent on the AC matching the TID of - the BA parameters. In the discussion [1] about this patch, Johannes - recalled that it fixed some races with the DELBA and indeed this - behavior was introduced in [2]. - While [2] is right for the BARs, the part queueing the {ADD,DEL}BAs on - their BA params TID AC violates the spec and is more a workaround for - some drivers. Helmut expressed some concerns wrt such drivers, in - particular DELBAs in rt2x00. - - ATM, DELBAs are sent after a driver has called (hence "purposely") - ieee80211_start_tx_ba_cb_irqsafe and Johannes and Emmanuel gave some - details wrt intentions behind the split of the IEEE80211_AMPDU_TX_STOP_* - given to the driver ampdu_action supposed to call this function, which - could prove handy to people trying to do the right thing in faulty - drivers (if their fw/hw don't get in their way). - - [1] http://mid.gmane.org/1390391564-18481-1-git-send-email-karl.beldan@gmail.com - [2] Commit: cf6bb79ad828 ("mac80211: Use appropriate TID for sending BAR, ADDBA and DELBA frames") - - Signed-off-by: Karl Beldan - Cc: Helmut Schaa - Cc: Emmanuel Grumbach - Signed-off-by: Johannes Berg ---- a/drivers/net/wireless/ath/ath6kl/cfg80211.c -+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c -@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struc - if (nw_type & ADHOC_NETWORK) { - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", - nw_type & ADHOC_CREATOR ? "creator" : "joiner"); -- cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); -+ cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL); - cfg80211_put_bss(ar->wiphy, bss); - return; - } -@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(st - } - - if (vif->nw_type & ADHOC_NETWORK) { -- if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) { -+ if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, - "%s: ath6k not in ibss mode\n", __func__); -- return; -- } -- memset(bssid, 0, ETH_ALEN); -- cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); - return; - } - -@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(s - struct ath6kl_vif *vif = netdev_priv(dev); - u16 interval; - int ret, rssi_thold; -+ int n_match_sets = request->n_match_sets; -+ -+ /* -+ * If there's a matchset w/o an SSID, then assume it's just for -+ * the RSSI (nothing else is currently supported) and ignore it. -+ * The device only supports a global RSSI filter that we set below. -+ */ -+ if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len) -+ n_match_sets = 0; - - if (ar->state != ATH6KL_STATE_ON) - return -EIO; -@@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(s - ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, - request->n_ssids, - request->match_sets, -- request->n_match_sets); -+ n_match_sets); - if (ret < 0) - return ret; - -- if (!request->n_match_sets) { -+ if (!n_match_sets) { - ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, - ALL_BSS_FILTER, 0); - if (ret < 0) -@@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(s - - if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD, - ar->fw_capabilities)) { -- if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF) -+ if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF) - rssi_thold = 0; -- else if (request->rssi_thold < -127) -+ else if (request->min_rssi_thold < -127) - rssi_thold = -127; - else -- rssi_thold = request->rssi_thold; -+ rssi_thold = request->min_rssi_thold; - - ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx, - rssi_thold); ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct at - if (AR_SREV_9300_20_OR_LATER(ah)) - udelay(50); - else if (AR_SREV_9100(ah)) -- udelay(10000); -+ mdelay(10); - else - udelay(100); - -@@ -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); -- - if (AR_SREV_9100(ah)) -- udelay(10000); -+ mdelay(10); - else - udelay(50); - ---- 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) - { -- int i, npend; -+ int i, npend = 0; - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (!ATH_TXQ_SETUP(sc, i)) ---- a/drivers/net/wireless/iwlwifi/mvm/scan.c -+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c -@@ -595,6 +595,9 @@ static void iwl_scan_offload_build_ssid( - * config match list. - */ - for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) { -+ /* skip empty SSID matchsets */ -+ if (!req->match_sets[i].ssid.ssid_len) -+ continue; - scan->direct_scan[i].id = WLAN_EID_SSID; - scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len; - memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid, ---- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c -+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c -@@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80 - /* During testing, hdr was NULL */ - return false; - } -- if ((ieee80211_is_robust_mgmt_frame(hdr)) && -+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag &= ~RX_FLAG_DECRYPTED; - else ---- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c -+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c -@@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80 - /* In testing, hdr was NULL here */ - return false; - } -- if ((ieee80211_is_robust_mgmt_frame(hdr)) && -+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag &= ~RX_FLAG_DECRYPTED; - else ---- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c -+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c -@@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80 - /* during testing, hdr was NULL here */ - return false; - } -- if ((ieee80211_is_robust_mgmt_frame(hdr)) && -+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag &= ~RX_FLAG_DECRYPTED; - else ---- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c -+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c -@@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee - /* during testing, hdr could be NULL here */ - return false; - } -- if ((ieee80211_is_robust_mgmt_frame(hdr)) && -+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag &= ~RX_FLAG_DECRYPTED; - else ---- a/include/linux/ieee80211.h -+++ b/include/linux/ieee80211.h -@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullf - } - - /** -+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU -+ * @fc: frame control field in little-endian byteorder -+ */ -+static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc) -+{ -+ /* IEEE 802.11-2012, definition of "bufferable management frame"; -+ * note that this ignores the IBSS special case. */ -+ return ieee80211_is_mgmt(fc) && -+ (ieee80211_is_action(fc) || -+ ieee80211_is_disassoc(fc) || -+ ieee80211_is_deauth(fc)); -+} -+ -+/** - * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set - * @seq_ctrl: frame sequence control bytes in little-endian byteorder - */ -@@ -2192,10 +2206,10 @@ static inline u8 *ieee80211_get_DA(struc - } - - /** -- * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame -+ * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame - * @hdr: the frame (buffer must include at least the first octet of payload) - */ --static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) -+static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) - { - if (ieee80211_is_disassoc(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control)) -@@ -2224,6 +2238,17 @@ static inline bool ieee80211_is_robust_m - } - - /** -+ * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame -+ * @skb: the skb containing the frame, length will be checked -+ */ -+static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb) -+{ -+ if (skb->len < 25) -+ return false; -+ return _ieee80211_is_robust_mgmt_frame((void *)skb->data); -+} -+ -+/** - * ieee80211_is_public_action - check if frame is a public action frame - * @hdr: the frame - * @len: length of the frame ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1395,9 +1395,11 @@ struct cfg80211_scan_request { - * struct cfg80211_match_set - sets of attributes to match - * - * @ssid: SSID to be matched -+ * @rssi_thold: don't report scan results below this threshold (in s32 dBm) - */ - struct cfg80211_match_set { - struct cfg80211_ssid ssid; -+ s32 rssi_thold; - }; - - /** -@@ -1420,7 +1422,8 @@ struct cfg80211_match_set { - * @dev: the interface - * @scan_start: start time of the scheduled scan - * @channels: channels to scan -- * @rssi_thold: don't report scan results below this threshold (in s32 dBm) -+ * @min_rssi_thold: for drivers only supporting a single threshold, this -+ * contains the minimum over all matchsets - */ - struct cfg80211_sched_scan_request { - struct cfg80211_ssid *ssids; -@@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request { - u32 flags; - struct cfg80211_match_set *match_sets; - int n_match_sets; -- s32 rssi_thold; -+ s32 min_rssi_thold; - - /* internal */ - struct wiphy *wiphy; -@@ -3130,8 +3133,8 @@ struct cfg80211_cached_keys; - * @identifier: (private) Identifier used in nl80211 to identify this - * wireless device if it has no netdev - * @current_bss: (private) Used by the internal configuration code -- * @channel: (private) Used by the internal configuration code to track -- * the user-set AP, monitor and WDS channel -+ * @chandef: (private) Used by the internal configuration code to track -+ * the user-set channel definition. - * @preset_chandef: (private) Used by the internal configuration code to - * track the channel to be used for AP later - * @bssid: (private) Used by the internal configuration code -@@ -3195,9 +3198,7 @@ struct wireless_dev { - - struct cfg80211_internal_bss *current_bss; /* associated / joined */ - struct cfg80211_chan_def preset_chandef; -- -- /* for AP and mesh channel tracking */ -- struct ieee80211_channel *channel; -+ struct cfg80211_chan_def chandef; - - bool ibss_fixed; - bool ibss_dfs_possible; -@@ -3879,6 +3880,7 @@ void cfg80211_michael_mic_failure(struct - * - * @dev: network device - * @bssid: the BSSID of the IBSS joined -+ * @channel: the channel of the IBSS joined - * @gfp: allocation flags - * - * This function notifies cfg80211 that the device joined an IBSS or -@@ -3888,7 +3890,8 @@ void cfg80211_michael_mic_failure(struct - * with the locally generated beacon -- this guarantees that there is - * always a scan result for this IBSS. cfg80211 will handle the rest. - */ --void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); -+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, -+ struct ieee80211_channel *channel, gfp_t gfp); - - /** - * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -2442,9 +2442,15 @@ enum nl80211_reg_rule_attr { - * enum nl80211_sched_scan_match_attr - scheduled scan match attributes - * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved - * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, -- * only report BSS with matching SSID. -+ * only report BSS with matching SSID. - * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a -- * BSS in scan results. Filtering is turned off if not specified. -+ * BSS in scan results. Filtering is turned off if not specified. Note that -+ * if this attribute is in a match set of its own, then it is treated as -+ * the default value for all matchsets with an SSID, rather than being a -+ * matchset of its own without an RSSI filter. This is due to problems with -+ * how this API was implemented in the past. Also, due to the same problem, -+ * the only way to create a matchset with only an RSSI filter (with this -+ * attribute) is if there's only a single matchset with the RSSI attribute. - * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter - * attribute number currently defined - * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use ---- a/net/mac80211/agg-tx.c -+++ b/net/mac80211/agg-tx.c -@@ -107,7 +107,7 @@ static void ieee80211_send_addba_request - mgmt->u.action.u.addba_req.start_seq_num = - cpu_to_le16(start_seq_num << 4); - -- ieee80211_tx_skb_tid(sdata, skb, tid); -+ ieee80211_tx_skb(sdata, skb); - } - - void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wip - /* TODO: make hostapd tell us what it wants */ - sdata->smps_mode = IEEE80211_SMPS_OFF; - sdata->needed_rx_chains = sdata->local->rx_chains; -- sdata->radar_required = params->radar_required; - - mutex_lock(&local->mtx); -+ sdata->radar_required = params->radar_required; - err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, - IEEE80211_CHANCTX_SHARED); - mutex_unlock(&local->mtx); -@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip - IEEE80211_P2P_OPPPS_ENABLE_BIT; - - err = ieee80211_assign_beacon(sdata, ¶ms->beacon); -- if (err < 0) -+ if (err < 0) { -+ ieee80211_vif_release_channel(sdata); - return err; -+ } - changed |= err; - - err = drv_start_ap(sdata->local, sdata); -@@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wip - if (old) - kfree_rcu(old, rcu_head); - RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); -+ ieee80211_vif_release_channel(sdata); - return err; - } - -@@ -1053,6 +1056,7 @@ static int ieee80211_change_beacon(struc - int err; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ sdata_assert_lock(sdata); - - /* don't allow changing the beacon while CSA is in place - offset - * of channel switch counter may change -@@ -1080,6 +1084,8 @@ static int ieee80211_stop_ap(struct wiph - struct probe_resp *old_probe_resp; - struct cfg80211_chan_def chandef; - -+ sdata_assert_lock(sdata); -+ - old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); - if (!old_beacon) - return -ENOENT; -@@ -1090,8 +1096,6 @@ static int ieee80211_stop_ap(struct wiph - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - -- cancel_work_sync(&sdata->u.ap.request_smps_work); -- - /* turn off carrier for this interface and dependent VLANs */ - list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) - netif_carrier_off(vlan->dev); -@@ -1103,6 +1107,7 @@ static int ieee80211_stop_ap(struct wiph - kfree_rcu(old_beacon, rcu_head); - if (old_probe_resp) - kfree_rcu(old_probe_resp, rcu_head); -+ sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; - - __sta_info_flush(sdata, true); - ieee80211_free_keys(sdata, true); -@@ -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); - -+ /* -+ * cookie is either the roc cookie (for normal roc) -+ * or the SKB (for mgmt TX) -+ */ -+ if (!txskb) { -+ /* local->mtx protects this */ -+ local->roc_cookie_counter++; -+ roc->cookie = local->roc_cookie_counter; -+ /* wow, you wrapped 64 bits ... more likely a bug */ -+ if (WARN_ON(roc->cookie == 0)) { -+ roc->cookie = 1; -+ local->roc_cookie_counter++; -+ } -+ *cookie = roc->cookie; -+ } else { -+ *cookie = (unsigned long)txskb; -+ } -+ - /* 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 +2798,6 @@ static int ieee80211_start_roc_work(stru - if (!queued) - list_add_tail(&roc->list, &local->roc_list); - -- /* -- * cookie is either the roc cookie (for normal roc) -- * or the SKB (for mgmt TX) -- */ -- if (!txskb) { -- /* local->mtx protects this */ -- local->roc_cookie_counter++; -- roc->cookie = local->roc_cookie_counter; -- /* wow, you wrapped 64 bits ... more likely a bug */ -- if (WARN_ON(roc->cookie == 0)) { -- roc->cookie = 1; -- local->roc_cookie_counter++; -- } -- *cookie = roc->cookie; -- } else { -- *cookie = (unsigned long)txskb; -- } -- - return 0; - } - -@@ -3004,8 +3012,10 @@ void ieee80211_csa_finalize_work(struct - if (!ieee80211_sdata_running(sdata)) - goto unlock; - -- sdata->radar_required = sdata->csa_radar_required; -+ sdata_assert_lock(sdata); -+ - mutex_lock(&local->mtx); -+ sdata->radar_required = sdata->csa_radar_required; - err = ieee80211_vif_change_channel(sdata, &changed); - mutex_unlock(&local->mtx); - if (WARN_ON(err < 0)) -@@ -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); -+ kfree(sdata->u.ap.next_beacon); -+ sdata->u.ap.next_beacon = NULL; -+ - if (err < 0) - goto unlock; - - changed |= err; -- kfree(sdata->u.ap.next_beacon); -- sdata->u.ap.next_beacon = NULL; -- - ieee80211_bss_info_change_notify(sdata, err); - break; - case NL80211_IFTYPE_ADHOC: -@@ -3066,7 +3076,7 @@ int ieee80211_channel_switch(struct wiph - struct ieee80211_if_mesh __maybe_unused *ifmsh; - int err, num_chanctx; - -- lockdep_assert_held(&sdata->wdev.mtx); -+ sdata_assert_lock(sdata); - - if (!list_empty(&local->roc_list) || local->scanning) - return -EBUSY; ---- a/net/mac80211/ht.c -+++ b/net/mac80211/ht.c -@@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee802 - mgmt->u.action.u.delba.params = cpu_to_le16(params); - mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); - -- ieee80211_tx_skb_tid(sdata, skb, tid); -+ ieee80211_tx_skb(sdata, skb); - } - - void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, -@@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(stru - u.ap.request_smps_work); - - sdata_lock(sdata); -- __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode); -+ if (sdata_dereference(sdata->u.ap.beacon, sdata)) -+ __ieee80211_request_smps_ap(sdata, -+ sdata->u.ap.driver_smps_mode); - sdata_unlock(sdata); - } - ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee - - ieee80211_roc_purge(local, sdata); - -- if (sdata->vif.type == NL80211_IFTYPE_STATION) -+ switch (sdata->vif.type) { -+ case NL80211_IFTYPE_STATION: - ieee80211_mgd_stop(sdata); -- -- if (sdata->vif.type == NL80211_IFTYPE_ADHOC) -+ break; -+ case NL80211_IFTYPE_ADHOC: - ieee80211_ibss_stop(sdata); -- -+ break; -+ case NL80211_IFTYPE_AP: -+ cancel_work_sync(&sdata->u.ap.request_smps_work); -+ break; -+ default: -+ break; -+ } - - /* - * Remove all stations associated with this interface. -@@ -827,7 +834,9 @@ static void ieee80211_do_stop(struct iee - cancel_work_sync(&local->dynamic_ps_enable_work); - - cancel_work_sync(&sdata->recalc_smps); -+ sdata_lock(sdata); - sdata->vif.csa_active = false; -+ sdata_unlock(sdata); - cancel_work_sync(&sdata->csa_finalize_work); - - cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -599,10 +599,10 @@ static int ieee80211_is_unicast_robust_m - { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - -- if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) -+ if (is_multicast_ether_addr(hdr->addr1)) - return 0; - -- return ieee80211_is_robust_mgmt_frame(hdr); -+ return ieee80211_is_robust_mgmt_frame(skb); - } - - -@@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust - { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - -- if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) -+ if (!is_multicast_ether_addr(hdr->addr1)) - return 0; - -- return ieee80211_is_robust_mgmt_frame(hdr); -+ return ieee80211_is_robust_mgmt_frame(skb); - } - - -@@ -626,7 +626,7 @@ static int ieee80211_get_mmie_keyidx(str - if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) - return -1; - -- if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) -+ if (!ieee80211_is_robust_mgmt_frame(skb)) - return -1; /* not a robust management frame */ - - mmie = (struct ieee80211_mmie *) -@@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info * - sta->sta.addr, sta->sta.aid); - - if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { -+ /* -+ * Clear the flag only if the other one is still set -+ * so that the TX path won't start TX'ing new frames -+ * directly ... In the case that the driver flag isn't -+ * set ieee80211_sta_ps_deliver_wakeup() will clear it. -+ */ -+ clear_sta_flag(sta, WLAN_STA_PS_STA); - ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n", - sta->sta.addr, sta->sta.aid); - return; -@@ -1311,18 +1318,15 @@ ieee80211_rx_h_sta_process(struct ieee80 - !ieee80211_has_morefrags(hdr->frame_control) && - !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && - (rx->sdata->vif.type == NL80211_IFTYPE_AP || -- rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { -+ rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && -+ /* PM bit is only checked in frames where it isn't reserved, -+ * in AP mode it's reserved in non-bufferable management frames -+ * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) -+ */ -+ (!ieee80211_is_mgmt(hdr->frame_control) || -+ ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { - if (test_sta_flag(sta, WLAN_STA_PS_STA)) { -- /* -- * Ignore doze->wake transitions that are -- * indicated by non-data frames, the standard -- * is unclear here, but for example going to -- * PS mode and then scanning would cause a -- * doze->wake transition for the probe request, -- * and that is clearly undesirable. -- */ -- if (ieee80211_is_data(hdr->frame_control) && -- !ieee80211_has_pm(hdr->frame_control)) -+ if (!ieee80211_has_pm(hdr->frame_control)) - sta_ps_end(sta); - } else { - if (ieee80211_has_pm(hdr->frame_control)) -@@ -1845,8 +1849,7 @@ static int ieee80211_drop_unencrypted_mg - * having configured keys. - */ - if (unlikely(ieee80211_is_action(fc) && !rx->key && -- ieee80211_is_robust_mgmt_frame( -- (struct ieee80211_hdr *) rx->skb->data))) -+ ieee80211_is_robust_mgmt_frame(rx->skb))) - return -EACCES; - } - ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, - if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) - return 0; - -- if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) -- skb->data)) -+ if (!ieee80211_is_robust_mgmt_frame(skb)) - return 0; - - return 1; -@@ -478,6 +477,20 @@ ieee80211_tx_h_unicast_ps_buf(struct iee - sta->sta.addr, sta->sta.aid, ac); - if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) - purge_old_ps_buffers(tx->local); -+ -+ /* sync with ieee80211_sta_ps_deliver_wakeup */ -+ spin_lock(&sta->ps_lock); -+ /* -+ * STA woke up the meantime and all the frames on ps_tx_buf have -+ * been queued to pending queue. No reordering can happen, go -+ * ahead and Tx the packet. -+ */ -+ if (!test_sta_flag(sta, WLAN_STA_PS_STA) && -+ !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { -+ spin_unlock(&sta->ps_lock); -+ return TX_CONTINUE; -+ } -+ - if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { - struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); - ps_dbg(tx->sdata, -@@ -492,6 +505,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee - info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; - info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; - skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); -+ spin_unlock(&sta->ps_lock); - - if (!timer_pending(&local->sta_cleanup)) - mod_timer(&local->sta_cleanup, -@@ -525,9 +539,7 @@ ieee80211_tx_h_ps_buf(struct ieee80211_t - - /* only deauth, disassoc and action are bufferable MMPDUs */ - if (ieee80211_is_mgmt(hdr->frame_control) && -- !ieee80211_is_deauth(hdr->frame_control) && -- !ieee80211_is_disassoc(hdr->frame_control) && -- !ieee80211_is_action(hdr->frame_control)) { -+ !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { - if (tx->flags & IEEE80211_TX_UNICAST) - info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; - return TX_CONTINUE; -@@ -567,7 +579,7 @@ ieee80211_tx_h_select_key(struct ieee802 - tx->key = key; - else if (ieee80211_is_mgmt(hdr->frame_control) && - is_multicast_ether_addr(hdr->addr1) && -- ieee80211_is_robust_mgmt_frame(hdr) && -+ ieee80211_is_robust_mgmt_frame(tx->skb) && - (key = rcu_dereference(tx->sdata->default_mgmt_key))) - tx->key = key; - else if (is_multicast_ether_addr(hdr->addr1) && -@@ -582,12 +594,12 @@ ieee80211_tx_h_select_key(struct ieee802 - tx->key = NULL; - else if (tx->skb->protocol == tx->sdata->control_port_protocol) - tx->key = NULL; -- else if (ieee80211_is_robust_mgmt_frame(hdr) && -+ else if (ieee80211_is_robust_mgmt_frame(tx->skb) && - !(ieee80211_is_action(hdr->frame_control) && - tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) - tx->key = NULL; - else if (ieee80211_is_mgmt(hdr->frame_control) && -- !ieee80211_is_robust_mgmt_frame(hdr)) -+ !ieee80211_is_robust_mgmt_frame(tx->skb)) - tx->key = NULL; - else { - I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); -@@ -878,7 +890,7 @@ static int ieee80211_fragment(struct iee - } - - /* adjust first fragment's length */ -- skb->len = hdrlen + per_fragm; -+ skb_trim(skb, hdrlen + per_fragm); - 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 - hdrlen = ieee80211_hdrlen(hdr->frame_control); - - if (!ieee80211_is_data(hdr->frame_control) && -- !ieee80211_is_robust_mgmt_frame(hdr)) -+ !ieee80211_is_robust_mgmt_frame(skb)) - return RX_CONTINUE; - - data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - ---- a/net/wireless/ap.c -+++ b/net/wireless/ap.c -@@ -27,9 +27,10 @@ static int __cfg80211_stop_ap(struct cfg - err = rdev_stop_ap(rdev, dev); - if (!err) { - wdev->beacon_interval = 0; -- wdev->channel = NULL; -+ memset(&wdev->chandef, 0, sizeof(wdev->chandef)); - wdev->ssid_len = 0; - rdev_set_qos_map(rdev, dev, NULL); -+ nl80211_send_ap_stopped(wdev); - } - - return err; ---- a/net/wireless/core.c -+++ b/net/wireless/core.c -@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg - - rdev->opencount--; - -- WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && -- !rdev->scan_req->notified); -+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) { -+ if (WARN_ON(!rdev->scan_req->notified)) -+ rdev->scan_req->aborted = true; -+ ___cfg80211_scan_done(rdev, false); -+ } - } - - static int cfg80211_rfkill_set_block(void *data, bool blocked) -@@ -447,9 +450,6 @@ int wiphy_register(struct wiphy *wiphy) - int i; - u16 ifmodes = wiphy->interface_modes; - -- /* support for 5/10 MHz is broken due to nl80211 API mess - disable */ -- wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ; -- - /* - * There are major locking problems in nl80211/mac80211 for CSA, - * disable for all drivers until this has been reworked. -@@ -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); -- WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && -- !rdev->scan_req->notified); -+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) { -+ if (WARN_ON(!rdev->scan_req->notified)) -+ rdev->scan_req->aborted = true; -+ ___cfg80211_scan_done(rdev, false); -+ } - - if (WARN_ON(rdev->sched_scan_req && - rdev->sched_scan_req->dev == wdev->netdev)) { ---- a/net/wireless/core.h -+++ b/net/wireless/core.h -@@ -62,6 +62,7 @@ struct cfg80211_registered_device { - struct rb_root bss_tree; - u32 bss_generation; - struct cfg80211_scan_request *scan_req; /* protected by RTNL */ -+ struct sk_buff *scan_msg; - struct cfg80211_sched_scan_request *sched_scan_req; - unsigned long suspend_at; - struct work_struct scan_done_wk; -@@ -210,6 +211,7 @@ struct cfg80211_event { - } dc; - struct { - u8 bssid[ETH_ALEN]; -+ struct ieee80211_channel *channel; - } ij; - }; - }; -@@ -257,7 +259,8 @@ int __cfg80211_leave_ibss(struct cfg8021 - struct net_device *dev, bool nowext); - int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, - struct net_device *dev, bool nowext); --void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); -+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, -+ struct ieee80211_channel *channel); - int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev); - -@@ -361,7 +364,8 @@ int cfg80211_validate_key_settings(struc - struct key_params *params, int key_idx, - bool pairwise, const u8 *mac_addr); - void __cfg80211_scan_done(struct work_struct *wk); --void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev); -+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, -+ bool send_message); - void __cfg80211_sched_scan_results(struct work_struct *wk); - int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, - bool driver_initiated); -@@ -441,7 +445,8 @@ static inline unsigned int elapsed_jiffi - void - cfg80211_get_chan_state(struct wireless_dev *wdev, - struct ieee80211_channel **chan, -- enum cfg80211_chan_mode *chanmode); -+ enum cfg80211_chan_mode *chanmode, -+ u8 *radar_detect); - - int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, - struct cfg80211_chan_def *chandef); ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -1723,9 +1723,10 @@ static int nl80211_dump_wiphy(struct sk_ - * We can then retry with the larger buffer. - */ - if ((ret == -ENOBUFS || ret == -EMSGSIZE) && -- !skb->len && -+ !skb->len && !state->split && - cb->min_dump_alloc < 4096) { - cb->min_dump_alloc = 4096; -+ state->split_start = 0; - rtnl_unlock(); - return 1; - } -@@ -2047,10 +2048,12 @@ static int nl80211_set_wiphy(struct sk_b - nla_for_each_nested(nl_txq_params, - info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], - rem_txq_params) { -- nla_parse(tb, NL80211_TXQ_ATTR_MAX, -- nla_data(nl_txq_params), -- nla_len(nl_txq_params), -- txq_params_policy); -+ result = nla_parse(tb, NL80211_TXQ_ATTR_MAX, -+ nla_data(nl_txq_params), -+ nla_len(nl_txq_params), -+ txq_params_policy); -+ if (result) -+ goto bad_res; - result = parse_txq_params(tb, &txq_params); - if (result) - goto bad_res; -@@ -3289,7 +3292,7 @@ static int nl80211_start_ap(struct sk_bu - if (!err) { - wdev->preset_chandef = params.chandef; - wdev->beacon_interval = params.beacon_interval; -- wdev->channel = params.chandef.chan; -+ wdev->chandef = params.chandef; - wdev->ssid_len = params.ssid_len; - memcpy(wdev->ssid, params.ssid, wdev->ssid_len); - } -@@ -5210,9 +5213,11 @@ static int nl80211_set_reg(struct sk_buf - - nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], - rem_reg_rules) { -- nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, -- nla_data(nl_reg_rule), nla_len(nl_reg_rule), -- reg_rule_policy); -+ r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, -+ nla_data(nl_reg_rule), nla_len(nl_reg_rule), -+ reg_rule_policy); -+ if (r) -+ goto bad_reg; - r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); - if (r) - goto bad_reg; -@@ -5277,7 +5282,7 @@ static int nl80211_trigger_scan(struct s - if (!rdev->ops->scan) - return -EOPNOTSUPP; - -- if (rdev->scan_req) { -+ if (rdev->scan_req || rdev->scan_msg) { - err = -EBUSY; - goto unlock; - } -@@ -5475,6 +5480,7 @@ static int nl80211_start_sched_scan(stru - enum ieee80211_band band; - size_t ie_len; - struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; -+ s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF; - - if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || - !rdev->ops->sched_scan_start) -@@ -5509,11 +5515,40 @@ static int nl80211_start_sched_scan(stru - if (n_ssids > wiphy->max_sched_scan_ssids) - return -EINVAL; - -- if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) -+ /* -+ * First, count the number of 'real' matchsets. Due to an issue with -+ * the old implementation, matchsets containing only the RSSI attribute -+ * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default' -+ * RSSI for all matchsets, rather than their own matchset for reporting -+ * all APs with a strong RSSI. This is needed to be compatible with -+ * older userspace that treated a matchset with only the RSSI as the -+ * global RSSI for all other matchsets - if there are other matchsets. -+ */ -+ if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) { - nla_for_each_nested(attr, - info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], -- tmp) -- n_match_sets++; -+ tmp) { -+ struct nlattr *rssi; -+ -+ err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, -+ nla_data(attr), nla_len(attr), -+ nl80211_match_policy); -+ if (err) -+ return err; -+ /* add other standalone attributes here */ -+ if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) { -+ n_match_sets++; -+ continue; -+ } -+ rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; -+ if (rssi) -+ default_match_rssi = nla_get_s32(rssi); -+ } -+ } -+ -+ /* However, if there's no other matchset, add the RSSI one */ -+ if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF) -+ n_match_sets = 1; - - if (n_match_sets > wiphy->max_match_sets) - return -EINVAL; -@@ -5634,11 +5669,22 @@ static int nl80211_start_sched_scan(stru - tmp) { - struct nlattr *ssid, *rssi; - -- nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, -- nla_data(attr), nla_len(attr), -- nl80211_match_policy); -+ err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, -+ nla_data(attr), nla_len(attr), -+ nl80211_match_policy); -+ if (err) -+ goto out_free; - ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]; - if (ssid) { -+ if (WARN_ON(i >= n_match_sets)) { -+ /* this indicates a programming error, -+ * the loop above should have verified -+ * things properly -+ */ -+ err = -EINVAL; -+ goto out_free; -+ } -+ - if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { - err = -EINVAL; - goto out_free; -@@ -5647,15 +5693,28 @@ static int nl80211_start_sched_scan(stru - nla_data(ssid), nla_len(ssid)); - request->match_sets[i].ssid.ssid_len = - nla_len(ssid); -+ /* special attribute - old implemenation w/a */ -+ request->match_sets[i].rssi_thold = -+ default_match_rssi; -+ rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; -+ if (rssi) -+ request->match_sets[i].rssi_thold = -+ nla_get_s32(rssi); - } -- rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; -- if (rssi) -- request->rssi_thold = nla_get_u32(rssi); -- else -- request->rssi_thold = -- NL80211_SCAN_RSSI_THOLD_OFF; - i++; - } -+ -+ /* there was no other matchset, so the RSSI one is alone */ -+ if (i == 0) -+ request->match_sets[0].rssi_thold = default_match_rssi; -+ -+ request->min_rssi_thold = INT_MAX; -+ for (i = 0; i < n_match_sets; i++) -+ request->min_rssi_thold = -+ min(request->match_sets[i].rssi_thold, -+ request->min_rssi_thold); -+ } else { -+ request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF; - } - - if (info->attrs[NL80211_ATTR_IE]) { -@@ -5751,7 +5810,7 @@ static int nl80211_start_radar_detection - - err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); - if (!err) { -- wdev->channel = chandef.chan; -+ wdev->chandef = chandef; - wdev->cac_started = true; - wdev->cac_start_time = jiffies; - } -@@ -7502,16 +7561,19 @@ static int nl80211_set_tx_bitrate_mask(s - * directly to the enum ieee80211_band values used in cfg80211. - */ - BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); -- nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) -- { -+ nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) { - enum ieee80211_band band = nla_type(tx_rates); -+ int err; -+ - if (band < 0 || band >= IEEE80211_NUM_BANDS) - return -EINVAL; - sband = rdev->wiphy.bands[band]; - if (sband == NULL) - return -EINVAL; -- nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), -- nla_len(tx_rates), nl80211_txattr_policy); -+ err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), -+ nla_len(tx_rates), nl80211_txattr_policy); -+ if (err) -+ return err; - if (tb[NL80211_TXRATE_LEGACY]) { - mask.control[band].legacy = rateset_to_mask( - sband, -@@ -10054,40 +10116,31 @@ void nl80211_send_scan_start(struct cfg8 - NL80211_MCGRP_SCAN, GFP_KERNEL); - } - --void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, -- struct wireless_dev *wdev) -+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, -+ struct wireless_dev *wdev, bool aborted) - { - struct sk_buff *msg; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) -- return; -+ return NULL; - - if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, -- NL80211_CMD_NEW_SCAN_RESULTS) < 0) { -+ aborted ? NL80211_CMD_SCAN_ABORTED : -+ NL80211_CMD_NEW_SCAN_RESULTS) < 0) { - nlmsg_free(msg); -- return; -+ return NULL; - } - -- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, -- NL80211_MCGRP_SCAN, GFP_KERNEL); -+ return msg; - } - --void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, -- struct wireless_dev *wdev) -+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, -+ struct sk_buff *msg) - { -- struct sk_buff *msg; -- -- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return; - -- if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, -- NL80211_CMD_SCAN_ABORTED) < 0) { -- nlmsg_free(msg); -- return; -- } -- - genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, - NL80211_MCGRP_SCAN, GFP_KERNEL); - } -@@ -11158,7 +11211,8 @@ void cfg80211_ch_switch_notify(struct ne - wdev->iftype != NL80211_IFTYPE_MESH_POINT)) - return; - -- wdev->channel = chandef->chan; -+ wdev->chandef = *chandef; -+ wdev->preset_chandef = *chandef; - nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); - } - EXPORT_SYMBOL(cfg80211_ch_switch_notify); -@@ -11673,6 +11727,35 @@ void cfg80211_crit_proto_stopped(struct - } - EXPORT_SYMBOL(cfg80211_crit_proto_stopped); - -+void nl80211_send_ap_stopped(struct wireless_dev *wdev) -+{ -+ struct wiphy *wiphy = wdev->wiphy; -+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); -+ struct sk_buff *msg; -+ void *hdr; -+ -+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); -+ if (!msg) -+ return; -+ -+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP); -+ if (!hdr) -+ goto out; -+ -+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || -+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) || -+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) -+ goto out; -+ -+ genlmsg_end(msg, hdr); -+ -+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0, -+ NL80211_MCGRP_MLME, GFP_KERNEL); -+ return; -+ out: -+ nlmsg_free(msg); -+} -+ - /* initialisation/exit functions */ - - int nl80211_init(void) ---- a/net/wireless/nl80211.h -+++ b/net/wireless/nl80211.h -@@ -8,10 +8,10 @@ void nl80211_exit(void); - void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); - void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev); --void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, -- struct wireless_dev *wdev); --void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, -- struct wireless_dev *wdev); -+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, -+ struct wireless_dev *wdev, bool aborted); -+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, -+ struct sk_buff *msg); - void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, - struct net_device *netdev, u32 cmd); - void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, -@@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_reg - enum nl80211_radar_event event, - struct net_device *netdev, gfp_t gfp); - -+void nl80211_send_ap_stopped(struct wireless_dev *wdev); -+ - void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev); - - #endif /* __NET_WIRELESS_NL80211_H */ ---- a/net/wireless/scan.c -+++ b/net/wireless/scan.c -@@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct - dev->bss_generation++; - } - --void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) -+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, -+ bool send_message) - { - struct cfg80211_scan_request *request; - struct wireless_dev *wdev; -+ struct sk_buff *msg; - #ifdef CPTCFG_CFG80211_WEXT - union iwreq_data wrqu; - #endif - - ASSERT_RTNL(); - -- request = rdev->scan_req; -+ if (rdev->scan_msg) { -+ nl80211_send_scan_result(rdev, rdev->scan_msg); -+ rdev->scan_msg = NULL; -+ return; -+ } - -+ request = rdev->scan_req; - if (!request) - return; - -@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802 - if (wdev->netdev) - cfg80211_sme_scan_done(wdev->netdev); - -- if (request->aborted) { -- nl80211_send_scan_aborted(rdev, wdev); -- } else { -- if (request->flags & NL80211_SCAN_FLAG_FLUSH) { -- /* flush entries from previous scans */ -- spin_lock_bh(&rdev->bss_lock); -- __cfg80211_bss_expire(rdev, request->scan_start); -- spin_unlock_bh(&rdev->bss_lock); -- } -- nl80211_send_scan_done(rdev, wdev); -+ if (!request->aborted && -+ request->flags & NL80211_SCAN_FLAG_FLUSH) { -+ /* flush entries from previous scans */ -+ spin_lock_bh(&rdev->bss_lock); -+ __cfg80211_bss_expire(rdev, request->scan_start); -+ spin_unlock_bh(&rdev->bss_lock); - } - -+ msg = nl80211_build_scan_msg(rdev, wdev, request->aborted); -+ - #ifdef CPTCFG_CFG80211_WEXT - if (wdev->netdev && !request->aborted) { - memset(&wrqu, 0, sizeof(wrqu)); -@@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg802 - - rdev->scan_req = NULL; - kfree(request); -+ -+ if (!send_message) -+ rdev->scan_msg = msg; -+ else -+ nl80211_send_scan_result(rdev, msg); - } - - void __cfg80211_scan_done(struct work_struct *wk) -@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st - scan_done_wk); - - rtnl_lock(); -- ___cfg80211_scan_done(rdev); -+ ___cfg80211_scan_done(rdev, true); - rtnl_unlock(); - } - -@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev - if (IS_ERR(rdev)) - return PTR_ERR(rdev); - -- if (rdev->scan_req) { -+ if (rdev->scan_req || rdev->scan_msg) { - err = -EBUSY; - goto out; - } -@@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_dev - if (IS_ERR(rdev)) - return PTR_ERR(rdev); - -- if (rdev->scan_req) -+ if (rdev->scan_req || rdev->scan_msg) - return -EAGAIN; - - res = ieee80211_scan_results(rdev, info, extra, data->length); ---- a/net/wireless/sme.c -+++ b/net/wireless/sme.c -@@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wir - ASSERT_RDEV_LOCK(rdev); - ASSERT_WDEV_LOCK(wdev); - -- if (rdev->scan_req) -+ if (rdev->scan_req || rdev->scan_msg) - return -EBUSY; - - if (wdev->conn->params.channel) ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -1001,7 +1001,6 @@ ieee80211_sta_process_chanswitch(struct - } - - ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; -- sdata->vif.csa_active = true; - - mutex_lock(&local->chanctx_mtx); - if (local->use_chanctx) { -@@ -1039,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct - mutex_unlock(&local->chanctx_mtx); - - sdata->csa_chandef = csa_ie.chandef; -+ sdata->vif.csa_active = true; - - if (csa_ie.mode) - ieee80211_stop_queues_by_reason(&local->hw, ---- a/net/mac80211/chan.c -+++ b/net/mac80211/chan.c -@@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required( - { - struct ieee80211_sub_if_data *sdata; - -+ lockdep_assert_held(&local->mtx); -+ - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (sdata->radar_required) { ---- a/net/mac80211/ibss.c -+++ b/net/mac80211/ibss.c -@@ -294,7 +294,6 @@ static void __ieee80211_sta_join_ibss(st - } - - mutex_lock(&local->mtx); -- ieee80211_vif_release_channel(sdata); - if (ieee80211_vif_use_channel(sdata, &chandef, - ifibss->fixed_channel ? - IEEE80211_CHANCTX_SHARED : -@@ -303,6 +302,7 @@ static void __ieee80211_sta_join_ibss(st - mutex_unlock(&local->mtx); - return; - } -+ sdata->radar_required = radar_required; - mutex_unlock(&local->mtx); - - memcpy(ifibss->bssid, bssid, ETH_ALEN); -@@ -318,7 +318,6 @@ static void __ieee80211_sta_join_ibss(st - rcu_assign_pointer(ifibss->presp, presp); - mgmt = (void *)presp->head; - -- sdata->radar_required = radar_required; - sdata->vif.bss_conf.enable_beacon = true; - sdata->vif.bss_conf.beacon_int = beacon_int; - sdata->vif.bss_conf.basic_rates = basic_rates; -@@ -386,7 +385,7 @@ static void __ieee80211_sta_join_ibss(st - presp->head_len, 0, GFP_KERNEL); - cfg80211_put_bss(local->hw.wiphy, bss); - netif_carrier_on(sdata->dev); -- cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); -+ cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL); - } - - static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, -@@ -802,6 +801,8 @@ ieee80211_ibss_process_chanswitch(struct - int err; - u32 sta_flags; - -+ sdata_assert_lock(sdata); -+ - sta_flags = IEEE80211_STA_DISABLE_VHT; - switch (ifibss->chandef.width) { - case NL80211_CHAN_WIDTH_5: -@@ -1471,6 +1472,11 @@ static void ieee80211_rx_mgmt_probe_req( - memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN); - ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa); - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; -+ -+ /* avoid excessive retries for probe request to wildcard SSIDs */ -+ if (pos[1] == 0) -+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK; -+ - ieee80211_tx_skb(sdata, skb); - } - ---- a/net/mac80211/mesh.c -+++ b/net/mac80211/mesh.c -@@ -872,6 +872,8 @@ ieee80211_mesh_process_chnswitch(struct - if (!ifmsh->mesh_id) - return false; - -+ sdata_assert_lock(sdata); -+ - sta_flags = IEEE80211_STA_DISABLE_VHT; - switch (sdata->vif.bss_conf.chandef.width) { - case NL80211_CHAN_WIDTH_20_NOHT: ---- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c -+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c -@@ -4658,6 +4658,7 @@ brcmf_notify_connect_status(struct brcmf - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; - struct net_device *ndev = ifp->ndev; - struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; -+ struct ieee80211_channel *chan; - s32 err = 0; - - if (ifp->vif->mode == WL_MODE_AP) { -@@ -4665,9 +4666,10 @@ brcmf_notify_connect_status(struct brcmf - } else if (brcmf_is_linkup(e)) { - brcmf_dbg(CONN, "Linkup\n"); - if (brcmf_is_ibssmode(ifp->vif)) { -+ chan = ieee80211_get_channel(cfg->wiphy, cfg->channel); - memcpy(profile->bssid, e->addr, ETH_ALEN); - wl_inform_ibss(cfg, ndev, e->addr); -- cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); -+ cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL); - clear_bit(BRCMF_VIF_STATUS_CONNECTING, - &ifp->vif->sme_state); - set_bit(BRCMF_VIF_STATUS_CONNECTED, ---- a/drivers/net/wireless/libertas/cfg.c -+++ b/drivers/net/wireless/libertas/cfg.c -@@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_pri - memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); - priv->wdev->ssid_len = params->ssid_len; - -- cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL); -+ cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan, -+ GFP_KERNEL); - - /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */ - priv->connect_status = LBS_CONNECTED; ---- a/drivers/net/wireless/mwifiex/cfg80211.c -+++ b/drivers/net/wireless/mwifiex/cfg80211.c -@@ -1881,7 +1881,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy - params->privacy); - done: - if (!ret) { -- cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); -+ cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, -+ params->chandef.chan, GFP_KERNEL); - dev_dbg(priv->adapter->dev, - "info: joined/created adhoc network with bssid" - " %pM successfully\n", priv->cfg_bssid); ---- a/drivers/net/wireless/rndis_wlan.c -+++ b/drivers/net/wireless/rndis_wlan.c -@@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(s - bssid, req_ie, req_ie_len, - resp_ie, resp_ie_len, GFP_KERNEL); - } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) -- cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); -+ cfg80211_ibss_joined(usbdev->net, bssid, -+ get_current_channel(usbdev, NULL), -+ GFP_KERNEL); - - kfree(info); - ---- a/net/wireless/ibss.c -+++ b/net/wireless/ibss.c -@@ -14,7 +14,8 @@ - #include "rdev-ops.h" - - --void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) -+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, -+ struct ieee80211_channel *channel) - { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_bss *bss; -@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_d - if (!wdev->ssid_len) - return; - -- bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, -- wdev->ssid, wdev->ssid_len, -+ bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0, - WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); - - if (WARN_ON(!bss)) -@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_d - #endif - } - --void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) -+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, -+ struct ieee80211_channel *channel, gfp_t gfp) - { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - struct cfg80211_event *ev; - unsigned long flags; - -- trace_cfg80211_ibss_joined(dev, bssid); -+ trace_cfg80211_ibss_joined(dev, bssid, channel); -+ -+ if (WARN_ON(!channel)) -+ return; - - ev = kzalloc(sizeof(*ev), gfp); - if (!ev) - return; - - ev->type = EVENT_IBSS_JOINED; -- memcpy(ev->cr.bssid, bssid, ETH_ALEN); -+ memcpy(ev->ij.bssid, bssid, ETH_ALEN); -+ ev->ij.channel = channel; - - spin_lock_irqsave(&wdev->event_lock, flags); - list_add_tail(&ev->list, &wdev->event_list); -@@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211 - - wdev->ibss_fixed = params->channel_fixed; - wdev->ibss_dfs_possible = params->userspace_handles_dfs; -+ wdev->chandef = params->chandef; - #ifdef CPTCFG_CFG80211_WEXT - wdev->wext.ibss.chandef = params->chandef; - #endif -@@ -200,6 +206,7 @@ static void __cfg80211_clear_ibss(struct - - wdev->current_bss = NULL; - wdev->ssid_len = 0; -+ memset(&wdev->chandef, 0, sizeof(wdev->chandef)); - #ifdef CPTCFG_CFG80211_WEXT - if (!nowext) - wdev->wext.ibss.ssid_len = 0; ---- a/net/wireless/trace.h -+++ b/net/wireless/trace.h -@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt, - TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) - ); - --DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined, -- TP_PROTO(struct net_device *netdev, const u8 *addr), -- TP_ARGS(netdev, addr) --); -- - DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame, - TP_PROTO(struct net_device *netdev, const u8 *addr), - TP_ARGS(netdev, addr) -@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_r - TP_ARGS(netdev, addr) - ); - -+TRACE_EVENT(cfg80211_ibss_joined, -+ TP_PROTO(struct net_device *netdev, const u8 *bssid, -+ struct ieee80211_channel *channel), -+ TP_ARGS(netdev, bssid, channel), -+ TP_STRUCT__entry( -+ NETDEV_ENTRY -+ MAC_ENTRY(bssid) -+ CHAN_ENTRY -+ ), -+ TP_fast_assign( -+ NETDEV_ASSIGN; -+ MAC_ASSIGN(bssid, bssid); -+ CHAN_ASSIGN(channel); -+ ), -+ TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT, -+ NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) -+); -+ - TRACE_EVENT(cfg80211_probe_status, - TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie, - bool acked), ---- a/net/wireless/util.c -+++ b/net/wireless/util.c -@@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct - ev->dc.reason, true); - break; - case EVENT_IBSS_JOINED: -- __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid); -+ __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, -+ ev->ij.channel); - break; - } - wdev_unlock(wdev); -@@ -1356,7 +1357,7 @@ int cfg80211_can_use_iftype_chan(struct - */ - mutex_lock_nested(&wdev_iter->mtx, 1); - __acquire(wdev_iter->mtx); -- cfg80211_get_chan_state(wdev_iter, &ch, &chmode); -+ cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect); - wdev_unlock(wdev_iter); - - switch (chmode) { ---- a/net/wireless/chan.c -+++ b/net/wireless/chan.c -@@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct - void - cfg80211_get_chan_state(struct wireless_dev *wdev, - struct ieee80211_channel **chan, -- enum cfg80211_chan_mode *chanmode) -+ enum cfg80211_chan_mode *chanmode, -+ u8 *radar_detect) - { - *chan = NULL; - *chanmode = CHAN_MODE_UNDEFINED; -@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_ - !wdev->ibss_dfs_possible) - ? CHAN_MODE_SHARED - : CHAN_MODE_EXCLUSIVE; -+ -+ /* consider worst-case - IBSS can try to return to the -+ * original user-specified channel as creator */ -+ if (wdev->ibss_dfs_possible) -+ *radar_detect |= BIT(wdev->chandef.width); - return; - } - break; -@@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_ - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_GO: - if (wdev->cac_started) { -- *chan = wdev->channel; -+ *chan = wdev->chandef.chan; - *chanmode = CHAN_MODE_SHARED; -+ *radar_detect |= BIT(wdev->chandef.width); - } else if (wdev->beacon_interval) { -- *chan = wdev->channel; -+ *chan = wdev->chandef.chan; - *chanmode = CHAN_MODE_SHARED; -+ -+ if (cfg80211_chandef_dfs_required(wdev->wiphy, -+ &wdev->chandef)) -+ *radar_detect |= BIT(wdev->chandef.width); - } - return; - case NL80211_IFTYPE_MESH_POINT: - if (wdev->mesh_id_len) { -- *chan = wdev->channel; -+ *chan = wdev->chandef.chan; - *chanmode = CHAN_MODE_SHARED; -+ -+ if (cfg80211_chandef_dfs_required(wdev->wiphy, -+ &wdev->chandef)) -+ *radar_detect |= BIT(wdev->chandef.width); - } - return; - case NL80211_IFTYPE_MONITOR: ---- a/net/wireless/mesh.c -+++ b/net/wireless/mesh.c -@@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211 - if (!err) { - memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); - wdev->mesh_id_len = setup->mesh_id_len; -- wdev->channel = setup->chandef.chan; -+ wdev->chandef = setup->chandef; - } - - return err; -@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg - err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, - chandef->chan); - if (!err) -- wdev->channel = chandef->chan; -+ wdev->chandef = *chandef; - - return err; - } -@@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct - err = rdev_leave_mesh(rdev, dev); - if (!err) { - wdev->mesh_id_len = 0; -- wdev->channel = NULL; -+ memset(&wdev->chandef, 0, sizeof(wdev->chandef)); - rdev_set_qos_map(rdev, dev, NULL); - } - ---- a/net/wireless/mlme.c -+++ b/net/wireless/mlme.c -@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_devic - if (WARN_ON(!wdev->cac_started)) - return; - -- if (WARN_ON(!wdev->channel)) -+ if (WARN_ON(!wdev->chandef.chan)) - return; - - switch (event) { ---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c -@@ -5065,6 +5065,10 @@ static u16 ar9003_hw_get_max_edge_power( - break; - } - } -+ -+ if (is2GHz && !twiceMaxEdgePower) -+ twiceMaxEdgePower = 60; -+ - return twiceMaxEdgePower; - } - ---- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c -@@ -23,10 +23,11 @@ - #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT - #define MAX_MAG_DELTA 11 - #define MAX_PHS_DELTA 10 -+#define MAXIQCAL 3 - - struct coeff { -- int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; -- int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; -+ int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL]; -+ int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL]; - int iqc_coeff[2]; - }; - -@@ -800,7 +801,7 @@ static bool ar9003_hw_calc_iq_corr(struc - if (q_q_coff > 63) - q_q_coff = 63; - -- iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; -+ iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff); - - ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n", - chain_idx, iqc_coeff[0]); -@@ -831,7 +832,7 @@ static bool ar9003_hw_calc_iq_corr(struc - if (q_q_coff > 63) - q_q_coff = 63; - -- iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; -+ iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff); - - ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n", - chain_idx, iqc_coeff[1]); -@@ -839,7 +840,8 @@ static bool ar9003_hw_calc_iq_corr(struc - return true; - } - --static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, -+static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL], -+ int nmeasurement, - int max_delta) - { - int mp_max = -64, max_idx = 0; -@@ -848,20 +850,20 @@ static void ar9003_hw_detect_outlier(int - - /* find min/max mismatch across all calibrated gains */ - for (i = 0; i < nmeasurement; i++) { -- if (mp_coeff[i] > mp_max) { -- mp_max = mp_coeff[i]; -+ if (mp_coeff[i][0] > mp_max) { -+ mp_max = mp_coeff[i][0]; - max_idx = i; -- } else if (mp_coeff[i] < mp_min) { -- mp_min = mp_coeff[i]; -+ } else if (mp_coeff[i][0] < mp_min) { -+ mp_min = mp_coeff[i][0]; - min_idx = i; - } - } - - /* find average (exclude max abs value) */ - for (i = 0; i < nmeasurement; i++) { -- if ((abs(mp_coeff[i]) < abs(mp_max)) || -- (abs(mp_coeff[i]) < abs(mp_min))) { -- mp_avg += mp_coeff[i]; -+ if ((abs(mp_coeff[i][0]) < abs(mp_max)) || -+ (abs(mp_coeff[i][0]) < abs(mp_min))) { -+ mp_avg += mp_coeff[i][0]; - mp_count++; - } - } -@@ -873,7 +875,7 @@ static void ar9003_hw_detect_outlier(int - if (mp_count) - mp_avg /= mp_count; - else -- mp_avg = mp_coeff[nmeasurement - 1]; -+ mp_avg = mp_coeff[nmeasurement - 1][0]; - - /* detect outlier */ - if (abs(mp_max - mp_min) > max_delta) { -@@ -882,15 +884,16 @@ static void ar9003_hw_detect_outlier(int - else - outlier_idx = min_idx; - -- mp_coeff[outlier_idx] = mp_avg; -+ mp_coeff[outlier_idx][0] = mp_avg; - } - } - --static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, -- struct coeff *coeff, -- bool is_reusable) -+static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah, -+ struct coeff *coeff, -+ bool is_reusable) - { - int i, im, nmeasurement; -+ int magnitude, phase; - u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; - struct ath9k_hw_cal_data *caldata = ah->caldata; - -@@ -920,21 +923,30 @@ static void ar9003_hw_tx_iqcal_load_avg_ - if (nmeasurement > MAX_MEASUREMENT) - nmeasurement = MAX_MEASUREMENT; - -- /* detect outlier only if nmeasurement > 1 */ -- if (nmeasurement > 1) { -- /* Detect magnitude outlier */ -- ar9003_hw_detect_outlier(coeff->mag_coeff[i], -- nmeasurement, MAX_MAG_DELTA); -- -- /* Detect phase outlier */ -- ar9003_hw_detect_outlier(coeff->phs_coeff[i], -- nmeasurement, MAX_PHS_DELTA); -+ /* -+ * Skip normal outlier detection for AR9550. -+ */ -+ if (!AR_SREV_9550(ah)) { -+ /* detect outlier only if nmeasurement > 1 */ -+ if (nmeasurement > 1) { -+ /* Detect magnitude outlier */ -+ ar9003_hw_detect_outlier(coeff->mag_coeff[i], -+ nmeasurement, -+ MAX_MAG_DELTA); -+ -+ /* Detect phase outlier */ -+ ar9003_hw_detect_outlier(coeff->phs_coeff[i], -+ nmeasurement, -+ MAX_PHS_DELTA); -+ } - } - - for (im = 0; im < nmeasurement; im++) { -+ magnitude = coeff->mag_coeff[i][im][0]; -+ phase = coeff->phs_coeff[i][im][0]; - -- coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | -- ((coeff->phs_coeff[i][im] & 0x7f) << 7); -+ coeff->iqc_coeff[0] = -+ (phase & 0x7f) | ((magnitude & 0x7f) << 7); - - if ((im % 2) == 0) - REG_RMW_FIELD(ah, tx_corr_coeff[im][i], -@@ -991,7 +1003,63 @@ static bool ar9003_hw_tx_iq_cal_run(stru - return true; - } - --static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) -+static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah, -+ struct coeff *coeff, -+ int i, int nmeasurement) -+{ -+ struct ath_common *common = ath9k_hw_common(ah); -+ int im, ix, iy, temp; -+ -+ for (im = 0; im < nmeasurement; im++) { -+ for (ix = 0; ix < MAXIQCAL - 1; ix++) { -+ for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) { -+ if (coeff->mag_coeff[i][im][iy] < -+ coeff->mag_coeff[i][im][ix]) { -+ temp = coeff->mag_coeff[i][im][ix]; -+ coeff->mag_coeff[i][im][ix] = -+ coeff->mag_coeff[i][im][iy]; -+ coeff->mag_coeff[i][im][iy] = temp; -+ } -+ if (coeff->phs_coeff[i][im][iy] < -+ coeff->phs_coeff[i][im][ix]) { -+ temp = coeff->phs_coeff[i][im][ix]; -+ coeff->phs_coeff[i][im][ix] = -+ coeff->phs_coeff[i][im][iy]; -+ coeff->phs_coeff[i][im][iy] = temp; -+ } -+ } -+ } -+ coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2]; -+ coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2]; -+ -+ ath_dbg(common, CALIBRATE, -+ "IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n", -+ i, im, -+ coeff->mag_coeff[i][im][0], -+ coeff->phs_coeff[i][im][0]); -+ } -+} -+ -+static bool ar955x_tx_iq_cal_median(struct ath_hw *ah, -+ struct coeff *coeff, -+ int iqcal_idx, -+ int nmeasurement) -+{ -+ int i; -+ -+ if ((iqcal_idx + 1) != MAXIQCAL) -+ return false; -+ -+ for (i = 0; i < AR9300_MAX_CHAINS; i++) { -+ __ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement); -+ } -+ -+ return true; -+} -+ -+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, -+ int iqcal_idx, -+ bool is_reusable) - { - struct ath_common *common = ath9k_hw_common(ah); - const u32 txiqcal_status[AR9300_MAX_CHAINS] = { -@@ -1004,10 +1072,11 @@ static void ar9003_hw_tx_iq_cal_post_pro - AR_PHY_CHAN_INFO_TAB_1, - AR_PHY_CHAN_INFO_TAB_2, - }; -- struct coeff coeff; -+ static struct coeff coeff; - s32 iq_res[6]; - int i, im, j; -- int nmeasurement; -+ int nmeasurement = 0; -+ bool outlier_detect = true; - - for (i = 0; i < AR9300_MAX_CHAINS; i++) { - if (!(ah->txchainmask & (1 << i))) -@@ -1065,17 +1134,23 @@ static void ar9003_hw_tx_iq_cal_post_pro - goto tx_iqcal_fail; - } - -- coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; -- coeff.phs_coeff[i][im] = -+ coeff.phs_coeff[i][im][iqcal_idx] = -+ coeff.iqc_coeff[0] & 0x7f; -+ coeff.mag_coeff[i][im][iqcal_idx] = - (coeff.iqc_coeff[0] >> 7) & 0x7f; - -- if (coeff.mag_coeff[i][im] > 63) -- coeff.mag_coeff[i][im] -= 128; -- if (coeff.phs_coeff[i][im] > 63) -- coeff.phs_coeff[i][im] -= 128; -+ if (coeff.mag_coeff[i][im][iqcal_idx] > 63) -+ coeff.mag_coeff[i][im][iqcal_idx] -= 128; -+ if (coeff.phs_coeff[i][im][iqcal_idx] > 63) -+ coeff.phs_coeff[i][im][iqcal_idx] -= 128; - } - } -- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable); -+ -+ if (AR_SREV_9550(ah)) -+ outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff, -+ iqcal_idx, nmeasurement); -+ if (outlier_detect) -+ ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable); - - return; - -@@ -1409,7 +1484,7 @@ skip_tx_iqcal: - } - - if (txiqcal_done) -- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); -+ ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable); - else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags)) - ar9003_hw_tx_iq_cal_reload(ah); - -@@ -1455,14 +1530,38 @@ skip_tx_iqcal: - return true; - } - -+static bool do_ar9003_agc_cal(struct ath_hw *ah) -+{ -+ struct ath_common *common = ath9k_hw_common(ah); -+ bool status; -+ -+ REG_WRITE(ah, AR_PHY_AGC_CONTROL, -+ REG_READ(ah, AR_PHY_AGC_CONTROL) | -+ AR_PHY_AGC_CONTROL_CAL); -+ -+ status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, -+ AR_PHY_AGC_CONTROL_CAL, -+ 0, AH_WAIT_TIMEOUT); -+ if (!status) { -+ ath_dbg(common, CALIBRATE, -+ "offset calibration failed to complete in %d ms," -+ "noisy environment?\n", -+ AH_WAIT_TIMEOUT / 1000); -+ return false; -+ } -+ -+ return true; -+} -+ - static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, - struct ath9k_channel *chan) - { - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_cal_data *caldata = ah->caldata; - bool txiqcal_done = false; -- bool is_reusable = true, status = true; -+ bool status = true; - bool run_agc_cal = false, sep_iq_cal = false; -+ int i = 0; - - /* Use chip chainmask only for calibration */ - ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); -@@ -1485,7 +1584,12 @@ static bool ar9003_hw_init_cal_soc(struc - * AGC calibration. Specifically, AR9550 in SoC chips. - */ - if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) { -- txiqcal_done = true; -+ if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0, -+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) { -+ txiqcal_done = true; -+ } else { -+ txiqcal_done = false; -+ } - run_agc_cal = true; - } else { - sep_iq_cal = true; -@@ -1512,27 +1616,37 @@ skip_tx_iqcal: - if (AR_SREV_9330_11(ah)) - ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan)); - -- /* Calibrate the AGC */ -- REG_WRITE(ah, AR_PHY_AGC_CONTROL, -- REG_READ(ah, AR_PHY_AGC_CONTROL) | -- AR_PHY_AGC_CONTROL_CAL); -- -- /* Poll for offset calibration complete */ -- status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, -- AR_PHY_AGC_CONTROL_CAL, -- 0, AH_WAIT_TIMEOUT); -- } -+ /* -+ * For non-AR9550 chips, we just trigger AGC calibration -+ * in the HW, poll for completion and then process -+ * the results. -+ * -+ * For AR955x, we run it multiple times and use -+ * median IQ correction. -+ */ -+ if (!AR_SREV_9550(ah)) { -+ status = do_ar9003_agc_cal(ah); -+ if (!status) -+ return false; - -- if (!status) { -- ath_dbg(common, CALIBRATE, -- "offset calibration failed to complete in %d ms; noisy environment?\n", -- AH_WAIT_TIMEOUT / 1000); -- return false; -+ if (txiqcal_done) -+ ar9003_hw_tx_iq_cal_post_proc(ah, 0, false); -+ } else { -+ if (!txiqcal_done) { -+ status = do_ar9003_agc_cal(ah); -+ if (!status) -+ return false; -+ } else { -+ for (i = 0; i < MAXIQCAL; i++) { -+ status = do_ar9003_agc_cal(ah); -+ if (!status) -+ return false; -+ ar9003_hw_tx_iq_cal_post_proc(ah, i, false); -+ } -+ } -+ } - } - -- if (txiqcal_done) -- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); -- - /* Revert chainmask to runtime parameters */ - ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); - ---- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h -+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h -@@ -15,6 +15,8 @@ - #ifndef RTL8187_H - #define RTL8187_H - -+#include -+ - #include "rtl818x.h" - #include "leds.h" - -@@ -139,7 +141,10 @@ struct rtl8187_priv { - u8 aifsn[4]; - u8 rfkill_mask; - struct { -- __le64 buf; -+ union { -+ __le64 buf; -+ u8 dummy1[L1_CACHE_BYTES]; -+ } ____cacheline_aligned; - struct sk_buff_head queue; - } b_tx_status; /* This queue is used by both -b and non-b devices */ - struct mutex io_mutex; -@@ -147,7 +152,8 @@ struct rtl8187_priv { - u8 bits8; - __le16 bits16; - __le32 bits32; -- } *io_dmabuf; -+ u8 dummy2[L1_CACHE_BYTES]; -+ } *io_dmabuf ____cacheline_aligned; - bool rfkill_off; - u16 seqno; - }; ---- a/net/mac80211/wme.c -+++ b/net/mac80211/wme.c -@@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80 - return IEEE80211_AC_BE; - } - -+ if (skb->protocol == sdata->control_port_protocol) { -+ skb->priority = 7; -+ return ieee80211_downgrade_queue(sdata, skb); -+ } -+ - /* use the data classifier to determine what 802.1d tag the - * data frame has */ - rcu_read_lock(); ---- a/drivers/net/wireless/ath/ath9k/xmit.c -+++ b/drivers/net/wireless/ath/ath9k/xmit.c -@@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_ - for (tidno = 0, tid = &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { - -- if (!tid->sched) -- continue; -- - ac = tid->ac; - txq = ac->txq; - - ath_txq_lock(sc, txq); - -+ if (!tid->sched) { -+ ath_txq_unlock(sc, txq); -+ continue; -+ } -+ - 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); - -@@ -2061,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buff - - ATH_TXBUF_RESET(bf); - -- if (tid) { -+ if (tid && ieee80211_is_data_present(hdr->frame_control)) { - fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; - seqno = tid->seq_next; - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); -@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw - txq->stopped = true; - } - -+ if (txctl->an && ieee80211_is_data_present(hdr->frame_control)) -+ 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 - hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; - hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; -+ hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; - - hw->queues = 4; - hw->max_rates = 4; ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1700,14 +1700,8 @@ void ieee80211_stop_queue_by_reason(stru - void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); - void ieee80211_add_pending_skb(struct ieee80211_local *local, - struct sk_buff *skb); --void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, -- struct sk_buff_head *skbs, -- void (*fn)(void *data), void *data); --static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, -- struct sk_buff_head *skbs) --{ -- ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); --} -+void ieee80211_add_pending_skbs(struct ieee80211_local *local, -+ struct sk_buff_head *skbs); - void ieee80211_flush_queues(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata); - ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee - return -ENOENT; - } - --static void cleanup_single_sta(struct sta_info *sta) -+static void __cleanup_single_sta(struct sta_info *sta) - { - int ac, i; - struct tid_ampdu_tx *tid_tx; -@@ -99,7 +99,8 @@ static void cleanup_single_sta(struct st - struct ieee80211_local *local = sdata->local; - struct ps_data *ps; - -- if (test_sta_flag(sta, WLAN_STA_PS_STA)) { -+ if (test_sta_flag(sta, WLAN_STA_PS_STA) || -+ test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { - if (sta->sdata->vif.type == NL80211_IFTYPE_AP || - sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - ps = &sdata->bss->ps; -@@ -109,6 +110,7 @@ static void cleanup_single_sta(struct st - return; - - clear_sta_flag(sta, WLAN_STA_PS_STA); -+ clear_sta_flag(sta, WLAN_STA_PS_DRIVER); - - atomic_dec(&ps->num_sta_ps); - sta_info_recalc_tim(sta); -@@ -139,7 +141,14 @@ static void cleanup_single_sta(struct st - ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); - kfree(tid_tx); - } -+} - -+static void cleanup_single_sta(struct sta_info *sta) -+{ -+ struct ieee80211_sub_if_data *sdata = sta->sdata; -+ struct ieee80211_local *local = sdata->local; -+ -+ __cleanup_single_sta(sta); - sta_info_free(local, sta); - } - -@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct i - rcu_read_unlock(); - - spin_lock_init(&sta->lock); -+ spin_lock_init(&sta->ps_lock); - INIT_WORK(&sta->drv_unblock_wk, sta_unblock); - INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); - mutex_init(&sta->ampdu_mlme.mtx); -@@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct - goto out_err; - } - -- /* notify driver */ -- err = sta_info_insert_drv_state(local, sdata, sta); -- if (err) -- goto out_err; -- - local->num_sta++; - local->sta_generation++; - smp_mb(); - -+ /* simplify things and don't accept BA sessions yet */ -+ set_sta_flag(sta, WLAN_STA_BLOCK_BA); -+ - /* make the station visible */ - sta_info_hash_add(local, sta); - - list_add_rcu(&sta->list, &local->sta_list); - -+ /* notify driver */ -+ err = sta_info_insert_drv_state(local, sdata, sta); -+ if (err) -+ goto out_remove; -+ - set_sta_flag(sta, WLAN_STA_INSERTED); -+ /* accept BA sessions now */ -+ clear_sta_flag(sta, WLAN_STA_BLOCK_BA); - - ieee80211_recalc_min_chandef(sdata); - ieee80211_sta_debugfs_add(sta); -@@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct - mesh_accept_plinks_update(sdata); - - return 0; -+ out_remove: -+ sta_info_hash_del(local, sta); -+ list_del_rcu(&sta->list); -+ local->num_sta--; -+ synchronize_net(); -+ __cleanup_single_sta(sta); - out_err: - mutex_unlock(&local->sta_mtx); - rcu_read_lock(); -@@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta - } - EXPORT_SYMBOL(ieee80211_find_sta); - --static void clear_sta_ps_flags(void *_sta) -+/* powersave support code */ -+void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) - { -- struct sta_info *sta = _sta; - struct ieee80211_sub_if_data *sdata = sta->sdata; -+ struct ieee80211_local *local = sdata->local; -+ struct sk_buff_head pending; -+ int filtered = 0, buffered = 0, ac; -+ unsigned long flags; - struct ps_data *ps; - - if (sdata->vif.type == NL80211_IFTYPE_AP || -@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_st - else - return; - -- clear_sta_flag(sta, WLAN_STA_PS_DRIVER); -- if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA)) -- atomic_dec(&ps->num_sta_ps); --} -- --/* powersave support code */ --void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) --{ -- struct ieee80211_sub_if_data *sdata = sta->sdata; -- struct ieee80211_local *local = sdata->local; -- struct sk_buff_head pending; -- int filtered = 0, buffered = 0, ac; -- unsigned long flags; -- - clear_sta_flag(sta, WLAN_STA_SP); - - BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); -@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(str - - skb_queue_head_init(&pending); - -+ /* sync with ieee80211_tx_h_unicast_ps_buf */ -+ spin_lock(&sta->ps_lock); - /* Send all buffered frames to the station */ - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - int count = skb_queue_len(&pending), tmp; -@@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(str - buffered += tmp - count; - } - -- ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); -+ ieee80211_add_pending_skbs(local, &pending); -+ clear_sta_flag(sta, WLAN_STA_PS_DRIVER); -+ clear_sta_flag(sta, WLAN_STA_PS_STA); -+ spin_unlock(&sta->ps_lock); -+ -+ atomic_dec(&ps->num_sta_ps); - - /* This station just woke up and isn't aware of our SMPS state */ - if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat { - * @drv_unblock_wk: used for driver PS unblocking - * @listen_interval: listen interval of this station, when we're acting as AP - * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly -+ * @ps_lock: used for powersave (when mac80211 is the AP) related locking - * @ps_tx_buf: buffers (per AC) of frames to transmit to this station - * when it leaves power saving state or polls - * @tx_filtered: buffers (per AC) of frames we already tried to -@@ -356,10 +357,8 @@ struct sta_info { - /* use the accessors defined below */ - unsigned long _flags; - -- /* -- * STA powersave frame queues, no more than the internal -- * locking required. -- */ -+ /* STA powersave lock and frame queues */ -+ spinlock_t ps_lock; - struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; - struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; - unsigned long driver_buffered_tids; ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ie - spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); - } - --void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, -- struct sk_buff_head *skbs, -- void (*fn)(void *data), void *data) -+void ieee80211_add_pending_skbs(struct ieee80211_local *local, -+ struct sk_buff_head *skbs) - { - struct ieee80211_hw *hw = &local->hw; - struct sk_buff *skb; -@@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struc - __skb_queue_tail(&local->pending[queue], skb); - } - -- if (fn) -- fn(data); -- - for (i = 0; i < hw->queues; i++) - __ieee80211_wake_queue(hw, i, - IEEE80211_QUEUE_STOP_REASON_SKB_ADD); ---- a/net/wireless/reg.c -+++ b/net/wireless/reg.c -@@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regu - return; - case NL80211_REGDOM_SET_BY_USER: - treatment = reg_process_hint_user(reg_request); -- if (treatment == REG_REQ_OK || -+ if (treatment == REG_REQ_IGNORE || - 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 -@@ -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, -+ "%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; -@@ -308,17 +318,6 @@ void ath9k_ani_reset(struct ath_hw *ah, - BUG_ON(aniState == NULL); - ah->stats.ast_ani_reset++; - -- /* only allow a subset of functions in AP mode */ -- if (ah->opmode == NL80211_IFTYPE_AP) { -- if (IS_CHAN_2GHZ(chan)) { -- ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | -- ATH9K_ANI_FIRSTEP_LEVEL); -- if (AR_SREV_9300_20_OR_LATER(ah)) -- ah->ani_function |= ATH9K_ANI_MRC_CCK; -- } else -- ah->ani_function = 0; -- } -- - ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL, - aniState->ofdmNoiseImmunityLevel); - cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL, -@@ -483,10 +482,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 ---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c -@@ -26,10 +26,6 @@ static const int firstep_table[] = - /* level: 0 1 2 3 4 5 6 7 8 */ - { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ - --static const int cycpwrThr1_table[] = --/* level: 0 1 2 3 4 5 6 7 8 */ -- { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ -- - /* - * register values to turn OFDM weak signal detection OFF - */ -@@ -921,7 +917,7 @@ static bool ar5008_hw_ani_control_new(st - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_channel *chan = ah->curchan; - struct ar5416AniState *aniState = &ah->ani; -- s32 value, value2; -+ s32 value; - - switch (cmd & ah->ani_function) { - case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ -@@ -1008,42 +1004,11 @@ static bool ar5008_hw_ani_control_new(st - case ATH9K_ANI_FIRSTEP_LEVEL:{ - u32 level = param; - -- if (level >= ARRAY_SIZE(firstep_table)) { -- ath_dbg(common, ANI, -- "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n", -- level, ARRAY_SIZE(firstep_table)); -- return false; -- } -- -- /* -- * make register setting relative to default -- * from INI file & cap value -- */ -- value = firstep_table[level] - -- firstep_table[ATH9K_ANI_FIRSTEP_LVL] + -- aniState->iniDef.firstep; -- if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) -- value = ATH9K_SIG_FIRSTEP_SETTING_MIN; -- if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX) -- value = ATH9K_SIG_FIRSTEP_SETTING_MAX; -+ value = level * 2; - REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, -- AR_PHY_FIND_SIG_FIRSTEP, -- value); -- /* -- * we need to set first step low register too -- * make register setting relative to default -- * from INI file & cap value -- */ -- value2 = firstep_table[level] - -- firstep_table[ATH9K_ANI_FIRSTEP_LVL] + -- aniState->iniDef.firstepLow; -- if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) -- value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; -- if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX) -- value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX; -- -+ AR_PHY_FIND_SIG_FIRSTEP, value); - REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, -- AR_PHY_FIND_SIG_FIRSTEP_LOW, value2); -+ AR_PHY_FIND_SIG_FIRSTEP_LOW, value); - - if (level != aniState->firstepLevel) { - ath_dbg(common, ANI, -@@ -1060,7 +1025,7 @@ static bool ar5008_hw_ani_control_new(st - aniState->firstepLevel, - level, - ATH9K_ANI_FIRSTEP_LVL, -- value2, -+ value, - aniState->iniDef.firstepLow); - if (level > aniState->firstepLevel) - ah->stats.ast_ani_stepup++; -@@ -1073,41 +1038,13 @@ static bool ar5008_hw_ani_control_new(st - case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ - u32 level = param; - -- if (level >= ARRAY_SIZE(cycpwrThr1_table)) { -- ath_dbg(common, ANI, -- "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n", -- level, ARRAY_SIZE(cycpwrThr1_table)); -- return false; -- } -- /* -- * make register setting relative to default -- * from INI file & cap value -- */ -- value = cycpwrThr1_table[level] - -- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + -- aniState->iniDef.cycpwrThr1; -- if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) -- value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; -- if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX) -- value = ATH9K_SIG_SPUR_IMM_SETTING_MAX; -+ value = (level + 1) * 2; - REG_RMW_FIELD(ah, AR_PHY_TIMING5, -- AR_PHY_TIMING5_CYCPWR_THR1, -- value); -+ AR_PHY_TIMING5_CYCPWR_THR1, value); - -- /* -- * set AR_PHY_EXT_CCA for extension channel -- * make register setting relative to default -- * from INI file & cap value -- */ -- value2 = cycpwrThr1_table[level] - -- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] + -- aniState->iniDef.cycpwrThr1Ext; -- if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) -- value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; -- if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX) -- value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX; -- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, -- AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2); -+ if (IS_CHAN_HT40(ah->curchan)) -+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, -+ AR_PHY_EXT_TIMING5_CYCPWR_THR1, value); - - if (level != aniState->spurImmunityLevel) { - ath_dbg(common, ANI, -@@ -1124,7 +1061,7 @@ static bool ar5008_hw_ani_control_new(st - aniState->spurImmunityLevel, - level, - ATH9K_ANI_SPUR_IMMUNE_LVL, -- value2, -+ value, - aniState->iniDef.cycpwrThr1Ext); - if (level > aniState->spurImmunityLevel) - ah->stats.ast_ani_spurup++; diff --git a/package/kernel/mac80211/patches/310-ap_scan.patch b/package/kernel/mac80211/patches/310-ap_scan.patch index 389a00370d..87f165a5e0 100644 --- a/package/kernel/mac80211/patches/310-ap_scan.patch +++ b/package/kernel/mac80211/patches/310-ap_scan.patch @@ -1,6 +1,6 @@ --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2148,7 +2148,7 @@ static int ieee80211_scan(struct wiphy * +@@ -2154,7 +2154,7 @@ static int ieee80211_scan(struct wiphy * * the frames sent while scanning on other channel will be * lost) */ diff --git a/package/kernel/mac80211/patches/400-ath_move_debug_code.patch b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch index 0dba7ac125..4cc77afa1b 100644 --- a/package/kernel/mac80211/patches/400-ath_move_debug_code.patch +++ b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch @@ -12,7 +12,7 @@ ccflags-y += -D__CHECK_ENDIAN__ --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h -@@ -282,13 +282,6 @@ void _ath_dbg(struct ath_common *common, +@@ -295,13 +295,6 @@ void _ath_dbg(struct ath_common *common, #endif /* CPTCFG_ATH_DEBUG */ /** Returns string describing opmode, or NULL if unknown mode. */ diff --git a/package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch b/package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch index 63ab0dba6e..acaa317f76 100644 --- a/package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch +++ b/package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch @@ -8,7 +8,7 @@ #include #include "hw.h" -@@ -449,8 +450,16 @@ static int ath9k_hw_init_macaddr(struct +@@ -448,8 +449,16 @@ static int ath9k_hw_init_macaddr(struct common->macaddr[2 * i] = eeval >> 8; common->macaddr[2 * i + 1] = eeval & 0xff; } diff --git a/package/kernel/mac80211/patches/403-ath_regd_optional.patch b/package/kernel/mac80211/patches/403-ath_regd_optional.patch index 07c54ccf81..4a9b7e48fc 100644 --- a/package/kernel/mac80211/patches/403-ath_regd_optional.patch +++ b/package/kernel/mac80211/patches/403-ath_regd_optional.patch @@ -58,7 +58,7 @@ ---help--- --- a/.local-symbols +++ b/.local-symbols -@@ -119,6 +119,7 @@ RTL8187_LEDS= +@@ -120,6 +120,7 @@ RTL8187_LEDS= ATH_COMMON= ATH_CARDS= ATH_DEBUG= diff --git a/package/kernel/mac80211/patches/405-regd_no_assoc_hints.patch b/package/kernel/mac80211/patches/405-regd_no_assoc_hints.patch index 6ad4fda272..4fa611f206 100644 --- a/package/kernel/mac80211/patches/405-regd_no_assoc_hints.patch +++ b/package/kernel/mac80211/patches/405-regd_no_assoc_hints.patch @@ -1,6 +1,6 @@ --- a/net/wireless/reg.c +++ b/net/wireless/reg.c -@@ -1878,6 +1878,8 @@ void regulatory_hint_country_ie(struct w +@@ -2000,6 +2000,8 @@ void regulatory_hint_country_ie(struct w enum environment_cap env = ENVIRON_ANY; struct regulatory_request *request = NULL, *lr; @@ -9,7 +9,7 @@ /* IE len must be evenly divisible by 2 */ if (country_ie_len & 0x01) return; -@@ -2072,6 +2074,7 @@ static void restore_regulatory_settings( +@@ -2194,6 +2196,7 @@ static void restore_regulatory_settings( void regulatory_hint_disconnect(void) { diff --git a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch index 1f71e0b8aa..909a5f104d 100644 --- a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch +++ b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -866,6 +866,7 @@ static const struct ieee80211_iface_limi +@@ -652,6 +652,7 @@ static const struct ieee80211_iface_limi #endif BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO) }, diff --git a/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch index 3487ab26f2..1f069946cd 100644 --- a/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch +++ b/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch @@ -18,7 +18,7 @@ goto end; --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c -@@ -1934,7 +1934,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) +@@ -1937,7 +1937,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) } if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + @@ -27,7 +27,7 @@ ah->opmode == NL80211_IFTYPE_MESH_POINT) { u64 tsf = ath5k_hw_get_tsf64(ah); u32 tsftu = TSF_TO_TU(tsf); -@@ -2020,7 +2020,7 @@ ath5k_beacon_update_timers(struct ath5k_ +@@ -2023,7 +2023,7 @@ ath5k_beacon_update_timers(struct ath5k_ intval = ah->bintval & AR5K_BEACON_PERIOD; if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs @@ -36,7 +36,7 @@ intval /= ATH_BCBUF; /* staggered multi-bss beacons */ if (intval < 15) ATH5K_WARN(ah, "intval %u is too low, min 15\n", -@@ -2487,6 +2487,7 @@ static const struct ieee80211_iface_limi +@@ -2490,6 +2490,7 @@ static const struct ieee80211_iface_limi BIT(NL80211_IFTYPE_MESH_POINT) | #endif BIT(NL80211_IFTYPE_AP) }, diff --git a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch index 664cf45175..36e01511ad 100644 --- a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch +++ b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1481,6 +1481,53 @@ void ath9k_deinit_debug(struct ath_softc +@@ -1485,6 +1485,53 @@ void ath9k_deinit_debug(struct ath_softc ath9k_spectral_deinit_debug(sc); } @@ -54,7 +54,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); -@@ -1500,6 +1547,8 @@ int ath9k_init_debug(struct ath_hw *ah) +@@ -1504,6 +1551,8 @@ int ath9k_init_debug(struct ath_hw *ah) ath9k_tx99_init_debug(sc); ath9k_spectral_init_debug(sc); diff --git a/package/kernel/mac80211/patches/501-ath9k-eeprom_endianess.patch b/package/kernel/mac80211/patches/501-ath9k-eeprom_endianess.patch index 96e7c6d8cc..169eb9ae0c 100644 --- a/package/kernel/mac80211/patches/501-ath9k-eeprom_endianess.patch +++ b/package/kernel/mac80211/patches/501-ath9k-eeprom_endianess.patch @@ -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 -@@ -722,6 +722,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; diff --git a/package/kernel/mac80211/patches/502-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/502-ath9k_ahb_init.patch index 4edc63bede..43c3260b80 100644 --- a/package/kernel/mac80211/patches/502-ath9k_ahb_init.patch +++ b/package/kernel/mac80211/patches/502-ath9k_ahb_init.patch @@ -1,15 +1,15 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -1112,23 +1112,23 @@ static int __init ath9k_init(void) - goto err_out; - } +@@ -892,23 +892,23 @@ static int __init ath9k_init(void) + { + int error; - error = ath_pci_init(); + error = ath_ahb_init(); if (error < 0) { - pr_err("No PCI devices found, driver not installed\n"); error = -ENODEV; - goto err_rate_unregister; + goto err_out; } - error = ath_ahb_init(); @@ -27,6 +27,6 @@ - ath_pci_exit(); + err_ahb_exit: + ath_ahb_exit(); - - err_rate_unregister: - ath_rate_control_unregister(); + err_out: + return error; + } diff --git a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch index d7478ff590..c8189333d2 100644 --- a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch +++ b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -359,13 +359,8 @@ static void ath9k_hw_init_config(struct +@@ -358,13 +358,8 @@ static void ath9k_hw_init_config(struct ah->config.rx_intr_mitigation = true; diff --git a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch index ef0b9a1e2a..e457267654 100644 --- a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch +++ b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -90,7 +90,7 @@ int ath_descdma_setup(struct ath_softc * +@@ -89,7 +89,7 @@ int ath_descdma_setup(struct ath_softc * (_l) &= ((_sz) - 1); \ } while (0) diff --git a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch index 8f3cc03043..665d8aa64d 100644 --- a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch +++ b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1528,6 +1528,52 @@ static const struct file_operations fops +@@ -1532,6 +1532,52 @@ static const struct file_operations fops .owner = THIS_MODULE }; @@ -35,7 +35,7 @@ + return -EINVAL; + + common->chan_bw = chan_bw; -+ if (!test_bit(SC_OP_INVALID, &sc->sc_flags)) ++ if (!test_bit(ATH_OP_INVALID, &common->op_flags)) + ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL); + + return count; @@ -53,7 +53,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); -@@ -1549,6 +1595,8 @@ int ath9k_init_debug(struct ath_hw *ah) +@@ -1553,6 +1599,8 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_eeprom); @@ -64,17 +64,17 @@ debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h -@@ -130,6 +130,7 @@ struct ath_common { - struct ieee80211_hw *hw; +@@ -140,6 +140,7 @@ struct ath_common { int debug_mask; enum ath_device_state state; + unsigned long op_flags; + u32 chan_bw; struct ath_ani ani; --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c -@@ -52,11 +52,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke +@@ -296,11 +296,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke /* * Update internal channel flags. */ @@ -89,7 +89,7 @@ ichan->channel = chan->center_freq; ichan->chan = chan; -@@ -64,7 +66,19 @@ static void ath9k_cmn_update_ichannel(st +@@ -308,7 +310,19 @@ static void ath9k_cmn_update_ichannel(st if (chan->band == IEEE80211_BAND_5GHZ) flags |= CHANNEL_5GHZ; @@ -110,7 +110,7 @@ case NL80211_CHAN_WIDTH_5: flags |= CHANNEL_QUARTER; break; -@@ -97,10 +111,11 @@ struct ath9k_channel *ath9k_cmn_get_chan +@@ -341,10 +355,11 @@ struct ath9k_channel *ath9k_cmn_get_chan struct cfg80211_chan_def *chandef) { struct ieee80211_channel *curchan = chandef->chan; diff --git a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch index db4e6a1238..540198f01c 100644 --- a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch +++ b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -614,6 +614,7 @@ int ath9k_hw_init(struct ath_hw *ah) +@@ -613,6 +613,7 @@ int ath9k_hw_init(struct ath_hw *ah) /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ switch (ah->hw_version.devid) { diff --git a/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch b/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch index 6df95bceae..aa460a81c4 100644 --- a/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch +++ b/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch @@ -1,6 +1,6 @@ --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -1711,6 +1711,7 @@ struct ieee80211_hw { +@@ -1703,6 +1703,7 @@ struct ieee80211_hw { u8 max_tx_aggregation_subframes; u8 offchannel_tx_hw_queue; u8 radiotap_mcs_details; @@ -10,7 +10,7 @@ u8 uapsd_queues; --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2329,7 +2329,9 @@ static int ieee80211_get_tx_power(struct +@@ -2335,7 +2335,9 @@ static int ieee80211_get_tx_power(struct struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); diff --git a/package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch b/package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch index 0d6c360d38..24bc0626ed 100644 --- a/package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch +++ b/package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch @@ -14,7 +14,7 @@ out: spin_unlock_bh(&sc->sc_pcu_lock); -@@ -1371,6 +1375,7 @@ static int ath9k_config(struct ieee80211 +@@ -1370,6 +1374,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); diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch index 8f2adc9d0f..f131f56c1e 100644 --- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -1,6 +1,6 @@ --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -2156,6 +2156,7 @@ struct cfg80211_qos_map { +@@ -2167,6 +2167,7 @@ struct cfg80211_qos_map { * (as advertised by the nl80211 feature flag.) * @get_tx_power: store the current TX power into the dbm variable; * return 0 if successful @@ -8,7 +8,7 @@ * * @set_wds_peer: set the WDS peer for a WDS interface * -@@ -2380,6 +2381,7 @@ struct cfg80211_ops { +@@ -2396,6 +2397,7 @@ struct cfg80211_ops { enum nl80211_tx_power_setting type, int mbm); int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm); @@ -18,7 +18,7 @@ const u8 *addr); --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -1033,6 +1033,7 @@ enum ieee80211_smps_mode { +@@ -1032,6 +1032,7 @@ enum ieee80211_smps_mode { * * @power_level: requested transmit power (in dBm), backward compatibility * value only that is set to the minimum of all interfaces @@ -26,7 +26,7 @@ * * @chandef: the channel definition to tune to * @radar_enabled: whether radar detection is enabled -@@ -1054,6 +1055,7 @@ struct ieee80211_conf { +@@ -1053,6 +1054,7 @@ struct ieee80211_conf { u32 flags; int power_level, dynamic_ps_timeout; int max_sleep_period; @@ -36,9 +36,9 @@ u8 ps_dtim_period; --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -1555,6 +1555,9 @@ enum nl80211_commands { - * data is in the format defined for the payload of the QoS Map Set element - * in IEEE Std 802.11-2012, 8.4.2.97. +@@ -1579,6 +1579,9 @@ enum nl80211_commands { + * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. + * As specified in the &enum nl80211_tdls_peer_capability. * + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce + * transmit power to stay within regulatory limits. u32, dBi. @@ -46,9 +46,9 @@ * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ -@@ -1883,6 +1886,8 @@ enum nl80211_attrs { +@@ -1914,6 +1917,8 @@ enum nl80211_attrs { - NL80211_ATTR_QOS_MAP, + NL80211_ATTR_TDLS_PEER_CAPABILITY, + NL80211_ATTR_WIPHY_ANTENNA_GAIN, + @@ -57,7 +57,7 @@ __NL80211_ATTR_AFTER_LAST, --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2339,6 +2339,19 @@ static int ieee80211_get_tx_power(struct +@@ -2345,6 +2345,19 @@ static int ieee80211_get_tx_power(struct return 0; } @@ -77,7 +77,7 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, const u8 *addr) { -@@ -3924,6 +3937,7 @@ struct cfg80211_ops mac80211_config_ops +@@ -4000,6 +4013,7 @@ const struct cfg80211_ops mac80211_confi .set_wiphy_params = ieee80211_set_wiphy_params, .set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, @@ -87,7 +87,7 @@ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1221,6 +1221,7 @@ struct ieee80211_local { +@@ -1225,6 +1225,7 @@ struct ieee80211_local { int dynamic_ps_forced_timeout; int user_power_level; /* in dBm, for all interfaces */ @@ -139,34 +139,32 @@ local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -384,6 +384,7 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, - [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY, - .len = IEEE80211_QOS_MAP_LEN_MAX }, +@@ -385,6 +385,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN }, + [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, + [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, + [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, }; /* policy for the key attributes */ -@@ -2104,6 +2105,22 @@ static int nl80211_set_wiphy(struct sk_b - if (result) - goto bad_res; +@@ -2116,6 +2117,20 @@ static int nl80211_set_wiphy(struct sk_b + return result; } -+ + + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { + int idx, dbi = 0; + -+ if (!rdev->ops->set_antenna_gain) { -+ result = -EOPNOTSUPP; -+ goto bad_res; -+ } ++ if (!rdev->ops->set_antenna_gain) ++ return -EOPNOTSUPP; + + idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN; + dbi = nla_get_u32(info->attrs[idx]); + + result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi); + if (result) -+ goto bad_res; ++ return result; + } - ++ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { + u32 tx_ant, rx_ant; diff --git a/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch b/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch index 30aa9ee187..b84a99134a 100644 --- a/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch +++ b/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h -@@ -74,6 +74,7 @@ struct ath_regulatory { +@@ -83,6 +83,7 @@ struct ath_regulatory { u16 max_power_level; u16 current_rd; int16_t power_limit; @@ -10,7 +10,7 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -2721,7 +2721,7 @@ void ath9k_hw_apply_txpower(struct ath_h +@@ -2720,7 +2720,7 @@ void ath9k_hw_apply_txpower(struct ath_h channel = chan->chan; chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER); new_pwr = min_t(int, chan_pwr, reg->power_limit); @@ -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 -@@ -1371,7 +1371,10 @@ static int ath9k_config(struct ieee80211 +@@ -1370,7 +1370,10 @@ static int ath9k_config(struct ieee80211 } if (changed & IEEE80211_CONF_CHANGE_POWER) { diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch index 59f78d9dfa..5502f02ccc 100644 --- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch +++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -563,6 +563,9 @@ static inline int ath9k_dump_btcoex(stru +@@ -555,6 +555,9 @@ static inline int ath9k_dump_btcoex(stru void ath_init_leds(struct ath_softc *sc); void ath_deinit_leds(struct ath_softc *sc); void ath_fill_led_pin(struct ath_softc *sc); @@ -10,7 +10,7 @@ #else static inline void ath_init_leds(struct ath_softc *sc) { -@@ -710,6 +713,13 @@ enum sc_op_flags { +@@ -693,6 +696,13 @@ void ath_ant_comb_scan(struct ath_softc #define PS_BEACON_SYNC BIT(4) #define PS_WAIT_FOR_ANI BIT(5) @@ -24,8 +24,8 @@ struct ath_softc { struct ieee80211_hw *hw; struct device *dev; -@@ -751,9 +761,8 @@ struct ath_softc { - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; +@@ -732,9 +742,8 @@ struct ath_softc { + struct ath_beacon beacon; #ifdef CPTCFG_MAC80211_LEDS - bool led_registered; @@ -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 -@@ -1018,7 +1018,7 @@ int ath9k_init_device(u16 devid, struct +@@ -806,7 +806,7 @@ int ath9k_init_device(u16 devid, struct #ifdef CPTCFG_MAC80211_LEDS /* must be initialized before ieee80211_register_hw */ @@ -173,7 +173,7 @@ #endif --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1573,6 +1573,61 @@ static const struct file_operations fops +@@ -1577,6 +1577,61 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -235,7 +235,7 @@ int ath9k_init_debug(struct ath_hw *ah) { -@@ -1597,6 +1652,10 @@ int ath9k_init_debug(struct ath_hw *ah) +@@ -1601,6 +1656,10 @@ int ath9k_init_debug(struct ath_hw *ah) &fops_eeprom); debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_chanbw); diff --git a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch index e1b6ff17e8..44aa905649 100644 --- a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch +++ b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1629,6 +1629,50 @@ static const struct file_operations fops +@@ -1633,6 +1633,50 @@ static const struct file_operations fops #endif @@ -51,7 +51,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); -@@ -1656,6 +1700,8 @@ int ath9k_init_debug(struct ath_hw *ah) +@@ -1660,6 +1704,8 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("gpio_led", S_IWUSR, sc->debug.debugfs_phy, sc, &fops_gpio_led); #endif @@ -94,7 +94,7 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1735,6 +1735,20 @@ fail: +@@ -1734,6 +1734,20 @@ fail: return -EINVAL; } @@ -115,7 +115,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, struct ath9k_hw_cal_data *caldata, bool fastcc) { -@@ -1940,6 +1954,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st +@@ -1939,6 +1953,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st ar9003_hw_disable_phy_restart(ah); ath9k_hw_apply_gpio_override(ah); @@ -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 -@@ -602,6 +602,11 @@ irqreturn_t ath_isr(int irq, void *dev) +@@ -603,6 +603,11 @@ irqreturn_t ath_isr(int irq, void *dev) ath9k_debug_sync_cause(sc, sync_cause); status &= ah->imask; /* discard unasked-for bits */ diff --git a/package/kernel/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch b/package/kernel/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch index d26a5af865..e2e18c91a2 100644 --- a/package/kernel/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch +++ b/package/kernel/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch @@ -11,7 +11,7 @@ int (*external_reset)(void); --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -2328,17 +2328,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw +@@ -2327,17 +2327,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw } eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); @@ -58,7 +58,7 @@ }; --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -722,6 +722,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; diff --git a/package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch index d126fd4e94..d3c17cdeb6 100644 --- a/package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch @@ -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 -@@ -846,7 +846,8 @@ static void ath9k_init_txpower_limits(st +@@ -643,7 +643,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); @@ -64,8 +64,8 @@ + ah->curchan = curchan; } - void ath9k_reload_chainmask_settings(struct ath_softc *sc) -@@ -980,6 +981,18 @@ static void ath9k_set_hw_capab(struct at + static const struct ieee80211_iface_limit if_limits[] = { +@@ -768,6 +769,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) { -@@ -1025,6 +1038,8 @@ int ath9k_init_device(u16 devid, struct +@@ -813,6 +826,8 @@ int ath9k_init_device(u16 devid, struct ARRAY_SIZE(ath9k_tpt_blink)); #endif @@ -110,7 +110,7 @@ static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c -@@ -307,6 +307,11 @@ void ath_ani_calibrate(unsigned long dat +@@ -308,6 +308,11 @@ void ath_ani_calibrate(unsigned long dat unsigned int timestamp = jiffies_to_msecs(jiffies); u32 cal_interval, short_cal_interval, long_cal_interval; unsigned long flags; diff --git a/package/kernel/mac80211/patches/551-ath9k_p2p_ifcomb.patch b/package/kernel/mac80211/patches/551-ath9k_p2p_ifcomb.patch index ffffe0cbe8..579a633077 100644 --- a/package/kernel/mac80211/patches/551-ath9k_p2p_ifcomb.patch +++ b/package/kernel/mac80211/patches/551-ath9k_p2p_ifcomb.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -863,15 +863,15 @@ void ath9k_reload_chainmask_settings(str +@@ -649,15 +649,15 @@ static void ath9k_init_txpower_limits(st static const struct ieee80211_iface_limit if_limits[] = { { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | diff --git a/package/kernel/mac80211/patches/552-ath9k_p2p_ps_support.patch b/package/kernel/mac80211/patches/552-ath9k_p2p_ps_support.patch index 4a61db3f9a..fbe5396e6d 100644 --- a/package/kernel/mac80211/patches/552-ath9k_p2p_ps_support.patch +++ b/package/kernel/mac80211/patches/552-ath9k_p2p_ps_support.patch @@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau return true; } -@@ -1126,6 +1128,8 @@ static int ath9k_add_interface(struct ie +@@ -1128,6 +1130,8 @@ static int ath9k_add_interface(struct ie if (ath9k_uses_beacons(vif->type)) ath9k_beacon_assign_slot(sc, vif); @@ -36,7 +36,7 @@ Signed-off-by: Felix Fietkau an->sc = sc; an->sta = NULL; an->vif = vif; -@@ -1170,6 +1174,29 @@ static int ath9k_change_interface(struct +@@ -1172,6 +1176,29 @@ static int ath9k_change_interface(struct return 0; } @@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau static void ath9k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { -@@ -1181,6 +1208,13 @@ static void ath9k_remove_interface(struc +@@ -1183,6 +1210,13 @@ static void ath9k_remove_interface(struc mutex_lock(&sc->mutex); @@ -80,7 +80,7 @@ Signed-off-by: Felix Fietkau sc->nvifs--; sc->tx99_vif = NULL; -@@ -1649,6 +1683,70 @@ static void ath9k_bss_assoc_iter(void *d +@@ -1649,6 +1683,72 @@ static void ath9k_bss_assoc_iter(void *d ath9k_set_assoc_state(sc, vif); } @@ -130,6 +130,7 @@ Signed-off-by: Felix Fietkau +void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif) +{ + struct ath_vif *avp = (void *)vif->drv_priv; ++ unsigned long flags; + u32 tsf; + + if (!sc->p2p_ps_timer) @@ -140,18 +141,19 @@ Signed-off-by: Felix Fietkau + + sc->p2p_ps_vif = avp; + -+ if (sc->ps_flags & PS_BEACON_SYNC) -+ return; -+ -+ tsf = ath9k_hw_gettsf32(sc->sc_ah); -+ ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf); -+ ath9k_update_p2p_ps_timer(sc, avp); ++ spin_lock_irqsave(&sc->sc_pm_lock, flags); ++ if (!(sc->ps_flags & PS_BEACON_SYNC)) { ++ tsf = ath9k_hw_gettsf32(sc->sc_ah); ++ ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf); ++ ath9k_update_p2p_ps_timer(sc, avp); ++ } ++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags); +} + static void ath9k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, -@@ -1723,6 +1821,12 @@ static void ath9k_bss_info_changed(struc +@@ -1723,6 +1823,12 @@ static void ath9k_bss_info_changed(struc } } @@ -166,7 +168,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -115,6 +115,9 @@ int ath_descdma_setup(struct ath_softc * +@@ -114,6 +114,9 @@ int ath_descdma_setup(struct ath_softc * #define ATH_TXFIFO_DEPTH 8 #define ATH_TX_ERROR 0x01 @@ -176,7 +178,7 @@ Signed-off-by: Felix Fietkau #define IEEE80211_SEQ_SEQ_SHIFT 4 #define IEEE80211_SEQ_MAX 4096 #define IEEE80211_WEP_IVLEN 3 -@@ -363,11 +366,15 @@ void ath9k_release_buffered_frames(struc +@@ -367,11 +370,15 @@ void ath9k_release_buffered_frames(struc /********/ struct ath_vif { @@ -192,7 +194,7 @@ Signed-off-by: Felix Fietkau }; struct ath9k_vif_iter_data { -@@ -472,6 +479,8 @@ int ath_update_survey_stats(struct ath_s +@@ -464,6 +471,8 @@ int ath_update_survey_stats(struct ath_s void ath_update_survey_nf(struct ath_softc *sc, int channel); void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); void ath_ps_full_sleep(unsigned long data); @@ -201,19 +203,19 @@ Signed-off-by: Felix Fietkau /**********/ /* BTCOEX */ -@@ -741,6 +750,9 @@ struct ath_softc { +@@ -724,6 +733,9 @@ struct ath_softc { struct completion paprd_complete; wait_queue_head_t tx_wait; + struct ath_gen_timer *p2p_ps_timer; + struct ath_vif *p2p_ps_vif; + - unsigned long sc_flags; unsigned long driver_data; + u8 gtt_cnt; --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -797,6 +797,9 @@ static int ath9k_init_softc(u16 devid, s +@@ -593,6 +593,9 @@ static int ath9k_init_softc(u16 devid, s if (ret) goto err_btcoex; @@ -223,7 +225,7 @@ Signed-off-by: Felix Fietkau ath9k_cmn_init_crypto(sc->sc_ah); ath9k_init_misc(sc); ath_fill_led_pin(sc); -@@ -1082,6 +1085,9 @@ static void ath9k_deinit_softc(struct at +@@ -870,6 +873,9 @@ static void ath9k_deinit_softc(struct at { int i = 0; diff --git a/package/kernel/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch index af94c9e312..eddbc6c06e 100644 --- a/package/kernel/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch +++ b/package/kernel/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -217,6 +217,19 @@ void ath9k_hw_get_channel_centers(struct +@@ -216,6 +216,19 @@ void ath9k_hw_get_channel_centers(struct centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); } @@ -20,7 +20,7 @@ /******************/ /* Chip Revisions */ /******************/ -@@ -1337,6 +1350,9 @@ static bool ath9k_hw_set_reset(struct at +@@ -1336,6 +1349,9 @@ static bool ath9k_hw_set_reset(struct at if (AR_SREV_9100(ah)) udelay(50); @@ -30,7 +30,7 @@ return true; } -@@ -1436,6 +1452,9 @@ static bool ath9k_hw_chip_reset(struct a +@@ -1435,6 +1451,9 @@ static bool ath9k_hw_chip_reset(struct a ar9003_hw_internal_regulator_apply(ah); ath9k_hw_init_pll(ah, chan); @@ -40,7 +40,7 @@ return true; } -@@ -1730,8 +1749,14 @@ static int ath9k_hw_do_fastcc(struct ath +@@ -1729,8 +1748,14 @@ static int ath9k_hw_do_fastcc(struct ath if (AR_SREV_9271(ah)) ar9002_hw_load_ani_reg(ah, chan); @@ -55,7 +55,7 @@ return -EINVAL; } -@@ -1959,6 +1984,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st +@@ -1958,6 +1983,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st if (AR_SREV_9565(ah) && common->bt_ant_diversity) REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); diff --git a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch index 2bbc6f162a..3d7a94514b 100644 --- a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch +++ b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch @@ -1,6 +1,6 @@ --- a/.local-symbols +++ b/.local-symbols -@@ -279,6 +279,7 @@ RT2X00_LIB_FIRMWARE= +@@ -280,6 +280,7 @@ RT2X00_LIB_FIRMWARE= RT2X00_LIB_CRYPTO= RT2X00_LIB_LEDS= RT2X00_LIB_DEBUGFS= diff --git a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch index 478a0f277e..7137834aa7 100644 --- a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch +++ b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch @@ -28,7 +28,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; -@@ -7579,7 +7600,10 @@ static int rt2800_probe_hw_mode(struct r +@@ -7578,7 +7599,10 @@ static int rt2800_probe_hw_mode(struct r case RF5390: case RF5392: spec->num_channels = 14; @@ -40,7 +40,7 @@ break; case RF3052: -@@ -7755,6 +7779,19 @@ static int rt2800_probe_rt(struct rt2x00 +@@ -7754,6 +7778,19 @@ static int rt2800_probe_rt(struct rt2x00 return 0; } @@ -60,7 +60,7 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; -@@ -7784,6 +7821,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r +@@ -7783,6 +7820,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); /* diff --git a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch index d843b7ab53..e95487395d 100644 --- a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch +++ b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch @@ -8,7 +8,7 @@ #include "rt2x00.h" #include "rt2800lib.h" -@@ -7781,13 +7782,14 @@ static int rt2800_probe_rt(struct rt2x00 +@@ -7780,13 +7781,14 @@ static int rt2800_probe_rt(struct rt2x00 int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev) { diff --git a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch index 8d3fcd245a..a62ad157ed 100644 --- a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch +++ b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch @@ -240,7 +240,7 @@ case RF5360: case RF5370: case RF5372: -@@ -7595,6 +7706,7 @@ static int rt2800_probe_hw_mode(struct r +@@ -7594,6 +7705,7 @@ static int rt2800_probe_hw_mode(struct r case RF3290: case RF3320: case RF3322: @@ -248,7 +248,7 @@ case RF5360: case RF5370: case RF5372: -@@ -7727,6 +7839,7 @@ static int rt2800_probe_hw_mode(struct r +@@ -7726,6 +7838,7 @@ static int rt2800_probe_hw_mode(struct r case RF3053: case RF3070: case RF3290: @@ -256,7 +256,7 @@ case RF5360: case RF5370: case RF5372: -@@ -7765,6 +7878,7 @@ static int rt2800_probe_rt(struct rt2x00 +@@ -7764,6 +7877,7 @@ static int rt2800_probe_rt(struct rt2x00 case RT3390: case RT3572: case RT3593: diff --git a/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch index 484c075893..752fb0eec9 100644 --- a/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch +++ b/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c -@@ -5529,6 +5529,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") +@@ -5714,6 +5714,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { diff --git a/package/kernel/mac80211/patches/919-wl18xx-align-event-mailbox-with-current-fw.patch b/package/kernel/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch similarity index 89% rename from package/kernel/mac80211/patches/919-wl18xx-align-event-mailbox-with-current-fw.patch rename to package/kernel/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch index 95db58f0f4..77647bbcf6 100644 --- a/package/kernel/mac80211/patches/919-wl18xx-align-event-mailbox-with-current-fw.patch +++ b/package/kernel/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch @@ -16,8 +16,6 @@ Signed-off-by: Eliad Peller drivers/net/wireless/ti/wl18xx/event.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) -diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h -index 398f3d2..a76e98e 100644 --- a/drivers/net/wireless/ti/wl18xx/event.h +++ b/drivers/net/wireless/ti/wl18xx/event.h @@ -68,6 +68,26 @@ struct wl18xx_event_mailbox { @@ -47,6 +45,3 @@ index 398f3d2..a76e98e 100644 } __packed; int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, --- -1.8.5.2.229.g4448466.dirty - diff --git a/package/kernel/mac80211/patches/901-wlcore-memset-wl--rx_filter_enabled-to-zero-after-recovery.patch b/package/kernel/mac80211/patches/901-wlcore-memset-wl--rx_filter_enabled-to-zero-after-recovery.patch deleted file mode 100644 index df2a6e9448..0000000000 --- a/package/kernel/mac80211/patches/901-wlcore-memset-wl--rx_filter_enabled-to-zero-after-recovery.patch +++ /dev/null @@ -1,73 +0,0 @@ -zero rx_filter_enabled array after recovery to avoid -cases were the driver will keep trying to clear a -filter which is not configured in FW. - -Such case will cause consecutive recoveries due to -command execution failures. - -While on it, convert rx_filter_enabled to bitmap, -to save some memory and make sparse happy (it -doesn't like sizeof(bool array)). - -Signed-off-by: Nadim Zubidat -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/main.c | 1 + - drivers/net/wireless/ti/wlcore/rx.c | 9 ++++++--- - drivers/net/wireless/ti/wlcore/wlcore.h | 2 +- - 3 files changed, 8 insertions(+), 4 deletions(-) - ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -1914,6 +1914,7 @@ static void wlcore_op_stop_locked(struct - memset(wl->links_map, 0, sizeof(wl->links_map)); - memset(wl->roc_map, 0, sizeof(wl->roc_map)); - memset(wl->session_ids, 0, sizeof(wl->session_ids)); -+ memset(wl->rx_filter_enabled, 0, sizeof(wl->rx_filter_enabled)); - wl->active_sta_count = 0; - wl->active_link_count = 0; - ---- a/drivers/net/wireless/ti/wlcore/rx.c -+++ b/drivers/net/wireless/ti/wlcore/rx.c -@@ -302,7 +302,7 @@ int wl1271_rx_filter_enable(struct wl127 - { - int ret; - -- if (wl->rx_filter_enabled[index] == enable) { -+ if (!!test_bit(index, wl->rx_filter_enabled) == enable) { - wl1271_warning("Request to enable an already " - "enabled rx filter %d", index); - return 0; -@@ -316,7 +316,10 @@ int wl1271_rx_filter_enable(struct wl127 - return ret; - } - -- wl->rx_filter_enabled[index] = enable; -+ if (enable) -+ __set_bit(index, wl->rx_filter_enabled); -+ else -+ __clear_bit(index, wl->rx_filter_enabled); - - return 0; - } -@@ -326,7 +329,7 @@ int wl1271_rx_filter_clear_all(struct wl - int i, ret = 0; - - for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) { -- if (!wl->rx_filter_enabled[i]) -+ if (!test_bit(i, wl->rx_filter_enabled)) - continue; - ret = wl1271_rx_filter_enable(wl, i, 0, NULL); - if (ret) ---- a/drivers/net/wireless/ti/wlcore/wlcore.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore.h -@@ -453,7 +453,7 @@ struct wl1271 { - size_t fw_status_priv_len; - - /* RX Data filter rule state - enabled/disabled */ -- bool rx_filter_enabled[WL1271_MAX_RX_FILTERS]; -+ unsigned long rx_filter_enabled[BITS_TO_LONGS(WL1271_MAX_RX_FILTERS)]; - - /* size of the private static data */ - size_t static_data_priv_len; diff --git a/package/kernel/mac80211/patches/902-wlcore-cancel-Tx-watchdog-on-~-and-rearm-on-first-Tx-after.patch b/package/kernel/mac80211/patches/902-wlcore-cancel-Tx-watchdog-on-~-and-rearm-on-first-Tx-after.patch deleted file mode 100644 index 497227d474..0000000000 --- a/package/kernel/mac80211/patches/902-wlcore-cancel-Tx-watchdog-on-~-and-rearm-on-first-Tx-after.patch +++ /dev/null @@ -1,73 +0,0 @@ -Sometimes a tx_flush during suspend fails, but the FW manages to flush -out the packets during the time when the host is supsended. Cancel -the Tx-watchdog on suspend to not cause a spurious recovery on resume -for that case. Set a flag to reinit the watchdog on the first Tx after -resume, so we'll still recover if the FW is not empty and there's -indeed a problem. - -Signed-off-by: Arik Nemtsov -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/main.c | 13 +++++++++++++ - drivers/net/wireless/ti/wlcore/tx.c | 9 +++++++-- - drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 + - 3 files changed, 21 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -1767,6 +1767,12 @@ static int wl1271_op_suspend(struct ieee - flush_work(&wl->tx_work); - flush_delayed_work(&wl->elp_work); - -+ /* -+ * Cancel the watchdog even if above tx_flush failed. We will detect -+ * it on resume anyway. -+ */ -+ cancel_delayed_work(&wl->tx_watchdog_work); -+ - return 0; - } - -@@ -1824,6 +1830,13 @@ static int wl1271_op_resume(struct ieee8 - - out: - wl->wow_enabled = false; -+ -+ /* -+ * Set a flag to re-init the watchdog on the first Tx after resume. -+ * That way we avoid possible conditions where Tx-complete interrupts -+ * fail to arrive and we perform a spurious recovery. -+ */ -+ set_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags); - mutex_unlock(&wl->mutex); - - return 0; ---- a/drivers/net/wireless/ti/wlcore/tx.c -+++ b/drivers/net/wireless/ti/wlcore/tx.c -@@ -234,8 +234,13 @@ static int wl1271_tx_allocate(struct wl1 - wl->tx_blocks_available -= total_blocks; - wl->tx_allocated_blocks += total_blocks; - -- /* If the FW was empty before, arm the Tx watchdog */ -- if (wl->tx_allocated_blocks == total_blocks) -+ /* -+ * If the FW was empty before, arm the Tx watchdog. Also do -+ * this on the first Tx after resume, as we always cancel the -+ * watchdog on suspend. -+ */ -+ if (wl->tx_allocated_blocks == total_blocks || -+ test_and_clear_bit(WL1271_FLAG_REINIT_TX_WDOG, &wl->flags)) - wl12xx_rearm_tx_watchdog_locked(wl); - - ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); ---- a/drivers/net/wireless/ti/wlcore/wlcore_i.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h -@@ -240,6 +240,7 @@ enum wl12xx_flags { - WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, - WL1271_FLAG_INTENDED_FW_RECOVERY, - WL1271_FLAG_IO_FAILED, -+ WL1271_FLAG_REINIT_TX_WDOG, - }; - - enum wl12xx_vif_flags { diff --git a/package/kernel/mac80211/patches/920-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch b/package/kernel/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch similarity index 89% rename from package/kernel/mac80211/patches/920-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch rename to package/kernel/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch index d15e9eb6a3..3d501b2fab 100644 --- a/package/kernel/mac80211/patches/920-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch +++ b/package/kernel/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch @@ -13,7 +13,7 @@ Signed-off-by: Arik Nemtsov --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -5179,6 +5179,10 @@ static void wl12xx_op_channel_switch(str +@@ -5181,6 +5181,10 @@ static void wl12xx_op_channel_switch(str if (unlikely(wl->state == WLCORE_STATE_OFF)) { wl12xx_for_each_wlvif_sta(wl, wlvif) { struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); @@ -24,7 +24,7 @@ Signed-off-by: Arik Nemtsov ieee80211_chswitch_done(vif, false); } goto out; -@@ -5194,6 +5198,9 @@ static void wl12xx_op_channel_switch(str +@@ -5196,6 +5200,9 @@ static void wl12xx_op_channel_switch(str wl12xx_for_each_wlvif_sta(wl, wlvif) { unsigned long delay_usec; diff --git a/package/kernel/mac80211/patches/903-wlcore-block-read-writes-to-FW-during-ELP.patch b/package/kernel/mac80211/patches/903-wlcore-block-read-writes-to-FW-during-ELP.patch deleted file mode 100644 index 1aafb32968..0000000000 --- a/package/kernel/mac80211/patches/903-wlcore-block-read-writes-to-FW-during-ELP.patch +++ /dev/null @@ -1,36 +0,0 @@ -When the chip is in ELP mode read/write to FW is invalid and may cause -the lower layers to get stuck. The reads/writes concerning ELP wakeup -are the exception here and are checked for. In addition to blocking the -IO, produce a warning. - -Signed-off-by: Barak Bercovitz -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/io.h | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/ti/wlcore/io.h -+++ b/drivers/net/wireless/ti/wlcore/io.h -@@ -60,7 +60,9 @@ static inline int __must_check wlcore_ra - { - int ret; - -- if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags)) -+ if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags) || -+ WARN_ON((test_bit(WL1271_FLAG_IN_ELP, &wl->flags) && -+ addr != HW_ACCESS_ELP_CTRL_REG))) - return -EIO; - - ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed); -@@ -76,7 +78,9 @@ static inline int __must_check wlcore_ra - { - int ret; - -- if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags)) -+ if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags) || -+ WARN_ON((test_bit(WL1271_FLAG_IN_ELP, &wl->flags) && -+ addr != HW_ACCESS_ELP_CTRL_REG))) - return -EIO; - - ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed); diff --git a/package/kernel/mac80211/patches/904-wlcore-AP-don-t-start-mac80211-PS-on-non-peer-HLIDs.patch b/package/kernel/mac80211/patches/904-wlcore-AP-don-t-start-mac80211-PS-on-non-peer-HLIDs.patch deleted file mode 100644 index 3942f1e5a1..0000000000 --- a/package/kernel/mac80211/patches/904-wlcore-AP-don-t-start-mac80211-PS-on-non-peer-HLIDs.patch +++ /dev/null @@ -1,28 +0,0 @@ -It seems the wl18xx FW sometimes sends spurious changes on the PSM state -of the broadcast HLID. This causes us to search for a station on a -non-peer link and fail, causing warnings in our log. - -Prevent the driver from considering PSM changes for any non-peer HLIDs. - -Signed-off-by: Arik Nemtsov -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/ps.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/ti/wlcore/ps.c -+++ b/drivers/net/wireless/ti/wlcore/ps.c -@@ -280,7 +280,11 @@ void wl12xx_ps_link_start(struct wl1271 - struct ieee80211_sta *sta; - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); - -- if (test_bit(hlid, &wl->ap_ps_map)) -+ if (WARN_ON_ONCE(wlvif->bss_type != BSS_TYPE_AP_BSS)) -+ return; -+ -+ if (!test_bit(hlid, wlvif->ap.sta_hlid_map) || -+ test_bit(hlid, &wl->ap_ps_map)) - return; - - wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d " diff --git a/package/kernel/mac80211/patches/905-wlcore-wl12xx-wl18xx-simplify-fw_status-handling.patch b/package/kernel/mac80211/patches/905-wlcore-wl12xx-wl18xx-simplify-fw_status-handling.patch deleted file mode 100644 index c669797ef3..0000000000 --- a/package/kernel/mac80211/patches/905-wlcore-wl12xx-wl18xx-simplify-fw_status-handling.patch +++ /dev/null @@ -1,731 +0,0 @@ -Instead of splitting the fw_status into 2 and using some -complex calculations, read the fw status and let each low-level -driver (wl12xx/wl18xx) convert it into a common struct. - -This is required for the upcoming fw api changes, which -break the current logic anyway. - -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wl12xx/main.c | 35 ++++++++++- - drivers/net/wireless/ti/wl12xx/wl12xx.h | 50 ++++++++++++++++ - drivers/net/wireless/ti/wl18xx/main.c | 39 ++++++++++++- - drivers/net/wireless/ti/wl18xx/tx.c | 4 +- - drivers/net/wireless/ti/wl18xx/wl18xx.h | 53 +++++++++++++++++ - drivers/net/wireless/ti/wlcore/cmd.c | 11 +++- - drivers/net/wireless/ti/wlcore/hw_ops.h | 9 +++ - drivers/net/wireless/ti/wlcore/main.c | 96 +++++++++++++++---------------- - drivers/net/wireless/ti/wlcore/rx.c | 2 +- - drivers/net/wireless/ti/wlcore/rx.h | 2 +- - drivers/net/wireless/ti/wlcore/wlcore.h | 7 ++- - drivers/net/wireless/ti/wlcore/wlcore_i.h | 72 ++++++++++------------- - 12 files changed, 277 insertions(+), 103 deletions(-) - ---- a/drivers/net/wireless/ti/wl12xx/main.c -+++ b/drivers/net/wireless/ti/wl12xx/main.c -@@ -1378,7 +1378,7 @@ static u32 wl12xx_get_rx_packet_len(stru - - static int wl12xx_tx_delayed_compl(struct wl1271 *wl) - { -- if (wl->fw_status_1->tx_results_counter == -+ if (wl->fw_status->tx_results_counter == - (wl->tx_results_count & 0xff)) - return 0; - -@@ -1438,6 +1438,37 @@ out: - return ret; - } - -+static void wl12xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status, -+ struct wl_fw_status *fw_status) -+{ -+ struct wl12xx_fw_status *int_fw_status = raw_fw_status; -+ -+ fw_status->intr = le32_to_cpu(int_fw_status->intr); -+ fw_status->fw_rx_counter = int_fw_status->fw_rx_counter; -+ fw_status->drv_rx_counter = int_fw_status->drv_rx_counter; -+ fw_status->tx_results_counter = int_fw_status->tx_results_counter; -+ fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs; -+ -+ fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime); -+ fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap); -+ fw_status->link_fast_bitmap = -+ le32_to_cpu(int_fw_status->link_fast_bitmap); -+ fw_status->total_released_blks = -+ le32_to_cpu(int_fw_status->total_released_blks); -+ fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total); -+ -+ fw_status->counters.tx_released_pkts = -+ int_fw_status->counters.tx_released_pkts; -+ fw_status->counters.tx_lnk_free_pkts = -+ int_fw_status->counters.tx_lnk_free_pkts; -+ fw_status->counters.tx_voice_released_blks = -+ int_fw_status->counters.tx_voice_released_blks; -+ fw_status->counters.tx_last_rate = -+ int_fw_status->counters.tx_last_rate; -+ -+ fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr); -+} -+ - static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl, - struct wl12xx_vif *wlvif) - { -@@ -1677,6 +1708,7 @@ static struct wlcore_ops wl12xx_ops = { - .tx_delayed_compl = wl12xx_tx_delayed_compl, - .hw_init = wl12xx_hw_init, - .init_vif = NULL, -+ .convert_fw_status = wl12xx_convert_fw_status, - .sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask, - .get_pg_ver = wl12xx_get_pg_ver, - .get_mac = wl12xx_get_mac, -@@ -1725,6 +1757,7 @@ static int wl12xx_setup(struct wl1271 *w - wl->band_rate_to_idx = wl12xx_band_rate_to_idx; - wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; - wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; -+ wl->fw_status_len = sizeof(struct wl12xx_fw_status); - wl->fw_status_priv_len = 0; - wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); - wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap); ---- a/drivers/net/wireless/ti/wl12xx/wl12xx.h -+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h -@@ -79,4 +79,54 @@ struct wl12xx_priv { - struct wl127x_rx_mem_pool_addr *rx_mem_addr; - }; - -+struct wl12xx_fw_packet_counters { -+ /* Cumulative counter of released packets per AC */ -+ u8 tx_released_pkts[NUM_TX_QUEUES]; -+ -+ /* Cumulative counter of freed packets per HLID */ -+ u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS]; -+ -+ /* Cumulative counter of released Voice memory blocks */ -+ u8 tx_voice_released_blks; -+ -+ /* Tx rate of the last transmitted packet */ -+ u8 tx_last_rate; -+ -+ u8 padding[2]; -+} __packed; -+ -+/* FW status registers */ -+struct wl12xx_fw_status { -+ __le32 intr; -+ u8 fw_rx_counter; -+ u8 drv_rx_counter; -+ u8 reserved; -+ u8 tx_results_counter; -+ __le32 rx_pkt_descs[WL12XX_NUM_RX_DESCRIPTORS]; -+ -+ __le32 fw_localtime; -+ -+ /* -+ * A bitmap (where each bit represents a single HLID) -+ * to indicate if the station is in PS mode. -+ */ -+ __le32 link_ps_bitmap; -+ -+ /* -+ * A bitmap (where each bit represents a single HLID) to indicate -+ * if the station is in Fast mode -+ */ -+ __le32 link_fast_bitmap; -+ -+ /* Cumulative counter of total released mem blocks since FW-reset */ -+ __le32 total_released_blks; -+ -+ /* Size (in Memory Blocks) of TX pool */ -+ __le32 tx_total; -+ -+ struct wl12xx_fw_packet_counters counters; -+ -+ __le32 log_start_addr; -+} __packed; -+ - #endif /* __WL12XX_PRIV_H__ */ ---- a/drivers/net/wireless/ti/wl18xx/main.c -+++ b/drivers/net/wireless/ti/wl18xx/main.c -@@ -1133,6 +1133,39 @@ static int wl18xx_hw_init(struct wl1271 - return ret; - } - -+static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status, -+ struct wl_fw_status *fw_status) -+{ -+ struct wl18xx_fw_status *int_fw_status = raw_fw_status; -+ -+ fw_status->intr = le32_to_cpu(int_fw_status->intr); -+ fw_status->fw_rx_counter = int_fw_status->fw_rx_counter; -+ fw_status->drv_rx_counter = int_fw_status->drv_rx_counter; -+ fw_status->tx_results_counter = int_fw_status->tx_results_counter; -+ fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs; -+ -+ fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime); -+ fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap); -+ fw_status->link_fast_bitmap = -+ le32_to_cpu(int_fw_status->link_fast_bitmap); -+ fw_status->total_released_blks = -+ le32_to_cpu(int_fw_status->total_released_blks); -+ fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total); -+ -+ fw_status->counters.tx_released_pkts = -+ int_fw_status->counters.tx_released_pkts; -+ fw_status->counters.tx_lnk_free_pkts = -+ int_fw_status->counters.tx_lnk_free_pkts; -+ fw_status->counters.tx_voice_released_blks = -+ int_fw_status->counters.tx_voice_released_blks; -+ fw_status->counters.tx_last_rate = -+ int_fw_status->counters.tx_last_rate; -+ -+ fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr); -+ -+ fw_status->priv = &int_fw_status->priv; -+} -+ - static void wl18xx_set_tx_desc_csum(struct wl1271 *wl, - struct wl1271_tx_hw_descr *desc, - struct sk_buff *skb) -@@ -1572,7 +1605,7 @@ static bool wl18xx_lnk_high_prio(struct - { - u8 thold; - struct wl18xx_fw_status_priv *status_priv = -- (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; -+ (struct wl18xx_fw_status_priv *)wl->fw_status->priv; - u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); - - /* suspended links are never high priority */ -@@ -1594,7 +1627,7 @@ static bool wl18xx_lnk_low_prio(struct w - { - u8 thold; - struct wl18xx_fw_status_priv *status_priv = -- (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; -+ (struct wl18xx_fw_status_priv *)wl->fw_status->priv; - u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); - - if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) -@@ -1632,6 +1665,7 @@ static struct wlcore_ops wl18xx_ops = { - .tx_immediate_compl = wl18xx_tx_immediate_completion, - .tx_delayed_compl = NULL, - .hw_init = wl18xx_hw_init, -+ .convert_fw_status = wl18xx_convert_fw_status, - .set_tx_desc_csum = wl18xx_set_tx_desc_csum, - .get_pg_ver = wl18xx_get_pg_ver, - .set_rx_csum = wl18xx_set_rx_csum, -@@ -1726,6 +1760,7 @@ static int wl18xx_setup(struct wl1271 *w - wl->band_rate_to_idx = wl18xx_band_rate_to_idx; - wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; - wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; -+ wl->fw_status_len = sizeof(struct wl18xx_fw_status); - wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv); - wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics); - wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv); ---- a/drivers/net/wireless/ti/wl18xx/tx.c -+++ b/drivers/net/wireless/ti/wl18xx/tx.c -@@ -32,7 +32,7 @@ static - void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif, - struct ieee80211_tx_rate *rate) - { -- u8 fw_rate = wl->fw_status_2->counters.tx_last_rate; -+ u8 fw_rate = wl->fw_status->counters.tx_last_rate; - - if (fw_rate > CONF_HW_RATE_INDEX_MAX) { - wl1271_error("last Tx rate invalid: %d", fw_rate); -@@ -139,7 +139,7 @@ static void wl18xx_tx_complete_packet(st - void wl18xx_tx_immediate_complete(struct wl1271 *wl) - { - struct wl18xx_fw_status_priv *status_priv = -- (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; -+ (struct wl18xx_fw_status_priv *)wl->fw_status->priv; - struct wl18xx_priv *priv = wl->priv; - u8 i; - ---- a/drivers/net/wireless/ti/wl18xx/wl18xx.h -+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h -@@ -109,6 +109,59 @@ struct wl18xx_fw_status_priv { - u8 padding[3]; - }; - -+struct wl18xx_fw_packet_counters { -+ /* Cumulative counter of released packets per AC */ -+ u8 tx_released_pkts[NUM_TX_QUEUES]; -+ -+ /* Cumulative counter of freed packets per HLID */ -+ u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS]; -+ -+ /* Cumulative counter of released Voice memory blocks */ -+ u8 tx_voice_released_blks; -+ -+ /* Tx rate of the last transmitted packet */ -+ u8 tx_last_rate; -+ -+ u8 padding[2]; -+} __packed; -+ -+/* FW status registers */ -+struct wl18xx_fw_status { -+ __le32 intr; -+ u8 fw_rx_counter; -+ u8 drv_rx_counter; -+ u8 reserved; -+ u8 tx_results_counter; -+ __le32 rx_pkt_descs[WL18XX_NUM_RX_DESCRIPTORS]; -+ -+ __le32 fw_localtime; -+ -+ /* -+ * A bitmap (where each bit represents a single HLID) -+ * to indicate if the station is in PS mode. -+ */ -+ __le32 link_ps_bitmap; -+ -+ /* -+ * A bitmap (where each bit represents a single HLID) to indicate -+ * if the station is in Fast mode -+ */ -+ __le32 link_fast_bitmap; -+ -+ /* Cumulative counter of total released mem blocks since FW-reset */ -+ __le32 total_released_blks; -+ -+ /* Size (in Memory Blocks) of TX pool */ -+ __le32 tx_total; -+ -+ struct wl18xx_fw_packet_counters counters; -+ -+ __le32 log_start_addr; -+ -+ /* Private status to be used by the lower drivers */ -+ struct wl18xx_fw_status_priv priv; -+} __packed; -+ - #define WL18XX_PHY_VERSION_MAX_LEN 20 - - struct wl18xx_static_data_priv { ---- a/drivers/net/wireless/ti/wlcore/cmd.c -+++ b/drivers/net/wireless/ti/wlcore/cmd.c -@@ -324,9 +324,14 @@ int wl12xx_allocate_link(struct wl1271 * - __set_bit(link, wlvif->links_map); - spin_unlock_irqrestore(&wl->wl_lock, flags); - -- /* take the last "freed packets" value from the current FW status */ -- wl->links[link].prev_freed_pkts = -- wl->fw_status_2->counters.tx_lnk_free_pkts[link]; -+ /* -+ * take the last "freed packets" value from the current FW status. -+ * on recovery, we might not have fw_status yet, and -+ * tx_lnk_free_pkts will be NULL. check for it. -+ */ -+ if (wl->fw_status->counters.tx_lnk_free_pkts) -+ wl->links[link].prev_freed_pkts = -+ wl->fw_status->counters.tx_lnk_free_pkts[link]; - wl->links[link].wlvif = wlvif; - - /* ---- a/drivers/net/wireless/ti/wlcore/hw_ops.h -+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h -@@ -106,6 +106,15 @@ wlcore_hw_init_vif(struct wl1271 *wl, st - return 0; - } - -+static inline void -+wlcore_hw_convert_fw_status(struct wl1271 *wl, void *raw_fw_status, -+ struct wl_fw_status *fw_status) -+{ -+ BUG_ON(!wl->ops->convert_fw_status); -+ -+ wl->ops->convert_fw_status(wl, raw_fw_status, fw_status); -+} -+ - static inline u32 - wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif) - { ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -357,12 +357,12 @@ static void wl12xx_irq_ps_regulate_link( - - static void wl12xx_irq_update_links_status(struct wl1271 *wl, - struct wl12xx_vif *wlvif, -- struct wl_fw_status_2 *status) -+ struct wl_fw_status *status) - { - u32 cur_fw_ps_map; - u8 hlid; - -- cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap); -+ cur_fw_ps_map = status->link_ps_bitmap; - if (wl->ap_fw_ps_map != cur_fw_ps_map) { - wl1271_debug(DEBUG_PSM, - "link ps prev 0x%x cur 0x%x changed 0x%x", -@@ -377,41 +377,38 @@ static void wl12xx_irq_update_links_stat - wl->links[hlid].allocated_pkts); - } - --static int wlcore_fw_status(struct wl1271 *wl, -- struct wl_fw_status_1 *status_1, -- struct wl_fw_status_2 *status_2) -+static int wlcore_fw_status(struct wl1271 *wl, struct wl_fw_status *status) - { - struct wl12xx_vif *wlvif; - struct timespec ts; - u32 old_tx_blk_count = wl->tx_blocks_available; - int avail, freed_blocks; - int i; -- size_t status_len; - int ret; - struct wl1271_link *lnk; - -- status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + -- sizeof(*status_2) + wl->fw_status_priv_len; -- -- ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1, -- status_len, false); -+ ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, -+ wl->raw_fw_status, -+ wl->fw_status_len, false); - if (ret < 0) - return ret; - -+ wlcore_hw_convert_fw_status(wl, wl->raw_fw_status, wl->fw_status); -+ - wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " - "drv_rx_counter = %d, tx_results_counter = %d)", -- status_1->intr, -- status_1->fw_rx_counter, -- status_1->drv_rx_counter, -- status_1->tx_results_counter); -+ status->intr, -+ status->fw_rx_counter, -+ status->drv_rx_counter, -+ status->tx_results_counter); - - for (i = 0; i < NUM_TX_QUEUES; i++) { - /* prevent wrap-around in freed-packets counter */ - wl->tx_allocated_pkts[i] -= -- (status_2->counters.tx_released_pkts[i] - -+ (status->counters.tx_released_pkts[i] - - wl->tx_pkts_freed[i]) & 0xff; - -- wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i]; -+ wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i]; - } - - -@@ -420,29 +417,28 @@ static int wlcore_fw_status(struct wl127 - lnk = &wl->links[i]; - - /* prevent wrap-around in freed-packets counter */ -- diff = (status_2->counters.tx_lnk_free_pkts[i] - -+ diff = (status->counters.tx_lnk_free_pkts[i] - - lnk->prev_freed_pkts) & 0xff; - - if (diff == 0) - continue; - - lnk->allocated_pkts -= diff; -- lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i]; -+ lnk->prev_freed_pkts = status->counters.tx_lnk_free_pkts[i]; - - /* accumulate the prev_freed_pkts counter */ - lnk->total_freed_pkts += diff; - } - - /* prevent wrap-around in total blocks counter */ -- if (likely(wl->tx_blocks_freed <= -- le32_to_cpu(status_2->total_released_blks))) -- freed_blocks = le32_to_cpu(status_2->total_released_blks) - -+ if (likely(wl->tx_blocks_freed <= status->total_released_blks)) -+ freed_blocks = status->total_released_blks - - wl->tx_blocks_freed; - else - freed_blocks = 0x100000000LL - wl->tx_blocks_freed + -- le32_to_cpu(status_2->total_released_blks); -+ status->total_released_blks; - -- wl->tx_blocks_freed = le32_to_cpu(status_2->total_released_blks); -+ wl->tx_blocks_freed = status->total_released_blks; - - wl->tx_allocated_blocks -= freed_blocks; - -@@ -458,7 +454,7 @@ static int wlcore_fw_status(struct wl127 - cancel_delayed_work(&wl->tx_watchdog_work); - } - -- avail = le32_to_cpu(status_2->tx_total) - wl->tx_allocated_blocks; -+ avail = status->tx_total - wl->tx_allocated_blocks; - - /* - * The FW might change the total number of TX memblocks before -@@ -477,15 +473,15 @@ static int wlcore_fw_status(struct wl127 - - /* for AP update num of allocated TX blocks per link and ps status */ - wl12xx_for_each_wlvif_ap(wl, wlvif) { -- wl12xx_irq_update_links_status(wl, wlvif, status_2); -+ wl12xx_irq_update_links_status(wl, wlvif, status); - } - - /* update the host-chipset time offset */ - getnstimeofday(&ts); - wl->time_offset = (timespec_to_ns(&ts) >> 10) - -- (s64)le32_to_cpu(status_2->fw_localtime); -+ (s64)(status->fw_localtime); - -- wl->fw_fast_lnk_map = le32_to_cpu(status_2->link_fast_bitmap); -+ wl->fw_fast_lnk_map = status->link_fast_bitmap; - - return 0; - } -@@ -549,13 +545,13 @@ static int wlcore_irq_locked(struct wl12 - clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); - smp_mb__after_clear_bit(); - -- ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); -+ ret = wlcore_fw_status(wl, wl->fw_status); - if (ret < 0) - goto out; - - wlcore_hw_tx_immediate_compl(wl); - -- intr = le32_to_cpu(wl->fw_status_1->intr); -+ intr = wl->fw_status->intr; - intr &= WLCORE_ALL_INTR_MASK; - if (!intr) { - done = true; -@@ -584,7 +580,7 @@ static int wlcore_irq_locked(struct wl12 - if (likely(intr & WL1271_ACX_INTR_DATA)) { - wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); - -- ret = wlcore_rx(wl, wl->fw_status_1); -+ ret = wlcore_rx(wl, wl->fw_status); - if (ret < 0) - goto out; - -@@ -843,11 +839,11 @@ static void wl12xx_read_fwlog_panic(stru - wl12xx_cmd_stop_fwlog(wl); - - /* Read the first memory block address */ -- ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); -+ ret = wlcore_fw_status(wl, wl->fw_status); - if (ret < 0) - goto out; - -- addr = le32_to_cpu(wl->fw_status_2->log_start_addr); -+ addr = wl->fw_status->log_start_addr; - if (!addr) - goto out; - -@@ -990,23 +986,23 @@ static int wlcore_fw_wakeup(struct wl127 - - static int wl1271_setup(struct wl1271 *wl) - { -- wl->fw_status_1 = kzalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + -- sizeof(*wl->fw_status_2) + -- wl->fw_status_priv_len, GFP_KERNEL); -- if (!wl->fw_status_1) -- return -ENOMEM; -+ wl->raw_fw_status = kzalloc(wl->fw_status_len, GFP_KERNEL); -+ if (!wl->raw_fw_status) -+ goto err; - -- wl->fw_status_2 = (struct wl_fw_status_2 *) -- (((u8 *) wl->fw_status_1) + -- WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc)); -+ wl->fw_status = kzalloc(sizeof(*wl->fw_status), GFP_KERNEL); -+ if (!wl->fw_status) -+ goto err; - - wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL); -- if (!wl->tx_res_if) { -- kfree(wl->fw_status_1); -- return -ENOMEM; -- } -+ if (!wl->tx_res_if) -+ goto err; - - return 0; -+err: -+ kfree(wl->fw_status); -+ kfree(wl->raw_fw_status); -+ return -ENOMEM; - } - - static int wl12xx_set_power_on(struct wl1271 *wl) -@@ -1952,9 +1948,10 @@ static void wlcore_op_stop_locked(struct - - wl1271_debugfs_reset(wl); - -- kfree(wl->fw_status_1); -- wl->fw_status_1 = NULL; -- wl->fw_status_2 = NULL; -+ kfree(wl->raw_fw_status); -+ wl->raw_fw_status = NULL; -+ kfree(wl->fw_status); -+ wl->fw_status = NULL; - kfree(wl->tx_res_if); - wl->tx_res_if = NULL; - kfree(wl->target_mem_map); -@@ -6058,7 +6055,8 @@ int wlcore_free_hw(struct wl1271 *wl) - kfree(wl->nvs); - wl->nvs = NULL; - -- kfree(wl->fw_status_1); -+ kfree(wl->raw_fw_status); -+ kfree(wl->fw_status); - kfree(wl->tx_res_if); - destroy_workqueue(wl->freezable_wq); - ---- a/drivers/net/wireless/ti/wlcore/rx.c -+++ b/drivers/net/wireless/ti/wlcore/rx.c -@@ -203,7 +203,7 @@ static int wl1271_rx_handle_data(struct - return is_data; - } - --int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) -+int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status) - { - unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; - u32 buf_size; ---- a/drivers/net/wireless/ti/wlcore/rx.h -+++ b/drivers/net/wireless/ti/wlcore/rx.h -@@ -142,7 +142,7 @@ struct wl1271_rx_descriptor { - u8 reserved; - } __packed; - --int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); -+int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status); - u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); - int wl1271_rx_filter_enable(struct wl1271 *wl, - int index, bool enable, ---- a/drivers/net/wireless/ti/wlcore/wlcore.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore.h -@@ -73,6 +73,8 @@ struct wlcore_ops { - void (*tx_immediate_compl)(struct wl1271 *wl); - int (*hw_init)(struct wl1271 *wl); - int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); -+ void (*convert_fw_status)(struct wl1271 *wl, void *raw_fw_status, -+ struct wl_fw_status *fw_status); - u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, - struct wl12xx_vif *wlvif); - int (*get_pg_ver)(struct wl1271 *wl, s8 *ver); -@@ -348,8 +350,8 @@ struct wl1271 { - u32 buffer_cmd; - u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; - -- struct wl_fw_status_1 *fw_status_1; -- struct wl_fw_status_2 *fw_status_2; -+ void *raw_fw_status; -+ struct wl_fw_status *fw_status; - struct wl1271_tx_hw_res_if *tx_res_if; - - /* Current chipset configuration */ -@@ -450,6 +452,7 @@ struct wl1271 { - struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS]; - - /* size of the private FW status data */ -+ size_t fw_status_len; - size_t fw_status_priv_len; - - /* RX Data filter rule state - enabled/disabled */ ---- a/drivers/net/wireless/ti/wlcore/wlcore_i.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h -@@ -120,70 +120,58 @@ struct wl1271_chip { - - #define AP_MAX_STATIONS 8 - --struct wl_fw_packet_counters { -- /* Cumulative counter of released packets per AC */ -- u8 tx_released_pkts[NUM_TX_QUEUES]; -- -- /* Cumulative counter of freed packets per HLID */ -- u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS]; -- -- /* Cumulative counter of released Voice memory blocks */ -- u8 tx_voice_released_blks; -- -- /* Tx rate of the last transmitted packet */ -- u8 tx_last_rate; -- -- u8 padding[2]; --} __packed; -- --/* FW status registers */ --struct wl_fw_status_1 { -- __le32 intr; -+struct wl_fw_status { -+ u32 intr; - u8 fw_rx_counter; - u8 drv_rx_counter; -- u8 reserved; - u8 tx_results_counter; -- __le32 rx_pkt_descs[0]; --} __packed; -- --/* -- * Each HW arch has a different number of Rx descriptors. -- * The length of the status depends on it, since it holds an array -- * of descriptors. -- */ --#define WLCORE_FW_STATUS_1_LEN(num_rx_desc) \ -- (sizeof(struct wl_fw_status_1) + \ -- (sizeof(((struct wl_fw_status_1 *)0)->rx_pkt_descs[0])) * \ -- num_rx_desc) -+ __le32 *rx_pkt_descs; - --struct wl_fw_status_2 { -- __le32 fw_localtime; -+ u32 fw_localtime; - - /* - * A bitmap (where each bit represents a single HLID) - * to indicate if the station is in PS mode. - */ -- __le32 link_ps_bitmap; -+ u32 link_ps_bitmap; - - /* - * A bitmap (where each bit represents a single HLID) to indicate - * if the station is in Fast mode - */ -- __le32 link_fast_bitmap; -+ u32 link_fast_bitmap; - - /* Cumulative counter of total released mem blocks since FW-reset */ -- __le32 total_released_blks; -+ u32 total_released_blks; - - /* Size (in Memory Blocks) of TX pool */ -- __le32 tx_total; -+ u32 tx_total; - -- struct wl_fw_packet_counters counters; -+ struct { -+ /* -+ * Cumulative counter of released packets per AC -+ * (length of the array is NUM_TX_QUEUES) -+ */ -+ u8 *tx_released_pkts; -+ -+ /* -+ * Cumulative counter of freed packets per HLID -+ * (length of the array is WL12XX_MAX_LINKS) -+ */ -+ u8 *tx_lnk_free_pkts; -+ -+ /* Cumulative counter of released Voice memory blocks */ -+ u8 tx_voice_released_blks; -+ -+ /* Tx rate of the last transmitted packet */ -+ u8 tx_last_rate; -+ } counters; - -- __le32 log_start_addr; -+ u32 log_start_addr; - - /* Private status to be used by the lower drivers */ -- u8 priv[0]; --} __packed; -+ void *priv; -+}; - - #define WL1271_MAX_CHANNELS 64 - struct wl1271_scan { diff --git a/package/kernel/mac80211/patches/906-wlcore-wl12xx-wl18xx-configure-num_links-per-hw.patch b/package/kernel/mac80211/patches/906-wlcore-wl12xx-wl18xx-configure-num_links-per-hw.patch deleted file mode 100644 index 5c342f5e1d..0000000000 --- a/package/kernel/mac80211/patches/906-wlcore-wl12xx-wl18xx-configure-num_links-per-hw.patch +++ /dev/null @@ -1,345 +0,0 @@ -Upcoming fw versions will have different max links support -(according to the hw). Get ready for it by configuring -wl->num_links per-hw, instead of using the const WL12XX_MAX_LINKS. - -However, continue using WLCORE_MAX_LINKS in order to simplify -structs declarations (we use it in multiple bitmaps, and converting -them to dynamic arrays is just cumbersome). - -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wl12xx/main.c | 3 +++ - drivers/net/wireless/ti/wl12xx/wl12xx.h | 2 ++ - drivers/net/wireless/ti/wl18xx/main.c | 3 +++ - drivers/net/wireless/ti/wl18xx/wl18xx.h | 4 +++- - drivers/net/wireless/ti/wlcore/cmd.c | 4 ++-- - drivers/net/wireless/ti/wlcore/event.c | 4 ++-- - drivers/net/wireless/ti/wlcore/main.c | 12 ++++++++---- - drivers/net/wireless/ti/wlcore/rx.c | 8 ++++---- - drivers/net/wireless/ti/wlcore/tx.c | 20 ++++++++++---------- - drivers/net/wireless/ti/wlcore/wlcore.h | 8 +++++--- - drivers/net/wireless/ti/wlcore/wlcore_i.h | 13 +++++++++---- - 11 files changed, 51 insertions(+), 30 deletions(-) - ---- a/drivers/net/wireless/ti/wl12xx/main.c -+++ b/drivers/net/wireless/ti/wl12xx/main.c -@@ -1749,9 +1749,12 @@ static int wl12xx_setup(struct wl1271 *w - struct wlcore_platdev_data *pdev_data = dev_get_platdata(&wl->pdev->dev); - struct wl12xx_platform_data *pdata = pdev_data->pdata; - -+ BUILD_BUG_ON(WL12XX_MAX_LINKS > WLCORE_MAX_LINKS); -+ - wl->rtable = wl12xx_rtable; - wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; - wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; -+ wl->num_links = WL12XX_MAX_LINKS; - wl->num_channels = 1; - wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES; - wl->band_rate_to_idx = wl12xx_band_rate_to_idx; ---- a/drivers/net/wireless/ti/wl12xx/wl12xx.h -+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h -@@ -65,6 +65,8 @@ - - #define WL12XX_RX_BA_MAX_SESSIONS 3 - -+#define WL12XX_MAX_LINKS 12 -+ - struct wl127x_rx_mem_pool_addr { - u32 addr; - u32 addr_extra; ---- a/drivers/net/wireless/ti/wl18xx/main.c -+++ b/drivers/net/wireless/ti/wl18xx/main.c -@@ -1752,9 +1752,12 @@ static int wl18xx_setup(struct wl1271 *w - struct wl18xx_priv *priv = wl->priv; - int ret; - -+ BUILD_BUG_ON(WL18XX_MAX_LINKS > WLCORE_MAX_LINKS); -+ - wl->rtable = wl18xx_rtable; - wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; - wl->num_rx_desc = WL18XX_NUM_RX_DESCRIPTORS; -+ wl->num_links = WL18XX_MAX_LINKS; - wl->num_channels = 2; - wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES; - wl->band_rate_to_idx = wl18xx_band_rate_to_idx; ---- a/drivers/net/wireless/ti/wl18xx/wl18xx.h -+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h -@@ -42,6 +42,8 @@ - - #define WL18XX_RX_BA_MAX_SESSIONS 5 - -+#define WL18XX_MAX_LINKS 12 -+ - struct wl18xx_priv { - /* buffer for sending commands to FW */ - u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; -@@ -114,7 +116,7 @@ struct wl18xx_fw_packet_counters { - u8 tx_released_pkts[NUM_TX_QUEUES]; - - /* Cumulative counter of freed packets per HLID */ -- u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS]; -+ u8 tx_lnk_free_pkts[WL18XX_MAX_LINKS]; - - /* Cumulative counter of released Voice memory blocks */ - u8 tx_voice_released_blks; ---- a/drivers/net/wireless/ti/wlcore/cmd.c -+++ b/drivers/net/wireless/ti/wlcore/cmd.c -@@ -312,8 +312,8 @@ static int wlcore_get_new_session_id(str - int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) - { - unsigned long flags; -- u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); -- if (link >= WL12XX_MAX_LINKS) -+ u8 link = find_first_zero_bit(wl->links_map, wl->num_links); -+ if (link >= wl->num_links) - return -EBUSY; - - wl->session_ids[link] = wlcore_get_new_session_id(wl, link); ---- a/drivers/net/wireless/ti/wlcore/event.c -+++ b/drivers/net/wireless/ti/wlcore/event.c -@@ -68,7 +68,7 @@ static void wl1271_stop_ba_event(struct - u8 hlid; - struct wl1271_link *lnk; - for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, -- WL12XX_MAX_LINKS) { -+ wl->num_links) { - lnk = &wl->links[hlid]; - if (!lnk->ba_bitmap) - continue; -@@ -173,7 +173,7 @@ static void wlcore_disconnect_sta(struct - const u8 *addr; - int h; - -- for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) { -+ for_each_set_bit(h, &sta_bitmap, wl->num_links) { - bool found = false; - /* find the ap vif connected to this sta */ - wl12xx_for_each_wlvif_ap(wl, wlvif) { ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -372,7 +372,7 @@ static void wl12xx_irq_update_links_stat - wl->ap_fw_ps_map = cur_fw_ps_map; - } - -- for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) -+ for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, wl->num_links) - wl12xx_irq_ps_regulate_link(wl, wlvif, hlid, - wl->links[hlid].allocated_pkts); - } -@@ -412,7 +412,7 @@ static int wlcore_fw_status(struct wl127 - } - - -- for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) { -+ for_each_set_bit(i, wl->links_map, wl->num_links) { - u8 diff; - lnk = &wl->links[i]; - -@@ -5888,7 +5888,7 @@ struct ieee80211_hw *wlcore_alloc_hw(siz - int i, j, ret; - unsigned int order; - -- BUILD_BUG_ON(AP_MAX_STATIONS > WL12XX_MAX_LINKS); -+ BUILD_BUG_ON(AP_MAX_STATIONS > WLCORE_MAX_LINKS); - - hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); - if (!hw) { -@@ -5911,8 +5911,12 @@ struct ieee80211_hw *wlcore_alloc_hw(siz - - wl->hw = hw; - -+ /* -+ * wl->num_links is not configured yet, so just use WLCORE_MAX_LINKS. -+ * we don't allocate any additional resource here, so that's fine. -+ */ - for (i = 0; i < NUM_TX_QUEUES; i++) -- for (j = 0; j < WL12XX_MAX_LINKS; j++) -+ for (j = 0; j < WLCORE_MAX_LINKS; j++) - skb_queue_head_init(&wl->links[j].tx_queue[i]); - - skb_queue_head_init(&wl->deferred_rx_queue); ---- a/drivers/net/wireless/ti/wlcore/rx.c -+++ b/drivers/net/wireless/ti/wlcore/rx.c -@@ -205,7 +205,7 @@ static int wl1271_rx_handle_data(struct - - int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status) - { -- unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; -+ unsigned long active_hlids[BITS_TO_LONGS(WLCORE_MAX_LINKS)] = {0}; - u32 buf_size; - u32 fw_rx_counter = status->fw_rx_counter % wl->num_rx_desc; - u32 drv_rx_counter = wl->rx_counter % wl->num_rx_desc; -@@ -263,12 +263,12 @@ int wlcore_rx(struct wl1271 *wl, struct - wl->aggr_buf + pkt_offset, - pkt_len, rx_align, - &hlid) == 1) { -- if (hlid < WL12XX_MAX_LINKS) -+ if (hlid < wl->num_links) - __set_bit(hlid, active_hlids); - else - WARN(1, -- "hlid exceeded WL12XX_MAX_LINKS " -- "(%d)\n", hlid); -+ "hlid (%d) exceeded MAX_LINKS\n", -+ hlid); - } - - wl->rx_counter++; ---- a/drivers/net/wireless/ti/wlcore/tx.c -+++ b/drivers/net/wireless/ti/wlcore/tx.c -@@ -565,11 +565,11 @@ static struct sk_buff *wlcore_vif_dequeu - int i, h, start_hlid; - - /* start from the link after the last one */ -- start_hlid = (wlvif->last_tx_hlid + 1) % WL12XX_MAX_LINKS; -+ start_hlid = (wlvif->last_tx_hlid + 1) % wl->num_links; - - /* dequeue according to AC, round robin on each link */ -- for (i = 0; i < WL12XX_MAX_LINKS; i++) { -- h = (start_hlid + i) % WL12XX_MAX_LINKS; -+ for (i = 0; i < wl->num_links; i++) { -+ h = (start_hlid + i) % wl->num_links; - - /* only consider connected stations */ - if (!test_bit(h, wlvif->links_map)) -@@ -693,8 +693,8 @@ static void wl1271_skb_queue_head(struct - skb_queue_head(&wl->links[hlid].tx_queue[q], skb); - - /* make sure we dequeue the same packet next time */ -- wlvif->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) % -- WL12XX_MAX_LINKS; -+ wlvif->last_tx_hlid = (hlid + wl->num_links - 1) % -+ wl->num_links; - } - - spin_lock_irqsave(&wl->wl_lock, flags); -@@ -727,7 +727,7 @@ void wl12xx_rearm_rx_streaming(struct wl - timeout = wl->conf.rx_streaming.duration; - wl12xx_for_each_wlvif_sta(wl, wlvif) { - bool found = false; -- for_each_set_bit(hlid, active_hlids, WL12XX_MAX_LINKS) { -+ for_each_set_bit(hlid, active_hlids, wl->num_links) { - if (test_bit(hlid, wlvif->links_map)) { - found = true; - break; -@@ -764,7 +764,7 @@ int wlcore_tx_work_locked(struct wl1271 - struct wl1271_tx_hw_descr *desc; - u32 buf_offset = 0, last_len = 0; - bool sent_packets = false; -- unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; -+ unsigned long active_hlids[BITS_TO_LONGS(WLCORE_MAX_LINKS)] = {0}; - int ret = 0; - int bus_ret = 0; - u8 hlid; -@@ -1066,7 +1066,7 @@ void wl12xx_tx_reset_wlvif(struct wl1271 - int i; - - /* TX failure */ -- for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { -+ for_each_set_bit(i, wlvif->links_map, wl->num_links) { - if (wlvif->bss_type == BSS_TYPE_AP_BSS && - i != wlvif->ap.bcast_hlid && i != wlvif->ap.global_hlid) { - /* this calls wl12xx_free_link */ -@@ -1090,7 +1090,7 @@ void wl12xx_tx_reset(struct wl1271 *wl) - - /* only reset the queues if something bad happened */ - if (wl1271_tx_total_queue_count(wl) != 0) { -- for (i = 0; i < WL12XX_MAX_LINKS; i++) -+ for (i = 0; i < wl->num_links; i++) - wl1271_tx_reset_link_queues(wl, i); - - for (i = 0; i < NUM_TX_QUEUES; i++) -@@ -1183,7 +1183,7 @@ void wl1271_tx_flush(struct wl1271 *wl) - WL1271_TX_FLUSH_TIMEOUT / 1000); - - /* forcibly flush all Tx buffers on our queues */ -- for (i = 0; i < WL12XX_MAX_LINKS; i++) -+ for (i = 0; i < wl->num_links; i++) - wl1271_tx_reset_link_queues(wl, i); - - out_wake: ---- a/drivers/net/wireless/ti/wlcore/wlcore.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore.h -@@ -224,7 +224,7 @@ struct wl1271 { - int channel; - u8 system_hlid; - -- unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; -+ unsigned long links_map[BITS_TO_LONGS(WLCORE_MAX_LINKS)]; - unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; - unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; - unsigned long rate_policies_map[ -@@ -232,7 +232,7 @@ struct wl1271 { - unsigned long klv_templates_map[ - BITS_TO_LONGS(WLCORE_MAX_KLV_TEMPLATES)]; - -- u8 session_ids[WL12XX_MAX_LINKS]; -+ u8 session_ids[WLCORE_MAX_LINKS]; - - struct list_head wlvif_list; - -@@ -380,7 +380,7 @@ struct wl1271 { - * AP-mode - links indexed by HLID. The global and broadcast links - * are always active. - */ -- struct wl1271_link links[WL12XX_MAX_LINKS]; -+ struct wl1271_link links[WLCORE_MAX_LINKS]; - - /* number of currently active links */ - int active_link_count; -@@ -438,6 +438,8 @@ struct wl1271 { - u32 num_tx_desc; - /* number of RX descriptors the HW supports. */ - u32 num_rx_desc; -+ /* number of links the HW supports */ -+ u8 num_links; - - /* translate HW Tx rates to standard rate-indices */ - const u8 **band_rate_to_idx; ---- a/drivers/net/wireless/ti/wlcore/wlcore_i.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h -@@ -58,10 +58,15 @@ - #define WL1271_DEFAULT_DTIM_PERIOD 1 - - #define WL12XX_MAX_ROLES 4 --#define WL12XX_MAX_LINKS 12 - #define WL12XX_INVALID_ROLE_ID 0xff - #define WL12XX_INVALID_LINK_ID 0xff - -+/* -+ * max number of links allowed by all HWs. -+ * this is NOT the actual max links supported by the current hw. -+ */ -+#define WLCORE_MAX_LINKS 12 -+ - /* the driver supports the 2.4Ghz and 5Ghz bands */ - #define WLCORE_NUM_BANDS 2 - -@@ -156,7 +161,7 @@ struct wl_fw_status { - - /* - * Cumulative counter of freed packets per HLID -- * (length of the array is WL12XX_MAX_LINKS) -+ * (length of the array is wl->num_links) - */ - u8 *tx_lnk_free_pkts; - -@@ -357,7 +362,7 @@ struct wl12xx_vif { - - /* HLIDs bitmap of associated stations */ - unsigned long sta_hlid_map[BITS_TO_LONGS( -- WL12XX_MAX_LINKS)]; -+ WLCORE_MAX_LINKS)]; - - /* recoreded keys - set here before AP startup */ - struct wl1271_ap_key *recorded_keys[MAX_NUM_KEYS]; -@@ -374,7 +379,7 @@ struct wl12xx_vif { - /* counters of packets per AC, across all links in the vif */ - int tx_queue_count[NUM_TX_QUEUES]; - -- unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; -+ unsigned long links_map[BITS_TO_LONGS(WLCORE_MAX_LINKS)]; - - u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; - u8 ssid_len; diff --git a/package/kernel/mac80211/patches/907-wlcore-wl12xx-wl18xx-configure-max_stations-per-hw.patch b/package/kernel/mac80211/patches/907-wlcore-wl12xx-wl18xx-configure-max_stations-per-hw.patch deleted file mode 100644 index 66fd7dde1b..0000000000 --- a/package/kernel/mac80211/patches/907-wlcore-wl12xx-wl18xx-configure-max_stations-per-hw.patch +++ /dev/null @@ -1,110 +0,0 @@ -Each hw supports a different max stations (connected to the -same ap). add a new wl->max_ap_stations and use it instead -of the current common AP_MAX_STATIONS. - -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wl12xx/main.c | 2 ++ - drivers/net/wireless/ti/wl12xx/wl12xx.h | 1 + - drivers/net/wireless/ti/wl18xx/main.c | 2 ++ - drivers/net/wireless/ti/wl18xx/wl18xx.h | 1 + - drivers/net/wireless/ti/wlcore/main.c | 4 +--- - drivers/net/wireless/ti/wlcore/wlcore.h | 2 ++ - drivers/net/wireless/ti/wlcore/wlcore_i.h | 2 -- - 7 files changed, 9 insertions(+), 5 deletions(-) - ---- a/drivers/net/wireless/ti/wl12xx/main.c -+++ b/drivers/net/wireless/ti/wl12xx/main.c -@@ -1750,11 +1750,13 @@ static int wl12xx_setup(struct wl1271 *w - struct wl12xx_platform_data *pdata = pdev_data->pdata; - - BUILD_BUG_ON(WL12XX_MAX_LINKS > WLCORE_MAX_LINKS); -+ BUILD_BUG_ON(WL12XX_MAX_AP_STATIONS > WL12XX_MAX_LINKS); - - wl->rtable = wl12xx_rtable; - wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; - wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; - wl->num_links = WL12XX_MAX_LINKS; -+ wl->max_ap_stations = WL12XX_MAX_AP_STATIONS; - wl->num_channels = 1; - wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES; - wl->band_rate_to_idx = wl12xx_band_rate_to_idx; ---- a/drivers/net/wireless/ti/wl12xx/wl12xx.h -+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h -@@ -65,6 +65,7 @@ - - #define WL12XX_RX_BA_MAX_SESSIONS 3 - -+#define WL12XX_MAX_AP_STATIONS 8 - #define WL12XX_MAX_LINKS 12 - - struct wl127x_rx_mem_pool_addr { ---- a/drivers/net/wireless/ti/wl18xx/main.c -+++ b/drivers/net/wireless/ti/wl18xx/main.c -@@ -1753,11 +1753,13 @@ static int wl18xx_setup(struct wl1271 *w - int ret; - - BUILD_BUG_ON(WL18XX_MAX_LINKS > WLCORE_MAX_LINKS); -+ BUILD_BUG_ON(WL18XX_MAX_AP_STATIONS > WL18XX_MAX_LINKS); - - wl->rtable = wl18xx_rtable; - wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; - wl->num_rx_desc = WL18XX_NUM_RX_DESCRIPTORS; - wl->num_links = WL18XX_MAX_LINKS; -+ wl->max_ap_stations = WL18XX_MAX_AP_STATIONS; - wl->num_channels = 2; - wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES; - wl->band_rate_to_idx = wl18xx_band_rate_to_idx; ---- a/drivers/net/wireless/ti/wl18xx/wl18xx.h -+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h -@@ -42,6 +42,7 @@ - - #define WL18XX_RX_BA_MAX_SESSIONS 5 - -+#define WL18XX_MAX_AP_STATIONS 8 - #define WL18XX_MAX_LINKS 12 - - struct wl18xx_priv { ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -4695,7 +4695,7 @@ static int wl1271_allocate_sta(struct wl - int ret; - - -- if (wl->active_sta_count >= AP_MAX_STATIONS) { -+ if (wl->active_sta_count >= wl->max_ap_stations) { - wl1271_warning("could not allocate HLID - too much stations"); - return -EBUSY; - } -@@ -5888,8 +5888,6 @@ struct ieee80211_hw *wlcore_alloc_hw(siz - int i, j, ret; - unsigned int order; - -- BUILD_BUG_ON(AP_MAX_STATIONS > WLCORE_MAX_LINKS); -- - hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); - if (!hw) { - wl1271_error("could not alloc ieee80211_hw"); ---- a/drivers/net/wireless/ti/wlcore/wlcore.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore.h -@@ -440,6 +440,8 @@ struct wl1271 { - u32 num_rx_desc; - /* number of links the HW supports */ - u8 num_links; -+ /* max stations a single AP can support */ -+ u8 max_ap_stations; - - /* translate HW Tx rates to standard rate-indices */ - const u8 **band_rate_to_idx; ---- a/drivers/net/wireless/ti/wlcore/wlcore_i.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h -@@ -123,8 +123,6 @@ struct wl1271_chip { - - #define NUM_TX_QUEUES 4 - --#define AP_MAX_STATIONS 8 -- - struct wl_fw_status { - u32 intr; - u8 fw_rx_counter; diff --git a/package/kernel/mac80211/patches/908-wlcore-wl12xx-wl18xx-configure-iface_combinations-per-hw.patch b/package/kernel/mac80211/patches/908-wlcore-wl12xx-wl18xx-configure-iface_combinations-per-hw.patch deleted file mode 100644 index eb00a50a0e..0000000000 --- a/package/kernel/mac80211/patches/908-wlcore-wl12xx-wl18xx-configure-iface_combinations-per-hw.patch +++ /dev/null @@ -1,176 +0,0 @@ -Each hw supports a different iface combinations. -Define the supported combinations in each driver, -and save it in wl->iface_combinations. - -Since each driver defines its own combinations now, -it can also define its max supported channels, so -we no longer need to save and set it explicitly -in wlcore. - -Update wl18xx interface combinations to allow -multiple APs. - -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wl12xx/main.c | 26 +++++++++++++++++++++- - drivers/net/wireless/ti/wl18xx/main.c | 39 ++++++++++++++++++++++++++++++++- - drivers/net/wireless/ti/wlcore/main.c | 28 ++--------------------- - drivers/net/wireless/ti/wlcore/wlcore.h | 5 +++-- - 4 files changed, 68 insertions(+), 30 deletions(-) - ---- a/drivers/net/wireless/ti/wl12xx/main.c -+++ b/drivers/net/wireless/ti/wl12xx/main.c -@@ -1743,6 +1743,29 @@ static struct ieee80211_sta_ht_cap wl12x - }, - }; - -+static const struct ieee80211_iface_limit wl12xx_iface_limits[] = { -+ { -+ .max = 3, -+ .types = BIT(NL80211_IFTYPE_STATION), -+ }, -+ { -+ .max = 1, -+ .types = BIT(NL80211_IFTYPE_AP) | -+ BIT(NL80211_IFTYPE_P2P_GO) | -+ BIT(NL80211_IFTYPE_P2P_CLIENT), -+ }, -+}; -+ -+static const struct ieee80211_iface_combination -+wl12xx_iface_combinations[] = { -+ { -+ .max_interfaces = 3, -+ .limits = wl12xx_iface_limits, -+ .n_limits = ARRAY_SIZE(wl12xx_iface_limits), -+ .num_different_channels = 1, -+ }, -+}; -+ - static int wl12xx_setup(struct wl1271 *wl) - { - struct wl12xx_priv *priv = wl->priv; -@@ -1757,7 +1780,8 @@ static int wl12xx_setup(struct wl1271 *w - wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; - wl->num_links = WL12XX_MAX_LINKS; - wl->max_ap_stations = WL12XX_MAX_AP_STATIONS; -- wl->num_channels = 1; -+ wl->iface_combinations = wl12xx_iface_combinations; -+ wl->n_iface_combinations = ARRAY_SIZE(wl12xx_iface_combinations); - wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES; - wl->band_rate_to_idx = wl12xx_band_rate_to_idx; - wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; ---- a/drivers/net/wireless/ti/wl18xx/main.c -+++ b/drivers/net/wireless/ti/wl18xx/main.c -@@ -1747,6 +1747,42 @@ static struct ieee80211_sta_ht_cap wl18x - }, - }; - -+static const struct ieee80211_iface_limit wl18xx_iface_limits[] = { -+ { -+ .max = 3, -+ .types = BIT(NL80211_IFTYPE_STATION), -+ }, -+ { -+ .max = 1, -+ .types = BIT(NL80211_IFTYPE_AP) | -+ BIT(NL80211_IFTYPE_P2P_GO) | -+ BIT(NL80211_IFTYPE_P2P_CLIENT), -+ }, -+}; -+ -+static const struct ieee80211_iface_limit wl18xx_iface_ap_limits[] = { -+ { -+ .max = 2, -+ .types = BIT(NL80211_IFTYPE_AP), -+ }, -+}; -+ -+static const struct ieee80211_iface_combination -+wl18xx_iface_combinations[] = { -+ { -+ .max_interfaces = 3, -+ .limits = wl18xx_iface_limits, -+ .n_limits = ARRAY_SIZE(wl18xx_iface_limits), -+ .num_different_channels = 2, -+ }, -+ { -+ .max_interfaces = 2, -+ .limits = wl18xx_iface_ap_limits, -+ .n_limits = ARRAY_SIZE(wl18xx_iface_ap_limits), -+ .num_different_channels = 1, -+ } -+}; -+ - static int wl18xx_setup(struct wl1271 *wl) - { - struct wl18xx_priv *priv = wl->priv; -@@ -1760,7 +1796,8 @@ static int wl18xx_setup(struct wl1271 *w - wl->num_rx_desc = WL18XX_NUM_RX_DESCRIPTORS; - wl->num_links = WL18XX_MAX_LINKS; - wl->max_ap_stations = WL18XX_MAX_AP_STATIONS; -- wl->num_channels = 2; -+ wl->iface_combinations = wl18xx_iface_combinations; -+ wl->n_iface_combinations = ARRAY_SIZE(wl18xx_iface_combinations); - wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES; - wl->band_rate_to_idx = wl18xx_band_rate_to_idx; - wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -5723,28 +5723,6 @@ static void wl1271_unregister_hw(struct - - } - --static const struct ieee80211_iface_limit wlcore_iface_limits[] = { -- { -- .max = 3, -- .types = BIT(NL80211_IFTYPE_STATION), -- }, -- { -- .max = 1, -- .types = BIT(NL80211_IFTYPE_AP) | -- BIT(NL80211_IFTYPE_P2P_GO) | -- BIT(NL80211_IFTYPE_P2P_CLIENT), -- }, --}; -- --static struct ieee80211_iface_combination --wlcore_iface_combinations[] = { -- { -- .max_interfaces = 3, -- .limits = wlcore_iface_limits, -- .n_limits = ARRAY_SIZE(wlcore_iface_limits), -- }, --}; -- - static int wl1271_init_ieee80211(struct wl1271 *wl) - { - int i; -@@ -5865,10 +5843,8 @@ static int wl1271_init_ieee80211(struct - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; - - /* allowed interface combinations */ -- wlcore_iface_combinations[0].num_different_channels = wl->num_channels; -- wl->hw->wiphy->iface_combinations = wlcore_iface_combinations; -- wl->hw->wiphy->n_iface_combinations = -- ARRAY_SIZE(wlcore_iface_combinations); -+ wl->hw->wiphy->iface_combinations = wl->iface_combinations; -+ wl->hw->wiphy->n_iface_combinations = wl->n_iface_combinations; - - SET_IEEE80211_DEV(wl->hw, wl->dev); - ---- a/drivers/net/wireless/ti/wlcore/wlcore.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore.h -@@ -485,8 +485,9 @@ struct wl1271 { - - struct completion nvs_loading_complete; - -- /* number of concurrent channels the HW supports */ -- u32 num_channels; -+ /* interface combinations supported by the hw */ -+ const struct ieee80211_iface_combination *iface_combinations; -+ u8 n_iface_combinations; - }; - - int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); diff --git a/package/kernel/mac80211/patches/909-wl18xx-move-to-new-firmware-wl18xx-fw-3.bin.patch b/package/kernel/mac80211/patches/909-wl18xx-move-to-new-firmware-wl18xx-fw-3.bin.patch deleted file mode 100644 index 85214c1037..0000000000 --- a/package/kernel/mac80211/patches/909-wl18xx-move-to-new-firmware-wl18xx-fw-3.bin.patch +++ /dev/null @@ -1,200 +0,0 @@ -Bump the min wl18xx fw version to 8.8.0.0.13 - -This fw is not backward compatible with older -firmware (due to api changes), so use bump -the firmware name as well. - -Some modifications were done to the driver-fw api -in order to support multiple APs. - -Additionally, some of the consts (such as max stations, -max links and max RX BA sessions) were changed. - -Signed-off-by: Arik Nemtsov -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wl18xx/main.c | 2 +- - drivers/net/wireless/ti/wl18xx/wl18xx.h | 10 +++++----- - drivers/net/wireless/ti/wlcore/acx.c | 4 +++- - drivers/net/wireless/ti/wlcore/acx.h | 6 ++++-- - drivers/net/wireless/ti/wlcore/cmd.c | 5 ++++- - drivers/net/wireless/ti/wlcore/cmd.h | 7 +++++-- - drivers/net/wireless/ti/wlcore/main.c | 2 +- - drivers/net/wireless/ti/wlcore/tx.c | 2 +- - drivers/net/wireless/ti/wlcore/wlcore_i.h | 2 +- - 9 files changed, 25 insertions(+), 15 deletions(-) - ---- a/drivers/net/wireless/ti/wl18xx/main.c -+++ b/drivers/net/wireless/ti/wl18xx/main.c -@@ -648,7 +648,7 @@ static const struct wl18xx_clk_cfg wl18x - }; - - /* TODO: maybe move to a new header file? */ --#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-2.bin" -+#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-3.bin" - - static int wl18xx_identify_chip(struct wl1271 *wl) - { ---- a/drivers/net/wireless/ti/wl18xx/wl18xx.h -+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h -@@ -26,10 +26,10 @@ - - /* minimum FW required for driver */ - #define WL18XX_CHIP_VER 8 --#define WL18XX_IFTYPE_VER 5 -+#define WL18XX_IFTYPE_VER 8 - #define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE - #define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE --#define WL18XX_MINOR_VER 39 -+#define WL18XX_MINOR_VER 13 - - #define WL18XX_CMD_MAX_SIZE 740 - -@@ -40,10 +40,10 @@ - - #define WL18XX_NUM_MAC_ADDRESSES 3 - --#define WL18XX_RX_BA_MAX_SESSIONS 5 -+#define WL18XX_RX_BA_MAX_SESSIONS 13 - --#define WL18XX_MAX_AP_STATIONS 8 --#define WL18XX_MAX_LINKS 12 -+#define WL18XX_MAX_AP_STATIONS 10 -+#define WL18XX_MAX_LINKS 16 - - struct wl18xx_priv { - /* buffer for sending commands to FW */ ---- a/drivers/net/wireless/ti/wlcore/acx.c -+++ b/drivers/net/wireless/ti/wlcore/acx.c -@@ -1591,7 +1591,8 @@ out: - return ret; - } - --int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr) -+int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, -+ struct wl12xx_vif *wlvif, u8 *addr) - { - struct wl1271_acx_inconnection_sta *acx = NULL; - int ret; -@@ -1603,6 +1604,7 @@ int wl1271_acx_set_inconnection_sta(stru - return -ENOMEM; - - memcpy(acx->addr, addr, ETH_ALEN); -+ acx->role_id = wlvif->role_id; - - ret = wl1271_cmd_configure(wl, ACX_UPDATE_INCONNECTION_STA_LIST, - acx, sizeof(*acx)); ---- a/drivers/net/wireless/ti/wlcore/acx.h -+++ b/drivers/net/wireless/ti/wlcore/acx.h -@@ -824,7 +824,8 @@ struct wl1271_acx_inconnection_sta { - struct acx_header header; - - u8 addr[ETH_ALEN]; -- u8 padding1[2]; -+ u8 role_id; -+ u8 padding; - } __packed; - - /* -@@ -1118,7 +1119,8 @@ int wl1271_acx_ps_rx_streaming(struct wl - bool enable); - int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif); - int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif); --int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); -+int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, -+ struct wl12xx_vif *wlvif, u8 *addr); - int wl1271_acx_fm_coex(struct wl1271 *wl); - int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); - int wl12xx_acx_config_hangover(struct wl1271 *wl); ---- a/drivers/net/wireless/ti/wlcore/cmd.c -+++ b/drivers/net/wireless/ti/wlcore/cmd.c -@@ -1532,6 +1532,7 @@ int wl12xx_cmd_add_peer(struct wl1271 *w - cmd->sp_len = sta->max_sp; - cmd->wmm = sta->wme ? 1 : 0; - cmd->session_id = wl->session_ids[hlid]; -+ cmd->role_id = wlvif->role_id; - - for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++) - if (sta->wme && (sta->uapsd_queues & BIT(i))) -@@ -1568,7 +1569,8 @@ out: - return ret; - } - --int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) -+int wl12xx_cmd_remove_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, -+ u8 hlid) - { - struct wl12xx_cmd_remove_peer *cmd; - int ret; -@@ -1586,6 +1588,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 - /* We never send a deauth, mac80211 is in charge of this */ - cmd->reason_opcode = 0; - cmd->send_deauth_flag = 0; -+ cmd->role_id = wlvif->role_id; - - ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0); - if (ret < 0) { ---- a/drivers/net/wireless/ti/wlcore/cmd.h -+++ b/drivers/net/wireless/ti/wlcore/cmd.h -@@ -88,7 +88,8 @@ int wl12xx_roc(struct wl1271 *wl, struct - int wl12xx_croc(struct wl1271 *wl, u8 role_id); - int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct ieee80211_sta *sta, u8 hlid); --int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid); -+int wl12xx_cmd_remove_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, -+ u8 hlid); - void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, - enum ieee80211_band band); - int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl); -@@ -594,6 +595,8 @@ struct wl12xx_cmd_add_peer { - u8 sp_len; - u8 wmm; - u8 session_id; -+ u8 role_id; -+ u8 padding[3]; - } __packed; - - struct wl12xx_cmd_remove_peer { -@@ -602,7 +605,7 @@ struct wl12xx_cmd_remove_peer { - u8 hlid; - u8 reason_opcode; - u8 send_deauth_flag; -- u8 padding1; -+ u8 role_id; - } __packed; - - /* ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -4798,7 +4798,7 @@ static int wl12xx_sta_remove(struct wl12 - if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map))) - return -EINVAL; - -- ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid); -+ ret = wl12xx_cmd_remove_peer(wl, wlvif, wl_sta->hlid); - if (ret < 0) - return ret; - ---- a/drivers/net/wireless/ti/wlcore/tx.c -+++ b/drivers/net/wireless/ti/wlcore/tx.c -@@ -101,7 +101,7 @@ static void wl1271_tx_ap_update_inconnec - * authentication response. this way it won't get de-authed by FW - * when transmitting too soon. - */ -- wl1271_acx_set_inconnection_sta(wl, hdr->addr1); -+ wl1271_acx_set_inconnection_sta(wl, wlvif, hdr->addr1); - - /* - * ROC for 1 second on the AP channel for completing the connection. ---- a/drivers/net/wireless/ti/wlcore/wlcore_i.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h -@@ -65,7 +65,7 @@ - * max number of links allowed by all HWs. - * this is NOT the actual max links supported by the current hw. - */ --#define WLCORE_MAX_LINKS 12 -+#define WLCORE_MAX_LINKS 16 - - /* the driver supports the 2.4Ghz and 5Ghz bands */ - #define WLCORE_NUM_BANDS 2 diff --git a/package/kernel/mac80211/patches/910-wlcore-send-EAPOL-frames-with-voice-priority.patch b/package/kernel/mac80211/patches/910-wlcore-send-EAPOL-frames-with-voice-priority.patch deleted file mode 100644 index 6f6b22a090..0000000000 --- a/package/kernel/mac80211/patches/910-wlcore-send-EAPOL-frames-with-voice-priority.patch +++ /dev/null @@ -1,37 +0,0 @@ -Send EAPOL frames with voice priority by setting (the new) -TX_HW_ATTR_EAPOL_FRAME bit in tx attribute. - -Sending EAPOL with voice priority fixes re-key -timeout issues during heavy traffic. - -Signed-off-by: Igal Chernobelsky -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/tx.c | 4 ++++ - drivers/net/wireless/ti/wlcore/tx.h | 1 + - 2 files changed, 5 insertions(+) - ---- a/drivers/net/wireless/ti/wlcore/tx.c -+++ b/drivers/net/wireless/ti/wlcore/tx.c -@@ -362,6 +362,10 @@ static void wl1271_tx_fill_hdr(struct wl - ieee80211_has_protected(frame_control)) - tx_attr |= TX_HW_ATTR_HOST_ENCRYPT; - -+ /* send EAPOL frames as voice */ -+ if (control->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) -+ tx_attr |= TX_HW_ATTR_EAPOL_FRAME; -+ - desc->tx_attr = cpu_to_le16(tx_attr); - - wlcore_hw_set_tx_desc_csum(wl, desc, skb); ---- a/drivers/net/wireless/ti/wlcore/tx.h -+++ b/drivers/net/wireless/ti/wlcore/tx.h -@@ -37,6 +37,7 @@ - #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) - #define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) - #define TX_HW_ATTR_HOST_ENCRYPT BIT(14) -+#define TX_HW_ATTR_EAPOL_FRAME BIT(15) - - #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 - #define TX_HW_ATTR_OFST_HEADER_PAD 1 diff --git a/package/kernel/mac80211/patches/911-wlcore-don-t-stop-sched_scan-on-interface-removal.patch b/package/kernel/mac80211/patches/911-wlcore-don-t-stop-sched_scan-on-interface-removal.patch deleted file mode 100644 index 91269d22fc..0000000000 --- a/package/kernel/mac80211/patches/911-wlcore-don-t-stop-sched_scan-on-interface-removal.patch +++ /dev/null @@ -1,25 +0,0 @@ -Stopping sched scan on interface removal (during recovery) -is no longer needed, as sched scanning is automatically -restarted by mac80211. - -Signed-off-by: Barak Bercovitz -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/main.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -2582,10 +2582,8 @@ static void __wl1271_op_remove_interface - ieee80211_scan_completed(wl->hw, true); - } - -- if (wl->sched_vif == wlvif) { -- ieee80211_sched_scan_stopped(wl->hw); -+ if (wl->sched_vif == wlvif) - wl->sched_vif = NULL; -- } - - if (wl->roc_vif == vif) { - wl->roc_vif = NULL; diff --git a/package/kernel/mac80211/patches/912-wlcore-wl18xx-allow-CCK-rates-for-AP-mode.patch b/package/kernel/mac80211/patches/912-wlcore-wl18xx-allow-CCK-rates-for-AP-mode.patch deleted file mode 100644 index c957b9c04e..0000000000 --- a/package/kernel/mac80211/patches/912-wlcore-wl18xx-allow-CCK-rates-for-AP-mode.patch +++ /dev/null @@ -1,47 +0,0 @@ -12xx chips allow only OFDM rates in AP mode for BT-Coex purposes. This -is no longer required in 18xx chips, starting with FW 8.6.0.0.8. - -Update the min allowed FW version in 18xx to support this functionality. - -Signed-off-by: Arik Nemtsov -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wl12xx/main.c | 1 + - drivers/net/wireless/ti/wlcore/init.c | 2 +- - drivers/net/wireless/ti/wlcore/wlcore.h | 3 +++ - 3 files changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/ti/wl12xx/main.c -+++ b/drivers/net/wireless/ti/wl12xx/main.c -@@ -1789,6 +1789,7 @@ static int wl12xx_setup(struct wl1271 *w - wl->fw_status_len = sizeof(struct wl12xx_fw_status); - wl->fw_status_priv_len = 0; - wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); -+ wl->ofdm_only_ap = true; - wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap); - wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap); - wl12xx_conf_init(wl); ---- a/drivers/net/wireless/ti/wlcore/init.c -+++ b/drivers/net/wireless/ti/wlcore/init.c -@@ -462,7 +462,7 @@ int wl1271_init_ap_rates(struct wl1271 * - * If the basic rates contain OFDM rates, use OFDM only - * rates for unicast TX as well. Else use all supported rates. - */ -- if ((wlvif->basic_rate_set & CONF_TX_OFDM_RATES)) -+ if (wl->ofdm_only_ap && (wlvif->basic_rate_set & CONF_TX_OFDM_RATES)) - supported_rates = CONF_TX_OFDM_RATES; - else - supported_rates = CONF_TX_ENABLED_RATES; ---- a/drivers/net/wireless/ti/wlcore/wlcore.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore.h -@@ -409,6 +409,9 @@ struct wl1271 { - /* AP-mode - number of currently connected stations */ - int active_sta_count; - -+ /* Flag determining whether AP should broadcast OFDM-only rates */ -+ bool ofdm_only_ap; -+ - /* last wlvif we transmitted from */ - struct wl12xx_vif *last_wlvif; - diff --git a/package/kernel/mac80211/patches/913-wlcore-don-t-handle-unsetting-of-default-wep-key.patch b/package/kernel/mac80211/patches/913-wlcore-don-t-handle-unsetting-of-default-wep-key.patch deleted file mode 100644 index 69621c59fe..0000000000 --- a/package/kernel/mac80211/patches/913-wlcore-don-t-handle-unsetting-of-default-wep-key.patch +++ /dev/null @@ -1,28 +0,0 @@ -mac80211 unsets the default wep key on disassoc. -The fw doesn't support this notification, so simply -ignore it. - -The actual flow actually triggers fw recovery in some -cases, as mac80211 unsets the default key only after -disassoc, when wlvif->sta.hlid, resulting in invalid -hlid being passed to the fw. - -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/main.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -3505,6 +3505,10 @@ static void wl1271_op_set_default_key_id - wl1271_debug(DEBUG_MAC80211, "mac80211 set default key idx %d", - key_idx); - -+ /* we don't handle unsetting of default key */ -+ if (key_idx == -1) -+ return; -+ - mutex_lock(&wl->mutex); - - if (unlikely(wl->state != WLCORE_STATE_ON)) { diff --git a/package/kernel/mac80211/patches/914-wlcore-consider-multiple-APs-when-checking-active_link_count.patch b/package/kernel/mac80211/patches/914-wlcore-consider-multiple-APs-when-checking-active_link_count.patch deleted file mode 100644 index 9e9eba7417..0000000000 --- a/package/kernel/mac80211/patches/914-wlcore-consider-multiple-APs-when-checking-active_link_count.patch +++ /dev/null @@ -1,51 +0,0 @@ -Each AP has its own global and broadcast links, so when -checking for active sta count (according to the active_link_count) -we must take them all into account. - -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/main.c | 10 +++++----- - drivers/net/wireless/ti/wlcore/tx.c | 10 +++++----- - 2 files changed, 10 insertions(+), 10 deletions(-) - ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -345,12 +345,12 @@ static void wl12xx_irq_ps_regulate_link( - * Start high-level PS if the STA is asleep with enough blocks in FW. - * Make an exception if this is the only connected link. In this - * case FW-memory congestion is less of a problem. -- * Note that a single connected STA means 3 active links, since we must -- * account for the global and broadcast AP links. The "fw_ps" check -- * assures us the third link is a STA connected to the AP. Otherwise -- * the FW would not set the PSM bit. -+ * Note that a single connected STA means 2*ap_count + 1 active links, -+ * since we must account for the global and broadcast AP links -+ * for each AP. The "fw_ps" check assures us the other link is a STA -+ * connected to the AP. Otherwise the FW would not set the PSM bit. - */ -- else if (wl->active_link_count > 3 && fw_ps && -+ else if (wl->active_link_count > (wl->ap_count*2 + 1) && fw_ps && - tx_pkts >= WL1271_PS_STA_MAX_PACKETS) - wl12xx_ps_link_start(wl, wlvif, hlid, true); - } ---- a/drivers/net/wireless/ti/wlcore/tx.c -+++ b/drivers/net/wireless/ti/wlcore/tx.c -@@ -134,12 +134,12 @@ static void wl1271_tx_regulate_link(stru - * into high-level PS and clean out its TX queues. - * Make an exception if this is the only connected link. In this - * case FW-memory congestion is less of a problem. -- * Note that a single connected STA means 3 active links, since we must -- * account for the global and broadcast AP links. The "fw_ps" check -- * assures us the third link is a STA connected to the AP. Otherwise -- * the FW would not set the PSM bit. -+ * Note that a single connected STA means 2*ap_count + 1 active links, -+ * since we must account for the global and broadcast AP links -+ * for each AP. The "fw_ps" check assures us the other link is a STA -+ * connected to the AP. Otherwise the FW would not set the PSM bit. - */ -- if (wl->active_link_count > 3 && fw_ps && -+ if (wl->active_link_count > (wl->ap_count*2 + 1) && fw_ps && - tx_pkts >= WL1271_PS_STA_MAX_PACKETS) - wl12xx_ps_link_start(wl, wlvif, hlid, true); - } diff --git a/package/kernel/mac80211/patches/915-wlcore-decrease-warning-verbosity-during-recovery.patch b/package/kernel/mac80211/patches/915-wlcore-decrease-warning-verbosity-during-recovery.patch deleted file mode 100644 index be2de10ccf..0000000000 --- a/package/kernel/mac80211/patches/915-wlcore-decrease-warning-verbosity-during-recovery.patch +++ /dev/null @@ -1,42 +0,0 @@ -Silently ignore repetitive scheduling of recovery work and commands -being passed to the bus when the HW is not available. This can happen -many times during recovery and slow it down. It also spams the kernel -logs. - -Signed-off-by: Arik Nemtsov -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/cmd.c | 4 ++-- - drivers/net/wireless/ti/wlcore/main.c | 5 +++-- - 2 files changed, 5 insertions(+), 4 deletions(-) - ---- a/drivers/net/wireless/ti/wlcore/cmd.c -+++ b/drivers/net/wireless/ti/wlcore/cmd.c -@@ -60,8 +60,8 @@ static int __wlcore_cmd_send(struct wl12 - u16 status; - u16 poll_count = 0; - -- if (WARN_ON(wl->state == WLCORE_STATE_RESTARTING && -- id != CMD_STOP_FWLOGGER)) -+ if (unlikely(wl->state == WLCORE_STATE_RESTARTING && -+ id != CMD_STOP_FWLOGGER)) - return -EIO; - - cmd = buf; ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -782,10 +782,11 @@ out: - - void wl12xx_queue_recovery_work(struct wl1271 *wl) - { -- WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); -- - /* Avoid a recursive recovery */ - if (wl->state == WLCORE_STATE_ON) { -+ WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, -+ &wl->flags)); -+ - wl->state = WLCORE_STATE_RESTARTING; - set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); - wl1271_ps_elp_wakeup(wl); diff --git a/package/kernel/mac80211/patches/916-wlcore-increase-timeout-to-5000-msecs.patch b/package/kernel/mac80211/patches/916-wlcore-increase-timeout-to-5000-msecs.patch deleted file mode 100644 index eb490e43c8..0000000000 --- a/package/kernel/mac80211/patches/916-wlcore-increase-timeout-to-5000-msecs.patch +++ /dev/null @@ -1,21 +0,0 @@ -dfs configuration command might take longer than -the current timeout. increase it to 5 seconds. - -Signed-off-by: Yaniv Machani -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/cmd.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/wireless/ti/wlcore/cmd.h -+++ b/drivers/net/wireless/ti/wlcore/cmd.h -@@ -207,7 +207,7 @@ enum cmd_templ { - #define WL1271_COMMAND_TIMEOUT 2000 - #define WL1271_CMD_TEMPL_DFLT_SIZE 252 - #define WL1271_CMD_TEMPL_MAX_SIZE 512 --#define WL1271_EVENT_TIMEOUT 1500 -+#define WL1271_EVENT_TIMEOUT 5000 - - struct wl1271_cmd_header { - __le16 id; diff --git a/package/kernel/mac80211/patches/917-wlcore-enable-beacon-filtering-only-after-receiving-a-beacon.patch b/package/kernel/mac80211/patches/917-wlcore-enable-beacon-filtering-only-after-receiving-a-beacon.patch deleted file mode 100644 index 5dbad9494e..0000000000 --- a/package/kernel/mac80211/patches/917-wlcore-enable-beacon-filtering-only-after-receiving-a-beacon.patch +++ /dev/null @@ -1,71 +0,0 @@ -Enabling beacon filtering before receving a beacon -might result in not having a beacon at all for the -current connected AP, which prevents the station -from entering power-save. - -Replace the current approach (of starting beacon -filtering on init) and configure beacon filering -only after bss_conf->dtimper is set (which means -mac80211 already parsed a beacon). - -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/acx.c | 3 ++- - drivers/net/wireless/ti/wlcore/init.c | 4 ++-- - drivers/net/wireless/ti/wlcore/main.c | 12 ++++++++++++ - 3 files changed, 16 insertions(+), 3 deletions(-) - ---- a/drivers/net/wireless/ti/wlcore/acx.c -+++ b/drivers/net/wireless/ti/wlcore/acx.c -@@ -358,7 +358,8 @@ int wl1271_acx_beacon_filter_opt(struct - struct acx_beacon_filter_option *beacon_filter = NULL; - int ret = 0; - -- wl1271_debug(DEBUG_ACX, "acx beacon filter opt"); -+ wl1271_debug(DEBUG_ACX, "acx beacon filter opt enable=%d", -+ enable_filter); - - if (enable_filter && - wl->conf.conn.bcn_filt_mode == CONF_BCN_FILT_MODE_DISABLED) ---- a/drivers/net/wireless/ti/wlcore/init.c -+++ b/drivers/net/wireless/ti/wlcore/init.c -@@ -287,8 +287,8 @@ static int wl1271_init_sta_beacon_filter - if (ret < 0) - return ret; - -- /* enable beacon filtering */ -- ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); -+ /* disable beacon filtering until we get the first beacon */ -+ ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); - if (ret < 0) - return ret; - ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -2941,6 +2941,11 @@ static int wlcore_unset_assoc(struct wl1 - ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); - if (ret < 0) - return ret; -+ -+ /* disable beacon filtering */ -+ ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); -+ if (ret < 0) -+ return ret; - } - - if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) { -@@ -4345,6 +4350,13 @@ static void wl1271_bss_info_changed_sta( - } - } - -+ if ((changed & BSS_CHANGED_BEACON_INFO) && bss_conf->dtim_period) { -+ /* enable beacon filtering */ -+ ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); -+ if (ret < 0) -+ goto out; -+ } -+ - ret = wl1271_bss_erp_info_changed(wl, vif, bss_conf, changed); - if (ret < 0) - goto out; diff --git a/package/kernel/mac80211/patches/918-wlcore-add-support-for-STA-CSA-with-chan-contexts.patch b/package/kernel/mac80211/patches/918-wlcore-add-support-for-STA-CSA-with-chan-contexts.patch deleted file mode 100644 index c33535d049..0000000000 --- a/package/kernel/mac80211/patches/918-wlcore-add-support-for-STA-CSA-with-chan-contexts.patch +++ /dev/null @@ -1,22 +0,0 @@ -TI wl12xx/wl18xx cards support channel switch via a driver specific -switch_channel op while operating with channel contexts. - -Signed-off-by: Arik Nemtsov -Signed-off-by: Eliad Peller - ---- -drivers/net/wireless/ti/wlcore/main.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -5770,7 +5770,8 @@ static int wl1271_init_ieee80211(struct - IEEE80211_HW_AP_LINK_PS | - IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | -- IEEE80211_HW_QUEUE_CONTROL; -+ IEEE80211_HW_QUEUE_CONTROL | -+ IEEE80211_HW_CHANCTX_STA_CSA; - - wl->hw->wiphy->cipher_suites = cipher_suites; - wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);