Skip to content

Uart: phytium: update phytium uart controller driver support to 6.6.0.4 - #2245

Open
wangchenlu2236 wants to merge 1 commit into
deepin-community:linux-6.6.yfrom
wangchenlu2236:uart-6.6.y
Open

wangchenlu2236 wants to merge 1 commit into
deepin-community:linux-6.6.yfrom
wangchenlu2236:uart-6.6.y

Conversation

@wangchenlu2236

@wangchenlu2236 wangchenlu2236 commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

This patches updates the support for phytium XXX controller driver.
1.uart-v2: phytium: Add DDR-DMA solution for uart

Summary by Sourcery

Enable Phytium UART v2 controllers to use DDR-based DMA transfers while preserving support for existing message-buffer operation.

New Features:

  • Add optional DDR-backed DMA buffering for Phytium UART v2 controllers with feature detection and shared buffer configuration.

Enhancements:

  • Update the UART v2 driver defaults, message capacity, naming, and protocol handling for newer controller support.
  • Extend UART configuration to communicate the data width required by FIFO-less devices.

Chores:

  • Bump the Phytium UART driver version to 1.1.2.

In order to decrease some hardware resources, we fulfill
this solution. what's more, it may improve transmission
efficiency and it can remain compatible with the older version
at the same time.

Mainline: NA
Signed-off-by: Feng Jun <fengjun@phytium.com.cn>
Signed-off-by: Wang Yinfeng <wangyinfeng@phytium.com.cn>
Signed-off-by: Wang Chenlu <wangchenlu2236@phytium.com.cn>
@sourcery-ai

sourcery-ai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Updates the Phytium UART v2 driver to version 1.1.2 with support for controllers exposing the DDR feature: probe-time capability detection and buffer allocation enable physical-address-based RX/TX transfers, while the existing shared-memory protocol remains available for non-DDR hardware; the patch also updates protocol constants, clock defaults, naming, and UART configuration handling.

Sequence diagram for Phytium UART DDR capability initialization

sequenceDiagram
    participant Driver as phytium_uart_probe
    participant UART as UART controller
    participant Memory as DDR buffers
    Driver->>UART: check_feature()
    UART-->>Driver: REG_CHECK_FEATURE with BIT_SUPPORT_DDR
    alt DDR supported
        Driver->>Memory: devm_kzalloc(DDR_BUF_SIZE) for rx_addr
        Driver->>UART: set_rx_addr()
        Driver->>UART: phyt_msg_insert(SET_DDR_BASE)
        Driver->>Memory: devm_kzalloc(DDR_BUF_SIZE) for tx_addr
    else DDR unsupported
        Driver->>Driver: use_ddr = false
    end
Loading

Sequence diagram for Phytium UART DDR transmit and receive

sequenceDiagram
    participant TTY as UART TTY layer
    participant Driver as Phytium UART driver
    participant Ring as Shared-memory ring
    participant DDR as DDR buffers
    participant UART as UART controller
    TTY->>Driver: phytium_tx_chars()
    alt use_ddr
        Driver->>DDR: write TX bytes to tx_addr
        Driver->>Ring: phyt_msg_insert(DDR physical address, length)
        Ring->>UART: deliver TX descriptor
        UART-->>Ring: RX descriptor with DDR address and length
        Driver->>DDR: read RX bytes via rx_addr
    else shared-memory protocol
        Driver->>Ring: phyt_msg_insert(inline message data)
        Ring->>UART: deliver TX message
        UART-->>Ring: RX message with inline data
        Driver->>Ring: read RX message data
    end
    Driver-->>TTY: deliver or transmit UART characters
Loading

File-Level Changes

Change Details Files
Adds feature-detected DDR-backed DMA-style buffering while retaining the existing shared-memory message path as a fallback.
  • Detects DDR capability during probe and allocates RX/TX buffers.
  • Registers the RX DDR buffer address and transfers TX/RX payloads through physical buffer addresses and length metadata.
  • Adjusts message sizes and ring-buffer offsets for the DDR protocol.
drivers/tty/serial/phytium-uart-v2.c
drivers/tty/serial/phytium-uart-v2.h
Updates controller configuration and driver metadata for the newer UART support level.
  • Raises the default clock and driver version.
  • Adds the DDR feature register, buffer constants, message subcommand, and larger message payload capacity.
  • Propagates renamed command type aliases and message insertion helper throughout the driver.
  • Adds UART data-bit configuration for single-byte FIFO implementations.
drivers/tty/serial/phytium-uart-v2.c
drivers/tty/serial/phytium-uart-v2.h

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign lanlanxiyiji for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@deepin-ci-robot

Copy link
Copy Markdown

Hi @wangchenlu2236. Thanks for your PR.

I'm waiting for a deepin-community member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 13 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="186-187" />
<code_context>
-		count = handler_msg->length / 2;
+
+		if (pup->use_ddr == true) {
+			pup->rx_addr = phys_to_virt(*(u64 *)&handler_msg->data[0]);
+			count = (*(u32 *)&handler_msg->data[8]) / 2;
+			index = count;
+		} else
</code_context>
<issue_to_address>
**Forged RX descriptor exposes kernel memory**

When A controller or firmware can place a forged DDR RX descriptor in the shared message ring, `phytium_fifo_to_tty` converts the RX descriptor’s physical address directly with `phys_to_virt` and reads from it without checking that it refers to the configured RX allocation. A controller or firmware that can forge a shared-memory descriptor can make the driver copy kernel memory into the UART receive stream, where a process with access to the TTY can read it.

Validate descriptor addresses and lengths against the configured RX buffer before converting or dereferencing them.
</issue_to_address>

### Comment 2
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="324" />
<code_context>
 	if (tx_ring_buffer_is_full(pup))
 		return false;
+	if (pup->use_ddr == true) {
+		u64 tmp_addr = (u64)&pup->tx_addr[xmit->tail];
+		/*
+		 * check current addr is aligned by 4bytes? if not, align
</code_context>
<issue_to_address>
**DDR writes corrupt adjacent memory**

When DDR transmission advances the transmit tail beyond the 2048-byte buffer, `phytium_tx_chars` indexes `tx_addr` with the larger UART transmit-ring tail, so it writes beyond the allocation and corrupts adjacent kernel memory.

Allocate a buffer large enough for the transmit ring or bound and wrap every DDR-buffer index and batch.

Also at `drivers/tty/serial/phytium-uart-v2.c:347`, `drivers/tty/serial/phytium-uart-v2.c:1339`, `drivers/tty/serial/phytium-uart-v2.h:67-68`.
</issue_to_address>

### Comment 3
<location path="drivers/tty/serial/phytium-uart-v2.h" line_range="66" />
<code_context>
+#define REG_CHECK_FEATURE	0x700
+#define BIT_SUPPORT_DDR		BIT(16)
+#define TYPE_MAX_LEN		12
+#define DATA_MAX_LEN		160
+#define DDR_BUF_SIZE		2048
+#define DDR_RX_MSG_SIZE		0x20
</code_context>
<issue_to_address>
**Legacy messages corrupt shared memory**

When the controller uses the non-DDR message path, `phyt_msg_insert` copies the 168-byte `struct msg` into 128-byte legacy slots, overwriting subsequent slots and, at the end of the TX ring, the RX area; legacy UART traffic is corrupted.

Keep the legacy message within its slot or copy only the legacy message size.

Also at `drivers/tty/serial/phytium-uart-v2.c:61`, `drivers/tty/serial/phytium-uart-v2.c:133`.
</issue_to_address>

### Comment 4
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="335" />
<code_context>
+			shift_bit = shift_addr - tmp_addr;
+			*(u64 *)&msg.data[0] = (u64)__virt_to_phys(shift_addr);
+		} else
+			*(u64 *)&msg.data[0] = (u64)__virt_to_phys((u64)&xmit->buf[xmit->tail]);
+	}
+	if (shift_bit)
</code_context>
<issue_to_address>
**DDR transmits the wrong bytes**

When DDR transmission uses an aligned staging address, or queued data crosses the transmit-ring boundary, `phytium_tx_chars` stages bytes in `tx_addr` but can put an `xmit->buf` address in the descriptor; its aligned-index handling can also make the copy and descriptor refer to different offsets. The controller reads stale, changed, or out-of-bounds data, corrupting transmitted characters.

Make the descriptor address, copy offset, and length consistently refer to the populated DDR TX buffer, including across ring wrap.

Also at `drivers/tty/serial/phytium-uart-v2.c:336`, `drivers/tty/serial/phytium-uart-v2.c:347`.
</issue_to_address>

### Comment 5
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="1234" />
<code_context>
+
+	cmd_subid = getHexValue(cmd);
+	msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid, 0);
+	mem_addr = (u64)__virt_to_phys((u64)pup->rx_addr);
+	/*
+	 * we use first 8 bytes of data array store rx buffer
</code_context>
<issue_to_address>
**DDR transfers use invalid addresses**

When DDR mode runs where CPU physical addresses differ from DMA addresses or memory is non-coherent, the driver passes `__virt_to_phys` addresses for `devm_kzalloc` buffers without DMA mapping or cache synchronization, so the controller accesses invalid or stale memory and DDR transfers fail or corrupt data.

Allocate and map the buffers with the device DMA API and perform the required DMA synchronization.

Also at `drivers/tty/serial/phytium-uart-v2.c:333`, `drivers/tty/serial/phytium-uart-v2.c:1334-1339`.
</issue_to_address>

### Comment 6
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="1341" />
<code_context>
+		pup->rx_addr = devm_kzalloc(&pdev->dev, DDR_BUF_SIZE,
+				GFP_KERNEL);
+		if (!pup->rx_addr)
+			goto free;
+		set_rx_addr(pup);
+		pup->tx_addr = devm_kzalloc(&pdev->dev, DDR_BUF_SIZE,
</code_context>
<issue_to_address>
**Probe failure leaves stale state**

When a DDR TX-buffer allocation or later probe step fails after the RX address is sent, probe exits after publishing the RX address to the controller and assigning the port entry; the failure path frees the buffer without undoing that state, leaving a stale controller address and a consumed port slot.

On probe failure, clear the port entry and withdraw or reset the controller's RX-buffer configuration before freeing the buffer.

Also at `drivers/tty/serial/phytium-uart-v2.c:1337-1338`.
</issue_to_address>

### Comment 7
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="200" />
<code_context>
-			ch = (handler_msg->data[2 * fifotaken]);
-			ch |= (handler_msg->data[2 * fifotaken + 1] << 8);
+			if (pup->use_ddr == true) {
+				ch = pup->rx_addr[2 * fifotaken];
+				ch |= (pup->rx_addr[2 * fifotaken + 1] << 8);
+			} else {
</code_context>
<issue_to_address>
**RX data changes while copied**

When the firmware produces another RX message while the handler is draining the current DDR buffer, `phytium_fifo_to_tty` releases the RX ring slot before copying from the shared `rx_addr`; the firmware can reuse that buffer during the copy, so the TTY receives corrupted or mixed data.

Keep the RX slot unavailable until the DDR buffer has been copied, or copy the buffer before releasing the slot.

Also at `drivers/tty/serial/phytium-uart-v2.c:186`, `drivers/tty/serial/phytium-uart-v2.c:1240`.
</issue_to_address>

### Comment 8
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="187" />
<code_context>
+
+		if (pup->use_ddr == true) {
+			pup->rx_addr = phys_to_virt(*(u64 *)&handler_msg->data[0]);
+			count = (*(u32 *)&handler_msg->data[8]) / 2;
+			index = count;
+		} else
</code_context>
<issue_to_address>
**DDR receive data is discarded**

When the controller reports more than 61 16-bit characters in one DDR message, `phytium_fifo_to_tty` processes at most `RX_DATA_MAXINUM` characters and then advances past the message, discarding the remaining DDR data.

Process the full reported character count or have the controller split messages into chunks no larger than the loop limit.
</issue_to_address>

### Comment 9
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="130" />
<code_context>
-
-	memcpy(pup->shmem_base + TX_MSG_SIZE * tx_tail,
+	if (pup->use_ddr == true)
+		memcpy(pup->shmem_base + DDR_TX_MSG_SIZE * tx_tail,
+			msg, DDR_TX_MSG_SIZE);
+	else
</code_context>
<issue_to_address>
**DDR replies read from wrong slots**

When DDR mode reads a modem-status, get-mctrl, or startup reply from a nonzero TX slot, `phyt_msg_insert` places DDR messages at 32-byte strides, but the modem-status, get-mctrl, and startup readers use the legacy 128-byte stride; they read another slot and report stale or incorrect state.

Use the DDR slot stride when locating replies in DDR mode.

Also at `drivers/tty/serial/phytium-uart-v2.c:131`, `drivers/tty/serial/phytium-uart-v2.c:384`, `drivers/tty/serial/phytium-uart-v2.c:504`, `drivers/tty/serial/phytium-uart-v2.c:760`.
</issue_to_address>

### Comment 10
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="290" />
<code_context>
-	phytium_uart_write(1, pup, REG_CHECK_TX);
-
-	PHYT_MSG_INSERT(pup, &msg);
+	phyt_msg_insert(pup, &msg);

 	pup->port.icount.tx++;
</code_context>
<issue_to_address>
**Urgent characters are not transmitted**

When DDR mode sends an `x_char`, such as XON or XOFF, `phytium_tx_xchar` puts the character inline in the message, but the DDR transmit path interprets the payload as a buffer address and size; the controller therefore does not transmit the urgent character.

Encode the character using the DDR payload format or send it through the DDR TX buffer.

Also at `drivers/tty/serial/phytium-uart-v2.c:130`, `drivers/tty/serial/phytium-uart-v2.c:323`.
</issue_to_address>

### Comment 11
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="1334" />
<code_context>
+
+	if (check_feature(pup)) {
+		pup->rx_addr = devm_kzalloc(&pdev->dev, DDR_BUF_SIZE,
+				GFP_KERNEL);
+		if (!pup->rx_addr)
+			goto free;
</code_context>
<issue_to_address>
**DDR allocation errors misreported**

When either DDR buffer allocation fails during probe, `phytium_uart_probe` sends either DDR-buffer allocation failure to the shared `free` label, which returns `-1` rather than `-ENOMEM` and provides no allocation-specific log. Probe failure is therefore reported as the wrong error, obscuring the cause of an unavailable UART. Return `-ENOMEM` and log the failed allocation.

Also at `drivers/tty/serial/phytium-uart-v2.c:1340`.
</issue_to_address>

### Comment 12
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="1337" />
<code_context>
+				GFP_KERNEL);
+		if (!pup->rx_addr)
+			goto free;
+		set_rx_addr(pup);
+		pup->tx_addr = devm_kzalloc(&pdev->dev, DDR_BUF_SIZE,
+				GFP_KERNEL);
</code_context>
<issue_to_address>
**Reset discards the DDR RX setup**

When the default/reset command clears the controller's DDR base configuration, probe sends the DDR base configuration before `phytium_register_port` sends the default command used to reset the UART. That reset can clear the DDR base, and the driver does not send the configuration again before receiving data, leaving DDR RX unconfigured. Send the base configuration after the reset or reapply it during startup.
</issue_to_address>

### Comment 13
<location path="drivers/tty/serial/phytium-uart-v2.c" line_range="987" />
<code_context>
 	msg.data[5] = crtscts & MSG_DATA_MASK;
+	/* Add uart data bit */
+	if (pup->port.fifosize <= 1)
+		msg.data[6] = 1;

-	PHYT_MSG_INSERT(pup, &msg);
</code_context>
<issue_to_address>
**FIFO-less UARTs get wrong data width**

When a FIFO-less controller uses this driver, `phytium_set_termios` checks whether `fifosize` is at most one, but probe sets it to `UART_FIFOSIZE` (64) and does not otherwise change it; the required data-width flag is never sent.

Set `fifosize` from the hardware configuration or identify FIFO-less controllers directly when setting the flag.

Also at `drivers/tty/serial/phytium-uart-v2.c:986`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines +186 to +187
pup->rx_addr = phys_to_virt(*(u64 *)&handler_msg->data[0]);
count = (*(u32 *)&handler_msg->data[8]) / 2;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · Forged RX descriptor exposes kernel memory

When A controller or firmware can place a forged DDR RX descriptor in the shared message ring, phytium_fifo_to_tty converts the RX descriptor’s physical address directly with phys_to_virt and reads from it without checking that it refers to the configured RX allocation. A controller or firmware that can forge a shared-memory descriptor can make the driver copy kernel memory into the UART receive stream, where a process with access to the TTY can read it.

Validate descriptor addresses and lengths against the configured RX buffer before converting or dereferencing them.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.c` at lines 186-187:

**Forged RX descriptor exposes kernel memory**

When A controller or firmware can place a forged DDR RX descriptor in the shared message ring, `phytium_fifo_to_tty` converts the RX descriptor’s physical address directly with `phys_to_virt` and reads from it without checking that it refers to the configured RX allocation. A controller or firmware that can forge a shared-memory descriptor can make the driver copy kernel memory into the UART receive stream, where a process with access to the TTY can read it.

Validate descriptor addresses and lengths against the configured RX buffer before converting or dereferencing them.

if (tx_ring_buffer_is_full(pup))
return false;
if (pup->use_ddr == true) {
u64 tmp_addr = (u64)&pup->tx_addr[xmit->tail];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Critical · DDR writes corrupt adjacent memory

When DDR transmission advances the transmit tail beyond the 2048-byte buffer, phytium_tx_chars indexes tx_addr with the larger UART transmit-ring tail, so it writes beyond the allocation and corrupts adjacent kernel memory.

Allocate a buffer large enough for the transmit ring or bound and wrap every DDR-buffer index and batch.

Also at drivers/tty/serial/phytium-uart-v2.c:347, drivers/tty/serial/phytium-uart-v2.c:1339, drivers/tty/serial/phytium-uart-v2.h:67-68.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.c` at line 324:

**DDR writes corrupt adjacent memory**

When DDR transmission advances the transmit tail beyond the 2048-byte buffer, `phytium_tx_chars` indexes `tx_addr` with the larger UART transmit-ring tail, so it writes beyond the allocation and corrupts adjacent kernel memory.

Allocate a buffer large enough for the transmit ring or bound and wrap every DDR-buffer index and batch.

Also at `drivers/tty/serial/phytium-uart-v2.c:347`, `drivers/tty/serial/phytium-uart-v2.c:1339`, `drivers/tty/serial/phytium-uart-v2.h:67-68`.

#define REG_CHECK_FEATURE 0x700
#define BIT_SUPPORT_DDR BIT(16)
#define TYPE_MAX_LEN 12
#define DATA_MAX_LEN 160

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · Legacy messages corrupt shared memory

When the controller uses the non-DDR message path, phyt_msg_insert copies the 168-byte struct msg into 128-byte legacy slots, overwriting subsequent slots and, at the end of the TX ring, the RX area; legacy UART traffic is corrupted.

Keep the legacy message within its slot or copy only the legacy message size.

Also at drivers/tty/serial/phytium-uart-v2.c:61, drivers/tty/serial/phytium-uart-v2.c:133.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.h` at line 66:

**Legacy messages corrupt shared memory**

When the controller uses the non-DDR message path, `phyt_msg_insert` copies the 168-byte `struct msg` into 128-byte legacy slots, overwriting subsequent slots and, at the end of the TX ring, the RX area; legacy UART traffic is corrupted.

Keep the legacy message within its slot or copy only the legacy message size.

Also at `drivers/tty/serial/phytium-uart-v2.c:61`, `drivers/tty/serial/phytium-uart-v2.c:133`.

shift_bit = shift_addr - tmp_addr;
*(u64 *)&msg.data[0] = (u64)__virt_to_phys(shift_addr);
} else
*(u64 *)&msg.data[0] = (u64)__virt_to_phys((u64)&xmit->buf[xmit->tail]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · DDR transmits the wrong bytes

When DDR transmission uses an aligned staging address, or queued data crosses the transmit-ring boundary, phytium_tx_chars stages bytes in tx_addr but can put an xmit->buf address in the descriptor; its aligned-index handling can also make the copy and descriptor refer to different offsets. The controller reads stale, changed, or out-of-bounds data, corrupting transmitted characters.

Make the descriptor address, copy offset, and length consistently refer to the populated DDR TX buffer, including across ring wrap.

Also at drivers/tty/serial/phytium-uart-v2.c:336, drivers/tty/serial/phytium-uart-v2.c:347.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.c` at line 335:

**DDR transmits the wrong bytes**

When DDR transmission uses an aligned staging address, or queued data crosses the transmit-ring boundary, `phytium_tx_chars` stages bytes in `tx_addr` but can put an `xmit->buf` address in the descriptor; its aligned-index handling can also make the copy and descriptor refer to different offsets. The controller reads stale, changed, or out-of-bounds data, corrupting transmitted characters.

Make the descriptor address, copy offset, and length consistently refer to the populated DDR TX buffer, including across ring wrap.

Also at `drivers/tty/serial/phytium-uart-v2.c:336`, `drivers/tty/serial/phytium-uart-v2.c:347`.


cmd_subid = getHexValue(cmd);
msg_fill(&msg, UART_MODULE_ID, MSG_SET, cmd_subid, 0);
mem_addr = (u64)__virt_to_phys((u64)pup->rx_addr);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · DDR transfers use invalid addresses

When DDR mode runs where CPU physical addresses differ from DMA addresses or memory is non-coherent, the driver passes __virt_to_phys addresses for devm_kzalloc buffers without DMA mapping or cache synchronization, so the controller accesses invalid or stale memory and DDR transfers fail or corrupt data.

Allocate and map the buffers with the device DMA API and perform the required DMA synchronization.

Also at drivers/tty/serial/phytium-uart-v2.c:333, drivers/tty/serial/phytium-uart-v2.c:1334-1339.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.c` at line 1234:

**DDR transfers use invalid addresses**

When DDR mode runs where CPU physical addresses differ from DMA addresses or memory is non-coherent, the driver passes `__virt_to_phys` addresses for `devm_kzalloc` buffers without DMA mapping or cache synchronization, so the controller accesses invalid or stale memory and DDR transfers fail or corrupt data.

Allocate and map the buffers with the device DMA API and perform the required DMA synchronization.

Also at `drivers/tty/serial/phytium-uart-v2.c:333`, `drivers/tty/serial/phytium-uart-v2.c:1334-1339`.


memcpy(pup->shmem_base + TX_MSG_SIZE * tx_tail,
if (pup->use_ddr == true)
memcpy(pup->shmem_base + DDR_TX_MSG_SIZE * tx_tail,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · DDR replies read from wrong slots

When DDR mode reads a modem-status, get-mctrl, or startup reply from a nonzero TX slot, phyt_msg_insert places DDR messages at 32-byte strides, but the modem-status, get-mctrl, and startup readers use the legacy 128-byte stride; they read another slot and report stale or incorrect state.

Use the DDR slot stride when locating replies in DDR mode.

Also at drivers/tty/serial/phytium-uart-v2.c:131, drivers/tty/serial/phytium-uart-v2.c:384, drivers/tty/serial/phytium-uart-v2.c:504, drivers/tty/serial/phytium-uart-v2.c:760.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.c` at line 130:

**DDR replies read from wrong slots**

When DDR mode reads a modem-status, get-mctrl, or startup reply from a nonzero TX slot, `phyt_msg_insert` places DDR messages at 32-byte strides, but the modem-status, get-mctrl, and startup readers use the legacy 128-byte stride; they read another slot and report stale or incorrect state.

Use the DDR slot stride when locating replies in DDR mode.

Also at `drivers/tty/serial/phytium-uart-v2.c:131`, `drivers/tty/serial/phytium-uart-v2.c:384`, `drivers/tty/serial/phytium-uart-v2.c:504`, `drivers/tty/serial/phytium-uart-v2.c:760`.

phytium_uart_write(1, pup, REG_CHECK_TX);

PHYT_MSG_INSERT(pup, &msg);
phyt_msg_insert(pup, &msg);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · Urgent characters are not transmitted

When DDR mode sends an x_char, such as XON or XOFF, phytium_tx_xchar puts the character inline in the message, but the DDR transmit path interprets the payload as a buffer address and size; the controller therefore does not transmit the urgent character.

Encode the character using the DDR payload format or send it through the DDR TX buffer.

Also at drivers/tty/serial/phytium-uart-v2.c:130, drivers/tty/serial/phytium-uart-v2.c:323.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.c` at line 290:

**Urgent characters are not transmitted**

When DDR mode sends an `x_char`, such as XON or XOFF, `phytium_tx_xchar` puts the character inline in the message, but the DDR transmit path interprets the payload as a buffer address and size; the controller therefore does not transmit the urgent character.

Encode the character using the DDR payload format or send it through the DDR TX buffer.

Also at `drivers/tty/serial/phytium-uart-v2.c:130`, `drivers/tty/serial/phytium-uart-v2.c:323`.


if (check_feature(pup)) {
pup->rx_addr = devm_kzalloc(&pdev->dev, DDR_BUF_SIZE,
GFP_KERNEL);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ Low · DDR allocation errors misreported

When either DDR buffer allocation fails during probe, phytium_uart_probe sends either DDR-buffer allocation failure to the shared free label, which returns -1 rather than -ENOMEM and provides no allocation-specific log. Probe failure is therefore reported as the wrong error, obscuring the cause of an unavailable UART. Return -ENOMEM and log the failed allocation.

Also at drivers/tty/serial/phytium-uart-v2.c:1340.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.c` at line 1334:

**DDR allocation errors misreported**

When either DDR buffer allocation fails during probe, `phytium_uart_probe` sends either DDR-buffer allocation failure to the shared `free` label, which returns `-1` rather than `-ENOMEM` and provides no allocation-specific log. Probe failure is therefore reported as the wrong error, obscuring the cause of an unavailable UART. Return `-ENOMEM` and log the failed allocation.

Also at `drivers/tty/serial/phytium-uart-v2.c:1340`.

GFP_KERNEL);
if (!pup->rx_addr)
goto free;
set_rx_addr(pup);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · Reset discards the DDR RX setup

When the default/reset command clears the controller's DDR base configuration, probe sends the DDR base configuration before phytium_register_port sends the default command used to reset the UART. That reset can clear the DDR base, and the driver does not send the configuration again before receiving data, leaving DDR RX unconfigured. Send the base configuration after the reset or reapply it during startup.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.c` at line 1337:

**Reset discards the DDR RX setup**

When the default/reset command clears the controller's DDR base configuration, probe sends the DDR base configuration before `phytium_register_port` sends the default command used to reset the UART. That reset can clear the DDR base, and the driver does not send the configuration again before receiving data, leaving DDR RX unconfigured. Send the base configuration after the reset or reapply it during startup.

msg.data[5] = crtscts & MSG_DATA_MASK;
/* Add uart data bit */
if (pup->port.fifosize <= 1)
msg.data[6] = 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · FIFO-less UARTs get wrong data width

When a FIFO-less controller uses this driver, phytium_set_termios checks whether fifosize is at most one, but probe sets it to UART_FIFOSIZE (64) and does not otherwise change it; the required data-width flag is never sent.

Set fifosize from the hardware configuration or identify FIFO-less controllers directly when setting the flag.

Also at drivers/tty/serial/phytium-uart-v2.c:986.

Prompt for AI agents
In `drivers/tty/serial/phytium-uart-v2.c` at line 987:

**FIFO-less UARTs get wrong data width**

When a FIFO-less controller uses this driver, `phytium_set_termios` checks whether `fifosize` is at most one, but probe sets it to `UART_FIFOSIZE` (64) and does not otherwise change it; the required data-width flag is never sent.

Set `fifosize` from the hardware configuration or identify FIFO-less controllers directly when setting the flag.

Also at `drivers/tty/serial/phytium-uart-v2.c:986`.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved UART buffer overruns, unsafe DMA buffer handling and publication, and a dangling port pointer create critical kernel memory corruption risks.

8 open issues
What changed in this PR

Adds optional DDR-backed DMA transfers to the Phytium UART v2 driver, alongside the existing message-buffer transport.

Changes:

  • Detect DDR support and configure shared buffers and transfer descriptors.
  • Update message capacity, the default clock, and FIFO-less UART configuration.
  • Bump the driver version to 1.1.2.
File Description
drivers/​tty/​serial/​phytium-uart-v2.h Defines DDR feature flags, buffer sizes, and the buffer-configuration command.
drivers/​tty/​serial/​phytium-uart-v2.c Adds DDR detection, allocation, and transfer handling; updates driver defaults and UART configuration.

Review effort: Balanced

Comment on lines +130 to +131
memcpy(pup->shmem_base + DDR_TX_MSG_SIZE * tx_tail,
msg, DDR_TX_MSG_SIZE);
Comment on lines +133 to 134
memcpy(pup->shmem_base + TX_MSG_SIZE * tx_tail,
msg, sizeof(struct msg));
shift_bit = shift_addr - tmp_addr;
*(u64 *)&msg.data[0] = (u64)__virt_to_phys(shift_addr);
} else
*(u64 *)&msg.data[0] = (u64)__virt_to_phys((u64)&xmit->buf[xmit->tail]);
msg.length = datasize;
msg.data[datasize - 1] = xmit->buf[xmit->tail];
} else
pup->tx_addr[index++] = xmit->buf[xmit->tail];
Comment on lines +1335 to +1336
if (!pup->rx_addr)
goto free;

if (pup->use_ddr == true) {
pup->rx_addr = phys_to_virt(*(u64 *)&handler_msg->data[0]);
count = (*(u32 *)&handler_msg->data[8]) / 2;
phytium_uart_write(1, pup, REG_CHECK_TX);

PHYT_MSG_INSERT(pup, &msg);
phyt_msg_insert(pup, &msg);
Comment on lines 386 to 387
handler_msg =
(struct msg *)(pup->shmem_base + TX_MSG_SIZE * old_tx_tail);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants