[PATCH 1/2] serial: use dmaengine_get_dma_device() instead of chan->device->dev
From: Frank . Li
Date: Fri Sep 25 2026 - 16:09:25 EST
From: Frank Li <Frank.Li@xxxxxxx>
Replace direct dma_chan::device::dev access with the proper
dmaengine_get_dma_device() for consumer API
chan->device->dev is not always the device used for DMA mapping.
Some DMA engines support per-channel IOMMU mappings, so different
channels may use different DMA devices. dmaengine_get_dma_device()
returns the correct device for each channel.
This also prepares for making the DMA engine provider data structures
private. DMA consumers should not access DMA engine internals directly.
Assisted-by: LLM
Signed-off-by: Frank Li <Frank.Li@xxxxxxx>
---
Check all unders driver/tty/ by rename device to _device in dma_chan struct
with all yes config.
Still few left, one for copy_align access, which need new API. some filter
DMA channel, need new API to get provider devices.
In https://lore.kernel.org/imx/67966b47-22cb-4b07-80c7-2044f557dbcb@xxxxxxxxxxxxxxxx/
There are better idea to move map singe/sg into dma prep functions.
But it takes more times, not straightforward works. Let replace this firstly,
---
drivers/tty/serial/8250/8250_dma.c | 21 +++++++++++++--------
drivers/tty/serial/8250/8250_omap.c | 4 ++--
drivers/tty/serial/amba-pl011.c | 10 +++++-----
drivers/tty/serial/pch_uart.c | 2 +-
drivers/tty/serial/samsung_tty.c | 27 +++++++++++++++------------
drivers/tty/serial/sh-sci.c | 14 ++++++++------
6 files changed, 44 insertions(+), 34 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 5a83e5269b415..dc7fb3db1584d 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -19,7 +19,7 @@ static void __dma_tx_complete(void *param)
unsigned long flags;
int ret;
- dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
+ dma_sync_single_for_cpu(dmaengine_get_dma_device(dma->txchan), dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
uart_port_lock_irqsave(&p->port, &flags);
@@ -136,7 +136,7 @@ int serial8250_tx_dma(struct uart_8250_port *p)
dma->tx_cookie = dmaengine_submit(desc);
- dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr,
+ dma_sync_single_for_device(dmaengine_get_dma_device(dma->txchan), dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_async_issue_pending(dma->txchan);
@@ -223,6 +223,8 @@ EXPORT_SYMBOL_GPL(serial8250_rx_dma_flush);
int serial8250_request_dma(struct uart_8250_port *p)
{
struct uart_8250_dma *dma = p->dma;
+ struct device *rx_dev;
+ struct device *tx_dev;
phys_addr_t rx_dma_addr = dma->rx_dma_addr ?
dma->rx_dma_addr : p->port.mapbase;
phys_addr_t tx_dma_addr = dma->tx_dma_addr ?
@@ -282,11 +284,14 @@ int serial8250_request_dma(struct uart_8250_port *p)
dmaengine_slave_config(dma->txchan, &dma->txconf);
+ rx_dev = dmaengine_get_dma_device(dma->rxchan);
+ tx_dev = dmaengine_get_dma_device(dma->txchan);
+
/* RX buffer */
if (!dma->rx_size)
dma->rx_size = PAGE_SIZE;
- dma->rx_buf = dma_alloc_coherent(dma->rxchan->device->dev, dma->rx_size,
+ dma->rx_buf = dma_alloc_coherent(rx_dev, dma->rx_size,
&dma->rx_addr, GFP_KERNEL);
if (!dma->rx_buf) {
ret = -ENOMEM;
@@ -294,12 +299,12 @@ int serial8250_request_dma(struct uart_8250_port *p)
}
/* TX buffer */
- dma->tx_addr = dma_map_single(dma->txchan->device->dev,
+ dma->tx_addr = dma_map_single(tx_dev,
p->port.state->port.xmit_buf,
UART_XMIT_SIZE,
DMA_TO_DEVICE);
- if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) {
- dma_free_coherent(dma->rxchan->device->dev, dma->rx_size,
+ if (dma_mapping_error(tx_dev, dma->tx_addr)) {
+ dma_free_coherent(rx_dev, dma->rx_size,
dma->rx_buf, dma->rx_addr);
ret = -ENOMEM;
goto err;
@@ -326,14 +331,14 @@ void serial8250_release_dma(struct uart_8250_port *p)
/* Release RX resources */
dmaengine_terminate_sync(dma->rxchan);
dma->rx_running = 0;
- dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, dma->rx_buf,
+ dma_free_coherent(dmaengine_get_dma_device(dma->rxchan), dma->rx_size, dma->rx_buf,
dma->rx_addr);
dma_release_channel(dma->rxchan);
dma->rxchan = NULL;
/* Release TX resources */
dmaengine_terminate_sync(dma->txchan);
- dma_unmap_single(dma->txchan->device->dev, dma->tx_addr,
+ dma_unmap_single(dmaengine_get_dma_device(dma->txchan), dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_release_channel(dma->txchan);
dma->txchan = NULL;
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index ceecb39fb82da..3a1473bf54d0f 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -1076,7 +1076,7 @@ static void omap_8250_dma_tx_complete(void *param)
bool en_thri = false;
struct omap8250_priv *priv = p->port.private_data;
- dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
+ dma_sync_single_for_cpu(dmaengine_get_dma_device(dma->txchan), dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
guard(uart_port_lock_irqsave)(&p->port);
@@ -1193,7 +1193,7 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
dma->tx_cookie = dmaengine_submit(desc);
- dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr,
+ dma_sync_single_for_device(dmaengine_get_dma_device(dma->txchan), dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_async_issue_pending(dma->txchan);
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index c4824c201e1c3..86729ddbdadc8 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -435,7 +435,7 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
static int pl011_dmabuf_init(struct dma_chan *chan, struct pl011_dmabuf *db,
enum dma_data_direction dir)
{
- db->buf = dma_alloc_coherent(chan->device->dev, PL011_DMA_BUFFER_SIZE,
+ db->buf = dma_alloc_coherent(dmaengine_get_dma_device(chan), PL011_DMA_BUFFER_SIZE,
&db->dma, GFP_KERNEL);
if (!db->buf)
return -ENOMEM;
@@ -448,7 +448,7 @@ static void pl011_dmabuf_free(struct dma_chan *chan, struct pl011_dmabuf *db,
enum dma_data_direction dir)
{
if (db->buf) {
- dma_free_coherent(chan->device->dev,
+ dma_free_coherent(dmaengine_get_dma_device(chan),
PL011_DMA_BUFFER_SIZE, db->buf, db->dma);
}
}
@@ -609,7 +609,7 @@ static void pl011_dma_tx_callback(void *data)
uart_port_lock_irqsave(&uap->port, &flags);
if (uap->dmatx.queued)
- dma_unmap_single(dmatx->chan->device->dev, dmatx->dma,
+ dma_unmap_single(dmaengine_get_dma_device(dmatx->chan), dmatx->dma,
dmatx->len, DMA_TO_DEVICE);
dmacr = uap->dmacr;
@@ -867,7 +867,7 @@ __acquires(&uap->port.lock)
dmaengine_terminate_async(uap->dmatx.chan);
if (uap->dmatx.queued) {
- dma_unmap_single(uap->dmatx.chan->device->dev, uap->dmatx.dma,
+ dma_unmap_single(dmaengine_get_dma_device(uap->dmatx.chan), uap->dmatx.dma,
uap->dmatx.len, DMA_TO_DEVICE);
uap->dmatx.queued = false;
uap->dmacr &= ~UART011_TXDMAE;
@@ -1249,7 +1249,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
/* In theory, this should already be done by pl011_dma_flush_buffer */
dmaengine_terminate_sync(uap->dmatx.chan);
if (uap->dmatx.queued) {
- dma_unmap_single(uap->dmatx.chan->device->dev,
+ dma_unmap_single(dmaengine_get_dma_device(uap->dmatx.chan),
uap->dmatx.dma, uap->dmatx.len,
DMA_TO_DEVICE);
uap->dmatx.queued = false;
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index db5c62b0322f6..5e8540e835351 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -656,7 +656,7 @@ static bool filter(struct dma_chan *chan, void *slave)
struct pch_dma_slave *param = slave;
if ((chan->chan_id == param->chan_id) && (param->dma_dev ==
- chan->device->dev)) {
+ dmaengine_get_dma_device(chan))) {
chan->private = param;
return true;
} else {
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index 63d0232dffc20..640f85e2d636b 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -300,7 +300,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(dma->tx_chan->device->dev,
+ dma_sync_single_for_cpu(dmaengine_get_dma_device(dma->tx_chan),
dma->tx_transfer_addr, dma->tx_size,
DMA_TO_DEVICE);
async_tx_ack(dma->tx_desc);
@@ -333,7 +333,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args)
count = dma->tx_bytes_requested - state.residue;
async_tx_ack(dma->tx_desc);
- dma_sync_single_for_cpu(dma->tx_chan->device->dev,
+ dma_sync_single_for_cpu(dmaengine_get_dma_device(dma->tx_chan),
dma->tx_transfer_addr, dma->tx_size,
DMA_TO_DEVICE);
@@ -435,7 +435,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 + tail;
- dma_sync_single_for_device(dma->tx_chan->device->dev,
+ dma_sync_single_for_device(dmaengine_get_dma_device(dma->tx_chan),
dma->tx_transfer_addr, dma->tx_size,
DMA_TO_DEVICE);
@@ -509,7 +509,7 @@ static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport,
if (!count)
return;
- dma_sync_single_for_cpu(dma->rx_chan->device->dev, dma->rx_addr,
+ dma_sync_single_for_cpu(dmaengine_get_dma_device(dma->rx_chan), dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
ourport->port.icount.rx += count;
@@ -631,7 +631,7 @@ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
{
struct s3c24xx_uart_dma *dma = ourport->dma;
- dma_sync_single_for_device(dma->rx_chan->device->dev, dma->rx_addr,
+ dma_sync_single_for_device(dmaengine_get_dma_device(dma->rx_chan), dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan,
@@ -1101,20 +1101,23 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
goto err_release_tx;
}
- dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf,
+ struct device *rx_dev = dmaengine_get_dma_device(dma->rx_chan);
+ struct device *tx_dev = dmaengine_get_dma_device(dma->tx_chan);
+
+ dma->rx_addr = dma_map_single(rx_dev, dma->rx_buf,
dma->rx_size, DMA_FROM_DEVICE);
- if (dma_mapping_error(dma->rx_chan->device->dev, dma->rx_addr)) {
+ if (dma_mapping_error(rx_dev, dma->rx_addr)) {
reason = "DMA mapping error for RX buffer";
ret = -EIO;
goto err_free_rx;
}
/* TX buffer */
- dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
+ dma->tx_addr = dma_map_single(tx_dev,
p->port.state->port.xmit_buf,
UART_XMIT_SIZE,
DMA_TO_DEVICE);
- if (dma_mapping_error(dma->tx_chan->device->dev, dma->tx_addr)) {
+ if (dma_mapping_error(tx_dev, dma->tx_addr)) {
reason = "DMA mapping error for TX buffer";
ret = -EIO;
goto err_unmap_rx;
@@ -1123,7 +1126,7 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
return 0;
err_unmap_rx:
- dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
+ dma_unmap_single(dmaengine_get_dma_device(dma->rx_chan), dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
err_free_rx:
kfree(dma->rx_buf);
@@ -1143,7 +1146,7 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
if (dma->rx_chan) {
dmaengine_terminate_all(dma->rx_chan);
- dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
+ dma_unmap_single(dmaengine_get_dma_device(dma->rx_chan), dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
kfree(dma->rx_buf);
dma_release_channel(dma->rx_chan);
@@ -1152,7 +1155,7 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
if (dma->tx_chan) {
dmaengine_terminate_all(dma->tx_chan);
- dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr,
+ dma_unmap_single(dmaengine_get_dma_device(dma->tx_chan), dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_release_channel(dma->tx_chan);
dma->tx_chan = NULL;
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 50ae9aae6b614..bd58bbfa65aa7 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1495,7 +1495,7 @@ static void sci_dma_rx_release(struct sci_port *s)
uart_port_unlock_irqrestore(port, flags);
dmaengine_terminate_sync(chan);
- dma_free_coherent(chan->device->dev, s->buf_len_rx * 2, s->rx_buf[0],
+ dma_free_coherent(dmaengine_get_dma_device(chan), s->buf_len_rx * 2, s->rx_buf[0],
sg_dma_address(&s->sg_rx[0]));
dma_release_channel(chan);
}
@@ -1591,7 +1591,7 @@ static void sci_dma_tx_release(struct sci_port *s)
s->chan_tx_saved = s->chan_tx = NULL;
s->cookie_tx = -EINVAL;
dmaengine_terminate_sync(chan);
- dma_unmap_single(chan->device->dev, s->tx_dma_addr, UART_XMIT_SIZE,
+ dma_unmap_single(dmaengine_get_dma_device(chan), s->tx_dma_addr, UART_XMIT_SIZE,
DMA_TO_DEVICE);
dma_release_channel(chan);
}
@@ -1676,7 +1676,7 @@ static void sci_dma_tx_work_fn(struct work_struct *work)
goto switch_to_pio;
}
- dma_sync_single_for_device(chan->device->dev, buf, s->tx_dma_len,
+ dma_sync_single_for_device(dmaengine_get_dma_device(chan), buf, s->tx_dma_len,
DMA_TO_DEVICE);
desc->callback = sci_dma_tx_complete;
@@ -1832,12 +1832,13 @@ static void sci_request_dma(struct uart_port *port)
chan = sci_request_dma_chan(port, DMA_MEM_TO_DEV);
dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
if (chan) {
+ struct device *dma_dev = dmaengine_get_dma_device(chan);
/* UART circular tx buffer is an aligned page. */
- s->tx_dma_addr = dma_map_single(chan->device->dev,
+ s->tx_dma_addr = dma_map_single(dma_dev,
tport->xmit_buf,
UART_XMIT_SIZE,
DMA_TO_DEVICE);
- if (dma_mapping_error(chan->device->dev, s->tx_dma_addr)) {
+ if (dma_mapping_error(dma_dev, s->tx_dma_addr)) {
dev_warn(port->dev, "Failed mapping Tx DMA descriptor\n");
dma_release_channel(chan);
} else {
@@ -1853,12 +1854,13 @@ static void sci_request_dma(struct uart_port *port)
chan = sci_request_dma_chan(port, DMA_DEV_TO_MEM);
dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
if (chan) {
+ struct device *dma_dev = dmaengine_get_dma_device(chan);
unsigned int i;
dma_addr_t dma;
void *buf;
s->buf_len_rx = 2 * max_t(size_t, 16, port->fifosize);
- buf = dma_alloc_coherent(chan->device->dev, s->buf_len_rx * 2,
+ buf = dma_alloc_coherent(dma_dev, s->buf_len_rx * 2,
&dma, GFP_KERNEL);
if (!buf) {
dev_warn(port->dev,
--
2.43.0