aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Pisa <ppisa@pikron.com>2006-06-22 17:21:03 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-22 17:21:03 -0400
commitfa3e686a34f4c33de31a128cc36def0b466bfe1a (patch)
tree7fb7bccf367a6d796fcf5751e5b3d901cbe91818
parente22b04fb6b1689aee208b65966fa9fb19e098006 (diff)
[ARM] 3601/1: i.MX/MX1 DMA error handling for signaled channels only
Patch from Pavel Pisa There has been bug, that dma_err_handler() touches even channels not signaling error condition. Problem noticed by Andrea Paterniani. Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-imx/dma.c65
-rw-r--r--include/asm-arm/arch-imx/imx-dma.h8
2 files changed, 45 insertions, 28 deletions
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 4ca51dcf13ac..36578871ecc8 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -15,6 +15,9 @@
15 * Changed to support scatter gather DMA 15 * Changed to support scatter gather DMA
16 * by taking Russell's code from RiscPC 16 * by taking Russell's code from RiscPC
17 * 17 *
18 * 2006-05-31 Pavel Pisa <pisa@cmp.felk.cvut.cz>
19 * Corrected error handling code.
20 *
18 */ 21 */
19 22
20#undef DEBUG 23#undef DEBUG
@@ -277,7 +280,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch,
277int 280int
278imx_dma_setup_handlers(imx_dmach_t dma_ch, 281imx_dma_setup_handlers(imx_dmach_t dma_ch,
279 void (*irq_handler) (int, void *, struct pt_regs *), 282 void (*irq_handler) (int, void *, struct pt_regs *),
280 void (*err_handler) (int, void *, struct pt_regs *), 283 void (*err_handler) (int, void *, struct pt_regs *, int),
281 void *data) 284 void *data)
282{ 285{
283 struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; 286 struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
@@ -463,43 +466,53 @@ static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
463 int i, disr = DISR; 466 int i, disr = DISR;
464 struct imx_dma_channel *channel; 467 struct imx_dma_channel *channel;
465 unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR; 468 unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
469 int errcode;
466 470
467 DISR = disr; 471 DISR = disr & err_mask;
468 for (i = 0; i < IMX_DMA_CHANNELS; i++) { 472 for (i = 0; i < IMX_DMA_CHANNELS; i++) {
469 channel = &imx_dma_channels[i]; 473 if(!(err_mask & (1 << i)))
470
471 if ((err_mask & 1 << i) && channel->name
472 && channel->err_handler) {
473 channel->err_handler(i, channel->data, regs);
474 continue; 474 continue;
475 } 475 channel = &imx_dma_channels[i];
476 476 errcode = 0;
477 imx_dma_channels[i].sg = NULL;
478 477
479 if (DBTOSR & (1 << i)) { 478 if (DBTOSR & (1 << i)) {
480 printk(KERN_WARNING 479 DBTOSR = (1 << i);
481 "Burst timeout on channel %d (%s)\n", 480 errcode |= IMX_DMA_ERR_BURST;
482 i, channel->name);
483 DBTOSR |= (1 << i);
484 } 481 }
485 if (DRTOSR & (1 << i)) { 482 if (DRTOSR & (1 << i)) {
486 printk(KERN_WARNING 483 DRTOSR = (1 << i);
487 "Request timeout on channel %d (%s)\n", 484 errcode |= IMX_DMA_ERR_REQUEST;
488 i, channel->name);
489 DRTOSR |= (1 << i);
490 } 485 }
491 if (DSESR & (1 << i)) { 486 if (DSESR & (1 << i)) {
492 printk(KERN_WARNING 487 DSESR = (1 << i);
493 "Transfer timeout on channel %d (%s)\n", 488 errcode |= IMX_DMA_ERR_TRANSFER;
494 i, channel->name);
495 DSESR |= (1 << i);
496 } 489 }
497 if (DBOSR & (1 << i)) { 490 if (DBOSR & (1 << i)) {
498 printk(KERN_WARNING 491 DBOSR = (1 << i);
499 "Buffer overflow timeout on channel %d (%s)\n", 492 errcode |= IMX_DMA_ERR_BUFFER;
500 i, channel->name);
501 DBOSR |= (1 << i);
502 } 493 }
494
495 /*
496 * The cleaning of @sg field would be questionable
497 * there, because its value can help to compute
498 * remaining/transfered bytes count in the handler
499 */
500 /*imx_dma_channels[i].sg = NULL;*/
501
502 if (channel->name && channel->err_handler) {
503 channel->err_handler(i, channel->data, regs, errcode);
504 continue;
505 }
506
507 imx_dma_channels[i].sg = NULL;
508
509 printk(KERN_WARNING
510 "DMA timeout on channel %d (%s) -%s%s%s%s\n",
511 i, channel->name,
512 errcode&IMX_DMA_ERR_BURST? " burst":"",
513 errcode&IMX_DMA_ERR_REQUEST? " request":"",
514 errcode&IMX_DMA_ERR_TRANSFER? " transfer":"",
515 errcode&IMX_DMA_ERR_BUFFER? " buffer":"");
503 } 516 }
504 return IRQ_HANDLED; 517 return IRQ_HANDLED;
505} 518}
diff --git a/include/asm-arm/arch-imx/imx-dma.h b/include/asm-arm/arch-imx/imx-dma.h
index f2063c1d610d..599f03e5a9ef 100644
--- a/include/asm-arm/arch-imx/imx-dma.h
+++ b/include/asm-arm/arch-imx/imx-dma.h
@@ -46,7 +46,7 @@
46struct imx_dma_channel { 46struct imx_dma_channel {
47 const char *name; 47 const char *name;
48 void (*irq_handler) (int, void *, struct pt_regs *); 48 void (*irq_handler) (int, void *, struct pt_regs *);
49 void (*err_handler) (int, void *, struct pt_regs *); 49 void (*err_handler) (int, void *, struct pt_regs *, int errcode);
50 void *data; 50 void *data;
51 dmamode_t dma_mode; 51 dmamode_t dma_mode;
52 struct scatterlist *sg; 52 struct scatterlist *sg;
@@ -58,6 +58,10 @@ struct imx_dma_channel {
58 58
59extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS]; 59extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
60 60
61#define IMX_DMA_ERR_BURST 1
62#define IMX_DMA_ERR_REQUEST 2
63#define IMX_DMA_ERR_TRANSFER 4
64#define IMX_DMA_ERR_BUFFER 8
61 65
62/* The type to distinguish channel numbers parameter from ordinal int type */ 66/* The type to distinguish channel numbers parameter from ordinal int type */
63typedef int imx_dmach_t; 67typedef int imx_dmach_t;
@@ -74,7 +78,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch,
74int 78int
75imx_dma_setup_handlers(imx_dmach_t dma_ch, 79imx_dma_setup_handlers(imx_dmach_t dma_ch,
76 void (*irq_handler) (int, void *, struct pt_regs *), 80 void (*irq_handler) (int, void *, struct pt_regs *),
77 void (*err_handler) (int, void *, struct pt_regs *), void *data); 81 void (*err_handler) (int, void *, struct pt_regs *, int), void *data);
78 82
79void imx_dma_enable(imx_dmach_t dma_ch); 83void imx_dma_enable(imx_dmach_t dma_ch);
80 84