summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2011-03-22 11:42:14 -0700
committerColin Cross <ccross@android.com>2011-03-22 11:42:14 -0700
commit9b571241de8cfa131178e9120ad46f1756bad8a7 (patch)
tree32b885801cbe77ebf254ddae3b21cc447d3a2979 /drivers
parent6c18f5c4b2918a089d278e00e379da838ac4692d (diff)
parentd3c9f78e7ec505076ddad2aefaeef5e8c20a4823 (diff)
Merge branch 'linux-tegra-2.6.36' into android-tegra-2.6.36
Diffstat (limited to 'drivers')
-rw-r--r--drivers/serial/tegra_hsuart.c86
-rw-r--r--drivers/video/tegra/host/debug.c25
2 files changed, 79 insertions, 32 deletions
diff --git a/drivers/serial/tegra_hsuart.c b/drivers/serial/tegra_hsuart.c
index 2c70ac7a7893..b3b8eeaf8cf6 100644
--- a/drivers/serial/tegra_hsuart.c
+++ b/drivers/serial/tegra_hsuart.c
@@ -255,30 +255,19 @@ static int tegra_start_dma_rx(struct tegra_uart_port *t)
static void tegra_rx_dma_threshold_callback(struct tegra_dma_req *req)
{
struct tegra_uart_port *t = req->dev;
- struct uart_port *u = &t->uport;
unsigned long flags;
- spin_lock_irqsave(&u->lock, flags);
+ spin_lock_irqsave(&t->uport.lock, flags);
do_handle_rx_dma(t);
- spin_unlock_irqrestore(&u->lock, flags);
+ spin_unlock_irqrestore(&t->uport.lock, flags);
}
-/* It is expected that the callers take the UART lock when this API is called.
- *
- * There are 2 contexts when this function is called:
- *
- * 1. DMA ISR - DMA ISR triggers the threshold complete calback, which calls the
- * dequue API which in-turn calls this callback. UART lock is taken during
- * the call to the threshold callback.
- *
- * 2. UART ISR - UART calls the dequue API which in-turn will call this API.
- * In this case, UART ISR takes the UART lock.
- * */
-static void tegra_rx_dma_complete_callback(struct tegra_dma_req *req)
+/* must be called with uart lock held */
+static void tegra_rx_dma_complete_req(struct tegra_uart_port *t,
+ struct tegra_dma_req *req)
{
- struct tegra_uart_port *t = req->dev;
struct uart_port *u = &t->uport;
struct tty_struct *tty = u->state->port.tty;
@@ -299,9 +288,24 @@ static void tegra_rx_dma_complete_callback(struct tegra_dma_req *req)
if (req->status == -TEGRA_DMA_REQ_ERROR_ABORTED)
return;
- spin_unlock(&u->lock);
tty_flip_buffer_push(u->state->port.tty);
- spin_lock(&u->lock);
+}
+
+static void tegra_rx_dma_complete_callback(struct tegra_dma_req *req)
+{
+ struct tegra_uart_port *t = req->dev;
+ unsigned long flags;
+
+ /*
+ * should never get called, dma should be dequeued during threshold
+ * callback
+ */
+
+ dev_warn(t->uport.dev, "possible rx overflow\n");
+
+ spin_lock_irqsave(&t->uport.lock, flags);
+ tegra_rx_dma_complete_req(t, req);
+ spin_unlock_irqrestore(&t->uport.lock, flags);
}
/* Lock already taken */
@@ -310,7 +314,9 @@ static void do_handle_rx_dma(struct tegra_uart_port *t)
struct uart_port *u = &t->uport;
if (t->rts_active)
set_rts(t, false);
- tegra_dma_dequeue(t->rx_dma);
+ if (!tegra_dma_dequeue_req(t->rx_dma, &t->rx_dma_req))
+ tegra_rx_dma_complete_req(t, &t->rx_dma_req);
+
tty_flip_buffer_push(u->state->port.tty);
/* enqueue the request again */
tegra_start_dma_rx(t);
@@ -481,22 +487,31 @@ static void tegra_tx_dma_complete_work(struct work_struct *work)
spin_unlock_irqrestore(&t->uport.lock, flags);
}
-static void tegra_tx_dma_complete_callback(struct tegra_dma_req *req)
+/* must be called with uart lock held */
+static void tegra_tx_dma_complete_req(struct tegra_uart_port *t,
+ struct tegra_dma_req *req)
{
- struct tegra_uart_port *t = req->dev;
struct circ_buf *xmit = &t->uport.state->xmit;
int count = req->bytes_transferred;
- unsigned long flags;
-
- dev_vdbg(t->uport.dev, "%s: %d\n", __func__, count);
- spin_lock_irqsave(&t->uport.lock, flags);
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&t->uport);
schedule_work(&t->tx_work);
+}
+
+static void tegra_tx_dma_complete_callback(struct tegra_dma_req *req)
+{
+ struct tegra_uart_port *t = req->dev;
+ unsigned long flags;
+
+ dev_vdbg(t->uport.dev, "%s: %d\n", __func__, req->bytes_transferred);
+
+ spin_lock_irqsave(&t->uport.lock, flags);
+
+ tegra_tx_dma_complete_req(t, req);
spin_unlock_irqrestore(&t->uport.lock, flags);
}
@@ -584,14 +599,20 @@ static void tegra_stop_rx(struct uart_port *u)
set_rts(t, false);
if (t->rx_in_progress) {
+ wait_sym_time(t, 1); /* wait a character interval */
+
ier = t->ier_shadow;
ier &= ~(UART_IER_RDI | UART_IER_RLSI | UART_IER_RTOIE | UART_IER_EORD);
t->ier_shadow = ier;
uart_writeb(t, ier, UART_IER);
t->rx_in_progress = 0;
- }
- if (t->use_rx_dma && t->rx_dma) {
- tegra_dma_dequeue(t->rx_dma);
+
+ if (t->use_rx_dma && t->rx_dma) {
+ if (!tegra_dma_dequeue_req(t->rx_dma, &t->rx_dma_req))
+ tegra_rx_dma_complete_req(t, &t->rx_dma_req);
+ } else {
+ do_handle_rx_pio(t);
+ }
tty_flip_buffer_push(u->state->port.tty);
}
@@ -981,8 +1002,10 @@ static void tegra_stop_tx(struct uart_port *u)
t = container_of(u, struct tegra_uart_port, uport);
- if (t->use_tx_dma)
- tegra_dma_dequeue_req(t->tx_dma, &t->tx_dma_req);
+ if (t->use_tx_dma) {
+ if (!tegra_dma_dequeue_req(t->tx_dma, &t->tx_dma_req))
+ tegra_tx_dma_complete_req(t, &t->tx_dma_req);
+ }
return;
}
@@ -1133,7 +1156,8 @@ static void tegra_flush_buffer(struct uart_port *u)
t = container_of(u, struct tegra_uart_port, uport);
if (t->use_tx_dma) {
- tegra_dma_dequeue_req(t->tx_dma, &t->tx_dma_req);
+ if (!tegra_dma_dequeue_req(t->tx_dma, &t->tx_dma_req))
+ tegra_tx_dma_complete_req(t, &t->tx_dma_req);
t->tx_dma_req.size = 0;
}
return;
diff --git a/drivers/video/tegra/host/debug.c b/drivers/video/tegra/host/debug.c
index a1be13eb063c..4f0b941a7ab1 100644
--- a/drivers/video/tegra/host/debug.c
+++ b/drivers/video/tegra/host/debug.c
@@ -126,6 +126,27 @@ static void nvhost_debug_handle_word(struct seq_file *s, int *state, int *count,
}
}
+static void nvhost_sync_reg_dump(struct seq_file *s)
+{
+ struct nvhost_master *m = s->private;
+ int i;
+
+ /* print HOST1X_SYNC regs 4 per line (from 0x3000 -> 0x31E0) */
+ for (i = 0; i <= 0x1E0; i += 4) {
+ if ((i & 0xF) == 0x0)
+ seq_printf(s, "\n0x%08x : ", i);
+ seq_printf(s, "%08x ", readl(m->sync_aperture + i));
+ }
+
+ seq_printf(s, "\n\n");
+
+ /* print HOST1X_SYNC regs 4 per line (from 0x3340 -> 0x3774) */
+ for (i = 0x340; i <= 0x774; i += 4) {
+ if ((i & 0xF) == 0x0)
+ seq_printf(s, "\n0x%08x : ", i);
+ seq_printf(s, "%08x ", readl(m->sync_aperture + i));
+ }
+}
static int nvhost_debug_show(struct seq_file *s, void *unused)
{
@@ -232,7 +253,7 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
fifostat = readl(regs + HOST1X_CHANNEL_FIFOSTAT);
if ((fifostat & 1 << 10) == 0 ) {
- seq_printf(s, "\n%d: fifo:\n", i);
+ seq_printf(s, "\n%d: fifo:\n", i);
writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
writel(1 << 31 | i << 16, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
rd_ptr = readl(m->aperture + HOST1X_SYNC_CFPEEK_PTRS) & 0x1ff;
@@ -265,6 +286,8 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
seq_printf(s, "\n");
}
+ nvhost_sync_reg_dump(s);
+
nvhost_module_idle(&m->mod);
return 0;
}