openwrt-ipq-breeze303/package/kernel/mac80211/patches/nss/ath11k/199-003-ath11k-add-nss-support.patch
Sean Khan db9ba5cdb1 ath11k_nss: Organize patch order and formatting
NSS patches should always get applied last as to avoid fuzzing issues
with upstream patches.

Also cleanup patches that introduced spaces as indents vs. tabs

Signed-off-by: Sean Khan <datapronix@protonmail.com>

ath11k_nss: drop upstreamed patch

A variation of this patch 'wifi: mac80211: Use flexible array in struct ieee80211_tim_ie'
was upstreamed in commit 'e6e4d90b69027d74ba7e9a0a586b95a5714e10c0'.
Remove it to avoid compilation issues.

Signed-off-by: Sean Khan <datapronix@protonmail.com>

ath11k_nss: Fix patch conflict

Signed-off-by: Sean Khan <datapronix@protonmail.com>
2024-10-11 19:19:08 -04:00

1211 lines
37 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
@@ -525,6 +525,12 @@ static int ath11k_ahb_config_ext_irq(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];
@@ -537,20 +543,20 @@ static int ath11k_ahb_config_ext_irq(str
ath11k_ahb_ext_grp_napi_poll);
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))
@@ -563,7 +569,7 @@ static int ath11k_ahb_config_ext_irq(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);
@@ -904,6 +910,7 @@ static int ath11k_ahb_setup_resources(st
}
ab->mem = mem;
+ ab->mem_pa = mem_res->start;
ab->mem_len = resource_size(mem_res);
return 0;
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -17,6 +17,12 @@
#include "hif.h"
#include "wow.h"
+unsigned int nss_offload;
+#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);
@@ -1528,10 +1534,16 @@ static int ath11k_core_pdev_create(struc
goto err_pdev_debug;
}
+ ret = ath11k_nss_setup(ab);
+ if (ret) {
+ 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_dp_pdev_free;
+ goto err_nss_tear;
}
ret = ath11k_thermal_register(ab);
@@ -1553,6 +1565,8 @@ err_thermal_unregister:
ath11k_thermal_unregister(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:
@@ -1566,6 +1580,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);
@@ -1772,6 +1790,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);
@@ -2095,6 +2117,10 @@ 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;
+
+ if (nss_offload)
+ ab->nss.stats_enabled = 1;
return 0;
}
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -30,6 +30,7 @@
#include "spectral.h"
#include "wow.h"
#include "rx_desc.h"
+#include "nss.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -384,6 +385,9 @@ struct ath11k_vif {
#endif /* CPTCFG_ATH11K_DEBUGFS */
struct ath11k_mgmt_frame_stats mgmt_stats;
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
+ struct arvif_nss nss;
+#endif
};
struct ath11k_vif_iter {
@@ -537,6 +541,9 @@ struct ath11k_sta {
#endif
bool use_4addr_set;
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
+ struct ath11k_nss_sta_stats *nss_stats;
+#endif
u16 tcl_metadata;
/* Protected with ar->data_lock */
@@ -632,6 +639,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];
struct ath11k_he ar_he;
@@ -892,9 +902,11 @@ struct ath11k_base {
struct ath11k_htc htc;
struct ath11k_dp dp;
+ struct ath11k_soc_nss nss;
void __iomem *mem;
void __iomem *mem_ce;
+ 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
@@ -47,12 +47,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",
@@ -132,6 +137,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 == DP_RX_RELEASE_RING_NUM) {
@@ -778,14 +795,16 @@ int ath11k_dp_service_srng(struct ath11k
int work_done = 0;
int i, j;
int tot_work_done = 0;
+ bool nss_offload;
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
- if (BIT(ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num) &
- ab->hw_params.ring_mask->tx[grp_id])
- ath11k_dp_tx_completion_handler(ab, i);
+ nss_offload = ab->nss.enabled;
+
+ if (!nss_offload && ab->hw_params.ring_mask->tx[grp_id]) {
+ i = __fls(ab->hw_params.ring_mask->tx[grp_id]);
+ ath11k_dp_tx_completion_handler(ab, 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;
@@ -793,7 +812,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);
@@ -804,7 +823,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);
@@ -838,7 +857,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
@@ -194,6 +194,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)
@@ -213,8 +214,8 @@ static inline u8 ath11k_dp_rx_h_mpdu_sta
return ab->hw_params.hw_ops->rx_desc_get_mpdu_tid(desc);
}
-static inline 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);
}
@@ -225,8 +226,8 @@ static inline u8 ath11k_dp_rx_h_msdu_end
return ab->hw_params.hw_ops->rx_desc_get_l3_pad_bytes(desc);
}
-static inline 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);
}
@@ -283,7 +284,7 @@ static inline void ath11k_dp_rxdesc_set_
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);
@@ -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;
@@ -2035,7 +2038,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) {
@@ -2062,7 +2065,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) {
@@ -2090,7 +2093,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) {
@@ -2826,6 +2829,22 @@ static void ath11k_dp_rx_process_receive
}
}
+void ath11k_dp_rx_from_nss(struct ath11k *ar, struct sk_buff *msdu,
+ struct napi_struct *napi)
+{
+ struct ieee80211_rx_status rx_status = {0};
+ struct ath11k_skb_rxcb *rxcb;
+
+ rxcb = ATH11K_SKB_RXCB(msdu);
+
+ ath11k_dp_rx_h_ppdu(ar, rxcb->rx_desc, &rx_status);
+ ath11k_dp_rx_h_mpdu(ar, msdu, rxcb->rx_desc, &rx_status);
+
+ rx_status.flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
+
+ ath11k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_status);
+}
+
int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
struct napi_struct *napi, int budget)
{
@@ -3133,6 +3152,13 @@ static void ath11k_dp_rx_update_user_sta
arsta = (struct ath11k_sta *)peer->sta->drv_priv;
rx_stats = arsta->rx_stats;
+ if (ar->ab->nss.enabled)
+ ath11k_nss_update_sta_rxrate(ppdu_info, peer, user_stats);
+
+ /* we've updated rate stats dont update dp rx stats if not enabled */
+ if (!ath11k_debugfs_is_extd_rx_stats_enabled(ar))
+ return;
+
if (!rx_stats)
return;
@@ -3209,8 +3235,10 @@ static void ath11k_dp_rx_update_peer_mu_
{
u32 num_users, i;
- if (!ath11k_debugfs_is_extd_rx_stats_enabled(ar))
+ if (!ar->ab->nss.enabled &&
+ !ath11k_debugfs_is_extd_rx_stats_enabled(ar)) {
return;
+ }
num_users = ppdu_info->num_users;
if (num_users > HAL_MAX_UL_MU_USERS)
@@ -5613,7 +5641,7 @@ int ath11k_dp_rx_process_mon_status(stru
struct sk_buff *skb;
struct sk_buff_head skb_list;
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;
@@ -5681,6 +5709,7 @@ int ath11k_dp_rx_process_mon_status(stru
if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
arsta = (struct ath11k_sta *)peer->sta->drv_priv;
ath11k_dp_rx_update_peer_su_stats(arsta, ppdu_info);
+ ath11k_nss_update_sta_rxrate(ppdu_info, peer, NULL);
} else {
ath11k_dp_rx_mon_process_ulofdma(ppdu_info);
ath11k_dp_rx_update_peer_mu_stats(ar, ppdu_info);
--- a/drivers/net/wireless/ath/ath11k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.h
@@ -145,4 +145,18 @@ 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 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);
+void ath11k_dp_rx_from_nss(struct ath11k *ar, struct sk_buff *msdu,
+ struct napi_struct *napi);
#endif /* ATH11K_DP_RX_H */
--- a/drivers/net/wireless/ath/ath11k/hal.h
+++ b/drivers/net/wireless/ath/ath11k/hal.h
@@ -424,6 +424,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
@@ -938,6 +938,12 @@ ath11k_hal_rx_parse_mon_status_tlv(struc
ppdu_info->num_mpdu_fcs_err =
FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR,
info0);
+
+ if (ppdu_info->fc_valid)
+ ppdu_info->frame_control =
+ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO2_FRAME_CTRL,
+ __le32_to_cpu(eu_stats->info2));
+
switch (ppdu_info->preamble_type) {
case HAL_RX_PREAMBLE_11N:
ppdu_info->ht_flags = 1;
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -24,6 +24,7 @@
#include "debugfs_sta.h"
#include "hif.h"
#include "wow.h"
+#include "nss.h"
#define CHAN2G(_channel, _freq, _flags) { \
.band = NL80211_BAND_2GHZ, \
@@ -1603,6 +1604,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",
@@ -1642,6 +1648,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, "vdev %d up\n", arvif->vdev_id);
}
@@ -3075,6 +3087,12 @@ static void ath11k_bss_assoc(struct ieee
"vdev %d up (associated) bssid %pM aid %d\n",
arvif->vdev_id, bss_conf->bssid, vif->cfg.aid);
+ ret = ath11k_nss_vdev_up(arvif);
+ if(ret) {
+ ath11k_warn(ar->ab, "failure in nss vdev up %d\r\n",ret);
+ return;
+ }
+
spin_lock_bh(&ar->ab->base_lock);
peer = ath11k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid);
@@ -3117,6 +3135,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, "vdev %i disassoc bssid %pM\n",
arvif->vdev_id, arvif->bssid);
@@ -3397,6 +3419,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, ATH11K_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,
@@ -4295,6 +4339,26 @@ 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, ATH11K_NSS_WIFI_VDEV_SECURITY_TYPE_CMD, key->cipher);
+ if (ret) {
+ ath11k_warn(ab, "failure to set vdev security type in nss");
+ goto unlock;
+ }
+
+ ret = ath11k_nss_set_peer_sec_type(ar, peer, key);
+ if (ret) {
+ ath11k_warn(ab, "failure to set peer security type in nss");
+ goto unlock;
+ }
+
+ ret = ath11k_nss_set_peer_authorize(ar, peer->peer_id);
+ if (ret) {
+ ath11k_warn(ab, "failure to authorize peer in nss");
+ goto unlock;
+ }
+
if (peer && cmd == SET_KEY) {
peer->keys[key->keyidx] = key;
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
@@ -4333,9 +4397,8 @@ static int ath11k_mac_op_set_key(struct
break;
}
}
-
+unlock:
spin_unlock_bh(&ab->base_lock);
-
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
@@ -6216,10 +6279,14 @@ static void ath11k_mac_op_tx(struct ieee
if (control->sta)
arsta = ath11k_sta_to_arsta(control->sta);
- ret = ath11k_dp_tx(ar, arvif, arsta, skb);
+ if (ar->ab->nss.enabled)
+ ret = ath11k_nss_tx(arvif, skb);
+ else
+ ret = ath11k_dp_tx(ar, arvif, arsta, skb);
if (unlikely(ret)) {
ath11k_warn(ar->ab, "failed to transmit frame %d\n", ret);
ieee80211_free_txskb(ar->hw, skb);
+ return;
}
}
@@ -6241,6 +6308,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);
}
@@ -6539,7 +6608,7 @@ static int ath11k_mac_setup_vdev_create_
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;
@@ -6585,6 +6654,8 @@ static void ath11k_mac_op_update_vif_off
arvif->vdev_id, ret);
vif->offload_flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;
}
+
+ return ret;
}
static bool ath11k_mac_vif_ap_active_any(struct ath11k_base *ab)
@@ -6715,6 +6786,8 @@ static int ath11k_mac_vdev_delete(struct
reinit_completion(&ar->vdev_delete_done);
+ ath11k_nss_vdev_delete(arvif);
+
ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
if (ret) {
ath11k_warn(ar->ab, "failed to delete WMI vdev %d: %d\n",
@@ -6855,7 +6928,34 @@ 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);
+ ret = ath11k_nss_vdev_create(arvif);
+ if(ret) {
+ ath11k_warn(ab, "failed to create nss vdev %d\n", ret);
+ goto err_vdev_del;
+ }
+
+ 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, ATH11K_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, ATH11K_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,
@@ -6979,6 +7079,7 @@ err_peer_del:
}
err_vdev_del:
+ ath11k_nss_vdev_delete(arvif);
ath11k_mac_vdev_delete(ar, arvif);
spin_lock_bh(&ar->data_lock);
list_del(&arvif->list);
@@ -7489,6 +7590,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 */
@@ -8717,6 +8822,8 @@ static void ath11k_mac_op_sta_statistics
sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) +
ATH11K_DEFAULT_NOISE_FLOOR;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
+
+ ath11k_nss_update_sta_stats(sinfo, sta, arsta);
}
#if IS_ENABLED(CONFIG_IPV6)
@@ -9144,6 +9251,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,
@@ -9530,7 +9638,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;
@@ -9645,6 +9754,9 @@ static int __ath11k_mac_register(struct
ab->hw_params.bios_sar_capa)
ar->hw->wiphy->sar_capa = ab->hw_params.bios_sar_capa;
+ 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
@@ -7,6 +7,7 @@
#include "core.h"
#include "peer.h"
#include "debug.h"
+#include "nss.h"
static struct ath11k_peer *ath11k_peer_find_list_by_id(struct ath11k_base *ab,
int peer_id)
@@ -150,6 +151,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, "peer map vdev %d peer %pM id %d\n",
@@ -312,17 +315,13 @@ static int __ath11k_peer_delete(struct a
lockdep_assert_held(&ar->conf_mutex);
+ reinit_completion(&ar->peer_delete_done);
+ ath11k_nss_peer_delete(ar->ab, addr);
+
mutex_lock(&ab->tbl_mtx_lock);
spin_lock_bh(&ab->base_lock);
peer = ath11k_peer_find_by_addr(ab, addr);
- /* Check if the found peer is what we want to remove.
- * While the sta is transitioning to another band we may
- * have 2 peer with the same addr assigned to different
- * vdev_id. Make sure we are deleting the correct peer.
- */
- if (peer && peer->vdev_id == vdev_id)
- ath11k_peer_rhash_delete(ab, peer);
/* Fallback to peer list search if the correct peer can't be found.
* Skip the deletion of the peer from the rhash since it has already
@@ -341,10 +340,17 @@ static int __ath11k_peer_delete(struct a
return -EINVAL;
}
+ /* Check if the found peer is what we want to remove.
+ * While the sta is transitioning to another band we may
+ * have 2 peer with the same addr assigned to different
+ * vdev_id. Make sure we are deleting the correct peer.
+ */
+ if (peer && peer->vdev_id == vdev_id)
+ ath11k_peer_rhash_delete(ab, peer);
+
spin_unlock_bh(&ab->base_lock);
mutex_unlock(&ab->tbl_mtx_lock);
- reinit_completion(&ar->peer_delete_done);
ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id);
if (ret) {
--- a/drivers/net/wireless/ath/ath11k/peer.h
+++ b/drivers/net/wireless/ath/ath11k/peer.h
@@ -28,6 +28,7 @@ struct ath11k_peer {
u16 ast_hash;
u8 pdev_idx;
u16 hw_peer_id;
+ struct ath11k_nss_peer nss;
/* 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
@@ -570,6 +570,7 @@ static int ath11k_pci_claim(struct ath11
}
ab->mem_ce = ab->mem;
+ ab->mem_pa = pci_resource_start(pdev, ATH11K_PCI_BAR_NUM);
ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci_mem 0x%p\n", ab->mem);
return 0;
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -10,11 +10,10 @@
#include "core.h"
#include "debug.h"
#include "wmi.h"
-#include "hal_rx.h"
#include "dp_tx.h"
#include "debugfs_htt_stats.h"
-#include "peer.h"
#include "hif.h"
+#include "qmi.h"
struct dentry *debugfs_ath11k;
@@ -665,6 +664,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;
@@ -1687,6 +1687,76 @@ static const struct file_operations fops
.open = simple_open
};
+
+static ssize_t ath11k_write_nss_stats(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath11k *ar = file->private_data;
+ struct ath11k_base *ab = ar->ab;
+ u8 nss_stats;
+ int ret;
+
+ if (!ab->nss.enabled) {
+ ath11k_warn(ab, "nss offload not enabled\n");
+ return -EINVAL;
+ }
+
+ if (kstrtou8_from_user(ubuf, count, 0, &nss_stats))
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH11K_STATE_ON) {
+ ret = -ENETDOWN;
+ goto out;
+ }
+
+ if (nss_stats == ab->nss.stats_enabled) {
+ ret = count;
+ goto out;
+ }
+
+ if (nss_stats > 0) {
+ ab->nss.stats_enabled = 1;
+ ath11k_nss_peer_stats_enable(ar);
+ } else {
+ ab->nss.stats_enabled = 0;
+ ath11k_nss_peer_stats_disable(ar);
+ }
+
+ ret = count;
+out:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static ssize_t ath11k_read_nss_stats(struct file *file,
+ char __user *ubuf,
+ size_t count, loff_t *ppos)
+
+{
+ char buf[32] = {0};
+ struct ath11k *ar = file->private_data;
+ struct ath11k_base *ab = ar->ab;
+ int len = 0;
+
+ mutex_lock(&ar->conf_mutex);
+ len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
+ ab->nss.stats_enabled);
+ mutex_unlock(&ar->conf_mutex);
+
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_nss_stats = {
+ .read = ath11k_read_nss_stats,
+ .write = ath11k_write_nss_stats,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath11k_debugfs_register(struct ath11k *ar)
{
struct ath11k_base *ab = ar->ab;
@@ -1753,6 +1823,11 @@ int ath11k_debugfs_register(struct ath11
&fops_reset_ps_duration);
}
+ if (ab->nss.enabled)
+ debugfs_create_file("nss_peer_stats_config", 0644,
+ ar->debug.debugfs_pdev, ar,
+ &fops_nss_stats);
+
return 0;
}
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -12,7 +12,7 @@
#include "peer.h"
#include "mac.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
@@ -38,6 +38,8 @@ 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);
int ath11k_dp_tx_htt_rx_full_mon_setup(struct ath11k_base *ab, int mac_id,
bool config);
--- a/drivers/net/wireless/ath/ath11k/nss.c
+++ b/drivers/net/wireless/ath/ath11k/nss.c
@@ -8,6 +8,8 @@
#include "nss.h"
#include "core.h"
#include "peer.h"
+#include "dp_rx.h"
+#include "dp_tx.h"
#include "hif.h"
#include "wmi.h"
#include "../../../../../net/mac80211/sta_info.h"
@@ -466,7 +468,7 @@ deliver_amsdu:
/* create list containing all the subframes */
ieee80211_amsdu_to_8023s(skb, &subframe_list, NULL,
- vif->type, 0, NULL, NULL);
+ vif->type, 0, NULL, NULL, 0);
/* This shouldn't happen, indicating error during defragmentation */
if (skb_queue_empty(&subframe_list))
@@ -661,12 +663,14 @@ drop:
return -EINVAL;
}
-int ath11k_nss_vdev_set_cmd(struct ath11k_vif *arvif, int cmd, int val)
+int ath11k_nss_vdev_set_cmd(struct ath11k_vif *arvif, enum ath11k_nss_vdev_cmd nss_cmd,
+ int val)
{
struct nss_wifi_vdev_msg *vdev_msg = NULL;
struct nss_wifi_vdev_cmd_msg *vdev_cmd;
struct ath11k *ar = arvif->ar;
nss_tx_status_t status;
+ int cmd;
if (!ar->ab->nss.enabled)
return 0;
@@ -679,6 +683,22 @@ int ath11k_nss_vdev_set_cmd(struct ath11
if (!vdev_msg)
return -ENOMEM;
+ switch(nss_cmd) {
+ case ATH11K_NSS_WIFI_VDEV_CFG_AP_BRIDGE_CMD:
+ cmd = NSS_WIFI_VDEV_CFG_AP_BRIDGE_CMD;
+ break;
+ case ATH11K_NSS_WIFI_VDEV_SECURITY_TYPE_CMD:
+ cmd = NSS_WIFI_VDEV_SECURITY_TYPE_CMD;
+ break;
+ case ATH11K_NSS_WIFI_VDEV_ENCAP_TYPE_CMD:
+ cmd = NSS_WIFI_VDEV_ENCAP_TYPE_CMD;
+ break;
+ case ATH11K_NSS_WIFI_VDEV_DECAP_TYPE_CMD:
+ cmd = NSS_WIFI_VDEV_DECAP_TYPE_CMD;
+ break;
+ default:
+ return -EINVAL;
+ }
/* TODO: Convert to function for conversion in case of many
* such commands
*/
@@ -1140,7 +1160,6 @@ void ath11k_nss_update_sta_stats(struct
{
struct sta_info *stainfo;
struct ath11k_peer *peer;
- int tid_idx;
struct ath11k *ar = arsta->arvif->ar;
struct ath11k_base *ab = ar->ab;
@@ -1234,6 +1253,9 @@ void ath11k_nss_update_sta_rxrate(struct
if (!ab->nss.enabled)
return;
+ if (!ieee80211_is_data(__cpu_to_le16(ppdu_info->frame_control)))
+ return;
+
if (!peer->nss.nss_stats)
return;
@@ -1293,7 +1315,7 @@ void ath11k_nss_update_sta_rxrate(struct
peer->nss.nss_stats->rxrate.mcs = mcs;
peer->nss.nss_stats->rxrate.flags = RATE_INFO_FLAGS_HE_MCS;
peer->nss.nss_stats->rxrate.he_dcm = ppdu_info->dcm;
- peer->nss.nss_stats->rxrate.he_gi = ath11k_he_gi_to_nl80211_he_gi(ppdu_info->gi);
+ peer->nss.nss_stats->rxrate.he_gi = ath11k_mac_he_gi_to_nl80211_he_gi(ppdu_info->gi);
peer->nss.nss_stats->rxrate.he_ru_alloc = ppdu_info->ru_alloc;
break;
}
--- a/drivers/net/wireless/ath/ath11k/nss.h
+++ b/drivers/net/wireless/ath/ath11k/nss.h
@@ -101,6 +101,13 @@ do { \
u64_stats_update_end(&tstats->syncp); \
} while (0)
+enum ath11k_nss_vdev_cmd {
+ ATH11K_NSS_WIFI_VDEV_CFG_AP_BRIDGE_CMD,
+ ATH11K_NSS_WIFI_VDEV_SECURITY_TYPE_CMD,
+ ATH11K_NSS_WIFI_VDEV_ENCAP_TYPE_CMD,
+ ATH11K_NSS_WIFI_VDEV_DECAP_TYPE_CMD,
+};
+
enum ath11k_nss_opmode {
ATH11K_NSS_OPMODE_UNKNOWN,
ATH11K_NSS_OPMODE_AP,
@@ -192,7 +199,8 @@ struct ath11k_soc_nss {
#ifdef CPTCFG_ATH11K_NSS_SUPPORT
int ath11k_nss_tx(struct ath11k_vif *arvif, struct sk_buff *skb);
-int ath11k_nss_vdev_set_cmd(struct ath11k_vif *arvif, int cmd, int val);
+int ath11k_nss_vdev_set_cmd(struct ath11k_vif *arvif, enum ath11k_nss_vdev_cmd cmd,
+ int val);
int ath11k_nss_vdev_create(struct ath11k_vif *arvif);
void ath11k_nss_vdev_delete(struct ath11k_vif *arvif);
int ath11k_nss_vdev_up(struct ath11k_vif *arvif);
@@ -219,7 +227,8 @@ static inline int ath11k_nss_tx(struct a
return 0;
}
-static inline int ath11k_nss_vdev_set_cmd(struct ath11k_vif *arvif, int cmd, int val)
+static inline int ath11k_nss_vdev_set_cmd(struct ath11k_vif *arvif, enum ath11k_nss_vdev_cmd cmd,
+ int val)
{
return 0;
}
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -104,8 +104,10 @@ static void ath11k_init_wmi_config_qca63
static void ath11k_hw_ipq8074_reo_setup(struct ath11k_base *ab)
{
+ u8 frag_dest_ring = HAL_SRNG_RING_ID_REO2SW1;
u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
u32 val;
+
/* Each hash entry uses three bits to map to a particular ring. */
u32 ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 |
HAL_HASH_ROUTING_RING_SW2 << 3 |
@@ -116,11 +118,14 @@ static void ath11k_hw_ipq8074_reo_setup(
HAL_HASH_ROUTING_RING_SW3 << 18 |
HAL_HASH_ROUTING_RING_SW4 << 21;
+ 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);
@@ -134,6 +139,10 @@ static void ath11k_hw_ipq8074_reo_setup(
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));
@@ -758,8 +767,10 @@ static u8 *ath11k_hw_wcn6855_rx_desc_mpd
static void ath11k_hw_wcn6855_reo_setup(struct ath11k_base *ab)
{
+ u8 frag_dest_ring = HAL_SRNG_RING_ID_REO2SW1;
u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
u32 val;
+
/* Each hash entry uses four bits to map to a particular ring. */
u32 ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 |
HAL_HASH_ROUTING_RING_SW2 << 4 |
@@ -770,6 +781,9 @@ static void ath11k_hw_wcn6855_reo_setup(
HAL_HASH_ROUTING_RING_SW3 << 24 |
HAL_HASH_ROUTING_RING_SW4 << 28;
+ if (ab->nss.enabled)
+ frag_dest_ring = HAL_SRNG_REO_ALTERNATE_SELECT;
+
val = ath11k_hif_read32(ab, reo_base + HAL_REO1_GEN_ENABLE);
val |= FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE, 1) |
FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1);
@@ -777,7 +791,7 @@ static void ath11k_hw_wcn6855_reo_setup(
val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL(ab));
val &= ~HAL_REO1_MISC_CTL_FRAGMENT_DST_RING;
- val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DST_RING, HAL_SRNG_RING_ID_REO2SW1);
+ val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DST_RING, frag_dest_ring);
ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL(ab), val);
ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab),
@@ -789,6 +803,10 @@ static void ath11k_hw_wcn6855_reo_setup(
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_2,
ring_hash_map);
ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3,
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
@@ -571,6 +571,12 @@ static int ath11k_pcic_ext_irq_config(st
netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
ath11k_pcic_ext_grp_napi_poll);
+ /* 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] ||
--- a/local-symbols
+++ b/local-symbols
@@ -170,6 +170,7 @@ WCN36XX_DEBUGFS=
ATH11K=
ATH11K_AHB=
ATH11K_PCI=
+ATH11K_NSS_SUPPORT=
ATH11K_DEBUG=
ATH11K_DEBUGFS=
ATH11K_TRACING=