1205 lines · c
1// SPDX-License-Identifier: BSD-3-Clause-Clear2/*3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.4 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.5 */6 7#include <crypto/hash.h>8#include "core.h"9#include "dp_tx.h"10#include "hal_tx.h"11#include "hif.h"12#include "debug.h"13#include "dp_rx.h"14#include "peer.h"15 16static void ath11k_dp_htt_htc_tx_complete(struct ath11k_base *ab,17 struct sk_buff *skb)18{19 dev_kfree_skb_any(skb);20}21 22void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr)23{24 struct ath11k_base *ab = ar->ab;25 struct ath11k_peer *peer;26 27 /* TODO: Any other peer specific DP cleanup */28 29 spin_lock_bh(&ab->base_lock);30 peer = ath11k_peer_find(ab, vdev_id, addr);31 if (!peer) {32 ath11k_warn(ab, "failed to lookup peer %pM on vdev %d\n",33 addr, vdev_id);34 spin_unlock_bh(&ab->base_lock);35 return;36 }37 38 ath11k_peer_rx_tid_cleanup(ar, peer);39 peer->dp_setup_done = false;40 crypto_free_shash(peer->tfm_mmic);41 spin_unlock_bh(&ab->base_lock);42}43 44int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr)45{46 struct ath11k_base *ab = ar->ab;47 struct ath11k_peer *peer;48 u32 reo_dest;49 int ret = 0, tid;50 51 /* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */52 reo_dest = ar->dp.mac_id + 1;53 ret = ath11k_wmi_set_peer_param(ar, addr, vdev_id,54 WMI_PEER_SET_DEFAULT_ROUTING,55 DP_RX_HASH_ENABLE | (reo_dest << 1));56 57 if (ret) {58 ath11k_warn(ab, "failed to set default routing %d peer :%pM vdev_id :%d\n",59 ret, addr, vdev_id);60 return ret;61 }62 63 for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) {64 ret = ath11k_peer_rx_tid_setup(ar, addr, vdev_id, tid, 1, 0,65 HAL_PN_TYPE_NONE);66 if (ret) {67 ath11k_warn(ab, "failed to setup rxd tid queue for tid %d: %d\n",68 tid, ret);69 goto peer_clean;70 }71 }72 73 ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id);74 if (ret) {75 ath11k_warn(ab, "failed to setup rx defrag context\n");76 tid--;77 goto peer_clean;78 }79 80 /* TODO: Setup other peer specific resource used in data path */81 82 return 0;83 84peer_clean:85 spin_lock_bh(&ab->base_lock);86 87 peer = ath11k_peer_find(ab, vdev_id, addr);88 if (!peer) {89 ath11k_warn(ab, "failed to find the peer to del rx tid\n");90 spin_unlock_bh(&ab->base_lock);91 return -ENOENT;92 }93 94 for (; tid >= 0; tid--)95 ath11k_peer_rx_tid_delete(ar, peer, tid);96 97 spin_unlock_bh(&ab->base_lock);98 99 return ret;100}101 102void ath11k_dp_srng_cleanup(struct ath11k_base *ab, struct dp_srng *ring)103{104 if (!ring->vaddr_unaligned)105 return;106 107 if (ring->cached) {108 dma_unmap_single(ab->dev, ring->paddr_unaligned, ring->size,109 DMA_FROM_DEVICE);110 kfree(ring->vaddr_unaligned);111 } else {112 dma_free_coherent(ab->dev, ring->size, ring->vaddr_unaligned,113 ring->paddr_unaligned);114 }115 116 ring->vaddr_unaligned = NULL;117}118 119static int ath11k_dp_srng_find_ring_in_mask(int ring_num, const u8 *grp_mask)120{121 int ext_group_num;122 u8 mask = 1 << ring_num;123 124 for (ext_group_num = 0; ext_group_num < ATH11K_EXT_IRQ_GRP_NUM_MAX;125 ext_group_num++) {126 if (mask & grp_mask[ext_group_num])127 return ext_group_num;128 }129 130 return -ENOENT;131}132 133static int ath11k_dp_srng_calculate_msi_group(struct ath11k_base *ab,134 enum hal_ring_type type, int ring_num)135{136 const u8 *grp_mask;137 138 switch (type) {139 case HAL_WBM2SW_RELEASE:140 if (ring_num == DP_RX_RELEASE_RING_NUM) {141 grp_mask = &ab->hw_params.ring_mask->rx_wbm_rel[0];142 ring_num = 0;143 } else {144 grp_mask = &ab->hw_params.ring_mask->tx[0];145 }146 break;147 case HAL_REO_EXCEPTION:148 grp_mask = &ab->hw_params.ring_mask->rx_err[0];149 break;150 case HAL_REO_DST:151 grp_mask = &ab->hw_params.ring_mask->rx[0];152 break;153 case HAL_REO_STATUS:154 grp_mask = &ab->hw_params.ring_mask->reo_status[0];155 break;156 case HAL_RXDMA_MONITOR_STATUS:157 case HAL_RXDMA_MONITOR_DST:158 grp_mask = &ab->hw_params.ring_mask->rx_mon_status[0];159 break;160 case HAL_RXDMA_DST:161 grp_mask = &ab->hw_params.ring_mask->rxdma2host[0];162 break;163 case HAL_RXDMA_BUF:164 grp_mask = &ab->hw_params.ring_mask->host2rxdma[0];165 break;166 case HAL_RXDMA_MONITOR_BUF:167 case HAL_TCL_DATA:168 case HAL_TCL_CMD:169 case HAL_REO_CMD:170 case HAL_SW2WBM_RELEASE:171 case HAL_WBM_IDLE_LINK:172 case HAL_TCL_STATUS:173 case HAL_REO_REINJECT:174 case HAL_CE_SRC:175 case HAL_CE_DST:176 case HAL_CE_DST_STATUS:177 default:178 return -ENOENT;179 }180 181 return ath11k_dp_srng_find_ring_in_mask(ring_num, grp_mask);182}183 184static void ath11k_dp_srng_msi_setup(struct ath11k_base *ab,185 struct hal_srng_params *ring_params,186 enum hal_ring_type type, int ring_num)187{188 int msi_group_number, msi_data_count;189 u32 msi_data_start, msi_irq_start, addr_lo, addr_hi;190 int ret;191 192 ret = ath11k_get_user_msi_vector(ab, "DP",193 &msi_data_count, &msi_data_start,194 &msi_irq_start);195 if (ret)196 return;197 198 msi_group_number = ath11k_dp_srng_calculate_msi_group(ab, type,199 ring_num);200 if (msi_group_number < 0) {201 ath11k_dbg(ab, ATH11K_DBG_PCI,202 "ring not part of an ext_group; ring_type: %d,ring_num %d",203 type, ring_num);204 ring_params->msi_addr = 0;205 ring_params->msi_data = 0;206 return;207 }208 209 if (msi_group_number > msi_data_count) {210 ath11k_dbg(ab, ATH11K_DBG_PCI,211 "multiple msi_groups share one msi, msi_group_num %d",212 msi_group_number);213 }214 215 ath11k_get_msi_address(ab, &addr_lo, &addr_hi);216 217 ring_params->msi_addr = addr_lo;218 ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);219 ring_params->msi_data = (msi_group_number % msi_data_count)220 + msi_data_start;221 ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;222}223 224int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,225 enum hal_ring_type type, int ring_num,226 int mac_id, int num_entries)227{228 struct hal_srng_params params = { 0 };229 int entry_sz = ath11k_hal_srng_get_entrysize(ab, type);230 int max_entries = ath11k_hal_srng_get_max_entries(ab, type);231 int ret;232 bool cached = false;233 234 if (max_entries < 0 || entry_sz < 0)235 return -EINVAL;236 237 if (num_entries > max_entries)238 num_entries = max_entries;239 240 ring->size = (num_entries * entry_sz) + HAL_RING_BASE_ALIGN - 1;241 242 if (ab->hw_params.alloc_cacheable_memory) {243 /* Allocate the reo dst and tx completion rings from cacheable memory */244 switch (type) {245 case HAL_REO_DST:246 case HAL_WBM2SW_RELEASE:247 cached = true;248 break;249 default:250 cached = false;251 }252 253 if (cached) {254 ring->vaddr_unaligned = kzalloc(ring->size, GFP_KERNEL);255 if (!ring->vaddr_unaligned)256 return -ENOMEM;257 258 ring->paddr_unaligned = dma_map_single(ab->dev,259 ring->vaddr_unaligned,260 ring->size,261 DMA_FROM_DEVICE);262 if (dma_mapping_error(ab->dev, ring->paddr_unaligned)) {263 kfree(ring->vaddr_unaligned);264 ring->vaddr_unaligned = NULL;265 return -ENOMEM;266 }267 }268 }269 270 if (!cached)271 ring->vaddr_unaligned = dma_alloc_coherent(ab->dev, ring->size,272 &ring->paddr_unaligned,273 GFP_KERNEL);274 275 if (!ring->vaddr_unaligned)276 return -ENOMEM;277 278 ring->vaddr = PTR_ALIGN(ring->vaddr_unaligned, HAL_RING_BASE_ALIGN);279 ring->paddr = ring->paddr_unaligned + ((unsigned long)ring->vaddr -280 (unsigned long)ring->vaddr_unaligned);281 282 params.ring_base_vaddr = ring->vaddr;283 params.ring_base_paddr = ring->paddr;284 params.num_entries = num_entries;285 ath11k_dp_srng_msi_setup(ab, ¶ms, type, ring_num + mac_id);286 287 switch (type) {288 case HAL_REO_DST:289 params.intr_batch_cntr_thres_entries =290 HAL_SRNG_INT_BATCH_THRESHOLD_RX;291 params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX;292 break;293 case HAL_RXDMA_BUF:294 case HAL_RXDMA_MONITOR_BUF:295 case HAL_RXDMA_MONITOR_STATUS:296 params.low_threshold = num_entries >> 3;297 params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN;298 params.intr_batch_cntr_thres_entries = 0;299 params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX;300 break;301 case HAL_WBM2SW_RELEASE:302 if (ring_num < 3) {303 params.intr_batch_cntr_thres_entries =304 HAL_SRNG_INT_BATCH_THRESHOLD_TX;305 params.intr_timer_thres_us =306 HAL_SRNG_INT_TIMER_THRESHOLD_TX;307 break;308 }309 /* follow through when ring_num >= 3 */310 fallthrough;311 case HAL_REO_EXCEPTION:312 case HAL_REO_REINJECT:313 case HAL_REO_CMD:314 case HAL_REO_STATUS:315 case HAL_TCL_DATA:316 case HAL_TCL_CMD:317 case HAL_TCL_STATUS:318 case HAL_WBM_IDLE_LINK:319 case HAL_SW2WBM_RELEASE:320 case HAL_RXDMA_DST:321 case HAL_RXDMA_MONITOR_DST:322 case HAL_RXDMA_MONITOR_DESC:323 params.intr_batch_cntr_thres_entries =324 HAL_SRNG_INT_BATCH_THRESHOLD_OTHER;325 params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_OTHER;326 break;327 case HAL_RXDMA_DIR_BUF:328 break;329 default:330 ath11k_warn(ab, "Not a valid ring type in dp :%d\n", type);331 return -EINVAL;332 }333 334 if (cached) {335 params.flags |= HAL_SRNG_FLAGS_CACHED;336 ring->cached = 1;337 }338 339 ret = ath11k_hal_srng_setup(ab, type, ring_num, mac_id, ¶ms);340 if (ret < 0) {341 ath11k_warn(ab, "failed to setup srng: %d ring_id %d\n",342 ret, ring_num);343 return ret;344 }345 346 ring->ring_id = ret;347 348 return 0;349}350 351void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)352{353 int i;354 355 if (!ab->hw_params.supports_shadow_regs)356 return;357 358 for (i = 0; i < ab->hw_params.max_tx_ring; i++)359 ath11k_dp_shadow_stop_timer(ab, &ab->dp.tx_ring_timer[i]);360 361 ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer);362}363 364static void ath11k_dp_srng_common_cleanup(struct ath11k_base *ab)365{366 struct ath11k_dp *dp = &ab->dp;367 int i;368 369 ath11k_dp_stop_shadow_timers(ab);370 ath11k_dp_srng_cleanup(ab, &dp->wbm_desc_rel_ring);371 ath11k_dp_srng_cleanup(ab, &dp->tcl_cmd_ring);372 ath11k_dp_srng_cleanup(ab, &dp->tcl_status_ring);373 for (i = 0; i < ab->hw_params.max_tx_ring; i++) {374 ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_data_ring);375 ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_comp_ring);376 }377 ath11k_dp_srng_cleanup(ab, &dp->reo_reinject_ring);378 ath11k_dp_srng_cleanup(ab, &dp->rx_rel_ring);379 ath11k_dp_srng_cleanup(ab, &dp->reo_except_ring);380 ath11k_dp_srng_cleanup(ab, &dp->reo_cmd_ring);381 ath11k_dp_srng_cleanup(ab, &dp->reo_status_ring);382}383 384static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)385{386 struct ath11k_dp *dp = &ab->dp;387 struct hal_srng *srng;388 int i, ret;389 u8 tcl_num, wbm_num;390 391 ret = ath11k_dp_srng_setup(ab, &dp->wbm_desc_rel_ring,392 HAL_SW2WBM_RELEASE, 0, 0,393 DP_WBM_RELEASE_RING_SIZE);394 if (ret) {395 ath11k_warn(ab, "failed to set up wbm2sw_release ring :%d\n",396 ret);397 goto err;398 }399 400 ret = ath11k_dp_srng_setup(ab, &dp->tcl_cmd_ring, HAL_TCL_CMD, 0, 0,401 DP_TCL_CMD_RING_SIZE);402 if (ret) {403 ath11k_warn(ab, "failed to set up tcl_cmd ring :%d\n", ret);404 goto err;405 }406 407 ret = ath11k_dp_srng_setup(ab, &dp->tcl_status_ring, HAL_TCL_STATUS,408 0, 0, DP_TCL_STATUS_RING_SIZE);409 if (ret) {410 ath11k_warn(ab, "failed to set up tcl_status ring :%d\n", ret);411 goto err;412 }413 414 for (i = 0; i < ab->hw_params.max_tx_ring; i++) {415 tcl_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].tcl_ring_num;416 wbm_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num;417 418 ret = ath11k_dp_srng_setup(ab, &dp->tx_ring[i].tcl_data_ring,419 HAL_TCL_DATA, tcl_num, 0,420 ab->hw_params.tx_ring_size);421 if (ret) {422 ath11k_warn(ab, "failed to set up tcl_data ring (%d) :%d\n",423 i, ret);424 goto err;425 }426 427 ret = ath11k_dp_srng_setup(ab, &dp->tx_ring[i].tcl_comp_ring,428 HAL_WBM2SW_RELEASE, wbm_num, 0,429 DP_TX_COMP_RING_SIZE);430 if (ret) {431 ath11k_warn(ab, "failed to set up tcl_comp ring (%d) :%d\n",432 i, ret);433 goto err;434 }435 436 srng = &ab->hal.srng_list[dp->tx_ring[i].tcl_data_ring.ring_id];437 ath11k_hal_tx_init_data_ring(ab, srng);438 439 ath11k_dp_shadow_init_timer(ab, &dp->tx_ring_timer[i],440 ATH11K_SHADOW_DP_TIMER_INTERVAL,441 dp->tx_ring[i].tcl_data_ring.ring_id);442 }443 444 ret = ath11k_dp_srng_setup(ab, &dp->reo_reinject_ring, HAL_REO_REINJECT,445 0, 0, DP_REO_REINJECT_RING_SIZE);446 if (ret) {447 ath11k_warn(ab, "failed to set up reo_reinject ring :%d\n",448 ret);449 goto err;450 }451 452 ret = ath11k_dp_srng_setup(ab, &dp->rx_rel_ring, HAL_WBM2SW_RELEASE,453 DP_RX_RELEASE_RING_NUM, 0, DP_RX_RELEASE_RING_SIZE);454 if (ret) {455 ath11k_warn(ab, "failed to set up rx_rel ring :%d\n", ret);456 goto err;457 }458 459 ret = ath11k_dp_srng_setup(ab, &dp->reo_except_ring, HAL_REO_EXCEPTION,460 0, 0, DP_REO_EXCEPTION_RING_SIZE);461 if (ret) {462 ath11k_warn(ab, "failed to set up reo_exception ring :%d\n",463 ret);464 goto err;465 }466 467 ret = ath11k_dp_srng_setup(ab, &dp->reo_cmd_ring, HAL_REO_CMD,468 0, 0, DP_REO_CMD_RING_SIZE);469 if (ret) {470 ath11k_warn(ab, "failed to set up reo_cmd ring :%d\n", ret);471 goto err;472 }473 474 srng = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id];475 ath11k_hal_reo_init_cmd_ring(ab, srng);476 477 ath11k_dp_shadow_init_timer(ab, &dp->reo_cmd_timer,478 ATH11K_SHADOW_CTRL_TIMER_INTERVAL,479 dp->reo_cmd_ring.ring_id);480 481 ret = ath11k_dp_srng_setup(ab, &dp->reo_status_ring, HAL_REO_STATUS,482 0, 0, DP_REO_STATUS_RING_SIZE);483 if (ret) {484 ath11k_warn(ab, "failed to set up reo_status ring :%d\n", ret);485 goto err;486 }487 488 /* When hash based routing of rx packet is enabled, 32 entries to map489 * the hash values to the ring will be configured.490 */491 ab->hw_params.hw_ops->reo_setup(ab);492 493 return 0;494 495err:496 ath11k_dp_srng_common_cleanup(ab);497 498 return ret;499}500 501static void ath11k_dp_scatter_idle_link_desc_cleanup(struct ath11k_base *ab)502{503 struct ath11k_dp *dp = &ab->dp;504 struct hal_wbm_idle_scatter_list *slist = dp->scatter_list;505 int i;506 507 for (i = 0; i < DP_IDLE_SCATTER_BUFS_MAX; i++) {508 if (!slist[i].vaddr)509 continue;510 511 dma_free_coherent(ab->dev, HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX,512 slist[i].vaddr, slist[i].paddr);513 slist[i].vaddr = NULL;514 }515}516 517static int ath11k_dp_scatter_idle_link_desc_setup(struct ath11k_base *ab,518 int size,519 u32 n_link_desc_bank,520 u32 n_link_desc,521 u32 last_bank_sz)522{523 struct ath11k_dp *dp = &ab->dp;524 struct dp_link_desc_bank *link_desc_banks = dp->link_desc_banks;525 struct hal_wbm_idle_scatter_list *slist = dp->scatter_list;526 u32 n_entries_per_buf;527 int num_scatter_buf, scatter_idx;528 struct hal_wbm_link_desc *scatter_buf;529 int align_bytes, n_entries;530 dma_addr_t paddr;531 int rem_entries;532 int i;533 int ret = 0;534 u32 end_offset;535 536 n_entries_per_buf = HAL_WBM_IDLE_SCATTER_BUF_SIZE /537 ath11k_hal_srng_get_entrysize(ab, HAL_WBM_IDLE_LINK);538 num_scatter_buf = DIV_ROUND_UP(size, HAL_WBM_IDLE_SCATTER_BUF_SIZE);539 540 if (num_scatter_buf > DP_IDLE_SCATTER_BUFS_MAX)541 return -EINVAL;542 543 for (i = 0; i < num_scatter_buf; i++) {544 slist[i].vaddr = dma_alloc_coherent(ab->dev,545 HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX,546 &slist[i].paddr, GFP_KERNEL);547 if (!slist[i].vaddr) {548 ret = -ENOMEM;549 goto err;550 }551 }552 553 scatter_idx = 0;554 scatter_buf = slist[scatter_idx].vaddr;555 rem_entries = n_entries_per_buf;556 557 for (i = 0; i < n_link_desc_bank; i++) {558 align_bytes = link_desc_banks[i].vaddr -559 link_desc_banks[i].vaddr_unaligned;560 n_entries = (DP_LINK_DESC_ALLOC_SIZE_THRESH - align_bytes) /561 HAL_LINK_DESC_SIZE;562 paddr = link_desc_banks[i].paddr;563 while (n_entries) {564 ath11k_hal_set_link_desc_addr(scatter_buf, i, paddr);565 n_entries--;566 paddr += HAL_LINK_DESC_SIZE;567 if (rem_entries) {568 rem_entries--;569 scatter_buf++;570 continue;571 }572 573 rem_entries = n_entries_per_buf;574 scatter_idx++;575 scatter_buf = slist[scatter_idx].vaddr;576 }577 }578 579 end_offset = (scatter_buf - slist[scatter_idx].vaddr) *580 sizeof(struct hal_wbm_link_desc);581 ath11k_hal_setup_link_idle_list(ab, slist, num_scatter_buf,582 n_link_desc, end_offset);583 584 return 0;585 586err:587 ath11k_dp_scatter_idle_link_desc_cleanup(ab);588 589 return ret;590}591 592static void593ath11k_dp_link_desc_bank_free(struct ath11k_base *ab,594 struct dp_link_desc_bank *link_desc_banks)595{596 int i;597 598 for (i = 0; i < DP_LINK_DESC_BANKS_MAX; i++) {599 if (link_desc_banks[i].vaddr_unaligned) {600 dma_free_coherent(ab->dev,601 link_desc_banks[i].size,602 link_desc_banks[i].vaddr_unaligned,603 link_desc_banks[i].paddr_unaligned);604 link_desc_banks[i].vaddr_unaligned = NULL;605 }606 }607}608 609static int ath11k_dp_link_desc_bank_alloc(struct ath11k_base *ab,610 struct dp_link_desc_bank *desc_bank,611 int n_link_desc_bank,612 int last_bank_sz)613{614 struct ath11k_dp *dp = &ab->dp;615 int i;616 int ret = 0;617 int desc_sz = DP_LINK_DESC_ALLOC_SIZE_THRESH;618 619 for (i = 0; i < n_link_desc_bank; i++) {620 if (i == (n_link_desc_bank - 1) && last_bank_sz)621 desc_sz = last_bank_sz;622 623 desc_bank[i].vaddr_unaligned =624 dma_alloc_coherent(ab->dev, desc_sz,625 &desc_bank[i].paddr_unaligned,626 GFP_KERNEL);627 if (!desc_bank[i].vaddr_unaligned) {628 ret = -ENOMEM;629 goto err;630 }631 632 desc_bank[i].vaddr = PTR_ALIGN(desc_bank[i].vaddr_unaligned,633 HAL_LINK_DESC_ALIGN);634 desc_bank[i].paddr = desc_bank[i].paddr_unaligned +635 ((unsigned long)desc_bank[i].vaddr -636 (unsigned long)desc_bank[i].vaddr_unaligned);637 desc_bank[i].size = desc_sz;638 }639 640 return 0;641 642err:643 ath11k_dp_link_desc_bank_free(ab, dp->link_desc_banks);644 645 return ret;646}647 648void ath11k_dp_link_desc_cleanup(struct ath11k_base *ab,649 struct dp_link_desc_bank *desc_bank,650 u32 ring_type, struct dp_srng *ring)651{652 ath11k_dp_link_desc_bank_free(ab, desc_bank);653 654 if (ring_type != HAL_RXDMA_MONITOR_DESC) {655 ath11k_dp_srng_cleanup(ab, ring);656 ath11k_dp_scatter_idle_link_desc_cleanup(ab);657 }658}659 660static int ath11k_wbm_idle_ring_setup(struct ath11k_base *ab, u32 *n_link_desc)661{662 struct ath11k_dp *dp = &ab->dp;663 u32 n_mpdu_link_desc, n_mpdu_queue_desc;664 u32 n_tx_msdu_link_desc, n_rx_msdu_link_desc;665 int ret = 0;666 667 n_mpdu_link_desc = (DP_NUM_TIDS_MAX * DP_AVG_MPDUS_PER_TID_MAX) /668 HAL_NUM_MPDUS_PER_LINK_DESC;669 670 n_mpdu_queue_desc = n_mpdu_link_desc /671 HAL_NUM_MPDU_LINKS_PER_QUEUE_DESC;672 673 n_tx_msdu_link_desc = (DP_NUM_TIDS_MAX * DP_AVG_FLOWS_PER_TID *674 DP_AVG_MSDUS_PER_FLOW) /675 HAL_NUM_TX_MSDUS_PER_LINK_DESC;676 677 n_rx_msdu_link_desc = (DP_NUM_TIDS_MAX * DP_AVG_MPDUS_PER_TID_MAX *678 DP_AVG_MSDUS_PER_MPDU) /679 HAL_NUM_RX_MSDUS_PER_LINK_DESC;680 681 *n_link_desc = n_mpdu_link_desc + n_mpdu_queue_desc +682 n_tx_msdu_link_desc + n_rx_msdu_link_desc;683 684 if (*n_link_desc & (*n_link_desc - 1))685 *n_link_desc = 1 << fls(*n_link_desc);686 687 ret = ath11k_dp_srng_setup(ab, &dp->wbm_idle_ring,688 HAL_WBM_IDLE_LINK, 0, 0, *n_link_desc);689 if (ret) {690 ath11k_warn(ab, "failed to setup wbm_idle_ring: %d\n", ret);691 return ret;692 }693 return ret;694}695 696int ath11k_dp_link_desc_setup(struct ath11k_base *ab,697 struct dp_link_desc_bank *link_desc_banks,698 u32 ring_type, struct hal_srng *srng,699 u32 n_link_desc)700{701 u32 tot_mem_sz;702 u32 n_link_desc_bank, last_bank_sz;703 u32 entry_sz, align_bytes, n_entries;704 u32 paddr;705 u32 *desc;706 int i, ret;707 708 tot_mem_sz = n_link_desc * HAL_LINK_DESC_SIZE;709 tot_mem_sz += HAL_LINK_DESC_ALIGN;710 711 if (tot_mem_sz <= DP_LINK_DESC_ALLOC_SIZE_THRESH) {712 n_link_desc_bank = 1;713 last_bank_sz = tot_mem_sz;714 } else {715 n_link_desc_bank = tot_mem_sz /716 (DP_LINK_DESC_ALLOC_SIZE_THRESH -717 HAL_LINK_DESC_ALIGN);718 last_bank_sz = tot_mem_sz %719 (DP_LINK_DESC_ALLOC_SIZE_THRESH -720 HAL_LINK_DESC_ALIGN);721 722 if (last_bank_sz)723 n_link_desc_bank += 1;724 }725 726 if (n_link_desc_bank > DP_LINK_DESC_BANKS_MAX)727 return -EINVAL;728 729 ret = ath11k_dp_link_desc_bank_alloc(ab, link_desc_banks,730 n_link_desc_bank, last_bank_sz);731 if (ret)732 return ret;733 734 /* Setup link desc idle list for HW internal usage */735 entry_sz = ath11k_hal_srng_get_entrysize(ab, ring_type);736 tot_mem_sz = entry_sz * n_link_desc;737 738 /* Setup scatter desc list when the total memory requirement is more */739 if (tot_mem_sz > DP_LINK_DESC_ALLOC_SIZE_THRESH &&740 ring_type != HAL_RXDMA_MONITOR_DESC) {741 ret = ath11k_dp_scatter_idle_link_desc_setup(ab, tot_mem_sz,742 n_link_desc_bank,743 n_link_desc,744 last_bank_sz);745 if (ret) {746 ath11k_warn(ab, "failed to setup scatting idle list descriptor :%d\n",747 ret);748 goto fail_desc_bank_free;749 }750 751 return 0;752 }753 754 spin_lock_bh(&srng->lock);755 756 ath11k_hal_srng_access_begin(ab, srng);757 758 for (i = 0; i < n_link_desc_bank; i++) {759 align_bytes = link_desc_banks[i].vaddr -760 link_desc_banks[i].vaddr_unaligned;761 n_entries = (link_desc_banks[i].size - align_bytes) /762 HAL_LINK_DESC_SIZE;763 paddr = link_desc_banks[i].paddr;764 while (n_entries &&765 (desc = ath11k_hal_srng_src_get_next_entry(ab, srng))) {766 ath11k_hal_set_link_desc_addr((struct hal_wbm_link_desc *)desc,767 i, paddr);768 n_entries--;769 paddr += HAL_LINK_DESC_SIZE;770 }771 }772 773 ath11k_hal_srng_access_end(ab, srng);774 775 spin_unlock_bh(&srng->lock);776 777 return 0;778 779fail_desc_bank_free:780 ath11k_dp_link_desc_bank_free(ab, link_desc_banks);781 782 return ret;783}784 785int ath11k_dp_service_srng(struct ath11k_base *ab,786 struct ath11k_ext_irq_grp *irq_grp,787 int budget)788{789 struct napi_struct *napi = &irq_grp->napi;790 const struct ath11k_hw_hal_params *hal_params;791 int grp_id = irq_grp->grp_id;792 int work_done = 0;793 int i, j;794 int tot_work_done = 0;795 796 for (i = 0; i < ab->hw_params.max_tx_ring; i++) {797 if (BIT(ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num) &798 ab->hw_params.ring_mask->tx[grp_id])799 ath11k_dp_tx_completion_handler(ab, i);800 }801 802 if (ab->hw_params.ring_mask->rx_err[grp_id]) {803 work_done = ath11k_dp_process_rx_err(ab, napi, budget);804 budget -= work_done;805 tot_work_done += work_done;806 if (budget <= 0)807 goto done;808 }809 810 if (ab->hw_params.ring_mask->rx_wbm_rel[grp_id]) {811 work_done = ath11k_dp_rx_process_wbm_err(ab,812 napi,813 budget);814 budget -= work_done;815 tot_work_done += work_done;816 817 if (budget <= 0)818 goto done;819 }820 821 if (ab->hw_params.ring_mask->rx[grp_id]) {822 i = fls(ab->hw_params.ring_mask->rx[grp_id]) - 1;823 work_done = ath11k_dp_process_rx(ab, i, napi,824 budget);825 budget -= work_done;826 tot_work_done += work_done;827 if (budget <= 0)828 goto done;829 }830 831 if (ab->hw_params.ring_mask->rx_mon_status[grp_id]) {832 for (i = 0; i < ab->num_radios; i++) {833 for (j = 0; j < ab->hw_params.num_rxdma_per_pdev; j++) {834 int id = i * ab->hw_params.num_rxdma_per_pdev + j;835 836 if (ab->hw_params.ring_mask->rx_mon_status[grp_id] &837 BIT(id)) {838 work_done =839 ath11k_dp_rx_process_mon_rings(ab,840 id,841 napi, budget);842 budget -= work_done;843 tot_work_done += work_done;844 845 if (budget <= 0)846 goto done;847 }848 }849 }850 }851 852 if (ab->hw_params.ring_mask->reo_status[grp_id])853 ath11k_dp_process_reo_status(ab);854 855 for (i = 0; i < ab->num_radios; i++) {856 for (j = 0; j < ab->hw_params.num_rxdma_per_pdev; j++) {857 int id = i * ab->hw_params.num_rxdma_per_pdev + j;858 859 if (ab->hw_params.ring_mask->rxdma2host[grp_id] & BIT(id)) {860 work_done = ath11k_dp_process_rxdma_err(ab, id, budget);861 budget -= work_done;862 tot_work_done += work_done;863 }864 865 if (budget <= 0)866 goto done;867 868 if (ab->hw_params.ring_mask->host2rxdma[grp_id] & BIT(id)) {869 struct ath11k *ar = ath11k_ab_to_ar(ab, id);870 struct ath11k_pdev_dp *dp = &ar->dp;871 struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;872 873 hal_params = ab->hw_params.hal_params;874 ath11k_dp_rxbufs_replenish(ab, id, rx_ring, 0,875 hal_params->rx_buf_rbm);876 }877 }878 }879 /* TODO: Implement handler for other interrupts */880 881done:882 return tot_work_done;883}884EXPORT_SYMBOL(ath11k_dp_service_srng);885 886void ath11k_dp_pdev_free(struct ath11k_base *ab)887{888 struct ath11k *ar;889 int i;890 891 del_timer_sync(&ab->mon_reap_timer);892 893 for (i = 0; i < ab->num_radios; i++) {894 ar = ab->pdevs[i].ar;895 ath11k_dp_rx_pdev_free(ab, i);896 ath11k_debugfs_unregister(ar);897 ath11k_dp_rx_pdev_mon_detach(ar);898 }899}900 901void ath11k_dp_pdev_pre_alloc(struct ath11k_base *ab)902{903 struct ath11k *ar;904 struct ath11k_pdev_dp *dp;905 int i;906 int j;907 908 for (i = 0; i < ab->num_radios; i++) {909 ar = ab->pdevs[i].ar;910 dp = &ar->dp;911 dp->mac_id = i;912 idr_init(&dp->rx_refill_buf_ring.bufs_idr);913 spin_lock_init(&dp->rx_refill_buf_ring.idr_lock);914 atomic_set(&dp->num_tx_pending, 0);915 init_waitqueue_head(&dp->tx_empty_waitq);916 for (j = 0; j < ab->hw_params.num_rxdma_per_pdev; j++) {917 idr_init(&dp->rx_mon_status_refill_ring[j].bufs_idr);918 spin_lock_init(&dp->rx_mon_status_refill_ring[j].idr_lock);919 }920 idr_init(&dp->rxdma_mon_buf_ring.bufs_idr);921 spin_lock_init(&dp->rxdma_mon_buf_ring.idr_lock);922 }923}924 925int ath11k_dp_pdev_alloc(struct ath11k_base *ab)926{927 struct ath11k *ar;928 int ret;929 int i;930 931 /* TODO:Per-pdev rx ring unlike tx ring which is mapped to different AC's */932 for (i = 0; i < ab->num_radios; i++) {933 ar = ab->pdevs[i].ar;934 ret = ath11k_dp_rx_pdev_alloc(ab, i);935 if (ret) {936 ath11k_warn(ab, "failed to allocate pdev rx for pdev_id :%d\n",937 i);938 goto err;939 }940 ret = ath11k_dp_rx_pdev_mon_attach(ar);941 if (ret) {942 ath11k_warn(ab, "failed to initialize mon pdev %d\n",943 i);944 goto err;945 }946 }947 948 return 0;949 950err:951 ath11k_dp_pdev_free(ab);952 953 return ret;954}955 956int ath11k_dp_htt_connect(struct ath11k_dp *dp)957{958 struct ath11k_htc_svc_conn_req conn_req;959 struct ath11k_htc_svc_conn_resp conn_resp;960 int status;961 962 memset(&conn_req, 0, sizeof(conn_req));963 memset(&conn_resp, 0, sizeof(conn_resp));964 965 conn_req.ep_ops.ep_tx_complete = ath11k_dp_htt_htc_tx_complete;966 conn_req.ep_ops.ep_rx_complete = ath11k_dp_htt_htc_t2h_msg_handler;967 968 /* connect to control service */969 conn_req.service_id = ATH11K_HTC_SVC_ID_HTT_DATA_MSG;970 971 status = ath11k_htc_connect_service(&dp->ab->htc, &conn_req,972 &conn_resp);973 974 if (status)975 return status;976 977 dp->eid = conn_resp.eid;978 979 return 0;980}981 982static void ath11k_dp_update_vdev_search(struct ath11k_vif *arvif)983{984 /* When v2_map_support is true:for STA mode, enable address985 * search index, tcl uses ast_hash value in the descriptor.986 * When v2_map_support is false: for STA mode, don't enable987 * address search index.988 */989 switch (arvif->vdev_type) {990 case WMI_VDEV_TYPE_STA:991 if (arvif->ar->ab->hw_params.htt_peer_map_v2) {992 arvif->hal_addr_search_flags = HAL_TX_ADDRX_EN;993 arvif->search_type = HAL_TX_ADDR_SEARCH_INDEX;994 } else {995 arvif->hal_addr_search_flags = HAL_TX_ADDRY_EN;996 arvif->search_type = HAL_TX_ADDR_SEARCH_DEFAULT;997 }998 break;999 case WMI_VDEV_TYPE_AP:1000 case WMI_VDEV_TYPE_IBSS:1001 arvif->hal_addr_search_flags = HAL_TX_ADDRX_EN;1002 arvif->search_type = HAL_TX_ADDR_SEARCH_DEFAULT;1003 break;1004 case WMI_VDEV_TYPE_MONITOR:1005 default:1006 return;1007 }1008}1009 1010void ath11k_dp_vdev_tx_attach(struct ath11k *ar, struct ath11k_vif *arvif)1011{1012 arvif->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 1) |1013 FIELD_PREP(HTT_TCL_META_DATA_VDEV_ID,1014 arvif->vdev_id) |1015 FIELD_PREP(HTT_TCL_META_DATA_PDEV_ID,1016 ar->pdev->pdev_id);1017 1018 /* set HTT extension valid bit to 0 by default */1019 arvif->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT;1020 1021 ath11k_dp_update_vdev_search(arvif);1022}1023 1024static int ath11k_dp_tx_pending_cleanup(int buf_id, void *skb, void *ctx)1025{1026 struct ath11k_base *ab = ctx;1027 struct sk_buff *msdu = skb;1028 1029 dma_unmap_single(ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len,1030 DMA_TO_DEVICE);1031 1032 dev_kfree_skb_any(msdu);1033 1034 return 0;1035}1036 1037void ath11k_dp_free(struct ath11k_base *ab)1038{1039 struct ath11k_dp *dp = &ab->dp;1040 int i;1041 1042 ath11k_dp_link_desc_cleanup(ab, dp->link_desc_banks,1043 HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring);1044 1045 ath11k_dp_srng_common_cleanup(ab);1046 1047 ath11k_dp_reo_cmd_list_cleanup(ab);1048 1049 for (i = 0; i < ab->hw_params.max_tx_ring; i++) {1050 spin_lock_bh(&dp->tx_ring[i].tx_idr_lock);1051 idr_for_each(&dp->tx_ring[i].txbuf_idr,1052 ath11k_dp_tx_pending_cleanup, ab);1053 idr_destroy(&dp->tx_ring[i].txbuf_idr);1054 spin_unlock_bh(&dp->tx_ring[i].tx_idr_lock);1055 kfree(dp->tx_ring[i].tx_status);1056 }1057 1058 /* Deinit any SOC level resource */1059}1060 1061int ath11k_dp_alloc(struct ath11k_base *ab)1062{1063 struct ath11k_dp *dp = &ab->dp;1064 struct hal_srng *srng = NULL;1065 size_t size = 0;1066 u32 n_link_desc = 0;1067 int ret;1068 int i;1069 1070 dp->ab = ab;1071 1072 INIT_LIST_HEAD(&dp->reo_cmd_list);1073 INIT_LIST_HEAD(&dp->reo_cmd_cache_flush_list);1074 INIT_LIST_HEAD(&dp->dp_full_mon_mpdu_list);1075 spin_lock_init(&dp->reo_cmd_lock);1076 1077 dp->reo_cmd_cache_flush_count = 0;1078 1079 ret = ath11k_wbm_idle_ring_setup(ab, &n_link_desc);1080 if (ret) {1081 ath11k_warn(ab, "failed to setup wbm_idle_ring: %d\n", ret);1082 return ret;1083 }1084 1085 srng = &ab->hal.srng_list[dp->wbm_idle_ring.ring_id];1086 1087 ret = ath11k_dp_link_desc_setup(ab, dp->link_desc_banks,1088 HAL_WBM_IDLE_LINK, srng, n_link_desc);1089 if (ret) {1090 ath11k_warn(ab, "failed to setup link desc: %d\n", ret);1091 return ret;1092 }1093 1094 ret = ath11k_dp_srng_common_setup(ab);1095 if (ret)1096 goto fail_link_desc_cleanup;1097 1098 size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE;1099 1100 for (i = 0; i < ab->hw_params.max_tx_ring; i++) {1101 idr_init(&dp->tx_ring[i].txbuf_idr);1102 spin_lock_init(&dp->tx_ring[i].tx_idr_lock);1103 dp->tx_ring[i].tcl_data_ring_id = i;1104 1105 dp->tx_ring[i].tx_status_head = 0;1106 dp->tx_ring[i].tx_status_tail = DP_TX_COMP_RING_SIZE - 1;1107 dp->tx_ring[i].tx_status = kmalloc(size, GFP_KERNEL);1108 if (!dp->tx_ring[i].tx_status) {1109 ret = -ENOMEM;1110 goto fail_cmn_srng_cleanup;1111 }1112 }1113 1114 for (i = 0; i < HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX; i++)1115 ath11k_hal_tx_set_dscp_tid_map(ab, i);1116 1117 /* Init any SOC level resource for DP */1118 1119 return 0;1120 1121fail_cmn_srng_cleanup:1122 ath11k_dp_srng_common_cleanup(ab);1123 1124fail_link_desc_cleanup:1125 ath11k_dp_link_desc_cleanup(ab, dp->link_desc_banks,1126 HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring);1127 1128 return ret;1129}1130 1131static void ath11k_dp_shadow_timer_handler(struct timer_list *t)1132{1133 struct ath11k_hp_update_timer *update_timer = from_timer(update_timer,1134 t, timer);1135 struct ath11k_base *ab = update_timer->ab;1136 struct hal_srng *srng = &ab->hal.srng_list[update_timer->ring_id];1137 1138 spin_lock_bh(&srng->lock);1139 1140 /* when the timer is fired, the handler checks whether there1141 * are new TX happened. The handler updates HP only when there1142 * are no TX operations during the timeout interval, and stop1143 * the timer. Timer will be started again when TX happens again.1144 */1145 if (update_timer->timer_tx_num != update_timer->tx_num) {1146 update_timer->timer_tx_num = update_timer->tx_num;1147 mod_timer(&update_timer->timer, jiffies +1148 msecs_to_jiffies(update_timer->interval));1149 } else {1150 update_timer->started = false;1151 ath11k_hal_srng_shadow_update_hp_tp(ab, srng);1152 }1153 1154 spin_unlock_bh(&srng->lock);1155}1156 1157void ath11k_dp_shadow_start_timer(struct ath11k_base *ab,1158 struct hal_srng *srng,1159 struct ath11k_hp_update_timer *update_timer)1160{1161 lockdep_assert_held(&srng->lock);1162 1163 if (!ab->hw_params.supports_shadow_regs)1164 return;1165 1166 update_timer->tx_num++;1167 1168 if (update_timer->started)1169 return;1170 1171 update_timer->started = true;1172 update_timer->timer_tx_num = update_timer->tx_num;1173 mod_timer(&update_timer->timer, jiffies +1174 msecs_to_jiffies(update_timer->interval));1175}1176 1177void ath11k_dp_shadow_stop_timer(struct ath11k_base *ab,1178 struct ath11k_hp_update_timer *update_timer)1179{1180 if (!ab->hw_params.supports_shadow_regs)1181 return;1182 1183 if (!update_timer->init)1184 return;1185 1186 del_timer_sync(&update_timer->timer);1187}1188 1189void ath11k_dp_shadow_init_timer(struct ath11k_base *ab,1190 struct ath11k_hp_update_timer *update_timer,1191 u32 interval, u32 ring_id)1192{1193 if (!ab->hw_params.supports_shadow_regs)1194 return;1195 1196 update_timer->tx_num = 0;1197 update_timer->timer_tx_num = 0;1198 update_timer->ab = ab;1199 update_timer->ring_id = ring_id;1200 update_timer->interval = interval;1201 update_timer->init = true;1202 timer_setup(&update_timer->timer,1203 ath11k_dp_shadow_timer_handler, 0);1204}1205