diff options
author | Venkata(Muni) Anda <muni@nvidia.com> | 2010-01-21 12:24:41 -0800 |
---|---|---|
committer | Venkata(Muni) Anda <muni@nvidia.com> | 2010-01-21 22:21:12 -0800 |
commit | 5b340d629f24131fd5cffee7efa277ba5e1bd400 (patch) | |
tree | b327f1dd4f3917f9a7d72426c312fc76a96b77a2 /arch/arm | |
parent | 5e6f67c8be842c0edb243638e2b17e56a1704692 (diff) |
tegra: Update the UART Tx data path and added new system DMA API.
-Using workqueues instead of tasklets for Tx DMA.
-Waiting for the FIFO to drain after the DMA is done, as it is apparently
needed by the HW.
- Added new DMA API to check if the req is already queued. Using
tegra_dma_is_empty might not be correct as one DMA chanel can be serviced
by multiple clients.
With this change, i can browse the BT sometimes. It takes some retires to
enable the BT.
Also during the operation of the BT, i still see the messages like
"out-of-order packet arrived"
Don't know if this is an issue with ther UART or the BT protocol.
Change-Id: I1502ad8178c3c95b4128c564c9f3c1d957195d46
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-tegra/dma.c | 27 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/dma.h | 7 |
2 files changed, 25 insertions, 9 deletions
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c index 4f337d06c5a7..bbd3691240ea 100644 --- a/arch/arm/mach-tegra/dma.c +++ b/arch/arm/mach-tegra/dma.c @@ -212,23 +212,40 @@ int tegra_dma_dequeue_req(int channel, struct tegra_dma_req *_req) } EXPORT_SYMBOL(tegra_dma_dequeue_req); -int tegra_dma_is_empty(int channel) +bool tegra_dma_is_empty(int channel) { unsigned long irq_flags; struct tegra_dma_channel *ch = &dma_channels[channel]; - int is_empty; + bool is_empty; spin_lock_irqsave(&ch->lock, irq_flags); if (list_empty(&ch->list)) - is_empty = 1; + is_empty = true; else - is_empty = 0; + is_empty = false; spin_unlock_irqrestore(&ch->lock, irq_flags); - return is_empty; } EXPORT_SYMBOL(tegra_dma_is_empty); +bool tegra_dma_is_req_inflight(int channel, struct tegra_dma_req *_req) +{ + unsigned long irq_flags; + struct tegra_dma_channel *ch = &dma_channels[channel]; + struct tegra_dma_req *req; + + spin_lock_irqsave(&ch->lock, irq_flags); + list_for_each_entry (req, &ch->list, list) { + if (req == _req) { + spin_unlock_irqrestore(&ch->lock, irq_flags); + return true; + } + } + spin_unlock_irqrestore(&ch->lock, irq_flags); + return false; +} +EXPORT_SYMBOL(tegra_dma_is_req_inflight); + int tegra_dma_enqueue_req(int channel, struct tegra_dma_req *req) { unsigned long irq_flags; diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h index c39be865bafc..508e2fcf8409 100644 --- a/arch/arm/mach-tegra/include/mach/dma.h +++ b/arch/arm/mach-tegra/include/mach/dma.h @@ -101,12 +101,11 @@ struct tegra_dma_req { int tegra_dma_enqueue_req(int channel, struct tegra_dma_req *req); int tegra_dma_dequeue_req(int channel, struct tegra_dma_req *req); void tegra_dma_dequeue(int channel); - -/* Returns 1 if there are DMA is empty. - */ -int tegra_dma_is_empty(int channel); void tegra_dma_flush(int channel); +bool tegra_dma_is_req_inflight(int channel, struct tegra_dma_req *req); +bool tegra_dma_is_empty(int channel); + int tegra_dma_allocate_channel(int mode); void tegra_dma_free_channel(int channel); |