Skip to content

Commit

Permalink
tty: serial: msm: Move request_irq to the end of startup
Browse files Browse the repository at this point in the history
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>

Signed-off-by: Neeraj Upadhyay <neeraju@codeaurora.org>
Reviewd-by: Andy Gross <andy.gross@linaro.org>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Neeraj Upadhyay authored and Greg Kroah-Hartman committed Aug 28, 2017
1 parent 62f466e commit 4d691f7
Showing 1 changed file with 14 additions and 5 deletions.
19 changes: 14 additions & 5 deletions drivers/tty/serial/msm_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -1175,11 +1175,6 @@ 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;

msm_init_clock(port);

if (likely(port->fifosize > 12))
Expand All @@ -1206,7 +1201,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);
clk_disable_unprepare(msm_port->clk);

return ret;
}

static void msm_shutdown(struct uart_port *port)
Expand Down

0 comments on commit 4d691f7

Please sign in to comment.