diff --git a/components/ipa/core/src/wlan_ipa_core.c b/components/ipa/core/src/wlan_ipa_core.c index 79f49cc0b89c..73bc5e514572 100644 --- a/components/ipa/core/src/wlan_ipa_core.c +++ b/components/ipa/core/src/wlan_ipa_core.c @@ -235,8 +235,19 @@ static void wlan_ipa_send_pkt_to_tl( qdf_ipa_rx_data_t *ipa_tx_desc) { struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx; + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_psoc *psoc; + qdf_device_t osdev; qdf_nbuf_t skb; struct wlan_ipa_tx_desc *tx_desc; + qdf_dma_addr_t paddr; + QDF_STATUS status; + + if (!ipa_ctx) + return; + pdev = ipa_ctx->pdev; + psoc = wlan_pdev_get_psoc(pdev); + osdev = wlan_psoc_get_qdf_dev(psoc); qdf_spin_lock_bh(&iface_context->interface_lock); /* @@ -253,6 +264,14 @@ static void wlan_ipa_send_pkt_to_tl( return; } } + + if (!osdev) { + ipa_free_skb(ipa_tx_desc); + iface_context->stats.num_tx_drop++; + qdf_spin_unlock_bh(&iface_context->interface_lock); + wlan_ipa_wdi_rm_try_release(ipa_ctx); + return; + } qdf_spin_unlock_bh(&iface_context->interface_lock); skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc); @@ -261,15 +280,33 @@ static void wlan_ipa_send_pkt_to_tl( /* Store IPA Tx buffer ownership into SKB CB */ qdf_nbuf_ipa_owned_set(skb); + + if (qdf_mem_smmu_s1_enabled(osdev)) { + status = qdf_nbuf_map(osdev, skb, QDF_DMA_TO_DEVICE); + if (QDF_IS_STATUS_SUCCESS(status)) { + paddr = qdf_nbuf_get_frag_paddr(skb, 0); + } else { + ipa_free_skb(ipa_tx_desc); + qdf_spin_lock_bh(&iface_context->interface_lock); + iface_context->stats.num_tx_drop++; + qdf_spin_unlock_bh(&iface_context->interface_lock); + wlan_ipa_wdi_rm_try_release(ipa_ctx); + return; + } + } else { + paddr = QDF_IPA_RX_DATA_DMA_ADDR(ipa_tx_desc); + } + if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) { qdf_nbuf_mapped_paddr_set(skb, - QDF_IPA_RX_DATA_DMA_ADDR(ipa_tx_desc) - + WLAN_IPA_WLAN_FRAG_HEADER - + WLAN_IPA_WLAN_IPA_HEADER); + paddr + + WLAN_IPA_WLAN_FRAG_HEADER + + WLAN_IPA_WLAN_IPA_HEADER); QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc) -= WLAN_IPA_WLAN_FRAG_HEADER + WLAN_IPA_WLAN_IPA_HEADER; - } else - qdf_nbuf_mapped_paddr_set(skb, ipa_tx_desc->dma_addr); + } else { + qdf_nbuf_mapped_paddr_set(skb, paddr); + } qdf_spin_lock_bh(&ipa_ctx->q_lock); /* get free Tx desc and assign ipa_tx_desc pointer */ @@ -284,6 +321,14 @@ static void wlan_ipa_send_pkt_to_tl( } else { ipa_ctx->stats.num_tx_desc_error++; qdf_spin_unlock_bh(&ipa_ctx->q_lock); + + if (qdf_mem_smmu_s1_enabled(osdev)) { + if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) + qdf_nbuf_mapped_paddr_set(skb, paddr); + + qdf_nbuf_unmap(osdev, skb, QDF_DMA_TO_DEVICE); + } + qdf_ipa_free_skb(ipa_tx_desc); wlan_ipa_wdi_rm_try_release(ipa_ctx); return; @@ -1386,12 +1431,34 @@ static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb) qdf_ipa_rx_data_t *ipa_tx_desc; struct wlan_ipa_tx_desc *tx_desc; uint16_t id; + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_psoc *psoc; + qdf_device_t osdev; if (!qdf_nbuf_ipa_owned_get(skb)) { dev_kfree_skb_any(skb); return; } + if (!ipa_ctx) + return; + pdev = ipa_ctx->pdev; + psoc = wlan_pdev_get_psoc(pdev); + osdev = wlan_psoc_get_qdf_dev(psoc); + + if (osdev && qdf_mem_smmu_s1_enabled(osdev)) { + if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) { + qdf_dma_addr_t paddr = QDF_NBUF_CB_PADDR(skb); + + qdf_nbuf_mapped_paddr_set(skb, + paddr - + WLAN_IPA_WLAN_FRAG_HEADER - + WLAN_IPA_WLAN_IPA_HEADER); + } + + qdf_nbuf_unmap(osdev, skb, QDF_DMA_TO_DEVICE); + } + /* Get Tx desc pointer from SKB CB */ id = QDF_NBUF_CB_TX_IPA_PRIV(skb); tx_desc = &ipa_ctx->tx_desc_pool[id]; diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index 040c0203b85e..f56d917c152a 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -886,9 +886,11 @@ void ol_tx_desc_frame_list_free(struct ol_txrx_pdev_t *pdev, * DMA mapped address. In such case, there's no need for WLAN * driver to DMA unmap the skb. */ - if ((qdf_nbuf_get_users(msdu) <= 1) && - !qdf_nbuf_ipa_owned_get(msdu)) - qdf_nbuf_unmap(pdev->osdev, msdu, QDF_DMA_TO_DEVICE); + if (qdf_nbuf_get_users(msdu) <= 1) { + if (!qdf_nbuf_ipa_owned_get(msdu)) + qdf_nbuf_unmap(pdev->osdev, msdu, + QDF_DMA_TO_DEVICE); + } /* free the tx desc */ ol_tx_desc_free(pdev, tx_desc); diff --git a/core/dp/txrx/ol_txrx_legacy_flow_control.c b/core/dp/txrx/ol_txrx_legacy_flow_control.c index 7e8ce3fc40a2..4900de373a6f 100644 --- a/core/dp/txrx/ol_txrx_legacy_flow_control.c +++ b/core/dp/txrx/ol_txrx_legacy_flow_control.c @@ -129,11 +129,11 @@ void ol_txrx_vdev_flush(struct cdp_vdev *pvdev) qdf_nbuf_t next = qdf_nbuf_next(vdev->ll_pause.txq.head); qdf_nbuf_set_next(vdev->ll_pause.txq.head, NULL); - if (QDF_NBUF_CB_PADDR(vdev->ll_pause.txq.head) && - !qdf_nbuf_ipa_owned_get(vdev->ll_pause.txq.head)) { - qdf_nbuf_unmap(vdev->pdev->osdev, - vdev->ll_pause.txq.head, - QDF_DMA_TO_DEVICE); + if (QDF_NBUF_CB_PADDR(vdev->ll_pause.txq.head)) { + if (!qdf_nbuf_ipa_owned_get(vdev->ll_pause.txq.head)) + qdf_nbuf_unmap(vdev->pdev->osdev, + vdev->ll_pause.txq.head, + QDF_DMA_TO_DEVICE); } qdf_nbuf_tx_free(vdev->ll_pause.txq.head, QDF_NBUF_PKT_ERROR);