* [PATCH] dmaengine: Extend NXP QDMA driver to check transmission errors
@ 2020-07-07 13:07 Koehrer Mathias (ETAS/EES-SL)
0 siblings, 0 replies; only message in thread
From: Koehrer Mathias (ETAS/EES-SL) @ 2020-07-07 13:07 UTC (permalink / raw)
To: dmaengine, vkoul
Extend NXP QDMA driver to check transmission errors
The NXP QDMA driver (fsl-qdma.c) does not check the status bits
that indicate if a DMA transfer has been completed successfully.
This patch extends the driver to do exactly this.
Signed-off-by: Mathias Koehrer <mathias.koehrer@etas.com>
---
Index: linux-5.4/drivers/dma/fsl-qdma.c
===================================================================
--- linux-5.4.orig/drivers/dma/fsl-qdma.c
+++ linux-5.4/drivers/dma/fsl-qdma.c
@@ -56,7 +56,7 @@
/* Registers for bit and genmask */
#define FSL_QDMA_CQIDR_SQT BIT(15)
-#define QDMA_CCDF_FOTMAT BIT(29)
+#define QDMA_CCDF_FORMAT BIT(29)
#define QDMA_CCDF_SER BIT(30)
#define QDMA_SG_FIN BIT(30)
#define QDMA_SG_LEN_MASK GENMASK(29, 0)
@@ -110,11 +110,23 @@
#define FSL_QDMA_CMD_DSEN_OFFSET 19
#define FSL_QDMA_CMD_LWC_OFFSET 16
+/* Field definition for Descriptor status */
+#define QDMA_CCDF_STATUS_RTE BIT(5)
+#define QDMA_CCDF_STATUS_WTE BIT(4)
+#define QDMA_CCDF_STATUS_CDE BIT(2)
+#define QDMA_CCDF_STATUS_SDE BIT(1)
+#define QDMA_CCDF_STATUS_DDE BIT(0)
+#define QDMA_CCDF_STATUS_MASK QDMA_CCDF_STATUS_RTE | \
+ QDMA_CCDF_STATUS_WTE | \
+ QDMA_CCDF_STATUS_CDE | \
+ QDMA_CCDF_STATUS_SDE | \
+ QDMA_CCDF_STATUS_DDE
+
/* Field definition for Descriptor offset */
-#define QDMA_CCDF_STATUS 20
#define QDMA_CCDF_OFFSET 20
#define QDMA_SDDF_CMD(x) (((u64)(x)) << 32)
+
/* Field definition for safe loop count*/
#define FSL_QDMA_HALT_COUNT 1500
#define FSL_QDMA_MAX_SIZE 16385
@@ -243,13 +255,13 @@ qdma_ccdf_get_offset(const struct fsl_qd
static inline void
qdma_ccdf_set_format(struct fsl_qdma_format *ccdf, int offset)
{
- ccdf->cfg = cpu_to_le32(QDMA_CCDF_FOTMAT | offset);
+ ccdf->cfg = cpu_to_le32(QDMA_CCDF_FORMAT | (offset <<
QDMA_CCDF_OFFSET));
}
static inline int
qdma_ccdf_get_status(const struct fsl_qdma_format *ccdf)
{
- return (le32_to_cpu(ccdf->status) & QDMA_CCDF_MASK) >>
QDMA_CCDF_STATUS;
+ return (le32_to_cpu(ccdf->status) & QDMA_CCDF_STATUS_MASK);
}
static inline void
@@ -618,6 +630,7 @@ fsl_qdma_queue_transfer_complete(struct
{
bool duplicate;
u32 reg, i, count;
+ u8 completion_status;
struct fsl_qdma_queue *temp_queue;
struct fsl_qdma_format *status_addr;
struct fsl_qdma_comp *fsl_comp = NULL;
@@ -677,6 +690,8 @@ fsl_qdma_queue_transfer_complete(struct
}
list_del(&fsl_comp->list);
+ completion_status = qdma_ccdf_get_status(status_addr);
+
reg = qdma_readl(fsl_qdma, block + FSL_QDMA_BSQMR);
reg |= FSL_QDMA_BSQMR_DI;
qdma_desc_addr_set64(status_addr, 0x0);
@@ -686,6 +701,24 @@ fsl_qdma_queue_transfer_complete(struct
qdma_writel(fsl_qdma, reg, block + FSL_QDMA_BSQMR);
spin_unlock(&temp_queue->queue_lock);
+ /* The completion_status is evaluated here (outside of
spin lock) */
+ if (completion_status) {
+ if (completion_status & QDMA_CCDF_STATUS_WTE) {
+ /* Write transaction error */
+ fsl_comp->vdesc.tx_result.result =
DMA_TRANS_WRITE_FAILED;
+ }
+ else if (completion_status &
QDMA_CCDF_STATUS_RTE) {
+ /* Read transaction error */
+ fsl_comp->vdesc.tx_result.result =
DMA_TRANS_READ_FAILED;
+ }
+ else {
+ /* Command/source/destination
description error */
+ fsl_comp->vdesc.tx_result.result =
DMA_TRANS_ABORTED;
+ dev_err(fsl_qdma->dma_dev.dev, "DMA
status descriptor error %x\n",
+ completion_status);
+ }
+ }
+
spin_lock(&fsl_comp->qchan->vchan.lock);
vchan_cookie_complete(&fsl_comp->vdesc);
fsl_comp->qchan->status = DMA_COMPLETE;
@@ -704,7 +737,14 @@ static irqreturn_t fsl_qdma_error_handle
intr = qdma_readl(fsl_qdma, status + FSL_QDMA_DEDR);
if (intr)
- dev_err(fsl_qdma->dma_dev.dev, "DMA transaction
error!\n");
+ {
+ unsigned int decfdw0r = qdma_readl(fsl_qdma, status +
FSL_QDMA_DECFDW0R);
+ unsigned int decfdw1r = qdma_readl(fsl_qdma, status +
FSL_QDMA_DECFDW1R);
+ unsigned int decfdw2r = qdma_readl(fsl_qdma, status +
FSL_QDMA_DECFDW2R);
+ unsigned int decfdw3r = qdma_readl(fsl_qdma, status +
FSL_QDMA_DECFDW3R);
+ dev_err(fsl_qdma->dma_dev.dev, "DMA transaction error!
(%x: %x-%x-%x-%x)\n",
+ intr, decfdw0r, decfdw1r, decfdw2r,
decfdw3r);
+ }
qdma_writel(fsl_qdma, FSL_QDMA_DEDR_CLEAR, status +
FSL_QDMA_DEDR);
return IRQ_HANDLED;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-07-07 13:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-07 13:07 [PATCH] dmaengine: Extend NXP QDMA driver to check transmission errors Koehrer Mathias (ETAS/EES-SL)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).