]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: dsa: consolidate switch_irq() 22273/head
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Wed, 4 Mar 2026 18:16:23 +0000 (19:16 +0100)
committerHauke Mehrtens <hauke@hauke-m.de>
Sat, 14 Mar 2026 21:48:37 +0000 (22:48 +0100)
The dsa irq handler works always in the same way for all SoCs.

- Read register ISR_PORT_LINK_STS_CHG to determine the ports that
  triggered the irq.
- Write the read value back to the register to confirm the irq
- Read link status via MAC_LINK_STS
- Trigger dsa_port_phylink_mac_change() for each changed port

Currently each SoC has its own implementation. Drop that in
favour of a generic implementation that makes use of the existing
bit register read/write helpers.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/22273
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl83xx.h
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c

index 59c1444e6e63557ccb1cde1dc8f2bb0e9d9e4889..3f98a20f95d42a4fdd1a512556dae38db2d66004 100644 (file)
@@ -1532,6 +1532,27 @@ static int rtl83xx_fib_event(struct notifier_block *this, unsigned long event, v
        return NOTIFY_DONE;
 }
 
+static irqreturn_t rtldsa_switch_irq(int irq, void *dev_id)
+{
+       struct rtl838x_switch_priv *priv;
+       struct dsa_switch *ds = dev_id;
+       u64 link, ports;
+
+       priv = ds->priv;
+       ports = priv->r->get_port_reg_le(priv->r->isr_port_link_sts_chg);
+       priv->r->set_port_reg_le(ports, priv->r->isr_port_link_sts_chg);
+
+       /* read latched */
+       link = priv->r->get_port_reg_le(priv->r->mac_link_sts);
+       link = priv->r->get_port_reg_le(priv->r->mac_link_sts);
+
+       for (int port = 0; port < priv->cpu_port; port++)
+               if (ports & BIT_ULL(port))
+                       dsa_port_phylink_mac_change(ds, port, link & BIT_ULL(port));
+
+       return IRQ_HANDLED;
+}
+
 /*
  * TODO: This check is usually built into the DSA initialization functions. After carving
  * out the mdio driver from the ethernet driver, there are two drivers that must be loaded
@@ -1699,24 +1720,8 @@ static int rtl83xx_sw_probe(struct platform_device *pdev)
 
        priv->link_state_irq = platform_get_irq(pdev, 0);
        pr_info("LINK state irq: %d\n", priv->link_state_irq);
-       switch (priv->family_id) {
-       case RTL8380_FAMILY_ID:
-               err = request_irq(priv->link_state_irq, rtl838x_switch_irq,
-                                 IRQF_SHARED, "rtl838x-link-state", priv->ds);
-               break;
-       case RTL8390_FAMILY_ID:
-               err = request_irq(priv->link_state_irq, rtl839x_switch_irq,
-                                 IRQF_SHARED, "rtl839x-link-state", priv->ds);
-               break;
-       case RTL9300_FAMILY_ID:
-               err = request_irq(priv->link_state_irq, rtldsa_930x_switch_irq,
-                                 IRQF_SHARED, "rtl930x-link-state", priv->ds);
-               break;
-       case RTL9310_FAMILY_ID:
-               err = request_irq(priv->link_state_irq, rtl931x_switch_irq,
-                                 IRQF_SHARED, "rtl931x-link-state", priv->ds);
-               break;
-       }
+       err = request_irq(priv->link_state_irq, rtldsa_switch_irq,
+                         IRQF_SHARED, "rtldsa-link-state", priv->ds);
        if (err) {
                dev_err(dev, "Error setting up switch interrupt.\n");
                /* Need to free allocated switch here */
index f9756dcc7e21c999900e59a9c392f934d54c3b5f..4cdcfc50a5bc5f4610dbee2513117201abc24d9e 100644 (file)
@@ -1898,27 +1898,3 @@ const struct rtldsa_config rtldsa_838x_cfg = {
        .lag_set_port_members = rtldsa_838x_lag_set_port_members,
        .lag_setup_algomask = rtldsa_83xx_lag_setup_algomask,
 };
-
-irqreturn_t rtl838x_switch_irq(int irq, void *dev_id)
-{
-       struct dsa_switch *ds = dev_id;
-       u32 status = sw_r32(RTL838X_ISR_GLB_SRC);
-       u32 ports = sw_r32(RTL838X_ISR_PORT_LINK_STS_CHG);
-       u32 link;
-
-       /* Clear status */
-       sw_w32(ports, RTL838X_ISR_PORT_LINK_STS_CHG);
-       pr_debug("RTL8380 Link change: status: %x, ports %x\n", status, ports);
-
-       for (int i = 0; i < 28; i++) {
-               if (ports & BIT(i)) {
-                       link = sw_r32(RTL838X_MAC_LINK_STS);
-                       if (link & BIT(i))
-                               dsa_port_phylink_mac_change(ds, i, true);
-                       else
-                               dsa_port_phylink_mac_change(ds, i, false);
-               }
-       }
-
-       return IRQ_HANDLED;
-}
index a4bd5a914e51e22aabb844d6ce4181b22be34308..3fab93ac696bc4d3855f394690dce41d377836a9 100644 (file)
@@ -708,30 +708,6 @@ static void rtl839x_set_static_move_action(int port, bool forward)
                    RTL839X_L2_PORT_STATIC_MV_ACT(port));
 }
 
-irqreturn_t rtl839x_switch_irq(int irq, void *dev_id)
-{
-       struct dsa_switch *ds = dev_id;
-       u32 status = sw_r32(RTL839X_ISR_GLB_SRC);
-       u64 ports = rtl839x_get_port_reg_le(RTL839X_ISR_PORT_LINK_STS_CHG);
-       u64 link;
-
-       /* Clear status */
-       rtl839x_set_port_reg_le(ports, RTL839X_ISR_PORT_LINK_STS_CHG);
-       pr_debug("RTL8390 Link change: status: %x, ports %llx\n", status, ports);
-
-       for (int i = 0; i < RTL839X_CPU_PORT; i++) {
-               if (ports & BIT_ULL(i)) {
-                       link = rtl839x_get_port_reg_le(RTL839X_MAC_LINK_STS);
-                       if (link & BIT_ULL(i))
-                               dsa_port_phylink_mac_change(ds, i, true);
-                       else
-                               dsa_port_phylink_mac_change(ds, i, false);
-               }
-       }
-
-       return IRQ_HANDLED;
-}
-
 static void
 rtldsa_839x_vlan_profile_dump(struct rtl838x_switch_priv *priv, int idx)
 {
index 7237aa862c73b6fd8089e006640cf36eed9e7a8e..cf24ecc1befa6c06036e2b37d5c864e077cef499 100644 (file)
@@ -159,23 +159,18 @@ int rtl838x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate
 
 /* RTL838x-specific */
 u32 rtl838x_hash(struct rtl838x_switch_priv *priv, u64 seed);
-irqreturn_t rtl838x_switch_irq(int irq, void *dev_id);
 void rtldsa_838x_print_matrix(void);
 
 /* RTL839x-specific */
 u32 rtl839x_hash(struct rtl838x_switch_priv *priv, u64 seed);
-irqreturn_t rtl839x_switch_irq(int irq, void *dev_id);
 void rtl839x_exec_tbl2_cmd(u32 cmd);
 void rtldsa_839x_print_matrix(void);
 
 /* RTL930x-specific */
 u32 rtl930x_hash(struct rtl838x_switch_priv *priv, u64 seed);
-irqreturn_t rtldsa_930x_switch_irq(int irq, void *dev_id);
-irqreturn_t rtl839x_switch_irq(int irq, void *dev_id);
 void rtldsa_930x_print_matrix(void);
 
 /* RTL931x-specific */
-irqreturn_t rtl931x_switch_irq(int irq, void *dev_id);
 void rtldsa_931x_print_matrix(void);
 
 int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_lag_upper_info *info);
index b258f05ba7d847b233b0426ae19d5f3375b285f5..1c428814bb56a07b3cb786206a96062fe12a126a 100644 (file)
@@ -1112,29 +1112,6 @@ void rtl9300_dump_debug(void)
        );
 }
 
-irqreturn_t rtldsa_930x_switch_irq(int irq, void *dev_id)
-{
-       struct dsa_switch *ds = dev_id;
-       struct rtl838x_switch_priv *priv = ds->priv;
-       unsigned long ports = sw_r32(RTL930X_ISR_PORT_LINK_STS_CHG);
-       unsigned int i;
-       u32 link;
-
-       /* Clear status */
-       sw_w32(ports, RTL930X_ISR_PORT_LINK_STS_CHG);
-
-       /* Read the register twice because of issues with latency at least
-        * with the external RTL8226 PHY on the XGS1210
-        */
-       link = sw_r32(RTL930X_MAC_LINK_STS);
-       link = sw_r32(RTL930X_MAC_LINK_STS);
-
-       for_each_set_bit(i, &ports, priv->cpu_port)
-               dsa_port_phylink_mac_change(ds, i, link & BIT(i));
-
-       return IRQ_HANDLED;
-}
-
 /* Calculate both the block 0 and the block 1 hash, and return in
  * lower and higher word of the return value since only 12 bit of
  * the hash are significant
index fbefb3c79bd7ecc23e444bb39381c58edd31dbd9..2e31c10cdc108b186152cc9ac4055693af54336e 100644 (file)
@@ -462,37 +462,6 @@ static int rtldsa_931x_port_rate_police_del(struct dsa_switch *ds, int port,
        return 0;
 }
 
-irqreturn_t rtl931x_switch_irq(int irq, void *dev_id)
-{
-       struct dsa_switch *ds = dev_id;
-       u32 status = sw_r32(RTL931X_ISR_GLB_SRC);
-       u64 ports = rtl839x_get_port_reg_le(RTL931X_ISR_PORT_LINK_STS_CHG);
-       u64 link;
-
-       /* Clear status */
-       rtl839x_set_port_reg_le(ports, RTL931X_ISR_PORT_LINK_STS_CHG);
-       pr_debug("RTL931X Link change: status: %x, ports %016llx\n", status, ports);
-
-       link = rtl839x_get_port_reg_le(RTL931X_MAC_LINK_STS);
-       /* Must re-read this to get correct status */
-       link = rtl839x_get_port_reg_le(RTL931X_MAC_LINK_STS);
-       pr_debug("RTL931X Link change: status: %x, link status %016llx\n", status, link);
-
-       for (int i = 0; i < 56; i++) {
-               if (ports & BIT_ULL(i)) {
-                       if (link & BIT_ULL(i)) {
-                               pr_debug("%s port %d up\n", __func__, i);
-                               dsa_port_phylink_mac_change(ds, i, true);
-                       } else {
-                               pr_debug("%s port %d down\n", __func__, i);
-                               dsa_port_phylink_mac_change(ds, i, false);
-                       }
-               }
-       }
-
-       return IRQ_HANDLED;
-}
-
 void rtldsa_931x_print_matrix(void)
 {
        struct table_reg *r = rtl_table_get(RTL9310_TBL_2, 1);