diff mbox series

[v3] serial: samsung: use dma_ops of DMA if attached

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

Commit Message

Tamseel Shams June 22, 2021, 9:17 a.m. UTC
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(-)

Comments

Krzysztof Kozlowski June 23, 2021, 6:10 a.m. UTC | #1
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
Tamseel Shams June 23, 2021, 6:29 a.m. UTC | #2
> > 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
Dan Carpenter June 28, 2021, 8:40 a.m. UTC | #3
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 mbox series

Patch

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;