From 3600a51a2519d7cd7d6098f61f4e0f3f0b92636a Mon Sep 17 00:00:00 2001 From: Karthik Kantamneni Date: Fri, 29 Sep 2023 12:52:30 +0530 Subject: [PATCH] qcacmn: Fix RXDMA null buffer address access issue During mon_pdev_init RX monitor status buffers will be attached to status ring. In case of buffer allocation failure HP will be pointing to null buffer address entry and during ring process this index slot will be skipped. This will lead to RXDMA accessing null buffer address descriptor. Fix this by adjusting the HP of monitor status ring during RX buffer allocation failures. Change-Id: I290a724fefc6f65be058a84c97b9e6d51a08ef39 CRs-Fixed: 3268663 --- dp/wifi3.0/monitor/1.0/dp_rx_mon_status_1.0.c | 14 +++++++++- hal/wifi3.0/hal_api.h | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/dp/wifi3.0/monitor/1.0/dp_rx_mon_status_1.0.c b/dp/wifi3.0/monitor/1.0/dp_rx_mon_status_1.0.c index dbc47c409f..244b1964f2 100644 --- a/dp/wifi3.0/monitor/1.0/dp_rx_mon_status_1.0.c +++ b/dp/wifi3.0/monitor/1.0/dp_rx_mon_status_1.0.c @@ -1033,6 +1033,7 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc, union dp_rx_desc_list_elem_t *next; void *rxdma_srng; struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(dp_soc, mac_id); + QDF_STATUS status = QDF_STATUS_SUCCESS; if (!dp_pdev) { dp_rx_mon_status_debug("%pK: pdev is null for mac_id = %d", @@ -1094,6 +1095,17 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc, if (qdf_unlikely(!rx_netbuf)) { dp_rx_mon_status_err("%pK: qdf_nbuf allocate or map fail, count %d", dp_soc, count); + /* + * If buffer allocation fails on current HP, then + * decrement HP so it will be set to previous index + * where proper buffer is attached. + */ + if (!count) + status = QDF_STATUS_E_NOMEM; + else + hal_srng_src_dec_hp(dp_soc->hal_soc, + rxdma_srng); + break; } @@ -1148,7 +1160,7 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc, mac_id, rx_desc_pool); } - return QDF_STATUS_SUCCESS; + return status; } #if !defined(DISABLE_MON_CONFIG) && defined(MON_ENABLE_DROP_FOR_MAC) diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index f444d993a4..5b5f157e6a 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -2178,6 +2178,34 @@ void *hal_srng_src_peek_n_get_next(hal_soc_handle_t hal_soc_hdl, return NULL; } +/** + * hal_srng_src_dec_hp - Decrement source srng HP to previous index + * @hal_soc_hdl: Opaque HAL SOC handle + * @hal_ring_hdl: Source ring pointer + * + * Return: None + */ +static inline +void hal_srng_src_dec_hp(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + uint32_t hp = srng->u.src_ring.hp; + + /* This HP adjustment is mostly done in error cases. + * Only local HP is being decremented not the value + * communicated to consumer or H.W. + */ + if (hp == srng->u.src_ring.cached_tp) + return; + else if (hp == 0) + hp = srng->ring_size - srng->entry_size; + else + hp = (hp - srng->entry_size) % srng->ring_size; + + srng->u.src_ring.hp = hp; +} + /** * hal_srng_src_peek_n_get_next_next() - Get next to next, i.e HP + 2 entry from * a ring without moving head pointer.