From: Gagandeep Singh <[email protected]>

fle_sdd_pre_populate() and fle_sdd_sg_pre_populate() converted the SDD
and SG entry virtual addresses to IOVA with DPAA2_VADDR_TO_IOVA(), which
does not verify that the range is actually mapped in the IOMMU/SMMU. An
unmapped buffer was silently programmed into the hardware descriptor,
leading to an SMMU translation fault at transfer time that is hard to
trace back to the missing mapping.

Use DPAA2_VADDR_TO_IOVA_AND_CHECK() for the SDD, source SG and
destination SG buffers and report the offending address and size when
the translation is missing, so the misconfiguration is caught early and
clearly. Both helpers now return an error code which is propagated to
the caller instead of continuing with an invalid descriptor.

Signed-off-by: Gagandeep Singh <[email protected]>
---
 drivers/dma/dpaa2/dpaa2_qdma.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c
index 3b272f6593..c68e9e8b84 100644
--- a/drivers/dma/dpaa2/dpaa2_qdma.c
+++ b/drivers/dma/dpaa2/dpaa2_qdma.c
@@ -1331,6 +1331,18 @@ dpaa2_qdma_vchan_rbp_set(struct qdma_virt_queue *vq,
        return 0;
 }
 
+static void
+dpaa2_qdma_fle_pool_iova_check(struct rte_mempool *mp __rte_unused,
+       void *opaque, struct rte_mempool_memhdr *memhdr,
+       unsigned int mem_idx __rte_unused)
+{
+       int *bad_map = opaque;
+
+       if (DPAA2_VADDR_TO_IOVA_AND_CHECK(memhdr->addr,
+                       memhdr->len) == RTE_BAD_IOVA)
+               *bad_map = 1;
+}
+
 static int
 dpaa2_qdma_vchan_setup(struct rte_dma_dev *dev, uint16_t vchan,
        const struct rte_dma_vchan_conf *conf,
@@ -1340,7 +1352,7 @@ dpaa2_qdma_vchan_setup(struct rte_dma_dev *dev, uint16_t 
vchan,
        struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
        uint32_t pool_size;
        char pool_name[64];
-       int ret;
+       int ret, bad_map = 0;
        uint64_t iova, va;
 
        DPAA2_QDMA_FUNC_TRACE();
@@ -1381,6 +1393,13 @@ dpaa2_qdma_vchan_setup(struct rte_dma_dev *dev, uint16_t 
vchan,
        va = qdma_dev->vqs[vchan].fle_pool->mz->addr_64;
        qdma_dev->vqs[vchan].fle_iova2va_offset = va - iova;
 
+       rte_mempool_mem_iter(qdma_dev->vqs[vchan].fle_pool,
+               dpaa2_qdma_fle_pool_iova_check, &bad_map);
+       if (bad_map) {
+               DPAA2_QDMA_ERR("No IOMMU map for %s", pool_name);
+               return -ENOMEM;
+       }
+
        if (qdma_dev->is_silent) {
                ret = rte_mempool_get_bulk(qdma_dev->vqs[vchan].fle_pool,
                                (void **)qdma_dev->vqs[vchan].cntx_sg,
-- 
2.43.0

Reply via email to