mac80211: remove ath11k nss code temporality

This commit is contained in:
coolsnowwolf 2021-06-29 22:24:20 +08:00
parent 3e0302e832
commit 87d72cae64
13 changed files with 4 additions and 5675 deletions

View File

@ -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))
$(eval $(call KernelPackage,mac80211))

View File

@ -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

View File

@ -1,151 +0,0 @@
From 4b965be536eefdd16ca0a88120fee23f5b92cd16 Mon Sep 17 00:00:00 2001
From: Karthikeyan Periyasamy <periyasa@codeaurora.org>
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 <periyasa@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
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,

View File

@ -1,36 +0,0 @@
From cf8480d338a1b9156121e5e035e6b9721db4332a Mon Sep 17 00:00:00 2001
From: Karthikeyan Periyasamy <periyasa@codeaurora.org>
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 <periyasa@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
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);

View File

@ -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[] = {
{

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -1,430 +0,0 @@
From 193bfea2185a0ee976f54812e41ace77e6ee85e4 Mon Sep 17 00:00:00 2001
From: Sriram R <srirrama@codeaurora.org>
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 <srirrama@codeaurora.org>
---
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,

View File

@ -1,881 +0,0 @@
From 65c511e3aeb9afb84a3c6c8ac34353af91b880e9 Mon Sep 17 00:00:00 2001
From: Sriram R <srirrama@codeaurora.org>
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 <srirrama@codeaurora.org>
---
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=

View File

@ -1,473 +0,0 @@
From 0e29b669153f100b60107d5f6b3fe407b71ba79a Mon Sep 17 00:00:00 2001
From: Sowmiya Sree Elavalagan <ssreeela@codeaurora.org>
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 <ssreeela@codeaurora.org>
---
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);

View File

@ -1,31 +0,0 @@
From b71cab89b4be24528db1f4641825d2a0fd5f8efe Mon Sep 17 00:00:00 2001
From: P Praneesh <ppranees@codeaurora.org>
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 <srirrama@codeaurora.org>
Signed-off-by: P Praneesh <ppranees@codeaurora.org>
---
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,

View File

@ -1,357 +0,0 @@
From 594992a7ef169aa406e7fc025df2455af5d226be Mon Sep 17 00:00:00 2001
From: P Praneesh <ppranees@codeaurora.org>
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 <srirrama@codeaurora.org>
Signed-off-by: P Praneesh <ppranees@codeaurora.org>
---
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);