123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- #include "hal_api.h"
- /* TODO: See if the following definition is available in HW headers */
- #define HAL_REO_OWNED 4
- #define HAL_REO_QUEUE_DESC 8
- #define HAL_REO_QUEUE_EXT_DESC 9
- #define PN_SIZE_24 0
- #define PN_SIZE_48 1
- #define PN_SIZE_128 2
- /* TODO: Using associated link desc counter 1 for Rx. Check with FW on
- * how these counters are assigned
- */
- #define HAL_RX_LINK_DESC_CNTR 1
- /* TODO: Following definition should be from HW headers */
- #define HAL_DESC_REO_OWNED 4
- /* TODO: Move this to common header file */
- static inline void hal_uniform_desc_hdr_setup(uint32_t *desc, uint32_t owner,
- uint32_t buffer_type)
- {
- HAL_DESC_SET_FIELD(desc, UNIFORM_DESCRIPTOR_HEADER_0, OWNER,
- owner);
- HAL_DESC_SET_FIELD(desc, UNIFORM_DESCRIPTOR_HEADER_0, BUFFER_TYPE,
- buffer_type);
- }
- #ifndef TID_TO_WME_AC
- #define WME_AC_BE 0 /* best effort */
- #define WME_AC_BK 1 /* background */
- #define WME_AC_VI 2 /* video */
- #define WME_AC_VO 3 /* voice */
- #define TID_TO_WME_AC(_tid) ( \
- (((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
- (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
- (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
- WME_AC_VO)
- #endif
- #define HAL_NON_QOS_TID 16
- /**
- * hal_reo_qdesc_setup - Setup HW REO queue descriptor
- *
- * @hal_soc: Opaque HAL SOC handle
- * @ba_window_size: BlockAck window size
- * @start_seq: Starting sequence number
- * @hw_qdesc_vaddr: Virtual address of REO queue descriptor memory
- * @hw_qdesc_paddr: Physical address of REO queue descriptor memory
- * @tid: TID
- *
- */
- void hal_reo_qdesc_setup(void *hal_soc, int tid, uint32_t ba_window_size,
- uint32_t start_seq, void *hw_qdesc_vaddr, qdf_dma_addr_t hw_qdesc_paddr,
- int pn_type)
- {
- uint32_t *reo_queue_desc = (uint32_t *)hw_qdesc_vaddr;
- uint32_t *reo_queue_ext_desc;
- uint32_t reg_val;
- uint32_t pn_enable, pn_size;
- qdf_mem_zero(hw_qdesc_vaddr, sizeof(struct rx_reo_queue));
- hal_uniform_desc_hdr_setup(reo_queue_desc, HAL_DESC_REO_OWNED,
- HAL_REO_QUEUE_DESC);
- /* This a just a SW meta data and will be copied to REO destination
- * descriptors indicated by hardware.
- * TODO: Setting TID in this field. See if we should set something else.
- */
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_1,
- RECEIVE_QUEUE_NUMBER, tid);
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2,
- VLD, 1);
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2,
- ASSOCIATED_LINK_DESCRIPTOR_COUNTER, HAL_RX_LINK_DESC_CNTR);
- /*
- * Fields DISABLE_DUPLICATE_DETECTION and SOFT_REORDER_ENABLE will be 0
- */
- reg_val = TID_TO_WME_AC(tid);
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, AC, reg_val);
- /* Check the purpose of RTY field.
- * HW documentation says "Retry bit is checked if this bit is set"
- */
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, CHK_2K_MODE, 1);
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, OOR_MODE, 1);
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, BA_WINDOW_SIZE,
- ba_window_size - 1);
- switch (pn_type) {
- case HAL_PN_WPA:
- pn_enable = 1;
- pn_size = PN_SIZE_48;
- case HAL_PN_WAPI_EVEN:
- case HAL_PN_WAPI_UNEVEN:
- pn_enable = 1;
- pn_size = PN_SIZE_128;
- default:
- pn_enable = 0;
- }
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, PN_CHECK_NEEDED,
- pn_enable);
- if (pn_type == HAL_PN_WAPI_EVEN)
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2,
- PN_SHALL_BE_EVEN, 1);
- else if (pn_type == HAL_PN_WAPI_UNEVEN)
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2,
- PN_SHALL_BE_UNEVEN, 1);
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, PN_HANDLING_ENABLE,
- pn_enable);
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, PN_SIZE,
- pn_size);
- /* TODO: Check if RX_REO_QUEUE_2_IGNORE_AMPDU_FLAG need to be set
- * based on BA window size and/or AMPDU capabilities
- */
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2,
- IGNORE_AMPDU_FLAG, 1);
- if (start_seq <= 0xfff)
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_3, SSN,
- start_seq);
- /* TODO: SVLD should be set to 1 if a valid SSN is received in ADDBA,
- * but REO is not delivering packets if we set it to 1. Need to enable
- * this once the issue is resolved */
- HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_3, SVLD, 0);
- /* TODO: Check if we should set start PN for WAPI */
- #ifdef notyet
- /* Setup first queue extension if BA window size is more than 1 */
- if (ba_window_size > 1) {
- reo_queue_ext_desc =
- (uint32_t *)(((struct rx_reo_queue *)reo_queue_desc) +
- 1);
- qdf_mem_zero(reo_queue_ext_desc,
- sizeof(struct rx_reo_queue_ext));
- hal_uniform_desc_hdr_setup(reo_queue_ext_desc,
- HAL_DESC_REO_OWNED, HAL_REO_QUEUE_EXT_DESC);
- }
- /* Setup second queue extension if BA window size is more than 105 */
- if (ba_window_size > 105) {
- reo_queue_ext_desc = (uint32_t *)
- (((struct rx_reo_queue_ext *)reo_queue_ext_desc) + 1);
- qdf_mem_zero(reo_queue_ext_desc,
- sizeof(struct rx_reo_queue_ext));
- hal_uniform_desc_hdr_setup(reo_queue_ext_desc,
- HAL_DESC_REO_OWNED, HAL_REO_QUEUE_EXT_DESC);
- }
- /* Setup third queue extension if BA window size is more than 210 */
- if (ba_window_size > 210) {
- reo_queue_ext_desc = (uint32_t *)
- (((struct rx_reo_queue_ext *)reo_queue_ext_desc) + 1);
- qdf_mem_zero(reo_queue_ext_desc,
- sizeof(struct rx_reo_queue_ext));
- hal_uniform_desc_hdr_setup(reo_queue_ext_desc,
- HAL_DESC_REO_OWNED, HAL_REO_QUEUE_EXT_DESC);
- }
- #else
- /* 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 recevied. 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.
- */
- if (tid != HAL_NON_QOS_TID) {
- reo_queue_ext_desc = (uint32_t *)
- (((struct rx_reo_queue *)reo_queue_desc) + 1);
- qdf_mem_zero(reo_queue_ext_desc, 3 *
- sizeof(struct rx_reo_queue_ext));
- /* Initialize first reo queue extension descriptor */
- hal_uniform_desc_hdr_setup(reo_queue_ext_desc,
- HAL_DESC_REO_OWNED, HAL_REO_QUEUE_EXT_DESC);
- /* Initialize second reo queue extension descriptor */
- reo_queue_ext_desc = (uint32_t *)
- (((struct rx_reo_queue_ext *)reo_queue_ext_desc) + 1);
- hal_uniform_desc_hdr_setup(reo_queue_ext_desc,
- HAL_DESC_REO_OWNED, HAL_REO_QUEUE_EXT_DESC);
- /* Initialize third reo queue extension descriptor */
- reo_queue_ext_desc = (uint32_t *)
- (((struct rx_reo_queue_ext *)reo_queue_ext_desc) + 1);
- hal_uniform_desc_hdr_setup(reo_queue_ext_desc,
- HAL_DESC_REO_OWNED, HAL_REO_QUEUE_EXT_DESC);
- }
- #endif
- }
- /**
- * hal_reo_setup - Initialize HW REO block
- *
- * @hal_soc: Opaque HAL SOC handle
- */
- void hal_reo_setup(void *hal_soc)
- {
- struct hal_soc *soc = (struct hal_soc *)hal_soc;
- HAL_REG_WRITE(soc, HWIO_REO_R0_GENERAL_ENABLE_ADDR(
- SEQ_WCSS_UMAC_REO_REG_OFFSET),
- HAL_SM(HWIO_REO_R0_GENERAL_ENABLE,
- FRAGMENT_DEST_RING, HAL_SRNG_REO_EXCEPTION) |
- HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, AGING_LIST_ENABLE, 1) |
- HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, AGING_FLUSH_ENABLE, 1));
- /* Other ring enable bits and REO_ENABLE will be set by FW */
- /* TODO: Setup destination ring mapping if enabled */
- /* TODO: Error destination ring setting is left to default.
- * Default setting is to send all errors to release ring.
- */
- HAL_REG_WRITE(soc,
- HWIO_REO_R0_AGING_THRESHOLD_IX_0_ADDR(
- SEQ_WCSS_UMAC_REO_REG_OFFSET),
- HAL_DEFAULT_REO_TIMEOUT_MS * 1000);
- HAL_REG_WRITE(soc,
- HWIO_REO_R0_AGING_THRESHOLD_IX_1_ADDR(
- SEQ_WCSS_UMAC_REO_REG_OFFSET),
- (HAL_DEFAULT_REO_TIMEOUT_MS * 1000));
- HAL_REG_WRITE(soc,
- HWIO_REO_R0_AGING_THRESHOLD_IX_2_ADDR(
- SEQ_WCSS_UMAC_REO_REG_OFFSET),
- (HAL_DEFAULT_REO_TIMEOUT_MS * 1000));
- HAL_REG_WRITE(soc,
- HWIO_REO_R0_AGING_THRESHOLD_IX_3_ADDR(
- SEQ_WCSS_UMAC_REO_REG_OFFSET),
- (HAL_DEFAULT_REO_TIMEOUT_MS * 1000));
- /* TODO: Check if the following registers shoould be setup by host:
- * AGING_CONTROL
- * HIGH_MEMORY_THRESHOLD
- * GLOBAL_LINK_DESC_COUNT_THRESH_IX_0[1,2]
- * GLOBAL_LINK_DESC_COUNT_CTRL
- */
- }
|