ERR050757 on LS104x indicates:
For outbound PCIe read transactions, a completion buffer is used
to store the PCIe completions till the data is passed back to the
initiator. At most 16 outstanding transactions are allowed and
maximum read request is 256 bytes. The completion buffer size
inside the controller needs to be at least 4KB, but the PCIe
controller has 3 KB of buffer. In case the size of pending
outbound read transactions of more than 3KB, the PCIe controller
may drop the incoming completions without notifying the initiator
of the transaction, leaving transactions unfinished. All
subsequent outbound reads to PCIe are blocked permanently.
To avoid qDMA hang as it keeps waiting for data that was silently
dropped, set stride mode for qDMA
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
config/arm/meson.build | 3 ++-
doc/guides/dmadevs/dpaa.rst | 2 ++
drivers/dma/dpaa/dpaa_qdma.c | 18 ++++++++++++++++++
drivers/dma/dpaa/dpaa_qdma.h | 5 +++++
4 files changed, 27 insertions(+), 1 deletion(-)
@@ -468,7 +468,8 @@ soc_dpaa = {
['RTE_MACHINE', '"dpaa"'],
['RTE_LIBRTE_DPAA2_USE_PHYS_IOVA', false],
['RTE_MAX_LCORE', 16],
- ['RTE_MAX_NUMA_NODES', 1]
+ ['RTE_MAX_NUMA_NODES', 1],
+ ['RTE_DMA_DPAA_ERRATA_ERR050757', true]
],
'numa': false
}
@@ -42,6 +42,8 @@ Compilation
For builds using ``meson`` and ``ninja``, the driver will be built when the
target platform is dpaa-based. No additional compilation steps are necessary.
+- ``RTE_DMA_DPAA_ERRATA_ERR050757`` - enable software workaround for Errata-A050757
+
Initialization
--------------
@@ -159,6 +159,10 @@ fsl_qdma_comp_fill_memcpy(struct fsl_qdma_comp *fsl_comp,
dma_addr_t dst, dma_addr_t src, u32 len)
{
struct fsl_qdma_format *csgf_src, *csgf_dest;
+#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
+ struct fsl_qdma_sdf *sdf;
+ u32 cfg = 0;
+#endif
/* Note: command table (fsl_comp->virt_addr) is getting filled
* directly in cmd descriptors of queues while enqueuing the descriptor
@@ -171,6 +175,20 @@ fsl_qdma_comp_fill_memcpy(struct fsl_qdma_comp *fsl_comp,
csgf_src = (struct fsl_qdma_format *)fsl_comp->virt_addr + 2;
csgf_dest = (struct fsl_qdma_format *)fsl_comp->virt_addr + 3;
+#ifdef RTE_DMA_DPAA_ERRATA_ERR050757
+ sdf = (struct fsl_qdma_sdf *)fsl_comp->desc_virt_addr;
+ sdf->cmd = rte_cpu_to_le_32(FSL_QDMA_CMD_RWTTYPE <<
+ FSL_QDMA_CMD_RWTTYPE_OFFSET);
+ if (len > FSL_QDMA_CMD_SSS_DISTANCE) {
+ sdf->cmd |= rte_cpu_to_le_32(FSL_QDMA_CMD_SSEN);
+ cfg |= rte_cpu_to_le_32(FSL_QDMA_CMD_SSS_STRIDE <<
+ FSL_QDMA_CFG_SSS_OFFSET |
+ FSL_QDMA_CMD_SSS_DISTANCE);
+ sdf->cfg = cfg;
+ } else
+ sdf->cfg = 0;
+#endif
+
/* Status notification is enqueued to status queue. */
qdma_desc_addr_set64(csgf_src, src);
qdma_csgf_set_len(csgf_src, len);
@@ -81,6 +81,11 @@
#define FSL_QDMA_CMD_RWTTYPE_OFFSET 28
#define FSL_QDMA_CMD_LWC_OFFSET 16
+#define FSL_QDMA_CMD_SSEN BIT(19)
+#define FSL_QDMA_CFG_SSS_OFFSET 12
+#define FSL_QDMA_CMD_SSS_STRIDE 128
+#define FSL_QDMA_CMD_SSS_DISTANCE 128
+
#define QDMA_CCDF_STATUS 20
#define QDMA_CCDF_OFFSET 20
#define QDMA_CCDF_MASK GENMASK(28, 20)