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
Cette révision appartient à :
Karthik Kantamneni
2023-09-29 12:52:30 +05:30
révisé par Rahul Choudhary
Parent 0fc63202c0
révision 3600a51a25
2 fichiers modifiés avec 41 ajouts et 1 suppressions

Voir le fichier

@@ -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; union dp_rx_desc_list_elem_t *next;
void *rxdma_srng; void *rxdma_srng;
struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(dp_soc, mac_id); struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(dp_soc, mac_id);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!dp_pdev) { if (!dp_pdev) {
dp_rx_mon_status_debug("%pK: pdev is null for mac_id = %d", 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)) { if (qdf_unlikely(!rx_netbuf)) {
dp_rx_mon_status_err("%pK: qdf_nbuf allocate or map fail, count %d", dp_rx_mon_status_err("%pK: qdf_nbuf allocate or map fail, count %d",
dp_soc, count); 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; break;
} }
@@ -1148,7 +1160,7 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc,
mac_id, rx_desc_pool); mac_id, rx_desc_pool);
} }
return QDF_STATUS_SUCCESS; return status;
} }
#if !defined(DISABLE_MON_CONFIG) && defined(MON_ENABLE_DROP_FOR_MAC) #if !defined(DISABLE_MON_CONFIG) && defined(MON_ENABLE_DROP_FOR_MAC)

Voir le fichier

@@ -2178,6 +2178,34 @@ void *hal_srng_src_peek_n_get_next(hal_soc_handle_t hal_soc_hdl,
return NULL; 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 * hal_srng_src_peek_n_get_next_next() - Get next to next, i.e HP + 2 entry from
* a ring without moving head pointer. * a ring without moving head pointer.