summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2010-05-07 23:56:09 +0530
committerGary King <gking@nvidia.com>2010-05-11 15:16:13 -0700
commitf24ec023e2d60362372d86d0ee5d95a0d4c2a439 (patch)
tree8a36248172605e477282f357e562b44357b6869b /arch
parentdd9a3d8d141a4b1e09ecb4556804bb7ce5b9a650 (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.c18
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);