]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: eth: prepare counters for fragments
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Fri, 17 Jul 2026 08:03:59 +0000 (10:03 +0200)
committerMarkus Stockhausen <markus.stockhausen@gmx.de>
Tue, 21 Jul 2026 07:30:09 +0000 (09:30 +0200)
Until now the driver packs each received packet into one ring buffer.
In the future jumbo packets will be split into multiple fragments.
Prepare the ring counters for this:

- Add the more flag to SoC packet header. This denotes if a packet
  has more data after the current fragment.
- Ring counters must be handled per packet and not per fragment.
  Increase work_done after each packet and not after each fragment.

Link: https://github.com/openwrt/openwrt/pull/24245
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c
target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.h

index b955219c92874a9953cb134f04f5744f335f78ef..d9eb474ecbbc2ea3c2edf736df8ebbbb83856ec9 100644 (file)
@@ -42,6 +42,7 @@
 #define RX_TRUNCATE_EN_83XX            BIT(4)
 #define TX_PAD_EN_838X                 BIT(5)
 
+#define SKB_MTU                                1600
 #define SKB_FRAG_SIZE                  1600
 #define SKB_PAD                                MAX(32, L1_CACHE_BYTES)
 #define SKB_HEADROOM_FAST              (SKB_PAD + NET_IP_ALIGN)
@@ -57,7 +58,8 @@ struct rteth_packet {
        dma_addr_t              dma;
        u16                     reserved;
        u16                     size;
-       u16                     offset;
+       u16                     more:1;
+       u16                     offset:15;
        u16                     len;
        u16                     cpu_tag[10];
        /* software mangement and data part */
@@ -466,16 +468,23 @@ static void rteth_839x_hw_reset(struct rteth_ctrl *ctrl)
 
 static void rteth_93xx_hw_reset(struct rteth_ctrl *ctrl)
 {
+       /*
+        * The counter registers track the number of packets that are allowed to be appended to
+        * the ring buffer. On RTL93xx a ring overflow must be avoided at all cost. Defensively
+        * calculate the space by anticipating that only fully filled packets are received.
+        */
+       int max_frame_size = SKB_MTU + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN + 4;
+       int frags_per_pkt = DIV_ROUND_UP(max_frame_size, SKB_FRAG_SIZE);
+       int cnt = min(RTETH_RX_RING_SIZE / frags_per_pkt, 0x3ff);
+
        rteth_nic_reset(ctrl, 0x6);
 
        /* Setup Head of Line */
        for (int ring = 0; ring < RTETH_RX_RINGS; ring++) {
-               int cnt = min(RTETH_RX_RING_SIZE, 0x3ff);
                int shift = (ring % 3) * 10;
                int reg = (ring / 3) * 4;
                u32 v;
 
-               /* set ring size */
                regmap_update_bits(ctrl->map, ctrl->r->dma_if_rx_ring_size + reg,
                                   0x3ff << shift, cnt << shift);
                /* clear counters by simply writing the current register values back */
@@ -544,9 +553,9 @@ static void rteth_hw_ring_setup(struct rteth_ctrl *ctrl)
 
 static void rteth_838x_hw_en_rxtx(struct rteth_ctrl *ctrl)
 {
-       /* Truncate RX buffer to DEFAULT_MTU bytes, pad TX */
+       /* Truncate RX buffer to SKB_MTU bytes, pad TX */
        regmap_write(ctrl->map, ctrl->r->dma_if_ctrl,
-                    (DEFAULT_MTU << 16) | RX_TRUNCATE_EN_83XX | TX_PAD_EN_838X);
+                    (SKB_MTU << 16) | RX_TRUNCATE_EN_83XX | TX_PAD_EN_838X);
 
        rteth_enable_all_rx_irqs(ctrl);
 
@@ -570,7 +579,7 @@ static void rteth_838x_hw_en_rxtx(struct rteth_ctrl *ctrl)
 static void rteth_839x_hw_en_rxtx(struct rteth_ctrl *ctrl)
 {
        /* Setup CPU-Port: RX Buffer */
-       regmap_write(ctrl->map, ctrl->r->dma_if_ctrl, (DEFAULT_MTU << 5) | RX_TRUNCATE_EN_83XX);
+       regmap_write(ctrl->map, ctrl->r->dma_if_ctrl, (SKB_MTU << 5) | RX_TRUNCATE_EN_83XX);
 
        rteth_enable_all_rx_irqs(ctrl);
 
@@ -593,8 +602,8 @@ static void rteth_839x_hw_en_rxtx(struct rteth_ctrl *ctrl)
 
 static void rteth_930x_hw_en_rxtx(struct rteth_ctrl *ctrl)
 {
-       /* Setup CPU-Port: RX Buffer truncated at DEFAULT_MTU Bytes */
-       regmap_write(ctrl->map, ctrl->r->dma_if_ctrl, (DEFAULT_MTU << 16) | RX_TRUNCATE_EN_93XX);
+       /* Setup CPU-Port: RX Buffer truncated at SKB_MTU Bytes */
+       regmap_write(ctrl->map, ctrl->r->dma_if_ctrl, (SKB_MTU << 16) | RX_TRUNCATE_EN_93XX);
 
        rteth_enable_all_rx_irqs(ctrl);
 
@@ -610,8 +619,8 @@ static void rteth_930x_hw_en_rxtx(struct rteth_ctrl *ctrl)
 
 static void rteth_931x_hw_en_rxtx(struct rteth_ctrl *ctrl)
 {
-       /* Setup CPU-Port: RX Buffer truncated at DEFAULT_MTU Bytes */
-       regmap_write(ctrl->map, ctrl->r->dma_if_ctrl, (DEFAULT_MTU << 16) | RX_TRUNCATE_EN_93XX);
+       /* Setup CPU-Port: RX Buffer truncated at SKB_MTU Bytes */
+       regmap_write(ctrl->map, ctrl->r->dma_if_ctrl, (SKB_MTU << 16) | RX_TRUNCATE_EN_93XX);
 
        rteth_enable_all_rx_irqs(ctrl);
 
@@ -1118,6 +1127,7 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget)
        dma_addr_t packet_dma;
        struct sk_buff *skb;
        struct dsa_tag tag;
+       bool is_tail;
 
        while (work_done < budget) {
                slot = ctrl->rx_data[ring].slot;
@@ -1129,6 +1139,9 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget)
 
                packet = &ctrl->rx_data[ring].packet[slot];
                len = packet->len - ETH_FCS_LEN;
+               is_tail = !packet->more;
+               if (is_tail)
+                       work_done++;
 
                if (unlikely(len > SKB_FRAG_SIZE)) {
                        netdev_err(dev, "invalid packet with %d bytes received\n", len);
@@ -1189,7 +1202,6 @@ recycle:
                dma_wmb();
                ctrl->rx_data[ring].ring[slot] = packet_dma | RING_OWN_HW;
                ctrl->rx_data[ring].slot = (slot + 1) % RTETH_RX_RING_SIZE;
-               work_done++;
        }
 
        spin_lock(&ctrl->rx_lock);
@@ -1702,7 +1714,7 @@ static int rteth_probe(struct platform_device *pdev)
 
        dev->ethtool_ops = &rteth_ethtool_ops;
        dev->min_mtu = ETH_ZLEN;
-       dev->max_mtu = DEFAULT_MTU;
+       dev->max_mtu = SKB_MTU;
        dev->features = NETIF_F_RXCSUM;
        dev->hw_features = NETIF_F_RXCSUM;
        dev->netdev_ops = ctrl->r->netdev_ops;
index 9d6837e915bfc8dbc7fd1a7cb70c33802e0971f3..052dcf21efdbfdf580d76af0fd5269fd05ba829c 100644 (file)
 
 #define RTL93XX_CPU_TAG1_IGNORE_STP_MASK       GENMASK(2, 2)
 
-/* Default MTU with jumbo frames support */
-#define DEFAULT_MTU 9000
-
 struct p_hdr;
 struct dsa_tag;
 struct rteth_ctrl;