realtek: eth: cleanup hardware transmit handling

There is a workaround in the transmit path for the RTL838x SoCs. This
is basically an open coded read_poll_timeout() and makes the code hard
to read. Additionally the magic trigger calculation is not easy to
understand.

Simplify things by using kernel standards and a better macro.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/22217
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Markus Stockhausen 2026-02-28 18:46:28 +01:00 committed by Hauke Mehrtens
parent 50ec0a3f97
commit 0e09c39a19

View File

@ -24,12 +24,12 @@
#include <asm/mach-rtl-otto/mach-rtl-otto.h>
#include "rtl838x_eth.h"
#define RTETH_OWN_CPU 1
#define RTETH_RX_RING_SIZE 128
#define RTETH_RX_RINGS 2
#define RTETH_TX_RING_SIZE 16
#define RTETH_TX_RINGS 2
#define RTETH_TX_TRIGGER 0x16
#define RTETH_OWN_CPU 1
#define RTETH_RX_RING_SIZE 128
#define RTETH_RX_RINGS 2
#define RTETH_TX_RING_SIZE 16
#define RTETH_TX_RINGS 2
#define RTETH_TX_TRIGGER(ctrl, ring) ((0x16 >> ring) & ctrl->r->tx_trigger_mask)
#define NOTIFY_EVENTS 10
#define NOTIFY_BLOCKS 10
@ -925,7 +925,7 @@ static void rteth_tx_timeout(struct net_device *ndev, unsigned int txqueue)
static int rteth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct rteth_ctrl *ctrl = netdev_priv(netdev);
int slot, len = skb->len, dest_port = -1;
int val, slot, len = skb->len, dest_port = -1;
int ring = skb_get_queue_mapping(skb);
struct device *dev = &ctrl->pdev->dev;
struct rteth_packet *packet;
@ -990,18 +990,16 @@ static int rteth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
spin_lock(&ctrl->tx_lock);
/* Before starting TX, prevent a Lexra bus bug on RTL8380 SoCs */
if (ctrl->r->family_id == RTL8380_FAMILY_ID) {
for (int i = 0; i < 10; i++) {
u32 val = sw_r32(ctrl->r->dma_if_ctrl);
if ((val & ctrl->r->tx_rx_enable) == ctrl->r->tx_rx_enable)
break;
}
}
/*
* Issue send for 1 or 2 triggers. On some SoCs (especially RTL838x) there is a known
* bug, where the hardware sometimes reads empty values from the register. Work around
* that with a poll that checks if TX/RX is enabled in the register.
*/
if (read_poll_timeout(sw_r32, val, val & ctrl->r->tx_rx_enable,
0, 5000, false, ctrl->r->dma_if_ctrl))
dev_warn_once(dev, "DMA interface ctrl register read failed\n");
/* issue SoC independent send for 1 or 2 triggers with some bit vodoo */
sw_w32_mask(0, (RTETH_TX_TRIGGER >> ring) & ctrl->r->tx_trigger_mask,
ctrl->r->dma_if_ctrl);
sw_w32(val | RTETH_TX_TRIGGER(ctrl, ring), ctrl->r->dma_if_ctrl);
netdev->stats.tx_packets++;
netdev->stats.tx_bytes += len;