@@ -203,6 +203,7 @@ struct at_xdmac_chan {
203203 u32 save_cim ;
204204 u32 save_cnda ;
205205 u32 save_cndc ;
206+ u32 irq_status ;
206207 unsigned long status ;
207208 struct tasklet_struct tasklet ;
208209 struct dma_slave_config sconfig ;
@@ -307,6 +308,11 @@ static inline int at_xdmac_csize(u32 maxburst)
307308 return csize ;
308309};
309310
311+ static inline bool at_xdmac_chan_is_peripheral_xfer (u32 cfg )
312+ {
313+ return cfg & AT_XDMAC_CC_TYPE_PER_TRAN ;
314+ }
315+
310316static inline u8 at_xdmac_get_dwidth (u32 cfg )
311317{
312318 return (cfg & AT_XDMAC_CC_DWIDTH_MASK ) >> AT_XDMAC_CC_DWIDTH_OFFSET ;
@@ -388,7 +394,13 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan,
388394 at_xdmac_chan_read (atchan , AT_XDMAC_CUBC ));
389395
390396 at_xdmac_chan_write (atchan , AT_XDMAC_CID , 0xffffffff );
391- reg = AT_XDMAC_CIE_RBEIE | AT_XDMAC_CIE_WBEIE | AT_XDMAC_CIE_ROIE ;
397+ reg = AT_XDMAC_CIE_RBEIE | AT_XDMAC_CIE_WBEIE ;
398+ /*
399+ * Request Overflow Error is only for peripheral synchronized transfers
400+ */
401+ if (at_xdmac_chan_is_peripheral_xfer (first -> lld .mbr_cfg ))
402+ reg |= AT_XDMAC_CIE_ROIE ;
403+
392404 /*
393405 * There is no end of list when doing cyclic dma, we need to get
394406 * an interrupt after each periods.
@@ -1574,38 +1586,73 @@ static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan)
15741586 dmaengine_desc_get_callback_invoke (txd , NULL );
15751587}
15761588
1589+ static void at_xdmac_handle_error (struct at_xdmac_chan * atchan )
1590+ {
1591+ struct at_xdmac * atxdmac = to_at_xdmac (atchan -> chan .device );
1592+ struct at_xdmac_desc * bad_desc ;
1593+
1594+ /*
1595+ * The descriptor currently at the head of the active list is
1596+ * broked. Since we don't have any way to report errors, we'll
1597+ * just have to scream loudly and try to carry on.
1598+ */
1599+ if (atchan -> irq_status & AT_XDMAC_CIS_RBEIS )
1600+ dev_err (chan2dev (& atchan -> chan ), "read bus error!!!" );
1601+ if (atchan -> irq_status & AT_XDMAC_CIS_WBEIS )
1602+ dev_err (chan2dev (& atchan -> chan ), "write bus error!!!" );
1603+ if (atchan -> irq_status & AT_XDMAC_CIS_ROIS )
1604+ dev_err (chan2dev (& atchan -> chan ), "request overflow error!!!" );
1605+
1606+ spin_lock_bh (& atchan -> lock );
1607+ /* Channel must be disabled first as it's not done automatically */
1608+ at_xdmac_write (atxdmac , AT_XDMAC_GD , atchan -> mask );
1609+ while (at_xdmac_read (atxdmac , AT_XDMAC_GS ) & atchan -> mask )
1610+ cpu_relax ();
1611+ bad_desc = list_first_entry (& atchan -> xfers_list ,
1612+ struct at_xdmac_desc ,
1613+ xfer_node );
1614+ spin_unlock_bh (& atchan -> lock );
1615+ /* Print bad descriptor's details if needed */
1616+ dev_dbg (chan2dev (& atchan -> chan ),
1617+ "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n" ,
1618+ __func__ , & bad_desc -> lld .mbr_sa , & bad_desc -> lld .mbr_da ,
1619+ bad_desc -> lld .mbr_ubc );
1620+
1621+ /* Then continue with usual descriptor management */
1622+ }
1623+
15771624static void at_xdmac_tasklet (unsigned long data )
15781625{
15791626 struct at_xdmac_chan * atchan = (struct at_xdmac_chan * )data ;
15801627 struct at_xdmac_desc * desc ;
15811628 u32 error_mask ;
15821629
1583- dev_dbg (chan2dev (& atchan -> chan ), "%s: status=0x%08lx \n" ,
1584- __func__ , atchan -> status );
1630+ dev_dbg (chan2dev (& atchan -> chan ), "%s: status=0x%08x \n" ,
1631+ __func__ , atchan -> irq_status );
15851632
15861633 error_mask = AT_XDMAC_CIS_RBEIS
15871634 | AT_XDMAC_CIS_WBEIS
15881635 | AT_XDMAC_CIS_ROIS ;
15891636
15901637 if (at_xdmac_chan_is_cyclic (atchan )) {
15911638 at_xdmac_handle_cyclic (atchan );
1592- } else if ((atchan -> status & AT_XDMAC_CIS_LIS )
1593- || (atchan -> status & error_mask )) {
1639+ } else if ((atchan -> irq_status & AT_XDMAC_CIS_LIS )
1640+ || (atchan -> irq_status & error_mask )) {
15941641 struct dma_async_tx_descriptor * txd ;
15951642
1596- if (atchan -> status & AT_XDMAC_CIS_RBEIS )
1597- dev_err (chan2dev (& atchan -> chan ), "read bus error!!!" );
1598- if (atchan -> status & AT_XDMAC_CIS_WBEIS )
1599- dev_err (chan2dev (& atchan -> chan ), "write bus error!!!" );
1600- if (atchan -> status & AT_XDMAC_CIS_ROIS )
1601- dev_err (chan2dev (& atchan -> chan ), "request overflow error!!!" );
1643+ if (atchan -> irq_status & error_mask )
1644+ at_xdmac_handle_error (atchan );
16021645
16031646 spin_lock_bh (& atchan -> lock );
16041647 desc = list_first_entry (& atchan -> xfers_list ,
16051648 struct at_xdmac_desc ,
16061649 xfer_node );
16071650 dev_vdbg (chan2dev (& atchan -> chan ), "%s: desc 0x%p\n" , __func__ , desc );
1608- BUG_ON (!desc -> active_xfer );
1651+ if (!desc -> active_xfer ) {
1652+ dev_err (chan2dev (& atchan -> chan ), "Xfer not active: exiting" );
1653+ spin_unlock_bh (& atchan -> lock );
1654+ return ;
1655+ }
16091656
16101657 txd = & desc -> tx_dma_desc ;
16111658
@@ -1652,7 +1699,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
16521699 atchan = & atxdmac -> chan [i ];
16531700 chan_imr = at_xdmac_chan_read (atchan , AT_XDMAC_CIM );
16541701 chan_status = at_xdmac_chan_read (atchan , AT_XDMAC_CIS );
1655- atchan -> status = chan_status & chan_imr ;
1702+ atchan -> irq_status = chan_status & chan_imr ;
16561703 dev_vdbg (atxdmac -> dma .dev ,
16571704 "%s: chan%d: imr=0x%x, status=0x%x\n" ,
16581705 __func__ , i , chan_imr , chan_status );
@@ -1666,7 +1713,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
16661713 at_xdmac_chan_read (atchan , AT_XDMAC_CDA ),
16671714 at_xdmac_chan_read (atchan , AT_XDMAC_CUBC ));
16681715
1669- if (atchan -> status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS ))
1716+ if (atchan -> irq_status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS ))
16701717 at_xdmac_write (atxdmac , AT_XDMAC_GD , atchan -> mask );
16711718
16721719 tasklet_schedule (& atchan -> tasklet );
0 commit comments