Skip to content

Commit 5256278

Browse files
noglitchcristibirsan
authored andcommitted
dmaengine: at_xdmac: enhance channel errors handling in tasklet
Complement the identification of errors with stoping the channel and dumping the descriptor that led to the error case. Signed-off-by: Nicolas Ferre <[email protected]>
1 parent 5b4fa3b commit 5256278

File tree

1 file changed

+37
-6
lines changed

1 file changed

+37
-6
lines changed

drivers/dma/at_xdmac.c

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,41 @@ static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan)
15751575
dmaengine_desc_get_callback_invoke(txd, NULL);
15761576
}
15771577

1578+
static void at_xdmac_handle_error(struct at_xdmac_chan *atchan)
1579+
{
1580+
struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
1581+
struct at_xdmac_desc *bad_desc;
1582+
1583+
/*
1584+
* The descriptor currently at the head of the active list is
1585+
* broked. Since we don't have any way to report errors, we'll
1586+
* just have to scream loudly and try to carry on.
1587+
*/
1588+
if (atchan->irq_status & AT_XDMAC_CIS_RBEIS)
1589+
dev_err(chan2dev(&atchan->chan), "read bus error!!!");
1590+
if (atchan->irq_status & AT_XDMAC_CIS_WBEIS)
1591+
dev_err(chan2dev(&atchan->chan), "write bus error!!!");
1592+
if (atchan->irq_status & AT_XDMAC_CIS_ROIS)
1593+
dev_err(chan2dev(&atchan->chan), "request overflow error!!!");
1594+
1595+
spin_lock_bh(&atchan->lock);
1596+
/* Channel must be disabled first as it's not done automatically */
1597+
at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
1598+
while (at_xdmac_read(atxdmac, AT_XDMAC_GS) & atchan->mask)
1599+
cpu_relax();
1600+
bad_desc = list_first_entry(&atchan->xfers_list,
1601+
struct at_xdmac_desc,
1602+
xfer_node);
1603+
spin_unlock_bh(&atchan->lock);
1604+
/* Print bad descriptor's details if needed */
1605+
dev_dbg(chan2dev(&atchan->chan),
1606+
"%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n",
1607+
__func__, &bad_desc->lld.mbr_sa, &bad_desc->lld.mbr_da,
1608+
bad_desc->lld.mbr_ubc);
1609+
1610+
/* Then continue with usual descriptor management */
1611+
}
1612+
15781613
static void at_xdmac_tasklet(unsigned long data)
15791614
{
15801615
struct at_xdmac_chan *atchan = (struct at_xdmac_chan *)data;
@@ -1594,12 +1629,8 @@ static void at_xdmac_tasklet(unsigned long data)
15941629
|| (atchan->irq_status & error_mask)) {
15951630
struct dma_async_tx_descriptor *txd;
15961631

1597-
if (atchan->irq_status & AT_XDMAC_CIS_RBEIS)
1598-
dev_err(chan2dev(&atchan->chan), "read bus error!!!");
1599-
if (atchan->irq_status & AT_XDMAC_CIS_WBEIS)
1600-
dev_err(chan2dev(&atchan->chan), "write bus error!!!");
1601-
if (atchan->irq_status & AT_XDMAC_CIS_ROIS)
1602-
dev_err(chan2dev(&atchan->chan), "request overflow error!!!");
1632+
if (atchan->irq_status & error_mask)
1633+
at_xdmac_handle_error(atchan);
16031634

16041635
spin_lock_bh(&atchan->lock);
16051636
desc = list_first_entry(&atchan->xfers_list,

0 commit comments

Comments
 (0)