mirror of https://gitee.com/openkylin/linux.git
[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>
This commit is contained in:
parent
e22b04fb6b
commit
fa3e686a34
|
@ -15,6 +15,9 @@
|
||||||
* Changed to support scatter gather DMA
|
* Changed to support scatter gather DMA
|
||||||
* by taking Russell's code from RiscPC
|
* by taking Russell's code from RiscPC
|
||||||
*
|
*
|
||||||
|
* 2006-05-31 Pavel Pisa <pisa@cmp.felk.cvut.cz>
|
||||||
|
* Corrected error handling code.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
@ -277,7 +280,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch,
|
||||||
int
|
int
|
||||||
imx_dma_setup_handlers(imx_dmach_t dma_ch,
|
imx_dma_setup_handlers(imx_dmach_t dma_ch,
|
||||||
void (*irq_handler) (int, void *, struct pt_regs *),
|
void (*irq_handler) (int, void *, struct pt_regs *),
|
||||||
void (*err_handler) (int, void *, struct pt_regs *),
|
void (*err_handler) (int, void *, struct pt_regs *, int),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
|
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)
|
||||||
int i, disr = DISR;
|
int i, disr = DISR;
|
||||||
struct imx_dma_channel *channel;
|
struct imx_dma_channel *channel;
|
||||||
unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
|
unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
|
||||||
|
int errcode;
|
||||||
|
|
||||||
DISR = disr;
|
DISR = disr & err_mask;
|
||||||
for (i = 0; i < IMX_DMA_CHANNELS; i++) {
|
for (i = 0; i < IMX_DMA_CHANNELS; i++) {
|
||||||
|
if(!(err_mask & (1 << i)))
|
||||||
|
continue;
|
||||||
channel = &imx_dma_channels[i];
|
channel = &imx_dma_channels[i];
|
||||||
|
errcode = 0;
|
||||||
|
|
||||||
if ((err_mask & 1 << i) && channel->name
|
if (DBTOSR & (1 << i)) {
|
||||||
&& channel->err_handler) {
|
DBTOSR = (1 << i);
|
||||||
channel->err_handler(i, channel->data, regs);
|
errcode |= IMX_DMA_ERR_BURST;
|
||||||
|
}
|
||||||
|
if (DRTOSR & (1 << i)) {
|
||||||
|
DRTOSR = (1 << i);
|
||||||
|
errcode |= IMX_DMA_ERR_REQUEST;
|
||||||
|
}
|
||||||
|
if (DSESR & (1 << i)) {
|
||||||
|
DSESR = (1 << i);
|
||||||
|
errcode |= IMX_DMA_ERR_TRANSFER;
|
||||||
|
}
|
||||||
|
if (DBOSR & (1 << i)) {
|
||||||
|
DBOSR = (1 << i);
|
||||||
|
errcode |= IMX_DMA_ERR_BUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The cleaning of @sg field would be questionable
|
||||||
|
* there, because its value can help to compute
|
||||||
|
* remaining/transfered bytes count in the handler
|
||||||
|
*/
|
||||||
|
/*imx_dma_channels[i].sg = NULL;*/
|
||||||
|
|
||||||
|
if (channel->name && channel->err_handler) {
|
||||||
|
channel->err_handler(i, channel->data, regs, errcode);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
imx_dma_channels[i].sg = NULL;
|
imx_dma_channels[i].sg = NULL;
|
||||||
|
|
||||||
if (DBTOSR & (1 << i)) {
|
printk(KERN_WARNING
|
||||||
printk(KERN_WARNING
|
"DMA timeout on channel %d (%s) -%s%s%s%s\n",
|
||||||
"Burst timeout on channel %d (%s)\n",
|
i, channel->name,
|
||||||
i, channel->name);
|
errcode&IMX_DMA_ERR_BURST? " burst":"",
|
||||||
DBTOSR |= (1 << i);
|
errcode&IMX_DMA_ERR_REQUEST? " request":"",
|
||||||
}
|
errcode&IMX_DMA_ERR_TRANSFER? " transfer":"",
|
||||||
if (DRTOSR & (1 << i)) {
|
errcode&IMX_DMA_ERR_BUFFER? " buffer":"");
|
||||||
printk(KERN_WARNING
|
|
||||||
"Request timeout on channel %d (%s)\n",
|
|
||||||
i, channel->name);
|
|
||||||
DRTOSR |= (1 << i);
|
|
||||||
}
|
|
||||||
if (DSESR & (1 << i)) {
|
|
||||||
printk(KERN_WARNING
|
|
||||||
"Transfer timeout on channel %d (%s)\n",
|
|
||||||
i, channel->name);
|
|
||||||
DSESR |= (1 << i);
|
|
||||||
}
|
|
||||||
if (DBOSR & (1 << i)) {
|
|
||||||
printk(KERN_WARNING
|
|
||||||
"Buffer overflow timeout on channel %d (%s)\n",
|
|
||||||
i, channel->name);
|
|
||||||
DBOSR |= (1 << i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
struct imx_dma_channel {
|
struct imx_dma_channel {
|
||||||
const char *name;
|
const char *name;
|
||||||
void (*irq_handler) (int, void *, struct pt_regs *);
|
void (*irq_handler) (int, void *, struct pt_regs *);
|
||||||
void (*err_handler) (int, void *, struct pt_regs *);
|
void (*err_handler) (int, void *, struct pt_regs *, int errcode);
|
||||||
void *data;
|
void *data;
|
||||||
dmamode_t dma_mode;
|
dmamode_t dma_mode;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
|
@ -58,6 +58,10 @@ struct imx_dma_channel {
|
||||||
|
|
||||||
extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
|
extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
|
||||||
|
|
||||||
|
#define IMX_DMA_ERR_BURST 1
|
||||||
|
#define IMX_DMA_ERR_REQUEST 2
|
||||||
|
#define IMX_DMA_ERR_TRANSFER 4
|
||||||
|
#define IMX_DMA_ERR_BUFFER 8
|
||||||
|
|
||||||
/* The type to distinguish channel numbers parameter from ordinal int type */
|
/* The type to distinguish channel numbers parameter from ordinal int type */
|
||||||
typedef int imx_dmach_t;
|
typedef int imx_dmach_t;
|
||||||
|
@ -74,7 +78,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch,
|
||||||
int
|
int
|
||||||
imx_dma_setup_handlers(imx_dmach_t dma_ch,
|
imx_dma_setup_handlers(imx_dmach_t dma_ch,
|
||||||
void (*irq_handler) (int, void *, struct pt_regs *),
|
void (*irq_handler) (int, void *, struct pt_regs *),
|
||||||
void (*err_handler) (int, void *, struct pt_regs *), void *data);
|
void (*err_handler) (int, void *, struct pt_regs *, int), void *data);
|
||||||
|
|
||||||
void imx_dma_enable(imx_dmach_t dma_ch);
|
void imx_dma_enable(imx_dmach_t dma_ch);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue