diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index 7223b8283aad..80e385b1ddf1 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -135,10 +135,15 @@ static void htt_rx_hash_deinit(struct htt_pdev_t *pdev) struct htt_rx_hash_bucket **hash_table; struct htt_list_node *list_iter = NULL; qdf_mem_info_t mem_map_table = {0}; + bool ipa_smmu = false; if (NULL == pdev->rx_ring.hash_table) return; + if (qdf_mem_smmu_s1_enabled(pdev->osdev) && pdev->is_ipa_uc_enabled && + pdev->rx_ring.smmu_map) + ipa_smmu = true; + qdf_spin_lock_bh(&(pdev->rx_ring.rx_hash_lock)); hash_table = pdev->rx_ring.hash_table; pdev->rx_ring.hash_table = NULL; @@ -153,8 +158,7 @@ static void htt_rx_hash_deinit(struct htt_pdev_t *pdev) pdev->rx_ring. listnode_offset); if (hash_entry->netbuf) { - if (qdf_mem_smmu_s1_enabled(pdev->osdev) && - pdev->is_ipa_uc_enabled) { + if (ipa_smmu) { qdf_update_mem_map_table(pdev->osdev, &mem_map_table, QDF_NBUF_CB_PADDR( @@ -395,9 +399,14 @@ static int htt_rx_ring_fill_n(struct htt_pdev_t *pdev, int num) int filled = 0; int debt_served = 0; qdf_mem_info_t mem_map_table = {0}; + bool ipa_smmu = false; idx = *(pdev->rx_ring.alloc_idx.vaddr); + if (qdf_mem_smmu_s1_enabled(pdev->osdev) && pdev->is_ipa_uc_enabled && + pdev->rx_ring.smmu_map) + ipa_smmu = true; + if ((idx < 0) || (idx > pdev->rx_ring.size_mask) || (num > pdev->rx_ring.size)) { QDF_TRACE(QDF_MODULE_ID_HTT, @@ -494,8 +503,7 @@ moretofill: pdev->rx_ring.buf.netbufs_ring[idx] = rx_netbuf; } - if (qdf_mem_smmu_s1_enabled(pdev->osdev) && - pdev->is_ipa_uc_enabled) { + if (ipa_smmu) { qdf_update_mem_map_table(pdev->osdev, &mem_map_table, paddr, HTT_RX_BUF_SIZE); cds_smmu_map_unmap(true, 1, &mem_map_table); @@ -633,10 +641,15 @@ static inline unsigned int htt_rx_in_order_ring_elems(struct htt_pdev_t *pdev) void htt_rx_detach(struct htt_pdev_t *pdev) { + bool ipa_smmu = false; qdf_timer_stop(&pdev->rx_ring.refill_retry_timer); qdf_timer_free(&pdev->rx_ring.refill_retry_timer); htt_rx_dbg_rxbuf_deinit(pdev); + if (qdf_mem_smmu_s1_enabled(pdev->osdev) && pdev->is_ipa_uc_enabled && + pdev->rx_ring.smmu_map) + ipa_smmu = true; + if (pdev->cfg.is_full_reorder_offload) { qdf_mem_free_consistent(pdev->osdev, pdev->osdev->dev, sizeof(uint32_t), @@ -649,30 +662,18 @@ void htt_rx_detach(struct htt_pdev_t *pdev) htt_rx_hash_deinit(pdev); } else { int sw_rd_idx = pdev->rx_ring.sw_rd_idx.msdu_payld; - qdf_mem_info_t *mem_map_table = NULL, *mem_info = NULL; - uint32_t num_unmapped = 0; + qdf_mem_info_t mem_map_table = {0}; - if (qdf_mem_smmu_s1_enabled(pdev->osdev) && - pdev->is_ipa_uc_enabled) { - mem_map_table = qdf_mem_map_table_alloc( - pdev->rx_ring.fill_level); - if (!mem_map_table) { - qdf_print("%s: Failed to allocate memory for mem map table\n", - __func__); - return; - } - mem_info = mem_map_table; - } while (sw_rd_idx != *(pdev->rx_ring.alloc_idx.vaddr)) { - if (qdf_mem_smmu_s1_enabled(pdev->osdev) && - pdev->is_ipa_uc_enabled) { - qdf_update_mem_map_table(pdev->osdev, mem_info, + if (ipa_smmu) { + qdf_update_mem_map_table(pdev->osdev, + &mem_map_table, QDF_NBUF_CB_PADDR( - pdev->rx_ring.buf.netbufs_ring[ - sw_rd_idx]), + pdev->rx_ring.buf. + netbufs_ring[sw_rd_idx]), HTT_RX_BUF_SIZE); - mem_info++; - num_unmapped++; + cds_smmu_map_unmap(false, 1, + &mem_map_table); } #ifdef DEBUG_DMA_DONE qdf_nbuf_unmap(pdev->osdev, @@ -692,13 +693,6 @@ void htt_rx_detach(struct htt_pdev_t *pdev) } qdf_mem_free(pdev->rx_ring.buf.netbufs_ring); - if (qdf_mem_smmu_s1_enabled(pdev->osdev) && - pdev->is_ipa_uc_enabled) { - if (num_unmapped) - cds_smmu_map_unmap(false, num_unmapped, - mem_map_table); - qdf_mem_free(mem_map_table); - } } qdf_mem_free_consistent(pdev->osdev, pdev->osdev->dev, @@ -1651,9 +1645,9 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, struct htt_host_rx_desc_base *rx_desc; enum rx_pkt_fate status = RX_PKT_FATE_SUCCESS; qdf_dma_addr_t paddr; - qdf_mem_info_t *mem_map_table = NULL, *mem_info = NULL; - uint32_t num_unmapped = 0; + qdf_mem_info_t mem_map_table = {0}; int ret = 1; + bool ipa_smmu = false; HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); @@ -1669,15 +1663,11 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, /* Get the total number of MSDUs */ msdu_count = HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(*(msg_word + 1)); HTT_RX_CHECK_MSDU_COUNT(msdu_count); - if (qdf_mem_smmu_s1_enabled(pdev->osdev) && pdev->is_ipa_uc_enabled) { - mem_map_table = qdf_mem_map_table_alloc(msdu_count); - if (!mem_map_table) { - qdf_print("%s: Failed to allocate memory for mem map table\n", - __func__); - return 0; - } - mem_info = mem_map_table; - } + + if (qdf_mem_smmu_s1_enabled(pdev->osdev) && pdev->is_ipa_uc_enabled && + pdev->rx_ring.smmu_map) + ipa_smmu = true; + ol_rx_update_histogram_stats(msdu_count, frag_ind, offload_ind); htt_rx_dbg_rxbuf_httrxind(pdev, msdu_count); @@ -1688,7 +1678,7 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, msg_word); *head_msdu = *tail_msdu = NULL; ret = 0; - goto free_mem_map_table; + goto end; } paddr = htt_rx_in_ord_paddr_get(msg_word); @@ -1699,17 +1689,15 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, *tail_msdu = NULL; pdev->rx_ring.pop_fail_cnt++; ret = 0; - goto free_mem_map_table; + goto end; } while (msdu_count > 0) { - if (qdf_mem_smmu_s1_enabled(pdev->osdev) && - pdev->is_ipa_uc_enabled) { - qdf_update_mem_map_table(pdev->osdev, mem_info, + if (ipa_smmu) { + qdf_update_mem_map_table(pdev->osdev, &mem_map_table, QDF_NBUF_CB_PADDR(msdu), HTT_RX_BUF_SIZE); - mem_info++; - num_unmapped++; + cds_smmu_map_unmap(false, 1, &mem_map_table); } /* @@ -1787,11 +1775,11 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, if (!prev) { *head_msdu = *tail_msdu = NULL; ret = 0; - goto free_mem_map_table; + goto end; } *tail_msdu = prev; qdf_nbuf_set_next(prev, NULL); - goto free_mem_map_table; + goto end; } else { /* if this is not the last msdu */ /* get the next msdu */ msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; @@ -1803,7 +1791,7 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, *tail_msdu = NULL; pdev->rx_ring.pop_fail_cnt++; ret = 0; - goto free_mem_map_table; + goto end; } /* if this is not the first msdu, update the @@ -1836,7 +1824,7 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, *tail_msdu = NULL; pdev->rx_ring.pop_fail_cnt++; ret = 0; - goto free_mem_map_table; + goto end; } qdf_nbuf_set_next(msdu, next); prev = msdu; @@ -1847,13 +1835,7 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, } } -free_mem_map_table: - if (qdf_mem_smmu_s1_enabled(pdev->osdev) && pdev->is_ipa_uc_enabled) { - if (num_unmapped) - cds_smmu_map_unmap(false, num_unmapped, - mem_map_table); - qdf_mem_free(mem_map_table); - } +end: return ret; } #endif @@ -2945,4 +2927,61 @@ void htt_deregister_rx_pkt_dump_callback(struct htt_pdev_t *pdev) } pdev->rx_pkt_dump_cb = NULL; } + +static QDF_STATUS htt_rx_hash_smmu_map(bool map, struct htt_pdev_t *pdev) +{ + uint32_t i; + struct htt_rx_hash_entry *hash_entry; + struct htt_rx_hash_bucket **hash_table; + struct htt_list_node *list_iter = NULL; + qdf_mem_info_t mem_map_table = {0}; + int ret; + + qdf_spin_lock_bh(&pdev->rx_ring.rx_hash_lock); + hash_table = pdev->rx_ring.hash_table; + + for (i = 0; i < RX_NUM_HASH_BUCKETS; i++) { + /* Free the hash entries in hash bucket i */ + list_iter = hash_table[i]->listhead.next; + while (list_iter != &hash_table[i]->listhead) { + hash_entry = + (struct htt_rx_hash_entry *)((char *)list_iter - + pdev->rx_ring. + listnode_offset); + if (hash_entry->netbuf) { + qdf_update_mem_map_table(pdev->osdev, + &mem_map_table, + QDF_NBUF_CB_PADDR( + hash_entry->netbuf), + HTT_RX_BUF_SIZE); + ret = cds_smmu_map_unmap(map, 1, + &mem_map_table); + if (ret) + return QDF_STATUS_E_FAILURE; + } + list_iter = list_iter->next; + } + } + qdf_spin_unlock_bh(&pdev->rx_ring.rx_hash_lock); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS htt_rx_update_smmu_map(struct htt_pdev_t *pdev, bool map) +{ + QDF_STATUS status; + + if (NULL == pdev->rx_ring.hash_table) + return QDF_STATUS_SUCCESS; + + if (!qdf_mem_smmu_s1_enabled(pdev->osdev) || !pdev->is_ipa_uc_enabled) + return QDF_STATUS_SUCCESS; + + qdf_spin_lock_bh(&pdev->rx_ring.refill_lock); + pdev->rx_ring.smmu_map = map; + status = htt_rx_hash_smmu_map(map, pdev); + qdf_spin_unlock_bh(&pdev->rx_ring.refill_lock); + + return status; +} #endif diff --git a/core/dp/htt/htt_types.h b/core/dp/htt/htt_types.h index f24ee104ccd0..7d17d3116b35 100644 --- a/core/dp/htt/htt_types.h +++ b/core/dp/htt/htt_types.h @@ -359,6 +359,7 @@ struct htt_pdev_t { qdf_spinlock_t rx_hash_lock; struct htt_rx_hash_bucket **hash_table; uint32_t listnode_offset; + bool smmu_map; } rx_ring; #ifdef CONFIG_HL_SUPPORT int rx_desc_size_hl; diff --git a/core/dp/ol/inc/ol_htt_rx_api.h b/core/dp/ol/inc/ol_htt_rx_api.h index fab4291dc5a4..f2ab6ffebcec 100644 --- a/core/dp/ol/inc/ol_htt_rx_api.h +++ b/core/dp/ol/inc/ol_htt_rx_api.h @@ -896,4 +896,12 @@ htt_rx_offload_paddr_msdu_pop_ll(htt_pdev_handle pdev, uint32_t htt_rx_amsdu_rx_in_order_get_pktlog(qdf_nbuf_t rx_ind_msg); +/** + * htt_rx_update_smmu_map() - set smmu map/unmap for rx buffers + * @pdev: htt pdev handle + * @map: value to set smmu map/unmap for rx buffers + * + * Return: QDF_STATUS + */ +QDF_STATUS htt_rx_update_smmu_map(struct htt_pdev_t *pdev, bool map); #endif /* _OL_HTT_RX_API__H_ */ diff --git a/core/dp/txrx/ol_txrx_ipa.c b/core/dp/txrx/ol_txrx_ipa.c index 1d6ebf94e418..d4653c42ecb5 100644 --- a/core/dp/txrx/ol_txrx_ipa.c +++ b/core/dp/txrx/ol_txrx_ipa.c @@ -728,8 +728,16 @@ QDF_STATUS ol_txrx_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled) QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_pdev *ppdev) { ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev; + QDF_STATUS status; int ret; + status = htt_rx_update_smmu_map(pdev->htt_pdev, true); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "IPA SMMU map failed status:%d", status); + return status; + } + /* ACTIVATE TX PIPE */ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "%s: Enable IPA pipes", __func__); @@ -738,6 +746,10 @@ QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_pdev *ppdev) QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: ipa_wdi_enable_pipes failed: ret=%d", __func__, ret); + status = htt_rx_update_smmu_map(pdev->htt_pdev, false); + if (status != QDF_STATUS_SUCCESS) + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "IPA SMMU unmap failed"); return QDF_STATUS_E_FAILURE; } @@ -764,10 +776,15 @@ QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_pdev *ppdev) QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: ipa_wdi_disable_pipes failed: ret=%d", __func__, ret); - return QDF_STATUS_E_FAILURE; } - return QDF_STATUS_SUCCESS; + if (htt_rx_update_smmu_map(pdev->htt_pdev, false) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "IPA SMMU unmap failed") + } + + return ret ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS; } /** @@ -1436,6 +1453,14 @@ QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_pdev *ppdev) ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)ppdev; struct ol_txrx_ipa_resources *ipa_res = &pdev->ipa_resource; int result; + QDF_STATUS status; + + status = htt_rx_update_smmu_map(pdev->htt_pdev, true); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "IPA SMMU map failed status:%d", status); + return status; + } /* ACTIVATE TX PIPE */ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, @@ -1446,14 +1471,14 @@ QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_pdev *ppdev) QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Enable TX PIPE fail, code %d", __func__, result); - return QDF_STATUS_E_FAILURE; + goto smmu_unmap; } result = qdf_ipa_resume_wdi_pipe(ipa_res->tx_pipe_handle); if (result) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Resume TX PIPE fail, code %d", __func__, result); - return QDF_STATUS_E_FAILURE; + goto smmu_unmap; } ol_txrx_ipa_uc_set_active((struct cdp_pdev *)pdev, true, true); @@ -1466,18 +1491,27 @@ QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_pdev *ppdev) QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Enable RX PIPE fail, code %d", __func__, result); - return QDF_STATUS_E_FAILURE; + goto smmu_unmap; } result = qdf_ipa_resume_wdi_pipe(ipa_res->rx_pipe_handle); if (result) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Resume RX PIPE fail, code %d", __func__, result); - return QDF_STATUS_E_FAILURE; + goto smmu_unmap; } ol_txrx_ipa_uc_set_active((struct cdp_pdev *)pdev, true, false); return QDF_STATUS_SUCCESS; + +smmu_unmap: + if (htt_rx_update_smmu_map(pdev->htt_pdev, false) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "IPA SMMU unmap failed"); + } + + return QDF_STATUS_E_FAILURE; } /** @@ -1499,7 +1533,7 @@ QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_pdev *ppdev) QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Suspend RX PIPE fail, code %d", __func__, result); - return QDF_STATUS_E_FAILURE; + goto smmu_unmap; } result = qdf_ipa_disable_wdi_pipe(ipa_res->rx_pipe_handle); @@ -1507,7 +1541,7 @@ QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_pdev *ppdev) QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Disable RX PIPE fail, code %d", __func__, result); - return QDF_STATUS_E_FAILURE; + goto smmu_unmap; } QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, @@ -1517,17 +1551,24 @@ QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_pdev *ppdev) QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Suspend TX PIPE fail, code %d", __func__, result); - return QDF_STATUS_E_FAILURE; + goto smmu_unmap; } result = qdf_ipa_disable_wdi_pipe(ipa_res->tx_pipe_handle); if (result) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Disable TX PIPE fail, code %d", __func__, result); - return QDF_STATUS_E_FAILURE; + goto smmu_unmap; } - return QDF_STATUS_SUCCESS; +smmu_unmap: + if (htt_rx_update_smmu_map(pdev->htt_pdev, false) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "IPA SMMU unmap failed"); + } + + return result ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS; } /**