* [PATCH v2 1/2] serial: use dmaengine_get_dma_device() instead of chan->device->dev
@ 2026-09-28 18:32 Frank.Li
2026-09-28 18:32 ` [PATCH v2 2/2] serial: amba-pl011: use dmaengine public API instead of raw ops Frank.Li
0 siblings, 1 reply; 2+ messages in thread
From: Frank.Li @ 2026-09-28 18:32 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Russell King,
Krzysztof Kozlowski, Peter Griffin, Alim Akhtar, Raul E Rangel,
Frank Li, Cunhao Lu, Moteen Shah, Kendall Willis,
Andy Shevchenko, Matthias Feser, Kartik Rajput, Fan Wu,
Karl Mehltretter, Peter Maydell, Stefan Dösinger, Biju Das,
Geert Uytterhoeven, Lad Prabhakar, Cosmin Tanislav,
open list:TTY LAYER AND SERIAL DRIVERS,
open list:TTY LAYER AND SERIAL DRIVERS,
moderated list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES,
open list:ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES
Cc: vkoul, imx
From: Frank Li <Frank.Li@nxp.com>
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@nxp.com>
---
Change in v2
- remove drivers/tty/serial/pch_uart.c param_dma->dev == chan->dev->dev
change, which need specific get dmaengine devices, not channel device to
filter channel. A new API needed, will update later.
- fix args warp according andy's feeback.
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@app.fastmail.com/
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 | 29 ++++++++++++++++-------------
drivers/tty/serial/8250/8250_omap.c | 4 ++--
drivers/tty/serial/amba-pl011.c | 12 ++++++------
drivers/tty/serial/samsung_tty.c | 27 +++++++++++++++------------
drivers/tty/serial/sh-sci.c | 14 ++++++++------
5 files changed, 47 insertions(+), 39 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 5a83e5269b415..1da605cc86011 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,24 +284,25 @@ 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_addr, GFP_KERNEL);
+ dma->rx_buf = dma_alloc_coherent(rx_dev, dma->rx_size, &dma->rx_addr,
+ GFP_KERNEL);
if (!dma->rx_buf) {
ret = -ENOMEM;
goto err;
}
/* TX buffer */
- dma->tx_addr = dma_map_single(dma->txchan->device->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,
+ dma->tx_addr = dma_map_single(tx_dev, p->port.state->port.xmit_buf,
+ UART_XMIT_SIZE, DMA_TO_DEVICE);
+ 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 +329,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->rx_addr);
+ 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..eb4ba78815028 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -435,8 +435,8 @@ 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->dma, GFP_KERNEL);
+ db->buf = dma_alloc_coherent(dmaengine_get_dma_device(chan),
+ PL011_DMA_BUFFER_SIZE, &db->dma, GFP_KERNEL);
if (!db->buf)
return -ENOMEM;
db->len = PL011_DMA_BUFFER_SIZE;
@@ -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/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
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH v2 2/2] serial: amba-pl011: use dmaengine public API instead of raw ops
2026-09-28 18:32 [PATCH v2 1/2] serial: use dmaengine_get_dma_device() instead of chan->device->dev Frank.Li
@ 2026-09-28 18:32 ` Frank.Li
0 siblings, 0 replies; 2+ messages in thread
From: Frank.Li @ 2026-09-28 18:32 UTC (permalink / raw)
To: Russell King, Greg Kroah-Hartman, Jiri Slaby, Kartik Rajput,
Fan Wu, Karl Mehltretter, Frank Li, Stefan Dösinger,
Peter Maydell, open list:TTY LAYER AND SERIAL DRIVERS,
open list:TTY LAYER AND SERIAL DRIVERS
Cc: vkoul, imx
From: Frank Li <Frank.Li@nxp.com>
Replace direct calls to the internal DMA device ops
(device->device_tx_status() and device->device_issue_pending())
with the proper public DMA engine wrappers:
- dmaengine_tx_status()
- dma_async_issue_pending()
Drivers must not call device ops directly; the wrappers provide
locking, debug checks, and a stable interface that hides internal
implementation details of the DMA controller driver.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
drivers/tty/serial/amba-pl011.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index eb4ba78815028..fcfa9f00aec65 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -721,7 +721,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
dmaengine_submit(desc);
/* Fire the DMA transaction */
- dma_dev->device_issue_pending(chan);
+ dma_async_issue_pending(chan);
uap->dmacr |= UART011_TXDMAE;
pl011_write(uap->dmacr, uap, REG_DMACR);
@@ -1011,8 +1011,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
*/
if (dmaengine_pause(rxchan))
dev_err(uap->port.dev, "unable to pause DMA transfer\n");
- dmastat = rxchan->device->device_tx_status(rxchan,
- dmarx->cookie, &state);
+ dmastat = dmaengine_tx_status(rxchan, dmarx->cookie, &state);
if (dmastat != DMA_PAUSED)
dev_err(uap->port.dev, "unable to pause DMA transfer\n");
@@ -1066,7 +1065,7 @@ static void pl011_dma_rx_callback(void *data)
* Rx data can be taken by the UART interrupts during
* the DMA irq handler. So we check the residue here.
*/
- rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
+ dmaengine_tx_status(rxchan, dmarx->cookie, &state);
pending = dbuf->len - state.residue;
BUG_ON(pending > PL011_DMA_BUFFER_SIZE);
/* Then we terminate the transfer - we now know our residue */
@@ -1124,7 +1123,7 @@ static void pl011_dma_rx_poll(struct timer_list *t)
struct dma_tx_state state;
dbuf = dmarx->use_buf_b ? &uap->dmarx.dbuf_b : &uap->dmarx.dbuf_a;
- rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
+ dmaengine_tx_status(rxchan, dmarx->cookie, &state);
if (likely(state.residue < dmarx->last_residue)) {
dmataken = dbuf->len - dmarx->last_residue;
size = dmarx->last_residue - state.residue;
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-28 18:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-28 18:32 [PATCH v2 1/2] serial: use dmaengine_get_dma_device() instead of chan->device->dev Frank.Li
2026-09-28 18:32 ` [PATCH v2 2/2] serial: amba-pl011: use dmaengine public API instead of raw ops Frank.Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®