From b98061ac6e30d2966a3af2d8ceb171398dc121db Mon Sep 17 00:00:00 2001 From: Gennaro Cimmino Date: Sun, 11 Oct 2026 11:11:13 +0200 Subject: [PATCH] realtek: pie: rtl839x: keep the first 512 rules for L3 L3 is to keep its RTL839x routes longest prefix first, the way the RTL930x prefix table holds them, so it needs rules that nothing else hands out and that it writes in place. Mark blocks 0-3 as used, so rtl839x_pie_rule_add() never returns one of them, and add a writer for them that takes the template of the block holding the IPv4 destination. Until L3 uses the writer, its rules come from rtl839x_pie_rule_add() from block 4 on, where template 2 holds the destination too. Nothing else adds RTL839x rules: tc offload is wired for RTL93xx only. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Gennaro Cimmino Link: https://github.com/openwrt/openwrt/pull/25805 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/pie.c | 36 +++++++++++++++++++ .../files-6.18/drivers/net/dsa/rtl83xx/pie.h | 5 +++ 2 files changed, 41 insertions(+) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/pie.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/pie.c index 0cca5426a13..2936d2db172 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/pie.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/pie.c @@ -1783,6 +1783,39 @@ void rtl839x_pie_rule_rm(struct rtl838x_switch_priv *priv, struct pie_rule *pr) clear_bit(idx, priv->pie_use_bm); } +/* L3 keeps its rules in an order of its own, the longest prefix first, so it + * writes each one in place, in the rules rtl839x_pie_init() keeps for it. A + * rule matches the IPv4 destination and takes the template of its block that + * has one. + */ +int rtl839x_pie_l3_rule_write(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr) +{ + int block = idx / PIE_BLOCK_SIZE; + int j, t; + + if (idx < 0 || idx >= RTL839X_PIE_L3_RULES) + return -EINVAL; + + for (j = 0; j < 2; j++) { + t = (sw_r32(RTL839X_ACL_BLK_TMPLTE_CTRL(block)) >> (j * 3)) & 0x7; + if (rtl839x_pie_templ_has(t, RTL839X_TEMPLATE_FIELD_DIP0)) + break; + } + if (j == 2) + return -EOPNOTSUPP; + + pr->tid = j; + pr->tid_m = 0x3; + pr->id = idx; + + mutex_lock(&priv->pie_mutex); + rtl839x_pie_lookup_enable(priv, idx); + rtl839x_pie_rule_write(priv, idx, pr); + mutex_unlock(&priv->pie_mutex); + + return 0; +} + void rtl839x_pie_init(struct rtl838x_switch_priv *priv) { u32 template_selectors; @@ -1802,6 +1835,9 @@ void rtl839x_pie_init(struct rtl838x_switch_priv *priv) /* Delete all present rules */ rtl839x_pie_rule_del(priv, 0, priv->r->n_pie_blocks * PIE_BLOCK_SIZE - 1); + /* Never hand out L3's rules, see rtl839x_pie_l3_rule_write() */ + bitmap_set(priv->pie_use_bm, 0, RTL839X_PIE_L3_RULES); + /* Enable predefined templates 0, 1 for blocks 0-2 */ template_selectors = 0 | (1 << 3); for (int i = 0; i < 3; i++) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/pie.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/pie.h index a7c809d4ab2..79ee2a8763e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/pie.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/pie.h @@ -14,6 +14,9 @@ #define MAX_PIE_ENTRIES (18 * PIE_BLOCK_SIZE) #define MAX_COUNTERS 2048 +/* The first rules of an RTL839x are L3's own, blocks 0-3 */ +#define RTL839X_PIE_L3_RULES (4 * PIE_BLOCK_SIZE) + struct pie_rule; struct rtl838x_switch_priv; @@ -32,6 +35,8 @@ int rtl839x_pie_rule_write(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr); int rtl839x_pie_rule_add(struct rtl838x_switch_priv *priv, struct pie_rule *pr); void rtl839x_pie_rule_rm(struct rtl838x_switch_priv *priv, struct pie_rule *pr); +int rtl839x_pie_l3_rule_write(struct rtl838x_switch_priv *priv, int idx, + struct pie_rule *pr); void rtl839x_pie_rule_dump(struct pie_rule *pr); void rtl930x_pie_init(struct rtl838x_switch_priv *priv);