diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2010-05-07 23:56:09 +0530 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-11 15:16:13 -0700 |
commit | f24ec023e2d60362372d86d0ee5d95a0d4c2a439 (patch) | |
tree | 8a36248172605e477282f357e562b44357b6869b /arch | |
parent | dd9a3d8d141a4b1e09ecb4556804bb7ce5b9a650 (diff) |
tegra serial: Fixing system freeze when doing uart data transfer.
Removed the rx and tx separate lock and used only one lock to control the
interrupt enable bit in independent rx and tx path. The interrupt control
register is shared between the rx and tx workqueue.
Tested on harmony with BT, playing songs for 30 minutes without any packet
loss.
Change-Id: I690f28559c0ae0c3dc98ab930298e964a7ea07dc
Reviewed-on: http://git-master/r/1316
Reviewed-by: Rahul Bansal <rbansal@nvidia.com>
Tested-by: Rahul Bansal <rbansal@nvidia.com>
Tested-by: Anjali Kotnala <akotnala@nvidia.com>
Reviewed-by: Udaykumar Rameshchan Raval <uraval@nvidia.com>
Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/dma.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c index 8efb1bbaa7b6..e8c95cb4d917 100644 --- a/arch/arm/mach-tegra/dma.c +++ b/arch/arm/mach-tegra/dma.c @@ -620,11 +620,12 @@ static void tegra_dma_init_hw(struct tegra_dma_channel *ch) static void handle_oneshot_dma(struct tegra_dma_channel *ch) { - static struct tegra_dma_req *req; + struct tegra_dma_req *req; + unsigned int irq_flags; - spin_lock(&ch->lock); + spin_lock_irqsave(&ch->lock, irq_flags); if (list_empty(&ch->list)) { - spin_unlock(&ch->lock); + spin_unlock_irqrestore(&ch->lock, irq_flags); return; } @@ -643,22 +644,23 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch) req->status = TEGRA_DMA_REQ_SUCCESS; req->req_state = TEGRA_DMA_REQ_STATE_COMPLETE; - spin_unlock(&ch->lock); + spin_unlock_irqrestore(&ch->lock, irq_flags); /* Callback should be called without any lock */ req->complete(req, TEGRA_DMA_REQ_SUCCESS); - spin_lock(&ch->lock); + spin_lock_irqsave(&ch->lock, irq_flags); } if (!list_empty(&ch->list)) { req = list_entry(ch->list.next, typeof(*req), list); - tegra_dma_update_hw(ch, req); + if (req->req_state == TEGRA_DMA_REQ_STATE_QUEUED) + tegra_dma_update_hw(ch, req); } - spin_unlock(&ch->lock); + spin_unlock_irqrestore(&ch->lock, irq_flags); } static void handle_continuous_dma(struct tegra_dma_channel *ch) { - static struct tegra_dma_req *req; + struct tegra_dma_req *req; struct tegra_dma_req *next_req; spin_lock(&ch->lock); |