qcacmn: Handle wbm_internal_error in tx completions

Handle wbm_internal_error in tx completions by releasing
associated descriptors and buffers.

Change-Id: I94d334c90c0514674323430fe53da72fb5424576
This commit is contained in:
Pavankumar Nandeshwar
2019-10-07 12:55:16 +05:30
committed by nshrivas
parent 2a7ed0abd3
commit b86ddaf205
6 changed files with 181 additions and 4 deletions

View File

@@ -1834,3 +1834,153 @@ dp_rxdma_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
return work_done;
}
static inline uint32_t
dp_wbm_int_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
hal_rxdma_desc_t rxdma_dst_ring_desc,
union dp_rx_desc_list_elem_t **head,
union dp_rx_desc_list_elem_t **tail)
{
void *rx_msdu_link_desc;
qdf_nbuf_t msdu;
qdf_nbuf_t last;
struct hal_rx_msdu_list msdu_list;
uint16_t num_msdus;
struct hal_buf_info buf_info;
void *p_buf_addr_info;
void *p_last_buf_addr_info;
uint32_t rx_bufs_used = 0;
uint32_t msdu_cnt;
uint32_t i;
msdu = 0;
last = NULL;
hal_rx_reo_ent_buf_paddr_get(rxdma_dst_ring_desc, &buf_info,
&p_last_buf_addr_info, &msdu_cnt);
do {
rx_msdu_link_desc =
dp_rx_cookie_2_link_desc_va(soc, &buf_info);
if (!rx_msdu_link_desc) {
DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_LINK_DESC], 1);
break;
}
hal_rx_msdu_list_get(soc->hal_soc, rx_msdu_link_desc,
&msdu_list, &num_msdus);
if (msdu_list.sw_cookie[0] != HAL_RX_COOKIE_SPECIAL) {
for (i = 0; i < num_msdus; i++) {
struct dp_rx_desc *rx_desc =
dp_rx_cookie_2_va_rxdma_buf(
soc,
msdu_list.sw_cookie[i]);
qdf_assert_always(rx_desc);
msdu = rx_desc->nbuf;
qdf_nbuf_unmap_single(soc->osdev, msdu,
QDF_DMA_FROM_DEVICE);
qdf_nbuf_free(msdu);
rx_bufs_used++;
dp_rx_add_to_free_desc_list(head,
tail, rx_desc);
}
}
hal_rx_mon_next_link_desc_get(rx_msdu_link_desc, &buf_info,
&p_buf_addr_info);
dp_rx_link_desc_return(soc, p_last_buf_addr_info,
HAL_BM_ACTION_PUT_IN_IDLE_LIST);
p_last_buf_addr_info = p_buf_addr_info;
} while (buf_info.paddr);
return rx_bufs_used;
}
/*
*
* dp_handle_wbm_internal_error() - handles wbm_internal_error case
*
* @soc: core DP main context
* @hal_desc: hal descriptor
* @buf_type: indicates if the buffer is of type link disc or msdu
* Return: None
*
* wbm_internal_error is seen in following scenarios :
*
* 1. Null pointers detected in WBM_RELEASE_RING descriptors
* 2. Null pointers detected during delinking process
*
* Some null pointer cases:
*
* a. MSDU buffer pointer is NULL
* b. Next_MSDU_Link_Desc pointer is NULL, with no last msdu flag
* c. MSDU buffer pointer is NULL or Next_Link_Desc pointer is NULL
*/
void
dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc,
uint32_t buf_type)
{
struct hal_buf_info buf_info = {0};
struct dp_pdev *dp_pdev;
struct dp_rx_desc *rx_desc = NULL;
uint32_t rx_buf_cookie;
uint32_t rx_bufs_reaped = 0;
union dp_rx_desc_list_elem_t *head = NULL;
union dp_rx_desc_list_elem_t *tail = NULL;
uint8_t pool_id;
hal_rx_reo_buf_paddr_get(hal_desc, &buf_info);
if (!buf_info.paddr) {
DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_BUFFER], 1);
return;
}
rx_buf_cookie = HAL_RX_REO_BUF_COOKIE_GET(hal_desc);
pool_id = DP_RX_DESC_COOKIE_POOL_ID_GET(rx_buf_cookie);
if (buf_type == HAL_WBM_RELEASE_RING_2_BUFFER_TYPE) {
DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_MSDU_BUFF], 1);
rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, rx_buf_cookie);
if (rx_desc && rx_desc->nbuf) {
qdf_nbuf_unmap_single(soc->osdev, rx_desc->nbuf,
QDF_DMA_FROM_DEVICE);
rx_desc->unmapped = 1;
qdf_nbuf_free(rx_desc->nbuf);
dp_rx_add_to_free_desc_list(&head,
&tail,
rx_desc);
rx_bufs_reaped++;
}
} else if (buf_type == HAL_WBM_RELEASE_RING_2_DESC_TYPE) {
rx_bufs_reaped = dp_wbm_int_err_mpdu_pop(soc, pool_id,
hal_desc,
&head, &tail);
}
if (rx_bufs_reaped) {
struct rx_desc_pool *rx_desc_pool;
struct dp_srng *dp_rxdma_srng;
DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_REO_BUFF_REAPED], 1);
dp_pdev = soc->pdev_list[pool_id];
dp_rxdma_srng = &dp_pdev->rx_refill_buf_ring;
rx_desc_pool = &soc->rx_desc_buf[pool_id];
dp_rx_buffers_replenish(soc, pool_id, dp_rxdma_srng,
rx_desc_pool,
rx_bufs_reaped,
&head, &tail);
}
}

View File

@@ -5597,8 +5597,12 @@ dp_print_soc_tx_stats(struct dp_soc *soc)
soc->stats.tx.tcl_ring_full[2]);
DP_PRINT_STATS("Tx invalid completion release = %d",
soc->stats.tx.invalid_release_source);
DP_PRINT_STATS("Tx comp wbm internal error = %d",
soc->stats.tx.wbm_internal_error);
DP_PRINT_STATS("Tx comp wbm internal error = %d : [%d %d %d %d]",
soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_ALL],
soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_BUFFER],
soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_LINK_DESC],
soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_MSDU_BUFF],
soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_REO_BUFF_REAPED]);
DP_PRINT_STATS("Tx comp loop pkt limit hit = %d",
soc->stats.tx.tx_comp_loop_pkt_limit_hit);
DP_PRINT_STATS("Tx comp HP out of sync2 = %d",

View File

@@ -3472,7 +3472,16 @@ more_data:
QDF_TRACE(QDF_MODULE_ID_DP,
QDF_TRACE_LEVEL_ERROR,
"Tx comp wbm_internal_error!!!\n");
DP_STATS_INC(soc, tx.wbm_internal_error, 1);
DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_ALL], 1);
if (HAL_TX_COMP_RELEASE_SOURCE_REO ==
buffer_src)
dp_handle_wbm_internal_error(
soc,
tx_comp_hal_desc,
hal_tx_comp_get_buffer_type(
tx_comp_hal_desc));
continue;
} else {
qdf_assert_always(0);

View File

@@ -330,6 +330,10 @@ void dp_iterate_update_peer_list(struct cdp_pdev *pdev_hdl);
#define DP_TX_TID_OVERRIDE(_msdu_info, _nbuf)
#endif
void
dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc,
uint32_t buf_type);
/* TODO TX_FEATURE_NOT_YET */
static inline void dp_tx_comp_process_exception(struct dp_tx_desc_s *tx_desc)
{

View File

@@ -88,6 +88,13 @@
#define DP_MAX_IRQ_PER_CONTEXT 12
#define DEFAULT_HW_PEER_ID 0xffff
#define WBM_INT_ERROR_ALL 0
#define WBM_INT_ERROR_REO_NULL_BUFFER 1
#define WBM_INT_ERROR_REO_NULL_LINK_DESC 2
#define WBM_INT_ERROR_REO_NULL_MSDU_BUFF 3
#define WBM_INT_ERROR_REO_BUFF_REAPED 4
#define MAX_WBM_INT_ERROR_REASONS 5
#define MAX_TX_HW_QUEUES MAX_TCL_DATA_RINGS
/* Maximum retries for Delba per tid per peer */
#define DP_MAX_DELBA_RETRY 3
@@ -662,7 +669,7 @@ struct dp_soc_stats {
/* tx completion release_src != TQM or FW */
uint32_t invalid_release_source;
/* tx completion wbm_internal_error */
uint32_t wbm_internal_error;
uint32_t wbm_internal_error[MAX_WBM_INT_ERROR_REASONS];
/* TX Comp loop packet limit hit */
uint32_t tx_comp_loop_pkt_limit_hit;
/* Head pointer Out of sync at the end of dp_tx_comp_handler */

View File

@@ -29,6 +29,8 @@
#define WBM_RELEASE_RING_5_TX_RATE_STATS_LSB 0
#define WBM_RELEASE_RING_5_TX_RATE_STATS_MASK 0xffffffff
#define HAL_WBM_RELEASE_RING_2_BUFFER_TYPE 0
#define HAL_WBM_RELEASE_RING_2_DESC_TYPE 1
/*---------------------------------------------------------------------------
Preprocessor definitions and constants
@@ -91,6 +93,7 @@ do { \
#define HAL_TX_COMPLETION_DESC_BASE_LEN 12
#define HAL_TX_COMP_RELEASE_SOURCE_TQM 0
#define HAL_TX_COMP_RELEASE_SOURCE_REO 2
#define HAL_TX_COMP_RELEASE_SOURCE_FW 3
/* Define a place-holder release reason for FW */