diff options
author | Pavel Pisa <ppisa@pikron.com> | 2006-06-22 17:21:03 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-06-22 17:21:03 -0400 |
commit | fa3e686a34f4c33de31a128cc36def0b466bfe1a (patch) | |
tree | 7fb7bccf367a6d796fcf5751e5b3d901cbe91818 /arch/arm/mach-imx | |
parent | e22b04fb6b1689aee208b65966fa9fb19e098006 (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>
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r-- | arch/arm/mach-imx/dma.c | 65 |
1 files changed, 39 insertions, 26 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, | |||
277 | int | 280 | int |
278 | imx_dma_setup_handlers(imx_dmach_t dma_ch, | 281 | imx_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 | } |