From 87d72cae64a6d73b11ec6963fc72a481b44ec0bf Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Tue, 29 Jun 2021 22:24:20 +0800 Subject: [PATCH] mac80211: remove ath11k nss code temporality --- package/kernel/mac80211/Makefile | 8 +- package/kernel/mac80211/ath.mk | 2 +- ...-tx-descriptor-search-index-properly.patch | 151 - ...emove-duplicate-function-declaration.patch | 36 - ...2-1-ath11k-ethernet-rx-decap-offload.patch | 438 --- ...02-2-ath11k-add-8023-undecap-support.patch | 55 - ...91-ath11k-add-mgmt-and-data-ack-rssi.patch | 103 - .../199-001-mac80211-add-nss-support.patch | 430 --- ...-ath11k_nss-add-nss-driver-interface.patch | 2714 ----------------- .../nss/199-003-ath11k-add-nss-support.patch | 881 ------ ...14-ath11k-qos-null-frame-tx-over-wmi.patch | 473 --- ...ath11k-Disable-unused-CE8-interrupts.patch | 31 - ...ow-fast-rx-by-bypassing-stats-update.patch | 357 --- 13 files changed, 4 insertions(+), 5675 deletions(-) delete mode 100644 package/kernel/mac80211/patches/ath11k/002-v5.12-ath11k-Update-tx-descriptor-search-index-properly.patch delete mode 100644 package/kernel/mac80211/patches/ath11k/003-v5.12-ath11k-remove-duplicate-function-declaration.patch delete mode 100644 package/kernel/mac80211/patches/ath11k/902-1-ath11k-ethernet-rx-decap-offload.patch delete mode 100644 package/kernel/mac80211/patches/ath11k/902-2-ath11k-add-8023-undecap-support.patch delete mode 100644 package/kernel/mac80211/patches/nss/191-ath11k-add-mgmt-and-data-ack-rssi.patch delete mode 100644 package/kernel/mac80211/patches/nss/199-001-mac80211-add-nss-support.patch delete mode 100644 package/kernel/mac80211/patches/nss/199-002-ath11k_nss-add-nss-driver-interface.patch delete mode 100644 package/kernel/mac80211/patches/nss/199-003-ath11k-add-nss-support.patch delete mode 100644 package/kernel/mac80211/patches/nss/214-ath11k-qos-null-frame-tx-over-wmi.patch delete mode 100644 package/kernel/mac80211/patches/nss/237-001-ath11k-Disable-unused-CE8-interrupts.patch delete mode 100644 package/kernel/mac80211/patches/nss/237-006-ath11k-Allow-fast-rx-by-bypassing-stats-update.patch diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 5aba3f7d9..6fb6de56a 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 PKG_VERSION:=5.10.42-1 -PKG_RELEASE:=3 +PKG_RELEASE:=2 PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.10.42/ PKG_HASH:=6876520105240844fdb32d1dcdf2bfdea291a37a96f16c892fda3776ba714fcb @@ -436,7 +436,7 @@ config-$(CONFIG_LEDS_TRIGGERS) += MAC80211_LEDS MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \ $(KERNEL_MAKE_FLAGS) \ - EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) -I$(STAGING_DIR)/usr/include/qca-nss-drv" \ + EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS)" \ KLIB_BUILD="$(LINUX_DIR)" \ MODPROBE=true \ KLIB=$(TARGET_MODULES_DIR) \ @@ -505,7 +505,6 @@ define Build/Patch $(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)/nss,nss/) $(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/) @@ -521,7 +520,6 @@ define Quilt/Refresh/Package $(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)/nss,nss/) $(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/) @@ -563,4 +561,4 @@ endef $(eval $(foreach drv,$(PKG_DRIVERS),$(call KernelPackage,$(drv)))) $(eval $(call KernelPackage,cfg80211)) -$(eval $(call KernelPackage,mac80211)) \ No newline at end of file +$(eval $(call KernelPackage,mac80211)) diff --git a/package/kernel/mac80211/ath.mk b/package/kernel/mac80211/ath.mk index 8e9037f03..4b728c754 100644 --- a/package/kernel/mac80211/ath.mk +++ b/package/kernel/mac80211/ath.mk @@ -292,7 +292,7 @@ define KernelPackage/ath11k TITLE:=Qualcomm 802.11ax wireless chipset support (common code) URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath11k DEPENDS+= +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT \ - +kmod-crypto-michael-mic +ATH11K_THERMAL:kmod-hwmon-core +ATH11K_THERMAL:kmod-thermal +@ipq807x:kmod-qca-nss-drv + +kmod-crypto-michael-mic +ATH11K_THERMAL:kmod-hwmon-core +ATH11K_THERMAL:kmod-thermal FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath11k/ath11k.ko AUTOLOAD:=$(call AutoProbe,ath11k) endef diff --git a/package/kernel/mac80211/patches/ath11k/002-v5.12-ath11k-Update-tx-descriptor-search-index-properly.patch b/package/kernel/mac80211/patches/ath11k/002-v5.12-ath11k-Update-tx-descriptor-search-index-properly.patch deleted file mode 100644 index a6351e5c8..000000000 --- a/package/kernel/mac80211/patches/ath11k/002-v5.12-ath11k-Update-tx-descriptor-search-index-properly.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 4b965be536eefdd16ca0a88120fee23f5b92cd16 Mon Sep 17 00:00:00 2001 -From: Karthikeyan Periyasamy -Date: Mon, 8 Feb 2021 13:32:11 +0200 -Subject: ath11k: Update tx descriptor search index properly - -Tx descriptor search index field should be updated with hw peer id -and not by AST Hash as per the HW/FW recommendation. Incorrect search -index causes throughput degradation in all scenario for all the -platforms. so updated the search index field with hw peer id, which -is a common change applicable for all the platforms. Also no need of these -configuration for non station type. seen 10% throughput increase in WDS -traffic with this change. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01492-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Karthikeyan Periyasamy -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/1612410960-9120-1-git-send-email-periyasa@codeaurora.org ---- - drivers/net/wireless/ath/ath11k/core.h | 1 + - drivers/net/wireless/ath/ath11k/dp_rx.c | 8 ++++++-- - drivers/net/wireless/ath/ath11k/dp_tx.c | 1 + - drivers/net/wireless/ath/ath11k/hal_tx.c | 2 ++ - drivers/net/wireless/ath/ath11k/hal_tx.h | 1 + - drivers/net/wireless/ath/ath11k/peer.c | 9 +++++++-- - drivers/net/wireless/ath/ath11k/peer.h | 3 ++- - 7 files changed, 20 insertions(+), 5 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -193,6 +193,7 @@ struct ath11k_vif { - u32 beacon_interval; - u32 dtim_period; - u16 ast_hash; -+ u16 ast_idx; - u16 tcl_metadata; - u8 hal_addr_search_flags; - u8 search_type; ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -1648,6 +1648,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s - u8 mac_addr[ETH_ALEN]; - u16 peer_mac_h16; - u16 ast_hash; -+ u16 hw_peer_id; - - ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type); - -@@ -1668,7 +1669,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s - resp->peer_map_ev.info1); - ath11k_dp_get_mac_addr(resp->peer_map_ev.mac_addr_l32, - peer_mac_h16, mac_addr); -- ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0); -+ ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0, 0); - break; - case HTT_T2H_MSG_TYPE_PEER_MAP2: - vdev_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_VDEV_ID, -@@ -1681,7 +1682,10 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s - peer_mac_h16, mac_addr); - ast_hash = FIELD_GET(HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL, - resp->peer_map_ev.info2); -- ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash); -+ hw_peer_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID, -+ resp->peer_map_ev.info1); -+ ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash, -+ hw_peer_id); - break; - case HTT_T2H_MSG_TYPE_PEER_UNMAP: - case HTT_T2H_MSG_TYPE_PEER_UNMAP2: ---- a/drivers/net/wireless/ath/ath11k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -165,6 +165,7 @@ tcl_ring_sel: - ti.pkt_offset = 0; - ti.lmac_id = ar->lmac_id; - ti.bss_ast_hash = arvif->ast_hash; -+ ti.bss_ast_idx = arvif->ast_idx; - ti.dscp_tid_tbl_idx = 0; - - if (skb->ip_summed == CHECKSUM_PARTIAL && ---- a/drivers/net/wireless/ath/ath11k/hal_tx.c -+++ b/drivers/net/wireless/ath/ath11k/hal_tx.c -@@ -71,6 +71,8 @@ void ath11k_hal_tx_cmd_desc_setup(struct - tcl_cmd->info3 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_DSCP_TID_TABLE_IDX, - ti->dscp_tid_tbl_idx) | - FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_SEARCH_INDEX, -+ ti->bss_ast_idx) | -+ FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_CACHE_SET_NUM, - ti->bss_ast_hash); - tcl_cmd->info4 = 0; - } ---- a/drivers/net/wireless/ath/ath11k/hal_tx.h -+++ b/drivers/net/wireless/ath/ath11k/hal_tx.h -@@ -29,6 +29,7 @@ struct hal_tx_info { - u32 flags1; /* %HAL_TCL_DATA_CMD_INFO2_ */ - u16 addr_search_flags; /* %HAL_TCL_DATA_CMD_INFO0_ADDR(X/Y)_ */ - u16 bss_ast_hash; -+ u16 bss_ast_idx; - u8 tid; - u8 search_type; /* %HAL_TX_ADDR_SEARCH_ */ - u8 lmac_id; ---- a/drivers/net/wireless/ath/ath11k/peer.c -+++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -118,7 +118,7 @@ exit: - } - - void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, -- u8 *mac_addr, u16 ast_hash) -+ u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) - { - struct ath11k_peer *peer; - -@@ -132,6 +132,7 @@ void ath11k_peer_map_event(struct ath11k - peer->vdev_id = vdev_id; - peer->peer_id = peer_id; - peer->ast_hash = ast_hash; -+ peer->hw_peer_id = hw_peer_id; - ether_addr_copy(peer->addr, mac_addr); - list_add(&peer->list, &ab->peers); - wake_up(&ab->peer_mapping_wq); -@@ -309,7 +310,11 @@ int ath11k_peer_create(struct ath11k *ar - - peer->pdev_idx = ar->pdev_idx; - peer->sta = sta; -- arvif->ast_hash = peer->ast_hash; -+ -+ if (arvif->vif->type == NL80211_IFTYPE_STATION) { -+ arvif->ast_hash = peer->ast_hash; -+ arvif->ast_idx = peer->hw_peer_id; -+ } - - peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; - peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; ---- a/drivers/net/wireless/ath/ath11k/peer.h -+++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -14,6 +14,7 @@ struct ath11k_peer { - int peer_id; - u16 ast_hash; - u8 pdev_idx; -+ u16 hw_peer_id; - - /* protected by ab->data_lock */ - struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; -@@ -31,7 +32,7 @@ struct ath11k_peer { - - void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); - void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, -- u8 *mac_addr, u16 ast_hash); -+ u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); - struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, - const u8 *addr); - struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, diff --git a/package/kernel/mac80211/patches/ath11k/003-v5.12-ath11k-remove-duplicate-function-declaration.patch b/package/kernel/mac80211/patches/ath11k/003-v5.12-ath11k-remove-duplicate-function-declaration.patch deleted file mode 100644 index 1522273e5..000000000 --- a/package/kernel/mac80211/patches/ath11k/003-v5.12-ath11k-remove-duplicate-function-declaration.patch +++ /dev/null @@ -1,36 +0,0 @@ -From cf8480d338a1b9156121e5e035e6b9721db4332a Mon Sep 17 00:00:00 2001 -From: Karthikeyan Periyasamy -Date: Mon, 11 Jan 2021 19:49:30 +0200 -Subject: ath11k: remove duplicate function declaration - -Removed the duplicated peer related function declaration -from core.h since those functions are already declared in peer.h - -Founded in code review. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01492-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Karthikeyan Periyasamy -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/1608304793-20612-1-git-send-email-periyasa@codeaurora.org ---- - drivers/net/wireless/ath/ath11k/core.h | 8 -------- - 1 file changed, 8 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -868,14 +868,6 @@ extern const struct service_to_pipe ath1 - extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qca6390[]; - extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qca6390[]; - --void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); --void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, -- u8 *mac_addr, u16 ast_hash); --struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, -- const u8 *addr); --struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, -- const u8 *addr); --struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, int peer_id); - int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab); - int ath11k_core_pre_init(struct ath11k_base *ab); - int ath11k_core_init(struct ath11k_base *ath11k); diff --git a/package/kernel/mac80211/patches/ath11k/902-1-ath11k-ethernet-rx-decap-offload.patch b/package/kernel/mac80211/patches/ath11k/902-1-ath11k-ethernet-rx-decap-offload.patch deleted file mode 100644 index 2873b6634..000000000 --- a/package/kernel/mac80211/patches/ath11k/902-1-ath11k-ethernet-rx-decap-offload.patch +++ /dev/null @@ -1,438 +0,0 @@ ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -294,6 +294,14 @@ static int ath11k_dp_purge_mon_ring(stru - return -ETIMEDOUT; - } - -+static bool ath11k_dp_rx_h_attn_is_mcbc(struct hal_rx_desc *desc) -+{ -+ return (!!FIELD_GET(RX_MSDU_END_INFO2_DA_IS_MCBC, -+ __le32_to_cpu(desc->msdu_end.info2))) && -+ (!!FIELD_GET(RX_ATTENTION_INFO1_MCAST_BCAST, -+ __le32_to_cpu(desc->attention.info1))); -+} -+ - /* Returns number of Rx buffers replenished */ - int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id, - struct dp_rxdma_ring *rx_ring, -@@ -2250,6 +2272,7 @@ static void ath11k_dp_rx_h_undecap(struc - { - u8 *first_hdr; - u8 decap; -+ struct ethhdr *ehdr; - - first_hdr = ath11k_dp_rx_h_80211_hdr(ar->ab, rx_desc); - decap = ath11k_dp_rx_h_msdu_start_decap_type(ar->ab, rx_desc); -@@ -2264,9 +2287,21 @@ static void ath11k_dp_rx_h_undecap(struc - decrypted); - break; - case DP_RX_DECAP_TYPE_ETHERNET2_DIX: -- /* TODO undecap support for middle/last msdu's of amsdu */ -- ath11k_dp_rx_h_undecap_eth(ar, msdu, first_hdr, -- enctype, status); -+ ehdr = (struct ethhdr *) msdu->data; -+ -+ /* mac80211 allows fast path only for authorized STA */ -+ if (ehdr->h_proto == cpu_to_be16(ETH_P_PAE)) { -+ ATH11K_SKB_RXCB(msdu)->is_eapol = true; -+ ath11k_dp_rx_h_undecap_eth(ar, msdu, first_hdr, -+ enctype, status); -+ } -+ -+ /* PN for mcast packets will be validated in mac80211; -+ * remove eth header and add 802.11 header. -+ */ -+ if (ATH11K_SKB_RXCB(msdu)->is_mcbc && decrypted) -+ ath11k_dp_rx_h_undecap_eth(ar, msdu, first_hdr, -+ enctype, status); - break; - case DP_RX_DECAP_TYPE_8023: - /* TODO: Handle undecap for these formats */ -@@ -2274,34 +2309,56 @@ static void ath11k_dp_rx_h_undecap(struc - } - } - -+static struct ath11k_peer * -+ath11k_dp_rx_h_find_peer(struct ath11k_base *ab, struct sk_buff *msdu) -+{ -+ struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); -+ struct hal_rx_desc *rx_desc = rxcb->rx_desc; -+ struct ath11k_peer *peer = NULL; -+ lockdep_assert_held(&ab->base_lock); -+ if (rxcb->peer_id) -+ peer = ath11k_peer_find_by_id(ab, rxcb->peer_id); -+ if (peer) -+ return peer; -+ -+ if (!rx_desc || -+ !(rx_desc->mpdu_start.info1 & RX_MPDU_START_INFO1_MAC_ADDR2_VALID)) -+ return NULL; -+ peer = ath11k_peer_find_by_addr(ab, rx_desc->mpdu_start.addr2); -+ return peer; -+} -+ - static void ath11k_dp_rx_h_mpdu(struct ath11k *ar, - struct sk_buff *msdu, - struct hal_rx_desc *rx_desc, - struct ieee80211_rx_status *rx_status) - { -- bool fill_crypto_hdr, mcast; -+ bool fill_crypto_hdr; - enum hal_encrypt_type enctype; - bool is_decrypted = false; -+ struct ath11k_skb_rxcb *rxcb; - struct ieee80211_hdr *hdr; - struct ath11k_peer *peer; - u32 err_bitmap; - -- hdr = (struct ieee80211_hdr *)msdu->data; -- - /* PN for multicast packets will be checked in mac80211 */ -+ rxcb = ATH11K_SKB_RXCB(msdu); -+ rxcb->is_mcbc = fill_crypto_hdr = ath11k_dp_rx_h_attn_is_mcbc(rx_desc); - -- mcast = is_multicast_ether_addr(hdr->addr1); -- fill_crypto_hdr = mcast; -+ if (rxcb->is_mcbc) { -+ rxcb->peer_id = ath11k_dp_rx_h_mpdu_start_peer_id(rx_desc); -+ rxcb->seq_no = ath11k_dp_rx_h_mpdu_start_seq_no(rx_desc); -+ } - - spin_lock_bh(&ar->ab->base_lock); -- peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2); -+ peer = ath11k_dp_rx_h_find_peer(ar->ab, msdu); - if (peer) { -- if (mcast) -+ if (rxcb->is_mcbc) - enctype = peer->sec_type_grp; - else - enctype = peer->sec_type; - } else { -- enctype = HAL_ENCRYPT_TYPE_OPEN; -+ enctype = ath11k_dp_rx_h_mpdu_start_enctype(rx_desc); - } - spin_unlock_bh(&ar->ab->base_lock); - -@@ -2341,8 +2398,11 @@ static void ath11k_dp_rx_h_mpdu(struct a - if (!is_decrypted || fill_crypto_hdr) - return; - -- hdr = (void *)msdu->data; -- hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); -+ if (ath11k_dp_rx_h_msdu_start_decap_type(rx_desc) != -+ DP_RX_DECAP_TYPE_ETHERNET2_DIX) { -+ hdr = (void *)msdu->data; -+ hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); -+ } - } - - static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc, -@@ -2516,51 +2576,46 @@ static void ath11k_dp_rx_h_ppdu(struct a - ath11k_dp_rx_h_rate(ar, rx_desc, rx_status); - } - --static char *ath11k_print_get_tid(struct ieee80211_hdr *hdr, char *out, -- size_t size) --{ -- u8 *qc; -- int tid; -- -- if (!ieee80211_is_data_qos(hdr->frame_control)) -- return ""; -- -- qc = ieee80211_get_qos_ctl(hdr); -- tid = *qc & IEEE80211_QOS_CTL_TID_MASK; -- snprintf(out, size, "tid %d", tid); -- -- return out; --} -- - static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *napi, -- struct sk_buff *msdu) -+ struct sk_buff *msdu, -+ struct ieee80211_rx_status *status) - { - static const struct ieee80211_radiotap_he known = { - .data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN | - IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN), - .data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN), - }; -- struct ieee80211_rx_status *status; -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; -+ struct ieee80211_rx_status *rx_status; - struct ieee80211_radiotap_he *he = NULL; -- char tid[32]; -+ struct ieee80211_sta *pubsta = NULL; -+ struct ath11k_peer *peer; -+ struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); -+ u8 decap = DP_RX_DECAP_TYPE_RAW; -+ bool is_mcbc = rxcb->is_mcbc; -+ bool is_eapol = rxcb->is_eapol; - -- status = IEEE80211_SKB_RXCB(msdu); -- if (status->encoding == RX_ENC_HE) { -+ if ((status->encoding == RX_ENC_HE) && !(status->flag & RX_FLAG_RADIOTAP_HE) && -+ !(status->flag & RX_FLAG_SKIP_MONITOR)) { - he = skb_push(msdu, sizeof(known)); - memcpy(he, &known, sizeof(known)); - status->flag |= RX_FLAG_RADIOTAP_HE; - } - -+ decap = ath11k_dp_rx_h_msdu_start_decap_type(rxcb->rx_desc); -+ spin_lock_bh(&ar->ab->base_lock); -+ peer = ath11k_dp_rx_h_find_peer(ar->ab, msdu); -+ if (peer && peer->sta) -+ pubsta = peer->sta; -+ spin_unlock_bh(&ar->ab->base_lock); -+ - ath11k_dbg(ar->ab, ATH11K_DBG_DATA, - "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", - msdu, - msdu->len, -- ieee80211_get_SA(hdr), -- ath11k_print_get_tid(hdr, tid, sizeof(tid)), -- is_multicast_ether_addr(ieee80211_get_DA(hdr)) ? -- "mcast" : "ucast", -- (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4, -+ peer ? peer->addr : NULL, -+ rxcb->tid, -+ (is_mcbc) ? "mcast" : "ucast", -+ rxcb->seq_no, - (status->encoding == RX_ENC_LEGACY) ? "legacy" : "", - (status->encoding == RX_ENC_HT) ? "ht" : "", - (status->encoding == RX_ENC_VHT) ? "vht" : "", -@@ -2519,21 +2575,30 @@ static void ath11k_dp_rx_deliver_msdu(st - - ath11k_dbg_dump(ar->ab, ATH11K_DBG_DP_RX, NULL, "dp rx msdu: ", - msdu->data, msdu->len); -+ rx_status = IEEE80211_SKB_RXCB(msdu); -+ *rx_status = *status; - - /* TODO: trace rx packet */ - -- ieee80211_rx_napi(ar->hw, NULL, msdu, napi); -+ /* PN for multicast packets are not validate in HW, -+ * so skip 802.3 rx path -+ * Also, fast_rx expectes the STA to be authorized, hence -+ * eapol packets are sent in slow path. -+ */ -+ if (decap == DP_RX_DECAP_TYPE_ETHERNET2_DIX && !is_eapol && -+ !(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED)) -+ rx_status->flag |= RX_FLAG_8023; -+ -+ ieee80211_rx_napi(ar->hw, pubsta, msdu, napi); - } - - static int ath11k_dp_rx_process_msdu(struct ath11k *ar, - struct sk_buff *msdu, -- struct sk_buff_head *msdu_list) -+ struct sk_buff_head *msdu_list, -+ struct ieee80211_rx_status *rx_status) - { - struct hal_rx_desc *rx_desc, *lrx_desc; -- struct ieee80211_rx_status rx_status = {0}; -- struct ieee80211_rx_status *status; - struct ath11k_skb_rxcb *rxcb; -- struct ieee80211_hdr *hdr; - struct sk_buff *last_buf; - u8 l3_pad_bytes; - u8 *hdr_status; -@@ -2591,19 +2656,11 @@ static int ath11k_dp_rx_process_msdu(str - } - } - -- hdr = (struct ieee80211_hdr *)msdu->data; -- -- /* Process only data frames */ -- if (!ieee80211_is_data(hdr->frame_control)) -- return -EINVAL; -- -- ath11k_dp_rx_h_ppdu(ar, rx_desc, &rx_status); -- ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, &rx_status); -+ ath11k_dp_rx_h_ppdu(ar, rx_desc, rx_status); -+ ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status); - -- rx_status.flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED; -+ rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED; - -- status = IEEE80211_SKB_RXCB(msdu); -- *status = rx_status; - return 0; - - free_out: -@@ -2618,6 +2675,7 @@ static void ath11k_dp_rx_process_receive - struct ath11k_skb_rxcb *rxcb; - struct sk_buff *msdu; - struct ath11k *ar; -+ struct ieee80211_rx_status rx_status = {0}; - u8 mac_id; - int ret; - -@@ -2640,7 +2698,7 @@ static void ath11k_dp_rx_process_receive - continue; - } - -- ret = ath11k_dp_rx_process_msdu(ar, msdu, msdu_list); -+ ret = ath11k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status); - if (ret) { - ath11k_dbg(ab, ATH11K_DBG_DATA, - "Unable to process msdu %d", ret); -@@ -2648,7 +2706,7 @@ static void ath11k_dp_rx_process_receive - continue; - } - -- ath11k_dp_rx_deliver_msdu(ar, napi, msdu); -+ ath11k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_status); - (*quota)--; - } - -@@ -2730,10 +2788,14 @@ try_again: - RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU); - rxcb->is_continuation = !!(desc.rx_msdu_info.info0 & - RX_MSDU_DESC_INFO0_MSDU_CONTINUATION); -- rxcb->mac_id = mac_id; -+ rxcb->peer_id = FIELD_GET(RX_MPDU_DESC_META_DATA_PEER_ID, -+ desc.rx_mpdu_info.meta_data); -+ rxcb->seq_no = FIELD_GET(RX_MPDU_DESC_INFO0_SEQ_NUM, -+ desc.rx_mpdu_info.info0); - rxcb->tid = FIELD_GET(HAL_REO_DEST_RING_INFO0_RX_QUEUE_NUM, - desc.info0); - -+ rxcb->mac_id = mac_id; - __skb_queue_tail(&msdu_list, msdu); - - if (total_msdu_reaped >= quota && !rxcb->is_continuation) { -@@ -4105,7 +4167,6 @@ static void ath11k_dp_rx_wbm_err(struct - { - struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); - struct ieee80211_rx_status rxs = {0}; -- struct ieee80211_rx_status *status; - bool drop = true; - - switch (rxcb->err_rel_src) { -@@ -4125,10 +4186,7 @@ static void ath11k_dp_rx_wbm_err(struct - return; - } - -- status = IEEE80211_SKB_RXCB(msdu); -- *status = rxs; -- -- ath11k_dp_rx_deliver_msdu(ar, napi, msdu); -+ ath11k_dp_rx_deliver_msdu(ar, napi, msdu, &rxs); - } - - int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab, -@@ -5080,7 +5138,7 @@ static int ath11k_dp_rx_mon_deliver(stru - { - struct ath11k_pdev_dp *dp = &ar->dp; - struct sk_buff *mon_skb, *skb_next, *header; -- struct ieee80211_rx_status *rxs = &dp->rx_status, *status; -+ struct ieee80211_rx_status *rxs = &dp->rx_status; - - mon_skb = ath11k_dp_rx_mon_merg_msdus(ar, mac_id, head_msdu, - tail_msdu, rxs); -@@ -5106,10 +5164,7 @@ static int ath11k_dp_rx_mon_deliver(stru - } - rxs->flag |= RX_FLAG_ONLY_MONITOR; - -- status = IEEE80211_SKB_RXCB(mon_skb); -- *status = *rxs; -- -- ath11k_dp_rx_deliver_msdu(ar, napi, mon_skb); -+ ath11k_dp_rx_deliver_msdu(ar, napi, mon_skb, rxs); - mon_skb = skb_next; - } while (mon_skb); - rxs->flag = 0; ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5198,7 +5198,8 @@ static void ath11k_mac_op_update_vif_off - if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET || - (vif->type != NL80211_IFTYPE_STATION && - vif->type != NL80211_IFTYPE_AP)) -- vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; -+ vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED | -+ IEEE80211_OFFLOAD_DECAP_ENABLED); - - if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) - param_value = ATH11K_HW_TXRX_ETHERNET; -@@ -5214,6 +5215,22 @@ static void ath11k_mac_op_update_vif_off - arvif->vdev_id, ret); - vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; - } -+ -+ param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE; -+ if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED) -+ param_value = ATH11K_HW_TXRX_ETHERNET; -+ else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) -+ param_value = ATH11K_HW_TXRX_RAW; -+ else -+ param_value = ATH11K_HW_TXRX_NATIVE_WIFI; -+ -+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -+ param_id, param_value); -+ if (ret) { -+ ath11k_warn(ab, "failed to set vdev %d rx decap mode: %d\n", -+ arvif->vdev_id, ret); -+ vif->offload_flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED; -+ } - } - - static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, -@@ -7301,7 +7318,10 @@ static int __ath11k_mac_register(struct - ieee80211_hw_set(ar->hw, QUEUE_CONTROL); - ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); - ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK); -- ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD); -+ if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET) { -+ ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD); -+ ieee80211_hw_set(ar->hw, SUPPORTS_RX_DECAP_OFFLOAD); -+ } - if (ht_cap & WMI_HT_CAP_ENABLED) { - ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION); - ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW); ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -97,6 +97,8 @@ struct ath11k_skb_rxcb { - bool is_first_msdu; - bool is_last_msdu; - bool is_continuation; -+ bool is_mcbc; -+ bool is_eapol; - struct hal_rx_desc *rx_desc; - u8 err_rel_src; - u8 err_code; -@@ -104,6 +106,8 @@ struct ath11k_skb_rxcb { - u8 unmapped; - u8 is_frag; - u8 tid; -+ u16 peer_id; -+ u16 seq_no; - }; - - enum ath11k_hw_rev { ---- a/drivers/net/wireless/ath/ath11k/hal_desc.h -+++ b/drivers/net/wireless/ath/ath11k/hal_desc.h -@@ -497,6 +497,8 @@ struct hal_tlv_hdr { - #define RX_MPDU_DESC_INFO0_DA_IDX_TIMEOUT BIT(29) - #define RX_MPDU_DESC_INFO0_RAW_MPDU BIT(30) - -+#define RX_MPDU_DESC_META_DATA_PEER_ID GENMASK(15, 0) -+ - struct rx_mpdu_desc { - u32 info0; /* %RX_MPDU_DESC_INFO */ - u32 meta_data; ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -25,10 +25,10 @@ module_param_named(crypto_mode, ath11k_c - MODULE_PARM_DESC(crypto_mode, "crypto mode: 0-hardware, 1-software"); - - /* frame mode values are mapped as per enum ath11k_hw_txrx_mode */ --unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI; -+unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_ETHERNET; - module_param_named(frame_mode, ath11k_frame_mode, uint, 0644); - MODULE_PARM_DESC(frame_mode, -- "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); -+ "Datapath frame mode (0: raw, 1: native wifi, 2: ethernet(default))"); - - static const struct ath11k_hw_params ath11k_hw_params[] = { - { diff --git a/package/kernel/mac80211/patches/ath11k/902-2-ath11k-add-8023-undecap-support.patch b/package/kernel/mac80211/patches/ath11k/902-2-ath11k-add-8023-undecap-support.patch deleted file mode 100644 index ba9113c10..000000000 --- a/package/kernel/mac80211/patches/ath11k/902-2-ath11k-add-8023-undecap-support.patch +++ /dev/null @@ -1,55 +0,0 @@ ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -2264,6 +2264,42 @@ static void ath11k_dp_rx_h_undecap_eth(s - ether_addr_copy(ieee80211_get_SA(hdr), sa); - } - -+static void ath11k_dp_rx_h_undecap_snap(struct ath11k *ar, -+ struct sk_buff *msdu, -+ u8 *first_hdr, -+ enum hal_encrypt_type enctype, -+ struct ieee80211_rx_status *status) -+{ -+ struct ieee80211_hdr *hdr; -+ size_t hdr_len; -+ u8 l3_pad_bytes; -+ struct hal_rx_desc *rx_desc; -+ -+ /* Delivered decapped frame: -+ * [amsdu header] <-- replaced with 802.11 hdr -+ * [rfc1042/llc] -+ * [payload] -+ */ -+ -+ rx_desc = (void *)msdu->data - sizeof(*rx_desc); -+ l3_pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(rx_desc); -+ -+ skb_put(msdu, l3_pad_bytes); -+ skb_pull(msdu, sizeof(struct ath11k_dp_amsdu_subframe_hdr) + l3_pad_bytes); -+ -+ hdr = (struct ieee80211_hdr *)first_hdr; -+ hdr_len = ieee80211_hdrlen(hdr->frame_control); -+ -+ if (!(status->flag & RX_FLAG_IV_STRIPPED)) { -+ memcpy(skb_push(msdu, -+ ath11k_dp_rx_crypto_param_len(ar, enctype)), -+ (void *)hdr + hdr_len, -+ ath11k_dp_rx_crypto_param_len(ar, enctype)); -+ } -+ -+ memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); -+} -+ - static void ath11k_dp_rx_h_undecap(struct ath11k *ar, struct sk_buff *msdu, - struct hal_rx_desc *rx_desc, - enum hal_encrypt_type enctype, -@@ -2294,7 +2330,8 @@ static void ath11k_dp_rx_h_undecap(struc - enctype, status); - break; - case DP_RX_DECAP_TYPE_8023: -- /* TODO: Handle undecap for these formats */ -+ ath11k_dp_rx_h_undecap_snap(ar, msdu, first_hdr, -+ enctype, status); - break; - } - } diff --git a/package/kernel/mac80211/patches/nss/191-ath11k-add-mgmt-and-data-ack-rssi.patch b/package/kernel/mac80211/patches/nss/191-ath11k-add-mgmt-and-data-ack-rssi.patch deleted file mode 100644 index 00e61118f..000000000 --- a/package/kernel/mac80211/patches/nss/191-ath11k-add-mgmt-and-data-ack-rssi.patch +++ /dev/null @@ -1,103 +0,0 @@ ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -7660,6 +7660,8 @@ static int __ath11k_mac_register(struct - - ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations; - -+ wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); -+ - ar->hw->queues = ATH11K_HW_MAX_QUEUES; - ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN; - ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1; ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -3921,7 +3921,8 @@ ath11k_wmi_copy_resource_config(struct w - wmi_cfg->bpf_instruction_size = tg_cfg->bpf_instruction_size; - wmi_cfg->max_bssid_rx_filters = tg_cfg->max_bssid_rx_filters; - wmi_cfg->use_pdev_id = tg_cfg->use_pdev_id; -- wmi_cfg->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; -+ wmi_cfg->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 | -+ WMI_RSRC_CFG_FLAG1_ACK_RSSI; - wmi_cfg->peer_map_unmap_v2_support = tg_cfg->peer_map_unmap_v2_support; - wmi_cfg->sched_params = tg_cfg->sched_params; - wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; -@@ -5180,8 +5181,7 @@ static int ath11k_pull_mgmt_rx_params_tl - return 0; - } - --static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id, -- u32 status) -+static int wmi_process_mgmt_tx_comp(struct ath11k *ar, struct wmi_mgmt_tx_compl_event *tx_compl_param) - { - struct sk_buff *msdu; - struct ieee80211_tx_info *info; -@@ -5194,24 +5194,28 @@ static int wmi_process_mgmt_tx_comp(stru - u16 frm_type; - - spin_lock_bh(&ar->txmgmt_idr_lock); -- msdu = idr_find(&ar->txmgmt_idr, desc_id); -+ msdu = idr_find(&ar->txmgmt_idr, tx_compl_param->desc_id); - - if (!msdu) { - ath11k_warn(ar->ab, "received mgmt tx compl for invalid msdu_id: %d\n", -- desc_id); -+ tx_compl_param->desc_id); - spin_unlock_bh(&ar->txmgmt_idr_lock); - return -ENOENT; - } - -- idr_remove(&ar->txmgmt_idr, desc_id); -+ idr_remove(&ar->txmgmt_idr, tx_compl_param->desc_id); - spin_unlock_bh(&ar->txmgmt_idr_lock); - - skb_cb = ATH11K_SKB_CB(msdu); - dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); - - info = IEEE80211_SKB_CB(msdu); -- if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) -+ if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !tx_compl_param->status) -+ { - info->flags |= IEEE80211_TX_STAT_ACK; -+ info->status.ack_signal = tx_compl_param->ack_rssi; -+ info->status.is_valid_ack_signal = true; -+ } - - hdr = (struct ieee80211_hdr *)msdu->data; - frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control); -@@ -5272,6 +5276,7 @@ static int ath11k_pull_mgmt_tx_compl_par - param->pdev_id = ev->pdev_id; - param->desc_id = ev->desc_id; - param->status = ev->status; -+ param->ack_rssi = ev->ack_rssi; - - kfree(tb); - return 0; -@@ -6746,8 +6751,7 @@ static void ath11k_mgmt_tx_compl_event(s - goto exit; - } - -- wmi_process_mgmt_tx_comp(ar, tx_compl_param.desc_id, -- tx_compl_param.status); -+ wmi_process_mgmt_tx_comp(ar, &tx_compl_param); - - ath11k_dbg(ab, ATH11K_DBG_MGMT, - "mgmt tx compl ev pdev_id %d, desc_id %d, status %d", ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2266,6 +2266,7 @@ struct wmi_init_cmd { - } __packed; - - #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) -+#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) - - struct wmi_resource_config { - u32 tlv_header; -@@ -4452,6 +4453,8 @@ struct wmi_mgmt_tx_compl_event { - u32 desc_id; - u32 status; - u32 pdev_id; -+ u32 ppdu_id; -+ u32 ack_rssi; - } __packed; - - struct wmi_scan_event { diff --git a/package/kernel/mac80211/patches/nss/199-001-mac80211-add-nss-support.patch b/package/kernel/mac80211/patches/nss/199-001-mac80211-add-nss-support.patch deleted file mode 100644 index ceb21b0e1..000000000 --- a/package/kernel/mac80211/patches/nss/199-001-mac80211-add-nss-support.patch +++ /dev/null @@ -1,430 +0,0 @@ -From 193bfea2185a0ee976f54812e41ace77e6ee85e4 Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Fri, 10 Jul 2020 12:46:12 +0530 -Subject: [PATCH 1/3] mac80211: add nss support - -Add Support for NSS Offload if the HW supports it. -New flag is introduced to indicate HW support for NSS -offload - -Signed-off-by: Sriram R ---- - include/net/mac80211.h | 13 +++++++++++++ - net/mac80211/debugfs.c | 1 + - net/mac80211/util.c | 16 ++++++++++++++++ - 3 files changed, 30 insertions(+) - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -359,6 +359,20 @@ enum ieee80211_bss_change { - /* when adding here, make sure to change ieee80211_reconfig */ - }; - -+/** -+ * enum ieee80211_nss_bss_change - NSS BSS change notification flags -+ * -+ * These flags are used with the nss_bss_info_changed() callback -+ * to indicate which NSS BSS parameter changed. -+ * -+ * @BSS_CHANGED_NSS_AP_ISOLATE: AP Isolate feature in NSS mode -+ * -+ */ -+ -+enum ieee80211_nss_bss_change { -+ BSS_CHANGED_NSS_AP_ISOLATE = BIT(0), -+}; -+ - /* - * The maximum number of IPv4 addresses listed for ARP filtering. If the number - * of addresses for an interface increase beyond this value, hardware ARP -@@ -631,6 +645,7 @@ struct ieee80211_fils_discovery { - * @s1g: BSS is S1G BSS (affects Association Request format). - * @beacon_tx_rate: The configured beacon transmit rate that needs to be passed - * to driver when rate control is offloaded to firmware. -+ * @nss_ap_isolate: Used for notifying the NSS host about AP isolate feature - */ - struct ieee80211_bss_conf { - const u8 *bssid; -@@ -701,6 +716,7 @@ struct ieee80211_bss_conf { - u32 unsol_bcast_probe_resp_interval; - bool s1g; - struct cfg80211_bitrate_mask beacon_tx_rate; -+ bool nss_ap_isolate; - }; - - /** -@@ -1781,6 +1797,16 @@ struct ieee80211_vif *wdev_to_ieee80211_ - struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif); - - /** -+ * ieee80211_vif_to_wdev_relaxed - return a wdev struct from a vif -+ * @vif: the vif to get the wdev for -+ * -+ * This function is similar to ieee80211_vif_to_wdev, but the wdev -+ * is returned even if sdata is not running. -+ * -+ */ -+struct wireless_dev *ieee80211_vif_to_wdev_relaxed(struct ieee80211_vif *vif); -+ -+/** - * enum ieee80211_key_flags - key flags - * - * These flags are used for communication about keys between the driver -@@ -2407,6 +2433,8 @@ struct ieee80211_txq { - * @IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD: Hardware supports rx decapsulation - * offload - * -+ * @IEEE80211_HW_SUPPORTS_NSS_OFFLOAD: Hardware/driver supports NSS offload -+ * - * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays - */ - enum ieee80211_hw_flags { -@@ -2462,6 +2490,7 @@ enum ieee80211_hw_flags { - IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT, - IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD, - IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD, -+ IEEE80211_HW_SUPPORTS_NSS_OFFLOAD, - - /* keep last, obviously */ - NUM_IEEE80211_HW_FLAGS -@@ -3440,6 +3469,10 @@ enum ieee80211_reconfig_type { - * of the bss parameters has changed when a call is made. The callback - * can sleep. - * -+ * @nss_bss_info_changed: Handler for configuration requests related to NSS BSS -+ * parameters that may vary during BSS's lifespan, and may affect low level -+ * driver. -+ * - * @prepare_multicast: Prepare for multicast filter configuration. - * This callback is optional, and its return value is passed - * to configure_filter(). This callback must be atomic. -@@ -3927,6 +3960,9 @@ struct ieee80211_ops { - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed); -+ void (*nss_bss_info_changed)(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ u32 changed); - - int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); - void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); ---- a/net/mac80211/debugfs.c -+++ b/net/mac80211/debugfs.c -@@ -407,6 +407,7 @@ static const char *hw_flag_names[] = { - FLAG(IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT), - FLAG(SUPPORTS_TX_ENCAP_OFFLOAD), - FLAG(SUPPORTS_RX_DECAP_OFFLOAD), -+ FLAG(SUPPORTS_NSS_OFFLOAD), - #undef FLAG - }; - ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -881,6 +881,22 @@ struct wireless_dev *ieee80211_vif_to_wd - } - EXPORT_SYMBOL_GPL(ieee80211_vif_to_wdev); - -+struct wireless_dev *ieee80211_vif_to_wdev_relaxed(struct ieee80211_vif *vif) -+{ -+ struct ieee80211_sub_if_data *sdata; -+ -+ if (!vif) -+ return NULL; -+ -+ sdata = vif_to_sdata(vif); -+ -+ if (sdata) -+ return &sdata->wdev; -+ -+ return NULL; -+} -+EXPORT_SYMBOL(ieee80211_vif_to_wdev_relaxed); -+ - /* - * Nothing should have been stuffed into the workqueue during - * the suspend->resume cycle. Since we can't check each caller ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -210,6 +210,17 @@ void ieee80211_bss_info_change_notify(st - drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); - } - -+void ieee80211_nss_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, -+ u32 changed) -+{ -+ struct ieee80211_local *local = sdata->local; -+ -+ if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -+ return; -+ -+ drv_nss_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); -+} -+ - u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) - { - sdata->vif.bss_conf.use_cts_prot = false; -@@ -598,12 +609,6 @@ struct ieee80211_hw *ieee80211_alloc_hw_ - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA); - #endif - wiphy_ext_feature_set(wiphy, -- NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211); -- wiphy_ext_feature_set(wiphy, -- NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH); -- wiphy_ext_feature_set(wiphy, -- NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS); -- wiphy_ext_feature_set(wiphy, - NL80211_EXT_FEATURE_SCAN_FREQ_KHZ); - - if (!ops->hw_scan) { -@@ -921,6 +926,18 @@ int ieee80211_register_hw(struct ieee802 - (!local->ops->start_nan || !local->ops->stop_nan))) - return -EINVAL; - -+ /* Control port over nl80211 is disabled for nss offload as -+ * sending per packet tx status is not supported and only -+ * rx over netdev from driver is done currently */ -+ if (!ieee80211_hw_check(hw, SUPPORTS_NSS_OFFLOAD)) { -+ wiphy_ext_feature_set(hw->wiphy, -+ NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211); -+ wiphy_ext_feature_set(hw->wiphy, -+ NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH); -+ wiphy_ext_feature_set(hw->wiphy, -+ NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS); -+ } -+ - #ifdef CONFIG_PM - if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume)) - return -EINVAL; ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -2092,7 +2092,10 @@ sta_get_last_rx_stats(struct sta_info *s - struct ieee80211_local *local = sta->local; - int cpu; - -- if (!ieee80211_hw_check(&local->hw, USES_RSS)) -+ if (ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) -+ return stats; -+ -+ if (!ieee80211_hw_check(&local->hw, USES_RSS)) - return stats; - - for_each_possible_cpu(cpu) { ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1007,11 +1007,23 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) - { - struct sk_buff *skb; - int ac = -1; -+ struct ieee80211_hdr *hdr; -+ bool nss_offload; - - if (!tx->sta) - return TX_CONTINUE; - -+ nss_offload = ieee80211_hw_check(&tx->local->hw, SUPPORTS_NSS_OFFLOAD); -+ - skb_queue_walk(&tx->skbs, skb) { -+ /* Do not increment stats for data packets if NSS offload is enabled. -+ * As we use the stats from NSS, this will be a duplication -+ */ -+ if (nss_offload) { -+ hdr = (void *) skb->data; -+ if (ieee80211_is_data(hdr->frame_control)) -+ continue; -+ } - ac = skb_get_queue_mapping(skb); - tx->sta->tx_stats.bytes[ac] += skb->len; - } -@@ -4227,17 +4239,19 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, - memset(info, 0, sizeof(*info)); - - tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; -- tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); -- if (tid_tx) { -- if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { -- /* fall back to non-offload slow path */ -- __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); -- return; -- } -+ if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) { -+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); -+ if (tid_tx) { -+ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { -+ /* fall back to non-offload slow path */ -+ __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); -+ return; -+ } - -- info->flags |= IEEE80211_TX_CTL_AMPDU; -- if (tid_tx->timeout) -- tid_tx->last_tx = jiffies; -+ info->flags |= IEEE80211_TX_CTL_AMPDU; -+ if (tid_tx->timeout) -+ tid_tx->last_tx = jiffies; -+ } - } - - if (unlikely(skb->sk && -@@ -4249,8 +4263,10 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, - - ieee80211_tx_stats(dev, skb->len); - -- sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; -- sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; -+ if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) { -+ sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; -+ sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; -+ } - - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, -@@ -4327,7 +4329,6 @@ netdev_tx_t ieee80211_subif_start_xmit_8 - struct net_device *dev) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -- struct ethhdr *ehdr = (struct ethhdr *)skb->data; - struct ieee80211_key *key; - struct sta_info *sta; - -@@ -4344,9 +4345,11 @@ netdev_tx_t ieee80211_subif_start_xmit_8 - goto out; - } - -- if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded || -- !test_sta_flag(sta, WLAN_STA_AUTHORIZED) || -- sdata->control_port_protocol == ehdr->h_proto)) -+ if (ieee80211_hw_check(&sdata->local->hw, SUPPORTS_NSS_OFFLOAD)) { -+ if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded)) -+ sta = NULL; -+ goto tx_offload; -+ } else if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded)) - goto skip_offload; - - key = rcu_dereference(sta->ptk[sta->ptk_idx]); -@@ -4303,6 +4323,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, - key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)) - goto skip_offload; - -+tx_offload: - ieee80211_8023_xmit(sdata, dev, sta, key, skb); - goto out; - ---- a/net/wireless/util.c -+++ b/net/wireless/util.c -@@ -2084,6 +2084,9 @@ bool cfg80211_does_bw_fit_range(const st - - int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp) - { -+ if(sinfo->pertid) -+ return 0; -+ - sinfo->pertid = kcalloc(IEEE80211_NUM_TIDS + 1, - sizeof(*(sinfo->pertid)), - gfp); ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -2280,7 +2280,7 @@ static int ieee80211_change_bss(struct w - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_supported_band *sband; -- u32 changed = 0; -+ u32 changed = 0, nss_changed = 0; - - if (!sdata_dereference(sdata->u.ap.beacon, sdata)) - return -ENOENT; -@@ -2327,6 +2327,8 @@ static int ieee80211_change_bss(struct w - sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS; - else - sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; -+ sdata->vif.bss_conf.nss_ap_isolate = params->ap_isolate; -+ nss_changed |= BSS_CHANGED_NSS_AP_ISOLATE; - ieee80211_check_fast_rx_iface(sdata); - } - -@@ -2356,6 +2358,8 @@ static int ieee80211_change_bss(struct w - - ieee80211_bss_info_change_notify(sdata, changed); - -+ ieee80211_nss_bss_info_change_notify(sdata, nss_changed); -+ - return 0; - } - ---- a/net/mac80211/driver-ops.h -+++ b/net/mac80211/driver-ops.h -@@ -178,6 +178,23 @@ static inline void drv_bss_info_changed( - trace_drv_return_void(local); - } - -+static inline void drv_nss_bss_info_changed(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_bss_conf *info, -+ u32 changed) -+{ -+ might_sleep(); -+ -+ if (!check_sdata_in_driver(sdata)) -+ return; -+ -+ trace_drv_nss_bss_info_changed(local, sdata, info, changed); -+ if (local->ops->nss_bss_info_changed) { -+ local->ops->nss_bss_info_changed(&local->hw, &sdata->vif, changed); -+ } -+ trace_drv_nss_return_void(local); -+} -+ - static inline u64 drv_prepare_multicast(struct ieee80211_local *local, - struct netdev_hw_addr_list *mc_list) - { ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1626,6 +1626,8 @@ int ieee80211_hw_config(struct ieee80211 - void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); - void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, - u32 changed); -+void ieee80211_nss_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, -+ u32 changed); - void ieee80211_configure_filter(struct ieee80211_local *local); - u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); - ---- a/net/mac80211/trace.h -+++ b/net/mac80211/trace.h -@@ -389,6 +389,38 @@ TRACE_EVENT(drv_config, - LOCAL_PR_ARG, __entry->changed, CHANDEF_PR_ARG - ) - ); -+TRACE_EVENT(drv_nss_bss_info_changed, -+ TP_PROTO(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_bss_conf *info, -+ u32 changed), -+ -+ TP_ARGS(local, sdata, info, changed), -+ -+ TP_STRUCT__entry( -+ LOCAL_ENTRY -+ VIF_ENTRY -+ __field(u32, changed) -+ __field(bool, nss_ap_isolate); -+ ), -+ -+ TP_fast_assign( -+ LOCAL_ASSIGN; -+ VIF_ASSIGN; -+ __entry->changed = changed; -+ __entry->nss_ap_isolate = info->nss_ap_isolate; -+ ), -+ -+ TP_printk( -+ LOCAL_PR_FMT VIF_PR_FMT " changed:%#x", -+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->changed -+ ) -+); -+ -+DEFINE_EVENT(local_only_evt, drv_nss_return_void, -+ TP_PROTO(struct ieee80211_local *local), -+ TP_ARGS(local) -+); - - TRACE_EVENT(drv_bss_info_changed, - TP_PROTO(struct ieee80211_local *local, diff --git a/package/kernel/mac80211/patches/nss/199-002-ath11k_nss-add-nss-driver-interface.patch b/package/kernel/mac80211/patches/nss/199-002-ath11k_nss-add-nss-driver-interface.patch deleted file mode 100644 index 67df0248e..000000000 --- a/package/kernel/mac80211/patches/nss/199-002-ath11k_nss-add-nss-driver-interface.patch +++ /dev/null @@ -1,2714 +0,0 @@ -From 0fa55ca418c8afd6da242407a184c23548c553dc Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Fri, 5 Jun 2020 12:21:15 +0530 -Subject: [PATCH 2/3] ath11k: Add nss driver interface - -This patch adds interface support for accessing nss driver with -support for initialization, teardown, vap up/down, peer create/delete, -tx/rx. NSS Stats addition is not part of this version. - -Signed-off-by: Sriram R ---- - drivers/net/wireless/ath/ath11k/Kconfig | 9 + - drivers/net/wireless/ath/ath11k/Makefile | 1 + - drivers/net/wireless/ath/ath11k/nss.c | 1762 ++++++++++++++++++++++++++++++ - drivers/net/wireless/ath/ath11k/nss.h | 217 ++++ - 4 files changed, 1989 insertions(+) - create mode 100644 drivers/net/wireless/ath/ath11k/nss.c - create mode 100644 drivers/net/wireless/ath/ath11k/nss.h - ---- a/drivers/net/wireless/ath/ath11k/Kconfig -+++ b/drivers/net/wireless/ath/ath11k/Kconfig -@@ -11,6 +11,15 @@ config ATH11K - - If you choose to build a module, it'll be called ath11k. - -+config ATH11K_NSS_SUPPORT -+ bool "QCA ath11k nss support" -+ depends on ATH11K -+ default y -+ ---help--- -+ Enables NSS offload support for ATH11K driver -+ -+ If unsure, say Y to enable NSS offload support. -+ - config ATH11K_AHB - tristate "Atheros ath11k AHB support" - depends on m ---- a/drivers/net/wireless/ath/ath11k/Makefile -+++ b/drivers/net/wireless/ath/ath11k/Makefile -@@ -27,6 +27,7 @@ ath11k-$(CONFIG_THERMAL) += thermal.o - ath11k-$(CPTCFG_ATH11K_TRACING) += trace.o - ath11k-$(CONFIG_THERMAL) += thermal.o - ath11k-$(CPTCFG_ATH11K_SPECTRAL) += spectral.o -+ath11k-$(CPTCFG_ATH11K_NSS_SUPPORT) += nss.o - - obj-$(CPTCFG_ATH11K_AHB) += ath11k_ahb.o - ath11k_ahb-y += ahb.o ---- /dev/null -+++ b/drivers/net/wireless/ath/ath11k/nss.c -@@ -0,0 +1,2341 @@ -+// SPDX-License-Identifier: BSD-3-Clause-Clear -+/* -+ * Copyright (c) 2020 The Linux Foundation. All rights reserved. -+ */ -+ -+#include "mac.h" -+#include "nss.h" -+#include "core.h" -+#include "peer.h" -+#include "dp_rx.h" -+#include "dp_tx.h" -+#include "hif.h" -+#include "../../../../../net/mac80211/sta_info.h" -+ -+/*-----------------------------ATH11K-NSS Helpers--------------------------*/ -+ -+static enum ath11k_nss_opmode -+ath11k_nss_get_vdev_opmode(struct ath11k_vif *arvif) -+{ -+ switch (arvif->vdev_type) { -+ case WMI_VDEV_TYPE_AP: -+ return ATH11K_NSS_OPMODE_AP; -+ case WMI_VDEV_TYPE_STA: -+ return ATH11K_NSS_OPMODE_STA; -+ default: -+ ath11k_warn(arvif->ar->ab, "unsupported nss vdev type %d\n", -+ arvif->vdev_type); -+ } -+ -+ return ATH11K_NSS_OPMODE_UNKNOWN; -+} -+ -+static void ath11k_nss_wifili_stats_sync(struct ath11k_base *ab, -+ struct nss_wifili_stats_sync_msg *wlsoc_stats) -+{ -+ struct nss_wifili_device_stats *devstats = &wlsoc_stats->stats; -+ struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats; -+ int i; -+ -+ spin_lock_bh(&ab->base_lock); -+ -+ soc_stats->err_ring_pkts += devstats->rxwbm_stats.err_src_rxdma; -+ soc_stats->invalid_rbm += devstats->rxwbm_stats.invalid_buf_mgr; -+ -+ for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++) -+ soc_stats->rxdma_error[i] += devstats->rxwbm_stats.err_dma_codes[i]; -+ -+ for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++) -+ soc_stats->reo_error[i] += devstats->rxwbm_stats.err_reo_codes[i]; -+ -+ for (i = 0; i < DP_REO_DST_RING_MAX; i++) -+ soc_stats->hal_reo_error[i] += devstats->rxreo_stats[i].ring_error; -+ -+ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) -+ soc_stats->tx_err.desc_na[i] += devstats->tcl_stats[i].tcl_ring_full; -+ -+ -+ for (i = 0; i < NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG; i++) -+ atomic_add(devstats->txcomp_stats[i].invalid_bufsrc -+ + devstats->txcomp_stats[i].invalid_cookie -+ + devstats->tx_sw_pool_stats[i].desc_alloc_fail -+ + devstats->tx_ext_sw_pool_stats[i].desc_alloc_fail, -+ &soc_stats->tx_err.misc_fail); -+ -+ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) -+ atomic_add(devstats->tx_data_stats[i].tx_send_fail_cnt, -+ &soc_stats->tx_err.misc_fail); -+ -+ spin_unlock_bh(&ab->base_lock); -+} -+ -+static void ath11k_nss_get_peer_tx_tid_stats(struct ath11k_base *ab, int npeers, struct nss_wifili_sojourn_peer_stats *stats) -+{ -+ struct ath11k_peer *peer; -+ int peer_idx, tid_idx; -+ -+ for (peer_idx = 0; peer_idx < npeers; peer_idx++) { -+ -+ rcu_read_lock(); -+ spin_lock_bh(&ab->base_lock); -+ -+ peer = ath11k_peer_find_by_id(ab, (&stats[peer_idx])->peer_id); -+ if (!peer || !peer->sta) { -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "unable to find peer %d\n", (&stats[peer_idx])->peer_id); -+ spin_unlock_bh(&ab->base_lock); -+ rcu_read_unlock(); -+ continue; -+ } -+ -+ if (!peer->nss.nss_stats) { -+ spin_unlock_bh(&ab->base_lock); -+ rcu_read_unlock(); -+ return; -+ } -+ -+ for (tid_idx = 0; tid_idx < NSS_TX_TID_MAX; tid_idx++) -+ peer->nss.nss_stats->tx_tid_msdu[tid_idx] += (&stats[peer_idx])->stats[tid_idx].num_msdus; -+ -+ spin_unlock_bh(&ab->base_lock); -+ rcu_read_unlock(); -+ } -+} -+ -+static void ath11k_nss_get_peer_stats(struct ath11k_base *ab, struct nss_wifili_peer_stats *stats) -+{ -+ struct ath11k_peer *peer; -+ struct nss_wifili_peer_ctrl_stats *pstats = NULL; -+ int i, j; -+ -+ for (i = 0; i < stats->npeers; i++) { -+ pstats = &stats->wpcs[i]; -+ -+ rcu_read_lock(); -+ spin_lock_bh(&ab->base_lock); -+ -+ peer = ath11k_peer_find_by_id(ab, pstats->peer_id); -+ if (!peer || !peer->sta) { -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "unable to find peer %d\n", pstats->peer_id); -+ spin_unlock_bh(&ab->base_lock); -+ rcu_read_unlock(); -+ continue; -+ } -+ -+ if (!peer->nss.nss_stats) { -+ spin_unlock_bh(&ab->base_lock); -+ rcu_read_unlock(); -+ return; -+ } -+ -+ if (pstats->tx.tx_success_cnt) -+ peer->nss.nss_stats->last_ack = jiffies; -+ -+ if (pstats->rx.rx_recvd) { -+ peer->nss.nss_stats->last_rx = jiffies; -+ } -+ -+ peer->nss.nss_stats->tx_packets += pstats->tx.tx_mcast_cnt + -+ pstats->tx.tx_ucast_cnt + -+ pstats->tx.tx_bcast_cnt; -+ peer->nss.nss_stats->tx_bytes += pstats->tx.tx_mcast_bytes + -+ pstats->tx.tx_ucast_bytes + -+ pstats->tx.tx_bcast_bytes; -+ peer->nss.nss_stats->tx_retries += pstats->tx.retries; -+ -+ for (j = 0; j < NSS_WIFILI_TQM_RR_MAX; j++) -+ peer->nss.nss_stats->tx_failed += pstats->tx.dropped.drop_stats[j]; -+ -+ peer->nss.nss_stats->rx_packets += pstats->rx.rx_recvd; -+ peer->nss.nss_stats->rx_bytes += pstats->rx.rx_recvd_bytes; -+ peer->nss.nss_stats->rx_dropped += pstats->rx.err.mic_err + -+ pstats->rx.err.decrypt_err; -+ -+ spin_unlock_bh(&ab->base_lock); -+ rcu_read_unlock(); -+ } -+} -+ -+void ath11k_nss_ext_rx_stats(struct ath11k_base *ab, struct htt_rx_ring_tlv_filter *tlv_filter) -+{ -+ if (ab->nss.enabled) -+ tlv_filter->rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS; -+} -+ -+static u32 ath11k_nss_cipher_type(struct ath11k_base *ab, u32 cipher) -+{ -+ switch (cipher) { -+ case WLAN_CIPHER_SUITE_CCMP: -+ return PEER_SEC_TYPE_AES_CCMP; -+ case WLAN_CIPHER_SUITE_TKIP: -+ return PEER_SEC_TYPE_TKIP; -+ case WLAN_CIPHER_SUITE_CCMP_256: -+ return PEER_SEC_TYPE_AES_CCMP_256; -+ case WLAN_CIPHER_SUITE_GCMP: -+ return PEER_SEC_TYPE_AES_GCMP; -+ case WLAN_CIPHER_SUITE_GCMP_256: -+ return PEER_SEC_TYPE_AES_GCMP_256; -+ default: -+ ath11k_warn(ab, "unknown cipher type %d\n", cipher); -+ return PEER_SEC_TYPE_NONE; -+ } -+} -+ -+static void ath11k_nss_tx_encap_nwifi(struct sk_buff *skb) -+{ -+ struct ieee80211_hdr *hdr = (void *)skb->data; -+ u8 *qos_ctl; -+ -+ if (!ieee80211_is_data_qos(hdr->frame_control)) -+ return; -+ -+ qos_ctl = ieee80211_get_qos_ctl(hdr); -+ memmove(skb->data + IEEE80211_QOS_CTL_LEN, -+ skb->data, (void *)qos_ctl - (void *)skb->data); -+ skb_pull(skb, IEEE80211_QOS_CTL_LEN); -+ -+ hdr = (void *)skb->data; -+ hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA); -+} -+ -+static void ath11k_nss_tx_encap_raw(struct sk_buff *skb) -+{ -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ struct ieee80211_hdr *hdr = (void *)skb->data; -+ u32 cipher; -+ -+ if (!ieee80211_has_protected(hdr->frame_control)) -+ return; -+ -+ /* Include length for MIC */ -+ skb_put(skb, IEEE80211_CCMP_MIC_LEN); -+ -+ /* Include length for ICV if TKIP is used */ -+ cipher = info->control.hw_key->cipher; -+ if (cipher == WLAN_CIPHER_SUITE_TKIP) -+ skb_put(skb, IEEE80211_TKIP_ICV_LEN); -+} -+ -+static void ath11k_nss_peer_mem_free(struct ath11k_base *ab, u32 peer_id) -+{ -+ struct ath11k_peer *peer; -+ -+ spin_lock_bh(&ab->base_lock); -+ -+ peer = ath11k_peer_find_by_id(ab, peer_id); -+ if (!peer) { -+ spin_unlock_bh(&ab->base_lock); -+ ath11k_warn(ab, "ath11k_nss: unable to free peer mem%d\n", -+ peer_id); -+ return; -+ } -+ -+ dma_unmap_single(ab->dev, peer->nss.paddr, -+ WIFILI_NSS_PEER_BYTE_SIZE, DMA_TO_DEVICE); -+ -+ kfree(peer->nss.vaddr); -+ if (peer->nss.nss_stats) { -+ kfree(peer->nss.nss_stats); -+ peer->nss.nss_stats = NULL; -+ } -+ -+ spin_unlock_bh(&ab->base_lock); -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "nss peer %d mem freed\n", peer_id); -+} -+ -+/*-----------------------------Events/Callbacks------------------------------*/ -+ -+void ath11k_nss_wifili_event_receive(struct ath11k_base *ab, struct nss_wifili_msg *msg) -+{ -+ u32 msg_type = msg->cm.type; -+ enum nss_cmn_response response = msg->cm.response; -+ u32 error = msg->cm.error; -+ u32 peer_id; -+ struct nss_wifili_peer_stats *peer_stats; -+ struct nss_wifili_sojourn_stats_msg *stats_msg; -+ -+ if (!ab) -+ return; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "nss wifili event received %d response %d error %d\n", -+ msg_type, response, error); -+ -+ switch (msg_type) { -+ case NSS_WIFILI_INIT_MSG: -+ case NSS_WIFILI_PDEV_INIT_MSG: -+ case NSS_WIFILI_START_MSG: -+ case NSS_WIFILI_SOC_RESET_MSG: -+ case NSS_WIFILI_STOP_MSG: -+ case NSS_WIFILI_PDEV_DEINIT_MSG: -+ ab->nss.response = response; -+ complete(&ab->nss.complete); -+ break; -+ -+ case NSS_WIFILI_PEER_CREATE_MSG: -+ if (response != NSS_CMN_RESPONSE_EMSG) -+ break; -+ -+ peer_id = (&msg->msg.peermsg)->peer_id; -+ -+ /* free peer memory allocated during peer create due to failure */ -+ ath11k_nss_peer_mem_free(ab, peer_id); -+ break; -+ case NSS_WIFILI_PEER_DELETE_MSG: -+ peer_id = (&msg->msg.peermsg)->peer_id; -+ -+ if (response == NSS_CMN_RESPONSE_EMSG) -+ ath11k_warn(ab, "ath11k_nss: peer delete failed%d\n", -+ peer_id); -+ -+ /* free peer memory allocated during peer create irrespective of -+ * delete status -+ */ -+ ath11k_nss_peer_mem_free(ab, peer_id); -+ break; -+ case NSS_WIFILI_PEER_SECURITY_TYPE_MSG: -+ if (response == NSS_CMN_RESPONSE_EMSG) -+ ath11k_warn(ab, "peer securty config failed\n"); -+ -+ break; -+ case NSS_WIFILI_STATS_MSG: -+ if (response == NSS_CMN_RESPONSE_EMSG) { -+ ath11k_warn(ab, "soc_dp_stats failed to get updated\n"); -+ break; -+ } -+ ath11k_nss_wifili_stats_sync(ab, &msg->msg.wlsoc_stats); -+ break; -+ case NSS_WIFILI_PEER_STATS_MSG: -+ peer_stats = &msg->msg.peer_stats.stats; -+ if (response == NSS_CMN_RESPONSE_EMSG) { -+ ath11k_warn(ab, "peer stats msg failed with error = %u\n", error); -+ break; -+ } -+ ath11k_nss_get_peer_stats(ab, peer_stats); -+ break; -+ case NSS_WIFILI_SOJOURN_STATS_MSG: -+ stats_msg = &msg->msg.sj_stats_msg; -+ if (response == NSS_CMN_RESPONSE_EMSG) { -+ ath11k_warn(ab, "tid peer stats msg failed with error = %u\n", error); -+ break; -+ } -+ ath11k_nss_get_peer_tx_tid_stats(ab, stats_msg->npeers, &stats_msg->sj_peer_stats[0]); -+ break; -+ case NSS_WIFILI_TID_REOQ_SETUP_MSG: -+ /* TODO setup tidq */ -+ break; -+ default: -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "unhandled event %d\n", msg_type); -+ break; -+ } -+} -+ -+void ath11k_nss_process_mic_error(struct ath11k_base *ab, struct sk_buff *skb) -+{ -+ struct ath11k_vif *arvif; -+ struct ath11k_peer *peer = NULL; -+ struct hal_rx_desc *desc = (struct hal_rx_desc *)skb->data; -+ struct wireless_dev *wdev; -+ u16 peer_id; -+ u8 peer_addr[ETH_ALEN]; -+ u8 ucast_keyidx, mcast_keyidx; -+ bool is_mcbc; -+ -+ if (!ath11k_dp_rx_h_msdu_end_first_msdu(desc)) -+ goto fail; -+ -+ is_mcbc = ath11k_dp_rx_h_attn_is_mcbc(desc); -+ peer_id = ath11k_dp_rx_h_mpdu_start_peer_id(desc); -+ -+ spin_lock_bh(&ab->base_lock); -+ peer = ath11k_peer_find_by_id(ab, peer_id); -+ if (!peer) { -+ ath11k_info(ab, "ath11k_nss:peer not found"); -+ spin_unlock_bh(&ab->base_lock); -+ goto fail; -+ } -+ -+ if (!peer->vif) { -+ ath11k_warn(ab, "ath11k_nss:vif not found"); -+ spin_unlock_bh(&ab->base_lock); -+ goto fail; -+ } -+ -+ ether_addr_copy(peer_addr, peer->addr); -+ mcast_keyidx = peer->mcast_keyidx; -+ ucast_keyidx = peer->ucast_keyidx; -+ arvif = ath11k_vif_to_arvif(peer->vif); -+ spin_unlock_bh(&ab->base_lock); -+ -+ if (!arvif->is_started) { -+ ath11k_warn(ab, "ath11k_nss:arvif not started"); -+ goto fail; -+ } -+ -+ wdev = ieee80211_vif_to_wdev_relaxed(arvif->vif); -+ if (!wdev) { -+ ath11k_warn(ab, "ath11k_nss: wdev is null\n"); -+ goto fail; -+ } -+ -+ if (!wdev->netdev) { -+ ath11k_warn(ab, "ath11k_nss: netdev is null\n"); -+ goto fail; -+ } -+ -+ cfg80211_michael_mic_failure(wdev->netdev, peer_addr, -+ is_mcbc ? NL80211_KEYTYPE_GROUP : -+ NL80211_KEYTYPE_PAIRWISE, -+ is_mcbc ? mcast_keyidx : ucast_keyidx, -+ NULL, GFP_ATOMIC); -+ kfree(skb); -+ return; -+ -+fail: -+ kfree(skb); -+ ath11k_warn(ab, "ath11k_nss: Failed to handle mic error\n"); -+ return; -+} -+ -+static void -+ath11k_nss_wifili_ext_callback_fn(struct ath11k_base *ab, struct sk_buff *skb, -+ __attribute__((unused)) struct napi_struct *napi) -+{ -+ struct nss_wifili_soc_per_packet_metadata *wepm; -+ -+ wepm = (struct nss_wifili_soc_per_packet_metadata *)(skb->head + -+ NSS_WIFILI_SOC_PER_PACKET_METADATA_OFFSET); -+ -+ switch (wepm->pkt_type) { -+ case NSS_WIFILI_SOC_EXT_DATA_PKT_MIC_ERROR: -+ ath11k_nss_process_mic_error(ab, skb); -+ break; -+ default: -+ kfree(skb); -+ break; -+ } -+} -+ -+void ath11k_nss_vdev_cfg_cb(void *app_data, struct nss_cmn_msg *msg) -+{ -+ struct ath11k_vif *arvif = (struct ath11k_vif *)app_data; -+ -+ if (!arvif) -+ return; -+ -+ ath11k_dbg(arvif->ar->ab, ATH11K_DBG_NSS, "vdev cfg msg callback received msg:%d rsp:%d\n", -+ msg->type, msg->response); -+ -+ complete(&arvif->nss.complete); -+} -+ -+static void ath11k_nss_vdev_event_receive(void *dev, struct nss_cmn_msg *vdev_msg) -+{ -+ /*TODO*/ -+} -+ -+static void -+ath11k_nss_vdev_special_data_receive(struct net_device *dev, struct sk_buff *skb, -+ __attribute__((unused)) struct napi_struct *napi) -+{ -+ /* TODO */ -+} -+ -+/* TODO: move to mac80211 after cleanups/refactoring required after feature completion */ -+static int ath11k_nss_deliver_rx(struct ieee80211_vif *vif, struct sk_buff *skb, -+ bool eth, int data_offs, struct napi_struct *napi) -+{ -+ struct sk_buff_head subframe_list; -+ struct ieee80211_hdr *hdr; -+ struct sk_buff *subframe; -+ struct net_device *dev; -+ int hdr_len; -+ u8 *qc; -+ -+ dev = skb->dev; -+ -+ if (eth) -+ goto deliver_msdu; -+ -+ hdr = (struct ieee80211_hdr *)skb->data; -+ hdr_len = ieee80211_hdrlen(hdr->frame_control); -+ -+ if (ieee80211_is_data_qos(hdr->frame_control)) { -+ qc = ieee80211_get_qos_ctl(hdr); -+ if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) -+ goto deliver_amsdu; -+ } -+ -+ if (ieee80211_data_to_8023_exthdr(skb, NULL, vif->addr, vif->type, -+ data_offs - hdr_len, false)) { -+ dev_kfree_skb_any(skb); -+ return -EINVAL; -+ } -+ -+deliver_msdu: -+ skb->protocol = eth_type_trans(skb, dev); -+ napi_gro_receive(napi, skb); -+ return 0; -+ -+deliver_amsdu: -+ /* Move to the start of the first subframe */ -+ skb_pull(skb, data_offs); -+ -+ __skb_queue_head_init(&subframe_list); -+ -+ /* create list containing all the subframes */ -+ ieee80211_amsdu_to_8023s(skb, &subframe_list, NULL, -+ vif->type, 0, NULL, NULL); -+ -+ /* This shouldn't happen, indicating error during defragmentation */ -+ if (skb_queue_empty(&subframe_list)) -+ return -EINVAL; -+ -+ while (!skb_queue_empty(&subframe_list)) { -+ subframe = __skb_dequeue(&subframe_list); -+ subframe->protocol = eth_type_trans(subframe, dev); -+ napi_gro_receive(napi, subframe); -+ } -+ -+ return 0; -+} -+ -+static int ath11k_nss_undecap_raw(struct ath11k_vif *arvif, struct sk_buff *skb, -+ int *data_offset) -+{ -+ struct ath11k_base *ab = arvif->ar->ab; -+ struct ath11k *ar = arvif->ar; -+ enum hal_encrypt_type enctype; -+ struct ath11k_peer *peer = NULL; -+ struct ieee80211_hdr *hdr; -+ int hdr_len; -+ -+ hdr = (struct ieee80211_hdr *)skb->data; -+ hdr_len = ieee80211_hdrlen(hdr->frame_control); -+ -+ *data_offset = hdr_len; -+ -+ /* FCS is included in the raw mode skb, we can trim it, fcs error -+ * packets are not expected to be received in this path -+ */ -+ skb_trim(skb, skb->len - FCS_LEN); -+ -+ spin_lock_bh(&ab->base_lock); -+ -+ peer = ath11k_peer_find_by_addr(ab, hdr->addr2); -+ if (!peer) { -+ ath11k_warn(ab, "peer not found for raw/nwifi undecap, drop this packet\n"); -+ spin_unlock_bh(&ab->base_lock); -+ return -EINVAL; -+ } -+ enctype = peer->sec_type; -+ -+ spin_unlock_bh(&ab->base_lock); -+ -+ *data_offset += ath11k_dp_rx_crypto_param_len(ar, enctype); -+ -+ /* Strip ICV, MIC, MMIC */ -+ skb_trim(skb, skb->len - -+ ath11k_dp_rx_crypto_mic_len(ar, enctype)); -+ -+ skb_trim(skb, skb->len - -+ ath11k_dp_rx_crypto_icv_len(ar, enctype)); -+ -+ if (enctype == HAL_ENCRYPT_TYPE_TKIP_MIC) -+ skb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN); -+ -+ return 0; -+} -+ -+static int ath11k_nss_undecap_nwifi(struct ath11k_vif *arvif, struct sk_buff *skb, -+ int *data_offset) -+{ -+ struct ieee80211_hdr *hdr; -+ int hdr_len; -+ -+ hdr = (struct ieee80211_hdr *)skb->data; -+ hdr_len = ieee80211_hdrlen(hdr->frame_control); -+ -+ *data_offset = hdr_len; -+ -+ /* We dont receive the IV from nss host on slow path -+ * hence we can return only the header length as offset. -+ **/ -+ return 0; -+} -+ -+static void -+ath11k_nss_vdev_data_receive(struct net_device *dev, struct sk_buff *skb, -+ __attribute__((unused)) struct napi_struct *napi) -+{ -+ enum ath11k_hw_txrx_mode decap_type; -+ struct wireless_dev *wdev; -+ struct ieee80211_vif *vif; -+ struct ath11k_vif *arvif; -+ struct ath11k_base *ab; -+ bool eth_decap = false; -+ int data_offs = 0; -+ int ret; -+ -+ if (!dev) { -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ wdev = dev->ieee80211_ptr; -+ if (!wdev) { -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ vif = wdev_to_ieee80211_vif(wdev); -+ if (!vif) { -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ arvif = (struct ath11k_vif *)vif->drv_priv; -+ if (!arvif) { -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ ab = arvif->ar->ab; -+ -+ skb->dev = dev; -+ -+ /* log the original skb received from nss */ -+ ath11k_dbg_dump(ab, ATH11K_DBG_DP_RX, "", "dp rx msdu from nss: ", -+ skb->data, skb->len); -+ -+ decap_type = arvif->nss.decap; -+ -+ switch (decap_type) { -+ case ATH11K_HW_TXRX_RAW: -+ ret = ath11k_nss_undecap_raw(arvif, skb, &data_offs); -+ break; -+ case ATH11K_HW_TXRX_NATIVE_WIFI: -+ ret = ath11k_nss_undecap_nwifi(arvif, skb, &data_offs); -+ break; -+ case ATH11K_HW_TXRX_ETHERNET: -+ /* no changes required for ethernet decap */ -+ ret = 0; -+ eth_decap = true; -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ if (ret) { -+ ath11k_warn(ab, "error in nss rx undecap, type %d err %d\n", decap_type, -+ ret); -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ ath11k_nss_deliver_rx(arvif->vif, skb, eth_decap, data_offs, napi); -+} -+ -+int ath11k_nss_tx(struct ath11k_vif *arvif, struct sk_buff *skb) -+{ -+ struct ath11k *ar = arvif->ar; -+ nss_tx_status_t status; -+ int encap_type = ath11k_dp_tx_get_encap_type(arvif, skb); -+ struct ath11k_soc_dp_stats *soc_stats = &ar->ab->soc_stats; -+ -+ if(encap_type != arvif->nss.encap) { -+ ath11k_warn(ar->ab, "encap mismatch in nss tx skb encap type %d" \ -+ "vif encap type %d\n", encap_type, arvif->nss.encap); -+ goto drop; -+ } -+ -+ if (encap_type == HAL_TCL_ENCAP_TYPE_ETHERNET) -+ goto send; -+ -+ if (encap_type == HAL_TCL_ENCAP_TYPE_RAW) -+ ath11k_nss_tx_encap_raw(skb); -+ else -+ ath11k_nss_tx_encap_nwifi(skb); -+ -+send: -+ ath11k_dbg_dump(ar->ab, ATH11K_DBG_DP_TX, "", "nss tx msdu: ", -+ skb->data, skb->len); -+ -+ status = nss_wifi_vdev_tx_buf(arvif->ar->nss.ctx, skb, arvif->nss.if_num); -+ -+ if (status != NSS_TX_SUCCESS) -+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss tx failure\n"); -+ -+ return status; -+drop: -+ atomic_inc(&soc_stats->tx_err.misc_fail); -+ WARN_ON_ONCE(1); -+ return -EINVAL; -+} -+ -+int ath11k_nss_vdev_set_cmd(struct ath11k_vif *arvif, int cmd, int val) -+{ -+ struct nss_wifi_vdev_msg *vdev_msg = NULL; -+ struct nss_wifi_vdev_cmd_msg *vdev_cmd; -+ struct ath11k *ar = arvif->ar; -+ nss_tx_status_t status; -+ -+ if (!ar->ab->nss.enabled) -+ return 0; -+ -+ /* Monitor interface is not offloaded to nss */ -+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) -+ return 0; -+ -+ vdev_msg = kzalloc(sizeof(*vdev_msg), GFP_ATOMIC); -+ if (!vdev_msg) -+ return -ENOMEM; -+ -+ /* TODO: Convert to function for conversion in case of many -+ * such commands -+ */ -+ if (cmd == NSS_WIFI_VDEV_SECURITY_TYPE_CMD) -+ val = ath11k_nss_cipher_type(ar->ab, val); -+ -+ if (cmd == NSS_WIFI_VDEV_ENCAP_TYPE_CMD) -+ arvif->nss.encap = val; -+ else if (cmd == NSS_WIFI_VDEV_DECAP_TYPE_CMD) -+ arvif->nss.decap = val; -+ -+ vdev_cmd = &vdev_msg->msg.vdev_cmd; -+ vdev_cmd->cmd = cmd; -+ vdev_cmd->value = val; -+ -+ nss_wifi_vdev_msg_init(vdev_msg, arvif->nss.if_num, -+ NSS_WIFI_VDEV_INTERFACE_CMD_MSG, -+ sizeof(struct nss_wifi_vdev_cmd_msg), -+ NULL, NULL); -+ -+ status = nss_wifi_vdev_tx_msg(ar->nss.ctx, vdev_msg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ar->ab, "nss vdev set cmd failure cmd:%d val:%d", -+ cmd, val); -+ goto free; -+ } -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss vdev set cmd success cmd:%d val:%d\n", -+ cmd, val); -+free: -+ kfree(vdev_msg); -+ return status; -+} -+ -+static int ath11k_nss_vdev_configure(struct ath11k_vif *arvif) -+{ -+ struct ath11k *ar = arvif->ar; -+ struct nss_wifi_vdev_msg *vdev_msg; -+ struct nss_wifi_vdev_config_msg *vdev_cfg; -+ nss_tx_status_t status; -+ int ret; -+ -+ vdev_msg = kzalloc(sizeof(struct nss_wifi_vdev_msg), GFP_ATOMIC); -+ if (!vdev_msg) -+ return -ENOMEM; -+ -+ vdev_cfg = &vdev_msg->msg.vdev_config; -+ -+ vdev_cfg->radio_ifnum = ar->nss.if_num; -+ vdev_cfg->vdev_id = arvif->vdev_id; -+ -+ vdev_cfg->opmode = ath11k_nss_get_vdev_opmode(arvif); -+ -+ ether_addr_copy(vdev_cfg->mac_addr, arvif->vif->addr); -+ -+ reinit_completion(&arvif->nss.complete); -+ -+ nss_wifi_vdev_msg_init(vdev_msg, arvif->nss.if_num, -+ NSS_WIFI_VDEV_INTERFACE_CONFIGURE_MSG, -+ sizeof(struct nss_wifi_vdev_config_msg), -+ (nss_wifi_vdev_msg_callback_t *)ath11k_nss_vdev_cfg_cb, -+ arvif); -+ -+ status = nss_wifi_vdev_tx_msg(ar->nss.ctx, vdev_msg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ar->ab, "failed to configure nss vdev nss_err:%d\n", -+ status); -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ ret = wait_for_completion_timeout(&arvif->nss.complete, -+ msecs_to_jiffies(ATH11K_NSS_MSG_TIMEOUT_MS)); -+ if (!ret) { -+ ath11k_warn(ar->ab, "timeout in receiving nss vdev cfg response\n"); -+ ret = -ETIMEDOUT; -+ goto free; -+ } -+ -+ ret = 0; -+free: -+ kfree(vdev_msg); -+ -+ return ret; -+} -+ -+static void ath11k_nss_vdev_unregister(struct ath11k_vif *arvif) -+{ -+ struct ath11k_base *ab = arvif->ar->ab; -+ -+ switch (arvif->vif->type) { -+ case NL80211_IFTYPE_AP: -+ case NL80211_IFTYPE_STATION: -+ nss_unregister_wifi_vdev_if(arvif->nss.if_num); -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "unregistered nss vdev %d \n", -+ arvif->nss.if_num); -+ break; -+ default: -+ ath11k_warn(ab, "unsupported interface type %d for nss vdev unregister\n", -+ arvif->vif->type); -+ return; -+ } -+} -+ -+static int ath11k_nss_vdev_register(struct ath11k_vif *arvif, -+ struct net_device *netdev) -+{ -+ struct ath11k *ar = arvif->ar; -+ struct ath11k_base *ab = ar->ab; -+ nss_tx_status_t status; -+ u32 features = 0; -+ -+ switch (arvif->vif->type) { -+ case NL80211_IFTYPE_AP: -+ case NL80211_IFTYPE_STATION: -+ status = nss_register_wifi_vdev_if(ar->nss.ctx, -+ arvif->nss.if_num, -+ ath11k_nss_vdev_data_receive, -+ ath11k_nss_vdev_special_data_receive, -+ ath11k_nss_vdev_event_receive, -+ netdev, features); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "failed to register nss vdev if_num %d nss_err:%d\n", -+ arvif->nss.if_num, status); -+ return -EINVAL; -+ } -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "registered nss vdev if_num %d\n", -+ arvif->nss.if_num); -+ -+ break; -+ default: -+ ath11k_warn(ab, "unsupported interface type %d for nss vdev register\n", -+ arvif->vif->type); -+ return -ENOTSUPP; -+ } -+ -+ return 0; -+} -+ -+void ath11k_nss_vdev_free(struct ath11k_vif *arvif) -+{ -+ struct ath11k_base *ab = arvif->ar->ab; -+ nss_tx_status_t status; -+ -+ switch (arvif->vif->type) { -+ case NL80211_IFTYPE_AP: -+ case NL80211_IFTYPE_STATION: -+ status = nss_dynamic_interface_dealloc_node( -+ arvif->nss.if_num, -+ NSS_DYNAMIC_INTERFACE_TYPE_VAP); -+ if (status != NSS_TX_SUCCESS) -+ ath11k_warn(ab, "failed to free nss vdev nss_err:%d\n", -+ status); -+ else -+ ath11k_dbg(ab, ATH11K_DBG_NSS, -+ "nss vdev interface deallocated\n"); -+ -+ return; -+ default: -+ ath11k_warn(ab, "unsupported interface type %d for nss vdev dealloc\n", -+ arvif->vif->type); -+ return; -+ } -+} -+ -+static int ath11k_nss_vdev_alloc(struct ath11k_vif *arvif) -+{ -+ struct ath11k_base *ab = arvif->ar->ab; -+ enum nss_dynamic_interface_type if_type; -+ int if_num; -+ -+ /* Initialize completion for verifying NSS message response */ -+ init_completion(&arvif->nss.complete); -+ -+ switch (arvif->vif->type) { -+ case NL80211_IFTYPE_AP: -+ case NL80211_IFTYPE_STATION: -+ if_type = NSS_DYNAMIC_INTERFACE_TYPE_VAP; -+ /* allocate interface context with NSS driver for the new vdev */ -+ if_num = nss_dynamic_interface_alloc_node(if_type); -+ if (if_num < 0) { -+ ath11k_warn(ab, "failed to allocate nss vdev\n"); -+ return -EINVAL; -+ } -+ -+ arvif->nss.if_num = if_num; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "allocated nss vdev if_num %d\n", -+ arvif->nss.if_num); -+ -+ break; -+ default: -+ ath11k_warn(ab, "unsupported interface type %d for nss vdev alloc\n", -+ arvif->vif->type); -+ return -ENOTSUPP; -+ } -+ -+ return 0; -+} -+ -+int ath11k_nss_vdev_create(struct ath11k_vif *arvif) -+{ -+ struct ath11k *ar = arvif->ar; -+ struct ath11k_base *ab = ar->ab; -+ struct wireless_dev *wdev; -+ int ret; -+ -+ if (!ab->nss.enabled) -+ return 0; -+ -+ /* Monitor interface is not offloaded to nss */ -+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) -+ return 0; -+ -+ if (arvif->nss.created) -+ return 0; -+ -+ wdev = ieee80211_vif_to_wdev_relaxed(arvif->vif); -+ if (!wdev) { -+ ath11k_warn(ab, "ath11k_nss: wdev is null\n"); -+ return -EINVAL; -+ } -+ -+ if (!wdev->netdev) { -+ ath11k_warn(ab, "ath11k_nss: netdev is null\n"); -+ return -EINVAL; -+ } -+ -+ ret = ath11k_nss_vdev_alloc(arvif); -+ if (ret) -+ return ret; -+ -+ ret = ath11k_nss_vdev_register(arvif, wdev->netdev); -+ if (ret) -+ goto free_vdev; -+ -+ switch (arvif->vif->type) { -+ case NL80211_IFTYPE_AP: -+ case NL80211_IFTYPE_STATION: -+ ret = ath11k_nss_vdev_configure(arvif); -+ if (ret) -+ goto unregister_vdev; -+ -+ break; -+ default: -+ ret = -ENOTSUPP; -+ goto unregister_vdev; -+ } -+ -+ arvif->nss.created = true; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, -+ "nss vdev interface created ctx %pK, ifnum %d\n", -+ ar->nss.ctx, arvif->nss.if_num); -+ -+ return ret; -+ -+unregister_vdev: -+ ath11k_nss_vdev_unregister(arvif); -+free_vdev: -+ ath11k_nss_vdev_free(arvif); -+ -+ return ret; -+} -+ -+void ath11k_nss_vdev_delete(struct ath11k_vif *arvif) -+{ -+ if (!arvif->ar->ab->nss.enabled) -+ return; -+ -+ /* Monitor interface is not offloaded to nss */ -+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) -+ return; -+ -+ if (!arvif->nss.created) -+ return; -+ -+ ath11k_nss_vdev_unregister(arvif); -+ -+ ath11k_nss_vdev_free(arvif); -+ -+ arvif->nss.created = false; -+} -+ -+int ath11k_nss_vdev_up(struct ath11k_vif *arvif) -+{ -+ struct nss_wifi_vdev_msg *vdev_msg = NULL; -+ struct nss_wifi_vdev_enable_msg *vdev_en; -+ struct ath11k *ar = arvif->ar; -+ nss_tx_status_t status; -+ int ret = 0; -+ -+ if (!ar->ab->nss.enabled) -+ return 0; -+ -+ /* Monitor interface is not offloaded to nss */ -+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) -+ return 0; -+ -+ vdev_msg = kzalloc(sizeof(struct nss_wifi_vdev_msg), GFP_ATOMIC); -+ if (!vdev_msg) -+ return -ENOMEM; -+ -+ vdev_en = &vdev_msg->msg.vdev_enable; -+ -+ ether_addr_copy(vdev_en->mac_addr, arvif->vif->addr); -+ -+ nss_wifi_vdev_msg_init(vdev_msg, arvif->nss.if_num, -+ NSS_WIFI_VDEV_INTERFACE_UP_MSG, -+ sizeof(struct nss_wifi_vdev_enable_msg), -+ NULL, NULL); -+ -+ status = nss_wifi_vdev_tx_msg(ar->nss.ctx, vdev_msg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ar->ab, "nss vdev up tx msg error %d\n", status); -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss vdev up tx msg success\n"); -+free: -+ kfree(vdev_msg); -+ return ret; -+} -+ -+int ath11k_nss_vdev_down(struct ath11k_vif *arvif) -+{ -+ struct nss_wifi_vdev_msg *vdev_msg = NULL; -+ struct ath11k *ar = arvif->ar; -+ nss_tx_status_t status; -+ int ret = 0; -+ -+ if (!ar->ab->nss.enabled) -+ return 0; -+ -+ /* Monitor interface is not offloaded to nss */ -+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) -+ return 0; -+ -+ vdev_msg = kzalloc(sizeof(struct nss_wifi_vdev_msg), GFP_ATOMIC); -+ if (!vdev_msg) -+ return -ENOMEM; -+ -+ nss_wifi_vdev_msg_init(vdev_msg, arvif->nss.if_num, -+ NSS_WIFI_VDEV_INTERFACE_DOWN_MSG, -+ sizeof(struct nss_wifi_vdev_disable_msg), -+ NULL, NULL); -+ -+ status = nss_wifi_vdev_tx_msg(ar->nss.ctx, vdev_msg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ar->ab, "nss vdev down tx msg error %d\n", status); -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss vdev down tx msg success\n"); -+free: -+ kfree(vdev_msg); -+ return ret; -+} -+ -+/*----------------------------Peer Setup/Config -----------------------------*/ -+ -+int ath11k_nss_set_peer_sec_type(struct ath11k *ar, -+ struct ath11k_peer *peer, -+ struct ieee80211_key_conf *key_conf) -+{ -+ struct nss_wifili_peer_security_type_msg *sec_msg; -+ nss_wifili_msg_callback_t msg_cb; -+ struct nss_wifili_msg *wlmsg; -+ nss_tx_status_t status; -+ u8 *mic_key; -+ -+ if (!ar->ab->nss.enabled) -+ return 0; -+ -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) -+ return -ENOMEM; -+ -+ sec_msg = &wlmsg->msg.securitymsg; -+ sec_msg->peer_id = peer->peer_id; -+ -+ /* 0 -unicast , 1 - mcast/unicast */ -+ sec_msg->pkt_type = !(key_conf->flags & IEEE80211_KEY_FLAG_PAIRWISE); -+ -+ sec_msg->security_type = ath11k_nss_cipher_type(ar->ab, -+ key_conf->cipher); -+ -+ if (sec_msg->security_type == PEER_SEC_TYPE_TKIP) { -+ mic_key = &key_conf->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; -+ memcpy(&sec_msg->mic_key[0], mic_key, NSS_WIFILI_MIC_KEY_LEN); -+ } -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ nss_cmn_msg_init(&wlmsg->cm, ar->ab->nss.if_num, -+ NSS_WIFILI_PEER_SECURITY_TYPE_MSG, -+ sizeof(struct nss_wifili_peer_security_type_msg), -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(ar->nss.ctx, wlmsg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ar->ab, "nss peer %d security cfg fail %d\n", -+ peer->peer_id, status); -+ goto free; -+ } -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss peer id %d security cfg complete\n", -+ peer->peer_id); -+free: -+ kfree(wlmsg); -+ return status; -+} -+ -+void ath11k_nss_update_sta_stats(struct station_info *sinfo, -+ struct ieee80211_sta *sta, -+ struct ath11k_sta *arsta) -+{ -+ struct sta_info *stainfo; -+ struct ath11k_peer *peer; -+ int tid_idx; -+ struct ath11k *ar = arsta->arvif->ar; -+ struct ath11k_base *ab = ar->ab; -+ -+ if (!ab->nss.enabled) -+ return; -+ -+ spin_lock_bh(&ab->base_lock); -+ peer = ath11k_peer_find_by_addr(arsta->arvif->ar->ab, sta->addr); -+ if (!peer) { -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "unable to find peer %pM\n", -+ sta->addr); -+ goto exit; -+ } -+ -+ if (!peer->nss.nss_stats) -+ goto exit; -+ -+ stainfo = container_of(sta, struct sta_info, sta); -+ if (peer->nss.nss_stats->last_rx && -+ time_after((unsigned long)peer->nss.nss_stats->last_rx, stainfo->rx_stats.last_rx)) -+ stainfo->rx_stats.last_rx = peer->nss.nss_stats->last_rx; -+ -+ if (peer->nss.nss_stats->last_ack && -+ time_after((unsigned long)peer->nss.nss_stats->last_ack, stainfo->status_stats.last_ack)) -+ stainfo->status_stats.last_ack = peer->nss.nss_stats->last_ack; -+ -+ stainfo->rx_stats.dropped += peer->nss.nss_stats->rx_dropped - -+ peer->nss.nss_stats->last_rxdrop; -+ peer->nss.nss_stats->last_rxdrop = peer->nss.nss_stats->rx_dropped; -+ -+ sinfo->tx_packets = 0; -+ /* Add only ac-0 count as mgmt packets uses WME_AC_BE */ -+ sinfo->tx_packets += stainfo->tx_stats.packets[WME_AC_BE]; -+ sinfo->tx_packets += peer->nss.nss_stats->tx_packets; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); -+ sinfo->tx_bytes = 0; -+ -+ /* Add only ac-0 count as mgmt packets uses WME_AC_BE */ -+ sinfo->tx_bytes += stainfo->tx_stats.bytes[WME_AC_BE]; -+ sinfo->tx_bytes += peer->nss.nss_stats->tx_bytes; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES); -+ -+ sinfo->tx_failed = stainfo->status_stats.retry_failed + -+ peer->nss.nss_stats->tx_failed; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); -+ -+ sinfo->tx_retries = stainfo->status_stats.retry_count + -+ peer->nss.nss_stats->tx_retries; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); -+ -+ sinfo->rx_packets = stainfo->rx_stats.packets + -+ peer->nss.nss_stats->rx_packets; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS); -+ -+ sinfo->rx_bytes = stainfo->rx_stats.bytes + -+ peer->nss.nss_stats->rx_bytes; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES); -+ -+ if (peer->nss.nss_stats->rxrate.legacy || peer->nss.nss_stats->rxrate.nss) { -+ if (peer->nss.nss_stats->rxrate.legacy) { -+ sinfo->rxrate.legacy = peer->nss.nss_stats->rxrate.legacy; -+ } else { -+ sinfo->rxrate.mcs = peer->nss.nss_stats->rxrate.mcs; -+ sinfo->rxrate.nss = peer->nss.nss_stats->rxrate.nss; -+ sinfo->rxrate.bw = peer->nss.nss_stats->rxrate.bw; -+ sinfo->rxrate.he_gi = peer->nss.nss_stats->rxrate.he_gi; -+ sinfo->rxrate.he_dcm = peer->nss.nss_stats->rxrate.he_dcm; -+ sinfo->rxrate.he_ru_alloc = peer->nss.nss_stats->rxrate.he_ru_alloc; -+ } -+ sinfo->rxrate.flags = peer->nss.nss_stats->rxrate.flags; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); -+ } -+ -+ if (!sinfo->pertid && cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) -+ goto exit; -+ -+ for (tid_idx = 0; tid_idx < NSS_TX_TID_MAX; tid_idx++) { -+ sinfo->pertid[tid_idx].tx_msdu = peer->nss.nss_stats->tx_tid_msdu[tid_idx]; -+ sinfo->pertid[tid_idx].filled |= BIT_ULL(NL80211_TID_STATS_TX_MSDU); -+ } -+ -+ for (tid_idx = 0; tid_idx < IEEE80211_NUM_TIDS; tid_idx++) { -+ sinfo->pertid[tid_idx].rx_msdu = peer->nss.nss_stats->rx_tid_msdu[tid_idx]; -+ sinfo->pertid[tid_idx].filled |= BIT_ULL(NL80211_TID_STATS_RX_MSDU); -+ } -+ -+exit: -+ spin_unlock_bh(&ab->base_lock); -+} -+ -+void ath11k_nss_update_sta_rxrate(struct hal_rx_mon_ppdu_info *ppdu_info, -+ struct ath11k_peer *peer) -+{ -+ struct ath11k_sta *arsta = (struct ath11k_sta *)peer->sta->drv_priv; -+ u16 ath11k_hal_rx_legacy_rates[] = -+ { 10, 20, 55, 60, 90, 110, 120, 180, 240, 360, 480, 540 }; -+ u16 rate = 0; -+ u16 num_msdu; -+ struct ath11k *ar = arsta->arvif->ar; -+ struct ath11k_base *ab = ar->ab; -+ -+ if (!ab->nss.enabled) -+ return; -+ -+ if (!peer->nss.nss_stats) -+ return; -+ -+ if ((ppdu_info->preamble_type == WMI_RATE_PREAMBLE_CCK || -+ ppdu_info->preamble_type == WMI_RATE_PREAMBLE_OFDM) && -+ (ppdu_info->rate < ATH11K_LEGACY_NUM)) { -+ rate = ath11k_hal_rx_legacy_rates[ppdu_info->rate]; -+ } -+ -+ memset(&peer->nss.nss_stats->rxrate, 0, sizeof(peer->nss.nss_stats->rxrate)); -+ -+ switch (ppdu_info->preamble_type) { -+ case WMI_RATE_PREAMBLE_OFDM: -+ peer->nss.nss_stats->rxrate.legacy = rate; -+ break; -+ case WMI_RATE_PREAMBLE_CCK: -+ peer->nss.nss_stats->rxrate.legacy = rate; -+ break; -+ case WMI_RATE_PREAMBLE_HT: -+ peer->nss.nss_stats->rxrate.mcs = ppdu_info->mcs + 8 * (ppdu_info->nss - 1); -+ peer->nss.nss_stats->rxrate.flags = RATE_INFO_FLAGS_MCS; -+ if (ppdu_info->gi) -+ peer->nss.nss_stats->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; -+ break; -+ case WMI_RATE_PREAMBLE_VHT: -+ peer->nss.nss_stats->rxrate.mcs = ppdu_info->mcs; -+ peer->nss.nss_stats->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS; -+ if (ppdu_info->gi) -+ peer->nss.nss_stats->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; -+ break; -+ case WMI_RATE_PREAMBLE_HE: -+ peer->nss.nss_stats->rxrate.mcs = ppdu_info->mcs; -+ peer->nss.nss_stats->rxrate.flags = RATE_INFO_FLAGS_HE_MCS; -+ peer->nss.nss_stats->rxrate.he_dcm = ppdu_info->dcm; -+// peer->nss.nss_stats->rxrate.he_gi = ath11k_he_gi_to_nl80211_he_gi(ppdu_info->gi); -+ peer->nss.nss_stats->rxrate.he_ru_alloc = ppdu_info->ru_alloc; -+ break; -+ } -+ -+ peer->nss.nss_stats->rxrate.nss = ppdu_info->nss; -+ peer->nss.nss_stats->rxrate.bw = ath11k_mac_bw_to_mac80211_bw(ppdu_info->bw); -+ -+ num_msdu = ppdu_info->tcp_msdu_count + ppdu_info->tcp_ack_msdu_count + -+ ppdu_info->udp_msdu_count + ppdu_info->other_msdu_count; -+ if (ppdu_info->tid <= IEEE80211_NUM_TIDS) -+ peer->nss.nss_stats->rx_tid_msdu[ppdu_info->tid] += num_msdu; -+} -+ -+int ath11k_nss_peer_delete(struct ath11k_base *ab, u8 *addr) -+{ -+ struct nss_wifili_peer_msg *peer_msg; -+ struct nss_wifili_msg *wlmsg = NULL; -+ struct ath11k_peer *peer; -+ nss_wifili_msg_callback_t msg_cb; -+ nss_tx_status_t status; -+ int ret; -+ -+ if (!ab->nss.enabled) -+ return 0; -+ -+ spin_lock_bh(&ab->base_lock); -+ -+ peer = ath11k_peer_find_by_addr(ab, addr); -+ if (!peer) { -+ ath11k_warn(ab, "peer not found for nss peer delete\n"); -+ spin_unlock_bh(&ab->base_lock); -+ return -EINVAL; -+ } -+ -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) { -+ ath11k_warn(ab, "nss send peer delete msg alloc failure\n"); -+ ret = -ENOMEM; -+ goto free_peer; -+ } -+ -+ peer_msg = &wlmsg->msg.peermsg; -+ -+ peer_msg->vdev_id = peer->vdev_id; -+ peer_msg->peer_id = peer->peer_id; -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num, -+ NSS_WIFILI_PEER_DELETE_MSG, -+ sizeof(struct nss_wifili_peer_msg), -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "nss send peer delete msg tx error %d\n", status); -+ ret = -EINVAL; -+ kfree(wlmsg); -+ goto free_peer; -+ } else { -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "nss peer delete message success : peer_id %d\n", -+ peer->peer_id); -+ ret = 0; -+ } -+ -+ kfree(wlmsg); -+ if (peer->nss.nss_stats) { -+ kfree(peer->nss.nss_stats); -+ peer->nss.nss_stats = NULL; -+ } -+ -+ spin_unlock_bh(&ab->base_lock); -+ -+ return ret; -+ -+free_peer: -+ dma_unmap_single(ab->dev, peer->nss.paddr, -+ WIFILI_NSS_PEER_BYTE_SIZE, DMA_TO_DEVICE); -+ kfree(peer->nss.vaddr); -+ if (peer->nss.nss_stats) { -+ kfree(peer->nss.nss_stats); -+ peer->nss.nss_stats = NULL; -+ } -+ spin_unlock_bh(&ab->base_lock); -+ return ret; -+} -+ -+int ath11k_nss_peer_create(struct ath11k_base *ab, struct ath11k_peer *peer) -+{ -+ struct nss_wifili_peer_msg *peer_msg; -+ struct nss_wifili_msg *wlmsg = NULL; -+ nss_wifili_msg_callback_t msg_cb; -+ nss_tx_status_t status; -+ int ret; -+ -+ if (!ab->nss.enabled) -+ return 0; -+ -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) -+ return -ENOMEM; -+ -+ peer_msg = &wlmsg->msg.peermsg; -+ -+ peer_msg->vdev_id = peer->vdev_id; -+ peer_msg->peer_id = peer->peer_id; -+ peer_msg->hw_ast_idx = peer->hw_peer_id; -+ peer_msg->tx_ast_hash = peer->ast_hash; -+ ether_addr_copy(peer_msg->peer_mac_addr, peer->addr); -+ -+ peer->nss.vaddr = kzalloc(WIFILI_NSS_PEER_BYTE_SIZE, GFP_ATOMIC); -+ -+ if (!peer->nss.vaddr) { -+ ath11k_warn(ab, "failed to allocate memory for nss peer info\n"); -+ kfree(wlmsg); -+ return -ENOMEM; -+ } -+ -+ peer->nss.paddr = dma_map_single(ab->dev, peer->nss.vaddr, -+ WIFILI_NSS_PEER_BYTE_SIZE, DMA_TO_DEVICE); -+ -+ ret = dma_mapping_error(ab->dev, peer->nss.paddr); -+ if (ret) { -+ ath11k_warn(ab, "error during nss peer info memalloc\n"); -+ kfree(peer->nss.vaddr); -+ ret = -ENOMEM; -+ goto msg_free; -+ } -+ -+ peer_msg->nss_peer_mem = peer->nss.paddr; -+ peer_msg->psta_vdev_id = peer->vdev_id; -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num, -+ NSS_WIFILI_PEER_CREATE_MSG, -+ sizeof(struct nss_wifili_peer_msg), -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg); -+ if (status != NSS_TX_SUCCESS) { -+ ret = -EINVAL; -+ ath11k_warn(ab, "nss send peer create msg tx error\n"); -+ goto peer_mem_free; -+ } -+ -+ ret = 0; -+ ath11k_dbg(ab, ATH11K_DBG_NSS, -+ "nss peer_create msg success mac:%pM vdev:%d peer_id:%d hw_ast_idx:%d ast_hash:%d\n", -+ peer_msg->peer_mac_addr, peer_msg->vdev_id, peer_msg->peer_id, -+ peer_msg->hw_ast_idx, peer_msg->tx_ast_hash); -+ -+ peer->nss.nss_stats = kzalloc(sizeof(*peer->nss.nss_stats), GFP_ATOMIC); -+ if (!peer->nss.nss_stats) -+ ath11k_warn(ab, "Unable to create nss stats memory\n"); -+ -+ goto msg_free; -+ -+peer_mem_free: -+ dma_unmap_single(ab->dev, peer->nss.paddr, -+ WIFILI_NSS_PEER_BYTE_SIZE, DMA_TO_DEVICE); -+ kfree(peer->nss.vaddr); -+msg_free: -+ kfree(wlmsg); -+ return ret; -+} -+ -+/*-------------------------------INIT/DEINIT---------------------------------*/ -+ -+static int ath11k_nss_radio_buf_cfg(struct ath11k *ar, int range, int buf_sz) -+{ -+ struct nss_wifili_radio_buf_cfg_msg *buf_cfg; -+ struct nss_wifili_radio_cfg_msg *radio_buf_cfg_msg; -+ struct nss_wifili_msg *wlmsg = NULL; -+ nss_tx_status_t status; -+ int ret = 0; -+ -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) -+ return -ENOMEM; -+ -+ radio_buf_cfg_msg = &wlmsg->msg.radiocfgmsg; -+ -+ radio_buf_cfg_msg->radio_if_num = ar->nss.if_num; -+ buf_cfg = &wlmsg->msg.radiocfgmsg.radiomsg.radiobufcfgmsg; -+ buf_cfg->range = range; -+ buf_cfg->buf_cnt = buf_sz; -+ -+ nss_cmn_msg_init(&wlmsg->cm, ar->ab->nss.if_num, -+ NSS_WIFILI_RADIO_BUF_CFG, -+ sizeof(struct nss_wifili_radio_buf_cfg_msg), -+ NULL, NULL); -+ -+ status = nss_wifili_tx_msg(ar->nss.ctx, wlmsg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ar->ab, "nss radio buf cfg send failed %d\n", status); -+ ret = -EINVAL; -+ } else { -+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS, -+ "nss radio cfg message range:%d buf_sz:%d if_num:%d ctx:%p\n", -+ range, buf_sz, ar->nss.if_num, ar->nss.ctx); -+ } -+ -+ kfree(wlmsg); -+ return ret; -+} -+ -+static void ath11k_nss_fill_srng_info(struct ath11k_base *ab, int ring_id, -+ struct nss_wifili_hal_srng_info *hsi) -+{ -+ struct ath11k_hal *hal = &ab->hal; -+ struct hal_srng *srng; -+ u32 offset; -+ int i; -+ -+ if (ring_id < 0) { -+ ath11k_warn(ab, "Invalid ring id used for nss init\n"); -+ WARN_ON(1); -+ return; -+ } -+ -+ srng = &hal->srng_list[ring_id]; -+ -+ hsi->ring_id = srng->ring_id; -+ hsi->ring_dir = srng->ring_dir; -+ hsi->ring_base_paddr = srng->ring_base_paddr; -+ hsi->entry_size = srng->entry_size; -+ hsi->num_entries = srng->num_entries; -+ hsi->flags = srng->flags; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, -+ "Ring info to send to nss - ring_id:%d ring_dir:%d ring_paddr:%d entry_size:%d num_entries:%d flags:%d\n", -+ hsi->ring_id, hsi->ring_dir, hsi->ring_base_paddr, -+ hsi->entry_size, hsi->num_entries, hsi->flags); -+ -+ for (i = 0; i < HAL_SRNG_NUM_REG_GRP; i++) { -+ offset = srng->hwreg_base[i]; -+ -+ /* For PCI based devices, get the umac ring base address offset -+ * based on window register configuration. -+ */ -+ if (!(srng->flags & HAL_SRNG_FLAGS_LMAC_RING)) -+ offset = ath11k_hif_get_window_offset(ab, srng->hwreg_base[i]); -+ -+ hsi->hwreg_base[i] = (u32)ab->mem_pa + offset; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "SRNG Register %d address %d\n", -+ i, hsi->hwreg_base[i]); -+ } -+} -+ -+static void ath11k_nss_tx_desc_mem_free(struct ath11k_base *ab) -+{ -+ int i; -+ -+ for (i = 0; i < ATH11K_NSS_MAX_NUMBER_OF_PAGE; i++) { -+ if (!ab->nss.tx_desc_paddr[i]) -+ continue; -+ -+ dma_free_coherent(ab->dev, -+ ab->nss.tx_desc_size[i], -+ ab->nss.tx_desc_vaddr[i], -+ ab->nss.tx_desc_paddr[i]); -+ ab->nss.tx_desc_vaddr[i] = NULL; -+ } -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "allocated tx desc mem freed\n"); -+} -+ -+static int ath11k_nss_tx_desc_mem_alloc(struct ath11k_base *ab, u32 required_size, u32 *page_idx) -+{ -+ int i, alloc_size; -+ int curr_page_idx; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "tx desc mem alloc size: %d\n", required_size); -+ -+ curr_page_idx = *page_idx; -+ -+ for (i = 0, alloc_size = 0; i < required_size; i += alloc_size) { -+ alloc_size = required_size - i; -+ -+ if (alloc_size > WIFILI_NSS_MAX_MEM_PAGE_SIZE) -+ alloc_size = WIFILI_NSS_MAX_MEM_PAGE_SIZE; -+ -+ ab->nss.tx_desc_vaddr[curr_page_idx] = -+ dma_alloc_coherent(ab->dev, alloc_size, -+ &ab->nss.tx_desc_paddr[curr_page_idx], -+ GFP_KERNEL); -+ -+ if (!ab->nss.tx_desc_vaddr[curr_page_idx]) -+ return -ENOMEM; -+ -+ ab->nss.tx_desc_size[curr_page_idx] = alloc_size; -+ curr_page_idx++; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, -+ "curr page %d, allocated %d, total allocated %d\n", -+ curr_page_idx, alloc_size, i + alloc_size); -+ -+ if (curr_page_idx == ATH11K_NSS_MAX_NUMBER_OF_PAGE) { -+ ath11k_warn(ab, "max page number reached while tx desc mem allocation\n"); -+ return -EINVAL; -+ } -+ } -+ *page_idx = curr_page_idx; -+ return 0; -+} -+ -+static int ath11k_nss_fill_tx_desc_info(struct ath11k_base *ab, -+ struct nss_wifili_init_msg *wim) -+{ -+ struct nss_wifili_tx_desc_addtnl_mem_msg *dam; -+ u32 required_size, required_size_ext; -+ struct nss_wifili_tx_desc_init_msg *dim; -+ u32 tx_desc_limit_0 = 0; -+ u32 tx_desc_limit_1 = 0; -+ u32 tx_desc_limit_2 = 0; -+ u32 dam_page_idx = 0; -+ int page_idx = 0; -+ int i; -+ -+ wim->tx_sw_internode_queue_size = ATH11K_WIFIILI_MAX_TX_PROCESSQ; -+ -+ dim = &wim->wtdim; -+ dam = &wim->wtdam; -+ -+ dim->num_pool = ab->num_radios; -+ dim->num_tx_device_limit = ATH11K_WIFILI_MAX_TX_DESC; -+ -+ //TODO Revisit below calc based on platform/mem cfg -+ switch (dim->num_pool) { -+ case 1: -+ tx_desc_limit_0 = ATH11K_WIFILI_DBDC_NUM_TX_DESC; -+ break; -+ case 2: -+ tx_desc_limit_0 = ATH11K_WIFILI_DBDC_NUM_TX_DESC; -+ tx_desc_limit_1 = ATH11K_WIFILI_DBDC_NUM_TX_DESC; -+ break; -+ case 3: -+ tx_desc_limit_0 = ATH11K_WIFILI_DBTC_NUM_TX_DESC; -+ tx_desc_limit_1 = ATH11K_WIFILI_DBTC_NUM_TX_DESC; -+ tx_desc_limit_2 = ATH11K_WIFILI_DBTC_NUM_TX_DESC; -+ break; -+ default: -+ ath11k_warn(ab, "unexpected num radios during tx desc alloc\n"); -+ return -EINVAL; -+ } -+ -+ dim->num_tx_desc = tx_desc_limit_0; -+ dim->num_tx_desc_ext = tx_desc_limit_0; -+ dim->num_tx_desc_2 = tx_desc_limit_1; -+ dim->num_tx_desc_ext_2 = tx_desc_limit_1; -+ dim->num_tx_desc_3 = tx_desc_limit_2; -+ dim->num_tx_desc_ext_3 = tx_desc_limit_2; -+ -+ required_size = (dim->num_tx_desc + dim->num_tx_desc_2 + -+ dim->num_tx_desc_3 + -+ dim->num_pool) * WIFILI_NSS_TX_DESC_SIZE; -+ -+ required_size_ext = (dim->num_tx_desc_ext + dim->num_tx_desc_ext_2 + -+ dim->num_tx_desc_ext_3 + -+ dim->num_pool) * WIFILI_NSS_TX_EXT_DESC_SIZE; -+ -+ if (ath11k_nss_tx_desc_mem_alloc(ab, required_size, &page_idx)) { -+ ath11k_warn(ab, "memory allocation for tx desc of size %d failed\n", -+ required_size); -+ return -ENOMEM; -+ } -+ -+ /* Fill the page number from where extension tx descriptor is available */ -+ dim->ext_desc_page_num = page_idx; -+ -+ if (ath11k_nss_tx_desc_mem_alloc(ab, required_size_ext, &page_idx)) { -+ ath11k_warn(ab, "memory allocation for extension tx desc of size %d failed\n", -+ required_size_ext); -+ return -ENOMEM; -+ } -+ -+ for (i = 0; i < page_idx; i++) { -+ if (i < NSS_WIFILI_MAX_NUMBER_OF_PAGE_MSG) { -+ dim->memory_addr[i] = (u32)ab->nss.tx_desc_paddr[i]; -+ dim->memory_size[i] = (u32)ab->nss.tx_desc_size[i]; -+ dim->num_memaddr++; -+ } else { -+ dam_page_idx = i - NSS_WIFILI_MAX_NUMBER_OF_PAGE_MSG; -+ dam->addtnl_memory_addr[dam_page_idx] = (u32)ab->nss.tx_desc_paddr[i]; -+ dam->addtnl_memory_size[dam_page_idx] = (u32)ab->nss.tx_desc_size[i]; -+ dam->num_addtnl_addr++; -+ } -+ } -+ -+ if (i > NSS_WIFILI_MAX_NUMBER_OF_PAGE_MSG) -+ wim->flags |= WIFILI_ADDTL_MEM_SEG_SET; -+ -+ return 0; -+} -+ -+static int ath11k_nss_get_target_type(struct ath11k_base *ab) -+{ -+ switch (ab->hw_rev) { -+ case ATH11K_HW_IPQ8074: -+ return ATH11K_WIFILI_TARGET_TYPE_QCA8074V2; -+/* case ATH11K_HW_IPQ6018_HW10: -+ * return ATH11K_WIFILI_TARGET_TYPE_QCA6018; -+ * case ATH11K_HW_QCN9074_HW10: -+ * return ATH11K_WIFILI_TARGET_TYPE_QCN9074; -+ * case ATH11K_HW_IPQ5018: -+ */ return ATH11K_WIFILI_TARGET_TYPE_QCA5018; -+ default: -+ ath11k_warn(ab, "NSS Offload not supported for this HW\n"); -+ return ATH11K_WIFILI_TARGET_TYPE_UNKNOWN; -+ } -+} -+ -+static int ath11k_nss_get_interface_type(struct ath11k_base *ab) -+{ -+ switch (ab->hw_rev) { -+ case ATH11K_HW_IPQ8074: -+ case ATH11K_HW_IPQ6018_HW10: -+// case ATH11K_HW_IPQ5018: -+ return NSS_WIFILI_INTERNAL_INTERFACE; -+// case ATH11K_HW_QCN9074_HW10: -+// return nss_get_available_wifili_external_if(); -+ default: -+ /* This can't happen since we validated target type earlier */ -+ WARN_ON(1); -+ return NSS_MAX_NET_INTERFACES; -+ } -+} -+ -+static int ath11k_nss_get_dynamic_interface_type(struct ath11k_base *ab) -+{ -+ switch (ab->nss.if_num) { -+ case NSS_WIFILI_INTERNAL_INTERFACE: -+ return NSS_DYNAMIC_INTERFACE_TYPE_WIFILI_INTERNAL; -+ case NSS_WIFILI_EXTERNAL_INTERFACE0: -+ return NSS_DYNAMIC_INTERFACE_TYPE_WIFILI_EXTERNAL0; -+ case NSS_WIFILI_EXTERNAL_INTERFACE1: -+ return NSS_DYNAMIC_INTERFACE_TYPE_WIFILI_EXTERNAL1; -+ default: -+ ath11k_warn(ab, "NSS Offload invalid interface\n"); -+ return NSS_DYNAMIC_INTERFACE_TYPE_NONE; -+ } -+} -+ -+static int ath11k_nss_init(struct ath11k_base *ab) -+{ -+ struct nss_wifili_init_msg *wim = NULL; -+ struct nss_wifili_msg *wlmsg = NULL; -+ struct nss_ctx_instance *nss_contex; -+ nss_wifili_msg_callback_t msg_cb; -+ u32 target_type; -+ u32 features = 0; -+ nss_tx_status_t status; -+ struct ath11k_dp *dp; -+ int i, ret; -+ -+ dp = &ab->dp; -+ -+ target_type = ath11k_nss_get_target_type(ab); -+ -+ if (target_type == ATH11K_WIFILI_TARGET_TYPE_UNKNOWN) -+ return -ENOTSUPP; -+ -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) -+ return -ENOMEM; -+ -+ wim = &wlmsg->msg.init; -+ -+ wim->target_type = target_type; -+ -+ /* fill rx parameters to initialize rx context */ -+ wim->wrip.tlv_size = sizeof(struct hal_rx_desc); -+ wim->wrip.rx_buf_len = DP_RX_BUFFER_SIZE; -+ -+ /* fill hal srng message */ -+ wim->hssm.dev_base_addr = (u32)ab->mem_pa; -+ wim->hssm.shadow_rdptr_mem_addr = (u32)ab->hal.rdp.paddr; -+ wim->hssm.shadow_wrptr_mem_addr = (u32)ab->hal.wrp.paddr; -+ -+ /* fill TCL data/completion ring info */ -+ wim->num_tcl_data_rings = DP_TCL_NUM_RING_MAX; -+ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) { -+ ath11k_nss_fill_srng_info(ab, dp->tx_ring[i].tcl_data_ring.ring_id, -+ &wim->tcl_ring_info[i]); -+ ath11k_nss_fill_srng_info(ab, dp->tx_ring[i].tcl_comp_ring.ring_id, -+ &wim->tx_comp_ring[i]); -+ } -+ -+ /* allocate tx desc memory for NSS and fill corresponding info */ -+ ret = ath11k_nss_fill_tx_desc_info(ab, wim); -+ if (ret) -+ goto free; -+ -+ /* fill reo dest ring info */ -+ wim->num_reo_dest_rings = DP_REO_DST_RING_MAX; -+ for (i = 0; i < DP_REO_DST_RING_MAX; i++) { -+ ath11k_nss_fill_srng_info(ab, dp->reo_dst_ring[i].ring_id, -+ &wim->reo_dest_ring[i]); -+ } -+ -+ /* fill reo reinject ring info */ -+ ath11k_nss_fill_srng_info(ab, dp->reo_reinject_ring.ring_id, -+ &wim->reo_reinject_ring); -+ -+ /* fill reo release ring info */ -+ ath11k_nss_fill_srng_info(ab, dp->rx_rel_ring.ring_id, -+ &wim->rx_rel_ring); -+ -+ /* fill reo exception ring info */ -+ ath11k_nss_fill_srng_info(ab, dp->reo_except_ring.ring_id, -+ &wim->reo_exception_ring); -+ -+ wim->flags |= WIFILI_NSS_CCE_DISABLED; -+ -+ ab->nss.if_num = ath11k_nss_get_interface_type(ab); -+ -+ ath11k_info(ab, "nss init soc nss if_num %d\n", ab->nss.if_num); -+ -+ if (ab->nss.if_num >= NSS_MAX_NET_INTERFACES) { -+ ath11k_warn(ab, "NSS invalid interface\n"); -+ goto free; -+ } -+ -+ /* register callbacks for events and exceptions with nss */ -+ nss_contex = nss_register_wifili_if(ab->nss.if_num, NULL, -+ (nss_wifili_callback_t)ath11k_nss_wifili_ext_callback_fn, -+ (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive, -+ (struct net_device *)ab, features); -+ -+ if (!nss_contex) { -+ ath11k_warn(ab, "nss wifili register failure\n"); -+ goto free; -+ } -+ -+ if (nss_cmn_get_state(nss_contex) != NSS_STATE_INITIALIZED) { -+ ath11k_warn(ab, "nss state in default init state\n"); -+ goto free; -+ } -+ -+ /* The registered soc context is stored in ab, and will be used for -+ * all soc related messages with nss -+ */ -+ ab->nss.ctx = nss_contex; -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ /* Initialize the common part of the wlmsg */ -+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num, -+ NSS_WIFILI_INIT_MSG, -+ sizeof(struct nss_wifili_init_msg), -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(nss_contex, wlmsg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "failure to send nss init msg\n"); -+ goto unregister; -+ } -+ -+ reinit_completion(&ab->nss.complete); -+ -+ /* Note: response is contention free during init sequence */ -+ ab->nss.response = ATH11K_NSS_MSG_ACK; -+ -+ ret = wait_for_completion_timeout(&ab->nss.complete, -+ msecs_to_jiffies(ATH11K_NSS_MSG_TIMEOUT_MS)); -+ if (!ret) { -+ ath11k_warn(ab, "timeout while waiting for nss init msg response\n"); -+ goto unregister; -+ } -+ -+ /* Check if the response is success from the callback */ -+ if (ab->nss.response != ATH11K_NSS_MSG_ACK) -+ goto unregister; -+ -+ kfree(wlmsg); -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "NSS Init Message TX Success %p %d\n", -+ ab->nss.ctx, ab->nss.if_num); -+ return 0; -+ -+unregister: -+ nss_unregister_wifili_if(ab->nss.if_num); -+free: -+ ath11k_nss_tx_desc_mem_free(ab); -+ kfree(wlmsg); -+ return -EINVAL; -+} -+ -+static int ath11k_nss_stats_cfg(struct ath11k *ar, int nss_msg, int enable) -+{ -+ struct nss_wifili_msg *wlmsg = NULL; -+ struct nss_wifili_stats_cfg_msg *stats_cfg; -+ nss_wifili_msg_callback_t msg_cb; -+ nss_tx_status_t status; -+ struct ath11k_base *ab = ar->ab; -+ int ret = 0; -+ -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) -+ return -ENOMEM; -+ -+ stats_cfg = &wlmsg->msg.scm; -+ stats_cfg->cfg = enable; -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num, -+ nss_msg, -+ sizeof(struct nss_wifili_stats_cfg_msg), -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(ar->nss.ctx, wlmsg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "nss stats cfg %d msg tx failure\n", nss_msg); -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "nss stats %d enable %d\n", nss_msg, enable); -+ -+free: -+ kfree(wlmsg); -+ return ret; -+} -+ -+static void ath11k_nss_stats_disable(struct ath11k *ar) -+{ -+ /*TODO Revisit if this required */ -+ ath11k_nss_stats_cfg(ar, NSS_WIFILI_STATS_CFG_MSG, -+ ATH11K_NSS_STATS_DISABLE); -+ -+ ath11k_nss_stats_cfg(ar, NSS_WIFILI_STATS_V2_CFG_MSG, -+ ATH11K_NSS_STATS_DISABLE); -+} -+ -+static void ath11k_nss_stats_enable(struct ath11k *ar) -+{ -+ /*TODO Revisit if we need to enable both these stats */ -+ ath11k_nss_stats_cfg(ar, NSS_WIFILI_STATS_CFG_MSG, -+ ATH11K_NSS_STATS_ENABLE); -+ -+ ath11k_nss_stats_cfg(ar, NSS_WIFILI_STATS_V2_CFG_MSG, -+ ATH11K_NSS_STATS_ENABLE); -+} -+ -+int ath11k_nss_pdev_init(struct ath11k_base *ab, int radio_id) -+{ -+ struct ath11k *ar = ab->pdevs[radio_id].ar; -+ struct nss_wifili_pdev_init_msg *pdevmsg; -+ struct nss_wifili_msg *wlmsg = NULL; -+ nss_wifili_msg_callback_t msg_cb; -+ nss_tx_status_t status; -+ int radio_if_num = -1; -+ int refill_ring_id; -+ int features = 0; -+ int dyn_if_type; -+ int ret, i; -+ -+ dyn_if_type = ath11k_nss_get_dynamic_interface_type(ab); -+ -+ /* Allocate a node for dynamic interface */ -+ radio_if_num = nss_dynamic_interface_alloc_node(dyn_if_type); -+ -+ if (radio_if_num < 0) -+ return -EINVAL; -+ -+ /* The ifnum and registered radio context is stored in ar and used -+ * for messages related to vdev/radio -+ */ -+ ar->nss.if_num = radio_if_num; -+ -+ /* No callbacks are registered for radio specific events/data */ -+ ar->nss.ctx = nss_register_wifili_radio_if((u32)radio_if_num, NULL, -+ NULL, NULL, (struct net_device *)ar, -+ features); -+ -+ if (!ar->nss.ctx) { -+ ath11k_warn(ab, "failure during nss pdev register\n"); -+ ret = -EINVAL; -+ goto dealloc; -+ } -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "nss pdev init - id:%d init ctxt:%p ifnum:%d\n", -+ ar->pdev->pdev_id, ar->nss.ctx, ar->nss.if_num); -+ -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) { -+ ret = -ENOMEM; -+ goto unregister; -+ } -+ -+ pdevmsg = &wlmsg->msg.pdevmsg; -+ -+ pdevmsg->radio_id = radio_id; -+ pdevmsg->lmac_id = ar->lmac_id; -+ pdevmsg->target_pdev_id = ar->pdev->pdev_id; -+ pdevmsg->num_rx_swdesc = WIFILI_RX_DESC_POOL_WEIGHT * DP_RXDMA_BUF_RING_SIZE; -+ -+ /* Store rxdma ring info to the message */ -+ refill_ring_id = ar->dp.rx_refill_buf_ring.refill_buf_ring.ring_id; -+ ath11k_nss_fill_srng_info(ab, refill_ring_id, &pdevmsg->rxdma_ring); -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num, -+ NSS_WIFILI_PDEV_INIT_MSG, -+ sizeof(struct nss_wifili_pdev_init_msg), -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(ar->nss.ctx, wlmsg); -+ -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "nss send pdev msg tx error : %d\n", status); -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ reinit_completion(&ab->nss.complete); -+ -+ /* Note: response is contention free during init sequence */ -+ ab->nss.response = ATH11K_NSS_MSG_ACK; -+ -+ ret = wait_for_completion_timeout(&ab->nss.complete, -+ msecs_to_jiffies(ATH11K_NSS_MSG_TIMEOUT_MS)); -+ if (!ret) { -+ ath11k_warn(ab, "timeout while waiting for pdev init msg response\n"); -+ ret = -ETIMEDOUT; -+ goto free; -+ } -+ -+ /* Check if the response is success from the callback */ -+ if (ab->nss.response != ATH11K_NSS_MSG_ACK) { -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ kfree(wlmsg); -+ -+ /* Enable nss stats */ -+ ath11k_nss_stats_enable(ar); -+ -+ /*TODO CFG Tx buffer limit as per no clients range per radio -+ * this needs to be based on target/mem cfg -+ * similar to tx desc cfg at soc init per radio -+ */ -+ -+ for (i = 0; i < ATH11K_NSS_RADIO_TX_LIMIT_RANGE; i++) -+ ath11k_nss_radio_buf_cfg(ar, i, ATH11K_NSS_RADIO_TX_LIMIT_RANGE3); -+ -+ return 0; -+ -+free: -+ kfree(wlmsg); -+unregister: -+ nss_unregister_wifili_radio_if(ar->nss.if_num); -+dealloc: -+ nss_dynamic_interface_dealloc_node(ar->nss.if_num, dyn_if_type); -+ return ret; -+} -+ -+/* TODO : Check if start, reset and stop messages can be done using single function as -+ * body is similar, having it now for clarity */ -+ -+int ath11k_nss_start(struct ath11k_base *ab) -+{ -+ struct nss_wifili_msg *wlmsg = NULL; -+ nss_wifili_msg_callback_t msg_cb; -+ nss_tx_status_t status; -+ int ret; -+ -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) -+ return -ENOMEM; -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ /* Empty message for NSS Start message */ -+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num, -+ NSS_WIFILI_START_MSG, -+ 0, -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg); -+ -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "nss send start msg tx error %d\n", status); -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ reinit_completion(&ab->nss.complete); -+ -+ /* Note: response is contention free during init sequence */ -+ ab->nss.response = ATH11K_NSS_MSG_ACK; -+ -+ ret = wait_for_completion_timeout(&ab->nss.complete, -+ msecs_to_jiffies(ATH11K_NSS_MSG_TIMEOUT_MS)); -+ if (!ret) { -+ ath11k_warn(ab, "timeout while waiting for response for nss start msg\n"); -+ ret = -ETIMEDOUT; -+ goto free; -+ } -+ -+ /* Check if the response is success from the callback */ -+ if (ab->nss.response != ATH11K_NSS_MSG_ACK) { -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ /* NSS Start success */ -+ ret = 0; -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "nss start success\n"); -+ -+free: -+ kfree(wlmsg); -+ return ret; -+} -+ -+static void ath11k_nss_reset(struct ath11k_base *ab) -+{ -+ struct nss_wifili_msg *wlmsg = NULL; -+ nss_wifili_msg_callback_t msg_cb; -+ nss_tx_status_t status; -+ int ret; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "NSS reset\n"); -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) { -+ ath11k_warn(ab, "mem allocation failure during nss reset\n"); -+ return; -+ } -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ /* Empty message for NSS Reset message */ -+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num, -+ NSS_WIFILI_SOC_RESET_MSG, -+ 0, -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg); -+ -+ /* Add a retry mechanism to reset nss until success */ -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "nss send reset msg tx error %d\n", status); -+ goto free; -+ } -+ -+ reinit_completion(&ab->nss.complete); -+ -+ /* Note: response is contention free during deinit sequence */ -+ ab->nss.response = ATH11K_NSS_MSG_ACK; -+ -+ ret = wait_for_completion_timeout(&ab->nss.complete, -+ msecs_to_jiffies(ATH11K_NSS_MSG_TIMEOUT_MS)); -+ if (!ret) { -+ ath11k_warn(ab, "timeout while waiting for response for nss reset msg\n"); -+ goto free; -+ } -+ -+ /* Check if the response is success from the callback */ -+ if (ab->nss.response != ATH11K_NSS_MSG_ACK) { -+ ath11k_warn(ab, "failure response during nss reset %d\n", ab->nss.response); -+ goto free; -+ } -+ -+ /* Unregister wifili interface */ -+ nss_unregister_wifili_if(ab->nss.if_num); -+ -+free: -+ kfree(wlmsg); -+} -+ -+static int ath11k_nss_stop(struct ath11k_base *ab) -+{ -+ struct nss_wifili_msg *wlmsg = NULL; -+ nss_wifili_msg_callback_t msg_cb; -+ nss_tx_status_t status; -+ int ret; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "NSS stop\n"); -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) -+ return -ENOMEM; -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ /* Empty message for Stop command */ -+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num, -+ NSS_WIFILI_STOP_MSG, -+ 0, -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg); -+ -+ /* Add a retry mechanism to stop nss until success */ -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "nss send stop msg tx error %d\n", status); -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ reinit_completion(&ab->nss.complete); -+ -+ /* Note: response is contention free during deinit sequence */ -+ ab->nss.response = ATH11K_NSS_MSG_ACK; -+ -+ ret = wait_for_completion_timeout(&ab->nss.complete, -+ msecs_to_jiffies(ATH11K_NSS_MSG_TIMEOUT_MS)); -+ if (!ret) { -+ ath11k_warn(ab, "timeout while waiting for response for nss stop msg\n"); -+ ret = -ETIMEDOUT; -+ goto free; -+ } -+ -+ /* Check if the response is success from the callback */ -+ if (ab->nss.response != ATH11K_NSS_MSG_ACK) { -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ /* NSS Stop success */ -+ ret = 0; -+free: -+ kfree(wlmsg); -+ return ret; -+} -+ -+int ath11k_nss_pdev_deinit(struct ath11k_base *ab, int radio_id) -+{ -+ struct ath11k *ar = ab->pdevs[radio_id].ar; -+ struct nss_wifili_pdev_deinit_msg *deinit; -+ struct nss_wifili_msg *wlmsg = NULL; -+ nss_wifili_msg_callback_t msg_cb; -+ nss_tx_status_t status; -+ int dyn_if_type; -+ int ret; -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "NSS pdev %d deinit\n", radio_id); -+ dyn_if_type = ath11k_nss_get_dynamic_interface_type(ab); -+ -+ /* Disable stats before teardown */ -+ ath11k_nss_stats_disable(ar); -+ -+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); -+ if (!wlmsg) -+ return -ENOMEM; -+ -+ deinit = &wlmsg->msg.pdevdeinit; -+ deinit->ifnum = radio_id; -+ -+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -+ -+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num, -+ NSS_WIFILI_PDEV_DEINIT_MSG, -+ sizeof(struct nss_wifili_pdev_deinit_msg), -+ msg_cb, NULL); -+ -+ status = nss_wifili_tx_msg(ar->nss.ctx, wlmsg); -+ if (status != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "nss send pdev deinit msg tx error %d\n", status); -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ reinit_completion(&ab->nss.complete); -+ -+ /* Note: response is contention free during deinit sequence */ -+ ab->nss.response = ATH11K_NSS_MSG_ACK; -+ -+ ret = wait_for_completion_timeout(&ab->nss.complete, -+ msecs_to_jiffies(ATH11K_NSS_MSG_TIMEOUT_MS)); -+ if (!ret) { -+ ath11k_warn(ab, "timeout while waiting for pdev deinit msg response\n"); -+ ret = -ETIMEDOUT; -+ goto free; -+ } -+ -+ /* Check if the response is success from the callback */ -+ if (ab->nss.response != ATH11K_NSS_MSG_ACK) { -+ ret = -EINVAL; -+ goto free; -+ } -+ -+ /* pdev deinit msg success, dealloc, deregister and return */ -+ ret = 0; -+ -+ nss_dynamic_interface_dealloc_node(ar->nss.if_num, dyn_if_type); -+ nss_unregister_wifili_radio_if(ar->nss.if_num); -+free: -+ kfree(wlmsg); -+ return ret; -+} -+ -+int ath11k_nss_teardown(struct ath11k_base *ab) -+{ -+ int i, ret; -+ -+ if (!ab->nss.enabled) -+ return 0; -+ -+ ath11k_nss_stop(ab); -+ -+ for (i = 0; i < ab->num_radios ; i++) { -+ ret = ath11k_nss_pdev_deinit(ab, i); -+ if (ret) -+ ath11k_warn(ab, "failure during pdev%d deinit\n", i); -+ } -+ -+ ath11k_nss_reset(ab); -+ ath11k_nss_tx_desc_mem_free(ab); -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "NSS Teardown Complete\n"); -+ -+ return 0; -+} -+ -+int ath11k_nss_setup(struct ath11k_base *ab) -+{ -+ int i; -+ int ret = 0; -+ u32 target_type; -+ -+ if (!ab->nss.enabled) -+ return 0; -+ -+ target_type = ath11k_nss_get_target_type(ab); -+ -+ if (target_type == ATH11K_WIFILI_TARGET_TYPE_UNKNOWN) -+ return -ENOTSUPP; -+ -+ /* Verify NSS support is enabled */ -+ if (nss_cmn_get_nss_enabled() == false) { -+ ath11k_warn(ab, "NSS offload support disabled, falling back to default mode\n"); -+ return -ENOTSUPP; -+ } -+ -+ /* Initialize completion for verifying NSS message response */ -+ init_completion(&ab->nss.complete); -+ -+ /* Setup common resources for NSS */ -+ ret = ath11k_nss_init(ab); -+ if (ret) { -+ ath11k_warn(ab, "NSS SOC Initialization Failed :%d\n", ret); -+ goto fail; -+ } -+ -+ /* Setup pdev related resources for NSS */ -+ for (i = 0; i < ab->num_radios; i++) { -+ ret = ath11k_nss_pdev_init(ab, i); -+ if (ret) { -+ ath11k_warn(ab, "NSS PDEV %d Initialization Failed :%d\n", i, ret); -+ goto pdev_deinit; -+ } -+ } -+ -+ /* Set the NSS statemachine to start */ -+ ret = ath11k_nss_start(ab); -+ if (ret) { -+ ath11k_warn(ab, "NSS Start Failed : %d\n", ret); -+ goto pdev_deinit; -+ } -+ -+ /* Default nexthop interface is set to ETH RX */ -+ ret = nss_wifi_vdev_base_set_next_hop(ab->nss.ctx, NSS_ETH_RX_INTERFACE); -+ if (ret != NSS_TX_SUCCESS) { -+ ath11k_warn(ab, "Failure to set default next hop : %d\n", ret); -+ goto stop; -+ } -+ -+ ath11k_dbg(ab, ATH11K_DBG_NSS, "NSS Setup Complete\n"); -+ return ret; -+ -+stop: -+ ath11k_nss_stop(ab); -+ -+pdev_deinit: -+ for (i -= 1; i >= 0; i--) -+ ath11k_nss_pdev_deinit(ab, i); -+ -+ ath11k_nss_reset(ab); -+ ath11k_nss_tx_desc_mem_free(ab); -+fail: -+ return ret; -+} ---- /dev/null -+++ b/drivers/net/wireless/ath/ath11k/nss.h -@@ -0,0 +1,267 @@ -+/* SPDX-License-Identifier: BSD-3-Clause-Clear */ -+/* -+ * Copyright (c) 2020 The Linux Foundation. All rights reserved. -+ */ -+ -+#ifndef ATH11K_NSS_H -+#define ATH11K_NSS_H -+ -+#include -+#include -+ -+struct ath11k; -+struct ath11k_base; -+struct ath11k_vif; -+struct ath11k_peer; -+struct ath11k_sta; -+struct hal_rx_mon_ppdu_info; -+ -+/* NSS DBG macro is not included as part of debug enum to avoid -+ * frequent changes during upgrade*/ -+#define ATH11K_DBG_NSS 0x80000000 -+ -+/* WIFILI Supported Target Types */ -+#define ATH11K_WIFILI_TARGET_TYPE_UNKNOWN 0xFF -+#define ATH11K_WIFILI_TARGET_TYPE_QCA8074 20 -+#define ATH11K_WIFILI_TARGET_TYPE_QCA8074V2 24 -+#define ATH11K_WIFILI_TARGET_TYPE_QCA6018 25 -+#define ATH11K_WIFILI_TARGET_TYPE_QCN9074 26 -+#define ATH11K_WIFILI_TARGET_TYPE_QCA5018 29 -+ -+/* Max limit for NSS Queue */ -+#define ATH11K_WIFIILI_MAX_TX_PROCESSQ 1024 -+ -+/* Max TX Desc limit */ -+#define ATH11K_WIFILI_MAX_TX_DESC 65536 -+ -+/* TX Desc related info */ -+/*TODO : Check this again during experiments for lowmem or -+ changes for platforms based on num radios supported */ -+#define ATH11K_WIFILI_DBDC_NUM_TX_DESC (1024 * 8) -+#define ATH11K_WIFILI_DBTC_NUM_TX_DESC (1024 * 8) -+ -+// TODO Revisit these page size calc -+#define WIFILI_NSS_TX_DESC_SIZE 20*4 -+#define WIFILI_NSS_TX_EXT_DESC_SIZE 40*4 -+/* Number of desc per page(12bit) should be<4096, page limit per 1024 byte is 80*3=240 */ -+#define WIFILI_NSS_TX_DESC_PAGE_LIMIT 240 -+#define WIFILI_NSS_MAX_MEM_PAGE_SIZE (WIFILI_NSS_TX_DESC_PAGE_LIMIT * 1024) -+#define WIFILI_NSS_MAX_EXT_MEM_PAGE_SIZE (WIFILI_NSS_TX_DESC_PAGE_LIMIT * 1024) -+#define WIFILI_RX_DESC_POOL_WEIGHT 3 -+ -+/* Status of the NSS messages sent from driver */ -+#define ATH11K_NSS_MSG_ACK 0 -+/* Timeout for waiting for response from NSS on TX msg */ -+#define ATH11K_NSS_MSG_TIMEOUT_MS 5000 -+ -+/* Init Flags */ -+#define WIFILI_NSS_CCE_DISABLED 0x1 -+#define WIFILI_ADDTL_MEM_SEG_SET 0x000000002 -+ -+/* ATH11K NSS PEER Info */ -+/* Host memory allocated for peer info storage in nss */ -+#define WIFILI_NSS_PEER_BYTE_SIZE 1152 -+ -+/* ATH11K NSS Stats */ -+#define ATH11K_NSS_STATS_ENABLE 1 -+#define ATH11K_NSS_STATS_DISABLE 0 -+ -+/* TX Buf cfg range */ -+#define ATH11K_NSS_RADIO_TX_LIMIT_RANGE 4 -+ -+/* TODO : Analysis based on platform */ -+/* TX Limit till 64 clients */ -+#define ATH11K_NSS_RADIO_TX_LIMIT_RANGE0 8192 -+/* TX Limit till 128 clients */ -+#define ATH11K_NSS_RADIO_TX_LIMIT_RANGE1 8192 -+/* TX Limit till 256 clients */ -+#define ATH11K_NSS_RADIO_TX_LIMIT_RANGE2 8192 -+/* TX Limit > 256 clients */ -+#define ATH11K_NSS_RADIO_TX_LIMIT_RANGE3 8192 -+ -+#define ATH11K_NSS_MAX_NUMBER_OF_PAGE 96 -+ -+#define NSS_TX_TID_MAX 8 -+ -+enum ath11k_nss_opmode { -+ ATH11K_NSS_OPMODE_UNKNOWN, -+ ATH11K_NSS_OPMODE_AP, -+ ATH11K_NSS_OPMODE_IBSS, -+ ATH11K_NSS_OPMODE_STA, -+ ATH11K_NSS_OPMODE_MONITOR, -+}; -+ -+struct peer_stats { -+ u64 last_rx; -+ u64 last_ack; -+ u32 tx_packets; -+ u32 tx_bytes; -+ u32 tx_retries; -+ u32 tx_failed; -+ u32 rx_packets; -+ u32 rx_bytes; -+ u32 rx_dropped; -+ u32 last_rxdrop; -+ struct rate_info rxrate; -+ u32 tx_tid_msdu[NSS_TX_TID_MAX]; -+ u32 rx_tid_msdu[IEEE80211_NUM_TIDS + 1]; -+}; -+ -+enum ath11k_nss_peer_sec_type { -+ PEER_SEC_TYPE_NONE, -+ PEER_SEC_TYPE_WEP128, -+ PEER_SEC_TYPE_WEP104, -+ PEER_SEC_TYPE_WEP40, -+ PEER_SEC_TYPE_TKIP, -+ PEER_SEC_TYPE_TKIP_NOMIC, -+ PEER_SEC_TYPE_AES_CCMP, -+ PEER_SEC_TYPE_WAPI, -+ PEER_SEC_TYPE_AES_CCMP_256, -+ PEER_SEC_TYPE_AES_GCMP, -+ PEER_SEC_TYPE_AES_GCMP_256, -+ PEER_SEC_TYPES_MAX -+}; -+ -+/* this holds the memory allocated for nss managed peer info */ -+struct ath11k_nss_peer { -+ uint32_t *vaddr; -+ dma_addr_t paddr; -+ struct peer_stats *nss_stats; -+}; -+ -+/* Structure to hold the vif related info for nss offload support */ -+struct arvif_nss { -+ /* dynamic ifnum allocated by nss driver for vif */ -+ int if_num; -+ /* Used for completion status for vdev config nss messages */ -+ struct completion complete; -+ /* Keep the copy of encap type for nss */ -+ int encap; -+ /* Keep the copy of decap type for nss */ -+ int decap; -+ bool created; -+}; -+ -+/* Structure to hold the pdev/radio related info for nss offload support */ -+struct ath11k_nss { -+ /* dynamic ifnum allocated by nss driver for pdev */ -+ int if_num; -+ /* Radio/pdev Context obtained on pdev register */ -+ void* ctx; -+}; -+ -+/* Structure to hold the soc related info for nss offload support */ -+struct ath11k_soc_nss { -+ /* turn on/off nss offload support in ath11k */ -+ bool enabled; -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT -+ /* soc nss ctx */ -+ void* ctx; -+ /* if_num to be used for soc related nss messages */ -+ int if_num; -+ /* Completion to nss message response */ -+ struct completion complete; -+ /* Response to nss messages are stored here on msg callback -+ * used only in contention free messages during init */ -+ int response; -+ /* Below is used for identifying allocated tx descriptors */ -+ dma_addr_t tx_desc_paddr[ATH11K_NSS_MAX_NUMBER_OF_PAGE]; -+ uint32_t * tx_desc_vaddr[ATH11K_NSS_MAX_NUMBER_OF_PAGE]; -+ uint32_t tx_desc_size[ATH11K_NSS_MAX_NUMBER_OF_PAGE]; -+#endif -+}; -+ -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT -+int ath11k_nss_tx(struct ath11k_vif *arvif, struct sk_buff *skb); -+int ath11k_nss_vdev_set_cmd(struct ath11k_vif *arvif, int cmd, int val); -+int ath11k_nss_vdev_create(struct ath11k_vif *arvif); -+void ath11k_nss_vdev_delete(struct ath11k_vif *arvif); -+int ath11k_nss_vdev_up(struct ath11k_vif *arvif); -+int ath11k_nss_vdev_down(struct ath11k_vif *arvif); -+int ath11k_nss_peer_delete(struct ath11k_base *ab, u8 *addr); -+int ath11k_nss_peer_create(struct ath11k_base *ab, struct ath11k_peer *peer); -+int ath11k_nss_set_peer_sec_type(struct ath11k *ar, struct ath11k_peer *peer, -+ struct ieee80211_key_conf *key_conf); -+void ath11k_nss_update_sta_stats(struct station_info *sinfo, -+ struct ieee80211_sta *sta, -+ struct ath11k_sta *arsta); -+void ath11k_nss_update_sta_rxrate(struct hal_rx_mon_ppdu_info *ppdu_info, -+ struct ath11k_peer *peer); -+int ath11k_nss_setup(struct ath11k_base *ab); -+int ath11k_nss_teardown(struct ath11k_base *ab); -+void ath11k_nss_ext_rx_stats(struct ath11k_base *ab, struct htt_rx_ring_tlv_filter *tlv_filter); -+#else -+static inline int ath11k_nss_tx(struct ath11k_vif *arvif, struct sk_buff *skb) -+{ -+ return 0; -+} -+ -+static inline int ath11k_nss_vdev_set_cmd(struct ath11k_vif *arvif, int cmd, int val) -+{ -+ return 0; -+} -+ -+static inline int ath11k_nss_vdev_create(struct ath11k_vif *arvif) -+{ -+ return 0; -+} -+ -+static inline void ath11k_nss_vdev_delete(struct ath11k_vif *arvif) -+{ -+} -+ -+static inline void ath11k_nss_update_sta_stats(struct station_info *sinfo, -+ struct ieee80211_sta *sta, -+ struct ath11k_sta *arsta) -+{ -+ return; -+} -+ -+static inline void ath11k_nss_update_sta_rxrate(struct hal_rx_mon_ppdu_info *ppdu_info, -+ struct ath11k_peer *peer) -+{ -+ return; -+} -+ -+static inline int ath11k_nss_vdev_up(struct ath11k_vif *arvif) -+{ -+ return 0; -+} -+ -+static inline int ath11k_nss_vdev_down(struct ath11k_vif *arvif) -+{ -+ return 0; -+} -+ -+static inline int ath11k_nss_peer_delete(struct ath11k_base *ab, u8 *addr) -+{ -+ return 0; -+} -+ -+static inline int ath11k_nss_peer_create(struct ath11k_base *ab, struct ath11k_peer *peer) -+{ -+ return 0; -+} -+ -+static inline int ath11k_nss_set_peer_sec_type(struct ath11k *ar, struct ath11k_peer *peer, -+ struct ieee80211_key_conf *key_conf) -+{ -+ return 0; -+} -+ -+static inline int ath11k_nss_setup(struct ath11k_base *ab) -+{ -+ return 0; -+} -+ -+static inline int ath11k_nss_teardown(struct ath11k_base *ab) -+{ -+ return 0; -+} -+ -+static inline void ath11k_nss_ext_rx_stats(struct ath11k_base *ab, struct htt_rx_ring_tlv_filter *tlv_filter) -+{ -+ return; -+} -+#endif /* CPTCFG_ATH11K_NSS_SUPPORT */ -+#endif ---- a/drivers/net/wireless/ath/ath11k/hif.h -+++ b/drivers/net/wireless/ath/ath11k/hif.h -@@ -29,6 +29,7 @@ struct ath11k_hif_ops { - u32 *base_vector); - void (*get_msi_address)(struct ath11k_base *ab, u32 *msi_addr_lo, - u32 *msi_addr_hi); -+ u32 (*get_window_offset)(struct ath11k_base *ab, u32 offset); - }; - - static inline void ath11k_hif_ce_irq_enable(struct ath11k_base *ab) -@@ -126,4 +127,11 @@ static inline void ath11k_get_msi_addres - - ab->hif.ops->get_msi_address(ab, msi_addr_lo, msi_addr_hi); - } -+static inline u32 ath11k_hif_get_window_offset(struct ath11k_base *ab, u32 offset) -+{ -+ if (ab->hif.ops->get_window_offset) -+ return ab->hif.ops->get_window_offset(ab, offset); -+ -+ return offset; -+} - #endif /* _HIF_H_ */ ---- a/drivers/net/wireless/ath/ath11k/pci.c -+++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -174,6 +174,20 @@ static inline u32 ath11k_pci_get_window_ - return window_start; - } - -+static inline u32 ath11k_pci_get_window_offset(struct ath11k_base *ab, -+ u32 offset) -+{ -+ u32 window_start; -+ -+ if (ab->bus_params.static_window_map) { -+ window_start = ath11k_pci_get_window_start(ab, offset); -+ -+ if (window_start) -+ offset = window_start + (offset & WINDOW_RANGE_MASK); -+ } -+ return offset; -+} -+ - void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value) - { - struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -@@ -1180,6 +1194,7 @@ static const struct ath11k_hif_ops ath11 - .get_msi_address = ath11k_pci_get_msi_address, - .get_user_msi_vector = ath11k_get_user_msi_assignment, - .map_service_to_pipe = ath11k_pci_map_service_to_pipe, -+ .get_window_offset = ath11k_pci_get_window_offset, - }; - - static int ath11k_pci_probe(struct pci_dev *pdev, diff --git a/package/kernel/mac80211/patches/nss/199-003-ath11k-add-nss-support.patch b/package/kernel/mac80211/patches/nss/199-003-ath11k-add-nss-support.patch deleted file mode 100644 index b2c85f0e6..000000000 --- a/package/kernel/mac80211/patches/nss/199-003-ath11k-add-nss-support.patch +++ /dev/null @@ -1,881 +0,0 @@ -From 65c511e3aeb9afb84a3c6c8ac34353af91b880e9 Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Fri, 10 Jul 2020 12:50:21 +0530 -Subject: [PATCH 3/3] ath11k: add nss support - - Add NSS Offload support for ath11k driver. - -Signed-off-by: Sriram R ---- - drivers/net/wireless/ath/ath11k/ahb.c | 18 ++++++-- - drivers/net/wireless/ath/ath11k/core.c | 24 ++++++++++ - drivers/net/wireless/ath/ath11k/core.h | 14 +++++- - drivers/net/wireless/ath/ath11k/dp.c | 21 ++++++--- - drivers/net/wireless/ath/ath11k/dp.h | 1 + - drivers/net/wireless/ath/ath11k/dp_rx.c | 17 +++++-- - drivers/net/wireless/ath/ath11k/dp_rx.h | 6 +++ - drivers/net/wireless/ath/ath11k/hal.h | 2 + - drivers/net/wireless/ath/ath11k/hal_rx.c | 10 +++- - drivers/net/wireless/ath/ath11k/mac.c | 78 +++++++++++++++++++++++++++++++- - drivers/net/wireless/ath/ath11k/peer.c | 9 +++- - drivers/net/wireless/ath/ath11k/peer.h | 6 ++- - local-symbols | 1 + - 13 files changed, 186 insertions(+), 21 deletions(-) - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -4245,7 +4245,7 @@ - int (*reset_tid_config)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u8 tids); -- void (*update_vif_offload)(struct ieee80211_hw *hw, -+ int (*update_vif_offload)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); - void (*sta_set_4addr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enabled); ---- a/drivers/net/wireless/ath/ath11k/ahb.c -+++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -442,6 +442,12 @@ static int ath11k_ahb_ext_irq_config(str - int i, j; - int irq; - int ret; -+ bool nss_offload; -+ -+ /* TCL Completion, REO Dest, ERR, Exception and h2rxdma rings are offloaded -+ * to nss when its enabled, hence don't enable these interrupts -+ */ -+ nss_offload = ab->nss.enabled; - - for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { - struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; -@@ -454,20 +460,20 @@ static int ath11k_ahb_ext_irq_config(str - ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); - - for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) { -- if (ab->hw_params.ring_mask->tx[i] & BIT(j)) { -+ if (!nss_offload && ab->hw_params.ring_mask->tx[i] & BIT(j)) { - irq_grp->irqs[num_irq++] = - wbm2host_tx_completions_ring1 - j; - } - -- if (ab->hw_params.ring_mask->rx[i] & BIT(j)) { -+ if (!nss_offload && ab->hw_params.ring_mask->rx[i] & BIT(j)) { - irq_grp->irqs[num_irq++] = - reo2host_destination_ring1 - j; - } - -- if (ab->hw_params.ring_mask->rx_err[i] & BIT(j)) -+ if (!nss_offload && ab->hw_params.ring_mask->rx_err[i] & BIT(j)) - irq_grp->irqs[num_irq++] = reo2host_exception; - -- if (ab->hw_params.ring_mask->rx_wbm_rel[i] & BIT(j)) -+ if (!nss_offload && ab->hw_params.ring_mask->rx_wbm_rel[i] & BIT(j)) - irq_grp->irqs[num_irq++] = wbm2host_rx_release; - - if (ab->hw_params.ring_mask->reo_status[i] & BIT(j)) -@@ -485,7 +491,7 @@ static int ath11k_ahb_ext_irq_config(str - ath11k_hw_get_mac_from_pdev_id(hw, j); - } - -- if (ab->hw_params.ring_mask->host2rxdma[i] & BIT(j)) { -+ if (!nss_offload && ab->hw_params.ring_mask->host2rxdma[i] & BIT(j)) { - irq_grp->irqs[num_irq++] = - host2rxdma_host_buf_ring_mac1 - - ath11k_hw_get_mac_from_pdev_id(hw, j); -@@ -678,6 +684,7 @@ static int ath11k_ahb_probe(struct platf - ab->hw_rev = (enum ath11k_hw_rev)of_id->data; - ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; - ab->mem = mem; -+ ab->mem_pa = mem_res->start; - ab->mem_len = resource_size(mem_res); - ab->enable_cold_boot_cal = enable_cold_boot_cal; - platform_set_drvdata(pdev, ab); ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -16,6 +16,12 @@ - #include "hif.h" - #include "wow.h" - -+unsigned int nss_offload = 1; -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT -+module_param_named(nss_offload, nss_offload, uint, 0644); -+MODULE_PARM_DESC(nss_offload, "Enable NSS Offload support"); -+#endif -+ - unsigned int ath11k_debug_mask; - EXPORT_SYMBOL(ath11k_debug_mask); - module_param_named(debug_mask, ath11k_debug_mask, uint, 0644); -@@ -639,23 +645,30 @@ static int ath11k_core_pdev_create(struc - return ret; - } - -- ret = ath11k_mac_register(ab); -+ ret = ath11k_dp_pdev_alloc(ab); - if (ret) { -- ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); -+ ath11k_err(ab, "failed to attach DP pdev: %d\n", ret); - goto err_pdev_debug; - } - -- ret = ath11k_dp_pdev_alloc(ab); -+ ret = ath11k_nss_setup(ab); - if (ret) { -- ath11k_err(ab, "failed to attach DP pdev: %d\n", ret); -- goto err_mac_unregister; -+ ath11k_err(ab, "failed to setup nss driver interface%d", -+ ret); -+ goto err_dp_pdev_free; -+ } -+ -+ ret = ath11k_mac_register(ab); -+ if (ret) { -+ ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); -+ goto err_nss_tear; - } - - ret = ath11k_thermal_register(ab); - if (ret) { - ath11k_err(ab, "could not register thermal device: %d\n", - ret); -- goto err_dp_pdev_free; -+ goto err_mac_unregister; - } - - ret = ath11k_spectral_init(ab); -@@ -668,10 +681,12 @@ static int ath11k_core_pdev_create(struc - - err_thermal_unregister: - ath11k_thermal_unregister(ab); --err_dp_pdev_free: -- ath11k_dp_pdev_free(ab); - err_mac_unregister: - ath11k_mac_unregister(ab); -+err_nss_tear: -+ ath11k_nss_teardown(ab); -+err_dp_pdev_free: -+ ath11k_dp_pdev_free(ab); - err_pdev_debug: - ath11k_debugfs_pdev_destroy(ab); - -@@ -683,6 +698,10 @@ static void ath11k_core_pdev_destroy(str - ath11k_spectral_deinit(ab); - ath11k_thermal_unregister(ab); - ath11k_mac_unregister(ab); -+ -+ ath11k_nss_teardown(ab); -+ ab->nss.enabled = false; -+ - ath11k_hif_irq_disable(ab); - ath11k_dp_pdev_free(ab); - ath11k_debugfs_pdev_destroy(ab); -@@ -942,6 +961,10 @@ static int ath11k_core_reconfigure_on_cr - int ret; - - mutex_lock(&ab->core_lock); -+ -+ ath11k_nss_teardown(ab); -+ ab->nss.enabled = false; -+ - ath11k_thermal_unregister(ab); - ath11k_hif_irq_disable(ab); - ath11k_dp_pdev_free(ab); -@@ -1163,6 +1186,8 @@ int ath11k_core_pre_init(struct ath11k_b - ath11k_err(ab, "failed to get hw params: %d\n", ret); - return ret; - } -+ ab->nss.enabled = nss_offload; -+ - - return 0; - } -@@ -1177,7 +1202,6 @@ int ath11k_core_init(struct ath11k_base - ath11k_err(ab, "failed to create soc core: %d\n", ret); - return ret; - } -- - return 0; - } - EXPORT_SYMBOL(ath11k_core_init); ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -26,6 +26,7 @@ - #include "thermal.h" - #include "dbring.h" - #include "spectral.h" -+#include "nss.h" - - #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) - -@@ -260,6 +261,9 @@ struct ath11k_vif { - bool rsnie_present; - bool wpaie_present; - struct ieee80211_chanctx_conf chanctx; -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT -+ struct arvif_nss nss; -+#endif - }; - - struct ath11k_vif_iter { -@@ -407,6 +411,9 @@ struct ath11k_sta { - /* protected by conf_mutex */ - bool aggr_mode; - #endif -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT -+ struct ath11k_nss_sta_stats *nss_stats; -+#endif - }; - - #define ATH11K_MIN_5G_FREQ 4150 -@@ -524,6 +531,9 @@ struct ath11k { - struct ieee80211_hw *hw; - struct ieee80211_ops *ops; - struct ath11k_pdev_wmi *wmi; -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT -+ struct ath11k_nss nss; -+#endif - struct ath11k_pdev_dp dp; - u8 mac_addr[ETH_ALEN]; - u32 ht_cap_info; -@@ -763,8 +773,10 @@ struct ath11k_base { - struct ath11k_htc htc; - - struct ath11k_dp dp; -+ struct ath11k_soc_nss nss; - - void __iomem *mem; -+ dma_addr_t mem_pa; - unsigned long mem_len; - - struct { ---- a/drivers/net/wireless/ath/ath11k/dp.c -+++ b/drivers/net/wireless/ath/ath11k/dp.c -@@ -45,12 +45,17 @@ int ath11k_dp_peer_setup(struct ath11k * - struct ath11k_peer *peer; - u32 reo_dest; - int ret = 0, tid; -+ bool rx_hash_enable = DP_RX_HASH_ENABLE; -+ -+ /* RX Hash based steering is disabled for NSS Offload */ -+ if (ar->ab->nss.enabled) -+ rx_hash_enable = DP_RX_HASH_DISABLE; - - /* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */ - reo_dest = ar->dp.mac_id + 1; - ret = ath11k_wmi_set_peer_param(ar, addr, vdev_id, - WMI_PEER_SET_DEFAULT_ROUTING, -- DP_RX_HASH_ENABLE | (reo_dest << 1)); -+ rx_hash_enable | (reo_dest << 1)); - - if (ret) { - ath11k_warn(ab, "failed to set default routing %d peer :%pM vdev_id :%d\n", -@@ -126,6 +131,18 @@ static int ath11k_dp_srng_calculate_msi_ - { - const u8 *grp_mask; - -+ if (ab->nss.enabled) { -+ switch (type) { -+ case HAL_REO_STATUS: -+ case HAL_RXDMA_MONITOR_STATUS: -+ case HAL_RXDMA_MONITOR_DST: -+ case HAL_RXDMA_MONITOR_BUF: -+ break; -+ default: -+ return -ENOENT; -+ } -+ } -+ - switch (type) { - case HAL_WBM2SW_RELEASE: - if (ring_num < 3) { -@@ -755,14 +772,18 @@ int ath11k_dp_service_srng(struct ath11k - int work_done = 0; - int i = 0, j; - int tot_work_done = 0; -+ bool nss_offload; -+ -+ /* Processing of offloaded rings are not required */ -+ nss_offload = ab->nss.enabled; - -- while (ab->hw_params.ring_mask->tx[grp_id] >> i) { -+ while (!nss_offload && ab->hw_params.ring_mask->tx[grp_id] >> i) { - if (ab->hw_params.ring_mask->tx[grp_id] & BIT(i)) - ath11k_dp_tx_completion_handler(ab, i); - i++; - } - -- if (ab->hw_params.ring_mask->rx_err[grp_id]) { -+ if (!nss_offload && ab->hw_params.ring_mask->rx_err[grp_id]) { - work_done = ath11k_dp_process_rx_err(ab, napi, budget); - budget -= work_done; - tot_work_done += work_done; -@@ -770,7 +791,7 @@ int ath11k_dp_service_srng(struct ath11k - goto done; - } - -- if (ab->hw_params.ring_mask->rx_wbm_rel[grp_id]) { -+ if (!nss_offload && ab->hw_params.ring_mask->rx_wbm_rel[grp_id]) { - work_done = ath11k_dp_rx_process_wbm_err(ab, - napi, - budget); -@@ -781,7 +802,7 @@ int ath11k_dp_service_srng(struct ath11k - goto done; - } - -- if (ab->hw_params.ring_mask->rx[grp_id]) { -+ if (!nss_offload && ab->hw_params.ring_mask->rx[grp_id]) { - i = fls(ab->hw_params.ring_mask->rx[grp_id]) - 1; - work_done = ath11k_dp_process_rx(ab, i, napi, - budget); -@@ -815,7 +836,7 @@ int ath11k_dp_service_srng(struct ath11k - if (ab->hw_params.ring_mask->reo_status[grp_id]) - ath11k_dp_process_reo_status(ab); - -- for (i = 0; i < ab->num_radios; i++) { -+ for (i = 0; !nss_offload && i < ab->num_radios; i++) { - for (j = 0; j < ab->hw_params.num_rxmda_per_pdev; j++) { - int id = i * ab->hw_params.num_rxmda_per_pdev + j; - ---- a/drivers/net/wireless/ath/ath11k/dp.h -+++ b/drivers/net/wireless/ath/ath11k/dp.h -@@ -166,6 +166,7 @@ struct ath11k_pdev_dp { - #define DP_AVG_MSDUS_PER_MPDU 4 - - #define DP_RX_HASH_ENABLE 1 /* Enable hash based Rx steering */ -+#define DP_RX_HASH_DISABLE 0 /* Disable hash based Rx steering */ - - #define DP_BA_WIN_SZ_MAX 256 - ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -17,6 +17,7 @@ - #include "hal_rx.h" - #include "dp_tx.h" - #include "peer.h" -+#include "nss.h" - - #define ATH11K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ) - -@@ -191,7 +192,7 @@ static u8 ath11k_dp_rx_h_mpdu_start_tid( - __le32_to_cpu(desc->mpdu_start.info2)); - } - --static u16 ath11k_dp_rx_h_mpdu_start_peer_id(struct hal_rx_desc *desc) -+u16 ath11k_dp_rx_h_mpdu_start_peer_id(struct hal_rx_desc *desc) - { - return __le16_to_cpu(desc->mpdu_start.sw_peer_id); - } -@@ -202,7 +203,7 @@ static u8 ath11k_dp_rx_h_msdu_end_l3pad( - __le32_to_cpu(desc->msdu_end.info2)); - } - --static bool ath11k_dp_rx_h_msdu_end_first_msdu(struct hal_rx_desc *desc) -+bool ath11k_dp_rx_h_msdu_end_first_msdu(struct hal_rx_desc *desc) - { - return !!FIELD_GET(RX_MSDU_END_INFO2_FIRST_MSDU, - __le32_to_cpu(desc->msdu_end.info2)); -@@ -294,7 +295,7 @@ static int ath11k_dp_purge_mon_ring(stru - return -ETIMEDOUT; - } - --static bool ath11k_dp_rx_h_attn_is_mcbc(struct hal_rx_desc *desc) -+bool ath11k_dp_rx_h_attn_is_mcbc(struct hal_rx_desc *desc) - { - return ath11k_dp_rx_h_msdu_end_first_msdu(desc) && - (!!FIELD_GET(RX_ATTENTION_INFO1_MCAST_BCAST, -@@ -498,7 +499,9 @@ static int ath11k_dp_rxdma_pdev_buf_setu - struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; - int i; - -- ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_BUF); -+ /* RXDMA BUF ring is offloaded to NSS */ -+ if (!ar->ab->nss.enabled) -+ ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_BUF); - - if (ar->ab->hw_params.rxdma1_enable) { - rx_ring = &dp->rxdma_mon_buf_ring; -@@ -1971,7 +1974,7 @@ static void ath11k_dp_rx_h_csum_offload( - CHECKSUM_NONE : CHECKSUM_UNNECESSARY; - } - --static int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, -+int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, - enum hal_encrypt_type enctype) - { - switch (enctype) { -@@ -1998,7 +2001,7 @@ static int ath11k_dp_rx_crypto_mic_len(s - return 0; - } - --static int ath11k_dp_rx_crypto_param_len(struct ath11k *ar, -+int ath11k_dp_rx_crypto_param_len(struct ath11k *ar, - enum hal_encrypt_type enctype) - { - switch (enctype) { -@@ -2026,7 +2029,7 @@ static int ath11k_dp_rx_crypto_param_len - return 0; - } - --static int ath11k_dp_rx_crypto_icv_len(struct ath11k *ar, -+int ath11k_dp_rx_crypto_icv_len(struct ath11k *ar, - enum hal_encrypt_type enctype) - { - switch (enctype) { -@@ -3403,7 +3406,7 @@ int ath11k_dp_rx_process_mon_status(stru - struct sk_buff_head skb_list; - struct hal_rx_mon_ppdu_info *ppdu_info; - struct ath11k_peer *peer; -- struct ath11k_sta *arsta; -+ struct ath11k_sta *arsta = NULL; - int num_buffs_reaped = 0; - u32 rx_buf_sz; - u16 log_type = 0; -@@ -3483,6 +3486,8 @@ int ath11k_dp_rx_process_mon_status(stru - ath11k_rx_stats_buf_pktlog_process(ar, skb->data, log_type, rx_buf_sz); - } - -+ ath11k_nss_update_sta_rxrate(&ppdu_info, peer); -+ - spin_unlock_bh(&ab->base_lock); - rcu_read_unlock(); - ---- a/drivers/net/wireless/ath/ath11k/dp_rx.h -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.h -@@ -115,4 +115,13 @@ int ath11k_peer_rx_frag_setup(struct ath - int ath11k_dp_rx_pktlog_start(struct ath11k_base *ab); - int ath11k_dp_rx_pktlog_stop(struct ath11k_base *ab, bool stop_timer); - -+int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, -+ enum hal_encrypt_type enctype); -+int ath11k_dp_rx_crypto_param_len(struct ath11k *ar, -+ enum hal_encrypt_type enctype); -+int ath11k_dp_rx_crypto_icv_len(struct ath11k *ar, -+ enum hal_encrypt_type enctype); -+bool ath11k_dp_rx_h_msdu_end_first_msdu(struct hal_rx_desc *desc); -+bool ath11k_dp_rx_h_attn_is_mcbc(struct hal_rx_desc *desc); -+u16 ath11k_dp_rx_h_mpdu_start_peer_id(struct hal_rx_desc *desc); - #endif /* ATH11K_DP_RX_H */ ---- a/drivers/net/wireless/ath/ath11k/hal.h -+++ b/drivers/net/wireless/ath/ath11k/hal.h -@@ -414,6 +414,8 @@ enum hal_srng_ring_id { - #define HAL_SRNG_RING_ID_MAX (HAL_SRNG_RING_ID_UMAC_ID_END + \ - HAL_SRNG_NUM_LMAC_RINGS) - -+#define HAL_SRNG_REO_ALTERNATE_SELECT 0x7 -+ - enum hal_ring_type { - HAL_REO_DST, - HAL_REO_EXCEPTION, ---- a/drivers/net/wireless/ath/ath11k/hal_rx.c -+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -803,14 +803,18 @@ void ath11k_hal_reo_init_cmd_ring(struct - - void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map) - { -+ u8 frag_dest_ring = HAL_SRNG_RING_ID_REO2SW1; - u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG; - u32 val; - -+ if (ab->nss.enabled) -+ frag_dest_ring = HAL_SRNG_REO_ALTERNATE_SELECT; -+ - val = ath11k_hif_read32(ab, reo_base + HAL_REO1_GEN_ENABLE); - - val &= ~HAL_REO1_GEN_ENABLE_FRAG_DST_RING; - val |= FIELD_PREP(HAL_REO1_GEN_ENABLE_FRAG_DST_RING, -- HAL_SRNG_RING_ID_REO2SW1) | -+ frag_dest_ring) | - FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE, 1) | - FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1); - ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); -@@ -824,6 +828,10 @@ void ath11k_hal_reo_hw_setup(struct ath1 - ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3(ab), - HAL_DEFAULT_REO_TIMEOUT_USEC); - -+ /* REO Dest ring setup is not required in NSS offload case */ -+ if (ab->nss.enabled) -+ return; -+ - ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0, - FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP, - ring_hash_map)); ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -17,6 +17,7 @@ - #include "testmode.h" - #include "peer.h" - #include "debugfs_sta.h" -+#include "nss.h" - - #define CHAN2G(_channel, _freq, _flags) { \ - .band = NL80211_BAND_2GHZ, \ -@@ -1102,6 +1103,11 @@ static void ath11k_control_beaconing(str - lockdep_assert_held(&arvif->ar->conf_mutex); - - if (!info->enable_beacon) { -+ -+ ret = ath11k_nss_vdev_down(arvif); -+ if(ret) -+ ath11k_warn(ar->ab, "failure in nss vdev down %d\r\n",ret); -+ - ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id); - if (ret) - ath11k_warn(ar->ab, "failed to down vdev_id %i: %d\n", -@@ -1144,6 +1150,12 @@ static void ath11k_control_beaconing(str - - arvif->is_up = true; - -+ ret = ath11k_nss_vdev_up(arvif); -+ if(ret) { -+ ath11k_warn(ar->ab, "failure in nss vdev up %d\r\n",ret); -+ return; -+ } -+ - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id); - } - -@@ -2302,6 +2314,12 @@ static void ath11k_bss_assoc(struct ieee - "mac vdev %d up (associated) bssid %pM aid %d\n", - arvif->vdev_id, bss_conf->bssid, bss_conf->aid); - -+ ret = ath11k_nss_vdev_up(arvif); -+ if(ret) { -+ ath11k_warn(ar->ab, "failure in nss vdev up %d\r\n",ret); -+ return; -+ } -+ - /* Authorize BSS Peer */ - ret = ath11k_wmi_set_peer_param(ar, arvif->bssid, - arvif->vdev_id, -@@ -2326,6 +2344,10 @@ static void ath11k_bss_disassoc(struct i - - lockdep_assert_held(&ar->conf_mutex); - -+ ret = ath11k_nss_vdev_down(arvif); -+ if(ret) -+ ath11k_warn(ar->ab, "failure in nss vdev down %d\r\n",ret); -+ - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n", - arvif->vdev_id, arvif->bssid); - -@@ -2599,6 +2621,28 @@ static int ath11k_mac_config_obss_pd(str - return 0; - } - -+static void ath11k_mac_op_nss_bss_info_changed(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ u32 changed) -+{ -+ struct ath11k *ar = hw->priv; -+ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); -+ int ret = 0; -+ -+ mutex_lock(&ar->conf_mutex); -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "Setting ap_isolate %d to NSS\n", -+ arvif->vif->bss_conf.nss_ap_isolate); -+ if (changed & BSS_CHANGED_NSS_AP_ISOLATE) { -+ ret = ath11k_nss_vdev_set_cmd(arvif, NSS_WIFI_VDEV_CFG_AP_BRIDGE_CMD, -+ !arvif->vif->bss_conf.nss_ap_isolate); -+ if(ret) -+ ath11k_warn(ar->ab, "failed to set ap_isolate in nss %d\n", ret); -+ } -+ -+ mutex_unlock(&ar->conf_mutex); -+} -+ - static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, -@@ -3356,6 +3400,16 @@ static int ath11k_mac_op_set_key(struct - - spin_lock_bh(&ab->base_lock); - peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr); -+ -+ /* TODO: Check if vdev specific security cfg is mandatory */ -+ ret = ath11k_nss_vdev_set_cmd(arvif, NSS_WIFI_VDEV_SECURITY_TYPE_CMD, key->cipher); -+ if (ret) -+ ath11k_warn(ab, "failure to set vdev security type in nss"); -+ -+ ret = ath11k_nss_set_peer_sec_type(ar, peer, key); -+ if (ret) -+ ath11k_warn(ab, "failure to set peer security type in nss"); -+ - if (peer && cmd == SET_KEY) { - peer->keys[key->keyidx] = key; - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { -@@ -5092,7 +5146,10 @@ static void ath11k_mac_op_tx(struct ieee - return; - } - -- ret = ath11k_dp_tx(ar, arvif, skb); -+ if (ar->ab->nss.enabled) -+ ret = ath11k_nss_tx(arvif,skb); -+ else -+ ret = ath11k_dp_tx(ar, arvif, skb); - if (ret) { - ath11k_warn(ar->ab, "failed to transmit frame %d\n", ret); - ieee80211_free_txskb(ar->hw, skb); -@@ -5117,6 +5174,8 @@ static int ath11k_mac_config_mon_status_ - - if (enable) { - tlv_filter = ath11k_mac_mon_status_filter_default; -+ ath11k_nss_ext_rx_stats(ar->ab, &tlv_filter); -+ - if (ath11k_debugfs_rx_filter(ar)) - tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar); - } -@@ -5340,7 +5340,7 @@ ath11k_mac_setup_vdev_create_params(stru - return 0; - } - --static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, -+static int ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) - { - struct ath11k *ar = hw->priv; -@@ -5342,6 +5401,12 @@ static void ath11k_mac_op_update_vif_off - u32 param_id, param_value; - int ret; - -+ ret = ath11k_nss_vdev_create(arvif); -+ if(ret) { -+ ath11k_warn(ab, "failed to create nss vdev %d\n", ret); -+ return ret; -+ } -+ - param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE; - if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET || - (vif->type != NL80211_IFTYPE_STATION && -@@ -5352,6 +5352,7 @@ static void ath11k_mac_op_update_vif_off - arvif->vdev_id, ret); - vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; - } -+ return ret; - } - - static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, -@@ -5488,7 +5553,28 @@ static int ath11k_mac_op_add_interface(s - list_add(&arvif->list, &ar->arvifs); - spin_unlock_bh(&ar->data_lock); - -- ath11k_mac_op_update_vif_offload(hw, vif); -+ if (ath11k_mac_op_update_vif_offload(hw, vif)) -+ goto err_vdev_del; -+ -+ if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) -+ param_value = ATH11K_HW_TXRX_ETHERNET; -+ else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) -+ param_value = ATH11K_HW_TXRX_RAW; -+ else -+ param_value = ATH11K_HW_TXRX_NATIVE_WIFI; -+ -+ ret = ath11k_nss_vdev_set_cmd(arvif, NSS_WIFI_VDEV_ENCAP_TYPE_CMD, param_value); -+ -+ if(ret) { -+ ath11k_warn(ab, "failed to set encap type in nss %d\n", ret); -+ goto err_vdev_del; -+ } -+ -+ ret = ath11k_nss_vdev_set_cmd(arvif, NSS_WIFI_VDEV_DECAP_TYPE_CMD, param_value); -+ if(ret) { -+ ath11k_warn(ab, "failed to set decap type in nss %d\n", ret); -+ goto err_vdev_del; -+ } - - nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1; - ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -@@ -5616,6 +5702,7 @@ err_peer_del: - } - - err_vdev_del: -+ ath11k_nss_vdev_delete(arvif); - ath11k_wmi_vdev_delete(ar, arvif->vdev_id); - ar->num_created_vdevs--; - ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); -@@ -5665,6 +5752,8 @@ static void ath11k_mac_op_remove_interfa - - reinit_completion(&ar->vdev_delete_done); - -+ ath11k_nss_vdev_delete(arvif); -+ - ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); - if (ret) { - ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n", -@@ -6082,6 +6171,10 @@ ath11k_mac_update_vif_chan(struct ath11k - if (WARN_ON(!arvif->is_up)) - continue; - -+ ret = ath11k_nss_vdev_down(arvif); -+ if(ret) -+ ath11k_warn(ar->ab, "failure in nss vdev down %d\r\n",ret); -+ - ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id); - if (ret) { - ath11k_warn(ab, "failed to down vdev %d: %d\n", -@@ -6124,6 +6217,10 @@ ath11k_mac_update_vif_chan(struct ath11k - arvif->vdev_id, ret); - continue; - } -+ -+ ret = ath11k_nss_vdev_up(arvif); -+ if(ret) -+ ath11k_warn(ar->ab, "failure in nss vdev up %d\r\n",ret); - } - - /* Restart the internal monitor vdev on new channel */ -@@ -7155,6 +7252,8 @@ static void ath11k_mac_op_sta_statistics - - /* TODO: Use real NF instead of default one. */ - sinfo->signal = arsta->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; -+ -+ ath11k_nss_update_sta_stats(sinfo, sta, arsta); - } - - static const struct ieee80211_ops ath11k_ops = { -@@ -7252,6 +7351,7 @@ static const struct ieee80211_ops ath11k - .update_vif_offload = ath11k_mac_op_update_vif_offload, - .config = ath11k_mac_op_config, - .bss_info_changed = ath11k_mac_op_bss_info_changed, -+ .nss_bss_info_changed = ath11k_mac_op_nss_bss_info_changed, - .configure_filter = ath11k_mac_op_configure_filter, - .hw_scan = ath11k_mac_op_hw_scan, - .cancel_hw_scan = ath11k_mac_op_cancel_hw_scan, -@@ -7651,7 +7751,8 @@ static int __ath11k_mac_register(struct - ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW); - ieee80211_hw_set(ar->hw, SUPPORTS_REORDERING_BUFFER); - ieee80211_hw_set(ar->hw, SUPPORTS_AMSDU_IN_AMPDU); -- ieee80211_hw_set(ar->hw, USES_RSS); -+ if(!ab->nss.enabled) -+ ieee80211_hw_set(ar->hw, USES_RSS); - } - - ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS; -@@ -7723,6 +7824,9 @@ static int __ath11k_mac_register(struct - ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT); - } - -+ if (ab->nss.enabled) -+ ieee80211_hw_set(ar->hw, SUPPORTS_NSS_OFFLOAD); -+ - ret = ieee80211_register_hw(ar->hw); - if (ret) { - ath11k_err(ar->ab, "ieee80211 registration failed: %d\n", ret); ---- a/drivers/net/wireless/ath/ath11k/peer.c -+++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -6,6 +6,7 @@ - #include "core.h" - #include "peer.h" - #include "debug.h" -+#include "nss.h" - - struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, - const u8 *addr) -@@ -129,6 +130,8 @@ void ath11k_peer_map_event(struct ath11k - ether_addr_copy(peer->addr, mac_addr); - list_add(&peer->list, &ab->peers); - wake_up(&ab->peer_mapping_wq); -+ if (ab->nss.enabled) -+ ath11k_nss_peer_create(ab, peer); - } - - ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n", -@@ -239,6 +242,8 @@ int ath11k_peer_delete(struct ath11k *ar - - reinit_completion(&ar->peer_delete_done); - -+ ath11k_nss_peer_delete(ar->ab, addr); -+ - ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); - if (ret) { - ath11k_warn(ar->ab, -@@ -332,6 +332,7 @@ int ath11k_peer_create(struct ath11k *ar - - peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; - peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; -+ peer->vif = arvif->vif; - - ar->num_peers++; - ---- a/drivers/net/wireless/ath/ath11k/peer.h -+++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -20,6 +20,7 @@ struct ppdu_user_delayba { - struct ath11k_peer { - struct list_head list; - struct ieee80211_sta *sta; -+ struct ieee80211_vif *vif; - int vdev_id; - u8 addr[ETH_ALEN]; - int peer_id; -@@ -27,6 +27,9 @@ struct ath11k_peer { - u16 ast_hash; - u8 pdev_idx; - u16 hw_peer_id; -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT -+ struct ath11k_nss_peer nss; -+#endif - - /* protected by ab->data_lock */ - struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; ---- a/drivers/net/wireless/ath/ath11k/pci.c -+++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -749,6 +749,11 @@ static int ath11k_pci_ext_irq_config(str - netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, - ath11k_pci_ext_grp_napi_poll, NAPI_POLL_WEIGHT); - -+ /* tcl, reo, rx_err, wbm release, rxdma rings are offloaded to nss. */ -+ if (ab->nss.enabled && !(ab->hw_params.ring_mask->reo_status[i] || -+ ab->hw_params.ring_mask->rx_mon_status[i])) -+ continue; -+ - if (ab->hw_params.ring_mask->tx[i] || - ab->hw_params.ring_mask->rx[i] || - ab->hw_params.ring_mask->rx_err[i] || -@@ -974,6 +979,7 @@ static int ath11k_pci_claim(struct ath11 - goto clear_master; - } - -+ ab->mem_pa = pci_resource_start(pdev, ATH11K_PCI_BAR_NUM); - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem); - return 0; - ---- a/drivers/net/wireless/ath/ath11k/debugfs.c -+++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -922,6 +922,7 @@ static ssize_t ath11k_write_extd_rx_stat - HTT_RX_FP_DATA_FILTER_FLASG3; - } else { - tlv_filter = ath11k_mac_mon_status_filter_default; -+ ath11k_nss_ext_rx_stats(ar->ab, &tlv_filter); - } - - ar->debug.rx_filter = tlv_filter.rx_filter; ---- a/drivers/net/wireless/ath/ath11k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -10,7 +10,7 @@ - #include "hw.h" - #include "peer.h" - --static enum hal_tcl_encap_type -+enum hal_tcl_encap_type - ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb) - { - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); ---- a/drivers/net/wireless/ath/ath11k/dp_tx.h -+++ b/drivers/net/wireless/ath/ath11k/dp_tx.h -@@ -36,5 +36,7 @@ int ath11k_dp_tx_htt_rx_filter_setup(str - int mac_id, enum hal_ring_type ring_type, - int rx_buf_size, - struct htt_rx_ring_tlv_filter *tlv_filter); -+enum hal_tcl_encap_type -+ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb); - - #endif ---- a/local-symbols -+++ b/local-symbols -@@ -133,6 +133,7 @@ ATH10K_DFS_CERTIFIED= - ATH11K= - ATH11K_AHB= - ATH11K_PCI= -+ATH11K_NSS_SUPPORT= - ATH11K_DEBUG= - ATH11K_DEBUGFS= - ATH11K_TRACING= diff --git a/package/kernel/mac80211/patches/nss/214-ath11k-qos-null-frame-tx-over-wmi.patch b/package/kernel/mac80211/patches/nss/214-ath11k-qos-null-frame-tx-over-wmi.patch deleted file mode 100644 index 8f7662e54..000000000 --- a/package/kernel/mac80211/patches/nss/214-ath11k-qos-null-frame-tx-over-wmi.patch +++ /dev/null @@ -1,473 +0,0 @@ -From 0e29b669153f100b60107d5f6b3fe407b71ba79a Mon Sep 17 00:00:00 2001 -From: Sowmiya Sree Elavalagan -Date: Wed, 30 Sep 2020 22:33:42 +0530 -Subject: [PATCH] ath11k: QOS null frame tx over wmi - -Added support to send qos null frame through FW. -NSS driver does not support QOS null frame tx. -Hence this is brought for nss offload case to send -qos null frame. QOS null packet queued from mac80211 -is sent to FW through wmi interface. This happens only if FW supports -qos null tx, this is based on service bit received in ext2 service -event from FW. On successful transmission of QOS null frame status -is set 0 in the event received for this wmi message. This is status -is sent to mac80211 for further handling. - -Signed-off-by: Sowmiya Sree Elavalagan ---- - drivers/net/wireless/ath/ath11k/mac.c | 28 ++++- - drivers/net/wireless/ath/ath11k/wmi.c | 200 ++++++++++++++++++++++++++-------- - drivers/net/wireless/ath/ath11k/wmi.h | 46 +++++++- - 3 files changed, 220 insertions(+), 54 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5314,6 +5314,16 @@ static int ath11k_mac_mgmt_tx_wmi(struct - - ATH11K_SKB_CB(skb)->paddr = paddr; - -+ if (ieee80211_is_qos_nullfunc(hdr->frame_control)) { -+ ret = ath11k_wmi_qos_null_send(ar, arvif->vdev_id, buf_id, skb); -+ if (ret) { -+ ath11k_warn(ar->ab, "failed to send qos null frame over wmi: %d\n", ret); -+ goto err_unmap_buf; -+ } -+ -+ return 0; -+ } -+ - ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb); - if (ret) { - ath11k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret); -@@ -5378,8 +5388,8 @@ static void ath11k_mgmt_over_wmi_tx_work - } - } - --static int ath11k_mac_mgmt_tx(struct ath11k *ar, struct sk_buff *skb, -- bool is_prb_rsp) -+static int ath11k_mac_tx_over_wmi(struct ath11k *ar, struct sk_buff *skb, -+ bool is_prb_rsp) - { - struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue; - -@@ -5439,7 +5449,7 @@ static void ath11k_mac_op_tx(struct ieee - } else if (ieee80211_is_mgmt(hdr->frame_control)) { - frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control); - is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control); -- ret = ath11k_mac_mgmt_tx(ar, skb, is_prb_rsp); -+ ret = ath11k_mac_tx_over_wmi(ar, skb, is_prb_rsp); - if (ret) { - if (ret != -EBUSY) - ath11k_warn(ar->ab, "failed to queue management frame %d\n", -@@ -5460,6 +5470,20 @@ static void ath11k_mac_op_tx(struct ieee - spin_unlock_bh(&ar->data_lock); - } - return; -+ } else if (ar->ab->nss.enabled && -+ ieee80211_is_qos_nullfunc(hdr->frame_control) && -+ test_bit(WMI_TLV_SERVICE_QOS_NULL_FRAME_TX_OVER_WMI, -+ ar->ab->wmi_ab.svc_map)) { -+ /* NSS driver does not support tx qos null pkt hence it is offload -+ * to fw via wmi path similar to mgmt frames -+ */ -+ ret = ath11k_mac_tx_over_wmi(ar, skb, false); -+ if (ret) { -+ ath11k_warn(ar->ab, "failed to queue qos null frame %d\n", -+ ret); -+ ieee80211_free_txskb(ar->hw, skb); -+ } -+ return; - } - - if (ar->ab->nss.enabled) ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -104,7 +104,7 @@ static const struct wmi_tlv_policy wmi_t - [WMI_TAG_MGMT_RX_HDR] - = { .min_len = sizeof(struct wmi_mgmt_rx_hdr) }, - [WMI_TAG_MGMT_TX_COMPL_EVENT] -- = { .min_len = sizeof(struct wmi_mgmt_tx_compl_event) }, -+ = { .min_len = sizeof(struct wmi_tx_compl_event) }, - [WMI_TAG_SCAN_EVENT] - = { .min_len = sizeof(struct wmi_scan_event) }, - [WMI_TAG_PEER_STA_KICKOUT_EVENT] -@@ -662,6 +662,55 @@ int ath11k_wmi_mgmt_send(struct ath11k * - return ret; - } - -+int ath11k_wmi_qos_null_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, -+ struct sk_buff *frame) -+{ -+ struct ath11k_pdev_wmi *wmi = ar->wmi; -+ struct wmi_qos_null_tx_cmd *cmd; -+ struct wmi_tlv *frame_tlv; -+ struct sk_buff *skb; -+ u32 buf_len; -+ int len, ret = 0; -+ -+ buf_len = frame->len < WMI_QOS_NULL_SEND_BUF_LEN ? -+ frame->len : WMI_QOS_NULL_SEND_BUF_LEN; -+ -+ len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4); -+ -+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); -+ if (!skb) -+ return -ENOMEM; -+ -+ cmd = (struct wmi_qos_null_tx_cmd *)skb->data; -+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_QOS_NULL_FRAME_TX_SEND) | -+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); -+ cmd->vdev_id = vdev_id; -+ cmd->desc_id = buf_id; -+ cmd->paddr_lo = lower_32_bits(ATH11K_SKB_CB(frame)->paddr); -+ cmd->paddr_hi = upper_32_bits(ATH11K_SKB_CB(frame)->paddr); -+ cmd->frame_len = frame->len; -+ cmd->buf_len = buf_len; -+ -+ frame_tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd)); -+ frame_tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | -+ FIELD_PREP(WMI_TLV_LEN, buf_len); -+ -+ memcpy(frame_tlv->value, frame->data, buf_len); -+ -+ ath11k_ce_byte_swap(frame_tlv->value, buf_len); -+ -+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_QOS_NULL_FRAME_TX_SEND_CMDID); -+ if (ret) { -+ ath11k_warn(ar->ab, -+ "failed to submit WMI_QOS_NULL_FRAME_TX_SEND_CMDID cmd\n"); -+ dev_kfree_skb(skb); -+ } -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, -+ "wmi QOS null tx send cmd sent successfully\n"); -+ return ret; -+} -+ - int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr, - struct vdev_create_params *param) - { -@@ -5371,7 +5420,7 @@ static int ath11k_pull_mgmt_rx_params_tl - return 0; - } - --static int wmi_process_mgmt_tx_comp(struct ath11k *ar, struct wmi_mgmt_tx_compl_event *tx_compl_param) -+static int wmi_process_tx_comp(struct ath11k *ar, struct wmi_tx_compl_event *tx_compl_param) - { - struct sk_buff *msdu; - struct ieee80211_tx_info *info; -@@ -5441,12 +5493,13 @@ skip_mgmt_stats: - return 0; - } - --static int ath11k_pull_mgmt_tx_compl_param_tlv(struct ath11k_base *ab, -- struct sk_buff *skb, -- struct wmi_mgmt_tx_compl_event *param) -+static int ath11k_pull_tx_compl_param_tlv(struct ath11k_base *ab, -+ struct sk_buff *skb, -+ struct wmi_tx_compl_event *param, -+ int event_id) - { - const void **tb; -- const struct wmi_mgmt_tx_compl_event *ev; -+ const struct wmi_tx_compl_event *ev; - int ret; - - tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); -@@ -5456,7 +5509,7 @@ static int ath11k_pull_mgmt_tx_compl_par - return ret; - } - -- ev = tb[WMI_TAG_MGMT_TX_COMPL_EVENT]; -+ ev = tb[event_id]; - if (!ev) { - ath11k_warn(ab, "failed to fetch mgmt tx compl ev"); - kfree(tb); -@@ -6932,10 +6985,11 @@ exit: - - static void ath11k_mgmt_tx_compl_event(struct ath11k_base *ab, struct sk_buff *skb) - { -- struct wmi_mgmt_tx_compl_event tx_compl_param = {0}; -+ struct wmi_tx_compl_event tx_compl_param = {0}; - struct ath11k *ar; - -- if (ath11k_pull_mgmt_tx_compl_param_tlv(ab, skb, &tx_compl_param) != 0) { -+ if (ath11k_pull_tx_compl_param_tlv(ab, skb, &tx_compl_param, -+ WMI_TAG_MGMT_TX_COMPL_EVENT) != 0) { - ath11k_warn(ab, "failed to extract mgmt tx compl event"); - return; - } -@@ -6948,7 +7002,7 @@ static void ath11k_mgmt_tx_compl_event(s - goto exit; - } - -- wmi_process_mgmt_tx_comp(ar, &tx_compl_param); -+ wmi_process_tx_comp(ar, &tx_compl_param); - - ath11k_dbg(ab, ATH11K_DBG_MGMT, - "mgmt tx compl ev pdev_id %d, desc_id %d, status %d", -@@ -6959,6 +7013,36 @@ exit: - rcu_read_unlock(); - } - -+static void ath11k_qos_null_compl_event(struct ath11k_base *ab, struct sk_buff *skb) -+{ -+ struct wmi_tx_compl_event tx_compl_param = {0}; -+ struct ath11k *ar; -+ -+ if (ath11k_pull_tx_compl_param_tlv(ab, skb, &tx_compl_param, -+ WMI_TAG_QOS_NULL_FRAME_TX_STATUS) != 0) { -+ ath11k_warn(ab, "failed to extract qos null tx compl event"); -+ return; -+ } -+ -+ rcu_read_lock(); -+ ar = ath11k_mac_get_ar_by_pdev_id(ab, tx_compl_param.pdev_id); -+ if (!ar) { -+ ath11k_warn(ab, "invalid pdev id %d in qos_null_tx_compl_event\n", -+ tx_compl_param.pdev_id); -+ goto exit; -+ } -+ -+ wmi_process_tx_comp(ar, &tx_compl_param); -+ -+ ath11k_dbg(ab, ATH11K_DBG_WMI, -+ "QOS null tx compl ev pdev_id %d, desc_id %d, status %d", -+ tx_compl_param.pdev_id, tx_compl_param.desc_id, -+ tx_compl_param.status); -+ -+exit: -+ rcu_read_unlock(); -+} -+ - static struct ath11k *ath11k_get_ar_on_scan_abort(struct ath11k_base *ab, - u32 vdev_id) - { -@@ -7330,47 +7414,67 @@ static void ath11k_vdev_install_key_comp - rcu_read_unlock(); - } - --static void ath11k_service_available_event(struct ath11k_base *ab, struct sk_buff *skb) -+static int ath11k_wmi_tlv_services_parser(struct ath11k_base *ab, -+ u16 tag, u16 len, -+ const void *ptr, void *data) - { -- const void **tb; - const struct wmi_service_available_event *ev; -- int ret; -+ u32 *wmi_ext2_service_bitmap; - int i, j; - -- tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); -- if (IS_ERR(tb)) { -- ret = PTR_ERR(tb); -- ath11k_warn(ab, "failed to parse tlv: %d\n", ret); -- return; -- } -+ switch (tag) { -+ case WMI_TAG_SERVICE_AVAILABLE_EVENT: -+ ev = (struct wmi_service_available_event *)ptr; -+ for (i = 0, j = WMI_MAX_SERVICE; -+ i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE; -+ i++) { -+ do { -+ if (ev->wmi_service_segment_bitmap[i] & -+ BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) -+ set_bit(j, ab->wmi_ab.svc_map); -+ } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); -+ } - -- ev = tb[WMI_TAG_SERVICE_AVAILABLE_EVENT]; -- if (!ev) { -- ath11k_warn(ab, "failed to fetch svc available ev"); -- kfree(tb); -- return; -- } -+ ath11k_dbg(ab, ATH11K_DBG_WMI, -+ "wmi_ext_service_bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x", -+ ev->wmi_service_segment_bitmap[0], -+ ev->wmi_service_segment_bitmap[1], -+ ev->wmi_service_segment_bitmap[2], -+ ev->wmi_service_segment_bitmap[3]); - -- /* TODO: Use wmi_service_segment_offset information to get the service -- * especially when more services are advertised in multiple sevice -- * available events. -- */ -- for (i = 0, j = WMI_MAX_SERVICE; -- i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE; -- i++) { -- do { -- if (ev->wmi_service_segment_bitmap[i] & -- BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) -- set_bit(j, ab->wmi_ab.svc_map); -- } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); -+ break; -+ -+ case WMI_TAG_ARRAY_UINT32: -+ wmi_ext2_service_bitmap = (u32 *)ptr; -+ for (i = 0, j = WMI_MAX_EXT_SERVICE; -+ i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT2_SERVICE; -+ i++) { -+ do { -+ if (wmi_ext2_service_bitmap[i] & -+ BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) -+ set_bit(j, ab->wmi_ab.svc_map); -+ } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); -+ } -+ -+ ath11k_dbg(ab, ATH11K_DBG_WMI, -+ "wmi_ext2_service__bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x", -+ wmi_ext2_service_bitmap[0], wmi_ext2_service_bitmap[1], -+ wmi_ext2_service_bitmap[2], wmi_ext2_service_bitmap[3]); -+ -+ break; - } -+ return 0; -+} - -- ath11k_dbg(ab, ATH11K_DBG_WMI, -- "wmi_ext_service_bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x", -- ev->wmi_service_segment_bitmap[0], ev->wmi_service_segment_bitmap[1], -- ev->wmi_service_segment_bitmap[2], ev->wmi_service_segment_bitmap[3]); -+static void ath11k_service_available_event(struct ath11k_base *ab, struct sk_buff *skb) -+{ -+ int ret = 0; - -- kfree(tb); -+ ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len, -+ ath11k_wmi_tlv_services_parser, -+ NULL); -+ if (ret) -+ ath11k_warn(ab, "failed to parse services available tlv %d\n", ret); - } - - static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff *skb) -@@ -8439,6 +8543,9 @@ static void ath11k_wmi_tlv_op_rx(struct - case WMI_DIAG_EVENTID: - ath11k_wmi_diag_event(ab, skb); - break; -+ case WMI_QOS_NULL_FRAME_TX_COMPLETION_EVENTID: -+ ath11k_qos_null_compl_event(ab, skb); -+ break; - /* TODO: Add remaining events */ - default: - ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -358,6 +358,7 @@ enum wmi_tlv_cmd_id { - WMI_BCN_OFFLOAD_CTRL_CMDID, - WMI_BSS_COLOR_CHANGE_ENABLE_CMDID, - WMI_VDEV_BCN_OFFLOAD_QUIET_CONFIG_CMDID, -+ WMI_QOS_NULL_FRAME_TX_SEND_CMDID, - WMI_ADDBA_CLEAR_RESP_CMDID = WMI_TLV_CMD(WMI_GRP_BA_NEG), - WMI_ADDBA_SEND_CMDID, - WMI_ADDBA_STATUS_CMDID, -@@ -687,6 +688,8 @@ enum wmi_tlv_event_id { - WMI_MGMT_TX_COMPLETION_EVENTID, - WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID, - WMI_TBTTOFFSET_EXT_UPDATE_EVENTID, -+ WMI_HOST_SWBA_V2_EVENTID, -+ WMI_QOS_NULL_FRAME_TX_COMPLETION_EVENTID, - WMI_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_CMD(WMI_GRP_BA_NEG), - WMI_TX_ADDBA_COMPLETE_EVENTID, - WMI_BA_RSP_SSN_EVENTID, -@@ -1878,6 +1881,9 @@ enum wmi_tlv_tag { - /* TODO add all the missing cmds */ - WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301, - WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO, -+ /* TODO add all the missing cmds */ -+ WMI_TAG_QOS_NULL_FRAME_TX_SEND = 0x3A6, -+ WMI_TAG_QOS_NULL_FRAME_TX_STATUS, - WMI_TAG_MAX - }; - -@@ -2136,8 +2142,21 @@ enum wmi_tlv_service { - WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213, - WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, - WMI_TLV_SERVICE_EXT2_MSG = 220, -+ WMI_TLV_SERVICE_CONFIGURE_ROAM_TRIGGER_PARAM_SUPPORT = 254, -+ WMI_TLV_SERVICE_CFR_TA_RA_AS_FP_SUPPORT = 255, -+ WMI_MAX_EXT_SERVICE = 256, -+ -+ WMI_TLV_SERVICE_CFR_CAPTURE_COUNT_SUPPORT = 256, -+ WMI_TLV_SERVICE_OCV_SUPPORT = 257, -+ WMI_TLV_SERVICE_LL_STATS_PER_CHAN_RX_TX_TIME_SUPPORT = 258, -+ WMI_TLV_SERVICE_THERMAL_MULTI_CLIENT_SUPPORT = 259, -+ WMI_TLV_SERVICE_NAN_SEND_NAN_ENABLE_RESPONSE_TO_HOST = 260, -+ WMI_TLV_SERVICE_UNIFIED_LL_GET_STA_CMD_SUPPORT = 261, -+ WMI_TLV_SERVICE_FSE_CMEM_ALLOC_SUPPORT = 262, -+ WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263, -+ WMI_TLV_SERVICE_QOS_NULL_FRAME_TX_OVER_WMI = 264, - -- WMI_MAX_EXT_SERVICE -+ WMI_MAX_EXT2_SERVICE - }; - - enum wmi_unit_test_cmdid { -@@ -3823,6 +3842,7 @@ struct wmi_scan_chan_list_cmd { - } __packed; - - #define WMI_MGMT_SEND_DOWNLD_LEN 64 -+#define WMI_QOS_NULL_SEND_BUF_LEN 64 - - #define WMI_TX_PARAMS_DWORD0_POWER GENMASK(7, 0) - #define WMI_TX_PARAMS_DWORD0_MCS_MASK GENMASK(19, 8) -@@ -3833,9 +3853,10 @@ struct wmi_scan_chan_list_cmd { - #define WMI_TX_PARAMS_DWORD1_BW_MASK GENMASK(14, 8) - #define WMI_TX_PARAMS_DWORD1_PREAMBLE_TYPE GENMASK(19, 15) - #define WMI_TX_PARAMS_DWORD1_FRAME_TYPE BIT(20) --#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 21) -+#define WMI_TX_PARAMS_DWORD1_CFR_CAPTURE BIT(21) -+#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 22) - --struct wmi_mgmt_send_params { -+struct wmi_tx_send_params { - u32 tlv_header; - u32 tx_params_dword0; - u32 tx_params_dword1; -@@ -4606,7 +4627,7 @@ struct wmi_rssi_ctl_ext { - u32 rssi_ctl_ext[MAX_ANTENNA_EIGHT - ATH_MAX_ANTENNA]; - }; - --struct wmi_mgmt_tx_compl_event { -+struct wmi_tx_compl_event { - u32 desc_id; - u32 status; - u32 pdev_id; -@@ -5721,6 +5742,17 @@ enum ath11k_wmi_tpc_stats_ctl_array { - ATH11K_TPC_STATS_CTL_160ARRAY, - }; - -+struct wmi_qos_null_tx_cmd { -+ u32 tlv_header; -+ u32 vdev_id; -+ u32 desc_id; -+ u32 paddr_lo; -+ u32 paddr_hi; -+ u32 frame_len; -+ u32 buf_len; -+ u32 tx_params_valid; -+} __packed; -+ - #define WMI_MAX_MEM_REQS 32 - - #define MAX_RADIOS 3 -@@ -5736,7 +5768,7 @@ struct ath11k_wmi_base { - - struct completion service_ready; - struct completion unified_ready; -- DECLARE_BITMAP(svc_map, WMI_MAX_EXT_SERVICE); -+ DECLARE_BITMAP(svc_map, WMI_MAX_EXT2_SERVICE); - wait_queue_head_t tx_credits_wq; - const struct wmi_peer_flags_map *peer_flags; - u32 num_mem_chunks; -@@ -5917,6 +5949,8 @@ int ath11k_wmi_cmd_send(struct ath11k_pd - struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); - int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, - struct sk_buff *frame); -+int ath11k_wmi_qos_null_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, -+ struct sk_buff *frame); - int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, - struct ieee80211_mutable_offsets *offs, - struct sk_buff *bcn); diff --git a/package/kernel/mac80211/patches/nss/237-001-ath11k-Disable-unused-CE8-interrupts.patch b/package/kernel/mac80211/patches/nss/237-001-ath11k-Disable-unused-CE8-interrupts.patch deleted file mode 100644 index 68527785a..000000000 --- a/package/kernel/mac80211/patches/nss/237-001-ath11k-Disable-unused-CE8-interrupts.patch +++ /dev/null @@ -1,31 +0,0 @@ -From b71cab89b4be24528db1f4641825d2a0fd5f8efe Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Mon, 14 Dec 2020 19:05:02 +0530 -Subject: [PATCH] ath11k: Disable unused CE8 interrupts - -Host driver doesn't need to process CE8 interrupts (used -by target independently) - -The volume of interrupts is huge within short interval, - CPU0 CPU1 CPU2 CPU3 -14022188 0 0 0 GIC 71 Edge ce8 - -Hence disable these interrupts. - -Signed-off-by: Sriram R -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath11k/ce.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/wireless/ath/ath11k/ce.c -+++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -80,7 +80,7 @@ const struct ce_attr ath11k_host_ce_conf - - /* CE8: target autonomous hif_memcpy */ - { -- .flags = CE_ATTR_FLAGS, -+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, - .src_nentries = 0, - .src_sz_max = 0, - .dest_nentries = 0, diff --git a/package/kernel/mac80211/patches/nss/237-006-ath11k-Allow-fast-rx-by-bypassing-stats-update.patch b/package/kernel/mac80211/patches/nss/237-006-ath11k-Allow-fast-rx-by-bypassing-stats-update.patch deleted file mode 100644 index f5cc7f299..000000000 --- a/package/kernel/mac80211/patches/nss/237-006-ath11k-Allow-fast-rx-by-bypassing-stats-update.patch +++ /dev/null @@ -1,357 +0,0 @@ -From 594992a7ef169aa406e7fc025df2455af5d226be Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Tue, 15 Dec 2020 10:31:30 +0530 -Subject: [PATCH] ath11k: Allow fast rx by bypassing stats update - -Add a provision to disable stats and enable fast rx support -for a peer when it is connected to an AP with ethernet decap support. -All valid IP packets are directly passed to the net core stack -bypassing mac80211 stats update - -Signed-off-by: Sriram R -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath11k/core.h | 3 ++ - drivers/net/wireless/ath/ath11k/debugfs.c | 76 +++++++++++++++++++++++++++++++++ - drivers/net/wireless/ath/ath11k/dp.c | 45 +++++++++++++++++++ - drivers/net/wireless/ath/ath11k/dp_rx.c | 54 ++++++++++++++++++++--- - drivers/net/wireless/ath/ath11k/hw.c | 25 +++++++++++ - drivers/net/wireless/ath/ath11k/hw.h | 1 + - drivers/net/wireless/ath/ath11k/mac.c | 2 + - drivers/net/wireless/ath/ath11k/peer.h | 1 + - 8 files changed, 201 insertions(+), 6 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -123,6 +123,7 @@ struct ath11k_skb_rxcb { - u8 tid; - u16 peer_id; - u16 seq_no; -+ struct napi_struct *napi; - }; - - enum ath11k_hw_rev { -@@ -968,6 +969,7 @@ struct ath11k_base { - - struct ath11k_dbring_cap *db_caps; - u32 num_db_cap; -+ bool stats_disable; - - struct timer_list mon_reap_timer; - /* must be last */ ---- a/drivers/net/wireless/ath/ath11k/debugfs.c -+++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1463,6 +1463,79 @@ static const struct file_operations fops - .open = simple_open - }; - -+static void ath11k_debug_config_mon_status(struct ath11k *ar, bool enable) -+{ -+ struct htt_rx_ring_tlv_filter tlv_filter = {0}; -+ struct ath11k_base *ab = ar->ab; -+ int i; -+ u32 ring_id; -+ -+ if (enable) -+ tlv_filter = ath11k_mac_mon_status_filter_default; -+ -+ for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) { -+ ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id; -+ ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, -+ ar->dp.mac_id + i, -+ HAL_RXDMA_MONITOR_STATUS, -+ DP_RX_BUFFER_SIZE, -+ &tlv_filter); -+ } -+} -+ -+static ssize_t ath11k_write_stats_disable(struct file *file, -+ const char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath11k_base *ab = file->private_data; -+ struct ath11k_pdev *pdev; -+ bool disable; -+ int ret, i, radioup = 0; -+ u32 mask = 0; -+ -+ for (i = 0; i < ab->num_radios; i++) { -+ pdev = &ab->pdevs[i]; -+ if (pdev && pdev->ar) { -+ radioup = 1; -+ break; -+ } -+ } -+ -+ if (radioup == 0) { -+ ath11k_err(ab, "radio is not up\n"); -+ ret = -ENETDOWN; -+ goto exit; -+ } -+ -+ if (kstrtobool_from_user(user_buf, count, &disable)) -+ return -EINVAL; -+ -+ if (disable != ab->stats_disable) { -+ ab->stats_disable = disable; -+ for (i = 0; i < ab->num_radios; i++) { -+ pdev = &ab->pdevs[i]; -+ if (pdev && pdev->ar) { -+ ath11k_debug_config_mon_status(pdev->ar, !disable); -+ -+ if (!disable) -+ mask = HTT_PPDU_STATS_TAG_DEFAULT; -+ -+ ath11k_dp_tx_htt_h2t_ppdu_stats_req(pdev->ar, mask); -+ } -+ } -+ } -+ -+ ret = count; -+ -+exit: -+ return ret; -+} -+ -+static const struct file_operations fops_soc_stats_disable = { -+ .open = simple_open, -+ .write = ath11k_write_stats_disable, -+}; -+ - int ath11k_debugfs_register(struct ath11k *ar) - { - struct ath11k_base *ab = ar->ab; -@@ -1774,6 +1847,9 @@ int ath11k_debugfs_soc_create(struct ath - debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab, - &fops_soc_dp_stats); - -+ debugfs_create_file("stats_disable", 0600, ab->debugfs_soc, ab, -+ &fops_soc_stats_disable); -+ - return 0; - } - ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -352,6 +352,16 @@ static void ath11k_dp_rx_desc_get_crypto - ab->hw_params.hw_ops->rx_desc_get_crypto_header(desc, crypto_hdr, enctype); - } - -+static inline u8 ath11k_dp_rx_h_msdu_start_ip_valid(struct hal_rx_desc *desc) -+{ -+ bool ipv4, ipv6; -+ ipv4 = FIELD_GET(RX_MSDU_START_INFO2_IPV4, -+ __le32_to_cpu(desc->msdu_start.info2)); -+ ipv6 = FIELD_GET(RX_MSDU_START_INFO2_IPV6, -+ __le32_to_cpu(desc->msdu_start.info2)); -+ return (ipv4 || ipv6); -+} -+ - /* Returns number of Rx buffers replenished */ - int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id, - struct dp_rxdma_ring *rx_ring, -@@ -2479,10 +2485,60 @@ ath11k_dp_rx_h_find_peer(struct ath11k_b - return peer; - } - -+static bool ath11k_dp_rx_check_fast_rx(struct ath11k *ar, -+ struct sk_buff *msdu, -+ struct hal_rx_desc *rx_desc, -+ struct ath11k_peer *peer) -+{ -+ struct ethhdr *ehdr; -+ struct ath11k_peer *f_peer; -+ struct ath11k_skb_rxcb *rxcb; -+ u8 decap; -+ -+ lockdep_assert_held(&ar->ab->base_lock); -+ -+ decap = ath11k_dp_rx_h_msdu_start_decap_type(rx_desc); -+ rxcb = ATH11K_SKB_RXCB(msdu); -+ -+ if (!ar->ab->stats_disable || -+ decap != DP_RX_DECAP_TYPE_ETHERNET2_DIX || -+ peer->vif->type != NL80211_IFTYPE_AP) -+ return false; -+ -+ /* mcbc packets go through mac80211 for PN validation */ -+ if (rxcb->is_mcbc) -+ return false; -+ -+ if (!peer->is_authorized) -+ return false; -+ -+ if (!ath11k_dp_rx_h_msdu_start_ip_valid(rx_desc)) -+ return false; -+ -+ /* fast rx is supported only on ethernet decap, so -+ * we can directly gfet the ethernet header -+ */ -+ ehdr = (struct ethhdr *)msdu->data; -+ -+ /* requires rebroadcast from mac80211 */ -+ if (is_multicast_ether_addr(ehdr->h_dest)) -+ return false; -+ -+ /* check if the msdu needs to be bridged to our connected peer */ -+ f_peer = ath11k_peer_find_by_addr(ar->ab, ehdr->h_dest); -+ -+ if (f_peer && f_peer != peer) -+ return false; -+ -+ /* allow direct rx */ -+ return true; -+} -+ - static void ath11k_dp_rx_h_mpdu(struct ath11k *ar, - struct sk_buff *msdu, - struct hal_rx_desc *rx_desc, -- struct ieee80211_rx_status *rx_status) -+ struct ieee80211_rx_status *rx_status, -+ bool *fast_rx) - { - bool fill_crypto_hdr; - enum hal_encrypt_type enctype; -@@ -2492,6 +2548,7 @@ static void ath11k_dp_rx_h_mpdu(struct a - struct ath11k_peer *peer; - struct rx_attention *rx_attention; - u32 err_bitmap; -+ struct wireless_dev *wdev = NULL; - - /* PN for multicast packets will be checked in mac80211 */ - rxcb = ATH11K_SKB_RXCB(msdu); -@@ -2505,6 +2562,25 @@ static void ath11k_dp_rx_h_mpdu(struct a - spin_lock_bh(&ar->ab->base_lock); - peer = ath11k_dp_rx_h_find_peer(ar->ab, msdu); - if (peer) { -+ /* If the pkt is a valid IP packet and peer supports -+ * fast rx, deliver directly to net, also note that -+ * pkts with crypto error are not expected to arrive in this -+ * path, so its safe to skip checking errors here */ -+ if (*fast_rx && -+ ath11k_dp_rx_check_fast_rx(ar, msdu, rx_desc, peer)) { -+ wdev = ieee80211_vif_to_wdev(peer->vif); -+ if (wdev) { -+ spin_unlock_bh(&ar->ab->base_lock); -+ ath11k_dp_rx_h_csum_offload(msdu); -+ msdu->dev = wdev->netdev; -+ msdu->protocol = eth_type_trans(msdu, msdu->dev); -+ napi_gro_receive(rxcb->napi, msdu); -+ return; -+ } -+ } -+ -+ *fast_rx = false; -+ - if (rxcb->is_mcbc) - enctype = peer->sec_type_grp; - else -@@ -2766,7 +2842,8 @@ static void ath11k_dp_rx_deliver_msdu(st - static int ath11k_dp_rx_process_msdu(struct ath11k *ar, - struct sk_buff *msdu, - struct sk_buff_head *msdu_list, -- struct ieee80211_rx_status *rx_status) -+ struct ieee80211_rx_status *rx_status, -+ bool *fast_rx) - { - struct ath11k_base *ab = ar->ab; - struct hal_rx_desc *rx_desc, *lrx_desc; -@@ -2842,8 +2919,13 @@ static int ath11k_dp_rx_process_msdu(str - } - } - -+ ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status, fast_rx); -+ if (*fast_rx) { -+ ar->ab->soc_stats.invalid_rbm++; -+ return 0; -+ } -+ - ath11k_dp_rx_h_ppdu(ar, rx_desc, rx_status); -- ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status); - - rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED; - -@@ -2864,6 +2946,7 @@ static void ath11k_dp_rx_process_receive - struct ieee80211_rx_status rx_status = {0}; - u8 mac_id; - int ret; -+ bool fast_rx; - - if (skb_queue_empty(msdu_list)) - return; -@@ -2884,7 +2967,11 @@ static void ath11k_dp_rx_process_receive - continue; - } - -- ret = ath11k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status); -+ /* Enable fast rx by default, the value will cahnge based on peer cap -+ * and packet type */ -+ fast_rx = true; -+ rxcb->napi = napi; -+ ret = ath11k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status, &fast_rx); - if (ret) { - ath11k_dbg(ab, ATH11K_DBG_DATA, - "Unable to process msdu %d", ret); -@@ -2892,7 +2979,10 @@ static void ath11k_dp_rx_process_receive - continue; - } - -- ath11k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_status); -+ /* msdu is already delivered directectly */ -+ if (!fast_rx) -+ ath11k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_status); -+ - (*quota)--; - } - -@@ -4484,6 +4574,7 @@ static int ath11k_dp_rx_h_null_q_desc(st - struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data; - u8 l3pad_bytes; - struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); -+ bool fast_rx; - - msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(desc); - -@@ -4527,7 +4618,8 @@ static int ath11k_dp_rx_h_null_q_desc(st - } - ath11k_dp_rx_h_ppdu(ar, desc, status); - -- ath11k_dp_rx_h_mpdu(ar, msdu, desc, status); -+ fast_rx = false; -+ ath11k_dp_rx_h_mpdu(ar, msdu, desc, status, &fast_rx); - - rxcb->tid = ath11k_dp_rx_h_mpdu_start_tid(desc); - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -4873,6 +4873,20 @@ static int ath11k_mac_op_sta_state(struc - if (ret) - ath11k_warn(ar->ab, "Failed to disassociate station: %pM\n", - sta->addr); -+ } else if (old_state == IEEE80211_STA_AUTHORIZED && -+ new_state == IEEE80211_STA_ASSOC) { -+ spin_lock_bh(&ar->ab->base_lock); -+ peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr); -+ if (peer && peer->sta) -+ peer->is_authorized = false; -+ spin_unlock_bh(&ar->ab->base_lock); -+ } else if (old_state == IEEE80211_STA_ASSOC && -+ new_state == IEEE80211_STA_AUTHORIZED) { -+ spin_lock_bh(&ar->ab->base_lock); -+ peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr); -+ if (peer && peer->sta) -+ peer->is_authorized = true; -+ spin_unlock_bh(&ar->ab->base_lock); - } - - mutex_unlock(&ar->conf_mutex); ---- a/drivers/net/wireless/ath/ath11k/peer.h -+++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -91,6 +91,7 @@ struct ath11k_peer { - u8 ucast_keyidx; - u16 sec_type; - u16 sec_type_grp; -+ bool is_authorized; - }; - - void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);