@@ -85,6 +85,7 @@ struct xdma_chan {
8585 * @cyclic: Cyclic transfer vs. scatter-gather
8686 * @periods: Number of periods in the cyclic transfer
8787 * @period_size: Size of a period in bytes in cyclic transfers
88+ * @error: tx error flag
8889 */
8990struct xdma_desc {
9091 struct virt_dma_desc vdesc ;
@@ -97,6 +98,7 @@ struct xdma_desc {
9798 bool cyclic ;
9899 u32 periods ;
99100 u32 period_size ;
101+ bool error ;
100102};
101103
102104#define XDMA_DEV_STATUS_REG_DMA BIT(0)
@@ -274,6 +276,7 @@ xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num, bool cyclic)
274276 sw_desc -> chan = chan ;
275277 sw_desc -> desc_num = desc_num ;
276278 sw_desc -> cyclic = cyclic ;
279+ sw_desc -> error = false;
277280 dblk_num = DIV_ROUND_UP (desc_num , XDMA_DESC_ADJACENT );
278281 sw_desc -> desc_blocks = kcalloc (dblk_num , sizeof (* sw_desc -> desc_blocks ),
279282 GFP_NOWAIT );
@@ -769,20 +772,20 @@ static enum dma_status xdma_tx_status(struct dma_chan *chan, dma_cookie_t cookie
769772 spin_lock_irqsave (& xdma_chan -> vchan .lock , flags );
770773
771774 vd = vchan_find_desc (& xdma_chan -> vchan , cookie );
772- if (vd )
773- desc = to_xdma_desc (vd );
774- if (!desc || !desc -> cyclic ) {
775- spin_unlock_irqrestore (& xdma_chan -> vchan .lock , flags );
776- return ret ;
777- }
778-
779- period_idx = desc -> completed_desc_num % desc -> periods ;
780- residue = (desc -> periods - period_idx ) * desc -> period_size ;
775+ if (!vd )
776+ goto out ;
781777
778+ desc = to_xdma_desc (vd );
779+ if (desc -> error ) {
780+ ret = DMA_ERROR ;
781+ } else if (desc -> cyclic ) {
782+ period_idx = desc -> completed_desc_num % desc -> periods ;
783+ residue = (desc -> periods - period_idx ) * desc -> period_size ;
784+ dma_set_residue (state , residue );
785+ }
786+ out :
782787 spin_unlock_irqrestore (& xdma_chan -> vchan .lock , flags );
783788
784- dma_set_residue (state , residue );
785-
786789 return ret ;
787790}
788791
@@ -819,6 +822,7 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
819822 st &= XDMA_CHAN_STATUS_MASK ;
820823 if ((st & XDMA_CHAN_ERROR_MASK ) ||
821824 !(st & (CHAN_CTRL_IE_DESC_COMPLETED | CHAN_CTRL_IE_DESC_STOPPED ))) {
825+ desc -> error = true;
822826 xdma_err (xdev , "channel error, status register value: 0x%x" , st );
823827 goto out ;
824828 }
0 commit comments