
Change REO queue descriptor delete sequence to flush base and extension descriptors separately, since flushing base descriptor alone results in extensions flushed by HW much later, sometimes after freeing descriptor memory, causing use-after-free corruptions. Also increase REO command and status ring sizes since number of commands per RX TID flush has increased with this change. Fix interrupt batch count setting for non pkt/buffer rings, which includes REO status ring. Also remove callbacks during reo command list destroy, done as part of SOC detach. This should not be done since callbacks will access stale data structures that are freed as part of PDEV/SOC detach. Change-Id: I4337454d3f53cc0b3c3014ef07cc2ba13cfebb18 CRs-Fixed: 2175989
326 lines
11 KiB
C
326 lines
11 KiB
C
/*
|
||
* Copyright (c) 2016-2018 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"
|
||
#include "qdf_module.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
|
||
|
||
/* 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);
|
||
/* Fixed pattern in reserved bits for debugging */
|
||
HAL_DESC_SET_FIELD(reo_queue_desc, UNIFORM_DESCRIPTOR_HEADER_0,
|
||
RESERVED_0A, 0xDDBEEF);
|
||
|
||
/* 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);
|
||
|
||
if (ba_window_size < 1)
|
||
ba_window_size = 1;
|
||
|
||
/* Set RTY bit for non-BA case. Duplicate detection is currently not
|
||
* done by HW in non-BA case if RTY bit is not set.
|
||
* TODO: This is a temporary War and should be removed once HW fix is
|
||
* made to check and discard duplicates even if RTY bit is not set.
|
||
*/
|
||
if (ba_window_size == 1)
|
||
HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, RTY, 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);
|
||
/* Fixed pattern in reserved bits for debugging */
|
||
HAL_DESC_SET_FIELD(reo_queue_ext_desc,
|
||
UNIFORM_DESCRIPTOR_HEADER_0, RESERVED_0A, 0xADBEEF);
|
||
/* 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);
|
||
/* Fixed pattern in reserved bits for debugging */
|
||
HAL_DESC_SET_FIELD(reo_queue_ext_desc,
|
||
UNIFORM_DESCRIPTOR_HEADER_0, RESERVED_0A, 0xBDBEEF);
|
||
/* 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);
|
||
/* Fixed pattern in reserved bits for debugging */
|
||
HAL_DESC_SET_FIELD(reo_queue_ext_desc,
|
||
UNIFORM_DESCRIPTOR_HEADER_0, RESERVED_0A, 0xCDBEEF);
|
||
}
|
||
#endif
|
||
}
|
||
qdf_export_symbol(hal_reo_qdesc_setup);
|
||
|
||
|
||
/**
|
||
* hal_reo_setup - Initialize HW REO block
|
||
*
|
||
* @hal_soc: Opaque HAL SOC handle
|
||
* @reo_params: parameters needed by HAL for REO config
|
||
*/
|
||
void hal_reo_setup(void *hal_soc,
|
||
struct hal_reo_params *reo_params)
|
||
{
|
||
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, reo_params->frag_dst_ring) |
|
||
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));
|
||
|
||
/*
|
||
* When hash based routing is enabled, routing of the rx packet
|
||
* is done based on the following value: 1 _ _ _ _ The last 4
|
||
* bits are based on hash[3:0]. This means the possible values
|
||
* are 0x10 to 0x1f. This value is used to look-up the
|
||
* ring ID configured in Destination_Ring_Ctrl_IX_* register.
|
||
* The Destination_Ring_Ctrl_IX_2 and Destination_Ring_Ctrl_IX_3
|
||
* registers need to be configured to set-up the 16 entries to
|
||
* map the hash values to a ring number. There are 3 bits per
|
||
* hash entry which are mapped as follows:
|
||
* 0: TCL, 1:SW1, 2:SW2, * 3:SW3, 4:SW4, 5:Release, 6:FW(WIFI),
|
||
* 7: NOT_USED.
|
||
*/
|
||
if (reo_params->rx_hash_enabled) {
|
||
HAL_REG_WRITE(soc,
|
||
HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR(
|
||
SEQ_WCSS_UMAC_REO_REG_OFFSET),
|
||
reo_params->remap1);
|
||
|
||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||
FL("HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR 0x%x\n"),
|
||
HAL_REG_READ(soc,
|
||
HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR(
|
||
SEQ_WCSS_UMAC_REO_REG_OFFSET)));
|
||
|
||
HAL_REG_WRITE(soc,
|
||
HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR(
|
||
SEQ_WCSS_UMAC_REO_REG_OFFSET),
|
||
reo_params->remap2);
|
||
|
||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||
FL("HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR 0x%x\n"),
|
||
HAL_REG_READ(soc,
|
||
HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR(
|
||
SEQ_WCSS_UMAC_REO_REG_OFFSET)));
|
||
}
|
||
|
||
|
||
/* 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
|
||
*/
|
||
}
|
||
qdf_export_symbol(hal_reo_setup);
|
||
|