Message ID | 20210622091710.44032-1-m.shams@samsung.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [v3] serial: samsung: use dma_ops of DMA if attached | expand |
On 22/06/2021 11:17, Tamseel Shams wrote: > When DMA is used for TX and RX by serial driver, it should > pass the DMA device pointer to DMA API instead of UART device > pointer. DMA device should be used for DMA API because only > the DMA device is aware of how the device connects to the memory. > There might be an extra level of address translation due to a > SMMU attached to the DMA device. When serial device pointer device > is used for DMA API, the DMA API will have no clue of the SMMU > attached to the DMA device. > > This patch is necessary to fix the SMMU page faults > which is observed when a DMA(with SMMU enabled) is attached > to UART for transfer. > > Signed-off-by: Tamseel Shams <m.shams@samsung.com> > Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com> > --- > Changes since v1: > 1. Rebased the patch on "tty-next" branch of TTY driver tree > > Changes since v2: > 1. Updated the commit message. > 2. Changed the comment description > > drivers/tty/serial/samsung_tty.c | 62 +++++++++++++++++++++++++------- > 1 file changed, 50 insertions(+), 12 deletions(-) > > diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c > index 9fbc61151c2e..7dd648cb7237 100644 > --- a/drivers/tty/serial/samsung_tty.c > +++ b/drivers/tty/serial/samsung_tty.c > @@ -284,8 +284,13 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) > struct s3c24xx_uart_dma *dma = ourport->dma; > struct circ_buf *xmit = &port->state->xmit; > struct dma_tx_state state; > + struct device *dma_map_ops_dev = ourport->port.dev; > int count; > > + /* Null pointer check for "dma" and "dma->tx_chan" */ The comment is not useful. > + if (dma && dma->tx_chan) > + dma_map_ops_dev = dma->tx_chan->device->dev; > + > if (!ourport->tx_enabled) > return; > > @@ -305,7 +310,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) > dmaengine_pause(dma->tx_chan); > dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); > dmaengine_terminate_all(dma->tx_chan); > - dma_sync_single_for_cpu(ourport->port.dev, > + dma_sync_single_for_cpu(dma_map_ops_dev, > dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE); > async_tx_ack(dma->tx_desc); > count = dma->tx_bytes_requested - state.residue; > @@ -331,14 +336,19 @@ static void s3c24xx_serial_tx_dma_complete(void *args) > struct circ_buf *xmit = &port->state->xmit; > struct s3c24xx_uart_dma *dma = ourport->dma; > struct dma_tx_state state; > + struct device *dma_map_ops_dev = ourport->port.dev; > unsigned long flags; > int count; > > + /* Null pointer check for "dma" and "dma->tx_chan" */ > + if (dma && dma->tx_chan) What is the "else" here? How is it even possible? Why having this "if" at all? > + dma_map_ops_dev = dma->tx_chan->device->dev; > + > dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); > count = dma->tx_bytes_requested - state.residue; > async_tx_ack(dma->tx_desc); > > - dma_sync_single_for_cpu(ourport->port.dev, dma->tx_transfer_addr, > + dma_sync_single_for_cpu(dma_map_ops_dev, dma->tx_transfer_addr, > dma->tx_size, DMA_TO_DEVICE); > > spin_lock_irqsave(&port->lock, flags); > @@ -436,6 +446,11 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, > struct uart_port *port = &ourport->port; > struct circ_buf *xmit = &port->state->xmit; > struct s3c24xx_uart_dma *dma = ourport->dma; > + struct device *dma_map_ops_dev = ourport->port.dev; > + > + /* Null pointer check for "dma" and "dma->tx_chan" */ > + if (dma && dma->tx_chan) > + dma_map_ops_dev = dma->tx_chan->device->dev; > > if (ourport->tx_mode != S3C24XX_TX_DMA) > enable_tx_dma(ourport); > @@ -443,7 +458,7 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, > dma->tx_size = count & ~(dma_get_cache_alignment() - 1); > dma->tx_transfer_addr = dma->tx_addr + xmit->tail; > > - dma_sync_single_for_device(ourport->port.dev, dma->tx_transfer_addr, > + dma_sync_single_for_device(dma_map_ops_dev, dma->tx_transfer_addr, > dma->tx_size, DMA_TO_DEVICE); > > dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan, > @@ -510,12 +525,17 @@ static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport, > struct tty_port *tty, int count) > { > struct s3c24xx_uart_dma *dma = ourport->dma; > + struct device *dma_map_ops_dev = ourport->port.dev; > int copied; > > + /* Null pointer check for "dma" and "dma->rx_chan" */ > + if (dma && dma->rx_chan) > + dma_map_ops_dev = dma->rx_chan->device->dev; > + > if (!count) > return; > > - dma_sync_single_for_cpu(ourport->port.dev, dma->rx_addr, > + dma_sync_single_for_cpu(dma_map_ops_dev, dma->rx_addr, > dma->rx_size, DMA_FROM_DEVICE); > > ourport->port.icount.rx += count; > @@ -635,8 +655,13 @@ static void s3c24xx_serial_rx_dma_complete(void *args) > static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport) > { > struct s3c24xx_uart_dma *dma = ourport->dma; > + struct device *dma_map_ops_dev = ourport->port.dev; > + > + /* Null pointer check for "dma" and "dma->rx_chan" */ > + if (dma && dma->rx_chan) > + dma_map_ops_dev = dma->rx_chan->device->dev; > > - dma_sync_single_for_device(ourport->port.dev, dma->rx_addr, > + dma_sync_single_for_device(dma_map_ops_dev, dma->rx_addr, > dma->rx_size, DMA_FROM_DEVICE); > > dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan, > @@ -1045,6 +1070,7 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) > struct s3c24xx_uart_dma *dma = p->dma; > struct dma_slave_caps dma_caps; > const char *reason = NULL; > + struct device *dma_map_ops_dev = p->port.dev; > int ret; > > /* Default slave configuration parameters */ > @@ -1102,18 +1128,25 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) > goto err_release_tx; > } > > - dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf, > + /* Null pointer check for "dma" and "dma->rx_chan" */ > + if (dma && dma->rx_chan) > + dma_map_ops_dev = dma->rx_chan->device->dev; > + > + dma->rx_addr = dma_map_single(dma_map_ops_dev, dma->rx_buf, > dma->rx_size, DMA_FROM_DEVICE); > - if (dma_mapping_error(p->port.dev, dma->rx_addr)) { > + if (dma_mapping_error(dma_map_ops_dev, dma->rx_addr)) { > reason = "DMA mapping error for RX buffer"; > ret = -EIO; > goto err_free_rx; > } > > + /* Null pointer check for "dma" and "dma->tx_chan" */ > + if (dma && dma->tx_chan) > + dma_map_ops_dev = dma->tx_chan->device->dev; > /* TX buffer */ > - dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf, > + dma->tx_addr = dma_map_single(dma_map_ops_dev, p->port.state->xmit.buf, > UART_XMIT_SIZE, DMA_TO_DEVICE); > - if (dma_mapping_error(p->port.dev, dma->tx_addr)) { > + if (dma_mapping_error(dma_map_ops_dev, dma->tx_addr)) { > reason = "DMA mapping error for TX buffer"; > ret = -EIO; > goto err_unmap_rx; > @@ -1122,7 +1155,9 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) > return 0; > > err_unmap_rx: > - dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size, > + if (dma->rx_chan) > + dma_map_ops_dev = dma->rx_chan->device->dev; > + dma_unmap_single(dma_map_ops_dev, dma->rx_addr, dma->rx_size, > DMA_FROM_DEVICE); > err_free_rx: > kfree(dma->rx_buf); > @@ -1139,10 +1174,12 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) > static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p) > { > struct s3c24xx_uart_dma *dma = p->dma; > + struct device *dma_map_ops_dev = p->port.dev; > > if (dma->rx_chan) { > + dma_map_ops_dev = dma->rx_chan->device->dev; > dmaengine_terminate_all(dma->rx_chan); > - dma_unmap_single(p->port.dev, dma->rx_addr, > + dma_unmap_single(dma_map_ops_dev, dma->rx_addr, > dma->rx_size, DMA_FROM_DEVICE); > kfree(dma->rx_buf); > dma_release_channel(dma->rx_chan); > @@ -1150,8 +1187,9 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p) > } > > if (dma->tx_chan) { > + dma_map_ops_dev = dma->tx_chan->device->dev; > dmaengine_terminate_all(dma->tx_chan); > - dma_unmap_single(p->port.dev, dma->tx_addr, > + dma_unmap_single(dma_map_ops_dev, dma->tx_addr, > UART_XMIT_SIZE, DMA_TO_DEVICE); > dma_release_channel(dma->tx_chan); > dma->tx_chan = NULL; > Best regards, Krzysztof
> > When DMA is used for TX and RX by serial driver, it should pass the > > DMA device pointer to DMA API instead of UART device pointer. DMA > > device should be used for DMA API because only the DMA device is aware > > of how the device connects to the memory. > > There might be an extra level of address translation due to a SMMU > > attached to the DMA device. When serial device pointer device is used > > for DMA API, the DMA API will have no clue of the SMMU attached to the > > DMA device. > > > > This patch is necessary to fix the SMMU page faults which is observed > > when a DMA(with SMMU enabled) is attached to UART for transfer. > > > > Signed-off-by: Tamseel Shams <m.shams@samsung.com> > > Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com> > > --- > > Changes since v1: > > 1. Rebased the patch on "tty-next" branch of TTY driver tree > > > > Changes since v2: > > 1. Updated the commit message. > > 2. Changed the comment description > > > > drivers/tty/serial/samsung_tty.c | 62 > > +++++++++++++++++++++++++------- > > 1 file changed, 50 insertions(+), 12 deletions(-) > > > > diff --git a/drivers/tty/serial/samsung_tty.c > > b/drivers/tty/serial/samsung_tty.c > > index 9fbc61151c2e..7dd648cb7237 100644 > > --- a/drivers/tty/serial/samsung_tty.c > > +++ b/drivers/tty/serial/samsung_tty.c > > @@ -284,8 +284,13 @@ static void s3c24xx_serial_stop_tx(struct uart_port > *port) > > struct s3c24xx_uart_dma *dma = ourport->dma; > > struct circ_buf *xmit = &port->state->xmit; > > struct dma_tx_state state; > > + struct device *dma_map_ops_dev = ourport->port.dev; > > int count; > > > > + /* Null pointer check for "dma" and "dma->tx_chan" */ > > The comment is not useful. > I will remove these comments. > > + if (dma && dma->tx_chan) > > + dma_map_ops_dev = dma->tx_chan->device->dev; > > + > > if (!ourport->tx_enabled) > > return; > > > > @@ -305,7 +310,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port > *port) > > dmaengine_pause(dma->tx_chan); > > dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); > > dmaengine_terminate_all(dma->tx_chan); > > - dma_sync_single_for_cpu(ourport->port.dev, > > + dma_sync_single_for_cpu(dma_map_ops_dev, > > dma->tx_transfer_addr, dma->tx_size, > DMA_TO_DEVICE); > > async_tx_ack(dma->tx_desc); > > count = dma->tx_bytes_requested - state.residue; @@ -331,14 > +336,19 > > @@ static void s3c24xx_serial_tx_dma_complete(void *args) > > struct circ_buf *xmit = &port->state->xmit; > > struct s3c24xx_uart_dma *dma = ourport->dma; > > struct dma_tx_state state; > > + struct device *dma_map_ops_dev = ourport->port.dev; > > unsigned long flags; > > int count; > > > > + /* Null pointer check for "dma" and "dma->tx_chan" */ > > + if (dma && dma->tx_chan) > > > What is the "else" here? How is it even possible? Why having this "if" > at all? > As mentioned in my reply (https://lkml.org/lkml/2021/6/23/6) to Robin's comments for patch version 2, I will be removing these "if" conditions, and directly assign DMA device pointers. > > + dma_map_ops_dev = dma->tx_chan->device->dev; > > + > > dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); > > count = dma->tx_bytes_requested - state.residue; > > async_tx_ack(dma->tx_desc); > > > > - dma_sync_single_for_cpu(ourport->port.dev, dma->tx_transfer_addr, > > + dma_sync_single_for_cpu(dma_map_ops_dev, dma->tx_transfer_addr, > > dma->tx_size, DMA_TO_DEVICE); > > > > spin_lock_irqsave(&port->lock, flags); @@ -436,6 +446,11 @@ static > > int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, > > struct uart_port *port = &ourport->port; > > struct circ_buf *xmit = &port->state->xmit; > > struct s3c24xx_uart_dma *dma = ourport->dma; > > + struct device *dma_map_ops_dev = ourport->port.dev; > > + > > + /* Null pointer check for "dma" and "dma->tx_chan" */ > > + if (dma && dma->tx_chan) > > + dma_map_ops_dev = dma->tx_chan->device->dev; > > > > if (ourport->tx_mode != S3C24XX_TX_DMA) > > enable_tx_dma(ourport); > > @@ -443,7 +458,7 @@ static int s3c24xx_serial_start_tx_dma(struct > s3c24xx_uart_port *ourport, > > dma->tx_size = count & ~(dma_get_cache_alignment() - 1); > > dma->tx_transfer_addr = dma->tx_addr + xmit->tail; > > > > - dma_sync_single_for_device(ourport->port.dev, dma- > >tx_transfer_addr, > > + dma_sync_single_for_device(dma_map_ops_dev, dma- > >tx_transfer_addr, > > dma->tx_size, DMA_TO_DEVICE); > > > > dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan, > > @@ -510,12 +525,17 @@ static void s3c24xx_uart_copy_rx_to_tty(struct > s3c24xx_uart_port *ourport, > > struct tty_port *tty, int count) > > { > > struct s3c24xx_uart_dma *dma = ourport->dma; > > + struct device *dma_map_ops_dev = ourport->port.dev; > > int copied; > > > > + /* Null pointer check for "dma" and "dma->rx_chan" */ > > + if (dma && dma->rx_chan) > > + dma_map_ops_dev = dma->rx_chan->device->dev; > > + > > if (!count) > > return; > > > > - dma_sync_single_for_cpu(ourport->port.dev, dma->rx_addr, > > + dma_sync_single_for_cpu(dma_map_ops_dev, dma->rx_addr, > > dma->rx_size, DMA_FROM_DEVICE); > > > > ourport->port.icount.rx += count; > > @@ -635,8 +655,13 @@ static void s3c24xx_serial_rx_dma_complete(void > > *args) static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port > > *ourport) { > > struct s3c24xx_uart_dma *dma = ourport->dma; > > + struct device *dma_map_ops_dev = ourport->port.dev; > > + > > + /* Null pointer check for "dma" and "dma->rx_chan" */ > > + if (dma && dma->rx_chan) > > + dma_map_ops_dev = dma->rx_chan->device->dev; > > > > - dma_sync_single_for_device(ourport->port.dev, dma->rx_addr, > > + dma_sync_single_for_device(dma_map_ops_dev, dma->rx_addr, > > dma->rx_size, DMA_FROM_DEVICE); > > > > dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan, > > @@ -1045,6 +1070,7 @@ static int s3c24xx_serial_request_dma(struct > s3c24xx_uart_port *p) > > struct s3c24xx_uart_dma *dma = p->dma; > > struct dma_slave_caps dma_caps; > > const char *reason = NULL; > > + struct device *dma_map_ops_dev = p->port.dev; > > int ret; > > > > /* Default slave configuration parameters */ @@ -1102,18 +1128,25 > @@ > > static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) > > goto err_release_tx; > > } > > > > - dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf, > > + /* Null pointer check for "dma" and "dma->rx_chan" */ > > + if (dma && dma->rx_chan) > > + dma_map_ops_dev = dma->rx_chan->device->dev; > > + > > + dma->rx_addr = dma_map_single(dma_map_ops_dev, dma->rx_buf, > > dma->rx_size, DMA_FROM_DEVICE); > > - if (dma_mapping_error(p->port.dev, dma->rx_addr)) { > > + if (dma_mapping_error(dma_map_ops_dev, dma->rx_addr)) { > > reason = "DMA mapping error for RX buffer"; > > ret = -EIO; > > goto err_free_rx; > > } > > > > + /* Null pointer check for "dma" and "dma->tx_chan" */ > > + if (dma && dma->tx_chan) > > + dma_map_ops_dev = dma->tx_chan->device->dev; > > /* TX buffer */ > > - dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf, > > + dma->tx_addr = dma_map_single(dma_map_ops_dev, > > +p->port.state->xmit.buf, > > UART_XMIT_SIZE, DMA_TO_DEVICE); > > - if (dma_mapping_error(p->port.dev, dma->tx_addr)) { > > + if (dma_mapping_error(dma_map_ops_dev, dma->tx_addr)) { > > reason = "DMA mapping error for TX buffer"; > > ret = -EIO; > > goto err_unmap_rx; > > @@ -1122,7 +1155,9 @@ static int s3c24xx_serial_request_dma(struct > s3c24xx_uart_port *p) > > return 0; > > > > err_unmap_rx: > > - dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size, > > + if (dma->rx_chan) > > + dma_map_ops_dev = dma->rx_chan->device->dev; > > + dma_unmap_single(dma_map_ops_dev, dma->rx_addr, dma->rx_size, > > DMA_FROM_DEVICE); > > err_free_rx: > > kfree(dma->rx_buf); > > @@ -1139,10 +1174,12 @@ static int s3c24xx_serial_request_dma(struct > > s3c24xx_uart_port *p) static void s3c24xx_serial_release_dma(struct > > s3c24xx_uart_port *p) { > > struct s3c24xx_uart_dma *dma = p->dma; > > + struct device *dma_map_ops_dev = p->port.dev; > > > > if (dma->rx_chan) { > > + dma_map_ops_dev = dma->rx_chan->device->dev; > > dmaengine_terminate_all(dma->rx_chan); > > - dma_unmap_single(p->port.dev, dma->rx_addr, > > + dma_unmap_single(dma_map_ops_dev, dma->rx_addr, > > dma->rx_size, DMA_FROM_DEVICE); > > kfree(dma->rx_buf); > > dma_release_channel(dma->rx_chan); > > @@ -1150,8 +1187,9 @@ static void s3c24xx_serial_release_dma(struct > s3c24xx_uart_port *p) > > } > > > > if (dma->tx_chan) { > > + dma_map_ops_dev = dma->tx_chan->device->dev; > > dmaengine_terminate_all(dma->tx_chan); > > - dma_unmap_single(p->port.dev, dma->tx_addr, > > + dma_unmap_single(dma_map_ops_dev, dma->tx_addr, > > UART_XMIT_SIZE, DMA_TO_DEVICE); > > dma_release_channel(dma->tx_chan); > > dma->tx_chan = NULL; > > > > > Best regards, > Krzysztof Thanks & Regards, Tamseel Shams
Hi Tamseel, url: https://github.com/0day-ci/linux/commits/Tamseel-Shams/serial-samsung-use-dma_ops-of-DMA-if-attached/20210622-195936 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing config: parisc-randconfig-m031-20210625 (attached as .config) compiler: hppa-linux-gcc (GCC) 9.3.0 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> New smatch warnings: drivers/tty/serial/samsung_tty.c:347 s3c24xx_serial_tx_dma_complete() error: we previously assumed 'dma' could be null (see line 344) drivers/tty/serial/samsung_tty.c:347 s3c24xx_serial_tx_dma_complete() error: we previously assumed 'dma->tx_chan' could be null (see line 344) drivers/tty/serial/samsung_tty.c:458 s3c24xx_serial_start_tx_dma() error: we previously assumed 'dma' could be null (see line 452) drivers/tty/serial/samsung_tty.c:538 s3c24xx_uart_copy_rx_to_tty() error: we previously assumed 'dma' could be null (see line 532) drivers/tty/serial/samsung_tty.c:664 s3c64xx_start_rx_dma() error: we previously assumed 'dma' could be null (see line 661) drivers/tty/serial/samsung_tty.c:1132 s3c24xx_serial_request_dma() warn: variable dereferenced before check 'dma' (see line 1077) Old smatch warnings: drivers/tty/serial/samsung_tty.c:2129 s3c24xx_serial_init_port() warn: missing error code 'ret' vim +/dma +347 drivers/tty/serial/samsung_tty.c 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 332 static void s3c24xx_serial_tx_dma_complete(void *args) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 333 { 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 334 struct s3c24xx_uart_port *ourport = args; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 335 struct uart_port *port = &ourport->port; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 336 struct circ_buf *xmit = &port->state->xmit; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 337 struct s3c24xx_uart_dma *dma = ourport->dma; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 338 struct dma_tx_state state; 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 339 struct device *dma_map_ops_dev = ourport->port.dev; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 340 unsigned long flags; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 341 int count; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 342 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 343 /* Null pointer check for "dma" and "dma->tx_chan" */ 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 @344 if (dma && dma->tx_chan) ^^^ Check for NULL 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 345 dma_map_ops_dev = dma->tx_chan->device->dev; 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 346 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 @347 dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); ^^^^^^^^^^^^ Unchecked dereference 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 348 count = dma->tx_bytes_requested - state.residue; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 349 async_tx_ack(dma->tx_desc); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 350 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 351 dma_sync_single_for_cpu(dma_map_ops_dev, dma->tx_transfer_addr, 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 352 dma->tx_size, DMA_TO_DEVICE); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 353 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 354 spin_lock_irqsave(&port->lock, flags); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 355 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 356 xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 357 port->icount.tx += count; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 358 ourport->tx_in_progress = 0; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 359 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 360 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 361 uart_write_wakeup(port); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 362 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 363 s3c24xx_serial_start_next_tx(ourport); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 364 spin_unlock_irqrestore(&port->lock, flags); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 365 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 366 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 367 static void enable_tx_dma(struct s3c24xx_uart_port *ourport) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 368 { 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 369 struct uart_port *port = &ourport->port; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 370 u32 ucon; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 371 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 372 /* Mask Tx interrupt */ aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 373 switch (ourport->info->type) { aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 374 case TYPE_S3C6400: bbb5ff91225dfb drivers/tty/serial/samsung.c Matthew Leach 2016-06-22 375 s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM); aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 376 break; fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 377 case TYPE_APPLE_S5L: fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 378 WARN_ON(1); // No DMA fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 379 break; aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 380 default: 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 381 disable_irq_nosync(ourport->tx_irq); aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 382 break; aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 383 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 384 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 385 /* Enable tx dma mode */ 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 386 ucon = rd_regl(port, S3C2410_UCON); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 387 ucon &= ~(S3C64XX_UCON_TXBURST_MASK | S3C64XX_UCON_TXMODE_MASK); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 388 ucon |= (dma_get_cache_alignment() >= 16) ? 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 389 S3C64XX_UCON_TXBURST_16 : S3C64XX_UCON_TXBURST_1; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 390 ucon |= S3C64XX_UCON_TXMODE_DMA; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 391 wr_regl(port, S3C2410_UCON, ucon); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 392 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 393 ourport->tx_mode = S3C24XX_TX_DMA; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 394 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 395 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 396 static void enable_tx_pio(struct s3c24xx_uart_port *ourport) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 397 { 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 398 struct uart_port *port = &ourport->port; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 399 u32 ucon, ufcon; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 400 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 401 /* Set ufcon txtrig */ 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 402 ourport->tx_in_progress = S3C24XX_TX_PIO; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 403 ufcon = rd_regl(port, S3C2410_UFCON); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 404 wr_regl(port, S3C2410_UFCON, ufcon); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 405 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 406 /* Enable tx pio mode */ 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 407 ucon = rd_regl(port, S3C2410_UCON); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 408 ucon &= ~(S3C64XX_UCON_TXMODE_MASK); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 409 ucon |= S3C64XX_UCON_TXMODE_CPU; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 410 wr_regl(port, S3C2410_UCON, ucon); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 411 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 412 /* Unmask Tx interrupt */ aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 413 switch (ourport->info->type) { aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 414 case TYPE_S3C6400: bbb5ff91225dfb drivers/tty/serial/samsung.c Matthew Leach 2016-06-22 415 s3c24xx_clear_bit(port, S3C64XX_UINTM_TXD, bbb5ff91225dfb drivers/tty/serial/samsung.c Matthew Leach 2016-06-22 416 S3C64XX_UINTM); aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 417 break; fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 418 case TYPE_APPLE_S5L: fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 419 ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK; fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 420 wr_regl(port, S3C2410_UCON, ucon); fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 421 break; aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 422 default: 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 423 enable_irq(ourport->tx_irq); aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 424 break; aaf144059ba474 drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 425 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 426 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 427 ourport->tx_mode = S3C24XX_TX_PIO; fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 428 fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 429 /* fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 430 * The Apple version only has edge triggered TX IRQs, so we need fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 431 * to kick off the process by sending some characters here. fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 432 */ fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 433 if (ourport->info->type == TYPE_APPLE_S5L) fcbba344907afe drivers/tty/serial/samsung_tty.c Hector Martin 2021-03-05 434 s3c24xx_serial_tx_chars(ourport); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 435 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 436 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 437 static void s3c24xx_serial_start_tx_pio(struct s3c24xx_uart_port *ourport) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 438 { 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 439 if (ourport->tx_mode != S3C24XX_TX_PIO) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 440 enable_tx_pio(ourport); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 441 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 442 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 443 static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 444 unsigned int count) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 445 { 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 446 struct uart_port *port = &ourport->port; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 447 struct circ_buf *xmit = &port->state->xmit; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 448 struct s3c24xx_uart_dma *dma = ourport->dma; 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 449 struct device *dma_map_ops_dev = ourport->port.dev; 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 450 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 451 /* Null pointer check for "dma" and "dma->tx_chan" */ 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 @452 if (dma && dma->tx_chan) 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 453 dma_map_ops_dev = dma->tx_chan->device->dev; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 454 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 455 if (ourport->tx_mode != S3C24XX_TX_DMA) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 456 enable_tx_dma(ourport); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 457 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 @458 dma->tx_size = count & ~(dma_get_cache_alignment() - 1); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 459 dma->tx_transfer_addr = dma->tx_addr + xmit->tail; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 460 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 461 dma_sync_single_for_device(dma_map_ops_dev, dma->tx_transfer_addr, 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 462 dma->tx_size, DMA_TO_DEVICE); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 463 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 464 dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan, 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 465 dma->tx_transfer_addr, dma->tx_size, 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 466 DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 467 if (!dma->tx_desc) { 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 468 dev_err(ourport->port.dev, "Unable to get desc for Tx\n"); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 469 return -EIO; b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 470 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 471 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 472 dma->tx_desc->callback = s3c24xx_serial_tx_dma_complete; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 473 dma->tx_desc->callback_param = ourport; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 474 dma->tx_bytes_requested = dma->tx_size; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 475 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 476 ourport->tx_in_progress = S3C24XX_TX_DMA; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 477 dma->tx_cookie = dmaengine_submit(dma->tx_desc); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 478 dma_async_issue_pending(dma->tx_chan); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 479 return 0; b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 480 } b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 481 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 482 static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 483 { 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 484 struct uart_port *port = &ourport->port; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 485 struct circ_buf *xmit = &port->state->xmit; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 486 unsigned long count; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 487 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 488 /* Get data size up to the end of buffer */ 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 489 count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 490 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 491 if (!count) { 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 492 s3c24xx_serial_stop_tx(port); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 493 return; 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 494 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 495 81ccb2a69f76b8 drivers/tty/serial/samsung.c Marek Szyprowski 2015-07-31 496 if (!ourport->dma || !ourport->dma->tx_chan || 736cd79f483fd7 drivers/tty/serial/samsung.c Robert Baldyga 2015-07-31 497 count < ourport->min_dma_size || 736cd79f483fd7 drivers/tty/serial/samsung.c Robert Baldyga 2015-07-31 498 xmit->tail & (dma_get_cache_alignment() - 1)) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 499 s3c24xx_serial_start_tx_pio(ourport); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 500 else 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 501 s3c24xx_serial_start_tx_dma(ourport, count); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 502 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 503 75781979f8d33e drivers/tty/serial/samsung.c Krzysztof Kozlowski 2015-05-02 504 static void s3c24xx_serial_start_tx(struct uart_port *port) b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 505 { b73c289cc90138 drivers/serial/samsung.c Ben Dooks 2008-10-21 506 struct s3c24xx_uart_port *ourport = to_ourport(port); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 507 struct circ_buf *xmit = &port->state->xmit; b73c289cc90138 drivers/serial/samsung.c Ben Dooks 2008-10-21 508 8336240ebb248b drivers/tty/serial/samsung_tty.c Greg Kroah-Hartman 2019-12-17 509 if (!ourport->tx_enabled) { b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 510 if (port->flags & UPF_CONS_FLOW) b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 511 s3c24xx_serial_rx_disable(port); b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 512 8336240ebb248b drivers/tty/serial/samsung_tty.c Greg Kroah-Hartman 2019-12-17 513 ourport->tx_enabled = 1; ba019a3e2ad53d drivers/tty/serial/samsung.c Robert Baldyga 2015-01-28 514 if (!ourport->dma || !ourport->dma->tx_chan) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 515 s3c24xx_serial_start_tx_pio(ourport); 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 516 } 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 517 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 518 if (ourport->dma && ourport->dma->tx_chan) { 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 519 if (!uart_circ_empty(xmit) && !ourport->tx_in_progress) 29bef79908459d drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 520 s3c24xx_serial_start_next_tx(ourport); b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 521 } b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 522 } b497549a035c2a drivers/serial/samsung.c Ben Dooks 2008-07-03 523 b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 524 static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport, b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 525 struct tty_port *tty, int count) b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 526 { b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 527 struct s3c24xx_uart_dma *dma = ourport->dma; 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 528 struct device *dma_map_ops_dev = ourport->port.dev; b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 529 int copied; b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 530 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 531 /* Null pointer check for "dma" and "dma->rx_chan" */ 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 @532 if (dma && dma->rx_chan) 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 533 dma_map_ops_dev = dma->rx_chan->device->dev; 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 534 b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 535 if (!count) b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 536 return; b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 537 36f392dcc64c96 drivers/tty/serial/samsung_tty.c Tamseel Shams 2021-06-22 @538 dma_sync_single_for_cpu(dma_map_ops_dev, dma->rx_addr, b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 539 dma->rx_size, DMA_FROM_DEVICE); b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 540 b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 541 ourport->port.icount.rx += count; b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 542 if (!tty) { b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 543 dev_err(ourport->port.dev, "No tty port\n"); b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 544 return; b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 545 } b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 546 copied = tty_insert_flip_string(tty, b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 547 ((unsigned char *)(ourport->dma->rx_buf)), count); b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 548 if (copied != count) { b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 549 WARN_ON(1); b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 550 dev_err(ourport->port.dev, "RxData copy to tty layer failed\n"); b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 551 } b543c301c2c5fb drivers/tty/serial/samsung.c Robert Baldyga 2014-12-10 552 } --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index 9fbc61151c2e..7dd648cb7237 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -284,8 +284,13 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) struct s3c24xx_uart_dma *dma = ourport->dma; struct circ_buf *xmit = &port->state->xmit; struct dma_tx_state state; + struct device *dma_map_ops_dev = ourport->port.dev; int count; + /* Null pointer check for "dma" and "dma->tx_chan" */ + if (dma && dma->tx_chan) + dma_map_ops_dev = dma->tx_chan->device->dev; + if (!ourport->tx_enabled) return; @@ -305,7 +310,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) dmaengine_pause(dma->tx_chan); dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); dmaengine_terminate_all(dma->tx_chan); - dma_sync_single_for_cpu(ourport->port.dev, + dma_sync_single_for_cpu(dma_map_ops_dev, dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE); async_tx_ack(dma->tx_desc); count = dma->tx_bytes_requested - state.residue; @@ -331,14 +336,19 @@ static void s3c24xx_serial_tx_dma_complete(void *args) struct circ_buf *xmit = &port->state->xmit; struct s3c24xx_uart_dma *dma = ourport->dma; struct dma_tx_state state; + struct device *dma_map_ops_dev = ourport->port.dev; unsigned long flags; int count; + /* Null pointer check for "dma" and "dma->tx_chan" */ + if (dma && dma->tx_chan) + dma_map_ops_dev = dma->tx_chan->device->dev; + dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); count = dma->tx_bytes_requested - state.residue; async_tx_ack(dma->tx_desc); - dma_sync_single_for_cpu(ourport->port.dev, dma->tx_transfer_addr, + dma_sync_single_for_cpu(dma_map_ops_dev, dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE); spin_lock_irqsave(&port->lock, flags); @@ -436,6 +446,11 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, struct uart_port *port = &ourport->port; struct circ_buf *xmit = &port->state->xmit; struct s3c24xx_uart_dma *dma = ourport->dma; + struct device *dma_map_ops_dev = ourport->port.dev; + + /* Null pointer check for "dma" and "dma->tx_chan" */ + if (dma && dma->tx_chan) + dma_map_ops_dev = dma->tx_chan->device->dev; if (ourport->tx_mode != S3C24XX_TX_DMA) enable_tx_dma(ourport); @@ -443,7 +458,7 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, dma->tx_size = count & ~(dma_get_cache_alignment() - 1); dma->tx_transfer_addr = dma->tx_addr + xmit->tail; - dma_sync_single_for_device(ourport->port.dev, dma->tx_transfer_addr, + dma_sync_single_for_device(dma_map_ops_dev, dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE); dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan, @@ -510,12 +525,17 @@ static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport, struct tty_port *tty, int count) { struct s3c24xx_uart_dma *dma = ourport->dma; + struct device *dma_map_ops_dev = ourport->port.dev; int copied; + /* Null pointer check for "dma" and "dma->rx_chan" */ + if (dma && dma->rx_chan) + dma_map_ops_dev = dma->rx_chan->device->dev; + if (!count) return; - dma_sync_single_for_cpu(ourport->port.dev, dma->rx_addr, + dma_sync_single_for_cpu(dma_map_ops_dev, dma->rx_addr, dma->rx_size, DMA_FROM_DEVICE); ourport->port.icount.rx += count; @@ -635,8 +655,13 @@ static void s3c24xx_serial_rx_dma_complete(void *args) static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport) { struct s3c24xx_uart_dma *dma = ourport->dma; + struct device *dma_map_ops_dev = ourport->port.dev; + + /* Null pointer check for "dma" and "dma->rx_chan" */ + if (dma && dma->rx_chan) + dma_map_ops_dev = dma->rx_chan->device->dev; - dma_sync_single_for_device(ourport->port.dev, dma->rx_addr, + dma_sync_single_for_device(dma_map_ops_dev, dma->rx_addr, dma->rx_size, DMA_FROM_DEVICE); dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan, @@ -1045,6 +1070,7 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) struct s3c24xx_uart_dma *dma = p->dma; struct dma_slave_caps dma_caps; const char *reason = NULL; + struct device *dma_map_ops_dev = p->port.dev; int ret; /* Default slave configuration parameters */ @@ -1102,18 +1128,25 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) goto err_release_tx; } - dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf, + /* Null pointer check for "dma" and "dma->rx_chan" */ + if (dma && dma->rx_chan) + dma_map_ops_dev = dma->rx_chan->device->dev; + + dma->rx_addr = dma_map_single(dma_map_ops_dev, dma->rx_buf, dma->rx_size, DMA_FROM_DEVICE); - if (dma_mapping_error(p->port.dev, dma->rx_addr)) { + if (dma_mapping_error(dma_map_ops_dev, dma->rx_addr)) { reason = "DMA mapping error for RX buffer"; ret = -EIO; goto err_free_rx; } + /* Null pointer check for "dma" and "dma->tx_chan" */ + if (dma && dma->tx_chan) + dma_map_ops_dev = dma->tx_chan->device->dev; /* TX buffer */ - dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf, + dma->tx_addr = dma_map_single(dma_map_ops_dev, p->port.state->xmit.buf, UART_XMIT_SIZE, DMA_TO_DEVICE); - if (dma_mapping_error(p->port.dev, dma->tx_addr)) { + if (dma_mapping_error(dma_map_ops_dev, dma->tx_addr)) { reason = "DMA mapping error for TX buffer"; ret = -EIO; goto err_unmap_rx; @@ -1122,7 +1155,9 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) return 0; err_unmap_rx: - dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size, + if (dma->rx_chan) + dma_map_ops_dev = dma->rx_chan->device->dev; + dma_unmap_single(dma_map_ops_dev, dma->rx_addr, dma->rx_size, DMA_FROM_DEVICE); err_free_rx: kfree(dma->rx_buf); @@ -1139,10 +1174,12 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p) { struct s3c24xx_uart_dma *dma = p->dma; + struct device *dma_map_ops_dev = p->port.dev; if (dma->rx_chan) { + dma_map_ops_dev = dma->rx_chan->device->dev; dmaengine_terminate_all(dma->rx_chan); - dma_unmap_single(p->port.dev, dma->rx_addr, + dma_unmap_single(dma_map_ops_dev, dma->rx_addr, dma->rx_size, DMA_FROM_DEVICE); kfree(dma->rx_buf); dma_release_channel(dma->rx_chan); @@ -1150,8 +1187,9 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p) } if (dma->tx_chan) { + dma_map_ops_dev = dma->tx_chan->device->dev; dmaengine_terminate_all(dma->tx_chan); - dma_unmap_single(p->port.dev, dma->tx_addr, + dma_unmap_single(dma_map_ops_dev, dma->tx_addr, UART_XMIT_SIZE, DMA_TO_DEVICE); dma_release_channel(dma->tx_chan); dma->tx_chan = NULL;