aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ep93xx_dma.c
diff options
context:
space:
mode:
authorAlexander Sverdlin <alexander.sverdlin@gmx.de>2016-01-07 17:05:48 -0500
committerVinod Koul <vinod.koul@intel.com>2016-01-24 23:19:55 -0500
commit94901e1b24496f04bd59176b7f87406e71505e27 (patch)
tree60da68d4d132eaae4e13092fe932e2f5fedd9a1b /drivers/dma/ep93xx_dma.c
parentc9784a467380dfbd8070c735e651af07331172d9 (diff)
dmaengine: ep93xx: Treat STALL and NFB IRQs same way
Debugging ALSA hangups it was found that EP9302 (latest E2 rev.) DMA controller sometimes asserts STALL interrupt instead of NFB interrupt. Simply ignoring the difference and simply acting upon the amount of data we still have to transfer seems to work fine. This somehow sounds similar to M2M issue which is already dealt with in the driver, when the controller asserts DONE interrupt too early. The issue is not documented in Cirrus Logic erratas for EP93XX, but original Cirrus DMA driver from 2003 (not based on DMA API) did the similar handling of STALL interrupt. In-tree driver (6d831c65) did it also, before conversion to DMA engine API. Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma/ep93xx_dma.c')
-rw-r--r--drivers/dma/ep93xx_dma.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index 57ff46284f15..21f08cc3352b 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -421,23 +421,25 @@ static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac)
421 desc->size); 421 desc->size);
422 } 422 }
423 423
424 switch (irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) { 424 /*
425 case M2P_INTERRUPT_STALL: 425 * Even latest E2 silicon revision sometimes assert STALL interrupt
426 /* Disable interrupts */ 426 * instead of NFB. Therefore we treat them equally, basing on the
427 control = readl(edmac->regs + M2P_CONTROL); 427 * amount of data we still have to transfer.
428 control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT); 428 */
429 m2p_set_control(edmac, control); 429 if (!(irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)))
430 430 return INTERRUPT_UNKNOWN;
431 return INTERRUPT_DONE;
432
433 case M2P_INTERRUPT_NFB:
434 if (ep93xx_dma_advance_active(edmac))
435 m2p_fill_desc(edmac);
436 431
432 if (ep93xx_dma_advance_active(edmac)) {
433 m2p_fill_desc(edmac);
437 return INTERRUPT_NEXT_BUFFER; 434 return INTERRUPT_NEXT_BUFFER;
438 } 435 }
439 436
440 return INTERRUPT_UNKNOWN; 437 /* Disable interrupts */
438 control = readl(edmac->regs + M2P_CONTROL);
439 control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
440 m2p_set_control(edmac, control);
441
442 return INTERRUPT_DONE;
441} 443}
442 444
443/* 445/*