Skip to content

Commit d175222

Browse files
1991Joyzouvinodkoul
authored andcommitted
dmaegnine: fsl-edma: add edma error interrupt handler
Add the edma error interrupt handler because it's useful to debug issue. i.MX8ULP edma has per channel error interrupt. i.MX91/93/95 and i.MX8QM/QXP/DXL edma share one error interrupt. Signed-off-by: Joy Zou <[email protected]> Signed-off-by: Frank Li <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent a9ea01f commit d175222

File tree

3 files changed

+149
-13
lines changed

3 files changed

+149
-13
lines changed

drivers/dma/fsl-edma-common.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ static void fsl_edma3_enable_request(struct fsl_edma_chan *fsl_chan)
9595
}
9696

9797
val = edma_readl_chreg(fsl_chan, ch_csr);
98-
val |= EDMA_V3_CH_CSR_ERQ;
98+
val |= EDMA_V3_CH_CSR_ERQ | EDMA_V3_CH_CSR_EEI;
9999
edma_writel_chreg(fsl_chan, val, ch_csr);
100100
}
101101

@@ -821,7 +821,7 @@ void fsl_edma_issue_pending(struct dma_chan *chan)
821821
int fsl_edma_alloc_chan_resources(struct dma_chan *chan)
822822
{
823823
struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
824-
int ret;
824+
int ret = 0;
825825

826826
if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK)
827827
clk_prepare_enable(fsl_chan->clk);
@@ -831,17 +831,29 @@ int fsl_edma_alloc_chan_resources(struct dma_chan *chan)
831831
sizeof(struct fsl_edma_hw_tcd64) : sizeof(struct fsl_edma_hw_tcd),
832832
32, 0);
833833

834-
if (fsl_chan->txirq) {
834+
if (fsl_chan->txirq)
835835
ret = request_irq(fsl_chan->txirq, fsl_chan->irq_handler, IRQF_SHARED,
836836
fsl_chan->chan_name, fsl_chan);
837837

838-
if (ret) {
839-
dma_pool_destroy(fsl_chan->tcd_pool);
840-
return ret;
841-
}
842-
}
838+
if (ret)
839+
goto err_txirq;
840+
841+
if (fsl_chan->errirq > 0)
842+
ret = request_irq(fsl_chan->errirq, fsl_chan->errirq_handler, IRQF_SHARED,
843+
fsl_chan->errirq_name, fsl_chan);
844+
845+
if (ret)
846+
goto err_errirq;
843847

844848
return 0;
849+
850+
err_errirq:
851+
if (fsl_chan->txirq)
852+
free_irq(fsl_chan->txirq, fsl_chan);
853+
err_txirq:
854+
dma_pool_destroy(fsl_chan->tcd_pool);
855+
856+
return ret;
845857
}
846858

847859
void fsl_edma_free_chan_resources(struct dma_chan *chan)
@@ -862,6 +874,8 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
862874

863875
if (fsl_chan->txirq)
864876
free_irq(fsl_chan->txirq, fsl_chan);
877+
if (fsl_chan->errirq)
878+
free_irq(fsl_chan->errirq, fsl_chan);
865879

866880
vchan_dma_desc_free_list(&fsl_chan->vchan, &head);
867881
dma_pool_destroy(fsl_chan->tcd_pool);

drivers/dma/fsl-edma-common.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@
7171
#define EDMA_V3_CH_ES_ERR BIT(31)
7272
#define EDMA_V3_MP_ES_VLD BIT(31)
7373

74+
#define EDMA_V3_CH_ERR_DBE BIT(0)
75+
#define EDMA_V3_CH_ERR_SBE BIT(1)
76+
#define EDMA_V3_CH_ERR_SGE BIT(2)
77+
#define EDMA_V3_CH_ERR_NCE BIT(3)
78+
#define EDMA_V3_CH_ERR_DOE BIT(4)
79+
#define EDMA_V3_CH_ERR_DAE BIT(5)
80+
#define EDMA_V3_CH_ERR_SOE BIT(6)
81+
#define EDMA_V3_CH_ERR_SAE BIT(7)
82+
#define EDMA_V3_CH_ERR_ECX BIT(8)
83+
#define EDMA_V3_CH_ERR_UCE BIT(9)
84+
#define EDMA_V3_CH_ERR BIT(31)
85+
7486
enum fsl_edma_pm_state {
7587
RUNNING = 0,
7688
SUSPENDED,
@@ -162,6 +174,7 @@ struct fsl_edma_chan {
162174
u32 dma_dev_size;
163175
enum dma_data_direction dma_dir;
164176
char chan_name[32];
177+
char errirq_name[36];
165178
void __iomem *tcd;
166179
void __iomem *mux_addr;
167180
u32 real_count;
@@ -174,7 +187,9 @@ struct fsl_edma_chan {
174187
int priority;
175188
int hw_chanid;
176189
int txirq;
190+
int errirq;
177191
irqreturn_t (*irq_handler)(int irq, void *dev_id);
192+
irqreturn_t (*errirq_handler)(int irq, void *dev_id);
178193
bool is_rxchan;
179194
bool is_remote;
180195
bool is_multi_fifo;
@@ -208,6 +223,9 @@ struct fsl_edma_desc {
208223
/* Need clean CHn_CSR DONE before enable TCD's MAJORELINK */
209224
#define FSL_EDMA_DRV_CLEAR_DONE_E_LINK BIT(14)
210225
#define FSL_EDMA_DRV_TCD64 BIT(15)
226+
/* All channel ERR IRQ share one IRQ line */
227+
#define FSL_EDMA_DRV_ERRIRQ_SHARE BIT(16)
228+
211229

212230
#define FSL_EDMA_DRV_EDMA3 (FSL_EDMA_DRV_SPLIT_REG | \
213231
FSL_EDMA_DRV_BUS_8BYTE | \

drivers/dma/fsl-edma-main.c

Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,83 @@ static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
5050
return IRQ_HANDLED;
5151
}
5252

53+
static void fsl_edma3_err_check(struct fsl_edma_chan *fsl_chan)
54+
{
55+
unsigned int ch_err;
56+
u32 val;
57+
58+
scoped_guard(spinlock, &fsl_chan->vchan.lock) {
59+
ch_err = edma_readl_chreg(fsl_chan, ch_es);
60+
if (!(ch_err & EDMA_V3_CH_ERR))
61+
return;
62+
63+
edma_writel_chreg(fsl_chan, EDMA_V3_CH_ERR, ch_es);
64+
val = edma_readl_chreg(fsl_chan, ch_csr);
65+
val &= ~EDMA_V3_CH_CSR_ERQ;
66+
edma_writel_chreg(fsl_chan, val, ch_csr);
67+
}
68+
69+
/* Ignore this interrupt since channel has been disabled already */
70+
if (!fsl_chan->edesc)
71+
return;
72+
73+
if (ch_err & EDMA_V3_CH_ERR_DBE)
74+
dev_err(&fsl_chan->pdev->dev, "Destination Bus Error interrupt.\n");
75+
76+
if (ch_err & EDMA_V3_CH_ERR_SBE)
77+
dev_err(&fsl_chan->pdev->dev, "Source Bus Error interrupt.\n");
78+
79+
if (ch_err & EDMA_V3_CH_ERR_SGE)
80+
dev_err(&fsl_chan->pdev->dev, "Scatter/Gather Configuration Error interrupt.\n");
81+
82+
if (ch_err & EDMA_V3_CH_ERR_NCE)
83+
dev_err(&fsl_chan->pdev->dev, "NBYTES/CITER Configuration Error interrupt.\n");
84+
85+
if (ch_err & EDMA_V3_CH_ERR_DOE)
86+
dev_err(&fsl_chan->pdev->dev, "Destination Offset Error interrupt.\n");
87+
88+
if (ch_err & EDMA_V3_CH_ERR_DAE)
89+
dev_err(&fsl_chan->pdev->dev, "Destination Address Error interrupt.\n");
90+
91+
if (ch_err & EDMA_V3_CH_ERR_SOE)
92+
dev_err(&fsl_chan->pdev->dev, "Source Offset Error interrupt.\n");
93+
94+
if (ch_err & EDMA_V3_CH_ERR_SAE)
95+
dev_err(&fsl_chan->pdev->dev, "Source Address Error interrupt.\n");
96+
97+
if (ch_err & EDMA_V3_CH_ERR_ECX)
98+
dev_err(&fsl_chan->pdev->dev, "Transfer Canceled interrupt.\n");
99+
100+
if (ch_err & EDMA_V3_CH_ERR_UCE)
101+
dev_err(&fsl_chan->pdev->dev, "Uncorrectable TCD error during channel execution interrupt.\n");
102+
103+
fsl_chan->status = DMA_ERROR;
104+
}
105+
106+
static irqreturn_t fsl_edma3_err_handler_per_chan(int irq, void *dev_id)
107+
{
108+
struct fsl_edma_chan *fsl_chan = dev_id;
109+
110+
fsl_edma3_err_check(fsl_chan);
111+
112+
return IRQ_HANDLED;
113+
}
114+
115+
static irqreturn_t fsl_edma3_err_handler_shared(int irq, void *dev_id)
116+
{
117+
struct fsl_edma_engine *fsl_edma = dev_id;
118+
unsigned int ch;
119+
120+
for (ch = 0; ch < fsl_edma->n_chans; ch++) {
121+
if (fsl_edma->chan_masked & BIT(ch))
122+
continue;
123+
124+
fsl_edma3_err_check(&fsl_edma->chans[ch]);
125+
}
126+
127+
return IRQ_HANDLED;
128+
}
129+
53130
static irqreturn_t fsl_edma3_tx_handler(int irq, void *dev_id)
54131
{
55132
struct fsl_edma_chan *fsl_chan = dev_id;
@@ -309,7 +386,8 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma
309386

310387
static int fsl_edma3_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
311388
{
312-
int i;
389+
char *errirq_name;
390+
int i, ret;
313391

314392
for (i = 0; i < fsl_edma->n_chans; i++) {
315393

@@ -324,6 +402,27 @@ static int fsl_edma3_irq_init(struct platform_device *pdev, struct fsl_edma_engi
324402
return -EINVAL;
325403

326404
fsl_chan->irq_handler = fsl_edma3_tx_handler;
405+
406+
if (!(fsl_edma->drvdata->flags & FSL_EDMA_DRV_ERRIRQ_SHARE)) {
407+
fsl_chan->errirq = fsl_chan->txirq;
408+
fsl_chan->errirq_handler = fsl_edma3_err_handler_per_chan;
409+
}
410+
}
411+
412+
/* All channel err use one irq number */
413+
if (fsl_edma->drvdata->flags & FSL_EDMA_DRV_ERRIRQ_SHARE) {
414+
/* last one is error irq */
415+
fsl_edma->errirq = platform_get_irq_optional(pdev, fsl_edma->n_chans);
416+
if (fsl_edma->errirq < 0)
417+
return 0; /* dts miss err irq, treat as no err irq case */
418+
419+
errirq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s-err",
420+
dev_name(&pdev->dev));
421+
422+
ret = devm_request_irq(&pdev->dev, fsl_edma->errirq, fsl_edma3_err_handler_shared,
423+
0, errirq_name, fsl_edma);
424+
if (ret)
425+
return dev_err_probe(&pdev->dev, ret, "Can't register eDMA err IRQ.\n");
327426
}
328427

329428
return 0;
@@ -464,7 +563,8 @@ static struct fsl_edma_drvdata imx7ulp_data = {
464563
};
465564

466565
static struct fsl_edma_drvdata imx8qm_data = {
467-
.flags = FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3 | FSL_EDMA_DRV_MEM_REMOTE,
566+
.flags = FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3 | FSL_EDMA_DRV_MEM_REMOTE
567+
| FSL_EDMA_DRV_ERRIRQ_SHARE,
468568
.chreg_space_sz = 0x10000,
469569
.chreg_off = 0x10000,
470570
.setup_irq = fsl_edma3_irq_init,
@@ -481,14 +581,15 @@ static struct fsl_edma_drvdata imx8ulp_data = {
481581
};
482582

483583
static struct fsl_edma_drvdata imx93_data3 = {
484-
.flags = FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3,
584+
.flags = FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3 | FSL_EDMA_DRV_ERRIRQ_SHARE,
485585
.chreg_space_sz = 0x10000,
486586
.chreg_off = 0x10000,
487587
.setup_irq = fsl_edma3_irq_init,
488588
};
489589

490590
static struct fsl_edma_drvdata imx93_data4 = {
491-
.flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4,
591+
.flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4
592+
| FSL_EDMA_DRV_ERRIRQ_SHARE,
492593
.chreg_space_sz = 0x8000,
493594
.chreg_off = 0x10000,
494595
.mux_off = 0x10000 + offsetof(struct fsl_edma3_ch_reg, ch_mux),
@@ -498,7 +599,7 @@ static struct fsl_edma_drvdata imx93_data4 = {
498599

499600
static struct fsl_edma_drvdata imx95_data5 = {
500601
.flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4 |
501-
FSL_EDMA_DRV_TCD64,
602+
FSL_EDMA_DRV_TCD64 | FSL_EDMA_DRV_ERRIRQ_SHARE,
502603
.chreg_space_sz = 0x8000,
503604
.chreg_off = 0x10000,
504605
.mux_off = 0x200,
@@ -700,6 +801,9 @@ static int fsl_edma_probe(struct platform_device *pdev)
700801
snprintf(fsl_chan->chan_name, sizeof(fsl_chan->chan_name), "%s-CH%02d",
701802
dev_name(&pdev->dev), i);
702803

804+
snprintf(fsl_chan->errirq_name, sizeof(fsl_chan->errirq_name),
805+
"%s-CH%02d-err", dev_name(&pdev->dev), i);
806+
703807
fsl_chan->edma = fsl_edma;
704808
fsl_chan->pm_state = RUNNING;
705809
fsl_chan->srcid = 0;

0 commit comments

Comments
 (0)