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

Commit e84afb21 authored by Karthik Kantamneni's avatar Karthik Kantamneni Committed by Madan Koyyalamudi
Browse files

qcacmn: Fix race condition during IPA map/unmap handling

While Rx buffers are getting umapped from net rx context if IPA
pipes are enabled at same time from MC thread context this is
leading to race condition and IPA map/unmap is going out of sync.

To fix this introducing IPA mapping lock and IPA mapping need to
be handled with lock held.

Change-Id: I9fa71bdb6d4e4aa93fc795cc5dd472a181325991
CRs-Fixed: 2945063
parent 94ba650f
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -207,6 +207,28 @@ static QDF_STATUS __dp_ipa_tx_buf_smmu_mapping(
	return ret;
}

#ifndef QCA_OL_DP_SRNG_LOCK_LESS_ACCESS
static void dp_ipa_set_reo_ctx_mapping_lock_required(struct dp_soc *soc,
						     bool lock_required)
{
	hal_ring_handle_t hal_ring_hdl;
	int ring;

	for (ring = 0; ring < MAX_REO_DEST_RINGS; ring++) {
		hal_ring_hdl = soc->reo_dest_ring[ring].hal_srng;
		hal_srng_lock(hal_ring_hdl);
		soc->ipa_reo_ctx_lock_required[ring] = lock_required;
		hal_srng_unlock(hal_ring_hdl);
	}
}
#else
static void dp_ipa_set_reo_ctx_mapping_lock_required(struct dp_soc *soc,
						     bool lock_required)
{
}

#endif

#ifdef RX_DESC_MULTI_PAGE_ALLOC
static QDF_STATUS dp_ipa_handle_rx_buf_pool_smmu_mapping(struct dp_soc *soc,
							 struct dp_pdev *pdev,
@@ -226,7 +248,9 @@ static QDF_STATUS dp_ipa_handle_rx_buf_pool_smmu_mapping(struct dp_soc *soc,
	pdev_id = pdev->pdev_id;
	rx_pool = &soc->rx_desc_buf[pdev_id];

	dp_ipa_set_reo_ctx_mapping_lock_required(soc, true);
	qdf_spin_lock_bh(&rx_pool->lock);
	dp_ipa_rx_buf_smmu_mapping_lock(soc);
	num_desc = rx_pool->pool_size;
	num_desc_per_page = rx_pool->desc_pages.num_element_per_page;
	for (i = 0; i < num_desc; i++) {
@@ -256,7 +280,9 @@ static QDF_STATUS dp_ipa_handle_rx_buf_pool_smmu_mapping(struct dp_soc *soc,
		__dp_ipa_handle_buf_smmu_mapping(soc, nbuf,
						 rx_pool->buf_size, create);
	}
	dp_ipa_rx_buf_smmu_mapping_unlock(soc);
	qdf_spin_unlock_bh(&rx_pool->lock);
	dp_ipa_set_reo_ctx_mapping_lock_required(soc, false);

	return QDF_STATUS_SUCCESS;
}
@@ -276,7 +302,9 @@ static QDF_STATUS dp_ipa_handle_rx_buf_pool_smmu_mapping(struct dp_soc *soc,
	pdev_id = pdev->pdev_id;
	rx_pool = &soc->rx_desc_buf[pdev_id];

	dp_ipa_set_reo_ctx_mapping_lock_required(soc, true);
	qdf_spin_lock_bh(&rx_pool->lock);
	dp_ipa_rx_buf_smmu_mapping_lock(soc);
	for (i = 0; i < rx_pool->pool_size; i++) {
		if ((!(rx_pool->array[i].rx_desc.in_use)) ||
		    rx_pool->array[i].rx_desc.unmapped)
@@ -300,7 +328,9 @@ static QDF_STATUS dp_ipa_handle_rx_buf_pool_smmu_mapping(struct dp_soc *soc,
		__dp_ipa_handle_buf_smmu_mapping(soc, nbuf,
						 rx_pool->buf_size, create);
	}
	dp_ipa_rx_buf_smmu_mapping_unlock(soc);
	qdf_spin_unlock_bh(&rx_pool->lock);
	dp_ipa_set_reo_ctx_mapping_lock_required(soc, false);

	return QDF_STATUS_SUCCESS;
}
@@ -1381,6 +1411,9 @@ QDF_STATUS dp_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,

	soc->ipa_first_tx_db_access = true;

	qdf_spinlock_create(&soc->ipa_rx_buf_map_lock);
	soc->ipa_rx_buf_map_lock_initialized = true;

	return QDF_STATUS_SUCCESS;
}

@@ -1596,6 +1629,9 @@ QDF_STATUS dp_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,

	soc->ipa_first_tx_db_access = true;

	qdf_spinlock_create(&soc->ipa_rx_buf_map_lock);
	soc->ipa_rx_buf_map_lock_initialized = true;

	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
		  "%s: Tx: %s=%pK, %s=%d, %s=%pK, %s=%pK, %s=%d, %s=%pK, %s=%d, %s=%pK",
		  __func__,
@@ -1732,6 +1768,11 @@ QDF_STATUS dp_ipa_cleanup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
		status = QDF_STATUS_E_FAILURE;
	}

	if (soc->ipa_rx_buf_map_lock_initialized) {
		qdf_spinlock_destroy(&soc->ipa_rx_buf_map_lock);
		soc->ipa_rx_buf_map_lock_initialized = false;
	}

	pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
	if (qdf_unlikely(!pdev)) {
		dp_err_rl("Invalid pdev for pdev_id %d", pdev_id);
+81 −0
Original line number Diff line number Diff line
@@ -283,6 +283,65 @@ QDF_STATUS dp_ipa_tx_buf_smmu_mapping(
QDF_STATUS dp_ipa_tx_buf_smmu_unmapping(
	struct cdp_soc_t *soc_hdl, uint8_t pdev_id);

#ifndef QCA_OL_DP_SRNG_LOCK_LESS_ACCESS
static inline void
dp_ipa_rx_buf_smmu_mapping_lock(struct dp_soc *soc)
{
	if (soc->ipa_rx_buf_map_lock_initialized)
		qdf_spin_lock_bh(&soc->ipa_rx_buf_map_lock);
}

static inline void
dp_ipa_rx_buf_smmu_mapping_unlock(struct dp_soc *soc)
{
	if (soc->ipa_rx_buf_map_lock_initialized)
		qdf_spin_unlock_bh(&soc->ipa_rx_buf_map_lock);
}

static inline void
dp_ipa_reo_ctx_buf_mapping_lock(struct dp_soc *soc,
				uint32_t reo_ring_num)
{
	if (!soc->ipa_reo_ctx_lock_required[reo_ring_num])
		return;

	qdf_spin_lock_bh(&soc->ipa_rx_buf_map_lock);
}

static inline void
dp_ipa_reo_ctx_buf_mapping_unlock(struct dp_soc *soc,
				  uint32_t reo_ring_num)
{
	if (!soc->ipa_reo_ctx_lock_required[reo_ring_num])
		return;

	qdf_spin_unlock_bh(&soc->ipa_rx_buf_map_lock);
}
#else

static inline void
dp_ipa_rx_buf_smmu_mapping_lock(struct dp_soc *soc)
{
}

static inline void
dp_ipa_rx_buf_smmu_mapping_unlock(struct dp_soc *soc)
{
}

static inline void
dp_ipa_reo_ctx_buf_mapping_lock(struct dp_soc *soc,
				uint32_t reo_ring_num)
{
}

static inline void
dp_ipa_reo_ctx_buf_mapping_unlock(struct dp_soc *soc,
				  uint32_t reo_ring_num)
{
}
#endif

#else
static inline int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
{
@@ -308,6 +367,28 @@ static inline QDF_STATUS dp_ipa_handle_rx_buf_smmu_mapping(struct dp_soc *soc,
	return QDF_STATUS_SUCCESS;
}

static inline void
dp_ipa_rx_buf_smmu_mapping_lock(struct dp_soc *soc)
{
}

static inline void
dp_ipa_rx_buf_smmu_mapping_unlock(struct dp_soc *soc)
{
}

static inline void
dp_ipa_reo_ctx_buf_mapping_lock(struct dp_soc *soc,
				uint32_t reo_ring_num)
{
}

static inline void
dp_ipa_reo_ctx_buf_mapping_unlock(struct dp_soc *soc,
				  uint32_t reo_ring_num)
{
}

static inline qdf_nbuf_t dp_ipa_handle_rx_reo_reinject(struct dp_soc *soc,
						       qdf_nbuf_t nbuf)
{
+9 −0
Original line number Diff line number Diff line
@@ -2464,6 +2464,9 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl,
		if (QDF_IS_STATUS_ERROR(status)) {
			if (qdf_unlikely(rx_desc && rx_desc->nbuf)) {
				qdf_assert_always(rx_desc->unmapped);
				dp_ipa_reo_ctx_buf_mapping_lock(
							soc,
							reo_ring_num);
				dp_ipa_handle_rx_buf_smmu_mapping(
							soc,
							rx_desc->nbuf,
@@ -2475,6 +2478,9 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl,
							QDF_DMA_FROM_DEVICE,
							RX_DATA_BUFFER_SIZE);
				rx_desc->unmapped = 1;
				dp_ipa_reo_ctx_buf_mapping_unlock(
								soc,
								reo_ring_num);
				dp_rx_buffer_pool_nbuf_free(soc, rx_desc->nbuf,
							    rx_desc->pool_id);
				dp_rx_add_to_free_desc_list(
@@ -2630,6 +2636,8 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl,
		 * in case double skb unmap happened.
		 */
		rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id];
		dp_ipa_reo_ctx_buf_mapping_lock(soc,
						reo_ring_num);
		dp_ipa_handle_rx_buf_smmu_mapping(soc, rx_desc->nbuf,
						  rx_desc_pool->buf_size,
						  false);
@@ -2637,6 +2645,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl,
					     QDF_DMA_FROM_DEVICE,
					     rx_desc_pool->buf_size);
		rx_desc->unmapped = 1;
		dp_ipa_reo_ctx_buf_mapping_unlock(soc, reo_ring_num);
		DP_RX_PROCESS_NBUF(soc, nbuf_head, nbuf_tail, ebuf_head,
				   ebuf_tail, rx_desc);
		/*
+2 −0
Original line number Diff line number Diff line
@@ -1976,6 +1976,7 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, hal_ring_desc_t ring_desc,
	if (rx_desc->unmapped)
		return rx_bufs_used;

	dp_ipa_rx_buf_smmu_mapping_lock(soc);
	dp_ipa_handle_rx_buf_smmu_mapping(soc, rx_desc->nbuf,
					  rx_desc_pool->buf_size,
					  false);
@@ -1983,6 +1984,7 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, hal_ring_desc_t ring_desc,
				     QDF_DMA_FROM_DEVICE,
				     rx_desc_pool->buf_size);
	rx_desc->unmapped = 1;
	dp_ipa_rx_buf_smmu_mapping_unlock(soc);

	rx_desc->rx_buf_start = qdf_nbuf_data(msdu);

+12 −0
Original line number Diff line number Diff line
@@ -336,6 +336,7 @@ dp_rx_msdus_drop(struct dp_soc *soc, hal_ring_desc_t ring_desc,
		}

		rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id];
		dp_ipa_rx_buf_smmu_mapping_lock(soc);
		dp_ipa_handle_rx_buf_smmu_mapping(soc, rx_desc->nbuf,
						  rx_desc_pool->buf_size,
						  false);
@@ -343,6 +344,7 @@ dp_rx_msdus_drop(struct dp_soc *soc, hal_ring_desc_t ring_desc,
					     QDF_DMA_FROM_DEVICE,
					     rx_desc_pool->buf_size);
		rx_desc->unmapped = 1;
		dp_ipa_rx_buf_smmu_mapping_unlock(soc);

		rx_desc->rx_buf_start = qdf_nbuf_data(rx_desc->nbuf);

@@ -585,6 +587,7 @@ dp_rx_reo_err_entry_process(struct dp_soc *soc,
		}

		rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id];
		dp_ipa_rx_buf_smmu_mapping_lock(soc);
		dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf,
						  rx_desc_pool->buf_size,
						  false);
@@ -592,6 +595,7 @@ dp_rx_reo_err_entry_process(struct dp_soc *soc,
					     QDF_DMA_FROM_DEVICE,
					     rx_desc_pool->buf_size);
		rx_desc->unmapped = 1;
		dp_ipa_rx_buf_smmu_mapping_unlock(soc);

		QDF_NBUF_CB_RX_PKT_LEN(nbuf) = msdu_list.msdu_info[i].msdu_len;
		rx_bufs_used++;
@@ -868,6 +872,7 @@ dp_rx_bar_frame_handle(struct dp_soc *soc,

	nbuf = rx_desc->nbuf;
	rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id];
	dp_ipa_rx_buf_smmu_mapping_lock(soc);
	dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf,
					  rx_desc_pool->buf_size,
					  false);
@@ -875,6 +880,7 @@ dp_rx_bar_frame_handle(struct dp_soc *soc,
				     QDF_DMA_FROM_DEVICE,
				     rx_desc_pool->buf_size);
	rx_desc->unmapped = 1;
	dp_ipa_rx_buf_smmu_mapping_unlock(soc);
	rx_tlv_hdr = qdf_nbuf_data(nbuf);
	peer_id =
		hal_rx_mpdu_start_sw_peer_id_get(soc->hal_soc,
@@ -2115,6 +2121,7 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,

		nbuf = rx_desc->nbuf;
		rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id];
		dp_ipa_rx_buf_smmu_mapping_lock(soc);
		dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf,
						  rx_desc_pool->buf_size,
						  false);
@@ -2122,6 +2129,7 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
					     QDF_DMA_FROM_DEVICE,
					     rx_desc_pool->buf_size);
		rx_desc->unmapped = 1;
		dp_ipa_rx_buf_smmu_mapping_unlock(soc);

		/*
		 * save the wbm desc info in nbuf TLV. We will need this
@@ -2510,6 +2518,7 @@ dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,

					rx_desc_pool = &soc->
						rx_desc_buf[rx_desc->pool_id];
					dp_ipa_rx_buf_smmu_mapping_lock(soc);
					dp_ipa_handle_rx_buf_smmu_mapping(
							soc, msdu,
							rx_desc_pool->buf_size,
@@ -2519,6 +2528,7 @@ dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
						QDF_DMA_FROM_DEVICE,
						rx_desc_pool->buf_size);
					rx_desc->unmapped = 1;
					dp_ipa_rx_buf_smmu_mapping_unlock(soc);

					QDF_TRACE(QDF_MODULE_ID_DP,
						QDF_TRACE_LEVEL_DEBUG,
@@ -2747,6 +2757,7 @@ dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc,

		if (rx_desc && rx_desc->nbuf) {
			rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id];
			dp_ipa_rx_buf_smmu_mapping_lock(soc);
			dp_ipa_handle_rx_buf_smmu_mapping(
						soc, rx_desc->nbuf,
						rx_desc_pool->buf_size,
@@ -2755,6 +2766,7 @@ dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc,
						     QDF_DMA_FROM_DEVICE,
						     rx_desc_pool->buf_size);
			rx_desc->unmapped = 1;
			dp_ipa_rx_buf_smmu_mapping_unlock(soc);

			dp_rx_buffer_pool_nbuf_free(soc, rx_desc->nbuf,
						    rx_desc->pool_id);
Loading