@@ -85,6 +85,7 @@ struct xdma_chan {
85
85
* @cyclic: Cyclic transfer vs. scatter-gather
86
86
* @periods: Number of periods in the cyclic transfer
87
87
* @period_size: Size of a period in bytes in cyclic transfers
88
+ * @error: tx error flag
88
89
*/
89
90
struct xdma_desc {
90
91
struct virt_dma_desc vdesc ;
@@ -97,6 +98,7 @@ struct xdma_desc {
97
98
bool cyclic ;
98
99
u32 periods ;
99
100
u32 period_size ;
101
+ bool error ;
100
102
};
101
103
102
104
#define XDMA_DEV_STATUS_REG_DMA BIT(0)
@@ -274,6 +276,7 @@ xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num, bool cyclic)
274
276
sw_desc -> chan = chan ;
275
277
sw_desc -> desc_num = desc_num ;
276
278
sw_desc -> cyclic = cyclic ;
279
+ sw_desc -> error = false;
277
280
dblk_num = DIV_ROUND_UP (desc_num , XDMA_DESC_ADJACENT );
278
281
sw_desc -> desc_blocks = kcalloc (dblk_num , sizeof (* sw_desc -> desc_blocks ),
279
282
GFP_NOWAIT );
@@ -769,20 +772,20 @@ static enum dma_status xdma_tx_status(struct dma_chan *chan, dma_cookie_t cookie
769
772
spin_lock_irqsave (& xdma_chan -> vchan .lock , flags );
770
773
771
774
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 ;
781
777
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 :
782
787
spin_unlock_irqrestore (& xdma_chan -> vchan .lock , flags );
783
788
784
- dma_set_residue (state , residue );
785
-
786
789
return ret ;
787
790
}
788
791
@@ -819,6 +822,7 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
819
822
st &= XDMA_CHAN_STATUS_MASK ;
820
823
if ((st & XDMA_CHAN_ERROR_MASK ) ||
821
824
!(st & (CHAN_CTRL_IE_DESC_COMPLETED | CHAN_CTRL_IE_DESC_STOPPED ))) {
825
+ desc -> error = true;
822
826
xdma_err (xdev , "channel error, status register value: 0x%x" , st );
823
827
goto out ;
824
828
}
0 commit comments