diff options
| author | Neeraj Upadhyay <neeraju@codeaurora.org> | 2017-04-26 13:06:19 +0530 |
|---|---|---|
| committer | Neeraj Upadhyay <neeraju@codeaurora.org> | 2017-04-26 13:18:01 +0530 |
| commit | cf3e50f158501b60da7afdfad68e0e7358485581 (patch) | |
| tree | bfce299e75bde15d4fd56623f247b24b895f0c58 | |
| parent | 048c70075fecb8f92d923fc5595efa00f2a00082 (diff) | |
tty: serial: msm: Move request_irq to the end of startup
Move the request_irq() call to the end of the msm_startup(),
so that we don't handle interrupts while msm_startup() is
running. This avoids potential races while initialization
is in progress. For example, consider below scenario
where rx handler reads the intermediate value of dma->chan,
set in msm_request_rx_dma(), and tries to do dma mapping,
which results in data abort.
uart_port_startup()
msm_startup()
request_irq()
...
msm_request_rx_dma()
...
dma->chan = dma_request_slave_channel_reason(dev, "rx");
<UART RX IRQ>
msm_uart_irq()
msm_handle_rx_dm()
msm_start_rx_dma()
dma->desc = dma_map_single()
<data abort>
Change-Id: I94113fe1ebe400f9bb0113922ebc5d257124e34a
Signed-off-by: Neeraj Upadhyay <neeraju@codeaurora.org>
| -rw-r--r-- | drivers/tty/serial/msm_serial.c | 26 |
1 files changed, 13 insertions, 13 deletions
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index db329230c7ca..75956a8854a2 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -1166,26 +1166,17 @@ static int msm_startup(struct uart_port *port) snprintf(msm_port->name, sizeof(msm_port->name), "msm_serial%d", port->line); - ret = request_irq(port->irq, msm_uart_irq, IRQF_TRIGGER_HIGH, - msm_port->name, port); - if (unlikely(ret)) - return ret; - /* * UART clk must be kept enabled to * avoid losing received character */ ret = clk_prepare_enable(msm_port->clk); - if (ret) { - goto err_clk; + if (ret) return ret; - } ret = clk_prepare_enable(msm_port->pclk); - if (ret) { + if (ret) goto err_pclk; - return ret; - } msm_serial_set_mnd_regs(port); @@ -1213,12 +1204,21 @@ static int msm_startup(struct uart_port *port) msm_request_rx_dma(msm_port, msm_port->uart.mapbase); } + ret = request_irq(port->irq, msm_uart_irq, IRQF_TRIGGER_HIGH, + msm_port->name, port); + if (unlikely(ret)) + goto err_irq; + return 0; +err_irq: + if (msm_port->is_uartdm) + msm_release_dma(msm_port); + + clk_disable_unprepare(msm_port->pclk); + err_pclk: clk_disable_unprepare(msm_port->clk); -err_clk: - free_irq(port->irq, port); return ret; } |
