瀏覽代碼

qcacmn: Handle ipa_mapped flag correctly to prevent race

Currently soc->ipa_mapped flag is set to true only after all
the buffers are SMMU mapped to IPA. This leads to a race
window where Rx buffers routed to WLAN HOST in the replenish
path are not mapped to IPA, as the ipa_mapped flag is still
set to 0. The fix is to set the ipa_mapped flag to 1, right when
the IPA pipes are enabled, before waiting for the complete
buffer pool to be IPA SMMU mapped.
With this fix, RX buffers can be unmapped and mapped to IPA
domain in dp_pdev_rx_buffers_attach() and
dp_pdev_nbuf_alloc_and_map_replenish() in WLAN host RX path when
ipa pipes are enabled.

This change also renames ipa_mapped flag to ipa_map_allowed.

Change-Id: Ibbe50cb211f858a3372e31644df2f5e98f99a292
CRs-Fixed: 3569745
Namita Nair 1 年之前
父節點
當前提交
8de279eab8
共有 7 個文件被更改,包括 41 次插入37 次删除
  1. 11 6
      dp/wifi3.0/dp_ipa.c
  2. 5 7
      dp/wifi3.0/dp_rx.c
  3. 6 9
      dp/wifi3.0/dp_rx.h
  4. 3 5
      dp/wifi3.0/dp_rx_defrag.c
  5. 6 7
      dp/wifi3.0/dp_rx_desc.c
  6. 1 1
      dp/wifi3.0/dp_types.h
  7. 9 2
      ipa/core/src/wlan_ipa_core.c

+ 11 - 6
dp/wifi3.0/dp_ipa.c

@@ -182,7 +182,8 @@ QDF_STATUS dp_ipa_handle_rx_buf_smmu_mapping(struct dp_soc *soc,
 	 * operation and nbuf has done ipa smmu map before,
 	 * do ipa smmu unmap as well.
 	 */
-	if (!qdf_atomic_read(&soc->ipa_pipes_enabled)) {
+	if (!(qdf_atomic_read(&soc->ipa_pipes_enabled) &&
+				qdf_atomic_read(&soc->ipa_map_allowed))) {
 		if (!create && qdf_nbuf_is_rx_ipa_smmu_map(nbuf)) {
 			DP_STATS_INC(soc, rx.err.ipa_unmap_no_pipe, 1);
 		} else {
@@ -382,7 +383,7 @@ QDF_STATUS dp_ipa_set_smmu_mapped(struct cdp_soc_t *soc_hdl, int val)
 {
 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
 
-	qdf_atomic_set(&soc->ipa_mapped, val);
+	qdf_atomic_set(&soc->ipa_map_allowed, val);
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -390,7 +391,7 @@ int dp_ipa_get_smmu_mapped(struct cdp_soc_t *soc_hdl)
 {
 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
 
-	return qdf_atomic_read(&soc->ipa_mapped);
+	return qdf_atomic_read(&soc->ipa_map_allowed);
 }
 
 static QDF_STATUS dp_ipa_get_shared_mem_info(qdf_device_t osdev,
@@ -3467,9 +3468,9 @@ QDF_STATUS dp_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
 	DP_IPA_EP_SET_TX_DB_PA(soc, ipa_res);
 
 	if (!ipa_config_is_opt_wifi_dp_enabled()) {
+		qdf_atomic_set(&soc->ipa_map_allowed, 1);
 		dp_ipa_handle_rx_buf_pool_smmu_mapping(soc, pdev, true,
 						       __func__, __LINE__);
-		qdf_atomic_set(&soc->ipa_mapped, 1);
 	}
 
 	result = qdf_ipa_wdi_enable_pipes(hdl);
@@ -3479,9 +3480,11 @@ QDF_STATUS dp_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
 			  __func__, result);
 		qdf_atomic_set(&soc->ipa_pipes_enabled, 0);
 		DP_IPA_RESET_TX_DB_PA(soc, ipa_res);
-		if (qdf_atomic_read(&soc->ipa_mapped))
+		if (qdf_atomic_read(&soc->ipa_map_allowed)) {
+			qdf_atomic_set(&soc->ipa_map_allowed, 0);
 			dp_ipa_handle_rx_buf_pool_smmu_mapping(
 					soc, pdev, false, __func__, __LINE__);
+		}
 		return QDF_STATUS_E_FAILURE;
 	}
 
@@ -3528,9 +3531,11 @@ QDF_STATUS dp_ipa_disable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
 
 	qdf_atomic_set(&soc->ipa_pipes_enabled, 0);
 
-	if (qdf_atomic_read(&soc->ipa_mapped))
+	if (!ipa_config_is_opt_wifi_dp_enabled()) {
+		qdf_atomic_set(&soc->ipa_map_allowed, 0);
 		dp_ipa_handle_rx_buf_pool_smmu_mapping(soc, pdev, false,
 						       __func__, __LINE__);
+	}
 
 	return result ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
 }

+ 5 - 7
dp/wifi3.0/dp_rx.c

@@ -365,11 +365,10 @@ dp_pdev_nbuf_alloc_and_map_replenish(struct dp_soc *dp_soc,
 
 	nbuf_frag_info_t->paddr =
 		qdf_nbuf_get_frag_paddr((nbuf_frag_info_t->virt_addr).nbuf, 0);
-	if (qdf_atomic_read(&dp_soc->ipa_mapped))
-		dp_ipa_handle_rx_buf_smmu_mapping(dp_soc, (qdf_nbuf_t)(
-						  (nbuf_frag_info_t->virt_addr).nbuf),
-						  rx_desc_pool->buf_size,
-						  true, __func__, __LINE__);
+	dp_ipa_handle_rx_buf_smmu_mapping(dp_soc, (qdf_nbuf_t)(
+					  (nbuf_frag_info_t->virt_addr).nbuf),
+					  rx_desc_pool->buf_size,
+					  true, __func__, __LINE__);
 
 	ret = dp_check_paddr(dp_soc, &((nbuf_frag_info_t->virt_addr).nbuf),
 			     &nbuf_frag_info_t->paddr,
@@ -3190,8 +3189,7 @@ dp_pdev_rx_buffers_attach(struct dp_soc *dp_soc, uint32_t mac_id,
 						     desc_list->rx_desc.cookie,
 						     rx_desc_pool->owner);
 
-			if (qdf_atomic_read(&dp_soc->ipa_mapped))
-				dp_ipa_handle_rx_buf_smmu_mapping(
+			dp_ipa_handle_rx_buf_smmu_mapping(
 						dp_soc, nbuf,
 						rx_desc_pool->buf_size, true,
 						__func__, __LINE__);

+ 6 - 9
dp/wifi3.0/dp_rx.h

@@ -2763,11 +2763,9 @@ void dp_rx_nbuf_unmap(struct dp_soc *soc,
 			    QDF_NBUF_CB_PADDR(rx_desc->nbuf),
 			    rx_desc_pool->buf_size);
 
-	if (qdf_atomic_read(&soc->ipa_mapped))
-		dp_ipa_handle_rx_buf_smmu_mapping(soc, rx_desc->nbuf,
-						  rx_desc_pool->buf_size,
-						  false, __func__, __LINE__);
-
+	dp_ipa_handle_rx_buf_smmu_mapping(soc, rx_desc->nbuf,
+					  rx_desc_pool->buf_size,
+					  false, __func__, __LINE__);
 	qdf_nbuf_unmap_nbytes_single(soc->osdev, rx_desc->nbuf,
 				     QDF_DMA_FROM_DEVICE,
 				     rx_desc_pool->buf_size);
@@ -2782,10 +2780,9 @@ void dp_rx_nbuf_unmap_pool(struct dp_soc *soc,
 {
 	dp_audio_smmu_unmap(soc->osdev, QDF_NBUF_CB_PADDR(nbuf),
 			    rx_desc_pool->buf_size);
-	if (qdf_atomic_read(&soc->ipa_mapped))
-		dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf,
-						  rx_desc_pool->buf_size,
-						  false, __func__, __LINE__);
+	dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf,
+					  rx_desc_pool->buf_size,
+					  false, __func__, __LINE__);
 	qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf, QDF_DMA_FROM_DEVICE,
 				     rx_desc_pool->buf_size);
 }

+ 3 - 5
dp/wifi3.0/dp_rx_defrag.c

@@ -1307,11 +1307,9 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_txrx_peer *txrx_peer,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (qdf_atomic_read(&soc->ipa_mapped))
-		dp_ipa_handle_rx_buf_smmu_mapping(soc, head,
-						  rx_desc_pool->buf_size, true,
-						  __func__, __LINE__);
-
+	dp_ipa_handle_rx_buf_smmu_mapping(soc, head,
+					  rx_desc_pool->buf_size, true,
+					  __func__, __LINE__);
 	dp_audio_smmu_map(soc->osdev,
 			  qdf_mem_paddr_from_dmaaddr(soc->osdev,
 						     QDF_NBUF_CB_PADDR(head)),

+ 6 - 7
dp/wifi3.0/dp_rx_desc.c

@@ -193,13 +193,12 @@ static void dp_rx_desc_nbuf_cleanup(struct dp_soc *soc,
 					    QDF_NBUF_CB_PADDR(nbuf),
 					    buf_size);
 
-		if (qdf_atomic_read(&soc->ipa_mapped)) {
-			if (dp_ipa_handle_rx_buf_smmu_mapping(
-							soc, nbuf, buf_size,
-							false, __func__,
-							__LINE__))
-				dp_info_rl("Unable to unmap nbuf: %pK", nbuf);
-		}
+		if (dp_ipa_handle_rx_buf_smmu_mapping(
+						soc, nbuf, buf_size,
+						false, __func__,
+						__LINE__))
+			dp_info_rl("Unable to unmap nbuf: %pK", nbuf);
+
 		qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf,
 					     QDF_DMA_BIDIRECTIONAL, buf_size);
 		dp_rx_nbuf_free(nbuf);

+ 1 - 1
dp/wifi3.0/dp_types.h

@@ -2964,7 +2964,7 @@ struct dp_soc {
 	struct htt_t2h_stats htt_stats;
 
 	void *external_txrx_handle; /* External data path handle */
-	qdf_atomic_t ipa_mapped;
+	qdf_atomic_t ipa_map_allowed;
 #ifdef IPA_OFFLOAD
 	struct ipa_dp_tx_rsc ipa_uc_tx_rsc;
 #ifdef IPA_WDI3_TX_TWO_PIPES

+ 9 - 2
ipa/core/src/wlan_ipa_core.c

@@ -4311,6 +4311,13 @@ void wlan_ipa_opt_dp_deinit(struct wlan_ipa_priv *ipa_ctx)
 
 	if (ipa_ctx->opt_wifi_datapath && ipa_config_is_opt_wifi_dp_enabled())
 		qdf_wake_lock_destroy(&ipa_ctx->opt_dp_wake_lock);
+
+	if (cdp_ipa_get_smmu_mapped(ipa_ctx->dp_soc)) {
+		cdp_ipa_set_smmu_mapped(ipa_ctx->dp_soc, 0);
+		cdp_ipa_rx_buf_smmu_pool_mapping(ipa_ctx->dp_soc,
+						 ipa_ctx->dp_pdev_id,
+						 false, __func__, __LINE__);
+	}
 }
 
 #else
@@ -5246,8 +5253,8 @@ void wlan_ipa_wdi_opt_dpath_notify_flt_rsvd(bool response)
 		smmu_msg->op_code = WLAN_IPA_SMMU_MAP;
 		uc_op_work = &ipa_ctx->uc_op_work[WLAN_IPA_SMMU_MAP];
 		uc_op_work->msg = smmu_msg;
-		qdf_sched_work(0, &uc_op_work->work);
 		cdp_ipa_set_smmu_mapped(ipa_ctx->dp_soc, 1);
+		qdf_sched_work(0, &uc_op_work->work);
 	}
 
 	notify_msg = qdf_mem_malloc(sizeof(*notify_msg));
@@ -5610,8 +5617,8 @@ void wlan_ipa_wdi_opt_dpath_notify_flt_rlsd(int flt0_rslt, int flt1_rslt)
 		smmu_msg->op_code = WLAN_IPA_SMMU_UNMAP;
 		uc_op_work = &ipa_ctx->uc_op_work[WLAN_IPA_SMMU_UNMAP];
 		uc_op_work->msg = smmu_msg;
-		qdf_sched_work(0, &uc_op_work->work);
 		cdp_ipa_set_smmu_mapped(ipa_ctx->dp_soc, 0);
+		qdf_sched_work(0, &uc_op_work->work);
 	} else {
 		ipa_err("IPA SMMU not mapped!!");
 	}