summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoshni Shah <roshni.shah@timesys.com>2014-01-07 00:34:13 -0500
committerAnthony Felice <tony.felice@timesys.com>2014-03-27 15:52:26 -0400
commit4ff9bbaa67ff75d0425eb910bd4a8eb1b1e4aaab (patch)
tree9f089fc33473b2d32dc2a0059347445033f55ebc
parent50c4c848d6b8743894cfcec166db475ef6140504 (diff)
Fixed a panic seen as soon as you type a character on the terminal when EDMA is disabled in UART config. The receive interrupt was attempting to schedule a work queue only defined if EDMA is enabled.
kernel BUG at kernel/workqueue.c:1037! Unable to handle kernel NULL pointer dereference at virtual address 00000000
-rw-r--r--drivers/tty/serial/mvf.c42
1 files changed, 22 insertions, 20 deletions
diff --git a/drivers/tty/serial/mvf.c b/drivers/tty/serial/mvf.c
index 814a7daa56f0..1b730afd4312 100644
--- a/drivers/tty/serial/mvf.c
+++ b/drivers/tty/serial/mvf.c
@@ -84,22 +84,22 @@ struct imx_port {
unsigned int format_9bits:1; /* 9bits data format */
unsigned short trcv_delay; /* transceiver delay */
unsigned char ma_addr; /* Match address */
- struct clk *clk;
+ struct clk *clk;
unsigned int tx_fifo_size, rx_fifo_size;
/* DMA fields */
- int enable_dma;
+ int enable_dma;
unsigned long dma_tx_ch; /* configured eDMA channel */
struct imx_dma_data dma_data;
struct dma_chan *dma_chan_rx, *dma_chan_tx;
struct scatterlist rx_sgl, tx_sgl;
- void *rx_buf;
+ void *rx_buf;
unsigned char *tx_buf;
unsigned int rx_bytes, tx_bytes;
struct work_struct tsk_rx, tsk_dma_tx;
unsigned int dma_tx_nents;
- bool dma_is_rxing, dma_is_txing;
+ bool dma_is_rxing, dma_is_txing;
wait_queue_head_t dma_wait;
};
@@ -226,21 +226,21 @@ static void tx_uart_dmarun(struct imx_port *sport)
if (sport->dma_tx_nents == 0)
return;
- mcf_edma_set_tcd_params(sport->dma_tx_ch,
- (u32)sg_phys(&sport->tx_sgl),
- (u32)(sport->port.mapbase + MXC_UARTDR),
+ mcf_edma_set_tcd_params(sport->dma_tx_ch, /* channel number */
+ (u32)sg_phys(&sport->tx_sgl), /* source */
+ (u32)(sport->port.mapbase + MXC_UARTDR), /* dest */
MCF_EDMA_TCD_ATTR_SSIZE_8BIT |
- MCF_EDMA_TCD_ATTR_DSIZE_8BIT,
- 1,
- 1,
- 0,
- sport->tx_bytes,
- 0,
- 0,
- 0,
+ MCF_EDMA_TCD_ATTR_DSIZE_8BIT, /* attr */
+ 1, /* soff */
+ 1, /* nbytes */
+ 0, /* slast */
+ sport->tx_bytes, /* citer */
+ 0, /* biter */
+ 0, /* doff */
+ 0, /* dlast_sga */
1, /* major_int */
1, /* disable_req */
- 0
+ 0 /* enabled sg */
);
sport->dma_is_txing = 1;
mcf_edma_enable_transfer(sport->dma_tx_ch);
@@ -304,7 +304,7 @@ static void dma_tx_work(struct work_struct *w)
{
if (sport->port.state->port.tty)
{
- uart_write_wakeup(&sport->port);
+ uart_write_wakeup(&sport->port);
}
}
@@ -359,7 +359,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id)
{
if (sport->port.state->port.tty)
{
- uart_write_wakeup(&sport->port);
+ uart_write_wakeup(&sport->port);
}
}
@@ -446,8 +446,10 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
out:
spin_unlock_irqrestore(&sport->port.lock, flags);
- //TODO: Check tsk_rx, seems to be edma related.
- schedule_work(&sport->tsk_rx);
+ if (sport->rx_bytes) {
+ tty_flip_buffer_push(tty);
+ sport->rx_bytes = 0;
+ }
return IRQ_HANDLED;
}