Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b187d515 authored by Yeshwanth Sriram Guntuka's avatar Yeshwanth Sriram Guntuka Committed by nshrivas
Browse files

qcacmn: Reset tx desc as part of flow pool delete

Tx desc flow pool for the vdev is not deleted as part
of disconnection due to tx_desc pending to be processed
in tx comp ring. Hdd_stop is triggered immediately after
this causing dp vdev detach. In parallel, the tx desc
from the tx comp ring is processed, wherein stale vdev
address is derefernced to get dp soc causing page fault.

Fix is to reset tx desc by setting the vdev to NULL as
part of dp_tx_delete_flow_pool and also reset count to
zero in dp_tx_comp_handler before ring desc process loop.

Change-Id: I66f718668ba84f89106d09e624d9593f89479e55
CRs-Fixed: 2683874
parent a5b4bc9b
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -3564,7 +3564,7 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc,
	struct dp_tx_desc_s *head_desc = NULL;
	struct dp_tx_desc_s *tail_desc = NULL;
	uint32_t num_processed = 0;
	uint32_t count = 0;
	uint32_t count;
	bool force_break = false;

	DP_HIST_INIT();
@@ -3573,6 +3573,8 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc,
	/* Re-initialize local variables to be re-used */
		head_desc = NULL;
		tail_desc = NULL;
	count = 0;

	if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring_hdl))) {
		dp_err("HAL RING Access Failed -- %pK", hal_ring_hdl);
		return 0;
@@ -3891,8 +3893,7 @@ dp_is_tx_desc_flush_match(struct dp_pdev *pdev,
 * the outstanding TX data or reset Vdev to NULL in associated TX
 * Desc.
 */
static void dp_tx_desc_flush(struct dp_pdev *pdev,
			     struct dp_vdev *vdev,
void dp_tx_desc_flush(struct dp_pdev *pdev, struct dp_vdev *vdev,
		      bool force_free)
{
	uint8_t i;
@@ -3976,8 +3977,7 @@ dp_tx_desc_reset_vdev(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
	TX_DESC_LOCK_UNLOCK(&soc->tx_desc[desc_pool_id].lock);
}

static void dp_tx_desc_flush(struct dp_pdev *pdev,
			     struct dp_vdev *vdev,
void dp_tx_desc_flush(struct dp_pdev *pdev, struct dp_vdev *vdev,
		      bool force_free)
{
	uint8_t i, num_pool;
+2 −0
Original line number Diff line number Diff line
@@ -361,4 +361,6 @@ void dp_peer_set_tx_capture_enabled(struct dp_peer *peer_handle, bool value)
{
}
#endif
void dp_tx_desc_flush(struct dp_pdev *pdev, struct dp_vdev *vdev,
		      bool force_free);
#endif
+7 −0
Original line number Diff line number Diff line
@@ -307,6 +307,8 @@ struct dp_tx_desc_pool_s *dp_tx_create_flow_pool(struct dp_soc *soc,
int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool,
	bool force)
{
	struct dp_vdev *vdev;

	if (!soc || !pool) {
		dp_err("pool or soc is NULL");
		QDF_ASSERT(0);
@@ -333,6 +335,11 @@ int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool,
	if (pool->avail_desc < pool->pool_size) {
		pool->status = FLOW_POOL_INVALID;
		qdf_spin_unlock_bh(&pool->flow_pool_lock);
		/* Reset TX desc associated to this Vdev as NULL */
		vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc,
							  pool->flow_pool_id);
		if (vdev)
			dp_tx_desc_flush(vdev->pdev, vdev, false);
		dp_err("avail desc less than pool size");
		return -EAGAIN;
	}