summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@microchip.com>2019-04-03 06:23:58 -0400
committerVinod Koul <vkoul@kernel.org>2019-04-23 01:08:56 -0400
commit223a4f4cfe93de2fce47a8f1f719cf4d0da4e3e6 (patch)
treedfc362162c6c8a3e890d8d628680403a42aff370
parente2c114c06da2d9ffad5b16690abf008d6696f689 (diff)
dmaengine: at_xdmac: enhance channel errors handling in tasklet
Complement the identification of errors with stopping the channel and dumping the descriptor that led to the error case. Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com> Signed-off-by: Vinod Koul <vkoul@kernel.org>
-rw-r--r--drivers/dma/at_xdmac.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 37a269420435..1dd7edaefbdc 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -1575,6 +1575,46 @@ static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan)
1575 dmaengine_desc_get_callback_invoke(txd, NULL); 1575 dmaengine_desc_get_callback_invoke(txd, NULL);
1576} 1576}
1577 1577
1578static 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 * broken. Since we don't have any way to report errors, we'll
1586 * just have to scream loudly and try to continue with other
1587 * descriptors queued (if any).
1588 */
1589 if (atchan->irq_status & AT_XDMAC_CIS_RBEIS)
1590 dev_err(chan2dev(&atchan->chan), "read bus error!!!");
1591 if (atchan->irq_status & AT_XDMAC_CIS_WBEIS)
1592 dev_err(chan2dev(&atchan->chan), "write bus error!!!");
1593 if (atchan->irq_status & AT_XDMAC_CIS_ROIS)
1594 dev_err(chan2dev(&atchan->chan), "request overflow error!!!");
1595
1596 spin_lock_bh(&atchan->lock);
1597
1598 /* Channel must be disabled first as it's not done automatically */
1599 at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
1600 while (at_xdmac_read(atxdmac, AT_XDMAC_GS) & atchan->mask)
1601 cpu_relax();
1602
1603 bad_desc = list_first_entry(&atchan->xfers_list,
1604 struct at_xdmac_desc,
1605 xfer_node);
1606
1607 spin_unlock_bh(&atchan->lock);
1608
1609 /* Print bad descriptor's details if needed */
1610 dev_dbg(chan2dev(&atchan->chan),
1611 "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n",
1612 __func__, &bad_desc->lld.mbr_sa, &bad_desc->lld.mbr_da,
1613 bad_desc->lld.mbr_ubc);
1614
1615 /* Then continue with usual descriptor management */
1616}
1617
1578static void at_xdmac_tasklet(unsigned long data) 1618static void at_xdmac_tasklet(unsigned long data)
1579{ 1619{
1580 struct at_xdmac_chan *atchan = (struct at_xdmac_chan *)data; 1620 struct at_xdmac_chan *atchan = (struct at_xdmac_chan *)data;
@@ -1594,12 +1634,8 @@ static void at_xdmac_tasklet(unsigned long data)
1594 || (atchan->irq_status & error_mask)) { 1634 || (atchan->irq_status & error_mask)) {
1595 struct dma_async_tx_descriptor *txd; 1635 struct dma_async_tx_descriptor *txd;
1596 1636
1597 if (atchan->irq_status & AT_XDMAC_CIS_RBEIS) 1637 if (atchan->irq_status & error_mask)
1598 dev_err(chan2dev(&atchan->chan), "read bus error!!!"); 1638 at_xdmac_handle_error(atchan);
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!!!");
1603 1639
1604 spin_lock(&atchan->lock); 1640 spin_lock(&atchan->lock);
1605 desc = list_first_entry(&atchan->xfers_list, 1641 desc = list_first_entry(&atchan->xfers_list,