wlan-ap-Telecominfraproject/feeds/wifi-ax/mac80211/patches/qca/199-003-ath11k-add-nss-support.patch
John Crispin 528a778e38 open-converged-wireless: Import 21.02 based uCentral tree
Signed-off-by: John Crispin <john@phrozen.org>
2021-03-25 12:19:47 +01:00

909 lines
29 KiB
Diff

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/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -440,6 +440,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];
@@ -452,20 +458,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))
@@ -483,7 +489,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);
@@ -653,6 +659,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
@@ -13,14 +13,21 @@
#include "dp_rx.h"
#include "debug.h"
#include "hif.h"
+#include "nss.h"
unsigned int ath11k_debug_mask;
unsigned int cryptmode;
EXPORT_SYMBOL(ath11k_debug_mask);
+unsigned int nss_offload;
+
module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);
module_param_named(cryptmode, cryptmode, uint, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(cryptmode, "crypto mode: 0-hardware, 1-software");
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
+module_param_named(nss_offload, nss_offload, uint, 0644);
+MODULE_PARM_DESC(nss_offload, "Enable NSS Offload support");
+#endif
extern unsigned int ath11k_frame_mode;
@@ -490,23 +497,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);
@@ -519,10 +533,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_debug_pdev_destroy(ab);
@@ -534,6 +550,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_debug_pdev_destroy(ab);
@@ -773,6 +793,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);
@@ -987,6 +1011,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;
}
@@ -1031,7 +1057,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 "spectral.h"
#include "vendor.h"
#include "rx_desc.h"
+#include "nss.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -249,6 +250,9 @@ struct ath11k_vif {
struct ieee80211_chanctx_conf chanctx;
struct dentry *debugfs_twt;
struct ath11k_mgmt_frame_stats mgmt_stats;
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
+ struct arvif_nss nss;
+#endif
};
struct ath11k_vif_iter {
@@ -396,6 +400,9 @@ struct ath11k_sta {
#endif
bool use_4addr_set;
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
+ struct ath11k_nss_sta_stats *nss_stats;
+#endif
};
#define ATH11K_MIN_5G_FREQ 4150
@@ -512,6 +519,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;
@@ -751,8 +761,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 {
@@ -970,7 +982,7 @@ extern const struct service_to_pipe ath1
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,
--- 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) {
@@ -733,14 +750,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;
@@ -748,7 +769,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);
@@ -759,7 +780,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);
@@ -793,7 +814,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
@@ -164,6 +164,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
@@ -15,6 +15,7 @@
#include "hal_rx.h"
#include "dp_tx.h"
#include "peer.h"
+#include "nss.h"
#define ATH11K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ)
@@ -194,8 +195,8 @@ static u8 ath11k_dp_rx_h_mpdu_start_tid(
return ab->hw_params.hw_ops->rx_desc_get_mpdu_tid(desc);
}
-static u16 ath11k_dp_rx_h_mpdu_start_peer_id(struct ath11k_base *ab,
- struct hal_rx_desc *desc)
+u16 ath11k_dp_rx_h_mpdu_start_peer_id(struct ath11k_base *ab,
+ struct hal_rx_desc *desc)
{
return ab->hw_params.hw_ops->rx_desc_get_mpdu_peer_id(desc);
}
@@ -206,8 +207,8 @@ static u8 ath11k_dp_rx_h_msdu_end_l3pad(
return ab->hw_params.hw_ops->rx_desc_get_l3_pad_bytes(desc);
}
-static bool ath11k_dp_rx_h_msdu_end_first_msdu(struct ath11k_base *ab,
- struct hal_rx_desc *desc)
+bool ath11k_dp_rx_h_msdu_end_first_msdu(struct ath11k_base *ab,
+ struct hal_rx_desc *desc)
{
return ab->hw_params.hw_ops->rx_desc_get_first_msdu(desc);
}
@@ -263,7 +264,7 @@ static void ath11k_dp_rxdesc_set_msdu_le
ab->hw_params.hw_ops->rx_desc_set_msdu_len(desc, len);
}
-static bool ath11k_dp_rx_h_attn_is_mcbc(struct ath11k_base *ab,
+bool ath11k_dp_rx_h_attn_is_mcbc(struct ath11k_base *ab,
struct hal_rx_desc *desc)
{
struct rx_attention *attn = ath11k_dp_rx_get_attention(ab, desc);
@@ -468,7 +469,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;
@@ -1755,6 +1758,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);
@@ -1775,7 +1779,8 @@ 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,
@@ -1788,7 +1793,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:
@@ -1979,7 +1987,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) {
@@ -2006,7 +2014,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) {
@@ -2034,7 +2042,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) {
@@ -3402,7 +3410,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;
@@ -3482,6 +3490,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
@@ -114,4 +114,16 @@ int ath11k_dp_rx_pdev_mon_detach(struct
int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar);
int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id);
+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 ath11k_base *ab,
+ struct hal_rx_desc *desc);
+bool ath11k_dp_rx_h_attn_is_mcbc(struct ath11k_base *ab,
+ struct hal_rx_desc *desc);
+u16 ath11k_dp_rx_h_mpdu_start_peer_id(struct ath11k_base *ab,
+ 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
@@ -401,6 +401,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
@@ -801,14 +801,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);
@@ -822,6 +826,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
@@ -16,6 +16,7 @@
#include "testmode.h"
#include "peer.h"
#include "vendor.h"
+#include "nss.h"
#define CHAN2G(_channel, _freq, _flags) { \
.band = NL80211_BAND_2GHZ, \
@@ -1124,6 +1125,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",
@@ -1166,6 +1172,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);
}
@@ -2324,6 +2336,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,
@@ -2348,6 +2366,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);
@@ -2423,6 +2445,28 @@ static void ath11k_recalculate_mgmt_rate
ath11k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret);
}
+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,
@@ -3168,6 +3212,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) {
@@ -4899,7 +4953,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);
@@ -4924,6 +4981,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_debug_rx_filter(ar))
tlv_filter.rx_filter = ath11k_debug_rx_filter(ar);
}
@@ -5253,6 +5312,12 @@ static int ath11k_mac_op_add_interface(s
list_add(&arvif->list, &ar->arvifs);
spin_unlock_bh(&ar->data_lock);
+ ret = ath11k_nss_vdev_create(arvif);
+ if(ret) {
+ ath11k_warn(ab, "failed to create nss vdev %d\n", ret);
+ goto err_vdev_del;
+ }
+
param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET)
switch (vif->type) {
@@ -5281,6 +5346,13 @@ static int ath11k_mac_op_add_interface(s
goto err_vdev_del;
}
+ 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;
+ }
+
/* Do not enable ethernet mode for mesh vifs, packets in mesh network
* can be forwarded to other mesh nodes and mac80211 expects the packet
* in 802.11 format. Also, please note that ethernet mode shall not be
@@ -5300,6 +5372,18 @@ static int ath11k_mac_op_add_interface(s
arvif->vdev_id, ret);
goto err_vdev_del;
}
+ } else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
+ param_value = ATH11K_HW_TXRX_RAW;
+ /* wmi vdev decap commands not required as it is set during wmi init */
+ } else {
+ param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
+ /* wmi vdev decap commands not required as it is set during wmi init */
+ }
+
+ 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;
@@ -5428,6 +5512,7 @@ err_peer_del:
}
err_vdev_del:
+ ath11k_nss_vdev_delete(arvif);
ath11k_mac_vdev_delete(arvif);
spin_lock_bh(&ar->data_lock);
@@ -5472,6 +5557,8 @@ static void ath11k_mac_op_remove_interfa
arvif->vdev_id, ret);
}
+ ath11k_nss_vdev_delete(arvif);
+
ret = ath11k_mac_vdev_delete(arvif);
if (ret)
goto err_vdev_del;
@@ -5871,6 +5958,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",
@@ -5913,6 +6004,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 */
@@ -6919,6 +7014,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;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
+
+ ath11k_nss_update_sta_stats(sinfo, sta, arsta);
}
#define ATH11K_WLAN_PRIO_MAX 0x63
@@ -7015,6 +7112,7 @@ static const struct ieee80211_ops ath11k
.remove_interface = ath11k_mac_op_remove_interface,
.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,
@@ -7453,6 +7551,9 @@ static int __ath11k_mac_register(struct
ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
}
+ 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)
@@ -115,7 +116,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;
@@ -129,9 +130,12 @@ 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);
+ 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",
@@ -221,6 +225,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,
--- a/drivers/net/wireless/ath/ath11k/peer.h
+++ b/drivers/net/wireless/ath/ath11k/peer.h
@@ -26,6 +26,10 @@ struct ath11k_peer {
int peer_id;
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];
@@ -46,7 +50,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,
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -591,6 +591,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] ||
@@ -814,6 +819,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/debug.c
+++ b/drivers/net/wireless/ath/ath11k/debug.c
@@ -1019,6 +1019,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
@@ -9,7 +9,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
@@ -134,6 +134,7 @@ ATH10K_DFS_CERTIFIED=
ATH11K=
ATH11K_AHB=
ATH11K_PCI=
+ATH11K_NSS_SUPPORT=
ATH11K_DEBUG=
ATH11K_DEBUGFS=
ATH11K_TRACING=