* [PATCH] drm/rcar-du: dsi: Implement DSI command TX using AXI memory access
@ 2026-08-09 19:58 Marek Vasut
2026-08-09 20:05 ` sashiko-bot
2026-08-10 10:04 ` Laurent Pinchart
0 siblings, 2 replies; 3+ messages in thread
From: Marek Vasut @ 2026-08-09 19:58 UTC (permalink / raw)
To: dri-devel
Cc: Marek Vasut, David Airlie, Geert Uytterhoeven, Kieran Bingham,
Laurent Pinchart, Maarten Lankhorst, Magnus Damm, Maxime Ripard,
Simona Vetter, Thomas Zimmermann, Tomi Valkeinen, linux-kernel,
linux-renesas-soc
Currently, the driver supports register access mode for DSI command
transfer, which limits both TX and RX to only 16 Bytes long packets.
Implement support for DSI command TX using AXI memory access mode,
which extends the packet transfer length up to 128 Bytes long in LP
and 1024 Bytes long in HS. Support for DSI command RX using the AXI
access mode is not implemented due to missing test hardware.
The implementation allocates a DMAble 4k page. In case the command
transfer is longer than 16 Bytes, the payload is copied into the
page and sent out using the AXI access mode, otherwise the register
access mode is used.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: David Airlie <airlied@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
.../gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c | 42 +++++++++++++++----
1 file changed, 35 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
index 6e46d6d99f3c0..c25218ca4320a 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
@@ -8,6 +8,7 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/math64.h>
@@ -75,6 +76,9 @@ struct rcar_mipi_dsi {
unsigned long mode_flags;
unsigned int num_data_lanes;
unsigned int lanes;
+
+ void *cmd_axi_cpu;
+ dma_addr_t cmd_axi_dma;
};
struct dsi_setup_info {
@@ -977,6 +981,7 @@ static ssize_t rcar_mipi_dsi_host_tx_transfer(struct mipi_dsi_host *host,
bool is_rx_xfer)
{
const bool is_tx_long = mipi_dsi_packet_format_is_long(msg->type);
+ const bool is_tx_axi = !is_rx_xfer && is_tx_long && (msg->tx_len > 16);
struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
struct mipi_dsi_packet packet;
u8 payload[16] = { 0 };
@@ -987,9 +992,14 @@ static ssize_t rcar_mipi_dsi_host_tx_transfer(struct mipi_dsi_host *host,
if (ret)
return ret;
- /* Configure LP or HS command transfer. */
- rcar_mipi_dsi_write(dsi, TXCMSETR, (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
- TXCMSETR_SPDTYP : 0);
+ /* Configure LP or HS and register or AXI command transfer. */
+ rcar_mipi_dsi_write(dsi, TXCMSETR, ((msg->flags & MIPI_DSI_MSG_USE_LPM) ?
+ TXCMSETR_SPDTYP : 0) |
+ (is_tx_axi ? TXCMSETR_LPPDACC : 0));
+
+ /* Configure DMA source address for AXI command transfer. */
+ if (is_tx_axi)
+ rcar_mipi_dsi_write(dsi, TXCMADDRSET0R, dsi->cmd_axi_dma);
/* Register access mode for RX transfer. */
if (is_rx_xfer)
@@ -1011,7 +1021,10 @@ static ssize_t rcar_mipi_dsi_host_tx_transfer(struct mipi_dsi_host *host,
TXCMPHDR_DATA1(packet.header[2]) |
TXCMPHDR_DATA0(packet.header[1]));
- if (is_tx_long) {
+ if (is_tx_axi) {
+ memcpy(dsi->cmd_axi_cpu, packet.payload,
+ min(msg->tx_len, 128));
+ } else if (is_tx_long) {
memcpy(payload, packet.payload,
min(msg->tx_len, sizeof(payload)));
@@ -1162,10 +1175,16 @@ static ssize_t rcar_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
int ret;
- if (msg->tx_len > 16 || msg->rx_len > 16) {
- /* ToDo: Implement Memory on AXI bus command mode. */
+ if (msg->tx_len > 1024 || msg->rx_len > 16) {
+ /* ToDo: Implement Memory on AXI bus RX command mode. */
dev_warn(dsi->dev,
- "Register-based command mode supports only up to 16 Bytes long payload\n");
+ "Command mode supports only up to 1024B long TX and 16B long RX payload\n");
+ return -EOPNOTSUPP;
+ }
+
+ if ((msg->flags & MIPI_DSI_MSG_USE_LPM) && msg->tx_len > 128) {
+ dev_warn(dsi->dev,
+ "Command mode in LP supports only up to 128B long TX payload\n");
return -EOPNOTSUPP;
}
@@ -1276,6 +1295,13 @@ static int rcar_mipi_dsi_probe(struct platform_device *pdev)
dsi->dev = &pdev->dev;
dsi->info = of_device_get_match_data(&pdev->dev);
+ dsi->cmd_axi_cpu = dma_alloc_coherent(&pdev->dev, SZ_4K, &dsi->cmd_axi_dma,
+ GFP_KERNEL | GFP_DMA32);
+ if (!dsi->cmd_axi_cpu) {
+ return dev_err_probe(&pdev->dev, -ENOMEM,
+ "Failed to allocate DSI AXI Access command buffer\n");
+ }
+
ret = rcar_mipi_dsi_parse_dt(dsi);
if (ret < 0)
return ret;
@@ -1309,6 +1335,8 @@ static void rcar_mipi_dsi_remove(struct platform_device *pdev)
{
struct rcar_mipi_dsi *dsi = platform_get_drvdata(pdev);
+ dma_free_coherent(&pdev->dev, SZ_4K, dsi->cmd_axi_cpu, dsi->cmd_axi_dma);
+
mipi_dsi_host_unregister(&dsi->host);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] drm/rcar-du: dsi: Implement DSI command TX using AXI memory access
2026-08-09 19:58 [PATCH] drm/rcar-du: dsi: Implement DSI command TX using AXI memory access Marek Vasut
@ 2026-08-09 20:05 ` sashiko-bot
2026-08-10 10:04 ` Laurent Pinchart
1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-08-09 20:05 UTC (permalink / raw)
To: Marek Vasut; +Cc: dri-devel, wsa+renesas
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] High Speed (HS) AXI command payload is silently truncated to 128 bytes.
- [High] Use-After-Free of the AXI DMA buffer during device removal due to teardown order inversion.
- [High] Large TX payloads combined with an RX or ACK request are forced into register mode and truncated.
- [Medium] Memory leak of the DMA coherent buffer on probe error paths.
--
--- Patch [1]: [PATCH] drm/rcar-du: dsi: Implement DSI command TX using AXI memory access ---
commit b5f3f6a7ebb3a67c9d4682699f04e9f66eb46473
Author: Marek Vasut <marek.vasut+renesas@mailbox.org>
drm/rcar-du: dsi: Implement DSI command TX using AXI memory access
This commit implements support for DSI command TX using AXI memory access
mode. It extends the packet transfer length up to 128 Bytes long in LP and
1024 Bytes long in HS by allocating a DMAble 4k page for large transfers.
> diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
> index 6e46d6d99f3c0..c25218ca4320a 100644
> --- a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
> +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
> @@ -977,6 +981,7 @@ static ssize_t rcar_mipi_dsi_host_tx_transfer(struct mipi_dsi_host *host,
> bool is_rx_xfer)
> {
> const bool is_tx_long = mipi_dsi_packet_format_is_long(msg->type);
> + const bool is_tx_axi = !is_rx_xfer && is_tx_long && (msg->tx_len > 16);
[Severity: High]
If a caller requests a transfer with a payload larger than 16 bytes and also
expects a response or requests an ACK (MIPI_DSI_MSG_REQ_ACK), is_tx_axi
evaluates to false. Will this cause the hardware to be misconfigured?
The packet header is instructed to transmit the full msg->tx_len, but since
it falls back to register mode, the payload is truncated to 16 bytes in the
TXCMPPD* registers. Does this lead to sending stale data or hardware
timeouts?
> struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
> struct mipi_dsi_packet packet;
[ ... ]
> @@ -1011,7 +1021,10 @@ static ssize_t rcar_mipi_dsi_host_tx_transfer(struct mipi_dsi_host *host,
> TXCMPHDR_DATA1(packet.header[2]) |
> TXCMPHDR_DATA0(packet.header[1]));
>
> - if (is_tx_long) {
> + if (is_tx_axi) {
> + memcpy(dsi->cmd_axi_cpu, packet.payload,
> + min(msg->tx_len, 128));
[Severity: High]
Does this silently truncate High Speed (HS) AXI command payloads to 128
bytes?
The validation in rcar_mipi_dsi_host_transfer() explicitly allows up to 1024
bytes in HS mode, but this memcpy() caps the copy at 128 bytes regardless of
the actual requested transfer size.
> + } else if (is_tx_long) {
> memcpy(payload, packet.payload,
> min(msg->tx_len, sizeof(payload)));
[ ... ]
> @@ -1276,6 +1295,13 @@ static int rcar_mipi_dsi_probe(struct platform_device *pdev)
> dsi->dev = &pdev->dev;
> dsi->info = of_device_get_match_data(&pdev->dev);
>
> + dsi->cmd_axi_cpu = dma_alloc_coherent(&pdev->dev, SZ_4K, &dsi->cmd_axi_dma,
> + GFP_KERNEL | GFP_DMA32);
> + if (!dsi->cmd_axi_cpu) {
> + return dev_err_probe(&pdev->dev, -ENOMEM,
> + "Failed to allocate DSI AXI Access command buffer\n");
> + }
> +
> ret = rcar_mipi_dsi_parse_dt(dsi);
> if (ret < 0)
> return ret;
[Severity: Medium]
Does this leak the DMA coherent buffer on probe error paths?
If an error occurs during rcar_mipi_dsi_probe() after dma_alloc_coherent()
succeeds (such as in rcar_mipi_dsi_parse_dt() or clock setup), the function
returns directly without calling dma_free_coherent().
[ ... ]
> @@ -1309,6 +1335,8 @@ static void rcar_mipi_dsi_remove(struct platform_device *pdev)
> {
> struct rcar_mipi_dsi *dsi = platform_get_drvdata(pdev);
>
> + dma_free_coherent(&pdev->dev, SZ_4K, dsi->cmd_axi_cpu, dsi->cmd_axi_dma);
> +
> mipi_dsi_host_unregister(&dsi->host);
> }
[Severity: High]
Could this create a use-after-free of the AXI DMA buffer during device
removal?
The DMA buffer is freed before mipi_dsi_host_unregister() is called.
Unregistering the host detaches child DSI panels, triggering their remove
callbacks. If a panel driver sends DSI commands (like entering sleep mode)
during unbind, it will attempt to memcpy() into the already-freed
dsi->cmd_axi_cpu buffer.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260809195831.842907-1-marek.vasut+renesas@mailbox.org?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] drm/rcar-du: dsi: Implement DSI command TX using AXI memory access
2026-08-09 19:58 [PATCH] drm/rcar-du: dsi: Implement DSI command TX using AXI memory access Marek Vasut
2026-08-09 20:05 ` sashiko-bot
@ 2026-08-10 10:04 ` Laurent Pinchart
1 sibling, 0 replies; 3+ messages in thread
From: Laurent Pinchart @ 2026-08-10 10:04 UTC (permalink / raw)
To: Marek Vasut
Cc: dri-devel, David Airlie, Geert Uytterhoeven, Kieran Bingham,
Maarten Lankhorst, Magnus Damm, Maxime Ripard, Simona Vetter,
Thomas Zimmermann, Tomi Valkeinen, linux-kernel,
linux-renesas-soc
Hi Marek,
Thank you for the patch.
On Sun, Aug 09, 2026 at 09:58:06PM +0200, Marek Vasut wrote:
> Currently, the driver supports register access mode for DSI command
> transfer, which limits both TX and RX to only 16 Bytes long packets.
> Implement support for DSI command TX using AXI memory access mode,
> which extends the packet transfer length up to 128 Bytes long in LP
> and 1024 Bytes long in HS. Support for DSI command RX using the AXI
> access mode is not implemented due to missing test hardware.
>
> The implementation allocates a DMAble 4k page. In case the command
> transfer is longer than 16 Bytes, the payload is copied into the
> page and sent out using the AXI access mode, otherwise the register
> access mode is used.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> ---
> Cc: David Airlie <airlied@gmail.com>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Magnus Damm <magnus.damm@gmail.com>
> Cc: Maxime Ripard <mripard@kernel.org>
> Cc: Simona Vetter <simona@ffwll.ch>
> Cc: Thomas Zimmermann <tzimmermann@suse.de>
> Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-renesas-soc@vger.kernel.org
> ---
> .../gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c | 42 +++++++++++++++----
> 1 file changed, 35 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
> index 6e46d6d99f3c0..c25218ca4320a 100644
> --- a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
> +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
> @@ -8,6 +8,7 @@
> #include <linux/bitfield.h>
> #include <linux/clk.h>
> #include <linux/delay.h>
> +#include <linux/dma-mapping.h>
> #include <linux/io.h>
> #include <linux/iopoll.h>
> #include <linux/math64.h>
> @@ -75,6 +76,9 @@ struct rcar_mipi_dsi {
> unsigned long mode_flags;
> unsigned int num_data_lanes;
> unsigned int lanes;
> +
> + void *cmd_axi_cpu;
> + dma_addr_t cmd_axi_dma;
> };
>
> struct dsi_setup_info {
> @@ -977,6 +981,7 @@ static ssize_t rcar_mipi_dsi_host_tx_transfer(struct mipi_dsi_host *host,
> bool is_rx_xfer)
> {
> const bool is_tx_long = mipi_dsi_packet_format_is_long(msg->type);
> + const bool is_tx_axi = !is_rx_xfer && is_tx_long && (msg->tx_len > 16);
> struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
> struct mipi_dsi_packet packet;
> u8 payload[16] = { 0 };
> @@ -987,9 +992,14 @@ static ssize_t rcar_mipi_dsi_host_tx_transfer(struct mipi_dsi_host *host,
> if (ret)
> return ret;
>
> - /* Configure LP or HS command transfer. */
> - rcar_mipi_dsi_write(dsi, TXCMSETR, (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
> - TXCMSETR_SPDTYP : 0);
> + /* Configure LP or HS and register or AXI command transfer. */
> + rcar_mipi_dsi_write(dsi, TXCMSETR, ((msg->flags & MIPI_DSI_MSG_USE_LPM) ?
> + TXCMSETR_SPDTYP : 0) |
> + (is_tx_axi ? TXCMSETR_LPPDACC : 0));
> +
> + /* Configure DMA source address for AXI command transfer. */
> + if (is_tx_axi)
> + rcar_mipi_dsi_write(dsi, TXCMADDRSET0R, dsi->cmd_axi_dma);
>
> /* Register access mode for RX transfer. */
> if (is_rx_xfer)
> @@ -1011,7 +1021,10 @@ static ssize_t rcar_mipi_dsi_host_tx_transfer(struct mipi_dsi_host *host,
> TXCMPHDR_DATA1(packet.header[2]) |
> TXCMPHDR_DATA0(packet.header[1]));
>
> - if (is_tx_long) {
> + if (is_tx_axi) {
> + memcpy(dsi->cmd_axi_cpu, packet.payload,
> + min(msg->tx_len, 128));
> + } else if (is_tx_long) {
> memcpy(payload, packet.payload,
> min(msg->tx_len, sizeof(payload)));
>
> @@ -1162,10 +1175,16 @@ static ssize_t rcar_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
> struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
> int ret;
>
> - if (msg->tx_len > 16 || msg->rx_len > 16) {
> - /* ToDo: Implement Memory on AXI bus command mode. */
> + if (msg->tx_len > 1024 || msg->rx_len > 16) {
> + /* ToDo: Implement Memory on AXI bus RX command mode. */
> dev_warn(dsi->dev,
> - "Register-based command mode supports only up to 16 Bytes long payload\n");
> + "Command mode supports only up to 1024B long TX and 16B long RX payload\n");
> + return -EOPNOTSUPP;
> + }
> +
> + if ((msg->flags & MIPI_DSI_MSG_USE_LPM) && msg->tx_len > 128) {
> + dev_warn(dsi->dev,
> + "Command mode in LP supports only up to 128B long TX payload\n");
> return -EOPNOTSUPP;
> }
>
> @@ -1276,6 +1295,13 @@ static int rcar_mipi_dsi_probe(struct platform_device *pdev)
> dsi->dev = &pdev->dev;
> dsi->info = of_device_get_match_data(&pdev->dev);
>
> + dsi->cmd_axi_cpu = dma_alloc_coherent(&pdev->dev, SZ_4K, &dsi->cmd_axi_dma,
> + GFP_KERNEL | GFP_DMA32);
I think setting the DMA mask for the device is preferred over using
GFP_DMA32.
> + if (!dsi->cmd_axi_cpu) {
> + return dev_err_probe(&pdev->dev, -ENOMEM,
> + "Failed to allocate DSI AXI Access command buffer\n");
> + }
No need for curly braces.
> +
> ret = rcar_mipi_dsi_parse_dt(dsi);
The allocated memory is leaking in error paths.
> if (ret < 0)
> return ret;
> @@ -1309,6 +1335,8 @@ static void rcar_mipi_dsi_remove(struct platform_device *pdev)
> {
> struct rcar_mipi_dsi *dsi = platform_get_drvdata(pdev);
>
> + dma_free_coherent(&pdev->dev, SZ_4K, dsi->cmd_axi_cpu, dsi->cmd_axi_dma);
> +
> mipi_dsi_host_unregister(&dsi->host);
> }
>
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-10 10:04 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-09 19:58 [PATCH] drm/rcar-du: dsi: Implement DSI command TX using AXI memory access Marek Vasut
2026-08-09 20:05 ` sashiko-bot
2026-08-10 10:04 ` Laurent Pinchart
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.