summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorVenkata(Muni) Anda <muni@nvidia.com>2010-01-21 12:24:41 -0800
committerVenkata(Muni) Anda <muni@nvidia.com>2010-01-21 22:21:12 -0800
commit5b340d629f24131fd5cffee7efa277ba5e1bd400 (patch)
treeb327f1dd4f3917f9a7d72426c312fc76a96b77a2 /arch
parent5e6f67c8be842c0edb243638e2b17e56a1704692 (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')
-rw-r--r--arch/arm/mach-tegra/dma.c27
-rw-r--r--arch/arm/mach-tegra/include/mach/dma.h7
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);