summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeeraj Upadhyay <neeraju@codeaurora.org>2017-04-26 13:06:19 +0530
committerNeeraj Upadhyay <neeraju@codeaurora.org>2017-04-26 13:18:01 +0530
commitcf3e50f158501b60da7afdfad68e0e7358485581 (patch)
treebfce299e75bde15d4fd56623f247b24b895f0c58
parent048c70075fecb8f92d923fc5595efa00f2a00082 (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.c26
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;
}