Commit 8d92057c authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-dsa-b53-fix-arl-accesses-for-bcm5325-65-and-allow-vid-0'

Jonas Gorski says:

====================
net: dsa: b53: fix ARL accesses for BCM5325/65 and allow VID 0

ARL entries on BCM5325 and BCM5365 were broken significantly in two
ways:

- Entries for the CPU port were using the wrong port id, pointing to a
  non existing port.
- Setting the VLAN ID for entries was not done, adding them all to VLAN
  0 instead.

While the former technically broke any communication to the CPU port,
with the latter they were added to the currently unused VID 0, so they
never became effective. Presumably the default PVID was set to 1 because
of these issues 0 was broken (and the root cause not found).

So fix writing and reading entries on BCM5325/65 by first fixing the CPU
port entries, then fixing setting the VLAN ID for entries.

Finally, re-allow VID 0 for BCM5325/65 to allow the whole 1-15 VLAN ID
range to be available to users, and align VLAN handling with all other
switch chips.
====================

Link: https://patch.msgid.link/20251128080625.27181-1-jonas.gorski@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 4e3583cb 0b2b2705
Loading
Loading
Loading
Loading
+18 −29
Original line number Diff line number Diff line
@@ -872,9 +872,6 @@ static void b53_enable_stp(struct b53_device *dev)

static u16 b53_default_pvid(struct b53_device *dev)
{
	if (is5325(dev) || is5365(dev))
		return 1;
	else
	return 0;
}

@@ -1699,9 +1696,6 @@ static int b53_vlan_prepare(struct dsa_switch *ds, int port,
{
	struct b53_device *dev = ds->priv;

	if ((is5325(dev) || is5365(dev)) && vlan->vid == 0)
		return -EOPNOTSUPP;

	/* Port 7 on 7278 connects to the ASP's UniMAC which is not capable of
	 * receiving VLAN tagged frames at all, we can still allow the port to
	 * be configured for egress untagged.
@@ -1853,19 +1847,24 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)
static void b53_arl_read_entry_25(struct b53_device *dev,
				  struct b53_arl_entry *ent, u8 idx)
{
	u8 vid_entry;
	u64 mac_vid;

	b53_read8(dev, B53_ARLIO_PAGE, B53_ARLTBL_VID_ENTRY_25(idx),
		  &vid_entry);
	b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx),
		   &mac_vid);
	b53_arl_to_entry_25(ent, mac_vid);
	b53_arl_to_entry_25(ent, mac_vid, vid_entry);
}

static void b53_arl_write_entry_25(struct b53_device *dev,
				   const struct b53_arl_entry *ent, u8 idx)
{
	u8 vid_entry;
	u64 mac_vid;

	b53_arl_from_entry_25(&mac_vid, ent);
	b53_arl_from_entry_25(&mac_vid, &vid_entry, ent);
	b53_write8(dev, B53_ARLIO_PAGE, B53_ARLTBL_VID_ENTRY_25(idx), vid_entry);
	b53_write64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx),
		    mac_vid);
}
@@ -1966,8 +1965,12 @@ 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);
	if (!is5325m(dev))
	if (!is5325m(dev)) {
		if (is5325(dev) || is5365(dev))
			b53_write8(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid);
		else
			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);
@@ -2115,20 +2118,12 @@ static void b53_arl_search_read_25(struct b53_device *dev, u8 idx,
				   struct b53_arl_entry *ent)
{
	u64 mac_vid;
	u8 ext;

	b53_read8(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_EXT_25, &ext);
	b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25,
		   &mac_vid);
	b53_arl_to_entry_25(ent, mac_vid);
}

static void b53_arl_search_read_65(struct b53_device *dev, u8 idx,
				   struct b53_arl_entry *ent)
{
	u64 mac_vid;

	b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65,
		   &mac_vid);
	b53_arl_to_entry_25(ent, mac_vid);
	b53_arl_search_to_entry_25(ent, mac_vid, ext);
}

static void b53_arl_search_read_89(struct b53_device *dev, u8 idx,
@@ -2742,12 +2737,6 @@ static const struct b53_arl_ops b53_arl_ops_25 = {
	.arl_search_read = b53_arl_search_read_25,
};

static const struct b53_arl_ops b53_arl_ops_65 = {
	.arl_read_entry = b53_arl_read_entry_25,
	.arl_write_entry = b53_arl_write_entry_25,
	.arl_search_read = b53_arl_search_read_65,
};

static const struct b53_arl_ops b53_arl_ops_89 = {
	.arl_read_entry = b53_arl_read_entry_89,
	.arl_write_entry = b53_arl_write_entry_89,
@@ -2810,7 +2799,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
		.arl_buckets = 1024,
		.imp_port = 5,
		.duplex_reg = B53_DUPLEX_STAT_FE,
		.arl_ops = &b53_arl_ops_65,
		.arl_ops = &b53_arl_ops_25,
	},
	{
		.chip_id = BCM5389_DEVICE_ID,
+31 −9
Original line number Diff line number Diff line
@@ -341,16 +341,18 @@ static inline void b53_arl_to_entry(struct b53_arl_entry *ent,
}

static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent,
				       u64 mac_vid)
				       u64 mac_vid, u8 vid_entry)
{
	memset(ent, 0, sizeof(*ent));
	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;
	ent->port = (mac_vid & ARLTBL_DATA_PORT_ID_MASK_25) >>
		     ARLTBL_DATA_PORT_ID_S_25;
	if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT)
		ent->port = B53_CPU_PORT_25;
	ent->vid = vid_entry;
}

static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent,
@@ -379,20 +381,22 @@ static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry,
		*fwd_entry |= ARLTBL_AGE;
}

static inline void b53_arl_from_entry_25(u64 *mac_vid,
static inline void b53_arl_from_entry_25(u64 *mac_vid, u8 *vid_entry,
					 const struct b53_arl_entry *ent)
{
	*mac_vid = ether_addr_to_u64(ent->mac);
	*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 (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT_25)
		*mac_vid |= (u64)B53_CPU_PORT << ARLTBL_DATA_PORT_ID_S_25;
	else
		*mac_vid |= ((u64)ent->port << ARLTBL_DATA_PORT_ID_S_25) &
			    ARLTBL_DATA_PORT_ID_MASK_25;
	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;
	*vid_entry = ent->vid;
}

static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry,
@@ -409,6 +413,24 @@ static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry,
		*fwd_entry |= ARLTBL_AGE_89;
}

static inline void b53_arl_search_to_entry_25(struct b53_arl_entry *ent,
					      u64 mac_vid, u8 ext)
{
	memset(ent, 0, sizeof(*ent));
	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 & ARL_SRCH_RSLT_VID_MASK_25) >>
		   ARL_SRCH_RSLT_VID_S_25;
	ent->port = (mac_vid & ARL_SRCH_RSLT_PORT_ID_MASK_25) >>
		    ARL_SRCH_RSLT_PORT_ID_S_25;
	if (is_multicast_ether_addr(ent->mac) && (ext & ARL_SRCH_RSLT_EXT_MC_MII))
		ent->port |= BIT(B53_CPU_PORT_25);
	else if (!is_multicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT)
		ent->port = B53_CPU_PORT_25;
}

static inline void b53_arl_search_to_entry_63xx(struct b53_arl_entry *ent,
						u64 mac_vid, u16 fwd_entry)
{
+13 −6
Original line number Diff line number Diff line
@@ -329,11 +329,9 @@
#define B53_ARLTBL_MAC_VID_ENTRY(n)	((0x10 * (n)) + 0x10)
#define   ARLTBL_MAC_MASK		0xffffffffffffULL
#define   ARLTBL_VID_S			48
#define   ARLTBL_VID_MASK_25		0xff
#define   ARLTBL_VID_MASK		0xfff
#define   ARLTBL_DATA_PORT_ID_S_25	48
#define   ARLTBL_DATA_PORT_ID_MASK_25	0xf
#define   ARLTBL_VID_S_65		53
#define   ARLTBL_DATA_PORT_ID_MASK_25	GENMASK_ULL(53, 48)
#define   ARLTBL_AGE_25			BIT_ULL(61)
#define   ARLTBL_STATIC_25		BIT_ULL(62)
#define   ARLTBL_VALID_25		BIT_ULL(63)
@@ -353,6 +351,9 @@
#define   ARLTBL_STATIC_89		BIT(14)
#define   ARLTBL_VALID_89		BIT(15)

/* BCM5325/BCM565 ARL Table VID Entry N Registers (8 bit) */
#define B53_ARLTBL_VID_ENTRY_25(n)	((0x2 * (n)) + 0x30)

/* Maximum number of bin entries in the ARL for all switches */
#define B53_ARLTBL_MAX_BIN_ENTRIES	4

@@ -376,10 +377,16 @@
#define B53_ARL_SRCH_RSLT_MACVID_89	0x33
#define B53_ARL_SRCH_RSLT_MACVID_63XX	0x34

/* Single register search result on 5325 */
/* Single register search result on 5325/5365 */
#define B53_ARL_SRCH_RSTL_0_MACVID_25	0x24
/* Single register search result on 5365 */
#define B53_ARL_SRCH_RSTL_0_MACVID_65	0x30
#define   ARL_SRCH_RSLT_PORT_ID_S_25	48
#define   ARL_SRCH_RSLT_PORT_ID_MASK_25	GENMASK_ULL(52, 48)
#define   ARL_SRCH_RSLT_VID_S_25	53
#define   ARL_SRCH_RSLT_VID_MASK_25	GENMASK_ULL(60, 53)

/* BCM5325/5365 Search result extend register (8 bit) */
#define B53_ARL_SRCH_RSLT_EXT_25	0x2c
#define   ARL_SRCH_RSLT_EXT_MC_MII	BIT(2)

/* ARL Search Data Result (32 bit) */
#define B53_ARL_SRCH_RSTL_0		0x68