qcacmn: gracefully handle error packets on partner soc

Ideally in MLO, Rx buffers should be routed to error
rings of the SOC which owns the RX buffer or link desc
incase of any error or fragment

But in case of HW issue if the packets are routed to
partner soc. Handle gracefully instead of assert

Change-Id: Ia56188808dfd034e960e1c1345de8f760e4b05f1
CRs-Fixed: 3327959
This commit is contained in:
Chaithanya Garrepalli
2022-11-04 09:17:03 +05:30
committed by Madan Koyyalamudi
parent f0811fb133
commit 86f7649e19
6 changed files with 127 additions and 28 deletions

View File

@@ -2205,20 +2205,52 @@ static int dp_rx_err_exception(struct dp_soc *soc, hal_ring_desc_t ring_desc)
#endif /* HANDLE_RX_REROUTE_ERR */
#ifdef WLAN_MLO_MULTI_CHIP
static void dp_idle_link_bm_id_check(struct dp_soc *soc, uint8_t rbm)
/*
* dp_idle_link_bm_id_check() - war for HW issue
*
* This is a war for HW issue where link descriptor
* of partner soc received due to packets wrongly
* interpreted as fragments
*
* @soc: DP SOC handle
* @rbm: idle link RBM value
* @ring_desc: reo error link descriptor
*
* returns: true in case link desc is consumed
* false in other cases
*/
static bool dp_idle_link_bm_id_check(struct dp_soc *soc, uint8_t rbm,
void *ring_desc)
{
struct dp_soc *replenish_soc = NULL;
/* return ok incase of link desc of same soc */
if (rbm == soc->idle_link_bm_id)
return false;
if (soc->arch_ops.dp_soc_get_by_idle_bm_id)
replenish_soc =
soc->arch_ops.dp_soc_get_by_idle_bm_id(soc, rbm);
qdf_assert_always(replenish_soc);
/*
* For WIN usecase we should only get fragment packets in
* this ring as for MLO case fragmentation is not supported
* we should not see links from other soc.
*
* Adding a assert for link descriptors from local soc
* Drop all packets from partner soc and replenish the descriptors
*/
qdf_assert_always(rbm == soc->idle_link_bm_id);
dp_handle_wbm_internal_error(replenish_soc, ring_desc,
HAL_WBM_RELEASE_RING_2_DESC_TYPE);
return true;
}
#else
static void dp_idle_link_bm_id_check(struct dp_soc *soc, uint8_t rbm)
static bool dp_idle_link_bm_id_check(struct dp_soc *soc, uint8_t rbm,
void *ring_desc)
{
return false;
}
#endif
@@ -2323,7 +2355,10 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
qdf_assert_always((hbi.sw_cookie >> LINK_DESC_ID_SHIFT) &
soc->link_desc_id_start);
dp_idle_link_bm_id_check(soc, hbi.rbm);
if (dp_idle_link_bm_id_check(soc, hbi.rbm, ring_desc)) {
DP_STATS_INC(soc, rx.err.invalid_link_cookie, 1);
goto next_entry;
}
status = dp_rx_link_cookie_check(ring_desc);
if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
@@ -2642,10 +2677,12 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
hal_ring_desc_t ring_desc;
hal_soc_handle_t hal_soc;
struct dp_rx_desc *rx_desc;
union dp_rx_desc_list_elem_t *head[MAX_PDEV_CNT] = { NULL };
union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT] = { NULL };
union dp_rx_desc_list_elem_t
*head[WLAN_MAX_MLO_CHIPS][MAX_PDEV_CNT] = { { NULL } };
union dp_rx_desc_list_elem_t
*tail[WLAN_MAX_MLO_CHIPS][MAX_PDEV_CNT] = { { NULL } };
uint32_t rx_bufs_used = 0;
uint32_t rx_bufs_reaped[MAX_PDEV_CNT] = { 0 };
uint32_t rx_bufs_reaped[WLAN_MAX_MLO_CHIPS][MAX_PDEV_CNT] = { { 0 } };
uint8_t buf_type;
uint8_t mac_id;
struct dp_pdev *dp_pdev;
@@ -2663,6 +2700,8 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
bool process_sg_buf = false;
uint32_t wbm_err_src;
QDF_STATUS status;
struct dp_soc *replenish_soc;
uint8_t chip_id;
struct hal_rx_mpdu_desc_info mpdu_desc_info = { 0 };
/* Debug -- Remove later */
@@ -2742,11 +2781,12 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
nbuf);
rx_desc->in_err_state = 1;
rx_desc->unmapped = 1;
rx_bufs_reaped[rx_desc->pool_id]++;
dp_rx_add_to_free_desc_list(&head[rx_desc->pool_id],
&tail[rx_desc->pool_id],
rx_desc);
rx_bufs_reaped[rx_desc->chip_id][rx_desc->pool_id]++;
dp_rx_add_to_free_desc_list(
&head[rx_desc->chip_id][rx_desc->pool_id],
&tail[rx_desc->chip_id][rx_desc->pool_id],
rx_desc);
continue;
}
@@ -2804,7 +2844,7 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
(uint8_t *)&wbm_err_info,
sizeof(wbm_err_info));
rx_bufs_reaped[rx_desc->pool_id]++;
rx_bufs_reaped[rx_desc->chip_id][rx_desc->pool_id]++;
if (qdf_nbuf_is_rx_chfrag_cont(nbuf) || process_sg_buf) {
DP_RX_LIST_APPEND(soc->wbm_sg_param.wbm_sg_nbuf_head,
@@ -2828,9 +2868,9 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
DP_RX_LIST_APPEND(nbuf_head, nbuf_tail, nbuf);
}
dp_rx_add_to_free_desc_list(&head[rx_desc->pool_id],
&tail[rx_desc->pool_id],
rx_desc);
dp_rx_add_to_free_desc_list
(&head[rx_desc->chip_id][rx_desc->pool_id],
&tail[rx_desc->chip_id][rx_desc->pool_id], rx_desc);
/*
* if continuation bit is set then we have MSDU spread
@@ -2843,15 +2883,30 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
done:
dp_srng_access_end(int_ctx, soc, hal_ring_hdl);
for (mac_id = 0; mac_id < MAX_PDEV_CNT; mac_id++) {
if (rx_bufs_reaped[mac_id]) {
dp_rxdma_srng = &soc->rx_refill_buf_ring[mac_id];
rx_desc_pool = &soc->rx_desc_buf[mac_id];
for (chip_id = 0; chip_id < WLAN_MAX_MLO_CHIPS; chip_id++) {
for (mac_id = 0; mac_id < MAX_PDEV_CNT; mac_id++) {
/*
* continue with next mac_id if no pkts were reaped
* from that pool
*/
if (!rx_bufs_reaped[chip_id][mac_id])
continue;
dp_rx_buffers_replenish(soc, mac_id, dp_rxdma_srng,
rx_desc_pool, rx_bufs_reaped[mac_id],
&head[mac_id], &tail[mac_id], false);
rx_bufs_used += rx_bufs_reaped[mac_id];
replenish_soc =
soc->arch_ops.dp_rx_replenish_soc_get(soc, chip_id);
dp_rxdma_srng =
&replenish_soc->rx_refill_buf_ring[mac_id];
rx_desc_pool = &replenish_soc->rx_desc_buf[mac_id];
dp_rx_buffers_replenish(replenish_soc, mac_id,
dp_rxdma_srng,
rx_desc_pool,
rx_bufs_reaped[chip_id][mac_id],
&head[chip_id][mac_id],
&tail[chip_id][mac_id], false);
rx_bufs_used += rx_bufs_reaped[chip_id][mac_id];
}
}
@@ -3531,7 +3586,6 @@ dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc,
/* buffer_addr_info is the first element of ring_desc */
hal_rx_buf_cookie_rbm_get(soc->hal_soc, (uint32_t *)hal_desc,
&buf_info);
pool_id = DP_RX_DESC_COOKIE_POOL_ID_GET(buf_info.sw_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);
@@ -3556,6 +3610,8 @@ dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc,
rx_bufs_reaped[rx_desc->pool_id]++;
}
} else if (buf_type == HAL_WBM_RELEASE_RING_2_DESC_TYPE) {
pool_id = DP_RX_DESC_COOKIE_POOL_ID_GET(buf_info.sw_cookie);
dp_wbm_int_err_mpdu_pop(soc, pool_id, hal_desc,
&head, &tail, rx_bufs_reaped);
}