summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjiad <jiad@codeaurora.org>2018-09-19 19:03:06 +0800
committernshrivas <nshrivas@codeaurora.org>2018-09-26 02:09:30 -0700
commitd1e7d29fff8ce00030a2145353ee25e9a9c3a040 (patch)
treea7c9413b1f124aa35a14e749922caa7622a02d88
parent76f3fa19095f7812f048734d77ae6c0d00f6970b (diff)
qcacld-3.0: Fix WDI 1.0 MCC TX SMMU fault
SMMU fault is observed for WDI 1.0 MCC TX when SMMU is enabled. Issue is that dma_addr passed from IPA driver is iova of IPA domain. WLAN driver directly uses the iova to do transmission. Since iova is not mapped in WLAN domain, SMMU fault occurs. Fix is to map skb to WLAN domain for TX when SMMU is enabled. Change-Id: I4c029a1e4dfff149e2784f5b95fe1f3cf3e3719e CRs-Fixed: 2318537
-rw-r--r--core/dp/txrx/ol_tx_desc.c11
-rw-r--r--core/dp/txrx/ol_tx_queue.c11
-rw-r--r--core/hdd/src/wlan_hdd_ipa.c41
3 files changed, 52 insertions, 11 deletions
diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c
index 0f94e7f27152..7b7bab9d20e6 100644
--- a/core/dp/txrx/ol_tx_desc.c
+++ b/core/dp/txrx/ol_tx_desc.c
@@ -738,9 +738,14 @@ 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);
+ else if (qdf_mem_smmu_s1_enabled(pdev->osdev))
+ 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_tx_queue.c b/core/dp/txrx/ol_tx_queue.c
index e35ab046a421..bc4825aba89a 100644
--- a/core/dp/txrx/ol_tx_queue.c
+++ b/core/dp/txrx/ol_tx_queue.c
@@ -1768,9 +1768,14 @@ void ol_txrx_vdev_flush(ol_txrx_vdev_handle vdev)
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_unmap(vdev->pdev->osdev,
- vdev->ll_pause.txq.head,
- QDF_DMA_TO_DEVICE);
+ 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);
+ else if (qdf_mem_smmu_s1_enabled(vdev->pdev->osdev))
+ 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);
diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c
index fa60b41cbea6..3c4cc3d9efee 100644
--- a/core/hdd/src/wlan_hdd_ipa.c
+++ b/core/hdd/src/wlan_hdd_ipa.c
@@ -5952,6 +5952,9 @@ static void hdd_ipa_send_pkt_to_tl(
hdd_adapter_t *adapter = NULL;
qdf_nbuf_t skb;
struct hdd_ipa_tx_desc *tx_desc;
+ qdf_device_t osdev;
+ qdf_dma_addr_t paddr;
+ QDF_STATUS status;
qdf_spin_lock_bh(&iface_context->interface_lock);
adapter = iface_context->adapter;
@@ -5979,6 +5982,15 @@ static void hdd_ipa_send_pkt_to_tl(
}
}
+ osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
+ if (!osdev) {
+ ipa_free_skb(ipa_tx_desc);
+ iface_context->stats.num_tx_drop++;
+ qdf_spin_unlock_bh(&iface_context->interface_lock);
+ hdd_ipa_wdi_rm_try_release(hdd_ipa);
+ return;
+ }
+
++adapter->stats.tx_packets;
qdf_spin_unlock_bh(&iface_context->interface_lock);
@@ -5989,15 +6001,34 @@ static void hdd_ipa_send_pkt_to_tl(
/* Store IPA Tx buffer ownership into SKB CB */
qdf_nbuf_ipa_owned_set(skb);
+
+ if (hdd_ipa_wdi_is_smmu_enabled(hdd_ipa, 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);
+ hdd_ipa_wdi_rm_try_release(hdd_ipa);
+ return;
+ }
+ } else {
+ paddr = ipa_tx_desc->dma_addr;
+ }
+
if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) {
qdf_nbuf_mapped_paddr_set(skb,
- ipa_tx_desc->dma_addr
- + HDD_IPA_WLAN_FRAG_HEADER
- + HDD_IPA_WLAN_IPA_HEADER);
+ paddr +
+ HDD_IPA_WLAN_FRAG_HEADER +
+ HDD_IPA_WLAN_IPA_HEADER);
+
ipa_tx_desc->skb->len -=
HDD_IPA_WLAN_FRAG_HEADER + HDD_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(&hdd_ipa->q_lock);
/* get free Tx desc and assign ipa_tx_desc pointer */