realtek: rtl930x: Add support for trapping management frames
authorHarshal Gohel <[email protected]>
Fri, 8 Aug 2025 15:31:03 +0000 (17:31 +0200)
committerHauke Mehrtens <[email protected]>
Tue, 26 Aug 2025 21:44:08 +0000 (23:44 +0200)
Driver needs to configure management frame actions
To support LLDP, EAPOL or MSTP, which needs to be trapped to the CPU
instead of being forwarded

Signed-off-by: Harshal Gohel <[email protected]>
Signed-off-by: Sharadanand Karanjkar <[email protected]>
Link: https://github.com/openwrt/openwrt/pull/19571
Signed-off-by: Hauke Mehrtens <[email protected]>
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl83xx.h
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c

index 544f693883fca1b5da1f7bf9c53424c0c2c482c5..5ec3905a80c26428a770b31f6e1ef5df46022b67 100644 (file)
@@ -471,6 +471,7 @@ typedef enum {
 #define RTL931X_RMA_LLDP_CTRL                  (0x8918)
 
 #define RTL930X_RMA_EAPOL_CTRL                 (0x9F08)
+#define RTL930X_SPCL_TRAP_PORT_CTRL            (0xA1A0)
 #define RTL931X_RMA_EAPOL_CTRL                 (0x8930)
 #define RTL931X_TRAP_ARP_GRAT_PORT_ACT         (0x8C04)
 
index ef5230d92edadc1bf03d3a432236e48a2b60d0d1..6d7f154129a9599f53ebbf4c14c8df731ff468a5 100644 (file)
@@ -209,7 +209,10 @@ void rtl9300_dump_debug(void);
 void rtl930x_pie_rule_dump_raw(u32 r[]);
 
 void rtl931x_print_matrix(void);
+
+void rtldsa_930x_set_receive_management_action(int port, rma_ctrl_t type, action_type_t action);
 void rtl931x_set_receive_management_action(int port, rma_ctrl_t type, action_type_t action);
+
 void rtl931x_sw_init(struct rtl838x_switch_priv *priv);
 
 #endif /* _NET_DSA_RTL83XX_H */
index c84ed6cca0987fe321518f5e2058f2523e1abe96..a421db4d0dfa802100788bcabc1bc0afff3dddfa 100644 (file)
@@ -657,6 +657,85 @@ static void rtl930x_write_mcast_pmask(int idx, u64 portmask)
        rtl_table_release(q);
 }
 
+void rtldsa_930x_set_receive_management_action(int port, rma_ctrl_t type,
+                                              action_type_t action)
+{
+       u32 shift;
+       u32 value;
+       u32 reg;
+
+       /* hack for value mapping */
+       if (type == GRATARP && action == COPY2CPU)
+               action = TRAP2MASTERCPU;
+
+       /* PTP doesn't allow to flood to all ports */
+       if (action == FLOODALL &&
+           (type == PTP || type == PTP_UDP || type == PTP_ETH2)) {
+               pr_warn("%s: Port flooding not supported for PTP\n", __func__);
+               return;
+       }
+
+       switch(action) {
+       case FORWARD:
+               value = 0;
+               break;
+       case DROP:
+               value = 1;
+               break;
+       case TRAP2CPU:
+               value = 2;
+               break;
+       case TRAP2MASTERCPU:
+               value = 3;
+               break;
+       case FLOODALL:
+               value = 4;
+               break;
+       default:
+               return;
+       }
+
+       switch(type) {
+       case BPDU:
+               reg = RTL930X_RMA_BPDU_CTRL + (port / 10) * 4;
+               shift = (port % 10) * 3;
+               sw_w32_mask(GENMASK(shift + 2, shift), value << shift, reg);
+               break;
+       case PTP:
+               reg = RTL930X_RMA_PTP_CTRL + port * 4;
+
+               /* udp */
+               sw_w32_mask(GENMASK(3, 2), value << 2, reg);
+
+               /* eth2 */
+               sw_w32_mask(GENMASK(1, 0), value, reg);
+               break;
+       case PTP_UDP:
+               reg = RTL930X_RMA_PTP_CTRL + port * 4;
+               sw_w32_mask(GENMASK(3, 2), value << 2, reg);
+               break;
+       case PTP_ETH2:
+               reg = RTL930X_RMA_PTP_CTRL + port * 4;
+               sw_w32_mask(GENMASK(1, 0), value, reg);
+               break;
+       case LLDP:
+               reg = RTL930X_RMA_LLDP_CTRL + (port / 10) * 4;
+               shift = (port % 10) * 3;
+               sw_w32_mask(GENMASK(shift + 2, shift), value << shift, reg);
+               break;
+       case EAPOL:
+               reg = RTL930X_RMA_EAPOL_CTRL + (port / 10) * 4;
+               shift = (port % 10) * 3;
+               sw_w32_mask(GENMASK(shift + 2, shift), value << shift, reg);
+               break;
+       case GRATARP:
+               reg = RTL930X_SPCL_TRAP_PORT_CTRL + (port / 16) * 4;
+               shift = (port % 16) * 2;
+               sw_w32_mask(GENMASK(shift + 1, shift), value << shift, reg);
+               break;
+       }
+}
+
 static u64 rtl930x_traffic_get(int source)
 {
        u32 v;
@@ -2419,4 +2498,5 @@ const struct rtl838x_reg rtl930x_reg = {
        .led_init = rtl930x_led_init,
        .enable_learning = rtldsa_930x_enable_learning,
        .enable_flood = rtldsa_930x_enable_flood,
+       .set_receive_management_action = rtldsa_930x_set_receive_management_action,
 };