lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250531101308.155757-2-noltari@gmail.com>
Date: Sat, 31 May 2025 12:12:59 +0200
From: Álvaro Fernández Rojas <noltari@...il.com>
To: jonas.gorski@...il.com,
	florian.fainelli@...adcom.com,
	andrew@...n.ch,
	olteanv@...il.com,
	davem@...emloft.net,
	edumazet@...gle.com,
	kuba@...nel.org,
	pabeni@...hat.com,
	vivien.didelot@...il.com,
	netdev@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	dgcbueu@...il.com
Cc: Florian Fainelli <f.fainelli@...il.com>,
	Álvaro Fernández Rojas <noltari@...il.com>
Subject: [RFC PATCH 01/10] net: dsa: b53: add support for FDB operations on 5325/5365

From: Florian Fainelli <f.fainelli@...il.com>

BCM5325 and BCM5365 are part of a much older generation of switches which,
due to their limited number of ports and VLAN entries (up to 256) allowed
a single 64-bit register to hold a full ARL entry.
This requires a little bit of massaging when reading, writing and
converting ARL entries in both directions.

Signed-off-by: Florian Fainelli <f.fainelli@...il.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@...il.com>
---
 drivers/net/dsa/b53/b53_common.c | 60 +++++++++++++++++++++-----------
 drivers/net/dsa/b53/b53_priv.h   | 57 +++++++++++++++++++++---------
 drivers/net/dsa/b53/b53_regs.h   |  7 ++--
 3 files changed, 84 insertions(+), 40 deletions(-)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 132683ed3abe..03c1e2e75061 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1760,9 +1760,11 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
 
 		b53_read64(dev, B53_ARLIO_PAGE,
 			   B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid);
-		b53_read32(dev, B53_ARLIO_PAGE,
-			   B53_ARLTBL_DATA_ENTRY(i), &fwd_entry);
-		b53_arl_to_entry(ent, mac_vid, fwd_entry);
+
+		if (!is5325(dev) && !is5365(dev))
+			b53_read32(dev, B53_ARLIO_PAGE,
+				   B53_ARLTBL_DATA_ENTRY(i), &fwd_entry);
+		b53_arl_to_entry(dev, ent, mac_vid, fwd_entry);
 
 		if (!(fwd_entry & ARLTBL_VALID)) {
 			set_bit(i, free_bins);
@@ -1795,7 +1797,8 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
 
 	/* Perform a read for the given MAC and VID */
 	b53_write48(dev, B53_ARLIO_PAGE, B53_MAC_ADDR_IDX, mac);
-	b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid);
+	if (!is5325(dev))
+		b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid);
 
 	/* Issue a read operation for this MAC */
 	ret = b53_arl_rw_op(dev, 1);
@@ -1846,12 +1849,14 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
 	ent.is_static = true;
 	ent.is_age = false;
 	memcpy(ent.mac, addr, ETH_ALEN);
-	b53_arl_from_entry(&mac_vid, &fwd_entry, &ent);
+	b53_arl_from_entry(dev, &mac_vid, &fwd_entry, &ent);
 
 	b53_write64(dev, B53_ARLIO_PAGE,
 		    B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid);
-	b53_write32(dev, B53_ARLIO_PAGE,
-		    B53_ARLTBL_DATA_ENTRY(idx), fwd_entry);
+
+	if (!is5325(dev) && !is5365(dev))
+		b53_write32(dev, B53_ARLIO_PAGE,
+			    B53_ARLTBL_DATA_ENTRY(idx), fwd_entry);
 
 	return b53_arl_rw_op(dev, 0);
 }
@@ -1863,12 +1868,6 @@ int b53_fdb_add(struct dsa_switch *ds, int port,
 	struct b53_device *priv = ds->priv;
 	int ret;
 
-	/* 5325 and 5365 require some more massaging, but could
-	 * be supported eventually
-	 */
-	if (is5325(priv) || is5365(priv))
-		return -EOPNOTSUPP;
-
 	mutex_lock(&priv->arl_mutex);
 	ret = b53_arl_op(priv, 0, port, addr, vid, true);
 	mutex_unlock(&priv->arl_mutex);
@@ -1895,10 +1894,15 @@ EXPORT_SYMBOL(b53_fdb_del);
 static int b53_arl_search_wait(struct b53_device *dev)
 {
 	unsigned int timeout = 1000;
-	u8 reg;
+	u8 reg, offset;
+
+	if (is5325(dev) || is5365(dev))
+		offset = B53_ARL_SRCH_CTL_25;
+	else
+		offset = B53_ARL_SRCH_CTL;
 
 	do {
-		b53_read8(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, &reg);
+		b53_read8(dev, B53_ARLIO_PAGE, offset, &reg);
 		if (!(reg & ARL_SRCH_STDN))
 			return 0;
 
@@ -1917,11 +1921,19 @@ static void b53_arl_search_rd(struct b53_device *dev, u8 idx,
 	u64 mac_vid;
 	u32 fwd_entry;
 
-	b53_read64(dev, B53_ARLIO_PAGE,
-		   B53_ARL_SRCH_RSTL_MACVID(idx), &mac_vid);
-	b53_read32(dev, B53_ARLIO_PAGE,
-		   B53_ARL_SRCH_RSTL(idx), &fwd_entry);
-	b53_arl_to_entry(ent, mac_vid, fwd_entry);
+	if (is5325(dev)) {
+		b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25,
+			   &mac_vid);
+	} else if (is5365(dev)) {
+		b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65,
+			   &mac_vid);
+	} else {
+		b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx),
+			   &mac_vid);
+		b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx),
+			   &fwd_entry);
+	}
+	b53_arl_to_entry(dev, ent, mac_vid, fwd_entry);
 }
 
 static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
@@ -1942,14 +1954,20 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
 	struct b53_device *priv = ds->priv;
 	struct b53_arl_entry results[2];
 	unsigned int count = 0;
+	u8 offset;
 	int ret;
 	u8 reg;
 
 	mutex_lock(&priv->arl_mutex);
 
+	if (is5325(priv) || is5365(priv))
+		offset = B53_ARL_SRCH_CTL_25;
+	else
+		offset = B53_ARL_SRCH_CTL;
+
 	/* Start search operation */
 	reg = ARL_SRCH_STDN;
-	b53_write8(priv, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, reg);
+	b53_write8(priv, offset, B53_ARL_SRCH_CTL, reg);
 
 	do {
 		ret = b53_arl_search_wait(priv);
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index a5ef7071ba07..05c5b9239bda 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -286,30 +286,55 @@ struct b53_arl_entry {
 	u8 is_static:1;
 };
 
-static inline void b53_arl_to_entry(struct b53_arl_entry *ent,
+static inline void b53_arl_to_entry(struct b53_device *dev,
+				    struct b53_arl_entry *ent,
 				    u64 mac_vid, u32 fwd_entry)
 {
 	memset(ent, 0, sizeof(*ent));
-	ent->port = fwd_entry & ARLTBL_DATA_PORT_ID_MASK;
-	ent->is_valid = !!(fwd_entry & ARLTBL_VALID);
-	ent->is_age = !!(fwd_entry & ARLTBL_AGE);
-	ent->is_static = !!(fwd_entry & ARLTBL_STATIC);
-	u64_to_ether_addr(mac_vid, ent->mac);
-	ent->vid = mac_vid >> ARLTBL_VID_S;
+	if (is5325(dev) || is5365(dev)) {
+		ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) &
+			    ARLTBL_DATA_PORT_ID_MASK_25;
+		ent->is_valid = !!(mac_vid & ARLTBL_VALID_25);
+		ent->is_age = !!(mac_vid & ARLTBL_AGE_25);
+		ent->is_static = !!(mac_vid & ARLTBL_STATIC_25);
+		u64_to_ether_addr(mac_vid, ent->mac);
+		ent->vid = mac_vid >> ARLTBL_VID_S_65;
+	} else {
+		ent->port = fwd_entry & ARLTBL_DATA_PORT_ID_MASK;
+		ent->is_valid = !!(fwd_entry & ARLTBL_VALID);
+		ent->is_age = !!(fwd_entry & ARLTBL_AGE);
+		ent->is_static = !!(fwd_entry & ARLTBL_STATIC);
+		u64_to_ether_addr(mac_vid, ent->mac);
+		ent->vid = mac_vid >> ARLTBL_VID_S;
+	}
 }
 
-static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry,
+static inline void b53_arl_from_entry(struct b53_device *dev,
+				      u64 *mac_vid, u32 *fwd_entry,
 				      const struct b53_arl_entry *ent)
 {
 	*mac_vid = ether_addr_to_u64(ent->mac);
-	*mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK) << ARLTBL_VID_S;
-	*fwd_entry = ent->port & ARLTBL_DATA_PORT_ID_MASK;
-	if (ent->is_valid)
-		*fwd_entry |= ARLTBL_VALID;
-	if (ent->is_static)
-		*fwd_entry |= ARLTBL_STATIC;
-	if (ent->is_age)
-		*fwd_entry |= ARLTBL_AGE;
+	if (is5325(dev) || is5365(dev)) {
+		*mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) <<
+				  ARLTBL_DATA_PORT_ID_S_25;
+		*mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) <<
+				  ARLTBL_VID_S_65;
+		if (ent->is_valid)
+			*mac_vid |= ARLTBL_VALID_25;
+		if (ent->is_static)
+			*mac_vid |= ARLTBL_STATIC_25;
+		if (ent->is_age)
+			*mac_vid |= ARLTBL_AGE_25;
+	} else {
+		*mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK) << ARLTBL_VID_S;
+		*fwd_entry = ent->port & ARLTBL_DATA_PORT_ID_MASK;
+		if (ent->is_valid)
+			*fwd_entry |= ARLTBL_VALID;
+		if (ent->is_static)
+			*fwd_entry |= ARLTBL_STATIC;
+		if (ent->is_age)
+			*fwd_entry |= ARLTBL_AGE;
+	}
 }
 
 #ifdef CONFIG_BCM47XX
diff --git a/drivers/net/dsa/b53/b53_regs.h b/drivers/net/dsa/b53/b53_regs.h
index 1fbc5a204bc7..1f15332fb2a7 100644
--- a/drivers/net/dsa/b53/b53_regs.h
+++ b/drivers/net/dsa/b53/b53_regs.h
@@ -324,9 +324,10 @@
 #define   ARLTBL_VID_MASK		0xfff
 #define   ARLTBL_DATA_PORT_ID_S_25	48
 #define   ARLTBL_DATA_PORT_ID_MASK_25	0xf
-#define   ARLTBL_AGE_25			BIT(61)
-#define   ARLTBL_STATIC_25		BIT(62)
-#define   ARLTBL_VALID_25		BIT(63)
+#define   ARLTBL_VID_S_65		53
+#define   ARLTBL_AGE_25			BIT_ULL(61)
+#define   ARLTBL_STATIC_25		BIT_ULL(62)
+#define   ARLTBL_VALID_25		BIT_ULL(63)
 
 /* ARL Table Data Entry N Registers (32 bit) */
 #define B53_ARLTBL_DATA_ENTRY(n)	((0x10 * (n)) + 0x18)
-- 
2.39.5


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ