diff options
| author | Neeraj Upadhyay <neeraju@codeaurora.org> | 2017-04-26 10:37:15 +0530 |
|---|---|---|
| committer | Neeraj Upadhyay <neeraju@codeaurora.org> | 2017-05-02 16:41:48 +0530 |
| commit | beaa060bcc86f1bad00d6d3bb16a918bd8e57d15 (patch) | |
| tree | 8a5d62b3f45e85b271f45c2ce764be37f27435dd | |
| parent | 048c70075fecb8f92d923fc5595efa00f2a00082 (diff) | |
tty: serial: msm: fix potential race b/w startup and irq handling
There is a potential race for tx/rx dma requests between
msm_startup() and irq handling, for cases where dmas are not
available. This results in irq path trying to do dma mapping,
resulting in data abort. 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: Icf5d48f2718c3c6a855ffd3d10988a93f8281d78
Signed-off-by: Neeraj Upadhyay <neeraju@codeaurora.org>
| -rw-r--r-- | drivers/tty/serial/msm_serial.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index db329230c7ca..343a32a4bad3 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -303,15 +303,17 @@ static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base) struct device *dev = msm_port->uart.dev; struct dma_slave_config conf; struct msm_dma *dma; + struct dma_chan *dma_chan; u32 crci = 0; int ret; dma = &msm_port->tx_dma; /* allocate DMA resources, if available */ - dma->chan = dma_request_slave_channel_reason(dev, "tx"); - if (IS_ERR(dma->chan)) + dma_chan = dma_request_slave_channel_reason(dev, "tx"); + if (IS_ERR(dma_chan)) goto no_tx; + dma->chan = dma_chan; of_property_read_u32(dev->of_node, "qcom,tx-crci", &crci); @@ -346,15 +348,17 @@ static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base) struct device *dev = msm_port->uart.dev; struct dma_slave_config conf; struct msm_dma *dma; + struct dma_chan *dma_chan; u32 crci = 0; int ret; dma = &msm_port->rx_dma; /* allocate DMA resources, if available */ - dma->chan = dma_request_slave_channel_reason(dev, "rx"); - if (IS_ERR(dma->chan)) + dma_chan = dma_request_slave_channel_reason(dev, "rx"); + if (IS_ERR(dma_chan)) goto no_rx; + dma->chan = dma_chan; of_property_read_u32(dev->of_node, "qcom,rx-crci", &crci); |
