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 rte_panic() with the offending address and size when the translation is missing, so the misconfiguration is caught early and clearly. Signed-off-by: Gagandeep Singh <[email protected]> --- drivers/dma/dpaa2/dpaa2_qdma.c | 42 ++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 6fd3530f0d..8a180ab400 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -187,7 +187,15 @@ fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd, { struct qbman_fle *fle = fle_sdd->fle; struct qdma_sdd *sdd = fle_sdd->sdd; - uint64_t sdd_iova = DPAA2_VADDR_TO_IOVA(sdd); + uint64_t sdd_iova, iova_size; + + iova_size = sizeof(struct qdma_sdd) * DPAA2_QDMA_MAX_SDD; + sdd_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(sdd, iova_size); + if (sdd_iova == RTE_BAD_IOVA) { + DPAA2_QDMA_ERR("No IOMMU map for sdd(%p)(size=%" PRIu64 ")", + sdd, iova_size); + return -ENOMEM; + } /* first frame list to source descriptor */ DPAA2_SET_FLE_ADDR(&fle[DPAA2_QDMA_SDD_FLE], sdd_iova); @@ -285,22 +293,36 @@ sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx) } } -static void +static int fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, struct qdma_virt_queue *qdma_vq) { struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry; struct qdma_sg_entry *dst_sge = sg_cntx->sg_dst_entry; - rte_iova_t src_sge_iova, dst_sge_iova; + rte_iova_t src_sge_iova, dst_sge_iova, iova_size; struct dpaa2_qdma_rbp *rbp = &qdma_vq->rbp; memset(sg_cntx, 0, sizeof(struct qdma_cntx_sg)); - src_sge_iova = DPAA2_VADDR_TO_IOVA(src_sge); - dst_sge_iova = DPAA2_VADDR_TO_IOVA(dst_sge); + iova_size = RTE_DPAAX_QDMA_JOB_SUBMIT_MAX * + sizeof(struct qdma_sg_entry); + + src_sge_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(src_sge, iova_size); + if (src_sge_iova == RTE_BAD_IOVA) { + DPAA2_QDMA_ERR("No IOMMU map for src_sge(%p)(size=%" PRIu64 ")", + src_sge, (uint64_t)iova_size); + return -ENOMEM; + } + + dst_sge_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(dst_sge, iova_size); + if (dst_sge_iova == RTE_BAD_IOVA) { + DPAA2_QDMA_ERR("No IOMMU map for dst_sge(%p)(size=%" PRIu64 ")", + dst_sge, (uint64_t)iova_size); + return -ENOMEM; + } sg_entry_pre_populate(sg_cntx); - fle_sdd_pre_populate(&sg_cntx->fle_sdd, + return fle_sdd_pre_populate(&sg_cntx->fle_sdd, rbp, src_sge_iova, dst_sge_iova, QBMAN_FLE_WORD4_FMT_SGE); } @@ -671,7 +693,13 @@ dpaa2_qdma_copy_sg(void *dev_private, if (qdma_vq->fle_pre_populate) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { - fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); + ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); + if (unlikely(ret)) { + if (!qdma_dev->is_silent) + rte_mempool_put(qdma_vq->fle_pool, + cntx_sg); + return ret; + } if (!qdma_dev->is_silent && cntx_sg && idx_addr) { for (i = 0; i < nb_src; i++) cntx_sg->cntx_idx[i] = idx_addr[i]; -- 2.43.0

