diff --git a/dp/wifi3.0/dp_ipa.c b/dp/wifi3.0/dp_ipa.c index 8de4e8f2da0a..bd34e19662a0 100644 --- a/dp/wifi3.0/dp_ipa.c +++ b/dp/wifi3.0/dp_ipa.c @@ -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); diff --git a/dp/wifi3.0/dp_ipa.h b/dp/wifi3.0/dp_ipa.h index 7df2b2873474..aba3bc176c78 100644 --- a/dp/wifi3.0/dp_ipa.h +++ b/dp/wifi3.0/dp_ipa.h @@ -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) { diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 0e8ba7ac34e4..e97e6da8b79a 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -2464,6 +2464,9 @@ more_data: 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 @@ more_data: 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 @@ more_data: * 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 @@ more_data: 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); /* diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c index 8bcd0b8d8a8a..da7d3bf3155d 100644 --- a/dp/wifi3.0/dp_rx_defrag.c +++ b/dp/wifi3.0/dp_rx_defrag.c @@ -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); diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 8de91eca4656..0f95f6a27060 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -336,6 +336,7 @@ more_msdu_link_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 @@ more_msdu_link_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 @@ more_msdu_link_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, nbuf, rx_desc_pool->buf_size, false); @@ -592,6 +595,7 @@ more_msdu_link_desc: 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); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index dfbdf24ccbfa..8d5860da27bb 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1756,6 +1756,9 @@ struct dp_soc { qdf_atomic_t ipa_pipes_enabled; bool ipa_first_tx_db_access; + qdf_spinlock_t ipa_rx_buf_map_lock; + bool ipa_rx_buf_map_lock_initialized; + uint8_t ipa_reo_ctx_lock_required[MAX_REO_DEST_RINGS]; #endif #ifdef WLAN_FEATURE_STATS_EXT diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index aa9bf4930873..a510a2e26f2a 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -1347,6 +1347,32 @@ void *hal_srng_dst_get_next_cached(void *hal_soc, return (void *)desc; } +static inline int hal_srng_lock(hal_ring_handle_t hal_ring_hdl) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + + if (qdf_unlikely(!hal_ring_hdl)) { + qdf_print("error: invalid hal_ring\n"); + return -EINVAL; + } + + SRNG_LOCK(&(srng->lock)); + return 0; +} + +static inline int hal_srng_unlock(hal_ring_handle_t hal_ring_hdl) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + + if (qdf_unlikely(!hal_ring_hdl)) { + qdf_print("error: invalid hal_ring\n"); + return -EINVAL; + } + + SRNG_UNLOCK(&(srng->lock)); + return 0; +} + /** * hal_srng_dst_get_next_hp - Get next entry from a destination ring and move * cached head pointer