From d889913205cf7ebda905b1e62c5867ed4e39f6c2 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 28 Nov 2022 17:09:53 +0200 Subject: wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices ath12k is a new mac80211 driver for Qualcomm Wi-Fi 7 devices, first supporting QCN9274 and WCN7850 PCI devices. QCN9274 supports both AP and station; WCN7850 supports only station mode. Monitor mode is not (yet) supported. Only PCI bus devices are supported. ath12k is forked from an earlier version of ath11k. It was simpler to have a "clean start" for the new generation and not try to share the code with ath11k. This makes maintenance easier and avoids major changes in ath11k, which would have significantly increased the risk of regressions in existing setups. ath12k uses le32 and cpu_to_le32() macros to handle endian conversions, instead of using the firmware byte swap feature utilized by ath11k. There is only one kernel module, named ath12k.ko. Currently ath12k only supports HE mode (IEEE 802.11ax) or older, but work is ongoing to add EHT mode (IEEE 802.11be) support. The size of the driver is ~41 kLOC and 45 files. To make the review easier, this initial version of ath12k does not support Device Tree, debugfs or any other extra features. Those will be added later, after ath12k is accepted to upstream. The driver is build tested by Intel's kernel test robot with both GCC and Clang. Sparse reports no warnings. The driver is mostly free of checkpatch warnings, albeit few of the warnings are omitted on purpose, list of them here: https://github.com/qca/qca-swiss-army-knife/blob/master/tools/scripts/ath12k/ath12k-check#L52 The driver has had multiple authors who are listed in alphabetical order below. Co-developed-by: Balamurugan Selvarajan Signed-off-by: Balamurugan Selvarajan Co-developed-by: Baochen Qiang Signed-off-by: Baochen Qiang Co-developed-by: Bhagavathi Perumal S Signed-off-by: Bhagavathi Perumal S Co-developed-by: Carl Huang Signed-off-by: Carl Huang Co-developed-by: Jeff Johnson Signed-off-by: Jeff Johnson Co-developed-by: Karthikeyan Periyasamy Signed-off-by: Karthikeyan Periyasamy Co-developed-by: P Praneesh Signed-off-by: P Praneesh Co-developed-by: Pradeep Kumar Chitrapu Signed-off-by: Pradeep Kumar Chitrapu Co-developed-by: Ramya Gnanasekar Signed-off-by: Ramya Gnanasekar Co-developed-by: Sriram R Signed-off-by: Sriram R Co-developed-by: Vasanthakumar Thiagarajan Signed-off-by: Vasanthakumar Thiagarajan Co-developed-by: Wen Gong Signed-off-by: Wen Gong Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/hal_rx.c | 853 +++++++++++++++++++++++++++++++ 1 file changed, 853 insertions(+) create mode 100644 drivers/net/wireless/ath/ath12k/hal_rx.c (limited to 'drivers/net/wireless/ath/ath12k/hal_rx.c') diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/hal_rx.c new file mode 100644 index 000000000000..d47befb83e38 --- /dev/null +++ b/drivers/net/wireless/ath/ath12k/hal_rx.c @@ -0,0 +1,853 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +/* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "debug.h" +#include "hal.h" +#include "hal_tx.h" +#include "hal_rx.h" +#include "hal_desc.h" +#include "hif.h" + +static void ath12k_hal_reo_set_desc_hdr(struct hal_desc_header *hdr, + u8 owner, u8 buffer_type, u32 magic) +{ + hdr->info0 = le32_encode_bits(owner, HAL_DESC_HDR_INFO0_OWNER) | + le32_encode_bits(buffer_type, HAL_DESC_HDR_INFO0_BUF_TYPE); + + /* Magic pattern in reserved bits for debugging */ + hdr->info0 |= le32_encode_bits(magic, HAL_DESC_HDR_INFO0_DBG_RESERVED); +} + +static int ath12k_hal_reo_cmd_queue_stats(struct hal_tlv_64_hdr *tlv, + struct ath12k_hal_reo_cmd *cmd) +{ + struct hal_reo_get_queue_stats *desc; + + tlv->tl = u32_encode_bits(HAL_REO_GET_QUEUE_STATS, HAL_TLV_HDR_TAG) | + u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN); + + desc = (struct hal_reo_get_queue_stats *)tlv->value; + memset(&desc->queue_addr_lo, 0, + (sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr))); + + desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED); + if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) + desc->cmd.info0 |= cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED); + + desc->queue_addr_lo = cpu_to_le32(cmd->addr_lo); + desc->info0 = le32_encode_bits(cmd->addr_hi, + HAL_REO_GET_QUEUE_STATS_INFO0_QUEUE_ADDR_HI); + if (cmd->flag & HAL_REO_CMD_FLG_STATS_CLEAR) + desc->info0 |= cpu_to_le32(HAL_REO_GET_QUEUE_STATS_INFO0_CLEAR_STATS); + + return le32_get_bits(desc->cmd.info0, HAL_REO_CMD_HDR_INFO0_CMD_NUMBER); +} + +static int ath12k_hal_reo_cmd_flush_cache(struct ath12k_hal *hal, + struct hal_tlv_64_hdr *tlv, + struct ath12k_hal_reo_cmd *cmd) +{ + struct hal_reo_flush_cache *desc; + u8 avail_slot = ffz(hal->avail_blk_resource); + + if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_BLOCK_LATER) { + if (avail_slot >= HAL_MAX_AVAIL_BLK_RES) + return -ENOSPC; + + hal->current_blk_index = avail_slot; + } + + tlv->tl = u32_encode_bits(HAL_REO_FLUSH_CACHE, HAL_TLV_HDR_TAG) | + u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN); + + desc = (struct hal_reo_flush_cache *)tlv->value; + memset(&desc->cache_addr_lo, 0, + (sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr))); + + desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED); + if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) + desc->cmd.info0 |= cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED); + + desc->cache_addr_lo = cpu_to_le32(cmd->addr_lo); + desc->info0 = le32_encode_bits(cmd->addr_hi, + HAL_REO_FLUSH_CACHE_INFO0_CACHE_ADDR_HI); + + if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS) + desc->info0 |= cpu_to_le32(HAL_REO_FLUSH_CACHE_INFO0_FWD_ALL_MPDUS); + + if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_BLOCK_LATER) { + desc->info0 |= cpu_to_le32(HAL_REO_FLUSH_CACHE_INFO0_BLOCK_CACHE_USAGE); + desc->info0 |= + le32_encode_bits(avail_slot, + HAL_REO_FLUSH_CACHE_INFO0_BLOCK_RESRC_IDX); + } + + if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_NO_INVAL) + desc->info0 |= cpu_to_le32(HAL_REO_FLUSH_CACHE_INFO0_FLUSH_WO_INVALIDATE); + + if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_ALL) + desc->info0 |= cpu_to_le32(HAL_REO_FLUSH_CACHE_INFO0_FLUSH_ALL); + + return le32_get_bits(desc->cmd.info0, HAL_REO_CMD_HDR_INFO0_CMD_NUMBER); +} + +static int ath12k_hal_reo_cmd_update_rx_queue(struct hal_tlv_64_hdr *tlv, + struct ath12k_hal_reo_cmd *cmd) +{ + struct hal_reo_update_rx_queue *desc; + + tlv->tl = u32_encode_bits(HAL_REO_UPDATE_RX_REO_QUEUE, HAL_TLV_HDR_TAG) | + u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN); + + desc = (struct hal_reo_update_rx_queue *)tlv->value; + memset(&desc->queue_addr_lo, 0, + (sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr))); + + desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED); + if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) + desc->cmd.info0 |= cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED); + + desc->queue_addr_lo = cpu_to_le32(cmd->addr_lo); + desc->info0 = + le32_encode_bits(cmd->addr_hi, + HAL_REO_UPD_RX_QUEUE_INFO0_QUEUE_ADDR_HI) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_RX_QUEUE_NUM), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_RX_QUEUE_NUM) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_VLD), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_VLD) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_ALDC), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_ASSOC_LNK_DESC_CNT) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_DIS_DUP_DETECTION), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_DIS_DUP_DETECTION) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_SOFT_REORDER_EN), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SOFT_REORDER_EN) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_AC), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_AC) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_BAR), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_BAR) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_RETRY), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_RETRY) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_CHECK_2K_MODE), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_CHECK_2K_MODE) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_OOR_MODE), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_OOR_MODE) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_BA_WINDOW_SIZE), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_BA_WINDOW_SIZE) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN_CHECK), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_CHECK) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_EVEN_PN), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_EVEN_PN) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_UNEVEN_PN), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_UNEVEN_PN) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN_HANDLE_ENABLE), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_HANDLE_ENABLE) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN_SIZE), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_SIZE) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_IGNORE_AMPDU_FLG), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_IGNORE_AMPDU_FLG) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_SVLD), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SVLD) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_SSN), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SSN) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_SEQ_2K_ERR), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SEQ_2K_ERR) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN_VALID), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_VALID) | + le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN), + HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN); + + desc->info1 = + le32_encode_bits(cmd->rx_queue_num, + HAL_REO_UPD_RX_QUEUE_INFO1_RX_QUEUE_NUMBER) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_VLD), + HAL_REO_UPD_RX_QUEUE_INFO1_VLD) | + le32_encode_bits(u32_get_bits(cmd->upd1, HAL_REO_CMD_UPD1_ALDC), + HAL_REO_UPD_RX_QUEUE_INFO1_ASSOC_LNK_DESC_COUNTER) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_DIS_DUP_DETECTION), + HAL_REO_UPD_RX_QUEUE_INFO1_DIS_DUP_DETECTION) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_SOFT_REORDER_EN), + HAL_REO_UPD_RX_QUEUE_INFO1_SOFT_REORDER_EN) | + le32_encode_bits(u32_get_bits(cmd->upd1, HAL_REO_CMD_UPD1_AC), + HAL_REO_UPD_RX_QUEUE_INFO1_AC) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_BAR), + HAL_REO_UPD_RX_QUEUE_INFO1_BAR) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_CHECK_2K_MODE), + HAL_REO_UPD_RX_QUEUE_INFO1_CHECK_2K_MODE) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_RETRY), + HAL_REO_UPD_RX_QUEUE_INFO1_RETRY) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_OOR_MODE), + HAL_REO_UPD_RX_QUEUE_INFO1_OOR_MODE) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_PN_CHECK), + HAL_REO_UPD_RX_QUEUE_INFO1_PN_CHECK) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_EVEN_PN), + HAL_REO_UPD_RX_QUEUE_INFO1_EVEN_PN) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_UNEVEN_PN), + HAL_REO_UPD_RX_QUEUE_INFO1_UNEVEN_PN) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_PN_HANDLE_ENABLE), + HAL_REO_UPD_RX_QUEUE_INFO1_PN_HANDLE_ENABLE) | + le32_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_IGNORE_AMPDU_FLG), + HAL_REO_UPD_RX_QUEUE_INFO1_IGNORE_AMPDU_FLG); + + if (cmd->pn_size == 24) + cmd->pn_size = HAL_RX_REO_QUEUE_PN_SIZE_24; + else if (cmd->pn_size == 48) + cmd->pn_size = HAL_RX_REO_QUEUE_PN_SIZE_48; + else if (cmd->pn_size == 128) + cmd->pn_size = HAL_RX_REO_QUEUE_PN_SIZE_128; + + if (cmd->ba_window_size < 1) + cmd->ba_window_size = 1; + + if (cmd->ba_window_size == 1) + cmd->ba_window_size++; + + desc->info2 = + le32_encode_bits(cmd->ba_window_size - 1, + HAL_REO_UPD_RX_QUEUE_INFO2_BA_WINDOW_SIZE) | + le32_encode_bits(cmd->pn_size, HAL_REO_UPD_RX_QUEUE_INFO2_PN_SIZE) | + le32_encode_bits(!!(cmd->upd2 & HAL_REO_CMD_UPD2_SVLD), + HAL_REO_UPD_RX_QUEUE_INFO2_SVLD) | + le32_encode_bits(u32_get_bits(cmd->upd2, HAL_REO_CMD_UPD2_SSN), + HAL_REO_UPD_RX_QUEUE_INFO2_SSN) | + le32_encode_bits(!!(cmd->upd2 & HAL_REO_CMD_UPD2_SEQ_2K_ERR), + HAL_REO_UPD_RX_QUEUE_INFO2_SEQ_2K_ERR) | + le32_encode_bits(!!(cmd->upd2 & HAL_REO_CMD_UPD2_PN_ERR), + HAL_REO_UPD_RX_QUEUE_INFO2_PN_ERR); + + return le32_get_bits(desc->cmd.info0, HAL_REO_CMD_HDR_INFO0_CMD_NUMBER); +} + +int ath12k_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng, + enum hal_reo_cmd_type type, + struct ath12k_hal_reo_cmd *cmd) +{ + struct hal_tlv_64_hdr *reo_desc; + int ret; + + spin_lock_bh(&srng->lock); + + ath12k_hal_srng_access_begin(ab, srng); + reo_desc = ath12k_hal_srng_src_get_next_entry(ab, srng); + if (!reo_desc) { + ret = -ENOBUFS; + goto out; + } + + switch (type) { + case HAL_REO_CMD_GET_QUEUE_STATS: + ret = ath12k_hal_reo_cmd_queue_stats(reo_desc, cmd); + break; + case HAL_REO_CMD_FLUSH_CACHE: + ret = ath12k_hal_reo_cmd_flush_cache(&ab->hal, reo_desc, cmd); + break; + case HAL_REO_CMD_UPDATE_RX_QUEUE: + ret = ath12k_hal_reo_cmd_update_rx_queue(reo_desc, cmd); + break; + case HAL_REO_CMD_FLUSH_QUEUE: + case HAL_REO_CMD_UNBLOCK_CACHE: + case HAL_REO_CMD_FLUSH_TIMEOUT_LIST: + ath12k_warn(ab, "Unsupported reo command %d\n", type); + ret = -ENOTSUPP; + break; + default: + ath12k_warn(ab, "Unknown reo command %d\n", type); + ret = -EINVAL; + break; + } + +out: + ath12k_hal_srng_access_end(ab, srng); + spin_unlock_bh(&srng->lock); + + return ret; +} + +void ath12k_hal_rx_buf_addr_info_set(struct ath12k_buffer_addr *binfo, + dma_addr_t paddr, u32 cookie, u8 manager) +{ + u32 paddr_lo, paddr_hi; + + paddr_lo = lower_32_bits(paddr); + paddr_hi = upper_32_bits(paddr); + binfo->info0 = le32_encode_bits(paddr_lo, BUFFER_ADDR_INFO0_ADDR); + binfo->info1 = le32_encode_bits(paddr_hi, BUFFER_ADDR_INFO1_ADDR) | + le32_encode_bits(cookie, BUFFER_ADDR_INFO1_SW_COOKIE) | + le32_encode_bits(manager, BUFFER_ADDR_INFO1_RET_BUF_MGR); +} + +void ath12k_hal_rx_buf_addr_info_get(struct ath12k_buffer_addr *binfo, + dma_addr_t *paddr, + u32 *cookie, u8 *rbm) +{ + *paddr = (((u64)le32_get_bits(binfo->info1, BUFFER_ADDR_INFO1_ADDR)) << 32) | + le32_get_bits(binfo->info0, BUFFER_ADDR_INFO0_ADDR); + *cookie = le32_get_bits(binfo->info1, BUFFER_ADDR_INFO1_SW_COOKIE); + *rbm = le32_get_bits(binfo->info1, BUFFER_ADDR_INFO1_RET_BUF_MGR); +} + +void ath12k_hal_rx_msdu_link_info_get(struct hal_rx_msdu_link *link, u32 *num_msdus, + u32 *msdu_cookies, + enum hal_rx_buf_return_buf_manager *rbm) +{ + struct hal_rx_msdu_details *msdu; + u32 val; + int i; + + *num_msdus = HAL_NUM_RX_MSDUS_PER_LINK_DESC; + + msdu = &link->msdu_link[0]; + *rbm = le32_get_bits(msdu->buf_addr_info.info1, + BUFFER_ADDR_INFO1_RET_BUF_MGR); + + for (i = 0; i < *num_msdus; i++) { + msdu = &link->msdu_link[i]; + + val = le32_get_bits(msdu->buf_addr_info.info0, + BUFFER_ADDR_INFO0_ADDR); + if (val == 0) { + *num_msdus = i; + break; + } + *msdu_cookies = le32_get_bits(msdu->buf_addr_info.info1, + BUFFER_ADDR_INFO1_SW_COOKIE); + msdu_cookies++; + } +} + +int ath12k_hal_desc_reo_parse_err(struct ath12k_base *ab, + struct hal_reo_dest_ring *desc, + dma_addr_t *paddr, u32 *desc_bank) +{ + enum hal_reo_dest_ring_push_reason push_reason; + enum hal_reo_dest_ring_error_code err_code; + u32 cookie, val; + + push_reason = le32_get_bits(desc->info0, + HAL_REO_DEST_RING_INFO0_PUSH_REASON); + err_code = le32_get_bits(desc->info0, + HAL_REO_DEST_RING_INFO0_ERROR_CODE); + ab->soc_stats.reo_error[err_code]++; + + if (push_reason != HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED && + push_reason != HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) { + ath12k_warn(ab, "expected error push reason code, received %d\n", + push_reason); + return -EINVAL; + } + + val = le32_get_bits(desc->info0, HAL_REO_DEST_RING_INFO0_BUFFER_TYPE); + if (val != HAL_REO_DEST_RING_BUFFER_TYPE_LINK_DESC) { + ath12k_warn(ab, "expected buffer type link_desc"); + return -EINVAL; + } + + ath12k_hal_rx_reo_ent_paddr_get(ab, &desc->buf_addr_info, paddr, &cookie); + *desc_bank = u32_get_bits(cookie, DP_LINK_DESC_BANK_MASK); + + return 0; +} + +int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc, + struct hal_rx_wbm_rel_info *rel_info) +{ + struct hal_wbm_release_ring *wbm_desc = desc; + struct hal_wbm_release_ring_cc_rx *wbm_cc_desc = desc; + enum hal_wbm_rel_desc_type type; + enum hal_wbm_rel_src_module rel_src; + bool hw_cc_done; + u64 desc_va; + u32 val; + + type = le32_get_bits(wbm_desc->info0, HAL_WBM_RELEASE_INFO0_DESC_TYPE); + /* We expect only WBM_REL buffer type */ + if (type != HAL_WBM_REL_DESC_TYPE_REL_MSDU) { + WARN_ON(1); + return -EINVAL; + } + + rel_src = le32_get_bits(wbm_desc->info0, + HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE); + if (rel_src != HAL_WBM_REL_SRC_MODULE_RXDMA && + rel_src != HAL_WBM_REL_SRC_MODULE_REO) + return -EINVAL; + + /* The format of wbm rel ring desc changes based on the + * hw cookie conversion status + */ + hw_cc_done = le32_get_bits(wbm_desc->info0, + HAL_WBM_RELEASE_RX_INFO0_CC_STATUS); + + if (!hw_cc_done) { + val = le32_get_bits(wbm_desc->buf_addr_info.info1, + BUFFER_ADDR_INFO1_RET_BUF_MGR); + if (val != HAL_RX_BUF_RBM_SW3_BM) { + ab->soc_stats.invalid_rbm++; + return -EINVAL; + } + + rel_info->cookie = le32_get_bits(wbm_desc->buf_addr_info.info1, + BUFFER_ADDR_INFO1_SW_COOKIE); + + rel_info->rx_desc = NULL; + } else { + val = le32_get_bits(wbm_cc_desc->info0, + HAL_WBM_RELEASE_RX_CC_INFO0_RBM); + if (val != HAL_RX_BUF_RBM_SW3_BM) { + ab->soc_stats.invalid_rbm++; + return -EINVAL; + } + + rel_info->cookie = le32_get_bits(wbm_cc_desc->info1, + HAL_WBM_RELEASE_RX_CC_INFO1_COOKIE); + + desc_va = ((u64)le32_to_cpu(wbm_cc_desc->buf_va_hi) << 32 | + le32_to_cpu(wbm_cc_desc->buf_va_lo)); + rel_info->rx_desc = + (struct ath12k_rx_desc_info *)((unsigned long)desc_va); + } + + rel_info->err_rel_src = rel_src; + rel_info->hw_cc_done = hw_cc_done; + + rel_info->first_msdu = le32_get_bits(wbm_desc->info3, + HAL_WBM_RELEASE_INFO3_FIRST_MSDU); + rel_info->last_msdu = le32_get_bits(wbm_desc->info3, + HAL_WBM_RELEASE_INFO3_LAST_MSDU); + rel_info->continuation = le32_get_bits(wbm_desc->info3, + HAL_WBM_RELEASE_INFO3_CONTINUATION); + + if (rel_info->err_rel_src == HAL_WBM_REL_SRC_MODULE_REO) { + rel_info->push_reason = + le32_get_bits(wbm_desc->info0, + HAL_WBM_RELEASE_INFO0_REO_PUSH_REASON); + rel_info->err_code = + le32_get_bits(wbm_desc->info0, + HAL_WBM_RELEASE_INFO0_REO_ERROR_CODE); + } else { + rel_info->push_reason = + le32_get_bits(wbm_desc->info0, + HAL_WBM_RELEASE_INFO0_RXDMA_PUSH_REASON); + rel_info->err_code = + le32_get_bits(wbm_desc->info0, + HAL_WBM_RELEASE_INFO0_RXDMA_ERROR_CODE); + } + + return 0; +} + +void ath12k_hal_rx_reo_ent_paddr_get(struct ath12k_base *ab, + struct ath12k_buffer_addr *buff_addr, + dma_addr_t *paddr, u32 *cookie) +{ + *paddr = ((u64)(le32_get_bits(buff_addr->info1, + BUFFER_ADDR_INFO1_ADDR)) << 32) | + le32_get_bits(buff_addr->info0, BUFFER_ADDR_INFO0_ADDR); + + *cookie = le32_get_bits(buff_addr->info1, BUFFER_ADDR_INFO1_SW_COOKIE); +} + +void ath12k_hal_rx_msdu_link_desc_set(struct ath12k_base *ab, + struct hal_wbm_release_ring *dst_desc, + struct hal_wbm_release_ring *src_desc, + enum hal_wbm_rel_bm_act action) +{ + dst_desc->buf_addr_info = src_desc->buf_addr_info; + dst_desc->info0 |= le32_encode_bits(HAL_WBM_REL_SRC_MODULE_SW, + HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE) | + le32_encode_bits(action, HAL_WBM_RELEASE_INFO0_BM_ACTION) | + le32_encode_bits(HAL_WBM_REL_DESC_TYPE_MSDU_LINK, + HAL_WBM_RELEASE_INFO0_DESC_TYPE); +} + +void ath12k_hal_reo_status_queue_stats(struct ath12k_base *ab, struct hal_tlv_64_hdr *tlv, + struct hal_reo_status *status) +{ + struct hal_reo_get_queue_stats_status *desc = + (struct hal_reo_get_queue_stats_status *)tlv->value; + + status->uniform_hdr.cmd_num = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_STATUS_NUM); + status->uniform_hdr.cmd_status = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS); + + ath12k_dbg(ab, ATH12K_DBG_HAL, "Queue stats status:\n"); + ath12k_dbg(ab, ATH12K_DBG_HAL, "header: cmd_num %d status %d\n", + status->uniform_hdr.cmd_num, + status->uniform_hdr.cmd_status); + ath12k_dbg(ab, ATH12K_DBG_HAL, "ssn %u cur_idx %u\n", + le32_get_bits(desc->info0, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_SSN), + le32_get_bits(desc->info0, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_CUR_IDX)); + ath12k_dbg(ab, ATH12K_DBG_HAL, "pn = [%08x, %08x, %08x, %08x]\n", + desc->pn[0], desc->pn[1], desc->pn[2], desc->pn[3]); + ath12k_dbg(ab, ATH12K_DBG_HAL, "last_rx: enqueue_tstamp %08x dequeue_tstamp %08x\n", + desc->last_rx_enqueue_timestamp, + desc->last_rx_dequeue_timestamp); + ath12k_dbg(ab, ATH12K_DBG_HAL, "rx_bitmap [%08x %08x %08x %08x %08x %08x %08x %08x]\n", + desc->rx_bitmap[0], desc->rx_bitmap[1], desc->rx_bitmap[2], + desc->rx_bitmap[3], desc->rx_bitmap[4], desc->rx_bitmap[5], + desc->rx_bitmap[6], desc->rx_bitmap[7]); + ath12k_dbg(ab, ATH12K_DBG_HAL, "count: cur_mpdu %u cur_msdu %u\n", + le32_get_bits(desc->info1, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MPDU_COUNT), + le32_get_bits(desc->info1, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MSDU_COUNT)); + ath12k_dbg(ab, ATH12K_DBG_HAL, "fwd_timeout %u fwd_bar %u dup_count %u\n", + le32_get_bits(desc->info2, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_TIMEOUT_COUNT), + le32_get_bits(desc->info2, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_FDTB_COUNT), + le32_get_bits(desc->info2, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_DUPLICATE_COUNT)); + ath12k_dbg(ab, ATH12K_DBG_HAL, "frames_in_order %u bar_rcvd %u\n", + le32_get_bits(desc->info3, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO3_FIO_COUNT), + le32_get_bits(desc->info3, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO3_BAR_RCVD_CNT)); + ath12k_dbg(ab, ATH12K_DBG_HAL, "num_mpdus %d num_msdus %d total_bytes %d\n", + desc->num_mpdu_frames, desc->num_msdu_frames, + desc->total_bytes); + ath12k_dbg(ab, ATH12K_DBG_HAL, "late_rcvd %u win_jump_2k %u hole_cnt %u\n", + le32_get_bits(desc->info4, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_LATE_RX_MPDU), + le32_get_bits(desc->info2, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_WINDOW_JMP2K), + le32_get_bits(desc->info4, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_HOLE_COUNT)); + ath12k_dbg(ab, ATH12K_DBG_HAL, "looping count %u\n", + le32_get_bits(desc->info5, + HAL_REO_GET_QUEUE_STATS_STATUS_INFO5_LOOPING_CNT)); +} + +void ath12k_hal_reo_flush_queue_status(struct ath12k_base *ab, struct hal_tlv_64_hdr *tlv, + struct hal_reo_status *status) +{ + struct hal_reo_flush_queue_status *desc = + (struct hal_reo_flush_queue_status *)tlv->value; + + status->uniform_hdr.cmd_num = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_STATUS_NUM); + status->uniform_hdr.cmd_status = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS); + status->u.flush_queue.err_detected = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_QUEUE_INFO0_ERR_DETECTED); +} + +void ath12k_hal_reo_flush_cache_status(struct ath12k_base *ab, struct hal_tlv_64_hdr *tlv, + struct hal_reo_status *status) +{ + struct ath12k_hal *hal = &ab->hal; + struct hal_reo_flush_cache_status *desc = + (struct hal_reo_flush_cache_status *)tlv->value; + + status->uniform_hdr.cmd_num = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_STATUS_NUM); + status->uniform_hdr.cmd_status = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS); + + status->u.flush_cache.err_detected = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_CACHE_STATUS_INFO0_IS_ERR); + status->u.flush_cache.err_code = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_CACHE_STATUS_INFO0_BLOCK_ERR_CODE); + if (!status->u.flush_cache.err_code) + hal->avail_blk_resource |= BIT(hal->current_blk_index); + + status->u.flush_cache.cache_controller_flush_status_hit = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_STATUS_HIT); + + status->u.flush_cache.cache_controller_flush_status_desc_type = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_DESC_TYPE); + status->u.flush_cache.cache_controller_flush_status_client_id = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_CLIENT_ID); + status->u.flush_cache.cache_controller_flush_status_err = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_ERR); + status->u.flush_cache.cache_controller_flush_status_cnt = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_COUNT); +} + +void ath12k_hal_reo_unblk_cache_status(struct ath12k_base *ab, struct hal_tlv_64_hdr *tlv, + struct hal_reo_status *status) +{ + struct ath12k_hal *hal = &ab->hal; + struct hal_reo_unblock_cache_status *desc = + (struct hal_reo_unblock_cache_status *)tlv->value; + + status->uniform_hdr.cmd_num = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_STATUS_NUM); + status->uniform_hdr.cmd_status = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS); + + status->u.unblock_cache.err_detected = + le32_get_bits(desc->info0, + HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_IS_ERR); + status->u.unblock_cache.unblock_type = + le32_get_bits(desc->info0, + HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_TYPE); + + if (!status->u.unblock_cache.err_detected && + status->u.unblock_cache.unblock_type == + HAL_REO_STATUS_UNBLOCK_BLOCKING_RESOURCE) + hal->avail_blk_resource &= ~BIT(hal->current_blk_index); +} + +void ath12k_hal_reo_flush_timeout_list_status(struct ath12k_base *ab, + struct hal_tlv_64_hdr *tlv, + struct hal_reo_status *status) +{ + struct hal_reo_flush_timeout_list_status *desc = + (struct hal_reo_flush_timeout_list_status *)tlv->value; + + status->uniform_hdr.cmd_num = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_STATUS_NUM); + status->uniform_hdr.cmd_status = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS); + + status->u.timeout_list.err_detected = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_IS_ERR); + status->u.timeout_list.list_empty = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_LIST_EMPTY); + + status->u.timeout_list.release_desc_cnt = + le32_get_bits(desc->info1, + HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_REL_DESC_COUNT); + status->u.timeout_list.fwd_buf_cnt = + le32_get_bits(desc->info0, + HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_FWD_BUF_COUNT); +} + +void ath12k_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab, + struct hal_tlv_64_hdr *tlv, + struct hal_reo_status *status) +{ + struct hal_reo_desc_thresh_reached_status *desc = + (struct hal_reo_desc_thresh_reached_status *)tlv->value; + + status->uniform_hdr.cmd_num = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_STATUS_NUM); + status->uniform_hdr.cmd_status = + le32_get_bits(desc->hdr.info0, + HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS); + + status->u.desc_thresh_reached.threshold_idx = + le32_get_bits(desc->info0, + HAL_REO_DESC_THRESH_STATUS_INFO0_THRESH_INDEX); + + status->u.desc_thresh_reached.link_desc_counter0 = + le32_get_bits(desc->info1, + HAL_REO_DESC_THRESH_STATUS_INFO1_LINK_DESC_COUNTER0); + + status->u.desc_thresh_reached.link_desc_counter1 = + le32_get_bits(desc->info2, + HAL_REO_DESC_THRESH_STATUS_INFO2_LINK_DESC_COUNTER1); + + status->u.desc_thresh_reached.link_desc_counter2 = + le32_get_bits(desc->info3, + HAL_REO_DESC_THRESH_STATUS_INFO3_LINK_DESC_COUNTER2); + + status->u.desc_thresh_reached.link_desc_counter_sum = + le32_get_bits(desc->info4, + HAL_REO_DESC_THRESH_STATUS_INFO4_LINK_DESC_COUNTER_SUM); +} + +void ath12k_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab, + struct hal_tlv_64_hdr *tlv, + struct hal_reo_status *status) +{ + struct hal_reo_status_hdr *desc = + (struct hal_reo_status_hdr *)tlv->value; + + status->uniform_hdr.cmd_num = + le32_get_bits(desc->info0, + HAL_REO_STATUS_HDR_INFO0_STATUS_NUM); + status->uniform_hdr.cmd_status = + le32_get_bits(desc->info0, + HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS); +} + +u32 ath12k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid) +{ + u32 num_ext_desc; + + if (ba_window_size <= 1) { + if (tid != HAL_DESC_REO_NON_QOS_TID) + num_ext_desc = 1; + else + num_ext_desc = 0; + } else if (ba_window_size <= 105) { + num_ext_desc = 1; + } else if (ba_window_size <= 210) { + num_ext_desc = 2; + } else { + num_ext_desc = 3; + } + + return sizeof(struct hal_rx_reo_queue) + + (num_ext_desc * sizeof(struct hal_rx_reo_queue_ext)); +} + +void ath12k_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc, + int tid, u32 ba_window_size, + u32 start_seq, enum hal_pn_type type) +{ + struct hal_rx_reo_queue_ext *ext_desc; + + memset(qdesc, 0, sizeof(*qdesc)); + + ath12k_hal_reo_set_desc_hdr(&qdesc->desc_hdr, HAL_DESC_REO_OWNED, + HAL_DESC_REO_QUEUE_DESC, + REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_0); + + qdesc->rx_queue_num = le32_encode_bits(tid, HAL_RX_REO_QUEUE_RX_QUEUE_NUMBER); + + qdesc->info0 = + le32_encode_bits(1, HAL_RX_REO_QUEUE_INFO0_VLD) | + le32_encode_bits(1, HAL_RX_REO_QUEUE_INFO0_ASSOC_LNK_DESC_COUNTER) | + le32_encode_bits(ath12k_tid_to_ac(tid), HAL_RX_REO_QUEUE_INFO0_AC); + + if (ba_window_size < 1) + ba_window_size = 1; + + if (ba_window_size == 1 && tid != HAL_DESC_REO_NON_QOS_TID) + ba_window_size++; + + if (ba_window_size == 1) + qdesc->info0 |= le32_encode_bits(1, HAL_RX_REO_QUEUE_INFO0_RETRY); + + qdesc->info0 |= le32_encode_bits(ba_window_size - 1, + HAL_RX_REO_QUEUE_INFO0_BA_WINDOW_SIZE); + switch (type) { + case HAL_PN_TYPE_NONE: + case HAL_PN_TYPE_WAPI_EVEN: + case HAL_PN_TYPE_WAPI_UNEVEN: + break; + case HAL_PN_TYPE_WPA: + qdesc->info0 |= + le32_encode_bits(1, HAL_RX_REO_QUEUE_INFO0_PN_CHECK) | + le32_encode_bits(HAL_RX_REO_QUEUE_PN_SIZE_48, + HAL_RX_REO_QUEUE_INFO0_PN_SIZE); + break; + } + + /* TODO: Set Ignore ampdu flags based on BA window size and/or + * AMPDU capabilities + */ + qdesc->info0 |= le32_encode_bits(1, HAL_RX_REO_QUEUE_INFO0_IGNORE_AMPDU_FLG); + + qdesc->info1 |= le32_encode_bits(0, HAL_RX_REO_QUEUE_INFO1_SVLD); + + if (start_seq <= 0xfff) + qdesc->info1 = le32_encode_bits(start_seq, + HAL_RX_REO_QUEUE_INFO1_SSN); + + if (tid == HAL_DESC_REO_NON_QOS_TID) + return; + + ext_desc = qdesc->ext_desc; + + /* TODO: HW queue descriptors are currently allocated for max BA + * window size for all QOS TIDs so that same descriptor can be used + * later when ADDBA request is received. This should be changed to + * allocate HW queue descriptors based on BA window size being + * negotiated (0 for non BA cases), and reallocate when BA window + * size changes and also send WMI message to FW to change the REO + * queue descriptor in Rx peer entry as part of dp_rx_tid_update. + */ + memset(ext_desc, 0, 3 * sizeof(*ext_desc)); + ath12k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED, + HAL_DESC_REO_QUEUE_EXT_DESC, + REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1); + ext_desc++; + ath12k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED, + HAL_DESC_REO_QUEUE_EXT_DESC, + REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2); + ext_desc++; + ath12k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED, + HAL_DESC_REO_QUEUE_EXT_DESC, + REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3); +} + +void ath12k_hal_reo_init_cmd_ring(struct ath12k_base *ab, + struct hal_srng *srng) +{ + struct hal_srng_params params; + struct hal_tlv_64_hdr *tlv; + struct hal_reo_get_queue_stats *desc; + int i, cmd_num = 1; + int entry_size; + u8 *entry; + + memset(¶ms, 0, sizeof(params)); + + entry_size = ath12k_hal_srng_get_entrysize(ab, HAL_REO_CMD); + ath12k_hal_srng_get_params(ab, srng, ¶ms); + entry = (u8 *)params.ring_base_vaddr; + + for (i = 0; i < params.num_entries; i++) { + tlv = (struct hal_tlv_64_hdr *)entry; + desc = (struct hal_reo_get_queue_stats *)tlv->value; + desc->cmd.info0 = le32_encode_bits(cmd_num++, + HAL_REO_CMD_HDR_INFO0_CMD_NUMBER); + entry += entry_size; + } +} + +void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map) +{ + u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG; + u32 val; + + val = ath12k_hif_read32(ab, reo_base + HAL_REO1_GEN_ENABLE); + + val |= u32_encode_bits(1, HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE) | + u32_encode_bits(1, HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE); + ath12k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); + + val = ath12k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR(ab)); + + val &= ~(HAL_REO1_MISC_CTL_FRAG_DST_RING | + HAL_REO1_MISC_CTL_BAR_DST_RING); + val |= u32_encode_bits(HAL_SRNG_RING_ID_REO2SW0, + HAL_REO1_MISC_CTL_FRAG_DST_RING); + val |= u32_encode_bits(HAL_SRNG_RING_ID_REO2SW0, + HAL_REO1_MISC_CTL_BAR_DST_RING); + ath12k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR(ab), val); + + ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab), + HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC); + ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_1(ab), + HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC); + ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_2(ab), + HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC); + ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3(ab), + HAL_DEFAULT_VO_REO_TIMEOUT_USEC); + + ath12k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2, + ring_hash_map); + ath12k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3, + ring_hash_map); +} -- cgit v1.2.3 From b57f03200853817c06567fa8f0d02de0f2755d6a Mon Sep 17 00:00:00 2001 From: Thiraviyam Mariyappan Date: Tue, 17 Jan 2023 14:03:18 +0200 Subject: wifi: ath12k: hal_rx: Use memset_startat() for clearing queue descriptors In preparation for FORTIFY_SOURCE performing compile-time and run-time field bounds checking for memset(), avoid intentionally writing across neighboring fields. Use memset_startat() so memset() doesn't get confused about writing beyond the destination member that is intended to be the starting point of zeroing through the end of the struct and fixes the below clang warning. Warning: include/linux/fortify-string.h:314:4: warning: call to '__write_overflow_field' declared with 'warning' attribute: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Wattribute-warning] Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0-03171-QCAHKSWPL_SILICONZ-1 Reported-by: kernel test robot Signed-off-by: Thiraviyam Mariyappan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20221221105529.19345-3-quic_tmariyap@quicinc.com --- drivers/net/wireless/ath/ath12k/hal_rx.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/ath/ath12k/hal_rx.c') diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/hal_rx.c index d47befb83e38..ee61a6462fdc 100644 --- a/drivers/net/wireless/ath/ath12k/hal_rx.c +++ b/drivers/net/wireless/ath/ath12k/hal_rx.c @@ -30,8 +30,7 @@ static int ath12k_hal_reo_cmd_queue_stats(struct hal_tlv_64_hdr *tlv, u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN); desc = (struct hal_reo_get_queue_stats *)tlv->value; - memset(&desc->queue_addr_lo, 0, - (sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr))); + memset_startat(desc, 0, queue_addr_lo); desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED); if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) @@ -64,8 +63,7 @@ static int ath12k_hal_reo_cmd_flush_cache(struct ath12k_hal *hal, u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN); desc = (struct hal_reo_flush_cache *)tlv->value; - memset(&desc->cache_addr_lo, 0, - (sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr))); + memset_startat(desc, 0, cache_addr_lo); desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED); if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) @@ -103,8 +101,7 @@ static int ath12k_hal_reo_cmd_update_rx_queue(struct hal_tlv_64_hdr *tlv, u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN); desc = (struct hal_reo_update_rx_queue *)tlv->value; - memset(&desc->queue_addr_lo, 0, - (sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr))); + memset_startat(desc, 0, queue_addr_lo); desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED); if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) -- cgit v1.2.3