net: dsa: b53: prevent standalone from trying to forward to other ports
authorJonas Gorski <jonas.gorski@gmail.com>
Thu, 8 May 2025 09:14:24 +0000 (11:14 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 13 May 2025 13:39:02 +0000 (15:39 +0200)
When bridged ports and standalone ports share a VLAN, e.g. via VLAN
uppers, or untagged traffic with a vlan unaware bridge, the ASIC will
still try to forward traffic to known FDB entries on standalone ports.
But since the port VLAN masks prevent forwarding to bridged ports, this
traffic will be dropped.

This e.g. can be observed in the bridge_vlan_unaware ping tests, where
this breaks pinging with learning on.

Work around this by enabling the simplified EAP mode on switches
supporting it for standalone ports, which causes the ASIC to redirect
traffic of unknown source MAC addresses to the CPU port.

Since standalone ports do not learn, there are no known source MAC
addresses, so effectively this redirects all incoming traffic to the CPU
port.

Fixes: ff39c2d68679 ("net: dsa: b53: Add bridge support")
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Link: https://patch.msgid.link/20250508091424.26870-1-jonas.gorski@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/dsa/b53/b53_common.c
drivers/net/dsa/b53/b53_regs.h

index 9eb39cf..7216eb8 100644 (file)
@@ -326,6 +326,26 @@ static void b53_get_vlan_entry(struct b53_device *dev, u16 vid,
        }
 }
 
+static void b53_set_eap_mode(struct b53_device *dev, int port, int mode)
+{
+       u64 eap_conf;
+
+       if (is5325(dev) || is5365(dev) || dev->chip_id == BCM5389_DEVICE_ID)
+               return;
+
+       b53_read64(dev, B53_EAP_PAGE, B53_PORT_EAP_CONF(port), &eap_conf);
+
+       if (is63xx(dev)) {
+               eap_conf &= ~EAP_MODE_MASK_63XX;
+               eap_conf |= (u64)mode << EAP_MODE_SHIFT_63XX;
+       } else {
+               eap_conf &= ~EAP_MODE_MASK;
+               eap_conf |= (u64)mode << EAP_MODE_SHIFT;
+       }
+
+       b53_write64(dev, B53_EAP_PAGE, B53_PORT_EAP_CONF(port), eap_conf);
+}
+
 static void b53_set_forwarding(struct b53_device *dev, int enable)
 {
        u8 mgmt;
@@ -586,6 +606,13 @@ int b53_setup_port(struct dsa_switch *ds, int port)
        b53_port_set_mcast_flood(dev, port, true);
        b53_port_set_learning(dev, port, false);
 
+       /* Force all traffic to go to the CPU port to prevent the ASIC from
+        * trying to forward to bridged ports on matching FDB entries, then
+        * dropping frames because it isn't allowed to forward there.
+        */
+       if (dsa_is_user_port(ds, port))
+               b53_set_eap_mode(dev, port, EAP_MODE_SIMPLIFIED);
+
        return 0;
 }
 EXPORT_SYMBOL(b53_setup_port);
@@ -2042,6 +2069,9 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
                pvlan |= BIT(i);
        }
 
+       /* Disable redirection of unknown SA to the CPU port */
+       b53_set_eap_mode(dev, port, EAP_MODE_BASIC);
+
        /* Configure the local port VLAN control membership to include
         * remote ports and update the local port bitmask
         */
@@ -2077,6 +2107,9 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge)
                        pvlan &= ~BIT(i);
        }
 
+       /* Enable redirection of unknown SA to the CPU port */
+       b53_set_eap_mode(dev, port, EAP_MODE_SIMPLIFIED);
+
        b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
        dev->ports[port].vlan_ctl_mask = pvlan;
 
index bfbcb66..5f7a0e5 100644 (file)
@@ -50,6 +50,9 @@
 /* Jumbo Frame Registers */
 #define B53_JUMBO_PAGE                 0x40
 
+/* EAP Registers */
+#define B53_EAP_PAGE                   0x42
+
 /* EEE Control Registers Page */
 #define B53_EEE_PAGE                   0x92
 
 #define   JMS_MIN_SIZE                 1518
 #define   JMS_MAX_SIZE                 9724
 
+/*************************************************************************
+ * EAP Page Registers
+ *************************************************************************/
+#define B53_PORT_EAP_CONF(i)           (0x20 + 8 * (i))
+#define  EAP_MODE_SHIFT                        51
+#define  EAP_MODE_SHIFT_63XX           50
+#define  EAP_MODE_MASK                 (0x3ull << EAP_MODE_SHIFT)
+#define  EAP_MODE_MASK_63XX            (0x3ull << EAP_MODE_SHIFT_63XX)
+#define  EAP_MODE_BASIC                        0
+#define  EAP_MODE_SIMPLIFIED           3
+
 /*************************************************************************
  * EEE Configuration Page Registers
  *************************************************************************/