]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: l3: relocate find_slot()
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Sun, 28 Jun 2026 08:46:49 +0000 (10:46 +0200)
committerMarkus Stockhausen <markus.stockhausen@gmx.de>
Mon, 29 Jun 2026 16:17:08 +0000 (18:17 +0200)
Move find_slot() and its helpers into the new layer 3 ecosystem.

Link: https://github.com/openwrt/openwrt/pull/23979
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c
target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h
target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h
target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c

index 5c95f06420eaef4531c719603c2c83f764e332ff..f82e36ac20d77331a3a15166eacd3b81c45ac38a 100644 (file)
@@ -95,6 +95,33 @@ static void otto_l3_839x_route_write(struct otto_l3_ctrl *ctrl, int idx, struct
        rtl_table_release(r);
 }
 
+__maybe_unused
+static u32 otto_l3_930x_hash4(u32 ip, int algorithm, bool move_dip)
+{
+       u32 s0, s1, pH;
+       u32 rows[4];
+       u32 hash;
+
+       memset(rows, 0, sizeof(rows));
+
+       rows[0] = HASH_PICK(ip, 27, 5);
+       rows[1] = HASH_PICK(ip, 18, 9);
+       rows[2] = HASH_PICK(ip, 9, 9);
+
+       if (!move_dip)
+               rows[3] = HASH_PICK(ip, 0, 9);
+
+       if (!algorithm) {
+               hash = rows[0] ^ rows[1] ^ rows[2] ^ rows[3];
+       } else {
+               s0 = rows[0] + rows[1] + rows[2];
+               s1 = (s0 & 0x1ff) + ((s0 & (0x1ff << 9)) >> 9);
+               pH = (s1 & 0x1ff) + ((s1 & (0x1ff << 9)) >> 9);
+               hash = pH ^ rows[3];
+       }
+       return hash;
+}
+
 /*
  * Get the Destination-MAC of an L3 egress interface or the Source MAC for routed packets
  * from the SoC's L3_EGR_INTF_MAC table. Indexes 0-2047 are DMACs, 2048+ are SMACs
@@ -115,6 +142,55 @@ static u64 otto_l3_930x_get_egress_mac(struct otto_l3_ctrl *ctrl, u32 idx)
        return mac;
 }
 
+/* Read a host route entry from the table using its index. Only IPv4 and IPv6 unicast supported */
+__maybe_unused
+static void otto_l3_930x_host_route_read(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt)
+{
+       struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 1);
+       u32 v;
+
+       idx = ((idx / 6) * 8) + (idx % 6);
+
+       rtl_table_read(r, idx);
+       /* The table has a size of 5 (for UC, 11 for MC) registers */
+       v = sw_r32(rtl_table_data(r, 0));
+       rt->attr.valid = !!(v & BIT(31));
+       if (!rt->attr.valid)
+               goto out;
+       rt->attr.type = (v >> 29) & 0x3;
+       switch (rt->attr.type) {
+       case 0: /* IPv4 Unicast route */
+               rt->dst_ip = sw_r32(rtl_table_data(r, 4));
+               break;
+       case 2: /* IPv6 Unicast route */
+               ipv6_addr_set(&rt->dst_ip6,
+                             sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 2)),
+                             sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 0)));
+               break;
+       case 1: /* IPv4 Multicast route */
+       case 3: /* IPv6 Multicast route */
+               dev_warn(ctrl->dev, "route type not supported\n");
+               goto out;
+       }
+
+       rt->attr.hit = !!(v & BIT(20));
+       rt->attr.dst_null = !!(v & BIT(19));
+       rt->attr.action = (v >> 17) & 3;
+       rt->nh.id = (v >> 6) & 0x7ff;
+       rt->attr.ttl_dec = !!(v & BIT(5));
+       rt->attr.ttl_check = !!(v & BIT(4));
+       rt->attr.qos_as = !!(v & BIT(3));
+       rt->attr.qos_prio =  v & 0x7;
+       dev_dbg(ctrl->dev, "index %d is valid: %d\n", idx, rt->attr.valid);
+       dev_dbg(ctrl->dev, "next_hop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n",
+               rt->nh.id, rt->attr.hit, rt->attr.action, rt->attr.ttl_dec, rt->attr.ttl_check,
+               rt->attr.dst_null);
+       dev_dbg(ctrl->dev, "Destination: %pI4\n", &rt->dst_ip);
+
+out:
+       rtl_table_release(r);
+}
+
 /* Write a host route entry from the table using its index. Only unicast routes supported */
 __maybe_unused
 static void otto_l3_930x_host_route_write(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt)
@@ -168,6 +244,41 @@ out:
        rtl_table_release(r);
 }
 
+__maybe_unused
+static int otto_l3_930x_find_slot(struct otto_l3_ctrl *ctrl, struct otto_l3_route *rt, bool must_exist)
+{
+       int slot_width, algorithm, addr, idx;
+       struct otto_l3_route route_entry;
+       u32 hash;
+
+       /* IPv6 entries take up 3 slots */
+       slot_width = (rt->attr.type == 0) || (rt->attr.type == 2) ? 1 : 3;
+
+       for (int t = 0; t < 2; t++) {
+               algorithm = (sw_r32(RTL930X_L3_HOST_TBL_CTRL) >> (2 + t)) & 0x1;
+               hash = otto_l3_930x_hash4(rt->dst_ip, algorithm, false);
+
+               dev_dbg(ctrl->dev, "table %d, algorithm %d, hash %04x\n", t, algorithm, hash);
+
+               for (int s = 0; s < 6; s += slot_width) {
+                       addr = (t << 12) | ((hash & 0x1ff) << 3) | s;
+                       dev_dbg(ctrl->dev, "physical address %d\n", addr);
+                       idx = ((addr / 8) * 6) + (addr % 8);
+                       dev_dbg(ctrl->dev, "logical address %d\n", idx);
+
+                       otto_l3_930x_host_route_read(ctrl, idx, &route_entry);
+                       dev_dbg(ctrl->dev, "route valid %d, route dest: %pI4, hit %d\n",
+                               rt->attr.valid, &rt->dst_ip, rt->attr.hit);
+                       if (!must_exist && rt->attr.valid)
+                               return idx;
+                       if (must_exist && route_entry.dst_ip == rt->dst_ip)
+                               return idx;
+               }
+       }
+
+       return -1;
+}
+
 /*
  * Reads a MAC entry for L3 termination as entry point for routing from the hardware table.
  * idx is the index into the L3_ROUTER_MAC table
@@ -693,7 +804,7 @@ static int otto_l3_nexthop_update(struct otto_l3_ctrl *ctrl, __be32 ip_addr, u64
                r->pr.dip_m = inet_make_mask(r->prefix_len);
 
                if (r->is_host_route) {
-                       int slot = priv->r->find_l3_slot(r, false);
+                       int slot = ctrl->cfg->find_slot(ctrl, r, false);
 
                        dev_info(ctrl->dev, "Got slot for route: %d\n", slot);
                        ctrl->cfg->host_route_write(ctrl, slot, r);
@@ -769,7 +880,7 @@ static void otto_l3_route_remove(struct otto_l3_ctrl *ctrl, struct otto_l3_route
                dev_warn(ctrl->dev, "Could not remove route\n");
 
        if (r->is_host_route) {
-               id = priv->r->find_l3_slot(r, false);
+               id = ctrl->cfg->find_slot(ctrl, r, false);
                dev_dbg(ctrl->dev, "Got id for host route: %d\n", id);
                r->attr.valid = false;
                ctrl->cfg->host_route_write(ctrl, id, r);
@@ -955,7 +1066,7 @@ static int otto_l3_fib_add_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifi
                        route->attr.action = ROUTE_ACT_TRAP2CPU;
                        route->attr.type = 0;
 
-                       slot = priv->r->find_l3_slot(route, false);
+                       slot = ctrl->cfg->find_slot(ctrl, route, false);
                        dev_dbg(ctrl->dev, "Got slot for route: %d\n", slot);
                        ctrl->cfg->host_route_write(ctrl, slot, route);
                }
@@ -1201,6 +1312,7 @@ const struct otto_l3_config otto_l3_839x_cfg = {
 
 const struct otto_l3_config otto_l3_930x_cfg = {
 #ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD
+       .find_slot = otto_l3_930x_find_slot,
        .get_egress_mac = otto_l3_930x_get_egress_mac,
        .set_egress_intf = otto_l3_930x_set_egress_intf,
        .host_route_write = otto_l3_930x_host_route_write,
index 8fb683e73f313a896580d321c20fa88d2c36e36a..ebdedcac205df16d5b1a138699eabe716b06dfe0 100644 (file)
@@ -8,6 +8,8 @@
 #define MAX_HOST_ROUTES                1536
 #define MAX_INTERFACES         100
 
+#define HASH_PICK(val, lsb, len) ((val & (((1 << len) - 1) << lsb)) >> lsb)
+
 /* An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point
  * for the L3 routing system. Packets arriving and matching an entry in this table
  * will be considered for routing.
@@ -43,6 +45,7 @@ struct otto_l3_intf {
 };
 
 struct otto_l3_config {
+       int (*find_slot)(struct otto_l3_ctrl *ctrl, struct otto_l3_route *rt, bool must_exist);
        void (*set_egress_intf)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_intf *intf);
        u64 (*get_egress_mac)(struct otto_l3_ctrl *ctrl, u32 idx);
        void (*host_route_write)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt);
index ff6ad3af734cb1945946ce9f2a78443a941cdd18..863c3603bf39f94d0b0e350c2436b72837940e21 100644 (file)
@@ -1403,7 +1403,6 @@ struct rtldsa_config {
        void (*packet_cntr_clear)(int counter);
        int (*l3_setup)(struct rtl838x_switch_priv *priv);
        void (*set_l3_egress_mac)(u32 idx, u64 mac);
-       int (*find_l3_slot)(struct otto_l3_route *rt, bool must_exist);
        void (*set_receive_management_action)(int port, rma_ctrl_t type, action_type_t action);
        void (*led_init)(struct rtl838x_switch_priv *priv);
        void (*qos_init)(struct rtl838x_switch_priv *priv);
index 6ab23cd69f117a95cb5d206326751a1d190b56f3..e2eb9a2e1221c753aaf35e08689b06bd03db0677 100644 (file)
@@ -1184,34 +1184,6 @@ static void rtl930x_init_eee(struct rtl838x_switch_priv *priv, bool enable)
 
 #ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD
 
-#define HASH_PICK(val, lsb, len)   ((val & (((1 << len) - 1) << lsb)) >> lsb)
-
-static u32 rtl930x_l3_hash4(u32 ip, int algorithm, bool move_dip)
-{
-       u32 rows[4];
-       u32 hash;
-       u32 s0, s1, pH;
-
-       memset(rows, 0, sizeof(rows));
-
-       rows[0] = HASH_PICK(ip, 27, 5);
-       rows[1] = HASH_PICK(ip, 18, 9);
-       rows[2] = HASH_PICK(ip, 9, 9);
-
-       if (!move_dip)
-               rows[3] = HASH_PICK(ip, 0, 9);
-
-       if (!algorithm) {
-               hash = rows[0] ^ rows[1] ^ rows[2] ^ rows[3];
-       } else {
-               s0 = rows[0] + rows[1] + rows[2];
-               s1 = (s0 & 0x1ff) + ((s0 & (0x1ff << 9)) >> 9);
-               pH = (s1 & 0x1ff) + ((s1 & (0x1ff << 9)) >> 9);
-               hash = pH ^ rows[3];
-       }
-       return hash;
-}
-
 // Currently not used
 // static u32 rtl930x_l3_hash6(struct in6_addr *ip6, int algorithm, bool move_dip)
 // {
@@ -1265,92 +1237,6 @@ static u32 rtl930x_l3_hash4(u32 ip, int algorithm, bool move_dip)
 //     return hash;
 // }
 
-/* Read a host route entry from the table using its index
- * We currently only support IPv4 and IPv6 unicast route
- */
-static void rtl930x_host_route_read(int idx, struct otto_l3_route *rt)
-{
-       u32 v;
-       /* Read L3_HOST_ROUTE_IPUC table (1) via register RTL9300_TBL_1 */
-       struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 1);
-
-       idx = ((idx / 6) * 8) + (idx % 6);
-
-       pr_debug("In %s, physical index %d\n", __func__, idx);
-       rtl_table_read(r, idx);
-       /* The table has a size of 5 (for UC, 11 for MC) registers */
-       v = sw_r32(rtl_table_data(r, 0));
-       rt->attr.valid = !!(v & BIT(31));
-       if (!rt->attr.valid)
-               goto out;
-       rt->attr.type = (v >> 29) & 0x3;
-       switch (rt->attr.type) {
-       case 0: /* IPv4 Unicast route */
-               rt->dst_ip = sw_r32(rtl_table_data(r, 4));
-               break;
-       case 2: /* IPv6 Unicast route */
-               ipv6_addr_set(&rt->dst_ip6,
-                             sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 2)),
-                             sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 0)));
-               break;
-       case 1: /* IPv4 Multicast route */
-       case 3: /* IPv6 Multicast route */
-               pr_warn("%s: route type not supported\n", __func__);
-               goto out;
-       }
-
-       rt->attr.hit = !!(v & BIT(20));
-       rt->attr.dst_null = !!(v & BIT(19));
-       rt->attr.action = (v >> 17) & 3;
-       rt->nh.id = (v >> 6) & 0x7ff;
-       rt->attr.ttl_dec = !!(v & BIT(5));
-       rt->attr.ttl_check = !!(v & BIT(4));
-       rt->attr.qos_as = !!(v & BIT(3));
-       rt->attr.qos_prio =  v & 0x7;
-       pr_debug("%s: index %d is valid: %d\n", __func__, idx, rt->attr.valid);
-       pr_debug("%s: next_hop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n",
-                __func__, rt->nh.id, rt->attr.hit, rt->attr.action, rt->attr.ttl_dec, rt->attr.ttl_check,
-                rt->attr.dst_null);
-       pr_debug("%s: Destination: %pI4\n", __func__, &rt->dst_ip);
-
-out:
-       rtl_table_release(r);
-}
-
-static int rtl930x_find_l3_slot(struct otto_l3_route *rt, bool must_exist)
-{
-       int slot_width, algorithm, addr, idx;
-       u32 hash;
-       struct otto_l3_route route_entry;
-
-       /* IPv6 entries take up 3 slots */
-       slot_width = (rt->attr.type == 0) || (rt->attr.type == 2) ? 1 : 3;
-
-       for (int t = 0; t < 2; t++) {
-               algorithm = (sw_r32(RTL930X_L3_HOST_TBL_CTRL) >> (2 + t)) & 0x1;
-               hash = rtl930x_l3_hash4(rt->dst_ip, algorithm, false);
-
-               pr_debug("%s: table %d, algorithm %d, hash %04x\n", __func__, t, algorithm, hash);
-
-               for (int s = 0; s < 6; s += slot_width) {
-                       addr = (t << 12) | ((hash & 0x1ff) << 3) | s;
-                       pr_debug("%s physical address %d\n", __func__, addr);
-                       idx = ((addr / 8) * 6) + (addr % 8);
-                       pr_debug("%s logical address %d\n", __func__, idx);
-
-                       rtl930x_host_route_read(idx, &route_entry);
-                       pr_debug("%s route valid %d, route dest: %pI4, hit %d\n", __func__,
-                                rt->attr.valid, &rt->dst_ip, rt->attr.hit);
-                       if (!must_exist && rt->attr.valid)
-                               return idx;
-                       if (must_exist && route_entry.dst_ip == rt->dst_ip)
-                               return idx;
-               }
-       }
-
-       return -1;
-}
-
 // Currently not used
 // static int rtl930x_l3_mtu_del(struct rtl838x_switch_priv *priv, int mtu)
 // {
@@ -2468,7 +2354,6 @@ const struct rtldsa_config rtldsa_930x_cfg = {
 #ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD
        .l3_setup = rtl930x_l3_setup,
        .set_l3_egress_mac = rtl930x_set_l3_egress_mac,
-       .find_l3_slot = rtl930x_find_l3_slot,
 #endif
        .led_init = rtl930x_led_init,
        .enable_learning = rtldsa_930x_enable_learning,