From: Ansuel Smith Date: Tue, 1 Jun 2021 23:49:50 +0000 (+0200) Subject: mac80211: split ath patch in dedicated subdir X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=3394af677cadd1f9b877100312c830d87488fcfb;p=openwrt%2Fstaging%2Fadrian.git mac80211: split ath patch in dedicated subdir The ath patch number is already large and adding other patch for ath11k will add more confusion with the patch numbering. Since the support of ath11k based device is imminent, prepare the mac80211 ath patch dir and split it in the dedicated ath5k, ath9k, ath10k and ath11k (empty for now). Signed-off-by: Ansuel Smith --- diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 4d10de09a7..92167ebf3b 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -501,6 +501,10 @@ define Build/Patch $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/build,build/) $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/subsys,subsys/) $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath,ath/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath5k,ath5k/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath9k,ath9k/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath10k,ath10k/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath11k,ath11k/) $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rt2x00,rt2x00/) $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/) $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/) @@ -512,6 +516,10 @@ define Quilt/Refresh/Package $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/build,build/) $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/subsys,subsys/) $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath,ath/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath5k,ath5k/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath9k,ath9k/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath10k,ath10k/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath11k,ath11k/) $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rt2x00,rt2x00/) $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/) $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/) diff --git a/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch b/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch deleted file mode 100644 index 55d48daa79..0000000000 --- a/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/drivers/net/wireless/ath/ath10k/Kconfig -+++ b/drivers/net/wireless/ath/ath10k/Kconfig -@@ -86,6 +86,12 @@ config ATH10K_TRACING - help - Select this to ath10k use tracing infrastructure. - -+config ATH10K_THERMAL -+ bool "Atheros ath10k thermal monitoring support" -+ depends on THERMAL -+ ---help--- -+ Select this to ath10k use hwmon for thermal measurement. -+ - config ATH10K_DFS_CERTIFIED - bool "Atheros DFS support for certified platforms" - depends on ATH10K && CFG80211_CERTIFICATION_ONUS ---- a/drivers/net/wireless/ath/ath10k/Makefile -+++ b/drivers/net/wireless/ath/ath10k/Makefile -@@ -18,7 +18,7 @@ ath10k_core-y += mac.o \ - ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += spectral.o - ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o - ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o --ath10k_core-$(CONFIG_THERMAL) += thermal.o -+ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o - ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o - ath10k_core-$(CONFIG_PM) += wow.o - ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o ---- a/drivers/net/wireless/ath/ath10k/thermal.h -+++ b/drivers/net/wireless/ath/ath10k/thermal.h -@@ -25,7 +25,7 @@ struct ath10k_thermal { - int temperature; - }; - --#if IS_REACHABLE(CONFIG_THERMAL) -+#if IS_REACHABLE(CPTCFG_ATH10K_THERMAL) - int ath10k_thermal_register(struct ath10k *ar); - void ath10k_thermal_unregister(struct ath10k *ar); - void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature); ---- a/local-symbols -+++ b/local-symbols -@@ -143,6 +143,7 @@ ATH10K_SNOC= - ATH10K_DEBUG= - ATH10K_DEBUGFS= - ATH10K_SPECTRAL= -+ATH10K_THERMAL= - ATH10K_TRACING= - ATH10K_DFS_CERTIFIED= - WCN36XX= diff --git a/package/kernel/mac80211/patches/ath/201-ath5k-WAR-for-AR71xx-PCI-bug.patch b/package/kernel/mac80211/patches/ath/201-ath5k-WAR-for-AR71xx-PCI-bug.patch deleted file mode 100644 index 21516ffde9..0000000000 --- a/package/kernel/mac80211/patches/ath/201-ath5k-WAR-for-AR71xx-PCI-bug.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/drivers/net/wireless/ath/ath5k/initvals.c -+++ b/drivers/net/wireless/ath/ath5k/initvals.c -@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini - { AR5K_IMR, 0 }, - { AR5K_IER, AR5K_IER_DISABLE }, - { AR5K_BSR, 0, AR5K_INI_READ }, -+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) - { AR5K_TXCFG, AR5K_DMASIZE_128B }, - { AR5K_RXCFG, AR5K_DMASIZE_128B }, -+#else -+ /* WAR for AR71xx PCI bug */ -+ { AR5K_TXCFG, AR5K_DMASIZE_128B }, -+ { AR5K_RXCFG, AR5K_DMASIZE_4B }, -+#endif - { AR5K_CFG, AR5K_INIT_CFG }, - { AR5K_TOPS, 8 }, - { AR5K_RXNOFRM, 8 }, ---- a/drivers/net/wireless/ath/ath5k/dma.c -+++ b/drivers/net/wireless/ath/ath5k/dma.c -@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah) - * guess we can tweak it and see how it goes ;-) - */ - if (ah->ah_version != AR5K_AR5210) { -+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) - AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); - AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, - AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); -+#else -+ /* WAR for AR71xx PCI bug */ -+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, -+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); -+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, -+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B); -+#endif - } - - /* Pre-enable interrupts on 5211/5212*/ diff --git a/package/kernel/mac80211/patches/ath/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch b/package/kernel/mac80211/patches/ath/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch deleted file mode 100644 index 0ce49b22ab..0000000000 --- a/package/kernel/mac80211/patches/ath/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch +++ /dev/null @@ -1,180 +0,0 @@ -From: Wen Gong -Date: Tue, 11 May 2021 20:02:52 +0200 -Subject: [PATCH] ath10k: add CCMP PN replay protection for fragmented - frames for PCIe - -PN replay check for not fragmented frames is finished in the firmware, -but this was not done for fragmented frames when ath10k is used with -QCA6174/QCA6377 PCIe. mac80211 has the function -ieee80211_rx_h_defragment() for PN replay check for fragmented frames, -but this does not get checked with QCA6174 due to the -ieee80211_has_protected() condition not matching the cleared Protected -bit case. - -Validate the PN of received fragmented frames within ath10k when CCMP is -used and drop the fragment if the PN is not correct (incremented by -exactly one from the previous fragment). This applies only for -QCA6174/QCA6377 PCIe. - -Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 - -Cc: stable@vger.kernel.org -Signed-off-by: Wen Gong -Signed-off-by: Jouni Malinen -Signed-off-by: Johannes Berg ---- - ---- a/drivers/net/wireless/ath/ath10k/htt.h -+++ b/drivers/net/wireless/ath/ath10k/htt.h -@@ -846,6 +846,7 @@ enum htt_security_types { - - #define ATH10K_HTT_TXRX_PEER_SECURITY_MAX 2 - #define ATH10K_TXRX_NUM_EXT_TIDS 19 -+#define ATH10K_TXRX_NON_QOS_TID 16 - - enum htt_security_flags { - #define HTT_SECURITY_TYPE_MASK 0x7F ---- a/drivers/net/wireless/ath/ath10k/htt_rx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -@@ -1746,16 +1746,87 @@ static void ath10k_htt_rx_h_csum_offload - msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu); - } - -+static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb, -+ u16 offset, -+ enum htt_rx_mpdu_encrypt_type enctype) -+{ -+ struct ieee80211_hdr *hdr; -+ u64 pn = 0; -+ u8 *ehdr; -+ -+ hdr = (struct ieee80211_hdr *)(skb->data + offset); -+ ehdr = skb->data + offset + ieee80211_hdrlen(hdr->frame_control); -+ -+ if (enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) { -+ pn = ehdr[0]; -+ pn |= (u64)ehdr[1] << 8; -+ pn |= (u64)ehdr[4] << 16; -+ pn |= (u64)ehdr[5] << 24; -+ pn |= (u64)ehdr[6] << 32; -+ pn |= (u64)ehdr[7] << 40; -+ } -+ return pn; -+} -+ -+static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar, -+ struct sk_buff *skb, -+ u16 peer_id, -+ u16 offset, -+ enum htt_rx_mpdu_encrypt_type enctype) -+{ -+ struct ath10k_peer *peer; -+ union htt_rx_pn_t *last_pn, new_pn = {0}; -+ struct ieee80211_hdr *hdr; -+ bool more_frags; -+ u8 tid, frag_number; -+ u32 seq; -+ -+ peer = ath10k_peer_find_by_id(ar, peer_id); -+ if (!peer) { -+ ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid peer for frag pn check\n"); -+ return false; -+ } -+ -+ hdr = (struct ieee80211_hdr *)(skb->data + offset); -+ if (ieee80211_is_data_qos(hdr->frame_control)) -+ tid = ieee80211_get_tid(hdr); -+ else -+ tid = ATH10K_TXRX_NON_QOS_TID; -+ -+ last_pn = &peer->frag_tids_last_pn[tid]; -+ new_pn.pn48 = ath10k_htt_rx_h_get_pn(ar, skb, offset, enctype); -+ more_frags = ieee80211_has_morefrags(hdr->frame_control); -+ frag_number = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; -+ seq = (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; -+ -+ if (frag_number == 0) { -+ last_pn->pn48 = new_pn.pn48; -+ peer->frag_tids_seq[tid] = seq; -+ } else { -+ if (seq != peer->frag_tids_seq[tid]) -+ return false; -+ -+ if (new_pn.pn48 != last_pn->pn48 + 1) -+ return false; -+ -+ last_pn->pn48 = new_pn.pn48; -+ } -+ -+ return true; -+} -+ - static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, - struct sk_buff_head *amsdu, - struct ieee80211_rx_status *status, - bool fill_crypt_header, - u8 *rx_hdr, -- enum ath10k_pkt_rx_err *err) -+ enum ath10k_pkt_rx_err *err, -+ u16 peer_id, -+ bool frag) - { - struct sk_buff *first; - struct sk_buff *last; -- struct sk_buff *msdu; -+ struct sk_buff *msdu, *temp; - struct htt_rx_desc *rxd; - struct ieee80211_hdr *hdr; - enum htt_rx_mpdu_encrypt_type enctype; -@@ -1768,6 +1839,7 @@ static void ath10k_htt_rx_h_mpdu(struct - bool is_decrypted; - bool is_mgmt; - u32 attention; -+ bool frag_pn_check = true; - - if (skb_queue_empty(amsdu)) - return; -@@ -1866,6 +1938,24 @@ static void ath10k_htt_rx_h_mpdu(struct - } - - skb_queue_walk(amsdu, msdu) { -+ if (frag && !fill_crypt_header && is_decrypted && -+ enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) -+ frag_pn_check = ath10k_htt_rx_h_frag_pn_check(ar, -+ msdu, -+ peer_id, -+ 0, -+ enctype); -+ -+ if (!frag_pn_check) { -+ /* Discard the fragment with invalid PN */ -+ temp = msdu->prev; -+ __skb_unlink(msdu, amsdu); -+ dev_kfree_skb_any(msdu); -+ msdu = temp; -+ frag_pn_check = true; -+ continue; -+ } -+ - ath10k_htt_rx_h_csum_offload(msdu); - ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype, - is_decrypted); -@@ -2071,7 +2161,8 @@ static int ath10k_htt_rx_handle_amsdu(st - ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt); - - ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter); -- ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err); -+ ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err, 0, -+ false); - msdus_to_queue = skb_queue_len(&amsdu); - ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status); - -@@ -3027,7 +3118,7 @@ static int ath10k_htt_rx_in_ord_ind(stru - ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); - ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL); - ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL, -- NULL); -+ NULL, peer_id, frag); - ath10k_htt_rx_h_enqueue(ar, &amsdu, status); - break; - case -EAGAIN: diff --git a/package/kernel/mac80211/patches/ath/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch b/package/kernel/mac80211/patches/ath/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch deleted file mode 100644 index 7288c66612..0000000000 --- a/package/kernel/mac80211/patches/ath/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch +++ /dev/null @@ -1,66 +0,0 @@ -From: Wen Gong -Date: Tue, 11 May 2021 20:02:53 +0200 -Subject: [PATCH] ath10k: drop fragments with multicast DA for PCIe - -Fragmentation is not used with multicast frames. Discard unexpected -fragments with multicast DA. This fixes CVE-2020-26145. - -Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 - -Cc: stable@vger.kernel.org -Signed-off-by: Wen Gong -Signed-off-by: Jouni Malinen -Signed-off-by: Johannes Berg ---- - ---- a/drivers/net/wireless/ath/ath10k/htt_rx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -@@ -1768,6 +1768,16 @@ static u64 ath10k_htt_rx_h_get_pn(struct - return pn; - } - -+static bool ath10k_htt_rx_h_frag_multicast_check(struct ath10k *ar, -+ struct sk_buff *skb, -+ u16 offset) -+{ -+ struct ieee80211_hdr *hdr; -+ -+ hdr = (struct ieee80211_hdr *)(skb->data + offset); -+ return !is_multicast_ether_addr(hdr->addr1); -+} -+ - static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar, - struct sk_buff *skb, - u16 peer_id, -@@ -1839,7 +1849,7 @@ static void ath10k_htt_rx_h_mpdu(struct - bool is_decrypted; - bool is_mgmt; - u32 attention; -- bool frag_pn_check = true; -+ bool frag_pn_check = true, multicast_check = true; - - if (skb_queue_empty(amsdu)) - return; -@@ -1946,13 +1956,20 @@ static void ath10k_htt_rx_h_mpdu(struct - 0, - enctype); - -- if (!frag_pn_check) { -- /* Discard the fragment with invalid PN */ -+ if (frag) -+ multicast_check = ath10k_htt_rx_h_frag_multicast_check(ar, -+ msdu, -+ 0); -+ -+ if (!frag_pn_check || !multicast_check) { -+ /* Discard the fragment with invalid PN or multicast DA -+ */ - temp = msdu->prev; - __skb_unlink(msdu, amsdu); - dev_kfree_skb_any(msdu); - msdu = temp; - frag_pn_check = true; -+ multicast_check = true; - continue; - } - diff --git a/package/kernel/mac80211/patches/ath/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch b/package/kernel/mac80211/patches/ath/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch deleted file mode 100644 index 85d9ce65e2..0000000000 --- a/package/kernel/mac80211/patches/ath/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: Wen Gong -Date: Tue, 11 May 2021 20:02:54 +0200 -Subject: [PATCH] ath10k: drop fragments with multicast DA for SDIO - -Fragmentation is not used with multicast frames. Discard unexpected -fragments with multicast DA. This fixes CVE-2020-26145. - -Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049 - -Cc: stable@vger.kernel.org -Signed-off-by: Wen Gong -Signed-off-by: Jouni Malinen -Signed-off-by: Johannes Berg ---- - ---- a/drivers/net/wireless/ath/ath10k/htt_rx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -@@ -2617,6 +2617,13 @@ static bool ath10k_htt_rx_proc_rx_frag_i - rx_desc = (struct htt_hl_rx_desc *)(skb->data + tot_hdr_len); - rx_desc_info = __le32_to_cpu(rx_desc->info); - -+ hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len); -+ -+ if (is_multicast_ether_addr(hdr->addr1)) { -+ /* Discard the fragment with multicast DA */ -+ goto err; -+ } -+ - if (!MS(rx_desc_info, HTT_RX_DESC_HL_INFO_ENCRYPTED)) { - spin_unlock_bh(&ar->data_lock); - return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb, -@@ -2624,8 +2631,6 @@ static bool ath10k_htt_rx_proc_rx_frag_i - HTT_RX_NON_TKIP_MIC); - } - -- hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len); -- - if (ieee80211_has_retry(hdr->frame_control)) - goto err; - diff --git a/package/kernel/mac80211/patches/ath/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch b/package/kernel/mac80211/patches/ath/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch deleted file mode 100644 index 03bce4231b..0000000000 --- a/package/kernel/mac80211/patches/ath/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Wen Gong -Date: Tue, 11 May 2021 20:02:55 +0200 -Subject: [PATCH] ath10k: drop MPDU which has discard flag set by firmware - for SDIO - -When the discard flag is set by the firmware for an MPDU, it should be -dropped. This allows a mitigation for CVE-2020-24588 to be implemented -in the firmware. - -Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049 - -Cc: stable@vger.kernel.org -Signed-off-by: Wen Gong -Signed-off-by: Jouni Malinen -Signed-off-by: Johannes Berg ---- - ---- a/drivers/net/wireless/ath/ath10k/htt_rx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -@@ -2312,6 +2312,11 @@ static bool ath10k_htt_rx_proc_rx_ind_hl - fw_desc = &rx->fw_desc; - rx_desc_len = fw_desc->len; - -+ if (fw_desc->u.bits.discard) { -+ ath10k_dbg(ar, ATH10K_DBG_HTT, "htt discard mpdu\n"); -+ goto err; -+ } -+ - /* I have not yet seen any case where num_mpdu_ranges > 1. - * qcacld does not seem handle that case either, so we introduce the - * same limitiation here as well. ---- a/drivers/net/wireless/ath/ath10k/rx_desc.h -+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h -@@ -1282,7 +1282,19 @@ struct fw_rx_desc_base { - #define FW_RX_DESC_UDP (1 << 6) - - struct fw_rx_desc_hl { -- u8 info0; -+ union { -+ struct { -+ u8 discard:1, -+ forward:1, -+ any_err:1, -+ dup_err:1, -+ reserved:1, -+ inspect:1, -+ extension:2; -+ } bits; -+ u8 info0; -+ } u; -+ - u8 version; - u8 len; - u8 flags; diff --git a/package/kernel/mac80211/patches/ath/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch b/package/kernel/mac80211/patches/ath/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch deleted file mode 100644 index da9d6802bd..0000000000 --- a/package/kernel/mac80211/patches/ath/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch +++ /dev/null @@ -1,48 +0,0 @@ -From: Wen Gong -Date: Tue, 11 May 2021 20:02:56 +0200 -Subject: [PATCH] ath10k: Fix TKIP Michael MIC verification for PCIe - -TKIP Michael MIC was not verified properly for PCIe cases since the -validation steps in ieee80211_rx_h_michael_mic_verify() in mac80211 did -not get fully executed due to unexpected flag values in -ieee80211_rx_status. - -Fix this by setting the flags property to meet mac80211 expectations for -performing Michael MIC validation there. This fixes CVE-2020-26141. It -does the same as ath10k_htt_rx_proc_rx_ind_hl() for SDIO which passed -MIC verification case. This applies only to QCA6174/QCA9377 PCIe. - -Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 - -Cc: stable@vger.kernel.org -Signed-off-by: Wen Gong -Signed-off-by: Jouni Malinen -Signed-off-by: Johannes Berg ---- - ---- a/drivers/net/wireless/ath/ath10k/htt_rx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -@@ -1974,6 +1974,11 @@ static void ath10k_htt_rx_h_mpdu(struct - } - - ath10k_htt_rx_h_csum_offload(msdu); -+ -+ if (frag && !fill_crypt_header && -+ enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) -+ status->flag &= ~RX_FLAG_MMIC_STRIPPED; -+ - ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype, - is_decrypted); - -@@ -1991,6 +1996,11 @@ static void ath10k_htt_rx_h_mpdu(struct - - hdr = (void *)msdu->data; - hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); -+ -+ if (frag && !fill_crypt_header && -+ enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) -+ status->flag &= ~RX_FLAG_IV_STRIPPED & -+ ~RX_FLAG_MMIC_STRIPPED; - } - } - diff --git a/package/kernel/mac80211/patches/ath/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch b/package/kernel/mac80211/patches/ath/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch deleted file mode 100644 index 0bdbed78d5..0000000000 --- a/package/kernel/mac80211/patches/ath/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch +++ /dev/null @@ -1,109 +0,0 @@ -From: Sriram R -Date: Tue, 11 May 2021 20:02:57 +0200 -Subject: [PATCH] ath10k: Validate first subframe of A-MSDU before - processing the list - -In certain scenarios a normal MSDU can be received as an A-MSDU when -the A-MSDU present bit of a QoS header gets flipped during reception. -Since this bit is unauthenticated, the hardware crypto engine can pass -the frame to the driver without any error indication. - -This could result in processing unintended subframes collected in the -A-MSDU list. Hence, validate A-MSDU list by checking if the first frame -has a valid subframe header. - -Comparing the non-aggregated MSDU and an A-MSDU, the fields of the first -subframe DA matches the LLC/SNAP header fields of a normal MSDU. -In order to avoid processing such frames, add a validation to -filter such A-MSDU frames where the first subframe header DA matches -with the LLC/SNAP header pattern. - -Tested-on: QCA9984 hw1.0 PCI 10.4-3.10-00047 - -Cc: stable@vger.kernel.org -Signed-off-by: Sriram R -Signed-off-by: Jouni Malinen -Signed-off-by: Johannes Berg ---- - ---- a/drivers/net/wireless/ath/ath10k/htt_rx.c -+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -@@ -2108,14 +2108,62 @@ static void ath10k_htt_rx_h_unchain(stru - ath10k_unchain_msdu(amsdu, unchain_cnt); - } - -+static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar, -+ struct sk_buff_head *amsdu) -+{ -+ u8 *subframe_hdr; -+ struct sk_buff *first; -+ bool is_first, is_last; -+ struct htt_rx_desc *rxd; -+ struct ieee80211_hdr *hdr; -+ size_t hdr_len, crypto_len; -+ enum htt_rx_mpdu_encrypt_type enctype; -+ int bytes_aligned = ar->hw_params.decap_align_bytes; -+ -+ first = skb_peek(amsdu); -+ -+ rxd = (void *)first->data - sizeof(*rxd); -+ hdr = (void *)rxd->rx_hdr_status; -+ -+ is_first = !!(rxd->msdu_end.common.info0 & -+ __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)); -+ is_last = !!(rxd->msdu_end.common.info0 & -+ __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)); -+ -+ /* Return in case of non-aggregated msdu */ -+ if (is_first && is_last) -+ return true; -+ -+ /* First msdu flag is not set for the first msdu of the list */ -+ if (!is_first) -+ return false; -+ -+ enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), -+ RX_MPDU_START_INFO0_ENCRYPT_TYPE); -+ -+ hdr_len = ieee80211_hdrlen(hdr->frame_control); -+ crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype); -+ -+ subframe_hdr = (u8 *)hdr + round_up(hdr_len, bytes_aligned) + -+ crypto_len; -+ -+ /* Validate if the amsdu has a proper first subframe. -+ * There are chances a single msdu can be received as amsdu when -+ * the unauthenticated amsdu flag of a QoS header -+ * gets flipped in non-SPP AMSDU's, in such cases the first -+ * subframe has llc/snap header in place of a valid da. -+ * return false if the da matches rfc1042 pattern -+ */ -+ if (ether_addr_equal(subframe_hdr, rfc1042_header)) -+ return false; -+ -+ return true; -+} -+ - static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, - struct sk_buff_head *amsdu, - struct ieee80211_rx_status *rx_status) - { -- /* FIXME: It might be a good idea to do some fuzzy-testing to drop -- * invalid/dangerous frames. -- */ -- - if (!rx_status->freq) { - ath10k_dbg(ar, ATH10K_DBG_HTT, "no channel configured; ignoring frame(s)!\n"); - return false; -@@ -2126,6 +2174,11 @@ static bool ath10k_htt_rx_amsdu_allowed( - return false; - } - -+ if (!ath10k_htt_rx_validate_amsdu(ar, amsdu)) { -+ ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid amsdu received\n"); -+ return false; -+ } -+ - return true; - } - diff --git a/package/kernel/mac80211/patches/ath/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch b/package/kernel/mac80211/patches/ath/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch deleted file mode 100644 index d648a3a3e5..0000000000 --- a/package/kernel/mac80211/patches/ath/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: Felix Fietkau -Date: Sat, 9 Jul 2016 15:25:24 +0200 -Subject: [PATCH] ath9k_hw: reset AHB-WMAC interface on AR91xx - -Should fix a few stability issues - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1435,8 +1435,12 @@ static bool ath9k_hw_set_reset(struct at - if (!AR_SREV_9100(ah)) - REG_WRITE(ah, AR_RC, 0); - -- if (AR_SREV_9100(ah)) -+ if (AR_SREV_9100(ah)) { -+ /* Reset the AHB-WMAC interface */ -+ if (ah->external_reset) -+ ah->external_reset(); - udelay(50); -+ } - - return true; - } diff --git a/package/kernel/mac80211/patches/ath/351-ath9k_hw-issue-external-reset-for-QCA955x.patch b/package/kernel/mac80211/patches/ath/351-ath9k_hw-issue-external-reset-for-QCA955x.patch deleted file mode 100644 index 5f265b84c2..0000000000 --- a/package/kernel/mac80211/patches/ath/351-ath9k_hw-issue-external-reset-for-QCA955x.patch +++ /dev/null @@ -1,129 +0,0 @@ -From: Felix Fietkau -Date: Sat, 9 Jul 2016 15:26:44 +0200 -Subject: [PATCH] ath9k_hw: issue external reset for QCA955x - -The RTC interface on the SoC needs to be reset along with the rest of -the WMAC. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1312,39 +1312,56 @@ void ath9k_hw_get_delta_slope_vals(struc - *coef_exponent = coef_exp - 16; - } - --/* AR9330 WAR: -- * call external reset function to reset WMAC if: -- * - doing a cold reset -- * - we have pending frames in the TX queues. -- */ --static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type) -+static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type) - { -- int i, npend = 0; -+ int i; - -- for (i = 0; i < AR_NUM_QCU; i++) { -- npend = ath9k_hw_numtxpending(ah, i); -- if (npend) -- break; -- } -- -- if (ah->external_reset && -- (npend || type == ATH9K_RESET_COLD)) { -- int reset_err = 0; -- -- ath_dbg(ath9k_hw_common(ah), RESET, -- "reset MAC via external reset\n"); -- -- reset_err = ah->external_reset(); -- if (reset_err) { -- ath_err(ath9k_hw_common(ah), -- "External reset failed, err=%d\n", -- reset_err); -- return false; -+ if (type == ATH9K_RESET_COLD) -+ return true; -+ -+ if (AR_SREV_9550(ah)) -+ return true; -+ -+ /* AR9330 WAR: -+ * call external reset function to reset WMAC if: -+ * - doing a cold reset -+ * - we have pending frames in the TX queues. -+ */ -+ if (AR_SREV_9330(ah)) { -+ for (i = 0; i < AR_NUM_QCU; i++) { -+ if (ath9k_hw_numtxpending(ah, i)) -+ return true; - } -+ } -+ -+ return false; -+} -+ -+static bool ath9k_hw_external_reset(struct ath_hw *ah, int type) -+{ -+ int err; -+ -+ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type)) -+ return true; -+ -+ ath_dbg(ath9k_hw_common(ah), RESET, -+ "reset MAC via external reset\n"); - -- REG_WRITE(ah, AR_RTC_RESET, 1); -+ err = ah->external_reset(); -+ if (err) { -+ ath_err(ath9k_hw_common(ah), -+ "External reset failed, err=%d\n", err); -+ return false; - } - -+ if (AR_SREV_9550(ah)) { -+ REG_WRITE(ah, AR_RTC_RESET, 0); -+ udelay(10); -+ } -+ -+ REG_WRITE(ah, AR_RTC_RESET, 1); -+ udelay(10); -+ - return true; - } - -@@ -1397,24 +1414,24 @@ static bool ath9k_hw_set_reset(struct at - rst_flags |= AR_RTC_RC_MAC_COLD; - } - -- if (AR_SREV_9330(ah)) { -- if (!ath9k_hw_ar9330_reset_war(ah, type)) -- return false; -- } -- - if (ath9k_hw_mci_is_enabled(ah)) - ar9003_mci_check_gpm_offset(ah); - - /* DMA HALT added to resolve ar9300 and ar9580 bus error during -- * RTC_RC reg read -+ * RTC_RC reg read. Also needed for AR9550 external reset - */ -- if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { -+ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) { - REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); - ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, - 20 * AH_WAIT_TIMEOUT); -- REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); - } - -+ if (!AR_SREV_9100(ah)) -+ ath9k_hw_external_reset(ah, type); -+ -+ if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) -+ REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); -+ - REG_WRITE(ah, AR_RTC_RC, rst_flags); - - REGWRITE_BUFFER_FLUSH(ah); diff --git a/package/kernel/mac80211/patches/ath/354-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/ath/354-ath9k-force-rx_clear-when-disabling-rx.patch deleted file mode 100644 index 8aaccf49b4..0000000000 --- a/package/kernel/mac80211/patches/ath/354-ath9k-force-rx_clear-when-disabling-rx.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Felix Fietkau -Date: Sun, 7 Jun 2015 13:53:35 +0200 -Subject: [PATCH] ath9k: force rx_clear when disabling rx - -This makes stopping Rx more reliable and should reduce the frequency of -Rx related DMA stop warnings. Don't use rx_clear in TX99 mode. - -Cc: stable@vger.kernel.org -Signed-off-by: Felix Fietkau -Signed-off-by: Helmut Schaa ---- - ---- a/drivers/net/wireless/ath/ath9k/mac.c -+++ b/drivers/net/wireless/ath/ath9k/mac.c -@@ -678,13 +678,18 @@ void ath9k_hw_startpcureceive(struct ath - - ath9k_ani_reset(ah, is_scanning); - -- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); -+ REG_CLR_BIT(ah, AR_DIAG_SW, -+ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); - } - EXPORT_SYMBOL(ath9k_hw_startpcureceive); - - void ath9k_hw_abortpcurecv(struct ath_hw *ah) - { -- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); -+ u32 reg = AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT; -+ -+ if (!IS_ENABLED(CPTCFG_ATH9K_TX99)) -+ reg |= AR_DIAG_FORCE_RX_CLEAR; -+ REG_SET_BIT(ah, AR_DIAG_SW, reg); - - ath9k_hw_disable_mib_counters(ah); - } diff --git a/package/kernel/mac80211/patches/ath/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch b/package/kernel/mac80211/patches/ath/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch deleted file mode 100644 index 385eea0116..0000000000 --- a/package/kernel/mac80211/patches/ath/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Felix Fietkau -Date: Sat, 14 May 2016 14:51:02 +0200 -Subject: [PATCH] Revert "ath9k: interpret requested txpower in EIRP - domain" - -This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411. ---- - ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -2977,7 +2977,8 @@ void ath9k_hw_apply_txpower(struct ath_h - { - struct ath_regulatory *reg = ath9k_hw_regulatory(ah); - struct ieee80211_channel *channel; -- int chan_pwr, new_pwr; -+ int chan_pwr, new_pwr, max_gain; -+ int ant_gain, ant_reduction = 0; - u16 ctl = NO_CTL; - - if (!chan) -@@ -2989,9 +2990,14 @@ void ath9k_hw_apply_txpower(struct ath_h - channel = chan->chan; - chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER); - new_pwr = min_t(int, chan_pwr, reg->power_limit); -+ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2; -+ -+ ant_gain = get_antenna_gain(ah, chan); -+ if (ant_gain > max_gain) -+ ant_reduction = ant_gain - max_gain; - - ah->eep_ops->set_txpower(ah, chan, ctl, -- get_antenna_gain(ah, chan), new_pwr, test); -+ ant_reduction, new_pwr, test); - } - - void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) diff --git a/package/kernel/mac80211/patches/ath/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch b/package/kernel/mac80211/patches/ath/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch deleted file mode 100644 index 0c3edc1260..0000000000 --- a/package/kernel/mac80211/patches/ath/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Felix Fietkau -Date: Wed, 19 Jul 2017 08:49:31 +0200 -Subject: [PATCH] ath9k: adjust tx power reduction for US regulatory - domain - -FCC regulatory rules allow for up to 6 dBi antenna gain. Account for -this in the EEPROM based tx power reduction code. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -2996,6 +2996,10 @@ void ath9k_hw_apply_txpower(struct ath_h - if (ant_gain > max_gain) - ant_reduction = ant_gain - max_gain; - -+ /* FCC allows maximum antenna gain of 6 dBi */ -+ if (reg->region == NL80211_DFS_FCC) -+ ant_reduction = max_t(int, ant_reduction - 12, 0); -+ - ah->eep_ops->set_txpower(ah, chan, ctl, - ant_reduction, new_pwr, test); - } diff --git a/package/kernel/mac80211/patches/ath/401-ath9k_blink_default.patch b/package/kernel/mac80211/patches/ath/401-ath9k_blink_default.patch deleted file mode 100644 index 3eb57bb1cf..0000000000 --- a/package/kernel/mac80211/patches/ath/401-ath9k_blink_default.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -48,7 +48,7 @@ int ath9k_modparam_nohwcrypt; - module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); - MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); - --int ath9k_led_blink; -+int ath9k_led_blink = 1; - module_param_named(blink, ath9k_led_blink, int, 0444); - MODULE_PARM_DESC(blink, "Enable LED blink on activity"); - diff --git a/package/kernel/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch deleted file mode 100644 index 17dd8f6597..0000000000 --- a/package/kernel/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -830,6 +830,7 @@ static const struct ieee80211_iface_limi - BIT(NL80211_IFTYPE_AP) }, - { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO) }, -+ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, - }; - - #ifdef CPTCFG_WIRELESS_WDS diff --git a/package/kernel/mac80211/patches/ath/411-ath5k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/ath/411-ath5k_allow_adhoc_and_ap.patch deleted file mode 100644 index 9dbe047c9a..0000000000 --- a/package/kernel/mac80211/patches/ath/411-ath5k_allow_adhoc_and_ap.patch +++ /dev/null @@ -1,46 +0,0 @@ ---- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c -+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c -@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw - goto end; - } - -- /* Don't allow other interfaces if one ad-hoc is configured. -- * TODO: Fix the problems with ad-hoc and multiple other interfaces. -- * We would need to operate the HW in ad-hoc mode to allow TSF updates -- * for the IBSS, but this breaks with additional AP or STA interfaces -- * at the moment. */ -- if (ah->num_adhoc_vifs || -- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { -+ /* Don't allow more than one ad-hoc interface */ -+ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) { - ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n"); - ret = -ELNRNG; - goto end; ---- a/drivers/net/wireless/ath/ath5k/base.c -+++ b/drivers/net/wireless/ath/ath5k/base.c -@@ -1964,7 +1964,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) - } - - if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + -- ah->num_mesh_vifs > 1) || -+ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) || - ah->opmode == NL80211_IFTYPE_MESH_POINT) { - u64 tsf = ath5k_hw_get_tsf64(ah); - u32 tsftu = TSF_TO_TU(tsf); -@@ -2050,7 +2050,7 @@ ath5k_beacon_update_timers(struct ath5k_ - - intval = ah->bintval & AR5K_BEACON_PERIOD; - if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs -- + ah->num_mesh_vifs > 1) { -+ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) { - intval /= ATH_BCBUF; /* staggered multi-bss beacons */ - if (intval < 15) - ATH5K_WARN(ah, "intval %u is too low, min 15\n", -@@ -2516,6 +2516,7 @@ static const struct ieee80211_iface_limi - BIT(NL80211_IFTYPE_MESH_POINT) | - #endif - BIT(NL80211_IFTYPE_AP) }, -+ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, - }; - - static const struct ieee80211_iface_combination if_comb = { diff --git a/package/kernel/mac80211/patches/ath/420-ath5k_disable_fast_cc.patch b/package/kernel/mac80211/patches/ath/420-ath5k_disable_fast_cc.patch deleted file mode 100644 index 414f49508f..0000000000 --- a/package/kernel/mac80211/patches/ath/420-ath5k_disable_fast_cc.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/drivers/net/wireless/ath/ath5k/reset.c -+++ b/drivers/net/wireless/ath/ath5k/reset.c -@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum - tsf_lo = 0; - mode = 0; - -+#if 0 - /* - * Sanity check for fast flag - * Fast channel change only available -@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum - */ - if (fast && (ah->ah_radio != AR5K_RF2413) && - (ah->ah_radio != AR5K_RF5413)) -+#endif - fast = false; - - /* Disable sleep clock operation diff --git a/package/kernel/mac80211/patches/ath/430-add_ath5k_platform.patch b/package/kernel/mac80211/patches/ath/430-add_ath5k_platform.patch deleted file mode 100644 index b213e2a819..0000000000 --- a/package/kernel/mac80211/patches/ath/430-add_ath5k_platform.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- /dev/null -+++ b/include/linux/ath5k_platform.h -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (c) 2008 Atheros Communications Inc. -+ * Copyright (c) 2009 Gabor Juhos -+ * Copyright (c) 2009 Imre Kaloz -+ * Copyright (c) 2010 Daniel Golle -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _LINUX_ATH5K_PLATFORM_H -+#define _LINUX_ATH5K_PLATFORM_H -+ -+#define ATH5K_PLAT_EEP_MAX_WORDS 2048 -+ -+struct ath5k_platform_data { -+ u16 *eeprom_data; -+ u8 *macaddr; -+}; -+ -+#endif /* _LINUX_ATH5K_PLATFORM_H */ diff --git a/package/kernel/mac80211/patches/ath/432-ath5k_add_pciids.patch b/package/kernel/mac80211/patches/ath/432-ath5k_add_pciids.patch deleted file mode 100644 index bd0e6707a5..0000000000 --- a/package/kernel/mac80211/patches/ath/432-ath5k_add_pciids.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/net/wireless/ath/ath5k/pci.c -+++ b/drivers/net/wireless/ath/ath5k/pci.c -@@ -47,6 +47,8 @@ static const struct pci_device_id ath5k_ - { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ - { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ - { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ -+ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */ -+ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */ - { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */ - { 0 } - }; diff --git a/package/kernel/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch b/package/kernel/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch deleted file mode 100644 index 92fb90c165..0000000000 --- a/package/kernel/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch +++ /dev/null @@ -1,142 +0,0 @@ -This adds a bwmode debugfs file which can be used to set alternate -channel operating bandwidths. Only tested with AR5413 and only at -5 and 20 mhz channels. - -Signed-off-by: Pat Erley ---- -Other devices will need to be added to the switch in write_file_bwmode - -drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ - 1 files changed, 86 insertions(+), 0 deletions(-) - ---- a/drivers/net/wireless/ath/ath5k/debug.c -+++ b/drivers/net/wireless/ath/ath5k/debug.c -@@ -803,6 +803,97 @@ static const struct file_operations fops - .llseek = default_llseek, - }; - -+/* debugfs: bwmode */ -+ -+static ssize_t read_file_bwmode(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath5k_hw *ah = file->private_data; -+ char buf[15]; -+ unsigned int len = 0; -+ -+ int cur_ah_bwmode = ah->ah_bwmode_debug; -+ -+#define print_selected(MODE, LABEL) \ -+ if (cur_ah_bwmode == MODE) \ -+ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \ -+ else \ -+ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \ -+ len += snprintf(buf+len, sizeof(buf)-len, " "); -+ -+ print_selected(AR5K_BWMODE_5MHZ, "5"); -+ print_selected(AR5K_BWMODE_10MHZ, "10"); -+ print_selected(AR5K_BWMODE_DEFAULT, "20"); -+ print_selected(AR5K_BWMODE_40MHZ, "40"); -+#undef print_selected -+ -+ len += snprintf(buf+len, sizeof(buf)-len, "\n"); -+ -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); -+} -+ -+static ssize_t write_file_bwmode(struct file *file, -+ const char __user *userbuf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath5k_hw *ah = file->private_data; -+ char buf[3]; -+ int bw = 20; -+ int tobwmode = AR5K_BWMODE_DEFAULT; -+ -+ if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) -+ return -EFAULT; -+ -+ /* TODO: Add check for active interface */ -+ -+ if(strncmp(buf, "5", 1) == 0 ) { -+ tobwmode = AR5K_BWMODE_5MHZ; -+ bw = 5; -+ } else if ( strncmp(buf, "10", 2) == 0 ) { -+ tobwmode = AR5K_BWMODE_10MHZ; -+ bw = 10; -+ } else if ( strncmp(buf, "20", 2) == 0 ) { -+ tobwmode = AR5K_BWMODE_DEFAULT; -+ bw = 20; -+ } else if ( strncmp(buf, "40", 2) == 0 ) { -+ tobwmode = AR5K_BWMODE_40MHZ; -+ bw = 40; -+ } else -+ return -EINVAL; -+ -+ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n", -+ bw, tobwmode); -+ -+ switch (ah->ah_radio) { -+ /* TODO: only define radios that actually support 5/10mhz channels */ -+ case AR5K_RF5413: -+ case AR5K_RF5110: -+ case AR5K_RF5111: -+ case AR5K_RF5112: -+ case AR5K_RF2413: -+ case AR5K_RF2316: -+ case AR5K_RF2317: -+ case AR5K_RF2425: -+ if(ah->ah_bwmode_debug != tobwmode) { -+ mutex_lock(&ah->lock); -+ ah->ah_bwmode = tobwmode; -+ ah->ah_bwmode_debug = tobwmode; -+ mutex_unlock(&ah->lock); -+ } -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ return count; -+} -+ -+static const struct file_operations fops_bwmode = { -+ .read = read_file_bwmode, -+ .write = write_file_bwmode, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; - - /* debugfs: queues etc */ - -@@ -997,6 +1088,8 @@ ath5k_debug_init_device(struct ath5k_hw - debugfs_create_file("queue", 0600, phydir, ah, &fops_queue); - debugfs_create_bool("32khz_clock", 0600, phydir, - &ah->ah_use_32khz_clock); -+ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah, -+ &fops_bwmode); - } - - /* functions used in other places */ ---- a/drivers/net/wireless/ath/ath5k/ath5k.h -+++ b/drivers/net/wireless/ath/ath5k/ath5k.h -@@ -1372,6 +1372,7 @@ struct ath5k_hw { - u8 ah_coverage_class; - bool ah_ack_bitrate_high; - u8 ah_bwmode; -+ u8 ah_bwmode_debug; - bool ah_short_slot; - - /* Antenna Control */ ---- a/drivers/net/wireless/ath/ath5k/base.c -+++ b/drivers/net/wireless/ath/ath5k/base.c -@@ -466,6 +466,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru - return -EINVAL; - } - -+ if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT) -+ ah->ah_bwmode = ah->ah_bwmode_debug; -+ - /* - * To switch channels clear any pending DMA operations; - * wait long enough for the RX fifo to drain, reset the diff --git a/package/kernel/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch b/package/kernel/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch deleted file mode 100644 index ea94b52385..0000000000 --- a/package/kernel/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch +++ /dev/null @@ -1,34 +0,0 @@ -From d946085ff5a331de64e91a2e3c96b9ca79d740f5 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Mon, 15 Jun 2020 00:10:34 +0200 -Subject: [PATCH] ath9k: enabled MFP capability unconditionally - -ath9k will already fallback on software-crypto for chipsets not -supporting IEEE802.11w (MFP). So advertising MFP is not dependent -on disabling HW crypto for all traffic entirely. - -Signed-off-by: David Bauer ---- - drivers/net/wireless/ath/ath9k/init.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -927,6 +927,7 @@ static void ath9k_set_hw_capab(struct at - ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); - ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); - ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); -+ ieee80211_hw_set(hw, MFP_CAPABLE); - - if (ath9k_ps_enable) - ieee80211_hw_set(hw, SUPPORTS_PS); -@@ -939,9 +940,6 @@ static void ath9k_set_hw_capab(struct at - IEEE80211_RADIOTAP_MCS_HAVE_STBC; - } - -- if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) -- ieee80211_hw_set(hw, MFP_CAPABLE); -- - hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | - NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | - NL80211_FEATURE_P2P_GO_CTWIN; diff --git a/package/kernel/mac80211/patches/ath/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/ath/500-ath9k_eeprom_debugfs.patch deleted file mode 100644 index 48ccc81308..0000000000 --- a/package/kernel/mac80211/patches/ath/500-ath9k_eeprom_debugfs.patch +++ /dev/null @@ -1,65 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/debug.c -+++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1364,6 +1364,53 @@ void ath9k_deinit_debug(struct ath_softc - ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); - } - -+static ssize_t read_file_eeprom(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath_softc *sc = file->private_data; -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ int bytes = 0; -+ int pos = *ppos; -+ int size = 4096; -+ u16 val; -+ int i; -+ -+ if (AR_SREV_9300_20_OR_LATER(ah)) -+ size = 16384; -+ -+ if (*ppos < 0) -+ return -EINVAL; -+ -+ if (count > size - *ppos) -+ count = size - *ppos; -+ -+ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) { -+ void *from = &val; -+ -+ if (!common->bus_ops->eeprom_read(common, i, &val)) -+ val = 0xffff; -+ -+ if (*ppos % 2) { -+ from++; -+ bytes = 1; -+ } else if (count == 1) { -+ bytes = 1; -+ } else { -+ bytes = 2; -+ } -+ copy_to_user(user_buf, from, bytes); -+ user_buf += bytes; -+ } -+ return *ppos - pos; -+} -+ -+static const struct file_operations fops_eeprom = { -+ .read = read_file_eeprom, -+ .open = simple_open, -+ .owner = THIS_MODULE -+}; -+ - int ath9k_init_debug(struct ath_hw *ah) - { - struct ath_common *common = ath9k_hw_common(ah); -@@ -1383,6 +1430,8 @@ int ath9k_init_debug(struct ath_hw *ah) - ath9k_tx99_init_debug(sc); - ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); - -+ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, -+ &fops_eeprom); - debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, - read_file_dma); - debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, diff --git a/package/kernel/mac80211/patches/ath/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/ath/501-ath9k_ahb_init.patch deleted file mode 100644 index b9c784eb25..0000000000 --- a/package/kernel/mac80211/patches/ath/501-ath9k_ahb_init.patch +++ /dev/null @@ -1,34 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -1143,25 +1143,25 @@ 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_out; - } - -- error = ath_ahb_init(); -+ error = ath_pci_init(); - if (error < 0) { -+ pr_err("No PCI devices found, driver not installed\n"); - error = -ENODEV; -- goto err_pci_exit; -+ goto err_ahb_exit; - } - - dmi_check_system(ath9k_quirks); - - return 0; - -- err_pci_exit: -- ath_pci_exit(); -+ err_ahb_exit: -+ ath_ahb_exit(); - err_out: - return error; - } diff --git a/package/kernel/mac80211/patches/ath/510-ath9k_intr_mitigation_tweak.patch b/package/kernel/mac80211/patches/ath/510-ath9k_intr_mitigation_tweak.patch deleted file mode 100644 index 75b48b480e..0000000000 --- a/package/kernel/mac80211/patches/ath/510-ath9k_intr_mitigation_tweak.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -403,13 +403,8 @@ static void ath9k_hw_init_config(struct - - ah->config.rx_intr_mitigation = true; - -- if (AR_SREV_9300_20_OR_LATER(ah)) { -- ah->config.rimt_last = 500; -- ah->config.rimt_first = 2000; -- } else { -- ah->config.rimt_last = 250; -- ah->config.rimt_first = 700; -- } -+ ah->config.rimt_last = 250; -+ ah->config.rimt_first = 500; - - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) - ah->config.pll_pwrsave = 7; diff --git a/package/kernel/mac80211/patches/ath/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/ath/511-ath9k_reduce_rxbuf.patch deleted file mode 100644 index 15b8d7b86b..0000000000 --- a/package/kernel/mac80211/patches/ath/511-ath9k_reduce_rxbuf.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/ath9k.h -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -88,7 +88,7 @@ int ath_descdma_setup(struct ath_softc * - (_l) &= ((_sz) - 1); \ - } while (0) - --#define ATH_RXBUF 512 -+#define ATH_RXBUF 256 - #define ATH_TXBUF 512 - #define ATH_TXBUF_RESERVE 5 - #define ATH_TXMAXTRY 13 diff --git a/package/kernel/mac80211/patches/ath/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/ath/512-ath9k_channelbw_debugfs.patch deleted file mode 100644 index 126d1d5c62..0000000000 --- a/package/kernel/mac80211/patches/ath/512-ath9k_channelbw_debugfs.patch +++ /dev/null @@ -1,125 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/debug.c -+++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1411,6 +1411,52 @@ static const struct file_operations fops - .owner = THIS_MODULE - }; - -+ -+static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath_softc *sc = file->private_data; -+ struct ath_common *common = ath9k_hw_common(sc->sc_ah); -+ char buf[32]; -+ unsigned int len; -+ -+ len = sprintf(buf, "0x%08x\n", common->chan_bw); -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); -+} -+ -+static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath_softc *sc = file->private_data; -+ struct ath_common *common = ath9k_hw_common(sc->sc_ah); -+ unsigned long chan_bw; -+ char buf[32]; -+ ssize_t len; -+ -+ len = min(count, sizeof(buf) - 1); -+ if (copy_from_user(buf, user_buf, len)) -+ return -EFAULT; -+ -+ buf[len] = '\0'; -+ if (kstrtoul(buf, 0, &chan_bw)) -+ return -EINVAL; -+ -+ common->chan_bw = chan_bw; -+ if (!test_bit(ATH_OP_INVALID, &common->op_flags)) -+ ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL); -+ -+ return count; -+} -+ -+static const struct file_operations fops_chanbw = { -+ .read = read_file_chan_bw, -+ .write = write_file_chan_bw, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ -+ - int ath9k_init_debug(struct ath_hw *ah) - { - struct ath_common *common = ath9k_hw_common(ah); -@@ -1432,6 +1478,8 @@ int ath9k_init_debug(struct ath_hw *ah) - - debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_eeprom); -+ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, -+ sc, &fops_chanbw); - debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, - read_file_dma); - debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, ---- a/drivers/net/wireless/ath/ath.h -+++ b/drivers/net/wireless/ath/ath.h -@@ -149,6 +149,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 -@@ -297,11 +297,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke - /* - * Update internal channel flags. - */ --static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, -+static void ath9k_cmn_update_ichannel(struct ath_common *common, -+ struct ath9k_channel *ichan, - struct cfg80211_chan_def *chandef) - { - struct ieee80211_channel *chan = chandef->chan; - u16 flags = 0; -+ int width; - - ichan->channel = chan->center_freq; - ichan->chan = chan; -@@ -309,7 +311,19 @@ static void ath9k_cmn_update_ichannel(st - if (chan->band == NL80211_BAND_5GHZ) - flags |= CHANNEL_5GHZ; - -- switch (chandef->width) { -+ switch (common->chan_bw) { -+ case 5: -+ width = NL80211_CHAN_WIDTH_5; -+ break; -+ case 10: -+ width = NL80211_CHAN_WIDTH_10; -+ break; -+ default: -+ width = chandef->width; -+ break; -+ } -+ -+ switch (width) { - case NL80211_CHAN_WIDTH_5: - flags |= CHANNEL_QUARTER; - break; -@@ -342,10 +356,11 @@ struct ath9k_channel *ath9k_cmn_get_chan - struct cfg80211_chan_def *chandef) - { - struct ieee80211_channel *curchan = chandef->chan; -+ struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_channel *channel; - - channel = &ah->channels[curchan->hw_value]; -- ath9k_cmn_update_ichannel(channel, chandef); -+ ath9k_cmn_update_ichannel(common, channel, chandef); - - return channel; - } diff --git a/package/kernel/mac80211/patches/ath/513-ath9k_add_pci_ids.patch b/package/kernel/mac80211/patches/ath/513-ath9k_add_pci_ids.patch deleted file mode 100644 index 113c35625f..0000000000 --- a/package/kernel/mac80211/patches/ath/513-ath9k_add_pci_ids.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -663,6 +663,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) { -+ case AR9300_DEVID_INVALID: - case AR5416_DEVID_PCI: - case AR5416_DEVID_PCIE: - case AR5416_AR9100_DEVID: ---- a/drivers/net/wireless/ath/ath9k/hw.h -+++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -36,6 +36,7 @@ - - #define ATHEROS_VENDOR_ID 0x168c - -+#define AR9300_DEVID_INVALID 0xabcd - #define AR5416_DEVID_PCI 0x0023 - #define AR5416_DEVID_PCIE 0x0024 - #define AR9160_DEVID_PCI 0x0027 ---- a/drivers/net/wireless/ath/ath9k/pci.c -+++ b/drivers/net/wireless/ath/ath9k/pci.c -@@ -774,6 +774,7 @@ static const struct pci_device_id ath_pc - .driver_data = ATH9K_PCI_BT_ANT_DIV }, - #endif - -+ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */ - { 0 } - }; - diff --git a/package/kernel/mac80211/patches/ath/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/ath/530-ath9k_extra_leds.patch deleted file mode 100644 index 5fd5c73a2f..0000000000 --- a/package/kernel/mac80211/patches/ath/530-ath9k_extra_leds.patch +++ /dev/null @@ -1,267 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/ath9k.h -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -844,6 +844,9 @@ static inline int ath9k_dump_btcoex(stru - #ifdef CPTCFG_MAC80211_LEDS - void ath_init_leds(struct ath_softc *sc); - void ath_deinit_leds(struct ath_softc *sc); -+int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name, -+ const char *trigger, bool active_low); -+ - #else - static inline void ath_init_leds(struct ath_softc *sc) - { -@@ -980,6 +983,13 @@ void ath_ant_comb_scan(struct ath_softc - - #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ - -+struct ath_led { -+ struct list_head list; -+ struct ath_softc *sc; -+ const struct gpio_led *gpio; -+ struct led_classdev cdev; -+}; -+ - struct ath_softc { - struct ieee80211_hw *hw; - struct device *dev; -@@ -1033,9 +1043,8 @@ struct ath_softc { - spinlock_t chan_lock; - - #ifdef CPTCFG_MAC80211_LEDS -- bool led_registered; -- char led_name[32]; -- struct led_classdev led_cdev; -+ const char *led_default_trigger; -+ struct list_head leds; - #endif - - #ifdef CPTCFG_ATH9K_DEBUGFS ---- a/drivers/net/wireless/ath/ath9k/gpio.c -+++ b/drivers/net/wireless/ath/ath9k/gpio.c -@@ -39,61 +39,111 @@ static void ath_fill_led_pin(struct ath_ - else - ah->led_pin = ATH_LED_PIN_DEF; - } -+} -+ -+static void ath_led_brightness(struct led_classdev *led_cdev, -+ enum led_brightness brightness) -+{ -+ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev); -+ struct ath_softc *sc = led->sc; -+ -+ ath9k_ps_wakeup(sc); -+ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio, -+ (brightness != LED_OFF) ^ led->gpio->active_low); -+ ath9k_ps_restore(sc); -+} -+ -+static int ath_add_led(struct ath_softc *sc, struct ath_led *led) -+{ -+ const struct gpio_led *gpio = led->gpio; -+ int ret; -+ -+ led->cdev.name = gpio->name; -+ led->cdev.default_trigger = gpio->default_trigger; -+ led->cdev.brightness_set = ath_led_brightness; -+ -+ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev); -+ if (ret < 0) -+ return ret; -+ -+ led->sc = sc; -+ list_add(&led->list, &sc->leds); - - /* Configure gpio for output */ -- ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", -+ ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - -- /* LED off, active low */ -- ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1); -+ /* LED off */ -+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); -+ -+ return 0; - } - --static void ath_led_brightness(struct led_classdev *led_cdev, -- enum led_brightness brightness) -+int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name, -+ const char *trigger, bool active_low) - { -- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); -- u32 val = (brightness == LED_OFF); -+ struct ath_led *led; -+ struct gpio_led *gpio; -+ char *_name; -+ int ret; - -- if (sc->sc_ah->config.led_active_high) -- val = !val; -+ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1, -+ GFP_KERNEL); -+ if (!led) -+ return -ENOMEM; -+ -+ led->gpio = gpio = (struct gpio_led *) (led + 1); -+ _name = (char *) (led->gpio + 1); -+ -+ strcpy(_name, name); -+ gpio->name = _name; -+ gpio->gpio = gpio_num; -+ gpio->active_low = active_low; -+ gpio->default_trigger = trigger; -+ -+ ret = ath_add_led(sc, led); -+ if (unlikely(ret < 0)) -+ kfree(led); - -- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); -+ return ret; - } - - void ath_deinit_leds(struct ath_softc *sc) - { -- if (!sc->led_registered) -- return; -+ struct ath_led *led; - -- ath_led_brightness(&sc->led_cdev, LED_OFF); -- led_classdev_unregister(&sc->led_cdev); -- -- ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin); -+ while (!list_empty(&sc->leds)) { -+ led = list_first_entry(&sc->leds, struct ath_led, list); -+ list_del(&led->list); -+ ath_led_brightness(&led->cdev, LED_OFF); -+ led_classdev_unregister(&led->cdev); -+ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio); -+ kfree(led); -+ } - } - - void ath_init_leds(struct ath_softc *sc) - { -- int ret; -+ char led_name[32]; -+ const char *trigger; -+ -+ INIT_LIST_HEAD(&sc->leds); - - if (AR_SREV_9100(sc->sc_ah)) - return; - - ath_fill_led_pin(sc); - -- if (!ath9k_led_blink) -- sc->led_cdev.default_trigger = -- ieee80211_get_radio_led_name(sc->hw); -- -- snprintf(sc->led_name, sizeof(sc->led_name), -- "ath9k-%s", wiphy_name(sc->hw->wiphy)); -- sc->led_cdev.name = sc->led_name; -- sc->led_cdev.brightness_set = ath_led_brightness; -+ snprintf(led_name, sizeof(led_name), "ath9k-%s", -+ wiphy_name(sc->hw->wiphy)); - -- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); -- if (ret < 0) -- return; -+ if (ath9k_led_blink) -+ trigger = sc->led_default_trigger; -+ else -+ trigger = ieee80211_get_radio_led_name(sc->hw); - -- sc->led_registered = true; -+ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, -+ !sc->sc_ah->config.led_active_high); - } - #endif - ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -1055,7 +1055,7 @@ int ath9k_init_device(u16 devid, struct - - #ifdef CPTCFG_MAC80211_LEDS - /* must be initialized before ieee80211_register_hw */ -- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, -+ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, - IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, - ARRAY_SIZE(ath9k_tpt_blink)); - #endif ---- a/drivers/net/wireless/ath/ath9k/debug.c -+++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1456,6 +1456,61 @@ static const struct file_operations fops - .llseek = default_llseek, - }; - -+#ifdef CONFIG_MAC80211_LEDS -+ -+static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath_softc *sc = file->private_data; -+ char buf[32], *str, *name, *c; -+ ssize_t len; -+ unsigned int gpio; -+ bool active_low = false; -+ -+ len = min(count, sizeof(buf) - 1); -+ if (copy_from_user(buf, ubuf, len)) -+ return -EFAULT; -+ -+ buf[len] = '\0'; -+ name = strchr(buf, ','); -+ if (!name) -+ return -EINVAL; -+ -+ *(name++) = 0; -+ if (!*name) -+ return -EINVAL; -+ -+ c = strchr(name, '\n'); -+ if (c) -+ *c = 0; -+ -+ str = buf; -+ if (*str == '!') { -+ str++; -+ active_low = true; -+ } -+ -+ if (kstrtouint(str, 0, &gpio) < 0) -+ return -EINVAL; -+ -+ if (gpio >= sc->sc_ah->caps.num_gpio_pins) -+ return -EINVAL; -+ -+ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0) -+ return -EINVAL; -+ -+ return count; -+} -+ -+static const struct file_operations fops_gpio_led = { -+ .write = write_file_gpio_led, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ -+#endif -+ - - int ath9k_init_debug(struct ath_hw *ah) - { -@@ -1480,6 +1535,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); -+#ifdef CONFIG_MAC80211_LEDS -+ debugfs_create_file("gpio_led", S_IWUSR, -+ sc->debug.debugfs_phy, sc, &fops_gpio_led); -+#endif - debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, - read_file_dma); - debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, diff --git a/package/kernel/mac80211/patches/ath/531-ath9k_extra_platform_leds.patch b/package/kernel/mac80211/patches/ath/531-ath9k_extra_platform_leds.patch deleted file mode 100644 index 8ed7ad8a09..0000000000 --- a/package/kernel/mac80211/patches/ath/531-ath9k_extra_platform_leds.patch +++ /dev/null @@ -1,76 +0,0 @@ ---- a/include/linux/ath9k_platform.h -+++ b/include/linux/ath9k_platform.h -@@ -46,6 +46,9 @@ struct ath9k_platform_data { - int (*external_reset)(void); - - bool use_eeprom; -+ -+ int num_leds; -+ const struct gpio_led *leds; - }; - - #endif /* _LINUX_ATH9K_PLATFORM_H */ ---- a/drivers/net/wireless/ath/ath9k/gpio.c -+++ b/drivers/net/wireless/ath/ath9k/gpio.c -@@ -15,6 +15,7 @@ - */ - - #include "ath9k.h" -+#include - - /********************************/ - /* LED functions */ -@@ -108,6 +109,24 @@ int ath_create_gpio_led(struct ath_softc - return ret; - } - -+static int ath_create_platform_led(struct ath_softc *sc, -+ const struct gpio_led *gpio) -+{ -+ struct ath_led *led; -+ int ret; -+ -+ led = kzalloc(sizeof(*led), GFP_KERNEL); -+ if (!led) -+ return -ENOMEM; -+ -+ led->gpio = gpio; -+ ret = ath_add_led(sc, led); -+ if (ret < 0) -+ kfree(led); -+ -+ return ret; -+} -+ - void ath_deinit_leds(struct ath_softc *sc) - { - struct ath_led *led; -@@ -124,8 +143,10 @@ void ath_deinit_leds(struct ath_softc *s - - void ath_init_leds(struct ath_softc *sc) - { -+ struct ath9k_platform_data *pdata = sc->dev->platform_data; - char led_name[32]; - const char *trigger; -+ int i; - - INIT_LIST_HEAD(&sc->leds); - -@@ -134,6 +155,17 @@ void ath_init_leds(struct ath_softc *sc) - - ath_fill_led_pin(sc); - -+ if (pdata && pdata->leds && pdata->num_leds) -+ for (i = 0; i < pdata->num_leds; i++) { -+ if (pdata->leds[i].gpio == sc->sc_ah->led_pin) -+ sc->sc_ah->led_pin = -1; -+ -+ ath_create_platform_led(sc, &pdata->leds[i]); -+ } -+ -+ if (sc->sc_ah->led_pin < 0) -+ return; -+ - snprintf(led_name, sizeof(led_name), "ath9k-%s", - wiphy_name(sc->hw->wiphy)); - diff --git a/package/kernel/mac80211/patches/ath/540-ath9k_reduce_ani_interval.patch b/package/kernel/mac80211/patches/ath/540-ath9k_reduce_ani_interval.patch deleted file mode 100644 index e899903478..0000000000 --- a/package/kernel/mac80211/patches/ath/540-ath9k_reduce_ani_interval.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/ani.h -+++ b/drivers/net/wireless/ath/ath9k/ani.h -@@ -42,7 +42,7 @@ - #define ATH9K_ANI_PERIOD 300 - - /* in ms */ --#define ATH9K_ANI_POLLINTERVAL 1000 -+#define ATH9K_ANI_POLLINTERVAL 300 - - #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0 - #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20 diff --git a/package/kernel/mac80211/patches/ath/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/ath/542-ath9k_debugfs_diag.patch deleted file mode 100644 index f93a6fe5cd..0000000000 --- a/package/kernel/mac80211/patches/ath/542-ath9k_debugfs_diag.patch +++ /dev/null @@ -1,139 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/debug.c -+++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1512,6 +1512,50 @@ static const struct file_operations fops - #endif - - -+static ssize_t read_file_diag(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath_softc *sc = file->private_data; -+ struct ath_hw *ah = sc->sc_ah; -+ char buf[32]; -+ unsigned int len; -+ -+ len = sprintf(buf, "0x%08lx\n", ah->diag); -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); -+} -+ -+static ssize_t write_file_diag(struct file *file, const char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath_softc *sc = file->private_data; -+ struct ath_hw *ah = sc->sc_ah; -+ unsigned long diag; -+ char buf[32]; -+ ssize_t len; -+ -+ len = min(count, sizeof(buf) - 1); -+ if (copy_from_user(buf, user_buf, len)) -+ return -EFAULT; -+ -+ buf[len] = '\0'; -+ if (kstrtoul(buf, 0, &diag)) -+ return -EINVAL; -+ -+ ah->diag = diag; -+ ath9k_hw_update_diag(ah); -+ -+ return count; -+} -+ -+static const struct file_operations fops_diag = { -+ .read = read_file_diag, -+ .write = write_file_diag, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ -+ - int ath9k_init_debug(struct ath_hw *ah) - { - struct ath_common *common = ath9k_hw_common(ah); -@@ -1539,6 +1583,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 -+ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, -+ sc, &fops_diag); - debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, - read_file_dma); - debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, ---- a/drivers/net/wireless/ath/ath9k/hw.h -+++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -522,6 +522,12 @@ enum { - ATH9K_RESET_COLD, - }; - -+enum { -+ ATH_DIAG_DISABLE_RX, -+ ATH_DIAG_DISABLE_TX, -+ ATH_DIAG_TRIGGER_ERROR, -+}; -+ - struct ath9k_hw_version { - u32 magic; - u16 devid; -@@ -810,6 +816,8 @@ struct ath_hw { - u32 ah_flags; - s16 nf_override; - -+ unsigned long diag; -+ - bool reset_power_on; - bool htc_reset_init; - -@@ -1076,6 +1084,7 @@ void ath9k_hw_check_nav(struct ath_hw *a - bool ath9k_hw_check_alive(struct ath_hw *ah); - - bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); -+void ath9k_hw_update_diag(struct ath_hw *ah); - - /* Generic hw timer primitives */ - 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 -@@ -1883,6 +1883,20 @@ u32 ath9k_hw_get_tsf_offset(struct times - } - EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); - -+void ath9k_hw_update_diag(struct ath_hw *ah) -+{ -+ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag)) -+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); -+ else -+ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); -+ -+ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag)) -+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); -+ else -+ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); -+} -+EXPORT_SYMBOL(ath9k_hw_update_diag); -+ - int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, - struct ath9k_hw_cal_data *caldata, bool fastcc) - { -@@ -2091,6 +2105,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st - ar9003_hw_disable_phy_restart(ah); - - ath9k_hw_apply_gpio_override(ah); -+ ath9k_hw_update_diag(ah); - - if (AR_SREV_9565(ah) && common->bt_ant_diversity) - 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 -@@ -531,6 +531,11 @@ irqreturn_t ath_isr(int irq, void *dev) - if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) - return IRQ_HANDLED; - -+ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) { -+ status |= ATH9K_INT_FATAL; -+ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag); -+ } -+ - /* - * If there are no status bits set, then this interrupt was not - * for me (should have been caught above). diff --git a/package/kernel/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch deleted file mode 100644 index 0d938a3730..0000000000 --- a/package/kernel/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch +++ /dev/null @@ -1,186 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/hw.h -+++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -723,6 +723,7 @@ struct ath_spec_scan { - * @config_pci_powersave: - * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC - * -+ * @get_adc_entropy: get entropy from the raw ADC I/Q output - * @spectral_scan_config: set parameters for spectral scan and enable/disable it - * @spectral_scan_trigger: trigger a spectral scan run - * @spectral_scan_wait: wait for a spectral scan run to finish -@@ -745,6 +746,7 @@ struct ath_hw_ops { - struct ath_hw_antcomb_conf *antconf); - void (*antdiv_comb_conf_set)(struct ath_hw *ah, - struct ath_hw_antcomb_conf *antconf); -+ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len); - void (*spectral_scan_config)(struct ath_hw *ah, - struct ath_spec_scan *param); - void (*spectral_scan_trigger)(struct ath_hw *ah); ---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c -@@ -1927,6 +1927,26 @@ void ar9003_hw_init_rate_txpower(struct - } - } - -+static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) -+{ -+ int i, j; -+ -+ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); -+ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); -+ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0); -+ -+ memset(buf, 0, len); -+ for (i = 0; i < len; i++) { -+ for (j = 0; j < 4; j++) { -+ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); -+ -+ buf[i] <<= 2; -+ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9); -+ udelay(1); -+ } -+ } -+} -+ - void ar9003_hw_attach_phy_ops(struct ath_hw *ah) - { - struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); -@@ -1963,6 +1983,7 @@ void ar9003_hw_attach_phy_ops(struct ath - priv_ops->set_radar_params = ar9003_hw_set_radar_params; - priv_ops->fast_chan_change = ar9003_hw_fast_chan_change; - -+ ops->get_adc_entropy = ar9003_hw_get_adc_entropy; - ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; - ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; - 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 -@@ -818,7 +818,8 @@ static void ath9k_init_txpower_limits(st - if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) - ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); - -- ah->curchan = curchan; -+ if (curchan) -+ ah->curchan = curchan; - } - - static const struct ieee80211_iface_limit if_limits[] = { -@@ -1015,6 +1016,18 @@ static void ath9k_set_hw_capab(struct at - wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); - } - -+static void ath_get_initial_entropy(struct ath_softc *sc) -+{ -+ struct ath_hw *ah = sc->sc_ah; -+ char buf[256]; -+ -+ /* reuse last channel initialized by the tx power test */ -+ ath9k_hw_reset(ah, ah->curchan, NULL, false); -+ -+ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf)); -+ add_device_randomness(buf, sizeof(buf)); -+} -+ - int ath9k_init_device(u16 devid, struct ath_softc *sc, - const struct ath_bus_ops *bus_ops) - { -@@ -1060,6 +1073,8 @@ int ath9k_init_device(u16 devid, struct - ARRAY_SIZE(ath9k_tpt_blink)); - #endif - -+ ath_get_initial_entropy(sc); -+ - /* Register with mac80211 */ - error = ieee80211_register_hw(hw); - if (error) ---- a/drivers/net/wireless/ath/ath9k/hw-ops.h -+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h -@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp - ath9k_hw_ops(ah)->tx99_set_txpower(ah, power); - } - -+static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah, -+ u8 *buf, size_t len) -+{ -+ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len); -+} -+ - #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT - - static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) ---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c -@@ -1349,9 +1349,30 @@ void ar5008_hw_init_rate_txpower(struct - } - } - -+static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) -+{ -+ int i, j; -+ -+ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); -+ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); -+ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0); -+ -+ memset(buf, 0, len); -+ for (i = 0; i < len; i++) { -+ for (j = 0; j < 4; j++) { -+ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); -+ -+ buf[i] <<= 2; -+ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8); -+ udelay(1); -+ } -+ } -+} -+ - int ar5008_hw_attach_phy_ops(struct ath_hw *ah) - { - struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); -+ struct ath_hw_ops *ops = ath9k_hw_ops(ah); - static const u32 ar5416_cca_regs[6] = { - AR_PHY_CCA, - AR_PHY_CH1_CCA, -@@ -1366,6 +1387,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ - if (ret) - return ret; - -+ ops->get_adc_entropy = ar5008_hw_get_adc_entropy; -+ - priv_ops->rf_set_freq = ar5008_hw_set_channel; - priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; - ---- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h -+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h -@@ -20,6 +20,12 @@ - #define PHY_AGC_CLR 0x10000000 - #define RFSILENT_BB 0x00002000 - -+#define AR_PHY_TEST_BBB_OBS_SEL 0x780000 -+#define AR_PHY_TEST_BBB_OBS_SEL_S 19 -+ -+#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23 -+#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S) -+ - #define AR_PHY_TURBO 0x9804 - #define AR_PHY_FC_TURBO_MODE 0x00000001 - #define AR_PHY_FC_TURBO_SHORT 0x00000002 -@@ -36,6 +42,9 @@ - - #define AR_PHY_TEST2 0x9808 - -+#define AR_PHY_TEST2_RX_OBS_SEL 0x3C00 -+#define AR_PHY_TEST2_RX_OBS_SEL_S 10 -+ - #define AR_PHY_TIMING2 0x9810 - #define AR_PHY_TIMING3 0x9814 - #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 -@@ -393,6 +402,8 @@ - #define AR_PHY_RFBUS_GRANT 0x9C20 - #define AR_PHY_RFBUS_GRANT_EN 0x00000001 - -+#define AR_PHY_TST_ADC 0x9C24 -+ - #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 - #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 - diff --git a/package/kernel/mac80211/patches/ath/544-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/ath/544-ath9k-ar933x-usb-hang-workaround.patch deleted file mode 100644 index 93eee34b64..0000000000 --- a/package/kernel/mac80211/patches/ath/544-ath9k-ar933x-usb-hang-workaround.patch +++ /dev/null @@ -1,79 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -248,6 +248,19 @@ void ath9k_hw_get_channel_centers(struct - centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); - } - -+static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah) -+{ -+ /* On AR9330 and AR9340 devices, some PHY registers must be -+ * tuned to gain better stability/performance. These registers -+ * might be changed while doing wlan reset so the registers must -+ * be reprogrammed after each reset. -+ */ -+ REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20)); -+ REG_RMW(ah, AR_PHY_USB_CTRL2, -+ (1 << 21) | (0xf << 22), -+ (1 << 21) | (0x3 << 22)); -+} -+ - /******************/ - /* Chip Revisions */ - /******************/ -@@ -1455,6 +1468,9 @@ static bool ath9k_hw_set_reset(struct at - udelay(50); - } - -+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) -+ ath9k_hw_disable_pll_lock_detect(ah); -+ - return true; - } - -@@ -1554,6 +1570,9 @@ static bool ath9k_hw_chip_reset(struct a - ar9003_hw_internal_regulator_apply(ah); - ath9k_hw_init_pll(ah, chan); - -+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) -+ ath9k_hw_disable_pll_lock_detect(ah); -+ - return true; - } - -@@ -1861,8 +1880,14 @@ static int ath9k_hw_do_fastcc(struct ath - if (AR_SREV_9271(ah)) - ar9002_hw_load_ani_reg(ah, chan); - -+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) -+ ath9k_hw_disable_pll_lock_detect(ah); -+ - return 0; - fail: -+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) -+ ath9k_hw_disable_pll_lock_detect(ah); -+ - return -EINVAL; - } - -@@ -2116,6 +2141,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st - ath9k_hw_set_radar_params(ah); - } - -+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) -+ ath9k_hw_disable_pll_lock_detect(ah); -+ - return 0; - } - EXPORT_SYMBOL(ath9k_hw_reset); ---- a/drivers/net/wireless/ath/ath9k/phy.h -+++ b/drivers/net/wireless/ath/ath9k/phy.h -@@ -48,6 +48,9 @@ - #define AR_PHY_PLL_CONTROL 0x16180 - #define AR_PHY_PLL_MODE 0x16184 - -+#define AR_PHY_USB_CTRL1 0x16c84 -+#define AR_PHY_USB_CTRL2 0x16c88 -+ - enum ath9k_ant_div_comb_lna_conf { - ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, - ATH_ANT_DIV_COMB_LNA2, diff --git a/package/kernel/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch b/package/kernel/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch deleted file mode 100644 index 466767adb9..0000000000 --- a/package/kernel/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch +++ /dev/null @@ -1,155 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c -@@ -978,55 +978,6 @@ static bool ar5008_hw_ani_control_new(st - * on == 0 means more noise imm - */ - u32 on = param ? 1 : 0; -- /* -- * make register setting for default -- * (weak sig detect ON) come from INI file -- */ -- int m1ThreshLow = on ? -- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; -- int m2ThreshLow = on ? -- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; -- int m1Thresh = on ? -- aniState->iniDef.m1Thresh : m1Thresh_off; -- int m2Thresh = on ? -- aniState->iniDef.m2Thresh : m2Thresh_off; -- int m2CountThr = on ? -- aniState->iniDef.m2CountThr : m2CountThr_off; -- int m2CountThrLow = on ? -- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; -- int m1ThreshLowExt = on ? -- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; -- int m2ThreshLowExt = on ? -- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; -- int m1ThreshExt = on ? -- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; -- int m2ThreshExt = on ? -- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; -- -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, -- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, -- m1ThreshLow); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, -- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, -- m2ThreshLow); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR, -- AR_PHY_SFCORR_M1_THRESH, m1Thresh); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR, -- AR_PHY_SFCORR_M2_THRESH, m2Thresh); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR, -- AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, -- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, -- m2CountThrLow); -- -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -- AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -- AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); - - if (on) - REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, ---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c -@@ -42,20 +42,6 @@ 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 -- */ --static const int m1ThreshLow_off = 127; --static const int m2ThreshLow_off = 127; --static const int m1Thresh_off = 127; --static const int m2Thresh_off = 127; --static const int m2CountThr_off = 31; --static const int m2CountThrLow_off = 63; --static const int m1ThreshLowExt_off = 127; --static const int m2ThreshLowExt_off = 127; --static const int m1ThreshExt_off = 127; --static const int m2ThreshExt_off = 127; -- - static const u8 ofdm2pwr[] = { - ALL_TARGET_LEGACY_6_24, - ALL_TARGET_LEGACY_6_24, -@@ -1077,11 +1063,6 @@ static bool ar9003_hw_ani_control(struct - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_channel *chan = ah->curchan; - struct ar5416AniState *aniState = &ah->ani; -- int m1ThreshLow, m2ThreshLow; -- int m1Thresh, m2Thresh; -- int m2CountThr, m2CountThrLow; -- int m1ThreshLowExt, m2ThreshLowExt; -- int m1ThreshExt, m2ThreshExt; - s32 value, value2; - - switch (cmd & ah->ani_function) { -@@ -1095,61 +1076,6 @@ static bool ar9003_hw_ani_control(struct - */ - u32 on = param ? 1 : 0; - -- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) -- goto skip_ws_det; -- -- m1ThreshLow = on ? -- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; -- m2ThreshLow = on ? -- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; -- m1Thresh = on ? -- aniState->iniDef.m1Thresh : m1Thresh_off; -- m2Thresh = on ? -- aniState->iniDef.m2Thresh : m2Thresh_off; -- m2CountThr = on ? -- aniState->iniDef.m2CountThr : m2CountThr_off; -- m2CountThrLow = on ? -- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; -- m1ThreshLowExt = on ? -- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; -- m2ThreshLowExt = on ? -- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; -- m1ThreshExt = on ? -- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; -- m2ThreshExt = on ? -- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; -- -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, -- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, -- m1ThreshLow); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, -- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, -- m2ThreshLow); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR, -- AR_PHY_SFCORR_M1_THRESH, -- m1Thresh); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR, -- AR_PHY_SFCORR_M2_THRESH, -- m2Thresh); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR, -- AR_PHY_SFCORR_M2COUNT_THR, -- m2CountThr); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, -- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, -- m2CountThrLow); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, -- m1ThreshLowExt); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, -- m2ThreshLowExt); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -- AR_PHY_SFCORR_EXT_M1_THRESH, -- m1ThreshExt); -- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -- AR_PHY_SFCORR_EXT_M2_THRESH, -- m2ThreshExt); --skip_ws_det: - if (on) - REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); diff --git a/package/kernel/mac80211/patches/ath/547-ath9k_led_defstate_fix.patch b/package/kernel/mac80211/patches/ath/547-ath9k_led_defstate_fix.patch deleted file mode 100644 index 5d84cf0c42..0000000000 --- a/package/kernel/mac80211/patches/ath/547-ath9k_led_defstate_fix.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: Michal Cieslakiewicz -Date: Sun, 31 Jan 2016 20:48:49 +0100 -Subject: [PATCH v4 2/8] mac80211: ath9k: set default state for platform LEDs - -Support default state for platform LEDs connected to ath9k device. -Now LEDs are correctly set on or off at ath9k module initialization. -Very useful if power LED is connected to wireless chip. - -Signed-off-by: Michal Cieslakiewicz ---- - gpio.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/ath/ath9k/gpio.c -+++ b/drivers/net/wireless/ath/ath9k/gpio.c -@@ -74,8 +74,11 @@ static int ath_add_led(struct ath_softc - ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - -- /* LED off */ -- ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); -+ /* Set default LED state */ -+ if (gpio->default_state == LEDS_GPIO_DEFSTATE_ON) -+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, !gpio->active_low); -+ else -+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); - - return 0; - } diff --git a/package/kernel/mac80211/patches/ath/548-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/ath/548-ath9k_enable_gpio_chip.patch deleted file mode 100644 index 88198a4562..0000000000 --- a/package/kernel/mac80211/patches/ath/548-ath9k_enable_gpio_chip.patch +++ /dev/null @@ -1,251 +0,0 @@ -From: Michal Cieslakiewicz -Date: Sun, 31 Jan 2016 21:01:31 +0100 -Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO - -Enable access to GPIO chip and its pins for Atheros AR92xx -wireless devices. For now AR9285 and AR9287 are supported. - -Signed-off-by: Michal Cieslakiewicz -Signed-off-by: Felix Fietkau ---- ---- a/drivers/net/wireless/ath/ath9k/ath9k.h -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - #include "common.h" - #include "debug.h" -@@ -990,6 +991,14 @@ struct ath_led { - struct led_classdev cdev; - }; - -+#ifdef CONFIG_GPIOLIB -+struct ath9k_gpio_chip { -+ struct ath_softc *sc; -+ char label[32]; -+ struct gpio_chip gchip; -+}; -+#endif -+ - struct ath_softc { - struct ieee80211_hw *hw; - struct device *dev; -@@ -1045,6 +1054,9 @@ struct ath_softc { - #ifdef CPTCFG_MAC80211_LEDS - const char *led_default_trigger; - struct list_head leds; -+#ifdef CONFIG_GPIOLIB -+ struct ath9k_gpio_chip *gpiochip; -+#endif - #endif - - #ifdef CPTCFG_ATH9K_DEBUGFS ---- a/drivers/net/wireless/ath/ath9k/gpio.c -+++ b/drivers/net/wireless/ath/ath9k/gpio.c -@@ -16,13 +16,139 @@ - - #include "ath9k.h" - #include -+#include -+ -+#ifdef CPTCFG_MAC80211_LEDS -+ -+#ifdef CONFIG_GPIOLIB -+ -+/***************/ -+/* GPIO Chip */ -+/***************/ -+ -+/* gpio_chip handler : set GPIO to input */ -+static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset) -+{ -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, -+ gchip); -+ -+ ath9k_hw_gpio_request_in(gc->sc->sc_ah, offset, "ath9k-gpio"); -+ -+ return 0; -+} -+ -+/* gpio_chip handler : set GPIO to output */ -+static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset, -+ int value) -+{ -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, -+ gchip); -+ -+ ath9k_hw_gpio_request_out(gc->sc->sc_ah, offset, "ath9k-gpio", -+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value); -+ -+ return 0; -+} -+ -+/* gpio_chip handler : query GPIO direction (0=out, 1=in) */ -+static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset) -+{ -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, -+ gchip); -+ struct ath_hw *ah = gc->sc->sc_ah; -+ -+ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3); -+} -+ -+/* gpio_chip handler : get GPIO pin value */ -+static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset) -+{ -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, -+ gchip); -+ -+ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset); -+} -+ -+/* gpio_chip handler : set GPIO pin to value */ -+static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset, -+ int value) -+{ -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, -+ gchip); -+ -+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value); -+} -+ -+/* register GPIO chip */ -+static void ath9k_register_gpio_chip(struct ath_softc *sc) -+{ -+ struct ath9k_gpio_chip *gc; -+ struct ath_hw *ah = sc->sc_ah; -+ -+ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL); -+ if (!gc) -+ return; -+ -+ gc->sc = sc; -+ snprintf(gc->label, sizeof(gc->label), "ath9k-%s", -+ wiphy_name(sc->hw->wiphy)); -+#ifdef CONFIG_OF -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) -+ gc->gchip.parent = sc->dev; -+#else -+ gc->gchip.dev = sc->dev; -+#endif -+#endif -+ gc->gchip.label = gc->label; -+ gc->gchip.base = -1; /* determine base automatically */ -+ gc->gchip.ngpio = ah->caps.num_gpio_pins; -+ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input; -+ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output; -+ gc->gchip.get_direction = ath9k_gpio_pin_get_dir; -+ gc->gchip.get = ath9k_gpio_pin_get; -+ gc->gchip.set = ath9k_gpio_pin_set; -+ -+ if (gpiochip_add(&gc->gchip)) { -+ kfree(gc); -+ return; -+ } -+ -+#ifdef CONFIG_OF -+ gc->gchip.owner = NULL; -+#endif -+ sc->gpiochip = gc; -+} -+ -+/* remove GPIO chip */ -+static void ath9k_unregister_gpio_chip(struct ath_softc *sc) -+{ -+ struct ath9k_gpio_chip *gc = sc->gpiochip; -+ -+ if (!gc) -+ return; -+ -+ gpiochip_remove(&gc->gchip); -+ kfree(gc); -+ sc->gpiochip = NULL; -+} -+ -+#else /* CONFIG_GPIOLIB */ -+ -+static inline void ath9k_register_gpio_chip(struct ath_softc *sc) -+{ -+} -+ -+static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc) -+{ -+} -+ -+#endif /* CONFIG_GPIOLIB */ - - /********************************/ - /* LED functions */ - /********************************/ - --#ifdef CPTCFG_MAC80211_LEDS -- - static void ath_fill_led_pin(struct ath_softc *sc) - { - struct ath_hw *ah = sc->sc_ah; -@@ -80,6 +206,12 @@ static int ath_add_led(struct ath_softc - else - ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); - -+#ifdef CONFIG_GPIOLIB -+ /* If there is GPIO chip configured, reserve LED pin */ -+ if (sc->gpiochip) -+ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name); -+#endif -+ - return 0; - } - -@@ -136,17 +268,24 @@ void ath_deinit_leds(struct ath_softc *s - - while (!list_empty(&sc->leds)) { - led = list_first_entry(&sc->leds, struct ath_led, list); -+#ifdef CONFIG_GPIOLIB -+ /* If there is GPIO chip configured, free LED pin */ -+ if (sc->gpiochip) -+ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio); -+#endif - list_del(&led->list); - ath_led_brightness(&led->cdev, LED_OFF); - led_classdev_unregister(&led->cdev); - ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio); - kfree(led); - } -+ ath9k_unregister_gpio_chip(sc); - } - - void ath_init_leds(struct ath_softc *sc) - { - struct ath9k_platform_data *pdata = sc->dev->platform_data; -+ struct device_node *np = sc->dev->of_node; - char led_name[32]; - const char *trigger; - int i; -@@ -156,6 +295,15 @@ void ath_init_leds(struct ath_softc *sc) - if (AR_SREV_9100(sc->sc_ah)) - return; - -+ if (!np) -+ ath9k_register_gpio_chip(sc); -+ -+ /* setup gpio controller only if requested and skip the led_pin setup */ -+ if (of_property_read_bool(np, "gpio-controller")) { -+ ath9k_register_gpio_chip(sc); -+ return; -+ } -+ - ath_fill_led_pin(sc); - - if (pdata && pdata->leds && pdata->num_leds) -@@ -180,6 +328,7 @@ void ath_init_leds(struct ath_softc *sc) - ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, - !sc->sc_ah->config.led_active_high); - } -+ - #endif - - /*******************/ diff --git a/package/kernel/mac80211/patches/ath/549-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/ath/549-ath9k_enable_gpio_buttons.patch deleted file mode 100644 index 83076b8ae4..0000000000 --- a/package/kernel/mac80211/patches/ath/549-ath9k_enable_gpio_buttons.patch +++ /dev/null @@ -1,143 +0,0 @@ -From: Michal Cieslakiewicz -Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons - -Enable platform-defined GPIO button support for ath9k device. -Key poller is activated for attached platform buttons. -Requires ath9k GPIO chip access. - -Signed-off-by: Michal Cieslakiewicz -Signed-off-by: Felix Fietkau ---- ---- a/drivers/net/wireless/ath/ath9k/ath9k.h -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -1056,6 +1056,7 @@ struct ath_softc { - struct list_head leds; - #ifdef CONFIG_GPIOLIB - struct ath9k_gpio_chip *gpiochip; -+ struct platform_device *btnpdev; /* gpio-keys-polled */ - #endif - #endif - ---- a/drivers/net/wireless/ath/ath9k/gpio.c -+++ b/drivers/net/wireless/ath/ath9k/gpio.c -@@ -17,6 +17,8 @@ - #include "ath9k.h" - #include - #include -+#include -+#include - - #ifdef CPTCFG_MAC80211_LEDS - -@@ -133,6 +135,67 @@ static void ath9k_unregister_gpio_chip(s - sc->gpiochip = NULL; - } - -+/******************/ -+/* GPIO Buttons */ -+/******************/ -+ -+/* add GPIO buttons */ -+static void ath9k_init_buttons(struct ath_softc *sc) -+{ -+ struct ath9k_platform_data *pdata = sc->dev->platform_data; -+ struct platform_device *pdev; -+ struct gpio_keys_platform_data gkpdata; -+ struct gpio_keys_button *bt; -+ int i; -+ -+ if (!sc->gpiochip) -+ return; -+ -+ if (!pdata || !pdata->btns || !pdata->num_btns) -+ return; -+ -+ bt = devm_kmemdup(sc->dev, pdata->btns, -+ pdata->num_btns * sizeof(struct gpio_keys_button), -+ GFP_KERNEL); -+ if (!bt) -+ return; -+ -+ for (i = 0; i < pdata->num_btns; i++) { -+ if (pdata->btns[i].gpio == sc->sc_ah->led_pin) -+ sc->sc_ah->led_pin = -1; -+ -+ ath9k_hw_gpio_request_in(sc->sc_ah, pdata->btns[i].gpio, -+ "ath9k-gpio"); -+ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio; -+ } -+ -+ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data)); -+ gkpdata.buttons = bt; -+ gkpdata.nbuttons = pdata->num_btns; -+ gkpdata.poll_interval = pdata->btn_poll_interval; -+ -+ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled", -+ PLATFORM_DEVID_AUTO, &gkpdata, -+ sizeof(gkpdata)); -+ if (!IS_ERR_OR_NULL(pdev)) -+ sc->btnpdev = pdev; -+ else { -+ sc->btnpdev = NULL; -+ devm_kfree(sc->dev, bt); -+ } -+} -+ -+/* remove GPIO buttons */ -+static void ath9k_deinit_buttons(struct ath_softc *sc) -+{ -+ if (!sc->gpiochip || !sc->btnpdev) -+ return; -+ -+ platform_device_unregister(sc->btnpdev); -+ -+ sc->btnpdev = NULL; -+} -+ - #else /* CONFIG_GPIOLIB */ - - static inline void ath9k_register_gpio_chip(struct ath_softc *sc) -@@ -143,6 +206,14 @@ static inline void ath9k_unregister_gpio - { - } - -+static inline void ath9k_init_buttons(struct ath_softc *sc) -+{ -+} -+ -+static inline void ath9k_deinit_buttons(struct ath_softc *sc) -+{ -+} -+ - #endif /* CONFIG_GPIOLIB */ - - /********************************/ -@@ -266,6 +337,7 @@ void ath_deinit_leds(struct ath_softc *s - { - struct ath_led *led; - -+ ath9k_deinit_buttons(sc); - while (!list_empty(&sc->leds)) { - led = list_first_entry(&sc->leds, struct ath_led, list); - #ifdef CONFIG_GPIOLIB -@@ -305,6 +377,7 @@ void ath_init_leds(struct ath_softc *sc) - } - - ath_fill_led_pin(sc); -+ ath9k_init_buttons(sc); - - if (pdata && pdata->leds && pdata->num_leds) - for (i = 0; i < pdata->num_leds; i++) { ---- a/include/linux/ath9k_platform.h -+++ b/include/linux/ath9k_platform.h -@@ -49,6 +49,10 @@ struct ath9k_platform_data { - - int num_leds; - const struct gpio_led *leds; -+ -+ unsigned num_btns; -+ const struct gpio_keys_button *btns; -+ unsigned btn_poll_interval; - }; - - #endif /* _LINUX_ATH9K_PLATFORM_H */ diff --git a/package/kernel/mac80211/patches/ath/550-ath9k-disable-bands-via-dt.patch b/package/kernel/mac80211/patches/ath/550-ath9k-disable-bands-via-dt.patch deleted file mode 100644 index 7d3a334c42..0000000000 --- a/package/kernel/mac80211/patches/ath/550-ath9k-disable-bands-via-dt.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -627,6 +627,12 @@ static int ath9k_of_init(struct ath_soft - - ath_dbg(common, CONFIG, "parsing configuration from OF node\n"); - -+ if (of_property_read_bool(np, "qca,disable-2ghz")) -+ ah->disable_2ghz = true; -+ -+ if (of_property_read_bool(np, "qca,disable-5ghz")) -+ ah->disable_5ghz = true; -+ - if (of_property_read_bool(np, "qca,no-eeprom")) { - /* ath9k-eeprom--.bin */ - scnprintf(eeprom_name, sizeof(eeprom_name), diff --git a/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch b/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch deleted file mode 100644 index cd2bdbf1a0..0000000000 --- a/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch +++ /dev/null @@ -1,403 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/channel.c -+++ b/drivers/net/wireless/ath/ath9k/channel.c -@@ -15,6 +15,7 @@ - */ - - #include "ath9k.h" -+#include "hsr.h" - - /* Set/change channels. If the channel is really being changed, it's done - * by reseting the chip. To accomplish this we must first cleanup any pending -@@ -22,6 +23,7 @@ - */ - static int ath_set_channel(struct ath_softc *sc) - { -+ struct device_node *np = sc->dev->of_node; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_hw *hw = sc->hw; -@@ -42,6 +44,11 @@ static int ath_set_channel(struct ath_so - ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", - chan->center_freq, chandef->width); - -+ if (of_property_read_bool(np, "ubnt,hsr")) { -+ ath9k_hsr_enable(ah, chandef->width, chan->center_freq); -+ ath9k_hsr_status(ah); -+ } -+ - /* update survey stats for the old channel before switching */ - spin_lock_irqsave(&common->cc_lock, flags); - ath_update_survey_stats(sc); ---- /dev/null -+++ b/drivers/net/wireless/ath/ath9k/hsr.c -@@ -0,0 +1,247 @@ -+/* -+ * -+ * The MIT License (MIT) -+ * -+ * Copyright (c) 2015 Kirill Berezin -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "hw.h" -+#include "ath9k.h" -+ -+#define HSR_GPIO_CSN 8 -+#define HSR_GPIO_CLK 6 -+#define HSR_GPIO_DOUT 7 -+#define HSR_GPIO_DIN 5 -+ -+/* delays are in useconds */ -+#define HSR_DELAY_HALF_TICK 100 -+#define HSR_DELAY_PRE_WRITE 75 -+#define HSR_DELAY_FINAL 20000 -+#define HSR_DELAY_TRAILING 200 -+ -+void ath9k_hsr_init(struct ath_hw *ah) -+{ -+ ath9k_hw_gpio_request_in(ah, HSR_GPIO_DIN, NULL); -+ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CSN, NULL, -+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -+ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CLK, NULL, -+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -+ ath9k_hw_gpio_request_out(ah, HSR_GPIO_DOUT, NULL, -+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -+ -+ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); -+ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); -+ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0); -+ -+ udelay(HSR_DELAY_TRAILING); -+} -+ -+static u32 ath9k_hsr_write_byte(struct ath_hw *ah, int delay, u32 value) -+{ -+ struct ath_common *common = ath9k_hw_common(ah); -+ int i; -+ u32 rval = 0; -+ -+ udelay(delay); -+ -+ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); -+ udelay(HSR_DELAY_HALF_TICK); -+ -+ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0); -+ udelay(HSR_DELAY_HALF_TICK); -+ -+ for (i = 0; i < 8; ++i) { -+ rval = rval << 1; -+ -+ /* pattern is left to right, that is 7-th bit runs first */ -+ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1); -+ udelay(HSR_DELAY_HALF_TICK); -+ -+ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1); -+ udelay(HSR_DELAY_HALF_TICK); -+ -+ rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN); -+ -+ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); -+ udelay(HSR_DELAY_HALF_TICK); -+ } -+ -+ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); -+ udelay(HSR_DELAY_HALF_TICK); -+ -+ ath_dbg(common, CONFIG, "ath9k_hsr_write_byte: write byte %d return value is %d %c\n", -+ value, rval, rval > 32 ? rval : '-'); -+ -+ return rval & 0xff; -+} -+ -+static int ath9k_hsr_write_a_chain(struct ath_hw *ah, char *chain, int items) -+{ -+ int status = 0; -+ int i = 0; -+ int err; -+ -+ /* a preamble */ -+ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -+ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -+ -+ /* clear HSR's reply buffer */ -+ if (status) { -+ int loop = 0; -+ -+ for (loop = 0; (loop < 42) && status; ++loop) -+ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, -+ 0); -+ -+ if (loop >= 42) { -+ ATH_DBG_WARN(1, -+ "ath9k_hsr_write_a_chain: can't clear an output buffer after a 42 cycles.\n"); -+ return -1; -+ } -+ } -+ -+ for (i = 0; (i < items) && (chain[i] != 0); ++i) -+ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]); -+ -+ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -+ mdelay(HSR_DELAY_FINAL / 1000); -+ -+ /* reply */ -+ memset(chain, 0, items); -+ -+ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -+ udelay(HSR_DELAY_TRAILING); -+ -+ for (i = 0; i < (items - 1); ++i) { -+ u32 ret; -+ -+ ret = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -+ if (ret != 0) -+ chain[i] = (char)ret; -+ else -+ break; -+ -+ udelay(HSR_DELAY_TRAILING); -+ } -+ -+ if (i <= 1) -+ return 0; -+ -+ err = kstrtoint(chain + 1, 10, &i); -+ if (err) -+ return err; -+ -+ return i; -+} -+ -+int ath9k_hsr_disable(struct ath_hw *ah) -+{ -+ char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0}; -+ int ret; -+ -+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); -+ if ((ret > 0) && (*cmd == 'B')) -+ return 0; -+ -+ return -1; -+} -+ -+int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq) -+{ -+ char cmd[10]; -+ int ret; -+ -+ /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn -+ * 20MHz on invalid values -+ */ -+ if ((bw != 5) && (bw != 10) && (bw != 20) && (bw != 40)) -+ bw = 20; -+ -+ memset(cmd, 0, sizeof(cmd)); -+ *cmd = 'b'; -+ snprintf(cmd + 1, 3, "%02d", bw); -+ -+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); -+ if ((*cmd != 'B') || (ret != bw)) { -+ ATH_DBG_WARN(1, -+ "ath9k_hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d)\n", -+ 'b', bw, *cmd, ret); -+ return -1; -+ } -+ -+ memset(cmd, 0, sizeof(cmd)); -+ *cmd = 'x'; -+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); -+ if (*cmd != 'X') { -+ ATH_DBG_WARN(1, -+ "ath9k_hsr_enable: failed 'x' command -> reply (%d, %d)\n", -+ *cmd, ret); -+ return -1; -+ } -+ -+ memset(cmd, 0, sizeof(cmd)); -+ *cmd = 'm'; -+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); -+ if (*cmd != 'M') { -+ ATH_DBG_WARN(1, -+ "ath9k_hsr_enable: failed 'm' command -> reply (%d, %d)\n", -+ *cmd, ret); -+ return -1; -+ } -+ -+ memset(cmd, 0, sizeof(cmd)); -+ *cmd = 'f'; -+ snprintf(cmd + 1, 6, "%05d", fq); -+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); -+ if ((*cmd != 'F') && (ret != fq)) { -+ ATH_DBG_WARN(1, -+ "ath9k_hsr_enable: failed set frequency -> reply (%d, %d)\n", -+ *cmd, ret); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+int ath9k_hsr_status(struct ath_hw *ah) -+{ -+ char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0}; -+ int ret; -+ -+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); -+ if (*cmd != 'S') { -+ ATH_DBG_WARN(1, "ath9k_hsr_status: returned %d,%d\n", *cmd, -+ ret); -+ return -1; -+ } -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/net/wireless/ath/ath9k/hsr.h -@@ -0,0 +1,48 @@ -+/* -+ * The MIT License (MIT) -+ * -+ * Copyright (c) 2015 Kirill Berezin -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#ifndef HSR_H -+#define HSR_H -+ -+#ifdef CPTCFG_ATH9K_UBNTHSR -+ -+void ath9k_hsr_init(struct ath_hw *ah); -+int ath9k_hsr_disable(struct ath_hw *ah); -+int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq); -+int ath9k_hsr_status(struct ath_hw *ah); -+ -+#else -+static inline void ath9k_hsr_init(struct ath_hw *ah) {} -+ -+static inline int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq) -+{ -+ return 0; -+} -+ -+static inline int ath9k_hsr_disable(struct ath_hw *ah) { return 0; } -+static inline int ath9k_hsr_status(struct ath_hw *ah) { return 0; } -+ -+#endif -+ -+#endif /* HSR_H */ ---- a/drivers/net/wireless/ath/ath9k/main.c -+++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -18,6 +18,7 @@ - #include - #include "ath9k.h" - #include "btcoex.h" -+#include "hsr.h" - - static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 queues, bool drop); -@@ -652,6 +653,7 @@ void ath_reset_work(struct work_struct * - static int ath9k_start(struct ieee80211_hw *hw) - { - struct ath_softc *sc = hw->priv; -+ struct device_node *np = sc->dev->of_node; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan; -@@ -730,6 +732,11 @@ static int ath9k_start(struct ieee80211_ - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - } - -+ if (of_property_read_bool(np, "ubnt,hsr")) { -+ ath9k_hsr_init(ah); -+ ath9k_hsr_disable(ah); -+ } -+ - /* - * Reset key cache to sane defaults (all entries cleared) instead of - * semi-random values after suspend/resume. ---- a/drivers/net/wireless/ath/ath9k/Makefile -+++ b/drivers/net/wireless/ath/ath9k/Makefile -@@ -17,6 +17,7 @@ ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += d - ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o - ath9k-$(CPTCFG_ATH9K_WOW) += wow.o - ath9k-$(CPTCFG_ATH9K_HWRNG) += rng.o -+ath9k-$(CPTCFG_ATH9K_UBNTHSR) += hsr.o - - ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o - ---- a/local-symbols -+++ b/local-symbols -@@ -113,6 +113,7 @@ ATH9K_WOW= - ATH9K_RFKILL= - ATH9K_CHANNEL_CONTEXT= - ATH9K_PCOEM= -+ATH9K_UBNTHSR= - ATH9K_PCI_NO_EEPROM= - ATH9K_HTC= - ATH9K_HTC_DEBUGFS= ---- a/drivers/net/wireless/ath/ath9k/Kconfig -+++ b/drivers/net/wireless/ath/ath9k/Kconfig -@@ -58,6 +58,19 @@ config ATH9K_AHB - Say Y, if you have a SoC with a compatible built-in - wireless MAC. Say N if unsure. - -+config ATH9K_UBNTHSR -+ bool "Ubiquiti UniFi Outdoor Plus HSR support" -+ depends on ATH9K -+ ---help--- -+ This options enables code to control the HSR RF -+ filter in the receive path of the Ubiquiti UniFi -+ Outdoor Plus access point. -+ -+ Say Y if you want to use the access point. The -+ code will only be used if the device is detected, -+ so it does not harm other setup other than occupying -+ a bit of memory. -+ - config ATH9K_DEBUGFS - bool "Atheros ath9k debugging" - depends on ATH9K && DEBUG_FS diff --git a/package/kernel/mac80211/patches/ath/552-ahb_of.patch b/package/kernel/mac80211/patches/ath/552-ahb_of.patch deleted file mode 100644 index 8fd6e4409b..0000000000 --- a/package/kernel/mac80211/patches/ath/552-ahb_of.patch +++ /dev/null @@ -1,337 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/ahb.c -+++ b/drivers/net/wireless/ath/ath9k/ahb.c -@@ -20,7 +20,15 @@ - #include - #include - #include -+#include - #include "ath9k.h" -+#include -+ -+#ifdef CONFIG_OF -+#include -+#include -+#include -+#endif - - static const struct platform_device_id ath9k_platform_id_table[] = { - { -@@ -69,6 +77,242 @@ static const struct ath_bus_ops ath_ahb_ - .eeprom_read = ath_ahb_eeprom_read, - }; - -+#ifdef CONFIG_OF -+ -+#define QCA955X_DDR_CTL_CONFIG 0x108 -+#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23) -+ -+static int of_get_wifi_cal(struct device_node *np, struct ath9k_platform_data *pdata) -+{ -+#ifdef CONFIG_MTD -+ struct device_node *mtd_np = NULL; -+ size_t retlen; -+ int size, ret; -+ struct mtd_info *mtd; -+ const char *part; -+ const __be32 *list; -+ phandle phandle; -+ -+ list = of_get_property(np, "mtd-cal-data", &size); -+ if (!list) -+ return 0; -+ -+ if (size != (2 * sizeof(*list))) -+ return 1; -+ -+ phandle = be32_to_cpup(list++); -+ if (phandle) -+ mtd_np = of_find_node_by_phandle(phandle); -+ -+ if (!mtd_np) -+ return 1; -+ -+ part = of_get_property(mtd_np, "label", NULL); -+ if (!part) -+ part = mtd_np->name; -+ -+ mtd = get_mtd_device_nm(part); -+ if (IS_ERR(mtd)) -+ return 1; -+ -+ ret = mtd_read(mtd, be32_to_cpup(list), sizeof(pdata->eeprom_data), -+ &retlen, (u8*)pdata->eeprom_data); -+ put_mtd_device(mtd); -+ -+#endif -+ return 0; -+} -+ -+static int ar913x_wmac_reset(void) -+{ -+ ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); -+ mdelay(10); -+ -+ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); -+ mdelay(10); -+ -+ return 0; -+} -+ -+static int ar933x_wmac_reset(void) -+{ -+ int retries = 20; -+ -+ ath79_device_reset_set(AR933X_RESET_WMAC); -+ ath79_device_reset_clear(AR933X_RESET_WMAC); -+ -+ while (1) { -+ u32 bootstrap; -+ -+ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); -+ if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0) -+ return 0; -+ -+ if (retries-- == 0) -+ break; -+ -+ udelay(10000); -+ } -+ -+ pr_err("ar933x: WMAC reset timed out"); -+ return -ETIMEDOUT; -+} -+ -+static int qca955x_wmac_reset(void) -+{ -+ int i; -+ -+ /* Try to wait for WMAC DDR activity to stop */ -+ for (i = 0; i < 10; i++) { -+ if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) & -+ QCA955X_DDR_CTL_CONFIG_ACT_WMAC)) -+ break; -+ -+ udelay(10); -+ } -+ -+ ath79_device_reset_set(QCA955X_RESET_RTC); -+ udelay(10); -+ ath79_device_reset_clear(QCA955X_RESET_RTC); -+ udelay(10); -+ -+ return 0; -+} -+ -+enum { -+ AR913X_WMAC = 0, -+ AR933X_WMAC, -+ AR934X_WMAC, -+ QCA953X_WMAC, -+ QCA955X_WMAC, -+ QCA956X_WMAC, -+}; -+ -+static int ar9330_get_soc_revision(void) -+{ -+ if (ath79_soc_rev == 1) -+ return ath79_soc_rev; -+ -+ return 0; -+} -+ -+static int ath79_get_soc_revision(void) -+{ -+ return ath79_soc_rev; -+} -+ -+static const struct of_ath_ahb_data { -+ u16 dev_id; -+ u32 bootstrap_reg; -+ u32 bootstrap_ref; -+ -+ int (*soc_revision)(void); -+ int (*wmac_reset)(void); -+} of_ath_ahb_data[] = { -+ [AR913X_WMAC] = { -+ .dev_id = AR5416_AR9100_DEVID, -+ .wmac_reset = ar913x_wmac_reset, -+ -+ }, -+ [AR933X_WMAC] = { -+ .dev_id = AR9300_DEVID_AR9330, -+ .bootstrap_reg = AR933X_RESET_REG_BOOTSTRAP, -+ .bootstrap_ref = AR933X_BOOTSTRAP_REF_CLK_40, -+ .soc_revision = ar9330_get_soc_revision, -+ .wmac_reset = ar933x_wmac_reset, -+ }, -+ [AR934X_WMAC] = { -+ .dev_id = AR9300_DEVID_AR9340, -+ .bootstrap_reg = AR934X_RESET_REG_BOOTSTRAP, -+ .bootstrap_ref = AR934X_BOOTSTRAP_REF_CLK_40, -+ .soc_revision = ath79_get_soc_revision, -+ }, -+ [QCA953X_WMAC] = { -+ .dev_id = AR9300_DEVID_AR953X, -+ .bootstrap_reg = QCA953X_RESET_REG_BOOTSTRAP, -+ .bootstrap_ref = QCA953X_BOOTSTRAP_REF_CLK_40, -+ .soc_revision = ath79_get_soc_revision, -+ }, -+ [QCA955X_WMAC] = { -+ .dev_id = AR9300_DEVID_QCA955X, -+ .bootstrap_reg = QCA955X_RESET_REG_BOOTSTRAP, -+ .bootstrap_ref = QCA955X_BOOTSTRAP_REF_CLK_40, -+ .wmac_reset = qca955x_wmac_reset, -+ }, -+ [QCA956X_WMAC] = { -+ .dev_id = AR9300_DEVID_QCA956X, -+ .bootstrap_reg = QCA956X_RESET_REG_BOOTSTRAP, -+ .bootstrap_ref = QCA956X_BOOTSTRAP_REF_CLK_40, -+ .soc_revision = ath79_get_soc_revision, -+ }, -+}; -+ -+const struct of_device_id of_ath_ahb_match[] = { -+ { .compatible = "qca,ar9130-wmac", .data = &of_ath_ahb_data[AR913X_WMAC] }, -+ { .compatible = "qca,ar9330-wmac", .data = &of_ath_ahb_data[AR933X_WMAC] }, -+ { .compatible = "qca,ar9340-wmac", .data = &of_ath_ahb_data[AR934X_WMAC] }, -+ { .compatible = "qca,qca9530-wmac", .data = &of_ath_ahb_data[QCA953X_WMAC] }, -+ { .compatible = "qca,qca9550-wmac", .data = &of_ath_ahb_data[QCA955X_WMAC] }, -+ { .compatible = "qca,qca9560-wmac", .data = &of_ath_ahb_data[QCA956X_WMAC] }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, of_ath_ahb_match); -+ -+static int of_ath_ahb_probe(struct platform_device *pdev) -+{ -+ struct ath9k_platform_data *pdata; -+ const struct of_device_id *match; -+ const struct of_ath_ahb_data *data; -+ u8 led_pin; -+ -+ match = of_match_device(of_ath_ahb_match, &pdev->dev); -+ data = (const struct of_ath_ahb_data *)match->data; -+ -+ pdata = dev_get_platdata(&pdev->dev); -+ -+ if (!of_property_read_u8(pdev->dev.of_node, "qca,led-pin", &led_pin)) -+ pdata->led_pin = led_pin; -+ else -+ pdata->led_pin = -1; -+ -+ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-2ghz")) -+ pdata->disable_2ghz = true; -+ -+ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-5ghz")) -+ pdata->disable_5ghz = true; -+ -+ if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo")) -+ pdata->tx_gain_buffalo = true; -+ -+ if (data->wmac_reset) { -+ data->wmac_reset(); -+ pdata->external_reset = data->wmac_reset; -+ } -+ -+ if (data->dev_id == AR9300_DEVID_AR953X) { -+ /* -+ * QCA953x only supports 25MHz refclk. -+ * Some vendors have an invalid bootstrap option -+ * set, which would break the WMAC here. -+ */ -+ pdata->is_clk_25mhz = true; -+ } else if (data->bootstrap_reg && data->bootstrap_ref) { -+ u32 t = ath79_reset_rr(data->bootstrap_reg); -+ if (t & data->bootstrap_ref) -+ pdata->is_clk_25mhz = false; -+ else -+ pdata->is_clk_25mhz = true; -+ } -+ -+ pdata->get_mac_revision = data->soc_revision; -+ -+ if (of_get_wifi_cal(pdev->dev.of_node, pdata)) -+ dev_err(&pdev->dev, "failed to load calibration data from mtd device\n"); -+ -+ return data->dev_id; -+} -+#endif -+ - static int ath_ahb_probe(struct platform_device *pdev) - { - void __iomem *mem; -@@ -80,6 +324,17 @@ static int ath_ahb_probe(struct platform - int ret = 0; - struct ath_hw *ah; - char hw_name[64]; -+ u16 dev_id; -+ -+ if (id) -+ dev_id = id->driver_data; -+ -+#ifdef CONFIG_OF -+ if (pdev->dev.of_node) -+ pdev->dev.platform_data = devm_kzalloc(&pdev->dev, -+ sizeof(struct ath9k_platform_data), -+ GFP_KERNEL); -+#endif - - if (!dev_get_platdata(&pdev->dev)) { - dev_err(&pdev->dev, "no platform data specified\n"); -@@ -122,13 +377,16 @@ static int ath_ahb_probe(struct platform - sc->mem = mem; - sc->irq = irq; - -+#ifdef CONFIG_OF -+ dev_id = of_ath_ahb_probe(pdev); -+#endif - ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); - if (ret) { - dev_err(&pdev->dev, "request_irq failed\n"); - goto err_free_hw; - } - -- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops); -+ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops); - if (ret) { - dev_err(&pdev->dev, "failed to initialize device\n"); - goto err_irq; -@@ -159,6 +417,9 @@ static int ath_ahb_remove(struct platfor - free_irq(sc->irq, sc); - ieee80211_free_hw(sc->hw); - } -+#ifdef CONFIG_OF -+ pdev->dev.platform_data = NULL; -+#endif - - return 0; - } -@@ -168,6 +429,9 @@ static struct platform_driver ath_ahb_dr - .remove = ath_ahb_remove, - .driver = { - .name = "ath9k", -+#ifdef CONFIG_OF -+ .of_match_table = of_ath_ahb_match, -+#endif - }, - .id_table = ath9k_platform_id_table, - }; ---- a/drivers/net/wireless/ath/ath9k/ath9k.h -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include "common.h" - #include "debug.h" -@@ -1012,6 +1013,9 @@ struct ath_softc { - struct ath_hw *sc_ah; - void __iomem *mem; - int irq; -+#ifdef CONFIG_OF -+ struct reset_control *reset; -+#endif - spinlock_t sc_serial_rw; - spinlock_t sc_pm_lock; - spinlock_t sc_pcu_lock; diff --git a/package/kernel/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch b/package/kernel/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch deleted file mode 100644 index 8e0041e3ef..0000000000 --- a/package/kernel/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -654,6 +654,12 @@ static int ath9k_of_init(struct ath_soft - return 0; - } - -+static void ath9k_of_gpio_mask(struct ath_softc *sc) -+{ -+ of_property_read_u32(sc->dev->of_node, "qca,gpio-mask", -+ &sc->sc_ah->caps.gpio_mask); -+} -+ - static int ath9k_init_softc(u16 devid, struct ath_softc *sc, - const struct ath_bus_ops *bus_ops) - { -@@ -757,6 +763,9 @@ static int ath9k_init_softc(u16 devid, s - if (ret) - goto err_hw; - -+ /* GPIO mask quirk */ -+ ath9k_of_gpio_mask(sc); -+ - ret = ath9k_init_queues(sc); - if (ret) - goto err_queues; diff --git a/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch deleted file mode 100644 index e004acc340..0000000000 --- a/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch +++ /dev/null @@ -1,33 +0,0 @@ -From: Sven Eckelmann -Date: Tue, 18 Nov 2014 12:29:28 +0100 -Subject: [PATCH] ath10k: Don't initialize devices asynchronously - -OpenWrt requires all PHYs to be initialized to create the configuration files -during bootup. ath10k violates this because it delays the creation of the PHY -to a not well defined point in the future. - -Forcing the work to be done immediately works around this problem but may also -delay the boot when firmware images cannot be found. - -Signed-off-by: Sven Eckelmann ---- - ---- a/drivers/net/wireless/ath/ath10k/core.c -+++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -3189,6 +3189,16 @@ int ath10k_core_register(struct ath10k * - - queue_work(ar->workqueue, &ar->register_work); - -+ /* OpenWrt requires all PHYs to be initialized to create the -+ * configuration files during bootup. ath10k violates this -+ * because it delays the creation of the PHY to a not well defined -+ * point in the future. -+ * -+ * Forcing the work to be done immediately works around this problem -+ * but may also delay the boot when firmware images cannot be found. -+ */ -+ flush_workqueue(ar->workqueue); -+ - return 0; - } - EXPORT_SYMBOL(ath10k_core_register); diff --git a/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch b/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch deleted file mode 100644 index 8f7a60eec8..0000000000 --- a/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Linus Lüssing -Date: Wed, 5 Feb 2020 20:10:43 +0100 -Subject: ath10k: increase rx buffer size to 2048 - -Before, only frames with a maximum size of 1528 bytes could be -transmitted between two 802.11s nodes. - -For batman-adv for instance, which adds its own header to each frame, -we typically need an MTU of at least 1532 bytes to be able to transmit -without fragmentation. - -This patch now increases the maxmimum frame size from 1528 to 1656 -bytes. - -Tested with two ath10k devices in 802.11s mode, as well as with -batman-adv on top of 802.11s with forwarding disabled. - -Fix originally found and developed by Ben Greear. - -Link: https://github.com/greearb/ath10k-ct/issues/89 -Link: https://github.com/greearb/ath10k-ct/commit/9e5ab25027e0971fa24ccf93373324c08c4e992d -Cc: Ben Greear -Signed-off-by: Linus Lüssing - -Forwarded: https://patchwork.kernel.org/patch/11367055/ - ---- a/drivers/net/wireless/ath/ath10k/htt.h -+++ b/drivers/net/wireless/ath/ath10k/htt.h -@@ -2243,7 +2243,7 @@ struct htt_rx_chan_info { - * Should be: sizeof(struct htt_host_rx_desc) + max rx MSDU size, - * rounded up to a cache line size. - */ --#define HTT_RX_BUF_SIZE 1920 -+#define HTT_RX_BUF_SIZE 2048 - #define HTT_RX_MSDU_SIZE (HTT_RX_BUF_SIZE - (int)sizeof(struct htt_rx_desc)) - - /* Refill a bunch of RX buffers for each refill round so that FW/HW can handle diff --git a/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch deleted file mode 100644 index 74b3292e0c..0000000000 --- a/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -9708,6 +9708,21 @@ static int ath10k_mac_init_rd(struct ath - return 0; - } - -+#ifdef CPTCFG_MAC80211_LEDS -+static const struct ieee80211_tpt_blink ath10k_tpt_blink[] = { -+ { .throughput = 0 * 1024, .blink_time = 334 }, -+ { .throughput = 1 * 1024, .blink_time = 260 }, -+ { .throughput = 2 * 1024, .blink_time = 220 }, -+ { .throughput = 5 * 1024, .blink_time = 190 }, -+ { .throughput = 10 * 1024, .blink_time = 170 }, -+ { .throughput = 25 * 1024, .blink_time = 150 }, -+ { .throughput = 54 * 1024, .blink_time = 130 }, -+ { .throughput = 120 * 1024, .blink_time = 110 }, -+ { .throughput = 265 * 1024, .blink_time = 80 }, -+ { .throughput = 586 * 1024, .blink_time = 50 }, -+}; -+#endif -+ - int ath10k_mac_register(struct ath10k *ar) - { - static const u32 cipher_suites[] = { -@@ -10057,6 +10072,12 @@ int ath10k_mac_register(struct ath10k *a - - ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; - -+#ifdef CPTCFG_MAC80211_LEDS -+ ieee80211_create_tpt_led_trigger(ar->hw, -+ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, -+ ARRAY_SIZE(ath10k_tpt_blink)); -+#endif -+ - ret = ieee80211_register_hw(ar->hw); - if (ret) { - ath10k_err(ar, "failed to register ieee80211: %d\n", ret); diff --git a/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch deleted file mode 100644 index 5e74687826..0000000000 --- a/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch +++ /dev/null @@ -1,609 +0,0 @@ -From: Sebastian Gottschall - -Adds LED and GPIO Control support for 988x, 9887, 9888, 99x0, 9984 based -chipsets with on chipset connected led's using WMI Firmware API. The LED -device will get available named as "ath10k-phyX" at sysfs and can be controlled -with various triggers. adds also debugfs interface for gpio control. - -This patch is specific for OpenWRt base, as is use old backported package -with old wireless source. Support for QCA9984 is removed and a simbol -is added to local-simbol file to export the actually compile the code -with the ATH10K_LEDS simbol. - - -Signed-off-by: Sebastian Gottschall -Reviewed-by: Steve deRosier -[kvalo: major reorg and cleanup] -Signed-off-by: Kalle Valo -Signed-off-by: Ansuel Smith ---- - -v13: - -* only compile tested! - -* fix all checkpatch warnings - -* fix commit log - -* sizeof(struct ath10k_gpiocontrol) -> sizeof(*gpio) - -* unsigned -> unsigned int - -* remove GPIOLIB code, that should be added in a separate patch - -* rename gpio.c to leds.c - -* add leds.h - -* rename some functions: - - ath10k_attach_led() -> ath10k_leds_register() - ath10k_unregister_led() -> ath10k_leds_unregister() - ath10k_reset_led_pin() -> ath10k_leds_start() - -* call ath10k_leds_unregister() before ath10k_thermal_unregister() to preserve ordering - -* call ath10k_leds_start() only from ath10k_core_start() and not from mac.c - -* rename struct ath10k_gpiocontrol as anonymous function under struct - ath10k::leds, no need for memory allocation - -* merge ath10k_add_led() to ath10k_attach_led(), which is it's only caller - -* remove #if IS_ENABLED() checks from most of places, memory savings from those were not worth it - -* Kconfig help text improvement and move it lower in the menu, also don't enable it by default - -* switch to set_brightness_blocking() so that the callback can sleep, - then no need to use ath10k_wmi_cmd_send_nowait() and can take mutex - to access ar->state - -* don't touch ath10k_wmi_pdev_get_temperature() - -* as QCA6174/QCA9377 are not (yet) supported don't add the command to WMI-TLV interface - -* remove debugfs interface, that should be added in another patch - -* cleanup includes - - - drivers/net/wireless/ath/ath10k/Kconfig | 10 +++ - drivers/net/wireless/ath/ath10k/Makefile | 1 + - drivers/net/wireless/ath/ath10k/core.c | 22 +++++++ - drivers/net/wireless/ath/ath10k/core.h | 9 ++- - drivers/net/wireless/ath/ath10k/hw.h | 1 + - drivers/net/wireless/ath/ath10k/leds.c | 103 ++++++++++++++++++++++++++++++ - drivers/net/wireless/ath/ath10k/leds.h | 45 +++++++++++++ - drivers/net/wireless/ath/ath10k/mac.c | 1 + - drivers/net/wireless/ath/ath10k/wmi-ops.h | 32 ++++++++++ - drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 + - drivers/net/wireless/ath/ath10k/wmi.c | 54 ++++++++++++++++ - drivers/net/wireless/ath/ath10k/wmi.h | 35 ++++++++++ - 12 files changed, 314 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/wireless/ath/ath10k/leds.c - create mode 100644 drivers/net/wireless/ath/ath10k/leds.h ---- a/drivers/net/wireless/ath/ath10k/Kconfig -+++ b/drivers/net/wireless/ath/ath10k/Kconfig -@@ -70,6 +70,16 @@ config ATH10K_DEBUGFS - - If unsure, say Y to make it easier to debug problems. - -+config ATH10K_LEDS -+ bool "Atheros ath10k LED support" -+ depends on ATH10K -+ select MAC80211_LEDS -+ select LEDS_CLASS -+ select NEW_LEDS -+ default y -+ ---help--- -+ This option is necessary, if you want LED support for chipset connected led pins. If unsure, say N. -+ - config ATH10K_SPECTRAL - bool "Atheros ath10k spectral scan support" - depends on ATH10K_DEBUGFS ---- a/drivers/net/wireless/ath/ath10k/Makefile -+++ b/drivers/net/wireless/ath/ath10k/Makefile -@@ -19,6 +19,7 @@ ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += - ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o - ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o - ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o -+ath10k_core-$(CPTCFG_ATH10K_LEDS) += leds.o - ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o - ath10k_core-$(CONFIG_PM) += wow.o - ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o ---- a/local-symbols -+++ b/local-symbols -@@ -146,6 +146,7 @@ ATH10K_DEBUG= - ATH10K_DEBUGFS= - ATH10K_SPECTRAL= - ATH10K_THERMAL= -+ATH10K_LEDS= - ATH10K_TRACING= - ATH10K_DFS_CERTIFIED= - WCN36XX= ---- a/drivers/net/wireless/ath/ath10k/core.c -+++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -25,6 +25,7 @@ - #include "testmode.h" - #include "wmi-ops.h" - #include "coredump.h" -+#include "leds.h" - - unsigned int ath10k_debug_mask; - EXPORT_SYMBOL(ath10k_debug_mask); -@@ -61,6 +62,7 @@ static const struct ath10k_hw_params ath - .dev_id = QCA988X_2_0_DEVICE_ID, - .bus = ATH10K_BUS_PCI, - .name = "qca988x hw2.0", -+ .led_pin = 1, - .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, - .uart_pin = 7, - .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, -@@ -130,6 +132,7 @@ static const struct ath10k_hw_params ath - .dev_id = QCA9887_1_0_DEVICE_ID, - .bus = ATH10K_BUS_PCI, - .name = "qca9887 hw1.0", -+ .led_pin = 1, - .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR, - .uart_pin = 7, - .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, -@@ -335,6 +338,7 @@ static const struct ath10k_hw_params ath - .dev_id = QCA99X0_2_0_DEVICE_ID, - .bus = ATH10K_BUS_PCI, - .name = "qca99x0 hw2.0", -+ .led_pin = 17, - .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR, - .uart_pin = 7, - .otp_exe_param = 0x00000700, -@@ -375,6 +379,7 @@ static const struct ath10k_hw_params ath - .dev_id = QCA9984_1_0_DEVICE_ID, - .bus = ATH10K_BUS_PCI, - .name = "qca9984/qca9994 hw1.0", -+ .led_pin = 17, - .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR, - .uart_pin = 7, - .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, -@@ -422,6 +427,7 @@ static const struct ath10k_hw_params ath - .dev_id = QCA9888_2_0_DEVICE_ID, - .bus = ATH10K_BUS_PCI, - .name = "qca9888 hw2.0", -+ .led_pin = 17, - .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR, - .uart_pin = 7, - .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, -@@ -2904,6 +2910,10 @@ int ath10k_core_start(struct ath10k *ar, - goto err_hif_stop; - } - -+ status = ath10k_leds_start(ar); -+ if (status) -+ goto err_hif_stop; -+ - return 0; - - err_hif_stop: -@@ -3162,9 +3172,18 @@ static void ath10k_core_register_work(st - goto err_spectral_destroy; - } - -+ status = ath10k_leds_register(ar); -+ if (status) { -+ ath10k_err(ar, "could not register leds: %d\n", -+ status); -+ goto err_thermal_unregister; -+ } -+ - set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags); - return; - -+err_thermal_unregister: -+ ath10k_thermal_unregister(ar); - err_spectral_destroy: - ath10k_spectral_destroy(ar); - err_debug_destroy: -@@ -3210,6 +3229,8 @@ void ath10k_core_unregister(struct ath10 - if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) - return; - -+ ath10k_leds_unregister(ar); -+ - ath10k_thermal_unregister(ar); - /* Stop spectral before unregistering from mac80211 to remove the - * relayfs debugfs file cleanly. Otherwise the parent debugfs tree ---- a/drivers/net/wireless/ath/ath10k/core.h -+++ b/drivers/net/wireless/ath/ath10k/core.h -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - #include "htt.h" - #include "htc.h" -@@ -1237,6 +1238,13 @@ struct ath10k { - } testmode; - - struct { -+ struct gpio_led wifi_led; -+ struct led_classdev cdev; -+ char label[48]; -+ u32 gpio_state_pin; -+ } leds; -+ -+ struct { - /* protected by data_lock */ - u32 rx_crc_err_drop; - u32 fw_crash_counter; ---- a/drivers/net/wireless/ath/ath10k/hw.h -+++ b/drivers/net/wireless/ath/ath10k/hw.h -@@ -517,6 +517,7 @@ struct ath10k_hw_params { - const char *name; - u32 patch_load_addr; - int uart_pin; -+ int led_pin; - u32 otp_exe_param; - - /* Type of hw cycle counter wraparound logic, for more info ---- /dev/null -+++ b/drivers/net/wireless/ath/ath10k/leds.c -@@ -0,0 +1,103 @@ -+/* -+ * Copyright (c) 2005-2011 Atheros Communications Inc. -+ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. -+ * Copyright (c) 2018 Sebastian Gottschall -+ * Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+ -+#include "core.h" -+#include "wmi.h" -+#include "wmi-ops.h" -+ -+#include "leds.h" -+ -+static int ath10k_leds_set_brightness_blocking(struct led_classdev *led_cdev, -+ enum led_brightness brightness) -+{ -+ struct ath10k *ar = container_of(led_cdev, struct ath10k, -+ leds.cdev); -+ struct gpio_led *led = &ar->leds.wifi_led; -+ -+ mutex_lock(&ar->conf_mutex); -+ -+ if (ar->state != ATH10K_STATE_ON) -+ goto out; -+ -+ ar->leds.gpio_state_pin = (brightness != LED_OFF) ^ led->active_low; -+ ath10k_wmi_gpio_output(ar, led->gpio, ar->leds.gpio_state_pin); -+ -+out: -+ mutex_unlock(&ar->conf_mutex); -+ -+ return 0; -+} -+ -+int ath10k_leds_start(struct ath10k *ar) -+{ -+ if (ar->hw_params.led_pin == 0) -+ /* leds not supported */ -+ return 0; -+ -+ /* under some circumstances, the gpio pin gets reconfigured -+ * to default state by the firmware, so we need to -+ * reconfigure it this behaviour has only ben seen on -+ * QCA9984 and QCA99XX devices so far -+ */ -+ ath10k_wmi_gpio_config(ar, ar->hw_params.led_pin, 0, -+ WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE); -+ ath10k_wmi_gpio_output(ar, ar->hw_params.led_pin, 1); -+ -+ return 0; -+} -+ -+int ath10k_leds_register(struct ath10k *ar) -+{ -+ int ret; -+ -+ if (ar->hw_params.led_pin == 0) -+ /* leds not supported */ -+ return 0; -+ -+ snprintf(ar->leds.label, sizeof(ar->leds.label), "ath10k-%s", -+ wiphy_name(ar->hw->wiphy)); -+ ar->leds.wifi_led.active_low = 1; -+ ar->leds.wifi_led.gpio = ar->hw_params.led_pin; -+ ar->leds.wifi_led.name = ar->leds.label; -+ ar->leds.wifi_led.default_state = LEDS_GPIO_DEFSTATE_KEEP; -+ -+ ar->leds.cdev.name = ar->leds.label; -+ ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking; -+ -+ /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */ -+ ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger; -+ -+ ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+void ath10k_leds_unregister(struct ath10k *ar) -+{ -+ if (ar->hw_params.led_pin == 0) -+ /* leds not supported */ -+ return; -+ -+ led_classdev_unregister(&ar->leds.cdev); -+} -+ ---- /dev/null -+++ b/drivers/net/wireless/ath/ath10k/leds.h -@@ -0,0 +1,41 @@ -+/* -+ * Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+#ifndef _LEDS_H_ -+#define _LEDS_H_ -+ -+#include "core.h" -+ -+#ifdef CPTCFG_ATH10K_LEDS -+void ath10k_leds_unregister(struct ath10k *ar); -+int ath10k_leds_start(struct ath10k *ar); -+int ath10k_leds_register(struct ath10k *ar); -+#else -+static inline void ath10k_leds_unregister(struct ath10k *ar) -+{ -+} -+ -+static inline int ath10k_leds_start(struct ath10k *ar) -+{ -+ return 0; -+} -+ -+static inline int ath10k_leds_register(struct ath10k *ar) -+{ -+ return 0; -+} -+ -+#endif -+#endif /* _LEDS_H_ */ ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -24,6 +24,7 @@ - #include "wmi-tlv.h" - #include "wmi-ops.h" - #include "wow.h" -+#include "leds.h" - - /*********/ - /* Rates */ ---- a/drivers/net/wireless/ath/ath10k/wmi-ops.h -+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h -@@ -226,7 +226,10 @@ struct wmi_ops { - const struct wmi_bb_timing_cfg_arg *arg); - struct sk_buff *(*gen_per_peer_per_tid_cfg)(struct ath10k *ar, - const struct wmi_per_peer_per_tid_cfg_arg *arg); -+ struct sk_buff *(*gen_gpio_config)(struct ath10k *ar, u32 gpio_num, -+ u32 input, u32 pull_type, u32 intr_mode); - -+ struct sk_buff *(*gen_gpio_output)(struct ath10k *ar, u32 gpio_num, u32 set); - }; - - int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); -@@ -1122,6 +1125,35 @@ ath10k_wmi_force_fw_hang(struct ath10k * - return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); - } - -+static inline int ath10k_wmi_gpio_config(struct ath10k *ar, u32 gpio_num, -+ u32 input, u32 pull_type, u32 intr_mode) -+{ -+ struct sk_buff *skb; -+ -+ if (!ar->wmi.ops->gen_gpio_config) -+ return -EOPNOTSUPP; -+ -+ skb = ar->wmi.ops->gen_gpio_config(ar, gpio_num, input, pull_type, intr_mode); -+ if (IS_ERR(skb)) -+ return PTR_ERR(skb); -+ -+ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_config_cmdid); -+} -+ -+static inline int ath10k_wmi_gpio_output(struct ath10k *ar, u32 gpio_num, u32 set) -+{ -+ struct sk_buff *skb; -+ -+ if (!ar->wmi.ops->gen_gpio_config) -+ return -EOPNOTSUPP; -+ -+ skb = ar->wmi.ops->gen_gpio_output(ar, gpio_num, set); -+ if (IS_ERR(skb)) -+ return PTR_ERR(skb); -+ -+ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_output_cmdid); -+} -+ - static inline int - ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level) - { ---- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c -+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c -@@ -4591,6 +4591,8 @@ static const struct wmi_ops wmi_tlv_ops - .gen_echo = ath10k_wmi_tlv_op_gen_echo, - .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf, - .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable, -+ /* .gen_gpio_config not implemented */ -+ /* .gen_gpio_output not implemented */ - }; - - static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { ---- a/drivers/net/wireless/ath/ath10k/wmi.c -+++ b/drivers/net/wireless/ath/ath10k/wmi.c -@@ -7468,6 +7468,49 @@ ath10k_wmi_op_gen_peer_set_param(struct - return skb; - } - -+static struct sk_buff *ath10k_wmi_op_gen_gpio_config(struct ath10k *ar, -+ u32 gpio_num, u32 input, -+ u32 pull_type, u32 intr_mode) -+{ -+ struct wmi_gpio_config_cmd *cmd; -+ struct sk_buff *skb; -+ -+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); -+ if (!skb) -+ return ERR_PTR(-ENOMEM); -+ -+ cmd = (struct wmi_gpio_config_cmd *)skb->data; -+ cmd->pull_type = __cpu_to_le32(pull_type); -+ cmd->gpio_num = __cpu_to_le32(gpio_num); -+ cmd->input = __cpu_to_le32(input); -+ cmd->intr_mode = __cpu_to_le32(intr_mode); -+ -+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_config gpio_num 0x%08x input 0x%08x pull_type 0x%08x intr_mode 0x%08x\n", -+ gpio_num, input, pull_type, intr_mode); -+ -+ return skb; -+} -+ -+static struct sk_buff *ath10k_wmi_op_gen_gpio_output(struct ath10k *ar, -+ u32 gpio_num, u32 set) -+{ -+ struct wmi_gpio_output_cmd *cmd; -+ struct sk_buff *skb; -+ -+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); -+ if (!skb) -+ return ERR_PTR(-ENOMEM); -+ -+ cmd = (struct wmi_gpio_output_cmd *)skb->data; -+ cmd->gpio_num = __cpu_to_le32(gpio_num); -+ cmd->set = __cpu_to_le32(set); -+ -+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_output gpio_num 0x%08x set 0x%08x\n", -+ gpio_num, set); -+ -+ return skb; -+} -+ - static struct sk_buff * - ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id, - enum wmi_sta_ps_mode psmode) -@@ -9156,6 +9199,9 @@ static const struct wmi_ops wmi_ops = { - .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, - .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, - .gen_echo = ath10k_wmi_op_gen_echo, -+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, -+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, -+ - /* .gen_bcn_tmpl not implemented */ - /* .gen_prb_tmpl not implemented */ - /* .gen_p2p_go_bcn_ie not implemented */ -@@ -9226,6 +9272,8 @@ static const struct wmi_ops wmi_10_1_ops - .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, - .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, - .gen_echo = ath10k_wmi_op_gen_echo, -+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, -+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, - /* .gen_bcn_tmpl not implemented */ - /* .gen_prb_tmpl not implemented */ - /* .gen_p2p_go_bcn_ie not implemented */ -@@ -9298,6 +9346,8 @@ static const struct wmi_ops wmi_10_2_ops - .gen_delba_send = ath10k_wmi_op_gen_delba_send, - .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, - .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, -+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, -+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, - /* .gen_pdev_enable_adaptive_cca not implemented */ - }; - -@@ -9369,6 +9419,8 @@ static const struct wmi_ops wmi_10_2_4_o - ath10k_wmi_op_gen_pdev_enable_adaptive_cca, - .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype, - .gen_bb_timing = ath10k_wmi_10_2_4_op_gen_bb_timing, -+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, -+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, - /* .gen_bcn_tmpl not implemented */ - /* .gen_prb_tmpl not implemented */ - /* .gen_p2p_go_bcn_ie not implemented */ -@@ -9450,6 +9502,8 @@ static const struct wmi_ops wmi_10_4_ops - .gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info, - .gen_echo = ath10k_wmi_op_gen_echo, - .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, -+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, -+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, - }; - - int ath10k_wmi_attach(struct ath10k *ar) ---- a/drivers/net/wireless/ath/ath10k/wmi.h -+++ b/drivers/net/wireless/ath/ath10k/wmi.h -@@ -3027,6 +3027,41 @@ enum wmi_10_4_feature_mask { - - }; - -+/* WMI_GPIO_CONFIG_CMDID */ -+enum { -+ WMI_GPIO_PULL_NONE, -+ WMI_GPIO_PULL_UP, -+ WMI_GPIO_PULL_DOWN, -+}; -+ -+enum { -+ WMI_GPIO_INTTYPE_DISABLE, -+ WMI_GPIO_INTTYPE_RISING_EDGE, -+ WMI_GPIO_INTTYPE_FALLING_EDGE, -+ WMI_GPIO_INTTYPE_BOTH_EDGE, -+ WMI_GPIO_INTTYPE_LEVEL_LOW, -+ WMI_GPIO_INTTYPE_LEVEL_HIGH -+}; -+ -+/* WMI_GPIO_CONFIG_CMDID */ -+struct wmi_gpio_config_cmd { -+ __le32 gpio_num; /* GPIO number to be setup */ -+ __le32 input; /* 0 - Output/ 1 - Input */ -+ __le32 pull_type; /* Pull type defined above */ -+ __le32 intr_mode; /* Interrupt mode defined above (Input) */ -+} __packed; -+ -+/* WMI_GPIO_OUTPUT_CMDID */ -+struct wmi_gpio_output_cmd { -+ __le32 gpio_num; /* GPIO number to be setup */ -+ __le32 set; /* Set the GPIO pin*/ -+} __packed; -+ -+/* WMI_GPIO_INPUT_EVENTID */ -+struct wmi_gpio_input_event { -+ __le32 gpio_num; /* GPIO number which changed state */ -+} __packed; -+ - struct wmi_ext_resource_config_10_4_cmd { - /* contains enum wmi_host_platform_type */ - __le32 host_platform_config; diff --git a/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch b/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch deleted file mode 100644 index 6da7bfa725..0000000000 --- a/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 79c9d7aabae1d1da9eea97d83b61e1517a8a2221 Mon Sep 17 00:00:00 2001 -From: Mathias Kresin -Date: Fri, 22 Jun 2018 18:59:44 +0200 -Subject: [PATCH] ath10k: use tpt LED trigger by default - -Use the tpt LED trigger for each created phy led. Ths way LEDs attached -to the ath10k GPIO pins are indicating the phy status and blink on -traffic. - -Signed-off-by: Mathias Kresin ---- - drivers/net/wireless/ath/ath10k/core.h | 4 ++++ - drivers/net/wireless/ath/ath10k/leds.c | 4 +--- - drivers/net/wireless/ath/ath10k/mac.c | 2 +- - 3 files changed, 6 insertions(+), 4 deletions(-) - ---- a/drivers/net/wireless/ath/ath10k/core.h -+++ b/drivers/net/wireless/ath/ath10k/core.h -@@ -1290,6 +1290,10 @@ struct ath10k { - bool coex_support; - int coex_gpio_pin; - -+#ifdef CPTCFG_MAC80211_LEDS -+ const char *led_default_trigger; -+#endif -+ - /* must be last */ - u8 drv_priv[] __aligned(sizeof(void *)); - }; ---- a/drivers/net/wireless/ath/ath10k/leds.c -+++ b/drivers/net/wireless/ath/ath10k/leds.c -@@ -81,9 +81,7 @@ int ath10k_leds_register(struct ath10k * - - ar->leds.cdev.name = ar->leds.label; - ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking; -- -- /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */ -- ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger; -+ ar->leds.cdev.default_trigger = ar->led_default_trigger; - - ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev); - if (ret) ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -10074,7 +10074,7 @@ int ath10k_mac_register(struct ath10k *a - ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; - - #ifdef CPTCFG_MAC80211_LEDS -- ieee80211_create_tpt_led_trigger(ar->hw, -+ ar->led_default_trigger = ieee80211_create_tpt_led_trigger(ar->hw, - IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, - ARRAY_SIZE(ath10k_tpt_blink)); - #endif diff --git a/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch b/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch deleted file mode 100644 index e951e011e6..0000000000 --- a/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch +++ /dev/null @@ -1,49 +0,0 @@ -From: Sven Eckelmann -Date: Tue, 11 Jun 2019 13:58:35 +0200 -Subject: ath10k: fix max antenna gain unit - -Most of the txpower for the ath10k firmware is stored as twicepower (0.5 dB -steps). This isn't the case for max_antenna_gain - which is still expected -by the firmware as dB. - -The firmware is converting it from dB to the internal (twicepower) -representation when it calculates the limits of a channel. This can be seen -in tpc_stats when configuring "12" as max_antenna_gain. Instead of the -expected 12 (6 dB), the tpc_stats shows 24 (12 dB). - -Tested on QCA9888 and IPQ4019 with firmware 10.4-3.5.3-00057. - -Fixes: 02256930d9b8 ("ath10k: use proper tx power unit") -Signed-off-by: Sven Eckelmann - -Forwarded: https://patchwork.kernel.org/patch/10986723/ - ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -1038,7 +1038,7 @@ static int ath10k_monitor_vdev_start(str - arg.channel.min_power = 0; - arg.channel.max_power = channel->max_power * 2; - arg.channel.max_reg_power = channel->max_reg_power * 2; -- arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; -+ arg.channel.max_antenna_gain = channel->max_antenna_gain; - - reinit_completion(&ar->vdev_setup_done); - reinit_completion(&ar->vdev_delete_done); -@@ -1484,7 +1484,7 @@ static int ath10k_vdev_start_restart(str - arg.channel.min_power = 0; - arg.channel.max_power = chandef->chan->max_power * 2; - arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; -- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2; -+ arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; - - if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { - arg.ssid = arvif->u.ap.ssid; -@@ -3255,7 +3255,7 @@ static int ath10k_update_channel_list(st - ch->min_power = 0; - ch->max_power = channel->max_power * 2; - ch->max_reg_power = channel->max_reg_power * 2; -- ch->max_antenna_gain = channel->max_antenna_gain * 2; -+ ch->max_antenna_gain = channel->max_antenna_gain; - ch->reg_class_id = 0; /* FIXME */ - - /* FIXME: why use only legacy modes, why not any diff --git a/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch b/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch deleted file mode 100644 index a149ce1216..0000000000 --- a/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch +++ /dev/null @@ -1,101 +0,0 @@ -From: Sven Eckelmann -Date: Wed, 28 Nov 2018 16:16:27 +0100 -Subject: ath10k: adjust tx power reduction for US regulatory domain - -FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4): - -> (4) The conducted output power limit -> specified in paragraph (b) of this section -> is based on the use of antennas -> with directional gains that do not exceed -> 6 dBi. Except as shown in paragraph -> (c) of this section, if transmitting -> antennas of directional gain greater -> than 6 dBi are used, the conducted -> output power from the intentional radiator -> shall be reduced below the stated -> values in paragraphs (b)(1), (b)(2), -> and (b)(3) of this section, as appropriate, -> by the amount in dB that the -> directional gain of the antenna exceeds -> 6 dBi. - -https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf - -Signed-off-by: Sven Eckelmann - -Forwarded: no - ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -1006,6 +1006,40 @@ static inline int ath10k_vdev_setup_sync - return ar->last_wmi_vdev_start_status; - } - -+static u32 ath10k_get_max_antenna_gain(struct ath10k *ar, -+ u32 ch_max_antenna_gain) -+{ -+ u32 max_antenna_gain; -+ -+ if (ar->dfs_detector && ar->dfs_detector->region == NL80211_DFS_FCC) { -+ /* FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4): -+ * -+ * > (4) The conducted output power limit -+ * > specified in paragraph (b) of this section -+ * > is based on the use of antennas -+ * > with directional gains that do not exceed -+ * > 6 dBi. Except as shown in paragraph -+ * > (c) of this section, if transmitting -+ * > antennas of directional gain greater -+ * > than 6 dBi are used, the conducted -+ * > output power from the intentional radiator -+ * > shall be reduced below the stated -+ * > values in paragraphs (b)(1), (b)(2), -+ * > and (b)(3) of this section, as appropriate, -+ * > by the amount in dB that the -+ * > directional gain of the antenna exceeds -+ * > 6 dBi. -+ * -+ * https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf -+ */ -+ max_antenna_gain = 6; -+ } else { -+ max_antenna_gain = 0; -+ } -+ -+ return max(ch_max_antenna_gain, max_antenna_gain); -+} -+ - static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) - { - struct cfg80211_chan_def *chandef = NULL; -@@ -1038,7 +1072,8 @@ static int ath10k_monitor_vdev_start(str - arg.channel.min_power = 0; - arg.channel.max_power = channel->max_power * 2; - arg.channel.max_reg_power = channel->max_reg_power * 2; -- arg.channel.max_antenna_gain = channel->max_antenna_gain; -+ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, -+ channel->max_antenna_gain); - - reinit_completion(&ar->vdev_setup_done); - reinit_completion(&ar->vdev_delete_done); -@@ -1484,7 +1519,8 @@ static int ath10k_vdev_start_restart(str - arg.channel.min_power = 0; - arg.channel.max_power = chandef->chan->max_power * 2; - arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; -- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; -+ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, -+ chandef->chan->max_antenna_gain); - - if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { - arg.ssid = arvif->u.ap.ssid; -@@ -3255,7 +3291,8 @@ static int ath10k_update_channel_list(st - ch->min_power = 0; - ch->max_power = channel->max_power * 2; - ch->max_reg_power = channel->max_reg_power * 2; -- ch->max_antenna_gain = channel->max_antenna_gain; -+ ch->max_antenna_gain = ath10k_get_max_antenna_gain(ar, -+ channel->max_antenna_gain); - ch->reg_class_id = 0; /* FIXME */ - - /* FIXME: why use only legacy modes, why not any diff --git a/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch b/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch new file mode 100644 index 0000000000..55d48daa79 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch @@ -0,0 +1,47 @@ +--- a/drivers/net/wireless/ath/ath10k/Kconfig ++++ b/drivers/net/wireless/ath/ath10k/Kconfig +@@ -86,6 +86,12 @@ config ATH10K_TRACING + help + Select this to ath10k use tracing infrastructure. + ++config ATH10K_THERMAL ++ bool "Atheros ath10k thermal monitoring support" ++ depends on THERMAL ++ ---help--- ++ Select this to ath10k use hwmon for thermal measurement. ++ + config ATH10K_DFS_CERTIFIED + bool "Atheros DFS support for certified platforms" + depends on ATH10K && CFG80211_CERTIFICATION_ONUS +--- a/drivers/net/wireless/ath/ath10k/Makefile ++++ b/drivers/net/wireless/ath/ath10k/Makefile +@@ -18,7 +18,7 @@ ath10k_core-y += mac.o \ + ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += spectral.o + ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o + ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o +-ath10k_core-$(CONFIG_THERMAL) += thermal.o ++ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o + ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o + ath10k_core-$(CONFIG_PM) += wow.o + ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o +--- a/drivers/net/wireless/ath/ath10k/thermal.h ++++ b/drivers/net/wireless/ath/ath10k/thermal.h +@@ -25,7 +25,7 @@ struct ath10k_thermal { + int temperature; + }; + +-#if IS_REACHABLE(CONFIG_THERMAL) ++#if IS_REACHABLE(CPTCFG_ATH10K_THERMAL) + int ath10k_thermal_register(struct ath10k *ar); + void ath10k_thermal_unregister(struct ath10k *ar); + void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature); +--- a/local-symbols ++++ b/local-symbols +@@ -143,6 +143,7 @@ ATH10K_SNOC= + ATH10K_DEBUG= + ATH10K_DEBUGFS= + ATH10K_SPECTRAL= ++ATH10K_THERMAL= + ATH10K_TRACING= + ATH10K_DFS_CERTIFIED= + WCN36XX= diff --git a/package/kernel/mac80211/patches/ath10k/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch b/package/kernel/mac80211/patches/ath10k/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch new file mode 100644 index 0000000000..0ce49b22ab --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch @@ -0,0 +1,180 @@ +From: Wen Gong +Date: Tue, 11 May 2021 20:02:52 +0200 +Subject: [PATCH] ath10k: add CCMP PN replay protection for fragmented + frames for PCIe + +PN replay check for not fragmented frames is finished in the firmware, +but this was not done for fragmented frames when ath10k is used with +QCA6174/QCA6377 PCIe. mac80211 has the function +ieee80211_rx_h_defragment() for PN replay check for fragmented frames, +but this does not get checked with QCA6174 due to the +ieee80211_has_protected() condition not matching the cleared Protected +bit case. + +Validate the PN of received fragmented frames within ath10k when CCMP is +used and drop the fragment if the PN is not correct (incremented by +exactly one from the previous fragment). This applies only for +QCA6174/QCA6377 PCIe. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 + +Cc: stable@vger.kernel.org +Signed-off-by: Wen Gong +Signed-off-by: Jouni Malinen +Signed-off-by: Johannes Berg +--- + +--- a/drivers/net/wireless/ath/ath10k/htt.h ++++ b/drivers/net/wireless/ath/ath10k/htt.h +@@ -846,6 +846,7 @@ enum htt_security_types { + + #define ATH10K_HTT_TXRX_PEER_SECURITY_MAX 2 + #define ATH10K_TXRX_NUM_EXT_TIDS 19 ++#define ATH10K_TXRX_NON_QOS_TID 16 + + enum htt_security_flags { + #define HTT_SECURITY_TYPE_MASK 0x7F +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -1746,16 +1746,87 @@ static void ath10k_htt_rx_h_csum_offload + msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu); + } + ++static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb, ++ u16 offset, ++ enum htt_rx_mpdu_encrypt_type enctype) ++{ ++ struct ieee80211_hdr *hdr; ++ u64 pn = 0; ++ u8 *ehdr; ++ ++ hdr = (struct ieee80211_hdr *)(skb->data + offset); ++ ehdr = skb->data + offset + ieee80211_hdrlen(hdr->frame_control); ++ ++ if (enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) { ++ pn = ehdr[0]; ++ pn |= (u64)ehdr[1] << 8; ++ pn |= (u64)ehdr[4] << 16; ++ pn |= (u64)ehdr[5] << 24; ++ pn |= (u64)ehdr[6] << 32; ++ pn |= (u64)ehdr[7] << 40; ++ } ++ return pn; ++} ++ ++static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar, ++ struct sk_buff *skb, ++ u16 peer_id, ++ u16 offset, ++ enum htt_rx_mpdu_encrypt_type enctype) ++{ ++ struct ath10k_peer *peer; ++ union htt_rx_pn_t *last_pn, new_pn = {0}; ++ struct ieee80211_hdr *hdr; ++ bool more_frags; ++ u8 tid, frag_number; ++ u32 seq; ++ ++ peer = ath10k_peer_find_by_id(ar, peer_id); ++ if (!peer) { ++ ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid peer for frag pn check\n"); ++ return false; ++ } ++ ++ hdr = (struct ieee80211_hdr *)(skb->data + offset); ++ if (ieee80211_is_data_qos(hdr->frame_control)) ++ tid = ieee80211_get_tid(hdr); ++ else ++ tid = ATH10K_TXRX_NON_QOS_TID; ++ ++ last_pn = &peer->frag_tids_last_pn[tid]; ++ new_pn.pn48 = ath10k_htt_rx_h_get_pn(ar, skb, offset, enctype); ++ more_frags = ieee80211_has_morefrags(hdr->frame_control); ++ frag_number = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; ++ seq = (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; ++ ++ if (frag_number == 0) { ++ last_pn->pn48 = new_pn.pn48; ++ peer->frag_tids_seq[tid] = seq; ++ } else { ++ if (seq != peer->frag_tids_seq[tid]) ++ return false; ++ ++ if (new_pn.pn48 != last_pn->pn48 + 1) ++ return false; ++ ++ last_pn->pn48 = new_pn.pn48; ++ } ++ ++ return true; ++} ++ + static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, + struct sk_buff_head *amsdu, + struct ieee80211_rx_status *status, + bool fill_crypt_header, + u8 *rx_hdr, +- enum ath10k_pkt_rx_err *err) ++ enum ath10k_pkt_rx_err *err, ++ u16 peer_id, ++ bool frag) + { + struct sk_buff *first; + struct sk_buff *last; +- struct sk_buff *msdu; ++ struct sk_buff *msdu, *temp; + struct htt_rx_desc *rxd; + struct ieee80211_hdr *hdr; + enum htt_rx_mpdu_encrypt_type enctype; +@@ -1768,6 +1839,7 @@ static void ath10k_htt_rx_h_mpdu(struct + bool is_decrypted; + bool is_mgmt; + u32 attention; ++ bool frag_pn_check = true; + + if (skb_queue_empty(amsdu)) + return; +@@ -1866,6 +1938,24 @@ static void ath10k_htt_rx_h_mpdu(struct + } + + skb_queue_walk(amsdu, msdu) { ++ if (frag && !fill_crypt_header && is_decrypted && ++ enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) ++ frag_pn_check = ath10k_htt_rx_h_frag_pn_check(ar, ++ msdu, ++ peer_id, ++ 0, ++ enctype); ++ ++ if (!frag_pn_check) { ++ /* Discard the fragment with invalid PN */ ++ temp = msdu->prev; ++ __skb_unlink(msdu, amsdu); ++ dev_kfree_skb_any(msdu); ++ msdu = temp; ++ frag_pn_check = true; ++ continue; ++ } ++ + ath10k_htt_rx_h_csum_offload(msdu); + ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype, + is_decrypted); +@@ -2071,7 +2161,8 @@ static int ath10k_htt_rx_handle_amsdu(st + ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt); + + ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter); +- ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err); ++ ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err, 0, ++ false); + msdus_to_queue = skb_queue_len(&amsdu); + ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status); + +@@ -3027,7 +3118,7 @@ static int ath10k_htt_rx_in_ord_ind(stru + ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); + ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL); + ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL, +- NULL); ++ NULL, peer_id, frag); + ath10k_htt_rx_h_enqueue(ar, &amsdu, status); + break; + case -EAGAIN: diff --git a/package/kernel/mac80211/patches/ath10k/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch b/package/kernel/mac80211/patches/ath10k/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch new file mode 100644 index 0000000000..7288c66612 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch @@ -0,0 +1,66 @@ +From: Wen Gong +Date: Tue, 11 May 2021 20:02:53 +0200 +Subject: [PATCH] ath10k: drop fragments with multicast DA for PCIe + +Fragmentation is not used with multicast frames. Discard unexpected +fragments with multicast DA. This fixes CVE-2020-26145. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 + +Cc: stable@vger.kernel.org +Signed-off-by: Wen Gong +Signed-off-by: Jouni Malinen +Signed-off-by: Johannes Berg +--- + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -1768,6 +1768,16 @@ static u64 ath10k_htt_rx_h_get_pn(struct + return pn; + } + ++static bool ath10k_htt_rx_h_frag_multicast_check(struct ath10k *ar, ++ struct sk_buff *skb, ++ u16 offset) ++{ ++ struct ieee80211_hdr *hdr; ++ ++ hdr = (struct ieee80211_hdr *)(skb->data + offset); ++ return !is_multicast_ether_addr(hdr->addr1); ++} ++ + static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar, + struct sk_buff *skb, + u16 peer_id, +@@ -1839,7 +1849,7 @@ static void ath10k_htt_rx_h_mpdu(struct + bool is_decrypted; + bool is_mgmt; + u32 attention; +- bool frag_pn_check = true; ++ bool frag_pn_check = true, multicast_check = true; + + if (skb_queue_empty(amsdu)) + return; +@@ -1946,13 +1956,20 @@ static void ath10k_htt_rx_h_mpdu(struct + 0, + enctype); + +- if (!frag_pn_check) { +- /* Discard the fragment with invalid PN */ ++ if (frag) ++ multicast_check = ath10k_htt_rx_h_frag_multicast_check(ar, ++ msdu, ++ 0); ++ ++ if (!frag_pn_check || !multicast_check) { ++ /* Discard the fragment with invalid PN or multicast DA ++ */ + temp = msdu->prev; + __skb_unlink(msdu, amsdu); + dev_kfree_skb_any(msdu); + msdu = temp; + frag_pn_check = true; ++ multicast_check = true; + continue; + } + diff --git a/package/kernel/mac80211/patches/ath10k/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch b/package/kernel/mac80211/patches/ath10k/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch new file mode 100644 index 0000000000..85d9ce65e2 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch @@ -0,0 +1,40 @@ +From: Wen Gong +Date: Tue, 11 May 2021 20:02:54 +0200 +Subject: [PATCH] ath10k: drop fragments with multicast DA for SDIO + +Fragmentation is not used with multicast frames. Discard unexpected +fragments with multicast DA. This fixes CVE-2020-26145. + +Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049 + +Cc: stable@vger.kernel.org +Signed-off-by: Wen Gong +Signed-off-by: Jouni Malinen +Signed-off-by: Johannes Berg +--- + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -2617,6 +2617,13 @@ static bool ath10k_htt_rx_proc_rx_frag_i + rx_desc = (struct htt_hl_rx_desc *)(skb->data + tot_hdr_len); + rx_desc_info = __le32_to_cpu(rx_desc->info); + ++ hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len); ++ ++ if (is_multicast_ether_addr(hdr->addr1)) { ++ /* Discard the fragment with multicast DA */ ++ goto err; ++ } ++ + if (!MS(rx_desc_info, HTT_RX_DESC_HL_INFO_ENCRYPTED)) { + spin_unlock_bh(&ar->data_lock); + return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb, +@@ -2624,8 +2631,6 @@ static bool ath10k_htt_rx_proc_rx_frag_i + HTT_RX_NON_TKIP_MIC); + } + +- hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len); +- + if (ieee80211_has_retry(hdr->frame_control)) + goto err; + diff --git a/package/kernel/mac80211/patches/ath10k/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch b/package/kernel/mac80211/patches/ath10k/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch new file mode 100644 index 0000000000..03bce4231b --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch @@ -0,0 +1,54 @@ +From: Wen Gong +Date: Tue, 11 May 2021 20:02:55 +0200 +Subject: [PATCH] ath10k: drop MPDU which has discard flag set by firmware + for SDIO + +When the discard flag is set by the firmware for an MPDU, it should be +dropped. This allows a mitigation for CVE-2020-24588 to be implemented +in the firmware. + +Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049 + +Cc: stable@vger.kernel.org +Signed-off-by: Wen Gong +Signed-off-by: Jouni Malinen +Signed-off-by: Johannes Berg +--- + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -2312,6 +2312,11 @@ static bool ath10k_htt_rx_proc_rx_ind_hl + fw_desc = &rx->fw_desc; + rx_desc_len = fw_desc->len; + ++ if (fw_desc->u.bits.discard) { ++ ath10k_dbg(ar, ATH10K_DBG_HTT, "htt discard mpdu\n"); ++ goto err; ++ } ++ + /* I have not yet seen any case where num_mpdu_ranges > 1. + * qcacld does not seem handle that case either, so we introduce the + * same limitiation here as well. +--- a/drivers/net/wireless/ath/ath10k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath10k/rx_desc.h +@@ -1282,7 +1282,19 @@ struct fw_rx_desc_base { + #define FW_RX_DESC_UDP (1 << 6) + + struct fw_rx_desc_hl { +- u8 info0; ++ union { ++ struct { ++ u8 discard:1, ++ forward:1, ++ any_err:1, ++ dup_err:1, ++ reserved:1, ++ inspect:1, ++ extension:2; ++ } bits; ++ u8 info0; ++ } u; ++ + u8 version; + u8 len; + u8 flags; diff --git a/package/kernel/mac80211/patches/ath10k/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch b/package/kernel/mac80211/patches/ath10k/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch new file mode 100644 index 0000000000..da9d6802bd --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch @@ -0,0 +1,48 @@ +From: Wen Gong +Date: Tue, 11 May 2021 20:02:56 +0200 +Subject: [PATCH] ath10k: Fix TKIP Michael MIC verification for PCIe + +TKIP Michael MIC was not verified properly for PCIe cases since the +validation steps in ieee80211_rx_h_michael_mic_verify() in mac80211 did +not get fully executed due to unexpected flag values in +ieee80211_rx_status. + +Fix this by setting the flags property to meet mac80211 expectations for +performing Michael MIC validation there. This fixes CVE-2020-26141. It +does the same as ath10k_htt_rx_proc_rx_ind_hl() for SDIO which passed +MIC verification case. This applies only to QCA6174/QCA9377 PCIe. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 + +Cc: stable@vger.kernel.org +Signed-off-by: Wen Gong +Signed-off-by: Jouni Malinen +Signed-off-by: Johannes Berg +--- + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -1974,6 +1974,11 @@ static void ath10k_htt_rx_h_mpdu(struct + } + + ath10k_htt_rx_h_csum_offload(msdu); ++ ++ if (frag && !fill_crypt_header && ++ enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) ++ status->flag &= ~RX_FLAG_MMIC_STRIPPED; ++ + ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype, + is_decrypted); + +@@ -1991,6 +1996,11 @@ static void ath10k_htt_rx_h_mpdu(struct + + hdr = (void *)msdu->data; + hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); ++ ++ if (frag && !fill_crypt_header && ++ enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) ++ status->flag &= ~RX_FLAG_IV_STRIPPED & ++ ~RX_FLAG_MMIC_STRIPPED; + } + } + diff --git a/package/kernel/mac80211/patches/ath10k/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch b/package/kernel/mac80211/patches/ath10k/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch new file mode 100644 index 0000000000..0bdbed78d5 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch @@ -0,0 +1,109 @@ +From: Sriram R +Date: Tue, 11 May 2021 20:02:57 +0200 +Subject: [PATCH] ath10k: Validate first subframe of A-MSDU before + processing the list + +In certain scenarios a normal MSDU can be received as an A-MSDU when +the A-MSDU present bit of a QoS header gets flipped during reception. +Since this bit is unauthenticated, the hardware crypto engine can pass +the frame to the driver without any error indication. + +This could result in processing unintended subframes collected in the +A-MSDU list. Hence, validate A-MSDU list by checking if the first frame +has a valid subframe header. + +Comparing the non-aggregated MSDU and an A-MSDU, the fields of the first +subframe DA matches the LLC/SNAP header fields of a normal MSDU. +In order to avoid processing such frames, add a validation to +filter such A-MSDU frames where the first subframe header DA matches +with the LLC/SNAP header pattern. + +Tested-on: QCA9984 hw1.0 PCI 10.4-3.10-00047 + +Cc: stable@vger.kernel.org +Signed-off-by: Sriram R +Signed-off-by: Jouni Malinen +Signed-off-by: Johannes Berg +--- + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -2108,14 +2108,62 @@ static void ath10k_htt_rx_h_unchain(stru + ath10k_unchain_msdu(amsdu, unchain_cnt); + } + ++static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar, ++ struct sk_buff_head *amsdu) ++{ ++ u8 *subframe_hdr; ++ struct sk_buff *first; ++ bool is_first, is_last; ++ struct htt_rx_desc *rxd; ++ struct ieee80211_hdr *hdr; ++ size_t hdr_len, crypto_len; ++ enum htt_rx_mpdu_encrypt_type enctype; ++ int bytes_aligned = ar->hw_params.decap_align_bytes; ++ ++ first = skb_peek(amsdu); ++ ++ rxd = (void *)first->data - sizeof(*rxd); ++ hdr = (void *)rxd->rx_hdr_status; ++ ++ is_first = !!(rxd->msdu_end.common.info0 & ++ __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)); ++ is_last = !!(rxd->msdu_end.common.info0 & ++ __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)); ++ ++ /* Return in case of non-aggregated msdu */ ++ if (is_first && is_last) ++ return true; ++ ++ /* First msdu flag is not set for the first msdu of the list */ ++ if (!is_first) ++ return false; ++ ++ enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), ++ RX_MPDU_START_INFO0_ENCRYPT_TYPE); ++ ++ hdr_len = ieee80211_hdrlen(hdr->frame_control); ++ crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype); ++ ++ subframe_hdr = (u8 *)hdr + round_up(hdr_len, bytes_aligned) + ++ crypto_len; ++ ++ /* Validate if the amsdu has a proper first subframe. ++ * There are chances a single msdu can be received as amsdu when ++ * the unauthenticated amsdu flag of a QoS header ++ * gets flipped in non-SPP AMSDU's, in such cases the first ++ * subframe has llc/snap header in place of a valid da. ++ * return false if the da matches rfc1042 pattern ++ */ ++ if (ether_addr_equal(subframe_hdr, rfc1042_header)) ++ return false; ++ ++ return true; ++} ++ + static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, + struct sk_buff_head *amsdu, + struct ieee80211_rx_status *rx_status) + { +- /* FIXME: It might be a good idea to do some fuzzy-testing to drop +- * invalid/dangerous frames. +- */ +- + if (!rx_status->freq) { + ath10k_dbg(ar, ATH10K_DBG_HTT, "no channel configured; ignoring frame(s)!\n"); + return false; +@@ -2126,6 +2174,11 @@ static bool ath10k_htt_rx_amsdu_allowed( + return false; + } + ++ if (!ath10k_htt_rx_validate_amsdu(ar, amsdu)) { ++ ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid amsdu received\n"); ++ return false; ++ } ++ + return true; + } + diff --git a/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch new file mode 100644 index 0000000000..e004acc340 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch @@ -0,0 +1,33 @@ +From: Sven Eckelmann +Date: Tue, 18 Nov 2014 12:29:28 +0100 +Subject: [PATCH] ath10k: Don't initialize devices asynchronously + +OpenWrt requires all PHYs to be initialized to create the configuration files +during bootup. ath10k violates this because it delays the creation of the PHY +to a not well defined point in the future. + +Forcing the work to be done immediately works around this problem but may also +delay the boot when firmware images cannot be found. + +Signed-off-by: Sven Eckelmann +--- + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -3189,6 +3189,16 @@ int ath10k_core_register(struct ath10k * + + queue_work(ar->workqueue, &ar->register_work); + ++ /* OpenWrt requires all PHYs to be initialized to create the ++ * configuration files during bootup. ath10k violates this ++ * because it delays the creation of the PHY to a not well defined ++ * point in the future. ++ * ++ * Forcing the work to be done immediately works around this problem ++ * but may also delay the boot when firmware images cannot be found. ++ */ ++ flush_workqueue(ar->workqueue); ++ + return 0; + } + EXPORT_SYMBOL(ath10k_core_register); diff --git a/package/kernel/mac80211/patches/ath10k/922-ath10k-increase-rx-buffer-size-to-2048.patch b/package/kernel/mac80211/patches/ath10k/922-ath10k-increase-rx-buffer-size-to-2048.patch new file mode 100644 index 0000000000..8f7a60eec8 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/922-ath10k-increase-rx-buffer-size-to-2048.patch @@ -0,0 +1,37 @@ +From: Linus Lüssing +Date: Wed, 5 Feb 2020 20:10:43 +0100 +Subject: ath10k: increase rx buffer size to 2048 + +Before, only frames with a maximum size of 1528 bytes could be +transmitted between two 802.11s nodes. + +For batman-adv for instance, which adds its own header to each frame, +we typically need an MTU of at least 1532 bytes to be able to transmit +without fragmentation. + +This patch now increases the maxmimum frame size from 1528 to 1656 +bytes. + +Tested with two ath10k devices in 802.11s mode, as well as with +batman-adv on top of 802.11s with forwarding disabled. + +Fix originally found and developed by Ben Greear. + +Link: https://github.com/greearb/ath10k-ct/issues/89 +Link: https://github.com/greearb/ath10k-ct/commit/9e5ab25027e0971fa24ccf93373324c08c4e992d +Cc: Ben Greear +Signed-off-by: Linus Lüssing + +Forwarded: https://patchwork.kernel.org/patch/11367055/ + +--- a/drivers/net/wireless/ath/ath10k/htt.h ++++ b/drivers/net/wireless/ath/ath10k/htt.h +@@ -2243,7 +2243,7 @@ struct htt_rx_chan_info { + * Should be: sizeof(struct htt_host_rx_desc) + max rx MSDU size, + * rounded up to a cache line size. + */ +-#define HTT_RX_BUF_SIZE 1920 ++#define HTT_RX_BUF_SIZE 2048 + #define HTT_RX_MSDU_SIZE (HTT_RX_BUF_SIZE - (int)sizeof(struct htt_rx_desc)) + + /* Refill a bunch of RX buffers for each refill round so that FW/HW can handle diff --git a/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch new file mode 100644 index 0000000000..74b3292e0c --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch @@ -0,0 +1,37 @@ +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -9708,6 +9708,21 @@ static int ath10k_mac_init_rd(struct ath + return 0; + } + ++#ifdef CPTCFG_MAC80211_LEDS ++static const struct ieee80211_tpt_blink ath10k_tpt_blink[] = { ++ { .throughput = 0 * 1024, .blink_time = 334 }, ++ { .throughput = 1 * 1024, .blink_time = 260 }, ++ { .throughput = 2 * 1024, .blink_time = 220 }, ++ { .throughput = 5 * 1024, .blink_time = 190 }, ++ { .throughput = 10 * 1024, .blink_time = 170 }, ++ { .throughput = 25 * 1024, .blink_time = 150 }, ++ { .throughput = 54 * 1024, .blink_time = 130 }, ++ { .throughput = 120 * 1024, .blink_time = 110 }, ++ { .throughput = 265 * 1024, .blink_time = 80 }, ++ { .throughput = 586 * 1024, .blink_time = 50 }, ++}; ++#endif ++ + int ath10k_mac_register(struct ath10k *ar) + { + static const u32 cipher_suites[] = { +@@ -10057,6 +10072,12 @@ int ath10k_mac_register(struct ath10k *a + + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; + ++#ifdef CPTCFG_MAC80211_LEDS ++ ieee80211_create_tpt_led_trigger(ar->hw, ++ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, ++ ARRAY_SIZE(ath10k_tpt_blink)); ++#endif ++ + ret = ieee80211_register_hw(ar->hw); + if (ret) { + ath10k_err(ar, "failed to register ieee80211: %d\n", ret); diff --git a/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch new file mode 100644 index 0000000000..5e74687826 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch @@ -0,0 +1,609 @@ +From: Sebastian Gottschall + +Adds LED and GPIO Control support for 988x, 9887, 9888, 99x0, 9984 based +chipsets with on chipset connected led's using WMI Firmware API. The LED +device will get available named as "ath10k-phyX" at sysfs and can be controlled +with various triggers. adds also debugfs interface for gpio control. + +This patch is specific for OpenWRt base, as is use old backported package +with old wireless source. Support for QCA9984 is removed and a simbol +is added to local-simbol file to export the actually compile the code +with the ATH10K_LEDS simbol. + + +Signed-off-by: Sebastian Gottschall +Reviewed-by: Steve deRosier +[kvalo: major reorg and cleanup] +Signed-off-by: Kalle Valo +Signed-off-by: Ansuel Smith +--- + +v13: + +* only compile tested! + +* fix all checkpatch warnings + +* fix commit log + +* sizeof(struct ath10k_gpiocontrol) -> sizeof(*gpio) + +* unsigned -> unsigned int + +* remove GPIOLIB code, that should be added in a separate patch + +* rename gpio.c to leds.c + +* add leds.h + +* rename some functions: + + ath10k_attach_led() -> ath10k_leds_register() + ath10k_unregister_led() -> ath10k_leds_unregister() + ath10k_reset_led_pin() -> ath10k_leds_start() + +* call ath10k_leds_unregister() before ath10k_thermal_unregister() to preserve ordering + +* call ath10k_leds_start() only from ath10k_core_start() and not from mac.c + +* rename struct ath10k_gpiocontrol as anonymous function under struct + ath10k::leds, no need for memory allocation + +* merge ath10k_add_led() to ath10k_attach_led(), which is it's only caller + +* remove #if IS_ENABLED() checks from most of places, memory savings from those were not worth it + +* Kconfig help text improvement and move it lower in the menu, also don't enable it by default + +* switch to set_brightness_blocking() so that the callback can sleep, + then no need to use ath10k_wmi_cmd_send_nowait() and can take mutex + to access ar->state + +* don't touch ath10k_wmi_pdev_get_temperature() + +* as QCA6174/QCA9377 are not (yet) supported don't add the command to WMI-TLV interface + +* remove debugfs interface, that should be added in another patch + +* cleanup includes + + + drivers/net/wireless/ath/ath10k/Kconfig | 10 +++ + drivers/net/wireless/ath/ath10k/Makefile | 1 + + drivers/net/wireless/ath/ath10k/core.c | 22 +++++++ + drivers/net/wireless/ath/ath10k/core.h | 9 ++- + drivers/net/wireless/ath/ath10k/hw.h | 1 + + drivers/net/wireless/ath/ath10k/leds.c | 103 ++++++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath10k/leds.h | 45 +++++++++++++ + drivers/net/wireless/ath/ath10k/mac.c | 1 + + drivers/net/wireless/ath/ath10k/wmi-ops.h | 32 ++++++++++ + drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 + + drivers/net/wireless/ath/ath10k/wmi.c | 54 ++++++++++++++++ + drivers/net/wireless/ath/ath10k/wmi.h | 35 ++++++++++ + 12 files changed, 314 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/wireless/ath/ath10k/leds.c + create mode 100644 drivers/net/wireless/ath/ath10k/leds.h +--- a/drivers/net/wireless/ath/ath10k/Kconfig ++++ b/drivers/net/wireless/ath/ath10k/Kconfig +@@ -70,6 +70,16 @@ config ATH10K_DEBUGFS + + If unsure, say Y to make it easier to debug problems. + ++config ATH10K_LEDS ++ bool "Atheros ath10k LED support" ++ depends on ATH10K ++ select MAC80211_LEDS ++ select LEDS_CLASS ++ select NEW_LEDS ++ default y ++ ---help--- ++ This option is necessary, if you want LED support for chipset connected led pins. If unsure, say N. ++ + config ATH10K_SPECTRAL + bool "Atheros ath10k spectral scan support" + depends on ATH10K_DEBUGFS +--- a/drivers/net/wireless/ath/ath10k/Makefile ++++ b/drivers/net/wireless/ath/ath10k/Makefile +@@ -19,6 +19,7 @@ ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += + ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o + ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o + ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o ++ath10k_core-$(CPTCFG_ATH10K_LEDS) += leds.o + ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o + ath10k_core-$(CONFIG_PM) += wow.o + ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o +--- a/local-symbols ++++ b/local-symbols +@@ -146,6 +146,7 @@ ATH10K_DEBUG= + ATH10K_DEBUGFS= + ATH10K_SPECTRAL= + ATH10K_THERMAL= ++ATH10K_LEDS= + ATH10K_TRACING= + ATH10K_DFS_CERTIFIED= + WCN36XX= +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -25,6 +25,7 @@ + #include "testmode.h" + #include "wmi-ops.h" + #include "coredump.h" ++#include "leds.h" + + unsigned int ath10k_debug_mask; + EXPORT_SYMBOL(ath10k_debug_mask); +@@ -61,6 +62,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA988X_2_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, + .name = "qca988x hw2.0", ++ .led_pin = 1, + .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, +@@ -130,6 +132,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA9887_1_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, + .name = "qca9887 hw1.0", ++ .led_pin = 1, + .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, +@@ -335,6 +338,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA99X0_2_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, + .name = "qca99x0 hw2.0", ++ .led_pin = 17, + .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .otp_exe_param = 0x00000700, +@@ -375,6 +379,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA9984_1_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, + .name = "qca9984/qca9994 hw1.0", ++ .led_pin = 17, + .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, +@@ -422,6 +427,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA9888_2_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, + .name = "qca9888 hw2.0", ++ .led_pin = 17, + .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, +@@ -2904,6 +2910,10 @@ int ath10k_core_start(struct ath10k *ar, + goto err_hif_stop; + } + ++ status = ath10k_leds_start(ar); ++ if (status) ++ goto err_hif_stop; ++ + return 0; + + err_hif_stop: +@@ -3162,9 +3172,18 @@ static void ath10k_core_register_work(st + goto err_spectral_destroy; + } + ++ status = ath10k_leds_register(ar); ++ if (status) { ++ ath10k_err(ar, "could not register leds: %d\n", ++ status); ++ goto err_thermal_unregister; ++ } ++ + set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags); + return; + ++err_thermal_unregister: ++ ath10k_thermal_unregister(ar); + err_spectral_destroy: + ath10k_spectral_destroy(ar); + err_debug_destroy: +@@ -3210,6 +3229,8 @@ void ath10k_core_unregister(struct ath10 + if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) + return; + ++ ath10k_leds_unregister(ar); ++ + ath10k_thermal_unregister(ar); + /* Stop spectral before unregistering from mac80211 to remove the + * relayfs debugfs file cleanly. Otherwise the parent debugfs tree +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include "htt.h" + #include "htc.h" +@@ -1237,6 +1238,13 @@ struct ath10k { + } testmode; + + struct { ++ struct gpio_led wifi_led; ++ struct led_classdev cdev; ++ char label[48]; ++ u32 gpio_state_pin; ++ } leds; ++ ++ struct { + /* protected by data_lock */ + u32 rx_crc_err_drop; + u32 fw_crash_counter; +--- a/drivers/net/wireless/ath/ath10k/hw.h ++++ b/drivers/net/wireless/ath/ath10k/hw.h +@@ -517,6 +517,7 @@ struct ath10k_hw_params { + const char *name; + u32 patch_load_addr; + int uart_pin; ++ int led_pin; + u32 otp_exe_param; + + /* Type of hw cycle counter wraparound logic, for more info +--- /dev/null ++++ b/drivers/net/wireless/ath/ath10k/leds.c +@@ -0,0 +1,103 @@ ++/* ++ * Copyright (c) 2005-2011 Atheros Communications Inc. ++ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. ++ * Copyright (c) 2018 Sebastian Gottschall ++ * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++ ++#include "core.h" ++#include "wmi.h" ++#include "wmi-ops.h" ++ ++#include "leds.h" ++ ++static int ath10k_leds_set_brightness_blocking(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct ath10k *ar = container_of(led_cdev, struct ath10k, ++ leds.cdev); ++ struct gpio_led *led = &ar->leds.wifi_led; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH10K_STATE_ON) ++ goto out; ++ ++ ar->leds.gpio_state_pin = (brightness != LED_OFF) ^ led->active_low; ++ ath10k_wmi_gpio_output(ar, led->gpio, ar->leds.gpio_state_pin); ++ ++out: ++ mutex_unlock(&ar->conf_mutex); ++ ++ return 0; ++} ++ ++int ath10k_leds_start(struct ath10k *ar) ++{ ++ if (ar->hw_params.led_pin == 0) ++ /* leds not supported */ ++ return 0; ++ ++ /* under some circumstances, the gpio pin gets reconfigured ++ * to default state by the firmware, so we need to ++ * reconfigure it this behaviour has only ben seen on ++ * QCA9984 and QCA99XX devices so far ++ */ ++ ath10k_wmi_gpio_config(ar, ar->hw_params.led_pin, 0, ++ WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE); ++ ath10k_wmi_gpio_output(ar, ar->hw_params.led_pin, 1); ++ ++ return 0; ++} ++ ++int ath10k_leds_register(struct ath10k *ar) ++{ ++ int ret; ++ ++ if (ar->hw_params.led_pin == 0) ++ /* leds not supported */ ++ return 0; ++ ++ snprintf(ar->leds.label, sizeof(ar->leds.label), "ath10k-%s", ++ wiphy_name(ar->hw->wiphy)); ++ ar->leds.wifi_led.active_low = 1; ++ ar->leds.wifi_led.gpio = ar->hw_params.led_pin; ++ ar->leds.wifi_led.name = ar->leds.label; ++ ar->leds.wifi_led.default_state = LEDS_GPIO_DEFSTATE_KEEP; ++ ++ ar->leds.cdev.name = ar->leds.label; ++ ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking; ++ ++ /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */ ++ ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger; ++ ++ ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++void ath10k_leds_unregister(struct ath10k *ar) ++{ ++ if (ar->hw_params.led_pin == 0) ++ /* leds not supported */ ++ return; ++ ++ led_classdev_unregister(&ar->leds.cdev); ++} ++ +--- /dev/null ++++ b/drivers/net/wireless/ath/ath10k/leds.h +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _LEDS_H_ ++#define _LEDS_H_ ++ ++#include "core.h" ++ ++#ifdef CPTCFG_ATH10K_LEDS ++void ath10k_leds_unregister(struct ath10k *ar); ++int ath10k_leds_start(struct ath10k *ar); ++int ath10k_leds_register(struct ath10k *ar); ++#else ++static inline void ath10k_leds_unregister(struct ath10k *ar) ++{ ++} ++ ++static inline int ath10k_leds_start(struct ath10k *ar) ++{ ++ return 0; ++} ++ ++static inline int ath10k_leds_register(struct ath10k *ar) ++{ ++ return 0; ++} ++ ++#endif ++#endif /* _LEDS_H_ */ +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -24,6 +24,7 @@ + #include "wmi-tlv.h" + #include "wmi-ops.h" + #include "wow.h" ++#include "leds.h" + + /*********/ + /* Rates */ +--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h ++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h +@@ -226,7 +226,10 @@ struct wmi_ops { + const struct wmi_bb_timing_cfg_arg *arg); + struct sk_buff *(*gen_per_peer_per_tid_cfg)(struct ath10k *ar, + const struct wmi_per_peer_per_tid_cfg_arg *arg); ++ struct sk_buff *(*gen_gpio_config)(struct ath10k *ar, u32 gpio_num, ++ u32 input, u32 pull_type, u32 intr_mode); + ++ struct sk_buff *(*gen_gpio_output)(struct ath10k *ar, u32 gpio_num, u32 set); + }; + + int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); +@@ -1122,6 +1125,35 @@ ath10k_wmi_force_fw_hang(struct ath10k * + return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); + } + ++static inline int ath10k_wmi_gpio_config(struct ath10k *ar, u32 gpio_num, ++ u32 input, u32 pull_type, u32 intr_mode) ++{ ++ struct sk_buff *skb; ++ ++ if (!ar->wmi.ops->gen_gpio_config) ++ return -EOPNOTSUPP; ++ ++ skb = ar->wmi.ops->gen_gpio_config(ar, gpio_num, input, pull_type, intr_mode); ++ if (IS_ERR(skb)) ++ return PTR_ERR(skb); ++ ++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_config_cmdid); ++} ++ ++static inline int ath10k_wmi_gpio_output(struct ath10k *ar, u32 gpio_num, u32 set) ++{ ++ struct sk_buff *skb; ++ ++ if (!ar->wmi.ops->gen_gpio_config) ++ return -EOPNOTSUPP; ++ ++ skb = ar->wmi.ops->gen_gpio_output(ar, gpio_num, set); ++ if (IS_ERR(skb)) ++ return PTR_ERR(skb); ++ ++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_output_cmdid); ++} ++ + static inline int + ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level) + { +--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c ++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c +@@ -4591,6 +4591,8 @@ static const struct wmi_ops wmi_tlv_ops + .gen_echo = ath10k_wmi_tlv_op_gen_echo, + .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf, + .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable, ++ /* .gen_gpio_config not implemented */ ++ /* .gen_gpio_output not implemented */ + }; + + static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -7468,6 +7468,49 @@ ath10k_wmi_op_gen_peer_set_param(struct + return skb; + } + ++static struct sk_buff *ath10k_wmi_op_gen_gpio_config(struct ath10k *ar, ++ u32 gpio_num, u32 input, ++ u32 pull_type, u32 intr_mode) ++{ ++ struct wmi_gpio_config_cmd *cmd; ++ struct sk_buff *skb; ++ ++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); ++ if (!skb) ++ return ERR_PTR(-ENOMEM); ++ ++ cmd = (struct wmi_gpio_config_cmd *)skb->data; ++ cmd->pull_type = __cpu_to_le32(pull_type); ++ cmd->gpio_num = __cpu_to_le32(gpio_num); ++ cmd->input = __cpu_to_le32(input); ++ cmd->intr_mode = __cpu_to_le32(intr_mode); ++ ++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_config gpio_num 0x%08x input 0x%08x pull_type 0x%08x intr_mode 0x%08x\n", ++ gpio_num, input, pull_type, intr_mode); ++ ++ return skb; ++} ++ ++static struct sk_buff *ath10k_wmi_op_gen_gpio_output(struct ath10k *ar, ++ u32 gpio_num, u32 set) ++{ ++ struct wmi_gpio_output_cmd *cmd; ++ struct sk_buff *skb; ++ ++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); ++ if (!skb) ++ return ERR_PTR(-ENOMEM); ++ ++ cmd = (struct wmi_gpio_output_cmd *)skb->data; ++ cmd->gpio_num = __cpu_to_le32(gpio_num); ++ cmd->set = __cpu_to_le32(set); ++ ++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_output gpio_num 0x%08x set 0x%08x\n", ++ gpio_num, set); ++ ++ return skb; ++} ++ + static struct sk_buff * + ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id, + enum wmi_sta_ps_mode psmode) +@@ -9156,6 +9199,9 @@ static const struct wmi_ops wmi_ops = { + .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, + .gen_echo = ath10k_wmi_op_gen_echo, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, ++ + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +@@ -9226,6 +9272,8 @@ static const struct wmi_ops wmi_10_1_ops + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, + .gen_echo = ath10k_wmi_op_gen_echo, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +@@ -9298,6 +9346,8 @@ static const struct wmi_ops wmi_10_2_ops + .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + /* .gen_pdev_enable_adaptive_cca not implemented */ + }; + +@@ -9369,6 +9419,8 @@ static const struct wmi_ops wmi_10_2_4_o + ath10k_wmi_op_gen_pdev_enable_adaptive_cca, + .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype, + .gen_bb_timing = ath10k_wmi_10_2_4_op_gen_bb_timing, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +@@ -9450,6 +9502,8 @@ static const struct wmi_ops wmi_10_4_ops + .gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info, + .gen_echo = ath10k_wmi_op_gen_echo, + .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + }; + + int ath10k_wmi_attach(struct ath10k *ar) +--- a/drivers/net/wireless/ath/ath10k/wmi.h ++++ b/drivers/net/wireless/ath/ath10k/wmi.h +@@ -3027,6 +3027,41 @@ enum wmi_10_4_feature_mask { + + }; + ++/* WMI_GPIO_CONFIG_CMDID */ ++enum { ++ WMI_GPIO_PULL_NONE, ++ WMI_GPIO_PULL_UP, ++ WMI_GPIO_PULL_DOWN, ++}; ++ ++enum { ++ WMI_GPIO_INTTYPE_DISABLE, ++ WMI_GPIO_INTTYPE_RISING_EDGE, ++ WMI_GPIO_INTTYPE_FALLING_EDGE, ++ WMI_GPIO_INTTYPE_BOTH_EDGE, ++ WMI_GPIO_INTTYPE_LEVEL_LOW, ++ WMI_GPIO_INTTYPE_LEVEL_HIGH ++}; ++ ++/* WMI_GPIO_CONFIG_CMDID */ ++struct wmi_gpio_config_cmd { ++ __le32 gpio_num; /* GPIO number to be setup */ ++ __le32 input; /* 0 - Output/ 1 - Input */ ++ __le32 pull_type; /* Pull type defined above */ ++ __le32 intr_mode; /* Interrupt mode defined above (Input) */ ++} __packed; ++ ++/* WMI_GPIO_OUTPUT_CMDID */ ++struct wmi_gpio_output_cmd { ++ __le32 gpio_num; /* GPIO number to be setup */ ++ __le32 set; /* Set the GPIO pin*/ ++} __packed; ++ ++/* WMI_GPIO_INPUT_EVENTID */ ++struct wmi_gpio_input_event { ++ __le32 gpio_num; /* GPIO number which changed state */ ++} __packed; ++ + struct wmi_ext_resource_config_10_4_cmd { + /* contains enum wmi_host_platform_type */ + __le32 host_platform_config; diff --git a/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch b/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch new file mode 100644 index 0000000000..6da7bfa725 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch @@ -0,0 +1,53 @@ +From 79c9d7aabae1d1da9eea97d83b61e1517a8a2221 Mon Sep 17 00:00:00 2001 +From: Mathias Kresin +Date: Fri, 22 Jun 2018 18:59:44 +0200 +Subject: [PATCH] ath10k: use tpt LED trigger by default + +Use the tpt LED trigger for each created phy led. Ths way LEDs attached +to the ath10k GPIO pins are indicating the phy status and blink on +traffic. + +Signed-off-by: Mathias Kresin +--- + drivers/net/wireless/ath/ath10k/core.h | 4 ++++ + drivers/net/wireless/ath/ath10k/leds.c | 4 +--- + drivers/net/wireless/ath/ath10k/mac.c | 2 +- + 3 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -1290,6 +1290,10 @@ struct ath10k { + bool coex_support; + int coex_gpio_pin; + ++#ifdef CPTCFG_MAC80211_LEDS ++ const char *led_default_trigger; ++#endif ++ + /* must be last */ + u8 drv_priv[] __aligned(sizeof(void *)); + }; +--- a/drivers/net/wireless/ath/ath10k/leds.c ++++ b/drivers/net/wireless/ath/ath10k/leds.c +@@ -81,9 +81,7 @@ int ath10k_leds_register(struct ath10k * + + ar->leds.cdev.name = ar->leds.label; + ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking; +- +- /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */ +- ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger; ++ ar->leds.cdev.default_trigger = ar->led_default_trigger; + + ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev); + if (ret) +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -10074,7 +10074,7 @@ int ath10k_mac_register(struct ath10k *a + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; + + #ifdef CPTCFG_MAC80211_LEDS +- ieee80211_create_tpt_led_trigger(ar->hw, ++ ar->led_default_trigger = ieee80211_create_tpt_led_trigger(ar->hw, + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, + ARRAY_SIZE(ath10k_tpt_blink)); + #endif diff --git a/package/kernel/mac80211/patches/ath10k/980-ath10k-fix-max-antenna-gain-unit.patch b/package/kernel/mac80211/patches/ath10k/980-ath10k-fix-max-antenna-gain-unit.patch new file mode 100644 index 0000000000..e951e011e6 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/980-ath10k-fix-max-antenna-gain-unit.patch @@ -0,0 +1,49 @@ +From: Sven Eckelmann +Date: Tue, 11 Jun 2019 13:58:35 +0200 +Subject: ath10k: fix max antenna gain unit + +Most of the txpower for the ath10k firmware is stored as twicepower (0.5 dB +steps). This isn't the case for max_antenna_gain - which is still expected +by the firmware as dB. + +The firmware is converting it from dB to the internal (twicepower) +representation when it calculates the limits of a channel. This can be seen +in tpc_stats when configuring "12" as max_antenna_gain. Instead of the +expected 12 (6 dB), the tpc_stats shows 24 (12 dB). + +Tested on QCA9888 and IPQ4019 with firmware 10.4-3.5.3-00057. + +Fixes: 02256930d9b8 ("ath10k: use proper tx power unit") +Signed-off-by: Sven Eckelmann + +Forwarded: https://patchwork.kernel.org/patch/10986723/ + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -1038,7 +1038,7 @@ static int ath10k_monitor_vdev_start(str + arg.channel.min_power = 0; + arg.channel.max_power = channel->max_power * 2; + arg.channel.max_reg_power = channel->max_reg_power * 2; +- arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; ++ arg.channel.max_antenna_gain = channel->max_antenna_gain; + + reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); +@@ -1484,7 +1484,7 @@ static int ath10k_vdev_start_restart(str + arg.channel.min_power = 0; + arg.channel.max_power = chandef->chan->max_power * 2; + arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; +- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2; ++ arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; + + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + arg.ssid = arvif->u.ap.ssid; +@@ -3255,7 +3255,7 @@ static int ath10k_update_channel_list(st + ch->min_power = 0; + ch->max_power = channel->max_power * 2; + ch->max_reg_power = channel->max_reg_power * 2; +- ch->max_antenna_gain = channel->max_antenna_gain * 2; ++ ch->max_antenna_gain = channel->max_antenna_gain; + ch->reg_class_id = 0; /* FIXME */ + + /* FIXME: why use only legacy modes, why not any diff --git a/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch b/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch new file mode 100644 index 0000000000..a149ce1216 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch @@ -0,0 +1,101 @@ +From: Sven Eckelmann +Date: Wed, 28 Nov 2018 16:16:27 +0100 +Subject: ath10k: adjust tx power reduction for US regulatory domain + +FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4): + +> (4) The conducted output power limit +> specified in paragraph (b) of this section +> is based on the use of antennas +> with directional gains that do not exceed +> 6 dBi. Except as shown in paragraph +> (c) of this section, if transmitting +> antennas of directional gain greater +> than 6 dBi are used, the conducted +> output power from the intentional radiator +> shall be reduced below the stated +> values in paragraphs (b)(1), (b)(2), +> and (b)(3) of this section, as appropriate, +> by the amount in dB that the +> directional gain of the antenna exceeds +> 6 dBi. + +https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf + +Signed-off-by: Sven Eckelmann + +Forwarded: no + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -1006,6 +1006,40 @@ static inline int ath10k_vdev_setup_sync + return ar->last_wmi_vdev_start_status; + } + ++static u32 ath10k_get_max_antenna_gain(struct ath10k *ar, ++ u32 ch_max_antenna_gain) ++{ ++ u32 max_antenna_gain; ++ ++ if (ar->dfs_detector && ar->dfs_detector->region == NL80211_DFS_FCC) { ++ /* FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4): ++ * ++ * > (4) The conducted output power limit ++ * > specified in paragraph (b) of this section ++ * > is based on the use of antennas ++ * > with directional gains that do not exceed ++ * > 6 dBi. Except as shown in paragraph ++ * > (c) of this section, if transmitting ++ * > antennas of directional gain greater ++ * > than 6 dBi are used, the conducted ++ * > output power from the intentional radiator ++ * > shall be reduced below the stated ++ * > values in paragraphs (b)(1), (b)(2), ++ * > and (b)(3) of this section, as appropriate, ++ * > by the amount in dB that the ++ * > directional gain of the antenna exceeds ++ * > 6 dBi. ++ * ++ * https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf ++ */ ++ max_antenna_gain = 6; ++ } else { ++ max_antenna_gain = 0; ++ } ++ ++ return max(ch_max_antenna_gain, max_antenna_gain); ++} ++ + static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) + { + struct cfg80211_chan_def *chandef = NULL; +@@ -1038,7 +1072,8 @@ static int ath10k_monitor_vdev_start(str + arg.channel.min_power = 0; + arg.channel.max_power = channel->max_power * 2; + arg.channel.max_reg_power = channel->max_reg_power * 2; +- arg.channel.max_antenna_gain = channel->max_antenna_gain; ++ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ channel->max_antenna_gain); + + reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); +@@ -1484,7 +1519,8 @@ static int ath10k_vdev_start_restart(str + arg.channel.min_power = 0; + arg.channel.max_power = chandef->chan->max_power * 2; + arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; +- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; ++ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ chandef->chan->max_antenna_gain); + + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + arg.ssid = arvif->u.ap.ssid; +@@ -3255,7 +3291,8 @@ static int ath10k_update_channel_list(st + ch->min_power = 0; + ch->max_power = channel->max_power * 2; + ch->max_reg_power = channel->max_reg_power * 2; +- ch->max_antenna_gain = channel->max_antenna_gain; ++ ch->max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ channel->max_antenna_gain); + ch->reg_class_id = 0; /* FIXME */ + + /* FIXME: why use only legacy modes, why not any diff --git a/package/kernel/mac80211/patches/ath5k/201-ath5k-WAR-for-AR71xx-PCI-bug.patch b/package/kernel/mac80211/patches/ath5k/201-ath5k-WAR-for-AR71xx-PCI-bug.patch new file mode 100644 index 0000000000..21516ffde9 --- /dev/null +++ b/package/kernel/mac80211/patches/ath5k/201-ath5k-WAR-for-AR71xx-PCI-bug.patch @@ -0,0 +1,38 @@ +--- a/drivers/net/wireless/ath/ath5k/initvals.c ++++ b/drivers/net/wireless/ath/ath5k/initvals.c +@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini + { AR5K_IMR, 0 }, + { AR5K_IER, AR5K_IER_DISABLE }, + { AR5K_BSR, 0, AR5K_INI_READ }, ++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) + { AR5K_TXCFG, AR5K_DMASIZE_128B }, + { AR5K_RXCFG, AR5K_DMASIZE_128B }, ++#else ++ /* WAR for AR71xx PCI bug */ ++ { AR5K_TXCFG, AR5K_DMASIZE_128B }, ++ { AR5K_RXCFG, AR5K_DMASIZE_4B }, ++#endif + { AR5K_CFG, AR5K_INIT_CFG }, + { AR5K_TOPS, 8 }, + { AR5K_RXNOFRM, 8 }, +--- a/drivers/net/wireless/ath/ath5k/dma.c ++++ b/drivers/net/wireless/ath/ath5k/dma.c +@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah) + * guess we can tweak it and see how it goes ;-) + */ + if (ah->ah_version != AR5K_AR5210) { ++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) + AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); + AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, + AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); ++#else ++ /* WAR for AR71xx PCI bug */ ++ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, ++ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); ++ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, ++ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B); ++#endif + } + + /* Pre-enable interrupts on 5211/5212*/ diff --git a/package/kernel/mac80211/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch new file mode 100644 index 0000000000..9dbe047c9a --- /dev/null +++ b/package/kernel/mac80211/patches/ath5k/411-ath5k_allow_adhoc_and_ap.patch @@ -0,0 +1,46 @@ +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw + goto end; + } + +- /* Don't allow other interfaces if one ad-hoc is configured. +- * TODO: Fix the problems with ad-hoc and multiple other interfaces. +- * We would need to operate the HW in ad-hoc mode to allow TSF updates +- * for the IBSS, but this breaks with additional AP or STA interfaces +- * at the moment. */ +- if (ah->num_adhoc_vifs || +- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { ++ /* Don't allow more than one ad-hoc interface */ ++ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) { + ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n"); + ret = -ELNRNG; + goto end; +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -1964,7 +1964,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) + } + + if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + +- ah->num_mesh_vifs > 1) || ++ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) || + ah->opmode == NL80211_IFTYPE_MESH_POINT) { + u64 tsf = ath5k_hw_get_tsf64(ah); + u32 tsftu = TSF_TO_TU(tsf); +@@ -2050,7 +2050,7 @@ ath5k_beacon_update_timers(struct ath5k_ + + intval = ah->bintval & AR5K_BEACON_PERIOD; + if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +- + ah->num_mesh_vifs > 1) { ++ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) { + intval /= ATH_BCBUF; /* staggered multi-bss beacons */ + if (intval < 15) + ATH5K_WARN(ah, "intval %u is too low, min 15\n", +@@ -2516,6 +2516,7 @@ static const struct ieee80211_iface_limi + BIT(NL80211_IFTYPE_MESH_POINT) | + #endif + BIT(NL80211_IFTYPE_AP) }, ++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, + }; + + static const struct ieee80211_iface_combination if_comb = { diff --git a/package/kernel/mac80211/patches/ath5k/420-ath5k_disable_fast_cc.patch b/package/kernel/mac80211/patches/ath5k/420-ath5k_disable_fast_cc.patch new file mode 100644 index 0000000000..414f49508f --- /dev/null +++ b/package/kernel/mac80211/patches/ath5k/420-ath5k_disable_fast_cc.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/ath/ath5k/reset.c ++++ b/drivers/net/wireless/ath/ath5k/reset.c +@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum + tsf_lo = 0; + mode = 0; + ++#if 0 + /* + * Sanity check for fast flag + * Fast channel change only available +@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum + */ + if (fast && (ah->ah_radio != AR5K_RF2413) && + (ah->ah_radio != AR5K_RF5413)) ++#endif + fast = false; + + /* Disable sleep clock operation diff --git a/package/kernel/mac80211/patches/ath5k/430-add_ath5k_platform.patch b/package/kernel/mac80211/patches/ath5k/430-add_ath5k_platform.patch new file mode 100644 index 0000000000..b213e2a819 --- /dev/null +++ b/package/kernel/mac80211/patches/ath5k/430-add_ath5k_platform.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/include/linux/ath5k_platform.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2008 Atheros Communications Inc. ++ * Copyright (c) 2009 Gabor Juhos ++ * Copyright (c) 2009 Imre Kaloz ++ * Copyright (c) 2010 Daniel Golle ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _LINUX_ATH5K_PLATFORM_H ++#define _LINUX_ATH5K_PLATFORM_H ++ ++#define ATH5K_PLAT_EEP_MAX_WORDS 2048 ++ ++struct ath5k_platform_data { ++ u16 *eeprom_data; ++ u8 *macaddr; ++}; ++ ++#endif /* _LINUX_ATH5K_PLATFORM_H */ diff --git a/package/kernel/mac80211/patches/ath5k/432-ath5k_add_pciids.patch b/package/kernel/mac80211/patches/ath5k/432-ath5k_add_pciids.patch new file mode 100644 index 0000000000..bd0e6707a5 --- /dev/null +++ b/package/kernel/mac80211/patches/ath5k/432-ath5k_add_pciids.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath5k/pci.c ++++ b/drivers/net/wireless/ath/ath5k/pci.c +@@ -47,6 +47,8 @@ static const struct pci_device_id ath5k_ + { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ + { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ + { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ ++ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */ ++ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */ + { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */ + { 0 } + }; diff --git a/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch b/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch new file mode 100644 index 0000000000..92fb90c165 --- /dev/null +++ b/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch @@ -0,0 +1,142 @@ +This adds a bwmode debugfs file which can be used to set alternate +channel operating bandwidths. Only tested with AR5413 and only at +5 and 20 mhz channels. + +Signed-off-by: Pat Erley +--- +Other devices will need to be added to the switch in write_file_bwmode + +drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ + 1 files changed, 86 insertions(+), 0 deletions(-) + +--- a/drivers/net/wireless/ath/ath5k/debug.c ++++ b/drivers/net/wireless/ath/ath5k/debug.c +@@ -803,6 +803,97 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++/* debugfs: bwmode */ ++ ++static ssize_t read_file_bwmode(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath5k_hw *ah = file->private_data; ++ char buf[15]; ++ unsigned int len = 0; ++ ++ int cur_ah_bwmode = ah->ah_bwmode_debug; ++ ++#define print_selected(MODE, LABEL) \ ++ if (cur_ah_bwmode == MODE) \ ++ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \ ++ else \ ++ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \ ++ len += snprintf(buf+len, sizeof(buf)-len, " "); ++ ++ print_selected(AR5K_BWMODE_5MHZ, "5"); ++ print_selected(AR5K_BWMODE_10MHZ, "10"); ++ print_selected(AR5K_BWMODE_DEFAULT, "20"); ++ print_selected(AR5K_BWMODE_40MHZ, "40"); ++#undef print_selected ++ ++ len += snprintf(buf+len, sizeof(buf)-len, "\n"); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_bwmode(struct file *file, ++ const char __user *userbuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath5k_hw *ah = file->private_data; ++ char buf[3]; ++ int bw = 20; ++ int tobwmode = AR5K_BWMODE_DEFAULT; ++ ++ if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) ++ return -EFAULT; ++ ++ /* TODO: Add check for active interface */ ++ ++ if(strncmp(buf, "5", 1) == 0 ) { ++ tobwmode = AR5K_BWMODE_5MHZ; ++ bw = 5; ++ } else if ( strncmp(buf, "10", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_10MHZ; ++ bw = 10; ++ } else if ( strncmp(buf, "20", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_DEFAULT; ++ bw = 20; ++ } else if ( strncmp(buf, "40", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_40MHZ; ++ bw = 40; ++ } else ++ return -EINVAL; ++ ++ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n", ++ bw, tobwmode); ++ ++ switch (ah->ah_radio) { ++ /* TODO: only define radios that actually support 5/10mhz channels */ ++ case AR5K_RF5413: ++ case AR5K_RF5110: ++ case AR5K_RF5111: ++ case AR5K_RF5112: ++ case AR5K_RF2413: ++ case AR5K_RF2316: ++ case AR5K_RF2317: ++ case AR5K_RF2425: ++ if(ah->ah_bwmode_debug != tobwmode) { ++ mutex_lock(&ah->lock); ++ ah->ah_bwmode = tobwmode; ++ ah->ah_bwmode_debug = tobwmode; ++ mutex_unlock(&ah->lock); ++ } ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ return count; ++} ++ ++static const struct file_operations fops_bwmode = { ++ .read = read_file_bwmode, ++ .write = write_file_bwmode, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; + + /* debugfs: queues etc */ + +@@ -997,6 +1088,8 @@ ath5k_debug_init_device(struct ath5k_hw + debugfs_create_file("queue", 0600, phydir, ah, &fops_queue); + debugfs_create_bool("32khz_clock", 0600, phydir, + &ah->ah_use_32khz_clock); ++ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah, ++ &fops_bwmode); + } + + /* functions used in other places */ +--- a/drivers/net/wireless/ath/ath5k/ath5k.h ++++ b/drivers/net/wireless/ath/ath5k/ath5k.h +@@ -1372,6 +1372,7 @@ struct ath5k_hw { + u8 ah_coverage_class; + bool ah_ack_bitrate_high; + u8 ah_bwmode; ++ u8 ah_bwmode_debug; + bool ah_short_slot; + + /* Antenna Control */ +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -466,6 +466,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru + return -EINVAL; + } + ++ if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT) ++ ah->ah_bwmode = ah->ah_bwmode_debug; ++ + /* + * To switch channels clear any pending DMA operations; + * wait long enough for the RX fifo to drain, reset the diff --git a/package/kernel/mac80211/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch b/package/kernel/mac80211/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch new file mode 100644 index 0000000000..d648a3a3e5 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch @@ -0,0 +1,25 @@ +From: Felix Fietkau +Date: Sat, 9 Jul 2016 15:25:24 +0200 +Subject: [PATCH] ath9k_hw: reset AHB-WMAC interface on AR91xx + +Should fix a few stability issues + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1435,8 +1435,12 @@ static bool ath9k_hw_set_reset(struct at + if (!AR_SREV_9100(ah)) + REG_WRITE(ah, AR_RC, 0); + +- if (AR_SREV_9100(ah)) ++ if (AR_SREV_9100(ah)) { ++ /* Reset the AHB-WMAC interface */ ++ if (ah->external_reset) ++ ah->external_reset(); + udelay(50); ++ } + + return true; + } diff --git a/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch b/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch new file mode 100644 index 0000000000..5f265b84c2 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch @@ -0,0 +1,129 @@ +From: Felix Fietkau +Date: Sat, 9 Jul 2016 15:26:44 +0200 +Subject: [PATCH] ath9k_hw: issue external reset for QCA955x + +The RTC interface on the SoC needs to be reset along with the rest of +the WMAC. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1312,39 +1312,56 @@ void ath9k_hw_get_delta_slope_vals(struc + *coef_exponent = coef_exp - 16; + } + +-/* AR9330 WAR: +- * call external reset function to reset WMAC if: +- * - doing a cold reset +- * - we have pending frames in the TX queues. +- */ +-static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type) ++static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type) + { +- int i, npend = 0; ++ int i; + +- for (i = 0; i < AR_NUM_QCU; i++) { +- npend = ath9k_hw_numtxpending(ah, i); +- if (npend) +- break; +- } +- +- if (ah->external_reset && +- (npend || type == ATH9K_RESET_COLD)) { +- int reset_err = 0; +- +- ath_dbg(ath9k_hw_common(ah), RESET, +- "reset MAC via external reset\n"); +- +- reset_err = ah->external_reset(); +- if (reset_err) { +- ath_err(ath9k_hw_common(ah), +- "External reset failed, err=%d\n", +- reset_err); +- return false; ++ if (type == ATH9K_RESET_COLD) ++ return true; ++ ++ if (AR_SREV_9550(ah)) ++ return true; ++ ++ /* AR9330 WAR: ++ * call external reset function to reset WMAC if: ++ * - doing a cold reset ++ * - we have pending frames in the TX queues. ++ */ ++ if (AR_SREV_9330(ah)) { ++ for (i = 0; i < AR_NUM_QCU; i++) { ++ if (ath9k_hw_numtxpending(ah, i)) ++ return true; + } ++ } ++ ++ return false; ++} ++ ++static bool ath9k_hw_external_reset(struct ath_hw *ah, int type) ++{ ++ int err; ++ ++ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type)) ++ return true; ++ ++ ath_dbg(ath9k_hw_common(ah), RESET, ++ "reset MAC via external reset\n"); + +- REG_WRITE(ah, AR_RTC_RESET, 1); ++ err = ah->external_reset(); ++ if (err) { ++ ath_err(ath9k_hw_common(ah), ++ "External reset failed, err=%d\n", err); ++ return false; + } + ++ if (AR_SREV_9550(ah)) { ++ REG_WRITE(ah, AR_RTC_RESET, 0); ++ udelay(10); ++ } ++ ++ REG_WRITE(ah, AR_RTC_RESET, 1); ++ udelay(10); ++ + return true; + } + +@@ -1397,24 +1414,24 @@ static bool ath9k_hw_set_reset(struct at + rst_flags |= AR_RTC_RC_MAC_COLD; + } + +- if (AR_SREV_9330(ah)) { +- if (!ath9k_hw_ar9330_reset_war(ah, type)) +- return false; +- } +- + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_check_gpm_offset(ah); + + /* DMA HALT added to resolve ar9300 and ar9580 bus error during +- * RTC_RC reg read ++ * RTC_RC reg read. Also needed for AR9550 external reset + */ +- if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { ++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) { + REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, + 20 * AH_WAIT_TIMEOUT); +- REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + } + ++ if (!AR_SREV_9100(ah)) ++ ath9k_hw_external_reset(ah, type); ++ ++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) ++ REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); ++ + REG_WRITE(ah, AR_RTC_RC, rst_flags); + + REGWRITE_BUFFER_FLUSH(ah); diff --git a/package/kernel/mac80211/patches/ath9k/354-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/ath9k/354-ath9k-force-rx_clear-when-disabling-rx.patch new file mode 100644 index 0000000000..8aaccf49b4 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/354-ath9k-force-rx_clear-when-disabling-rx.patch @@ -0,0 +1,35 @@ +From: Felix Fietkau +Date: Sun, 7 Jun 2015 13:53:35 +0200 +Subject: [PATCH] ath9k: force rx_clear when disabling rx + +This makes stopping Rx more reliable and should reduce the frequency of +Rx related DMA stop warnings. Don't use rx_clear in TX99 mode. + +Cc: stable@vger.kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Helmut Schaa +--- + +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -678,13 +678,18 @@ void ath9k_hw_startpcureceive(struct ath + + ath9k_ani_reset(ah, is_scanning); + +- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); ++ REG_CLR_BIT(ah, AR_DIAG_SW, ++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); + } + EXPORT_SYMBOL(ath9k_hw_startpcureceive); + + void ath9k_hw_abortpcurecv(struct ath_hw *ah) + { +- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); ++ u32 reg = AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT; ++ ++ if (!IS_ENABLED(CPTCFG_ATH9K_TX99)) ++ reg |= AR_DIAG_FORCE_RX_CLEAR; ++ REG_SET_BIT(ah, AR_DIAG_SW, reg); + + ath9k_hw_disable_mib_counters(ah); + } diff --git a/package/kernel/mac80211/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch b/package/kernel/mac80211/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch new file mode 100644 index 0000000000..385eea0116 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch @@ -0,0 +1,36 @@ +From: Felix Fietkau +Date: Sat, 14 May 2016 14:51:02 +0200 +Subject: [PATCH] Revert "ath9k: interpret requested txpower in EIRP + domain" + +This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411. +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -2977,7 +2977,8 @@ void ath9k_hw_apply_txpower(struct ath_h + { + struct ath_regulatory *reg = ath9k_hw_regulatory(ah); + struct ieee80211_channel *channel; +- int chan_pwr, new_pwr; ++ int chan_pwr, new_pwr, max_gain; ++ int ant_gain, ant_reduction = 0; + u16 ctl = NO_CTL; + + if (!chan) +@@ -2989,9 +2990,14 @@ void ath9k_hw_apply_txpower(struct ath_h + channel = chan->chan; + chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER); + new_pwr = min_t(int, chan_pwr, reg->power_limit); ++ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2; ++ ++ ant_gain = get_antenna_gain(ah, chan); ++ if (ant_gain > max_gain) ++ ant_reduction = ant_gain - max_gain; + + ah->eep_ops->set_txpower(ah, chan, ctl, +- get_antenna_gain(ah, chan), new_pwr, test); ++ ant_reduction, new_pwr, test); + } + + void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) diff --git a/package/kernel/mac80211/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch b/package/kernel/mac80211/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch new file mode 100644 index 0000000000..0c3edc1260 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch @@ -0,0 +1,24 @@ +From: Felix Fietkau +Date: Wed, 19 Jul 2017 08:49:31 +0200 +Subject: [PATCH] ath9k: adjust tx power reduction for US regulatory + domain + +FCC regulatory rules allow for up to 6 dBi antenna gain. Account for +this in the EEPROM based tx power reduction code. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -2996,6 +2996,10 @@ void ath9k_hw_apply_txpower(struct ath_h + if (ant_gain > max_gain) + ant_reduction = ant_gain - max_gain; + ++ /* FCC allows maximum antenna gain of 6 dBi */ ++ if (reg->region == NL80211_DFS_FCC) ++ ant_reduction = max_t(int, ant_reduction - 12, 0); ++ + ah->eep_ops->set_txpower(ah, chan, ctl, + ant_reduction, new_pwr, test); + } diff --git a/package/kernel/mac80211/patches/ath9k/401-ath9k_blink_default.patch b/package/kernel/mac80211/patches/ath9k/401-ath9k_blink_default.patch new file mode 100644 index 0000000000..3eb57bb1cf --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/401-ath9k_blink_default.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -48,7 +48,7 @@ int ath9k_modparam_nohwcrypt; + module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); + MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); + +-int ath9k_led_blink; ++int ath9k_led_blink = 1; + module_param_named(blink, ath9k_led_blink, int, 0444); + MODULE_PARM_DESC(blink, "Enable LED blink on activity"); + diff --git a/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch new file mode 100644 index 0000000000..17dd8f6597 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/410-ath9k_allow_adhoc_and_ap.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -830,6 +830,7 @@ static const struct ieee80211_iface_limi + BIT(NL80211_IFTYPE_AP) }, + { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) }, ++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, + }; + + #ifdef CPTCFG_WIRELESS_WDS diff --git a/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch b/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch new file mode 100644 index 0000000000..ea94b52385 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/450-ath9k-enabled-MFP-capability-unconditionally.patch @@ -0,0 +1,34 @@ +From d946085ff5a331de64e91a2e3c96b9ca79d740f5 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 15 Jun 2020 00:10:34 +0200 +Subject: [PATCH] ath9k: enabled MFP capability unconditionally + +ath9k will already fallback on software-crypto for chipsets not +supporting IEEE802.11w (MFP). So advertising MFP is not dependent +on disabling HW crypto for all traffic entirely. + +Signed-off-by: David Bauer +--- + drivers/net/wireless/ath/ath9k/init.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -927,6 +927,7 @@ static void ath9k_set_hw_capab(struct at + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); + ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); ++ ieee80211_hw_set(hw, MFP_CAPABLE); + + if (ath9k_ps_enable) + ieee80211_hw_set(hw, SUPPORTS_PS); +@@ -939,9 +940,6 @@ static void ath9k_set_hw_capab(struct at + IEEE80211_RADIOTAP_MCS_HAVE_STBC; + } + +- if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) +- ieee80211_hw_set(hw, MFP_CAPABLE); +- + hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | + NL80211_FEATURE_P2P_GO_CTWIN; diff --git a/package/kernel/mac80211/patches/ath9k/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/ath9k/500-ath9k_eeprom_debugfs.patch new file mode 100644 index 0000000000..48ccc81308 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/500-ath9k_eeprom_debugfs.patch @@ -0,0 +1,65 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1364,6 +1364,53 @@ void ath9k_deinit_debug(struct ath_softc + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); + } + ++static ssize_t read_file_eeprom(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ struct ath_common *common = ath9k_hw_common(ah); ++ int bytes = 0; ++ int pos = *ppos; ++ int size = 4096; ++ u16 val; ++ int i; ++ ++ if (AR_SREV_9300_20_OR_LATER(ah)) ++ size = 16384; ++ ++ if (*ppos < 0) ++ return -EINVAL; ++ ++ if (count > size - *ppos) ++ count = size - *ppos; ++ ++ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) { ++ void *from = &val; ++ ++ if (!common->bus_ops->eeprom_read(common, i, &val)) ++ val = 0xffff; ++ ++ if (*ppos % 2) { ++ from++; ++ bytes = 1; ++ } else if (count == 1) { ++ bytes = 1; ++ } else { ++ bytes = 2; ++ } ++ copy_to_user(user_buf, from, bytes); ++ user_buf += bytes; ++ } ++ return *ppos - pos; ++} ++ ++static const struct file_operations fops_eeprom = { ++ .read = read_file_eeprom, ++ .open = simple_open, ++ .owner = THIS_MODULE ++}; ++ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1383,6 +1430,8 @@ int ath9k_init_debug(struct ath_hw *ah) + ath9k_tx99_init_debug(sc); + ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); + ++ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, ++ &fops_eeprom); + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, diff --git a/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch new file mode 100644 index 0000000000..b9c784eb25 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/501-ath9k_ahb_init.patch @@ -0,0 +1,34 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -1143,25 +1143,25 @@ 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_out; + } + +- error = ath_ahb_init(); ++ error = ath_pci_init(); + if (error < 0) { ++ pr_err("No PCI devices found, driver not installed\n"); + error = -ENODEV; +- goto err_pci_exit; ++ goto err_ahb_exit; + } + + dmi_check_system(ath9k_quirks); + + return 0; + +- err_pci_exit: +- ath_pci_exit(); ++ err_ahb_exit: ++ ath_ahb_exit(); + err_out: + return error; + } diff --git a/package/kernel/mac80211/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch b/package/kernel/mac80211/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch new file mode 100644 index 0000000000..75b48b480e --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/510-ath9k_intr_mitigation_tweak.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -403,13 +403,8 @@ static void ath9k_hw_init_config(struct + + ah->config.rx_intr_mitigation = true; + +- if (AR_SREV_9300_20_OR_LATER(ah)) { +- ah->config.rimt_last = 500; +- ah->config.rimt_first = 2000; +- } else { +- ah->config.rimt_last = 250; +- ah->config.rimt_first = 700; +- } ++ ah->config.rimt_last = 250; ++ ah->config.rimt_first = 500; + + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + ah->config.pll_pwrsave = 7; diff --git a/package/kernel/mac80211/patches/ath9k/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/ath9k/511-ath9k_reduce_rxbuf.patch new file mode 100644 index 0000000000..15b8d7b86b --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/511-ath9k_reduce_rxbuf.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -88,7 +88,7 @@ int ath_descdma_setup(struct ath_softc * + (_l) &= ((_sz) - 1); \ + } while (0) + +-#define ATH_RXBUF 512 ++#define ATH_RXBUF 256 + #define ATH_TXBUF 512 + #define ATH_TXBUF_RESERVE 5 + #define ATH_TXMAXTRY 13 diff --git a/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch new file mode 100644 index 0000000000..126d1d5c62 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch @@ -0,0 +1,125 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1411,6 +1411,52 @@ static const struct file_operations fops + .owner = THIS_MODULE + }; + ++ ++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ char buf[32]; ++ unsigned int len; ++ ++ len = sprintf(buf, "0x%08x\n", common->chan_bw); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ unsigned long chan_bw; ++ char buf[32]; ++ ssize_t len; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ if (kstrtoul(buf, 0, &chan_bw)) ++ return -EINVAL; ++ ++ common->chan_bw = chan_bw; ++ if (!test_bit(ATH_OP_INVALID, &common->op_flags)) ++ ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL); ++ ++ return count; ++} ++ ++static const struct file_operations fops_chanbw = { ++ .read = read_file_chan_bw, ++ .write = write_file_chan_bw, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1432,6 +1478,8 @@ int ath9k_init_debug(struct ath_hw *ah) + + debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_eeprom); ++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++ sc, &fops_chanbw); + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, +--- a/drivers/net/wireless/ath/ath.h ++++ b/drivers/net/wireless/ath/ath.h +@@ -149,6 +149,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 +@@ -297,11 +297,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke + /* + * Update internal channel flags. + */ +-static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, ++static void ath9k_cmn_update_ichannel(struct ath_common *common, ++ struct ath9k_channel *ichan, + struct cfg80211_chan_def *chandef) + { + struct ieee80211_channel *chan = chandef->chan; + u16 flags = 0; ++ int width; + + ichan->channel = chan->center_freq; + ichan->chan = chan; +@@ -309,7 +311,19 @@ static void ath9k_cmn_update_ichannel(st + if (chan->band == NL80211_BAND_5GHZ) + flags |= CHANNEL_5GHZ; + +- switch (chandef->width) { ++ switch (common->chan_bw) { ++ case 5: ++ width = NL80211_CHAN_WIDTH_5; ++ break; ++ case 10: ++ width = NL80211_CHAN_WIDTH_10; ++ break; ++ default: ++ width = chandef->width; ++ break; ++ } ++ ++ switch (width) { + case NL80211_CHAN_WIDTH_5: + flags |= CHANNEL_QUARTER; + break; +@@ -342,10 +356,11 @@ struct ath9k_channel *ath9k_cmn_get_chan + struct cfg80211_chan_def *chandef) + { + struct ieee80211_channel *curchan = chandef->chan; ++ struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *channel; + + channel = &ah->channels[curchan->hw_value]; +- ath9k_cmn_update_ichannel(channel, chandef); ++ ath9k_cmn_update_ichannel(common, channel, chandef); + + return channel; + } diff --git a/package/kernel/mac80211/patches/ath9k/513-ath9k_add_pci_ids.patch b/package/kernel/mac80211/patches/ath9k/513-ath9k_add_pci_ids.patch new file mode 100644 index 0000000000..113c35625f --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/513-ath9k_add_pci_ids.patch @@ -0,0 +1,30 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -663,6 +663,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) { ++ case AR9300_DEVID_INVALID: + case AR5416_DEVID_PCI: + case AR5416_DEVID_PCIE: + case AR5416_AR9100_DEVID: +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -36,6 +36,7 @@ + + #define ATHEROS_VENDOR_ID 0x168c + ++#define AR9300_DEVID_INVALID 0xabcd + #define AR5416_DEVID_PCI 0x0023 + #define AR5416_DEVID_PCIE 0x0024 + #define AR9160_DEVID_PCI 0x0027 +--- a/drivers/net/wireless/ath/ath9k/pci.c ++++ b/drivers/net/wireless/ath/ath9k/pci.c +@@ -774,6 +774,7 @@ static const struct pci_device_id ath_pc + .driver_data = ATH9K_PCI_BT_ANT_DIV }, + #endif + ++ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */ + { 0 } + }; + diff --git a/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch new file mode 100644 index 0000000000..5fd5c73a2f --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch @@ -0,0 +1,267 @@ +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -844,6 +844,9 @@ static inline int ath9k_dump_btcoex(stru + #ifdef CPTCFG_MAC80211_LEDS + void ath_init_leds(struct ath_softc *sc); + void ath_deinit_leds(struct ath_softc *sc); ++int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name, ++ const char *trigger, bool active_low); ++ + #else + static inline void ath_init_leds(struct ath_softc *sc) + { +@@ -980,6 +983,13 @@ void ath_ant_comb_scan(struct ath_softc + + #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ + ++struct ath_led { ++ struct list_head list; ++ struct ath_softc *sc; ++ const struct gpio_led *gpio; ++ struct led_classdev cdev; ++}; ++ + struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; +@@ -1033,9 +1043,8 @@ struct ath_softc { + spinlock_t chan_lock; + + #ifdef CPTCFG_MAC80211_LEDS +- bool led_registered; +- char led_name[32]; +- struct led_classdev led_cdev; ++ const char *led_default_trigger; ++ struct list_head leds; + #endif + + #ifdef CPTCFG_ATH9K_DEBUGFS +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -39,61 +39,111 @@ static void ath_fill_led_pin(struct ath_ + else + ah->led_pin = ATH_LED_PIN_DEF; + } ++} ++ ++static void ath_led_brightness(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev); ++ struct ath_softc *sc = led->sc; ++ ++ ath9k_ps_wakeup(sc); ++ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio, ++ (brightness != LED_OFF) ^ led->gpio->active_low); ++ ath9k_ps_restore(sc); ++} ++ ++static int ath_add_led(struct ath_softc *sc, struct ath_led *led) ++{ ++ const struct gpio_led *gpio = led->gpio; ++ int ret; ++ ++ led->cdev.name = gpio->name; ++ led->cdev.default_trigger = gpio->default_trigger; ++ led->cdev.brightness_set = ath_led_brightness; ++ ++ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev); ++ if (ret < 0) ++ return ret; ++ ++ led->sc = sc; ++ list_add(&led->list, &sc->leds); + + /* Configure gpio for output */ +- ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", ++ ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + +- /* LED off, active low */ +- ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1); ++ /* LED off */ ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); ++ ++ return 0; + } + +-static void ath_led_brightness(struct led_classdev *led_cdev, +- enum led_brightness brightness) ++int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name, ++ const char *trigger, bool active_low) + { +- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); +- u32 val = (brightness == LED_OFF); ++ struct ath_led *led; ++ struct gpio_led *gpio; ++ char *_name; ++ int ret; + +- if (sc->sc_ah->config.led_active_high) +- val = !val; ++ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1, ++ GFP_KERNEL); ++ if (!led) ++ return -ENOMEM; ++ ++ led->gpio = gpio = (struct gpio_led *) (led + 1); ++ _name = (char *) (led->gpio + 1); ++ ++ strcpy(_name, name); ++ gpio->name = _name; ++ gpio->gpio = gpio_num; ++ gpio->active_low = active_low; ++ gpio->default_trigger = trigger; ++ ++ ret = ath_add_led(sc, led); ++ if (unlikely(ret < 0)) ++ kfree(led); + +- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); ++ return ret; + } + + void ath_deinit_leds(struct ath_softc *sc) + { +- if (!sc->led_registered) +- return; ++ struct ath_led *led; + +- ath_led_brightness(&sc->led_cdev, LED_OFF); +- led_classdev_unregister(&sc->led_cdev); +- +- ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin); ++ while (!list_empty(&sc->leds)) { ++ led = list_first_entry(&sc->leds, struct ath_led, list); ++ list_del(&led->list); ++ ath_led_brightness(&led->cdev, LED_OFF); ++ led_classdev_unregister(&led->cdev); ++ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio); ++ kfree(led); ++ } + } + + void ath_init_leds(struct ath_softc *sc) + { +- int ret; ++ char led_name[32]; ++ const char *trigger; ++ ++ INIT_LIST_HEAD(&sc->leds); + + if (AR_SREV_9100(sc->sc_ah)) + return; + + ath_fill_led_pin(sc); + +- if (!ath9k_led_blink) +- sc->led_cdev.default_trigger = +- ieee80211_get_radio_led_name(sc->hw); +- +- snprintf(sc->led_name, sizeof(sc->led_name), +- "ath9k-%s", wiphy_name(sc->hw->wiphy)); +- sc->led_cdev.name = sc->led_name; +- sc->led_cdev.brightness_set = ath_led_brightness; ++ snprintf(led_name, sizeof(led_name), "ath9k-%s", ++ wiphy_name(sc->hw->wiphy)); + +- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); +- if (ret < 0) +- return; ++ if (ath9k_led_blink) ++ trigger = sc->led_default_trigger; ++ else ++ trigger = ieee80211_get_radio_led_name(sc->hw); + +- sc->led_registered = true; ++ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, ++ !sc->sc_ah->config.led_active_high); + } + #endif + +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -1055,7 +1055,7 @@ int ath9k_init_device(u16 devid, struct + + #ifdef CPTCFG_MAC80211_LEDS + /* must be initialized before ieee80211_register_hw */ +- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, ++ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, + ARRAY_SIZE(ath9k_tpt_blink)); + #endif +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1456,6 +1456,61 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++#ifdef CONFIG_MAC80211_LEDS ++ ++static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ char buf[32], *str, *name, *c; ++ ssize_t len; ++ unsigned int gpio; ++ bool active_low = false; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, ubuf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ name = strchr(buf, ','); ++ if (!name) ++ return -EINVAL; ++ ++ *(name++) = 0; ++ if (!*name) ++ return -EINVAL; ++ ++ c = strchr(name, '\n'); ++ if (c) ++ *c = 0; ++ ++ str = buf; ++ if (*str == '!') { ++ str++; ++ active_low = true; ++ } ++ ++ if (kstrtouint(str, 0, &gpio) < 0) ++ return -EINVAL; ++ ++ if (gpio >= sc->sc_ah->caps.num_gpio_pins) ++ return -EINVAL; ++ ++ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0) ++ return -EINVAL; ++ ++ return count; ++} ++ ++static const struct file_operations fops_gpio_led = { ++ .write = write_file_gpio_led, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++#endif ++ + + int ath9k_init_debug(struct ath_hw *ah) + { +@@ -1480,6 +1535,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); ++#ifdef CONFIG_MAC80211_LEDS ++ debugfs_create_file("gpio_led", S_IWUSR, ++ sc->debug.debugfs_phy, sc, &fops_gpio_led); ++#endif + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, diff --git a/package/kernel/mac80211/patches/ath9k/531-ath9k_extra_platform_leds.patch b/package/kernel/mac80211/patches/ath9k/531-ath9k_extra_platform_leds.patch new file mode 100644 index 0000000000..8ed7ad8a09 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/531-ath9k_extra_platform_leds.patch @@ -0,0 +1,76 @@ +--- a/include/linux/ath9k_platform.h ++++ b/include/linux/ath9k_platform.h +@@ -46,6 +46,9 @@ struct ath9k_platform_data { + int (*external_reset)(void); + + bool use_eeprom; ++ ++ int num_leds; ++ const struct gpio_led *leds; + }; + + #endif /* _LINUX_ATH9K_PLATFORM_H */ +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -15,6 +15,7 @@ + */ + + #include "ath9k.h" ++#include + + /********************************/ + /* LED functions */ +@@ -108,6 +109,24 @@ int ath_create_gpio_led(struct ath_softc + return ret; + } + ++static int ath_create_platform_led(struct ath_softc *sc, ++ const struct gpio_led *gpio) ++{ ++ struct ath_led *led; ++ int ret; ++ ++ led = kzalloc(sizeof(*led), GFP_KERNEL); ++ if (!led) ++ return -ENOMEM; ++ ++ led->gpio = gpio; ++ ret = ath_add_led(sc, led); ++ if (ret < 0) ++ kfree(led); ++ ++ return ret; ++} ++ + void ath_deinit_leds(struct ath_softc *sc) + { + struct ath_led *led; +@@ -124,8 +143,10 @@ void ath_deinit_leds(struct ath_softc *s + + void ath_init_leds(struct ath_softc *sc) + { ++ struct ath9k_platform_data *pdata = sc->dev->platform_data; + char led_name[32]; + const char *trigger; ++ int i; + + INIT_LIST_HEAD(&sc->leds); + +@@ -134,6 +155,17 @@ void ath_init_leds(struct ath_softc *sc) + + ath_fill_led_pin(sc); + ++ if (pdata && pdata->leds && pdata->num_leds) ++ for (i = 0; i < pdata->num_leds; i++) { ++ if (pdata->leds[i].gpio == sc->sc_ah->led_pin) ++ sc->sc_ah->led_pin = -1; ++ ++ ath_create_platform_led(sc, &pdata->leds[i]); ++ } ++ ++ if (sc->sc_ah->led_pin < 0) ++ return; ++ + snprintf(led_name, sizeof(led_name), "ath9k-%s", + wiphy_name(sc->hw->wiphy)); + diff --git a/package/kernel/mac80211/patches/ath9k/540-ath9k_reduce_ani_interval.patch b/package/kernel/mac80211/patches/ath9k/540-ath9k_reduce_ani_interval.patch new file mode 100644 index 0000000000..e899903478 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/540-ath9k_reduce_ani_interval.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/ani.h ++++ b/drivers/net/wireless/ath/ath9k/ani.h +@@ -42,7 +42,7 @@ + #define ATH9K_ANI_PERIOD 300 + + /* in ms */ +-#define ATH9K_ANI_POLLINTERVAL 1000 ++#define ATH9K_ANI_POLLINTERVAL 300 + + #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0 + #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20 diff --git a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch new file mode 100644 index 0000000000..f93a6fe5cd --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch @@ -0,0 +1,139 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1512,6 +1512,50 @@ static const struct file_operations fops + #endif + + ++static ssize_t read_file_diag(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ char buf[32]; ++ unsigned int len; ++ ++ len = sprintf(buf, "0x%08lx\n", ah->diag); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_diag(struct file *file, const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ unsigned long diag; ++ char buf[32]; ++ ssize_t len; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ if (kstrtoul(buf, 0, &diag)) ++ return -EINVAL; ++ ++ ah->diag = diag; ++ ath9k_hw_update_diag(ah); ++ ++ return count; ++} ++ ++static const struct file_operations fops_diag = { ++ .read = read_file_diag, ++ .write = write_file_diag, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1539,6 +1583,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 ++ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++ sc, &fops_diag); + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -522,6 +522,12 @@ enum { + ATH9K_RESET_COLD, + }; + ++enum { ++ ATH_DIAG_DISABLE_RX, ++ ATH_DIAG_DISABLE_TX, ++ ATH_DIAG_TRIGGER_ERROR, ++}; ++ + struct ath9k_hw_version { + u32 magic; + u16 devid; +@@ -810,6 +816,8 @@ struct ath_hw { + u32 ah_flags; + s16 nf_override; + ++ unsigned long diag; ++ + bool reset_power_on; + bool htc_reset_init; + +@@ -1076,6 +1084,7 @@ void ath9k_hw_check_nav(struct ath_hw *a + bool ath9k_hw_check_alive(struct ath_hw *ah); + + bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); ++void ath9k_hw_update_diag(struct ath_hw *ah); + + /* Generic hw timer primitives */ + 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 +@@ -1883,6 +1883,20 @@ u32 ath9k_hw_get_tsf_offset(struct times + } + EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); + ++void ath9k_hw_update_diag(struct ath_hw *ah) ++{ ++ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag)) ++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); ++ else ++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); ++ ++ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag)) ++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); ++ else ++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); ++} ++EXPORT_SYMBOL(ath9k_hw_update_diag); ++ + int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, + struct ath9k_hw_cal_data *caldata, bool fastcc) + { +@@ -2091,6 +2105,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ar9003_hw_disable_phy_restart(ah); + + ath9k_hw_apply_gpio_override(ah); ++ ath9k_hw_update_diag(ah); + + if (AR_SREV_9565(ah) && common->bt_ant_diversity) + 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 +@@ -531,6 +531,11 @@ irqreturn_t ath_isr(int irq, void *dev) + if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) + return IRQ_HANDLED; + ++ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) { ++ status |= ATH9K_INT_FATAL; ++ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag); ++ } ++ + /* + * If there are no status bits set, then this interrupt was not + * for me (should have been caught above). diff --git a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch new file mode 100644 index 0000000000..0d938a3730 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch @@ -0,0 +1,186 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -723,6 +723,7 @@ struct ath_spec_scan { + * @config_pci_powersave: + * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC + * ++ * @get_adc_entropy: get entropy from the raw ADC I/Q output + * @spectral_scan_config: set parameters for spectral scan and enable/disable it + * @spectral_scan_trigger: trigger a spectral scan run + * @spectral_scan_wait: wait for a spectral scan run to finish +@@ -745,6 +746,7 @@ struct ath_hw_ops { + struct ath_hw_antcomb_conf *antconf); + void (*antdiv_comb_conf_set)(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf); ++ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len); + void (*spectral_scan_config)(struct ath_hw *ah, + struct ath_spec_scan *param); + void (*spectral_scan_trigger)(struct ath_hw *ah); +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -1927,6 +1927,26 @@ void ar9003_hw_init_rate_txpower(struct + } + } + ++static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) ++{ ++ int i, j; ++ ++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); ++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); ++ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0); ++ ++ memset(buf, 0, len); ++ for (i = 0; i < len; i++) { ++ for (j = 0; j < 4; j++) { ++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); ++ ++ buf[i] <<= 2; ++ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9); ++ udelay(1); ++ } ++ } ++} ++ + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +@@ -1963,6 +1983,7 @@ void ar9003_hw_attach_phy_ops(struct ath + priv_ops->set_radar_params = ar9003_hw_set_radar_params; + priv_ops->fast_chan_change = ar9003_hw_fast_chan_change; + ++ ops->get_adc_entropy = ar9003_hw_get_adc_entropy; + ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; + ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; + 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 +@@ -818,7 +818,8 @@ static void ath9k_init_txpower_limits(st + if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) + ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); + +- ah->curchan = curchan; ++ if (curchan) ++ ah->curchan = curchan; + } + + static const struct ieee80211_iface_limit if_limits[] = { +@@ -1015,6 +1016,18 @@ static void ath9k_set_hw_capab(struct at + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); + } + ++static void ath_get_initial_entropy(struct ath_softc *sc) ++{ ++ struct ath_hw *ah = sc->sc_ah; ++ char buf[256]; ++ ++ /* reuse last channel initialized by the tx power test */ ++ ath9k_hw_reset(ah, ah->curchan, NULL, false); ++ ++ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf)); ++ add_device_randomness(buf, sizeof(buf)); ++} ++ + int ath9k_init_device(u16 devid, struct ath_softc *sc, + const struct ath_bus_ops *bus_ops) + { +@@ -1060,6 +1073,8 @@ int ath9k_init_device(u16 devid, struct + ARRAY_SIZE(ath9k_tpt_blink)); + #endif + ++ ath_get_initial_entropy(sc); ++ + /* Register with mac80211 */ + error = ieee80211_register_hw(hw); + if (error) +--- a/drivers/net/wireless/ath/ath9k/hw-ops.h ++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h +@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp + ath9k_hw_ops(ah)->tx99_set_txpower(ah, power); + } + ++static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah, ++ u8 *buf, size_t len) ++{ ++ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len); ++} ++ + #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT + + static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -1349,9 +1349,30 @@ void ar5008_hw_init_rate_txpower(struct + } + } + ++static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) ++{ ++ int i, j; ++ ++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); ++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); ++ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0); ++ ++ memset(buf, 0, len); ++ for (i = 0; i < len; i++) { ++ for (j = 0; j < 4; j++) { ++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); ++ ++ buf[i] <<= 2; ++ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8); ++ udelay(1); ++ } ++ } ++} ++ + int ar5008_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); ++ struct ath_hw_ops *ops = ath9k_hw_ops(ah); + static const u32 ar5416_cca_regs[6] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, +@@ -1366,6 +1387,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ + if (ret) + return ret; + ++ ops->get_adc_entropy = ar5008_hw_get_adc_entropy; ++ + priv_ops->rf_set_freq = ar5008_hw_set_channel; + priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; + +--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h ++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h +@@ -20,6 +20,12 @@ + #define PHY_AGC_CLR 0x10000000 + #define RFSILENT_BB 0x00002000 + ++#define AR_PHY_TEST_BBB_OBS_SEL 0x780000 ++#define AR_PHY_TEST_BBB_OBS_SEL_S 19 ++ ++#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23 ++#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S) ++ + #define AR_PHY_TURBO 0x9804 + #define AR_PHY_FC_TURBO_MODE 0x00000001 + #define AR_PHY_FC_TURBO_SHORT 0x00000002 +@@ -36,6 +42,9 @@ + + #define AR_PHY_TEST2 0x9808 + ++#define AR_PHY_TEST2_RX_OBS_SEL 0x3C00 ++#define AR_PHY_TEST2_RX_OBS_SEL_S 10 ++ + #define AR_PHY_TIMING2 0x9810 + #define AR_PHY_TIMING3 0x9814 + #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +@@ -393,6 +402,8 @@ + #define AR_PHY_RFBUS_GRANT 0x9C20 + #define AR_PHY_RFBUS_GRANT_EN 0x00000001 + ++#define AR_PHY_TST_ADC 0x9C24 ++ + #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 + #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 + diff --git a/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch new file mode 100644 index 0000000000..93eee34b64 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/544-ath9k-ar933x-usb-hang-workaround.patch @@ -0,0 +1,79 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -248,6 +248,19 @@ void ath9k_hw_get_channel_centers(struct + centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); + } + ++static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah) ++{ ++ /* On AR9330 and AR9340 devices, some PHY registers must be ++ * tuned to gain better stability/performance. These registers ++ * might be changed while doing wlan reset so the registers must ++ * be reprogrammed after each reset. ++ */ ++ REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20)); ++ REG_RMW(ah, AR_PHY_USB_CTRL2, ++ (1 << 21) | (0xf << 22), ++ (1 << 21) | (0x3 << 22)); ++} ++ + /******************/ + /* Chip Revisions */ + /******************/ +@@ -1455,6 +1468,9 @@ static bool ath9k_hw_set_reset(struct at + udelay(50); + } + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return true; + } + +@@ -1554,6 +1570,9 @@ static bool ath9k_hw_chip_reset(struct a + ar9003_hw_internal_regulator_apply(ah); + ath9k_hw_init_pll(ah, chan); + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return true; + } + +@@ -1861,8 +1880,14 @@ static int ath9k_hw_do_fastcc(struct ath + if (AR_SREV_9271(ah)) + ar9002_hw_load_ani_reg(ah, chan); + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return 0; + fail: ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return -EINVAL; + } + +@@ -2116,6 +2141,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ath9k_hw_set_radar_params(ah); + } + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return 0; + } + EXPORT_SYMBOL(ath9k_hw_reset); +--- a/drivers/net/wireless/ath/ath9k/phy.h ++++ b/drivers/net/wireless/ath/ath9k/phy.h +@@ -48,6 +48,9 @@ + #define AR_PHY_PLL_CONTROL 0x16180 + #define AR_PHY_PLL_MODE 0x16184 + ++#define AR_PHY_USB_CTRL1 0x16c84 ++#define AR_PHY_USB_CTRL2 0x16c88 ++ + enum ath9k_ant_div_comb_lna_conf { + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, + ATH_ANT_DIV_COMB_LNA2, diff --git a/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch b/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch new file mode 100644 index 0000000000..466767adb9 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch @@ -0,0 +1,155 @@ +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -978,55 +978,6 @@ static bool ar5008_hw_ani_control_new(st + * on == 0 means more noise imm + */ + u32 on = param ? 1 : 0; +- /* +- * make register setting for default +- * (weak sig detect ON) come from INI file +- */ +- int m1ThreshLow = on ? +- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; +- int m2ThreshLow = on ? +- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; +- int m1Thresh = on ? +- aniState->iniDef.m1Thresh : m1Thresh_off; +- int m2Thresh = on ? +- aniState->iniDef.m2Thresh : m2Thresh_off; +- int m2CountThr = on ? +- aniState->iniDef.m2CountThr : m2CountThr_off; +- int m2CountThrLow = on ? +- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; +- int m1ThreshLowExt = on ? +- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; +- int m2ThreshLowExt = on ? +- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; +- int m1ThreshExt = on ? +- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; +- int m2ThreshExt = on ? +- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +- m1ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +- m2ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M1_THRESH, m1Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2_THRESH, m2Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +- m2CountThrLow); +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); + + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -42,20 +42,6 @@ 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 +- */ +-static const int m1ThreshLow_off = 127; +-static const int m2ThreshLow_off = 127; +-static const int m1Thresh_off = 127; +-static const int m2Thresh_off = 127; +-static const int m2CountThr_off = 31; +-static const int m2CountThrLow_off = 63; +-static const int m1ThreshLowExt_off = 127; +-static const int m2ThreshLowExt_off = 127; +-static const int m1ThreshExt_off = 127; +-static const int m2ThreshExt_off = 127; +- + static const u8 ofdm2pwr[] = { + ALL_TARGET_LEGACY_6_24, + ALL_TARGET_LEGACY_6_24, +@@ -1077,11 +1063,6 @@ static bool ar9003_hw_ani_control(struct + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *chan = ah->curchan; + struct ar5416AniState *aniState = &ah->ani; +- int m1ThreshLow, m2ThreshLow; +- int m1Thresh, m2Thresh; +- int m2CountThr, m2CountThrLow; +- int m1ThreshLowExt, m2ThreshLowExt; +- int m1ThreshExt, m2ThreshExt; + s32 value, value2; + + switch (cmd & ah->ani_function) { +@@ -1095,61 +1076,6 @@ static bool ar9003_hw_ani_control(struct + */ + u32 on = param ? 1 : 0; + +- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) +- goto skip_ws_det; +- +- m1ThreshLow = on ? +- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; +- m2ThreshLow = on ? +- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; +- m1Thresh = on ? +- aniState->iniDef.m1Thresh : m1Thresh_off; +- m2Thresh = on ? +- aniState->iniDef.m2Thresh : m2Thresh_off; +- m2CountThr = on ? +- aniState->iniDef.m2CountThr : m2CountThr_off; +- m2CountThrLow = on ? +- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; +- m1ThreshLowExt = on ? +- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; +- m2ThreshLowExt = on ? +- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; +- m1ThreshExt = on ? +- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; +- m2ThreshExt = on ? +- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +- m1ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +- m2ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M1_THRESH, +- m1Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2_THRESH, +- m2Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2COUNT_THR, +- m2CountThr); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +- m2CountThrLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, +- m1ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, +- m2ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH, +- m1ThreshExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH, +- m2ThreshExt); +-skip_ws_det: + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); diff --git a/package/kernel/mac80211/patches/ath9k/547-ath9k_led_defstate_fix.patch b/package/kernel/mac80211/patches/ath9k/547-ath9k_led_defstate_fix.patch new file mode 100644 index 0000000000..5d84cf0c42 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/547-ath9k_led_defstate_fix.patch @@ -0,0 +1,29 @@ +From: Michal Cieslakiewicz +Date: Sun, 31 Jan 2016 20:48:49 +0100 +Subject: [PATCH v4 2/8] mac80211: ath9k: set default state for platform LEDs + +Support default state for platform LEDs connected to ath9k device. +Now LEDs are correctly set on or off at ath9k module initialization. +Very useful if power LED is connected to wireless chip. + +Signed-off-by: Michal Cieslakiewicz +--- + gpio.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -74,8 +74,11 @@ static int ath_add_led(struct ath_softc + ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + +- /* LED off */ +- ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); ++ /* Set default LED state */ ++ if (gpio->default_state == LEDS_GPIO_DEFSTATE_ON) ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, !gpio->active_low); ++ else ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); + + return 0; + } diff --git a/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch new file mode 100644 index 0000000000..88198a4562 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch @@ -0,0 +1,251 @@ +From: Michal Cieslakiewicz +Date: Sun, 31 Jan 2016 21:01:31 +0100 +Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO + +Enable access to GPIO chip and its pins for Atheros AR92xx +wireless devices. For now AR9285 and AR9287 are supported. + +Signed-off-by: Michal Cieslakiewicz +Signed-off-by: Felix Fietkau +--- +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include "common.h" + #include "debug.h" +@@ -990,6 +991,14 @@ struct ath_led { + struct led_classdev cdev; + }; + ++#ifdef CONFIG_GPIOLIB ++struct ath9k_gpio_chip { ++ struct ath_softc *sc; ++ char label[32]; ++ struct gpio_chip gchip; ++}; ++#endif ++ + struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; +@@ -1045,6 +1054,9 @@ struct ath_softc { + #ifdef CPTCFG_MAC80211_LEDS + const char *led_default_trigger; + struct list_head leds; ++#ifdef CONFIG_GPIOLIB ++ struct ath9k_gpio_chip *gpiochip; ++#endif + #endif + + #ifdef CPTCFG_ATH9K_DEBUGFS +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -16,13 +16,139 @@ + + #include "ath9k.h" + #include ++#include ++ ++#ifdef CPTCFG_MAC80211_LEDS ++ ++#ifdef CONFIG_GPIOLIB ++ ++/***************/ ++/* GPIO Chip */ ++/***************/ ++ ++/* gpio_chip handler : set GPIO to input */ ++static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ ++ ath9k_hw_gpio_request_in(gc->sc->sc_ah, offset, "ath9k-gpio"); ++ ++ return 0; ++} ++ ++/* gpio_chip handler : set GPIO to output */ ++static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ ++ ath9k_hw_gpio_request_out(gc->sc->sc_ah, offset, "ath9k-gpio", ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value); ++ ++ return 0; ++} ++ ++/* gpio_chip handler : query GPIO direction (0=out, 1=in) */ ++static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ struct ath_hw *ah = gc->sc->sc_ah; ++ ++ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3); ++} ++ ++/* gpio_chip handler : get GPIO pin value */ ++static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ ++ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset); ++} ++ ++/* gpio_chip handler : set GPIO pin to value */ ++static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ ++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value); ++} ++ ++/* register GPIO chip */ ++static void ath9k_register_gpio_chip(struct ath_softc *sc) ++{ ++ struct ath9k_gpio_chip *gc; ++ struct ath_hw *ah = sc->sc_ah; ++ ++ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL); ++ if (!gc) ++ return; ++ ++ gc->sc = sc; ++ snprintf(gc->label, sizeof(gc->label), "ath9k-%s", ++ wiphy_name(sc->hw->wiphy)); ++#ifdef CONFIG_OF ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) ++ gc->gchip.parent = sc->dev; ++#else ++ gc->gchip.dev = sc->dev; ++#endif ++#endif ++ gc->gchip.label = gc->label; ++ gc->gchip.base = -1; /* determine base automatically */ ++ gc->gchip.ngpio = ah->caps.num_gpio_pins; ++ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input; ++ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output; ++ gc->gchip.get_direction = ath9k_gpio_pin_get_dir; ++ gc->gchip.get = ath9k_gpio_pin_get; ++ gc->gchip.set = ath9k_gpio_pin_set; ++ ++ if (gpiochip_add(&gc->gchip)) { ++ kfree(gc); ++ return; ++ } ++ ++#ifdef CONFIG_OF ++ gc->gchip.owner = NULL; ++#endif ++ sc->gpiochip = gc; ++} ++ ++/* remove GPIO chip */ ++static void ath9k_unregister_gpio_chip(struct ath_softc *sc) ++{ ++ struct ath9k_gpio_chip *gc = sc->gpiochip; ++ ++ if (!gc) ++ return; ++ ++ gpiochip_remove(&gc->gchip); ++ kfree(gc); ++ sc->gpiochip = NULL; ++} ++ ++#else /* CONFIG_GPIOLIB */ ++ ++static inline void ath9k_register_gpio_chip(struct ath_softc *sc) ++{ ++} ++ ++static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc) ++{ ++} ++ ++#endif /* CONFIG_GPIOLIB */ + + /********************************/ + /* LED functions */ + /********************************/ + +-#ifdef CPTCFG_MAC80211_LEDS +- + static void ath_fill_led_pin(struct ath_softc *sc) + { + struct ath_hw *ah = sc->sc_ah; +@@ -80,6 +206,12 @@ static int ath_add_led(struct ath_softc + else + ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); + ++#ifdef CONFIG_GPIOLIB ++ /* If there is GPIO chip configured, reserve LED pin */ ++ if (sc->gpiochip) ++ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name); ++#endif ++ + return 0; + } + +@@ -136,17 +268,24 @@ void ath_deinit_leds(struct ath_softc *s + + while (!list_empty(&sc->leds)) { + led = list_first_entry(&sc->leds, struct ath_led, list); ++#ifdef CONFIG_GPIOLIB ++ /* If there is GPIO chip configured, free LED pin */ ++ if (sc->gpiochip) ++ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio); ++#endif + list_del(&led->list); + ath_led_brightness(&led->cdev, LED_OFF); + led_classdev_unregister(&led->cdev); + ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio); + kfree(led); + } ++ ath9k_unregister_gpio_chip(sc); + } + + void ath_init_leds(struct ath_softc *sc) + { + struct ath9k_platform_data *pdata = sc->dev->platform_data; ++ struct device_node *np = sc->dev->of_node; + char led_name[32]; + const char *trigger; + int i; +@@ -156,6 +295,15 @@ void ath_init_leds(struct ath_softc *sc) + if (AR_SREV_9100(sc->sc_ah)) + return; + ++ if (!np) ++ ath9k_register_gpio_chip(sc); ++ ++ /* setup gpio controller only if requested and skip the led_pin setup */ ++ if (of_property_read_bool(np, "gpio-controller")) { ++ ath9k_register_gpio_chip(sc); ++ return; ++ } ++ + ath_fill_led_pin(sc); + + if (pdata && pdata->leds && pdata->num_leds) +@@ -180,6 +328,7 @@ void ath_init_leds(struct ath_softc *sc) + ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, + !sc->sc_ah->config.led_active_high); + } ++ + #endif + + /*******************/ diff --git a/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch new file mode 100644 index 0000000000..83076b8ae4 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch @@ -0,0 +1,143 @@ +From: Michal Cieslakiewicz +Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons + +Enable platform-defined GPIO button support for ath9k device. +Key poller is activated for attached platform buttons. +Requires ath9k GPIO chip access. + +Signed-off-by: Michal Cieslakiewicz +Signed-off-by: Felix Fietkau +--- +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -1056,6 +1056,7 @@ struct ath_softc { + struct list_head leds; + #ifdef CONFIG_GPIOLIB + struct ath9k_gpio_chip *gpiochip; ++ struct platform_device *btnpdev; /* gpio-keys-polled */ + #endif + #endif + +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -17,6 +17,8 @@ + #include "ath9k.h" + #include + #include ++#include ++#include + + #ifdef CPTCFG_MAC80211_LEDS + +@@ -133,6 +135,67 @@ static void ath9k_unregister_gpio_chip(s + sc->gpiochip = NULL; + } + ++/******************/ ++/* GPIO Buttons */ ++/******************/ ++ ++/* add GPIO buttons */ ++static void ath9k_init_buttons(struct ath_softc *sc) ++{ ++ struct ath9k_platform_data *pdata = sc->dev->platform_data; ++ struct platform_device *pdev; ++ struct gpio_keys_platform_data gkpdata; ++ struct gpio_keys_button *bt; ++ int i; ++ ++ if (!sc->gpiochip) ++ return; ++ ++ if (!pdata || !pdata->btns || !pdata->num_btns) ++ return; ++ ++ bt = devm_kmemdup(sc->dev, pdata->btns, ++ pdata->num_btns * sizeof(struct gpio_keys_button), ++ GFP_KERNEL); ++ if (!bt) ++ return; ++ ++ for (i = 0; i < pdata->num_btns; i++) { ++ if (pdata->btns[i].gpio == sc->sc_ah->led_pin) ++ sc->sc_ah->led_pin = -1; ++ ++ ath9k_hw_gpio_request_in(sc->sc_ah, pdata->btns[i].gpio, ++ "ath9k-gpio"); ++ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio; ++ } ++ ++ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data)); ++ gkpdata.buttons = bt; ++ gkpdata.nbuttons = pdata->num_btns; ++ gkpdata.poll_interval = pdata->btn_poll_interval; ++ ++ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled", ++ PLATFORM_DEVID_AUTO, &gkpdata, ++ sizeof(gkpdata)); ++ if (!IS_ERR_OR_NULL(pdev)) ++ sc->btnpdev = pdev; ++ else { ++ sc->btnpdev = NULL; ++ devm_kfree(sc->dev, bt); ++ } ++} ++ ++/* remove GPIO buttons */ ++static void ath9k_deinit_buttons(struct ath_softc *sc) ++{ ++ if (!sc->gpiochip || !sc->btnpdev) ++ return; ++ ++ platform_device_unregister(sc->btnpdev); ++ ++ sc->btnpdev = NULL; ++} ++ + #else /* CONFIG_GPIOLIB */ + + static inline void ath9k_register_gpio_chip(struct ath_softc *sc) +@@ -143,6 +206,14 @@ static inline void ath9k_unregister_gpio + { + } + ++static inline void ath9k_init_buttons(struct ath_softc *sc) ++{ ++} ++ ++static inline void ath9k_deinit_buttons(struct ath_softc *sc) ++{ ++} ++ + #endif /* CONFIG_GPIOLIB */ + + /********************************/ +@@ -266,6 +337,7 @@ void ath_deinit_leds(struct ath_softc *s + { + struct ath_led *led; + ++ ath9k_deinit_buttons(sc); + while (!list_empty(&sc->leds)) { + led = list_first_entry(&sc->leds, struct ath_led, list); + #ifdef CONFIG_GPIOLIB +@@ -305,6 +377,7 @@ void ath_init_leds(struct ath_softc *sc) + } + + ath_fill_led_pin(sc); ++ ath9k_init_buttons(sc); + + if (pdata && pdata->leds && pdata->num_leds) + for (i = 0; i < pdata->num_leds; i++) { +--- a/include/linux/ath9k_platform.h ++++ b/include/linux/ath9k_platform.h +@@ -49,6 +49,10 @@ struct ath9k_platform_data { + + int num_leds; + const struct gpio_led *leds; ++ ++ unsigned num_btns; ++ const struct gpio_keys_button *btns; ++ unsigned btn_poll_interval; + }; + + #endif /* _LINUX_ATH9K_PLATFORM_H */ diff --git a/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch b/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch new file mode 100644 index 0000000000..7d3a334c42 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/550-ath9k-disable-bands-via-dt.patch @@ -0,0 +1,15 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -627,6 +627,12 @@ static int ath9k_of_init(struct ath_soft + + ath_dbg(common, CONFIG, "parsing configuration from OF node\n"); + ++ if (of_property_read_bool(np, "qca,disable-2ghz")) ++ ah->disable_2ghz = true; ++ ++ if (of_property_read_bool(np, "qca,disable-5ghz")) ++ ah->disable_5ghz = true; ++ + if (of_property_read_bool(np, "qca,no-eeprom")) { + /* ath9k-eeprom--.bin */ + scnprintf(eeprom_name, sizeof(eeprom_name), diff --git a/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch b/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch new file mode 100644 index 0000000000..cd2bdbf1a0 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch @@ -0,0 +1,403 @@ +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -15,6 +15,7 @@ + */ + + #include "ath9k.h" ++#include "hsr.h" + + /* Set/change channels. If the channel is really being changed, it's done + * by reseting the chip. To accomplish this we must first cleanup any pending +@@ -22,6 +23,7 @@ + */ + static int ath_set_channel(struct ath_softc *sc) + { ++ struct device_node *np = sc->dev->of_node; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_hw *hw = sc->hw; +@@ -42,6 +44,11 @@ static int ath_set_channel(struct ath_so + ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", + chan->center_freq, chandef->width); + ++ if (of_property_read_bool(np, "ubnt,hsr")) { ++ ath9k_hsr_enable(ah, chandef->width, chan->center_freq); ++ ath9k_hsr_status(ah); ++ } ++ + /* update survey stats for the old channel before switching */ + spin_lock_irqsave(&common->cc_lock, flags); + ath_update_survey_stats(sc); +--- /dev/null ++++ b/drivers/net/wireless/ath/ath9k/hsr.c +@@ -0,0 +1,247 @@ ++/* ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Kirill Berezin ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hw.h" ++#include "ath9k.h" ++ ++#define HSR_GPIO_CSN 8 ++#define HSR_GPIO_CLK 6 ++#define HSR_GPIO_DOUT 7 ++#define HSR_GPIO_DIN 5 ++ ++/* delays are in useconds */ ++#define HSR_DELAY_HALF_TICK 100 ++#define HSR_DELAY_PRE_WRITE 75 ++#define HSR_DELAY_FINAL 20000 ++#define HSR_DELAY_TRAILING 200 ++ ++void ath9k_hsr_init(struct ath_hw *ah) ++{ ++ ath9k_hw_gpio_request_in(ah, HSR_GPIO_DIN, NULL); ++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CSN, NULL, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CLK, NULL, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_DOUT, NULL, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); ++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0); ++ ++ udelay(HSR_DELAY_TRAILING); ++} ++ ++static u32 ath9k_hsr_write_byte(struct ath_hw *ah, int delay, u32 value) ++{ ++ struct ath_common *common = ath9k_hw_common(ah); ++ int i; ++ u32 rval = 0; ++ ++ udelay(delay); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ for (i = 0; i < 8; ++i) { ++ rval = rval << 1; ++ ++ /* pattern is left to right, that is 7-th bit runs first */ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); ++ udelay(HSR_DELAY_HALF_TICK); ++ } ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ ath_dbg(common, CONFIG, "ath9k_hsr_write_byte: write byte %d return value is %d %c\n", ++ value, rval, rval > 32 ? rval : '-'); ++ ++ return rval & 0xff; ++} ++ ++static int ath9k_hsr_write_a_chain(struct ath_hw *ah, char *chain, int items) ++{ ++ int status = 0; ++ int i = 0; ++ int err; ++ ++ /* a preamble */ ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ ++ /* clear HSR's reply buffer */ ++ if (status) { ++ int loop = 0; ++ ++ for (loop = 0; (loop < 42) && status; ++loop) ++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, ++ 0); ++ ++ if (loop >= 42) { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_write_a_chain: can't clear an output buffer after a 42 cycles.\n"); ++ return -1; ++ } ++ } ++ ++ for (i = 0; (i < items) && (chain[i] != 0); ++i) ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]); ++ ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ mdelay(HSR_DELAY_FINAL / 1000); ++ ++ /* reply */ ++ memset(chain, 0, items); ++ ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ udelay(HSR_DELAY_TRAILING); ++ ++ for (i = 0; i < (items - 1); ++i) { ++ u32 ret; ++ ++ ret = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ if (ret != 0) ++ chain[i] = (char)ret; ++ else ++ break; ++ ++ udelay(HSR_DELAY_TRAILING); ++ } ++ ++ if (i <= 1) ++ return 0; ++ ++ err = kstrtoint(chain + 1, 10, &i); ++ if (err) ++ return err; ++ ++ return i; ++} ++ ++int ath9k_hsr_disable(struct ath_hw *ah) ++{ ++ char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0}; ++ int ret; ++ ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if ((ret > 0) && (*cmd == 'B')) ++ return 0; ++ ++ return -1; ++} ++ ++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq) ++{ ++ char cmd[10]; ++ int ret; ++ ++ /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn ++ * 20MHz on invalid values ++ */ ++ if ((bw != 5) && (bw != 10) && (bw != 20) && (bw != 40)) ++ bw = 20; ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'b'; ++ snprintf(cmd + 1, 3, "%02d", bw); ++ ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if ((*cmd != 'B') || (ret != bw)) { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d)\n", ++ 'b', bw, *cmd, ret); ++ return -1; ++ } ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'x'; ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if (*cmd != 'X') { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed 'x' command -> reply (%d, %d)\n", ++ *cmd, ret); ++ return -1; ++ } ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'm'; ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if (*cmd != 'M') { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed 'm' command -> reply (%d, %d)\n", ++ *cmd, ret); ++ return -1; ++ } ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'f'; ++ snprintf(cmd + 1, 6, "%05d", fq); ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if ((*cmd != 'F') && (ret != fq)) { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed set frequency -> reply (%d, %d)\n", ++ *cmd, ret); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ath9k_hsr_status(struct ath_hw *ah) ++{ ++ char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++ int ret; ++ ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if (*cmd != 'S') { ++ ATH_DBG_WARN(1, "ath9k_hsr_status: returned %d,%d\n", *cmd, ++ ret); ++ return -1; ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath9k/hsr.h +@@ -0,0 +1,48 @@ ++/* ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Kirill Berezin ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#ifndef HSR_H ++#define HSR_H ++ ++#ifdef CPTCFG_ATH9K_UBNTHSR ++ ++void ath9k_hsr_init(struct ath_hw *ah); ++int ath9k_hsr_disable(struct ath_hw *ah); ++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq); ++int ath9k_hsr_status(struct ath_hw *ah); ++ ++#else ++static inline void ath9k_hsr_init(struct ath_hw *ah) {} ++ ++static inline int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq) ++{ ++ return 0; ++} ++ ++static inline int ath9k_hsr_disable(struct ath_hw *ah) { return 0; } ++static inline int ath9k_hsr_status(struct ath_hw *ah) { return 0; } ++ ++#endif ++ ++#endif /* HSR_H */ +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -18,6 +18,7 @@ + #include + #include "ath9k.h" + #include "btcoex.h" ++#include "hsr.h" + + static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop); +@@ -652,6 +653,7 @@ void ath_reset_work(struct work_struct * + static int ath9k_start(struct ieee80211_hw *hw) + { + struct ath_softc *sc = hw->priv; ++ struct device_node *np = sc->dev->of_node; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan; +@@ -730,6 +732,11 @@ static int ath9k_start(struct ieee80211_ + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + } + ++ if (of_property_read_bool(np, "ubnt,hsr")) { ++ ath9k_hsr_init(ah); ++ ath9k_hsr_disable(ah); ++ } ++ + /* + * Reset key cache to sane defaults (all entries cleared) instead of + * semi-random values after suspend/resume. +--- a/drivers/net/wireless/ath/ath9k/Makefile ++++ b/drivers/net/wireless/ath/ath9k/Makefile +@@ -17,6 +17,7 @@ ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += d + ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o + ath9k-$(CPTCFG_ATH9K_WOW) += wow.o + ath9k-$(CPTCFG_ATH9K_HWRNG) += rng.o ++ath9k-$(CPTCFG_ATH9K_UBNTHSR) += hsr.o + + ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o + +--- a/local-symbols ++++ b/local-symbols +@@ -113,6 +113,7 @@ ATH9K_WOW= + ATH9K_RFKILL= + ATH9K_CHANNEL_CONTEXT= + ATH9K_PCOEM= ++ATH9K_UBNTHSR= + ATH9K_PCI_NO_EEPROM= + ATH9K_HTC= + ATH9K_HTC_DEBUGFS= +--- a/drivers/net/wireless/ath/ath9k/Kconfig ++++ b/drivers/net/wireless/ath/ath9k/Kconfig +@@ -58,6 +58,19 @@ config ATH9K_AHB + Say Y, if you have a SoC with a compatible built-in + wireless MAC. Say N if unsure. + ++config ATH9K_UBNTHSR ++ bool "Ubiquiti UniFi Outdoor Plus HSR support" ++ depends on ATH9K ++ ---help--- ++ This options enables code to control the HSR RF ++ filter in the receive path of the Ubiquiti UniFi ++ Outdoor Plus access point. ++ ++ Say Y if you want to use the access point. The ++ code will only be used if the device is detected, ++ so it does not harm other setup other than occupying ++ a bit of memory. ++ + config ATH9K_DEBUGFS + bool "Atheros ath9k debugging" + depends on ATH9K && DEBUG_FS diff --git a/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch b/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch new file mode 100644 index 0000000000..8fd6e4409b --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch @@ -0,0 +1,337 @@ +--- a/drivers/net/wireless/ath/ath9k/ahb.c ++++ b/drivers/net/wireless/ath/ath9k/ahb.c +@@ -20,7 +20,15 @@ + #include + #include + #include ++#include + #include "ath9k.h" ++#include ++ ++#ifdef CONFIG_OF ++#include ++#include ++#include ++#endif + + static const struct platform_device_id ath9k_platform_id_table[] = { + { +@@ -69,6 +77,242 @@ static const struct ath_bus_ops ath_ahb_ + .eeprom_read = ath_ahb_eeprom_read, + }; + ++#ifdef CONFIG_OF ++ ++#define QCA955X_DDR_CTL_CONFIG 0x108 ++#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23) ++ ++static int of_get_wifi_cal(struct device_node *np, struct ath9k_platform_data *pdata) ++{ ++#ifdef CONFIG_MTD ++ struct device_node *mtd_np = NULL; ++ size_t retlen; ++ int size, ret; ++ struct mtd_info *mtd; ++ const char *part; ++ const __be32 *list; ++ phandle phandle; ++ ++ list = of_get_property(np, "mtd-cal-data", &size); ++ if (!list) ++ return 0; ++ ++ if (size != (2 * sizeof(*list))) ++ return 1; ++ ++ phandle = be32_to_cpup(list++); ++ if (phandle) ++ mtd_np = of_find_node_by_phandle(phandle); ++ ++ if (!mtd_np) ++ return 1; ++ ++ part = of_get_property(mtd_np, "label", NULL); ++ if (!part) ++ part = mtd_np->name; ++ ++ mtd = get_mtd_device_nm(part); ++ if (IS_ERR(mtd)) ++ return 1; ++ ++ ret = mtd_read(mtd, be32_to_cpup(list), sizeof(pdata->eeprom_data), ++ &retlen, (u8*)pdata->eeprom_data); ++ put_mtd_device(mtd); ++ ++#endif ++ return 0; ++} ++ ++static int ar913x_wmac_reset(void) ++{ ++ ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); ++ mdelay(10); ++ ++ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar933x_wmac_reset(void) ++{ ++ int retries = 20; ++ ++ ath79_device_reset_set(AR933X_RESET_WMAC); ++ ath79_device_reset_clear(AR933X_RESET_WMAC); ++ ++ while (1) { ++ u32 bootstrap; ++ ++ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); ++ if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0) ++ return 0; ++ ++ if (retries-- == 0) ++ break; ++ ++ udelay(10000); ++ } ++ ++ pr_err("ar933x: WMAC reset timed out"); ++ return -ETIMEDOUT; ++} ++ ++static int qca955x_wmac_reset(void) ++{ ++ int i; ++ ++ /* Try to wait for WMAC DDR activity to stop */ ++ for (i = 0; i < 10; i++) { ++ if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) & ++ QCA955X_DDR_CTL_CONFIG_ACT_WMAC)) ++ break; ++ ++ udelay(10); ++ } ++ ++ ath79_device_reset_set(QCA955X_RESET_RTC); ++ udelay(10); ++ ath79_device_reset_clear(QCA955X_RESET_RTC); ++ udelay(10); ++ ++ return 0; ++} ++ ++enum { ++ AR913X_WMAC = 0, ++ AR933X_WMAC, ++ AR934X_WMAC, ++ QCA953X_WMAC, ++ QCA955X_WMAC, ++ QCA956X_WMAC, ++}; ++ ++static int ar9330_get_soc_revision(void) ++{ ++ if (ath79_soc_rev == 1) ++ return ath79_soc_rev; ++ ++ return 0; ++} ++ ++static int ath79_get_soc_revision(void) ++{ ++ return ath79_soc_rev; ++} ++ ++static const struct of_ath_ahb_data { ++ u16 dev_id; ++ u32 bootstrap_reg; ++ u32 bootstrap_ref; ++ ++ int (*soc_revision)(void); ++ int (*wmac_reset)(void); ++} of_ath_ahb_data[] = { ++ [AR913X_WMAC] = { ++ .dev_id = AR5416_AR9100_DEVID, ++ .wmac_reset = ar913x_wmac_reset, ++ ++ }, ++ [AR933X_WMAC] = { ++ .dev_id = AR9300_DEVID_AR9330, ++ .bootstrap_reg = AR933X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = AR933X_BOOTSTRAP_REF_CLK_40, ++ .soc_revision = ar9330_get_soc_revision, ++ .wmac_reset = ar933x_wmac_reset, ++ }, ++ [AR934X_WMAC] = { ++ .dev_id = AR9300_DEVID_AR9340, ++ .bootstrap_reg = AR934X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = AR934X_BOOTSTRAP_REF_CLK_40, ++ .soc_revision = ath79_get_soc_revision, ++ }, ++ [QCA953X_WMAC] = { ++ .dev_id = AR9300_DEVID_AR953X, ++ .bootstrap_reg = QCA953X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = QCA953X_BOOTSTRAP_REF_CLK_40, ++ .soc_revision = ath79_get_soc_revision, ++ }, ++ [QCA955X_WMAC] = { ++ .dev_id = AR9300_DEVID_QCA955X, ++ .bootstrap_reg = QCA955X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = QCA955X_BOOTSTRAP_REF_CLK_40, ++ .wmac_reset = qca955x_wmac_reset, ++ }, ++ [QCA956X_WMAC] = { ++ .dev_id = AR9300_DEVID_QCA956X, ++ .bootstrap_reg = QCA956X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = QCA956X_BOOTSTRAP_REF_CLK_40, ++ .soc_revision = ath79_get_soc_revision, ++ }, ++}; ++ ++const struct of_device_id of_ath_ahb_match[] = { ++ { .compatible = "qca,ar9130-wmac", .data = &of_ath_ahb_data[AR913X_WMAC] }, ++ { .compatible = "qca,ar9330-wmac", .data = &of_ath_ahb_data[AR933X_WMAC] }, ++ { .compatible = "qca,ar9340-wmac", .data = &of_ath_ahb_data[AR934X_WMAC] }, ++ { .compatible = "qca,qca9530-wmac", .data = &of_ath_ahb_data[QCA953X_WMAC] }, ++ { .compatible = "qca,qca9550-wmac", .data = &of_ath_ahb_data[QCA955X_WMAC] }, ++ { .compatible = "qca,qca9560-wmac", .data = &of_ath_ahb_data[QCA956X_WMAC] }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, of_ath_ahb_match); ++ ++static int of_ath_ahb_probe(struct platform_device *pdev) ++{ ++ struct ath9k_platform_data *pdata; ++ const struct of_device_id *match; ++ const struct of_ath_ahb_data *data; ++ u8 led_pin; ++ ++ match = of_match_device(of_ath_ahb_match, &pdev->dev); ++ data = (const struct of_ath_ahb_data *)match->data; ++ ++ pdata = dev_get_platdata(&pdev->dev); ++ ++ if (!of_property_read_u8(pdev->dev.of_node, "qca,led-pin", &led_pin)) ++ pdata->led_pin = led_pin; ++ else ++ pdata->led_pin = -1; ++ ++ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-2ghz")) ++ pdata->disable_2ghz = true; ++ ++ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-5ghz")) ++ pdata->disable_5ghz = true; ++ ++ if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo")) ++ pdata->tx_gain_buffalo = true; ++ ++ if (data->wmac_reset) { ++ data->wmac_reset(); ++ pdata->external_reset = data->wmac_reset; ++ } ++ ++ if (data->dev_id == AR9300_DEVID_AR953X) { ++ /* ++ * QCA953x only supports 25MHz refclk. ++ * Some vendors have an invalid bootstrap option ++ * set, which would break the WMAC here. ++ */ ++ pdata->is_clk_25mhz = true; ++ } else if (data->bootstrap_reg && data->bootstrap_ref) { ++ u32 t = ath79_reset_rr(data->bootstrap_reg); ++ if (t & data->bootstrap_ref) ++ pdata->is_clk_25mhz = false; ++ else ++ pdata->is_clk_25mhz = true; ++ } ++ ++ pdata->get_mac_revision = data->soc_revision; ++ ++ if (of_get_wifi_cal(pdev->dev.of_node, pdata)) ++ dev_err(&pdev->dev, "failed to load calibration data from mtd device\n"); ++ ++ return data->dev_id; ++} ++#endif ++ + static int ath_ahb_probe(struct platform_device *pdev) + { + void __iomem *mem; +@@ -80,6 +324,17 @@ static int ath_ahb_probe(struct platform + int ret = 0; + struct ath_hw *ah; + char hw_name[64]; ++ u16 dev_id; ++ ++ if (id) ++ dev_id = id->driver_data; ++ ++#ifdef CONFIG_OF ++ if (pdev->dev.of_node) ++ pdev->dev.platform_data = devm_kzalloc(&pdev->dev, ++ sizeof(struct ath9k_platform_data), ++ GFP_KERNEL); ++#endif + + if (!dev_get_platdata(&pdev->dev)) { + dev_err(&pdev->dev, "no platform data specified\n"); +@@ -122,13 +377,16 @@ static int ath_ahb_probe(struct platform + sc->mem = mem; + sc->irq = irq; + ++#ifdef CONFIG_OF ++ dev_id = of_ath_ahb_probe(pdev); ++#endif + ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); + if (ret) { + dev_err(&pdev->dev, "request_irq failed\n"); + goto err_free_hw; + } + +- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops); ++ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops); + if (ret) { + dev_err(&pdev->dev, "failed to initialize device\n"); + goto err_irq; +@@ -159,6 +417,9 @@ static int ath_ahb_remove(struct platfor + free_irq(sc->irq, sc); + ieee80211_free_hw(sc->hw); + } ++#ifdef CONFIG_OF ++ pdev->dev.platform_data = NULL; ++#endif + + return 0; + } +@@ -168,6 +429,9 @@ static struct platform_driver ath_ahb_dr + .remove = ath_ahb_remove, + .driver = { + .name = "ath9k", ++#ifdef CONFIG_OF ++ .of_match_table = of_ath_ahb_match, ++#endif + }, + .id_table = ath9k_platform_id_table, + }; +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "common.h" + #include "debug.h" +@@ -1012,6 +1013,9 @@ struct ath_softc { + struct ath_hw *sc_ah; + void __iomem *mem; + int irq; ++#ifdef CONFIG_OF ++ struct reset_control *reset; ++#endif + spinlock_t sc_serial_rw; + spinlock_t sc_pm_lock; + spinlock_t sc_pcu_lock; diff --git a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch new file mode 100644 index 0000000000..8e0041e3ef --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch @@ -0,0 +1,25 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -654,6 +654,12 @@ static int ath9k_of_init(struct ath_soft + return 0; + } + ++static void ath9k_of_gpio_mask(struct ath_softc *sc) ++{ ++ of_property_read_u32(sc->dev->of_node, "qca,gpio-mask", ++ &sc->sc_ah->caps.gpio_mask); ++} ++ + static int ath9k_init_softc(u16 devid, struct ath_softc *sc, + const struct ath_bus_ops *bus_ops) + { +@@ -757,6 +763,9 @@ static int ath9k_init_softc(u16 devid, s + if (ret) + goto err_hw; + ++ /* GPIO mask quirk */ ++ ath9k_of_gpio_mask(sc); ++ + ret = ath9k_init_queues(sc); + if (ret) + goto err_queues;