2021-06-22 12:01:25

by Tamseel Shams

[permalink] [raw]
Subject: [PATCH v3] serial: samsung: use dma_ops of DMA if attached

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 <[email protected]>
Signed-off-by: Ajay Kumar <[email protected]>
---
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" */
+ 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;
--
2.17.1


2021-06-23 06:13:48

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v3] serial: samsung: use dma_ops of DMA if attached

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 <[email protected]>
> Signed-off-by: Ajay Kumar <[email protected]>
> ---
> 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

2021-06-23 07:59:20

by Tamseel Shams

[permalink] [raw]
Subject: RE: [PATCH v3] serial: samsung: use dma_ops of DMA if attached

> > 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 <[email protected]>
> > Signed-off-by: Ajay Kumar <[email protected]>
> > ---
> > 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

2021-06-28 08:43:33

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH v3] serial: samsung: use dma_ops of DMA if attached

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 <[email protected]>
Reported-by: Dan Carpenter <[email protected]>

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/[email protected]