From 65c511e3aeb9afb84a3c6c8ac34353af91b880e9 Mon Sep 17 00:00:00 2001 From: Sriram R Date: Fri, 10 Jul 2020 12:50:21 +0530 Subject: [PATCH 3/3] ath11k: add nss support Add NSS Offload support for ath11k driver. Signed-off-by: Sriram R --- drivers/net/wireless/ath/ath11k/ahb.c | 18 ++++++-- drivers/net/wireless/ath/ath11k/core.c | 24 ++++++++++ drivers/net/wireless/ath/ath11k/core.h | 14 +++++- drivers/net/wireless/ath/ath11k/dp.c | 21 ++++++--- drivers/net/wireless/ath/ath11k/dp.h | 1 + drivers/net/wireless/ath/ath11k/dp_rx.c | 17 +++++-- drivers/net/wireless/ath/ath11k/dp_rx.h | 6 +++ drivers/net/wireless/ath/ath11k/hal.h | 2 + drivers/net/wireless/ath/ath11k/hal_rx.c | 10 +++- drivers/net/wireless/ath/ath11k/mac.c | 78 +++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath11k/peer.c | 9 +++- drivers/net/wireless/ath/ath11k/peer.h | 6 ++- local-symbols | 1 + 13 files changed, 186 insertions(+), 21 deletions(-) --- a/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=