diff options
author | Xin Xie <xxie@nvidia.com> | 2011-03-17 16:02:13 -0700 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-03-18 14:56:03 -0800 |
commit | 41d4494d0d3235b8f0c605364d5bd0370f3d5323 (patch) | |
tree | 9bc5a223cb466f8b5072fad3ed04bd59cffd8a06 /arch | |
parent | 1ae405ab138037ffa3f08b424d23797ce9bcdb0a (diff) |
[ARM]: tegra: fix APB DMA transfer timeout
In one bug report, the APB readl DMA transfer took up to 300mS. And
after apb_readl() has the timeout, the kernel crashed due to the NULL
pointer dereference.
In the apb_readl(), after the timeout the tegra_dma_req is destroyed at
the function return. But the DMA interrupt handler later will try to
delete the same destroyed DMA request link list node which will cause
the kernel crash.
Fix this by dequeue the DMA request if the DMA transfer timeout happens.
Change-Id: Ie1bd0082e1eb507b7f5098d5206797ff6110fe34
Reviewed-on: http://git-master/r/23413
Reviewed-by: Xin Xie <xxie@nvidia.com>
Tested-by: Xin Xie <xxie@nvidia.com>
Reviewed-by: Venkata (Muni) Anda <vanda@nvidia.com>
Reviewed-by: Shail Dave <sdave@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/apbio.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c index d6e08c966e72..2d83ae3a51c2 100644 --- a/arch/arm/mach-tegra/apbio.c +++ b/arch/arm/mach-tegra/apbio.c @@ -66,10 +66,12 @@ static inline u32 apb_readl(unsigned long offset) tegra_dma_enqueue_req(tegra_apb_dma, &req); ret = wait_for_completion_timeout(&tegra_apb_wait, - msecs_to_jiffies(50)); + msecs_to_jiffies(400)); - if (WARN(ret == 0, "apb read dma timed out")) + if (WARN(ret == 0, "apb read dma timed out")) { + tegra_dma_dequeue_req(tegra_apb_dma, &req); *(u32 *)tegra_apb_bb = 0; + } mutex_unlock(&tegra_apb_dma_lock); return *((u32 *)tegra_apb_bb); @@ -103,7 +105,10 @@ static inline void apb_writel(u32 value, unsigned long offset) tegra_dma_enqueue_req(tegra_apb_dma, &req); ret = wait_for_completion_timeout(&tegra_apb_wait, - msecs_to_jiffies(50)); + msecs_to_jiffies(400)); + + if (WARN(ret == 0, "apb write dma timed out")) + tegra_dma_dequeue_req(tegra_apb_dma, &req); mutex_unlock(&tegra_apb_dma_lock); } |