Commit d5812a86 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-dsa-b53-Various-ARL-fixes'



Florian Fainelli says:

====================
net: dsa: b53: Various ARL fixes

This patch series fixes a number of short comings in the existing b53
driver ARL management logic in particular:

- we were not looking up the {MAC,VID} tuples against their VID, despite
  having VLANs enabled

- the MDB entries (multicast) would lose their validity as soon as a
  single port in the vector would leave the entry

- the ARL was currently under utilized because we would always place new
  entries in bin index #1, instead of using all possible bins available,
  thus reducing the ARL effective size by 50% or 75% depending on the
  switch generation

- it was possible to overwrite the ARL entries because no proper space
  verification was done

This patch series addresses all of these issues.

Changes in v2:
- added a new patch to correctly flip invidual VLAN learning vs. shared
  VLAN learning depending on the global VLAN state

- added Andrew's R-b tags for patches which did not change

- corrected some verbosity and minor issues in patch #4 to match caller
  expectations, also avoid a variable length DECLARE_BITMAP() call
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 87f78f27 64fec949
Loading
Loading
Loading
Loading
+33 −5
Original line number Diff line number Diff line
@@ -1474,6 +1474,10 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)
		reg |= ARLTBL_RW;
	else
		reg &= ~ARLTBL_RW;
	if (dev->vlan_enabled)
		reg &= ~ARLTBL_IVL_SVL_SELECT;
	else
		reg |= ARLTBL_IVL_SVL_SELECT;
	b53_write8(dev, B53_ARLIO_PAGE, B53_ARLTBL_RW_CTRL, reg);

	return b53_arl_op_wait(dev);
@@ -1483,6 +1487,7 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
			u16 vid, struct b53_arl_entry *ent, u8 *idx,
			bool is_valid)
{
	DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
	unsigned int i;
	int ret;

@@ -1490,6 +1495,8 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
	if (ret)
		return ret;

	bitmap_zero(free_bins, dev->num_arl_entries);

	/* Read the bins */
	for (i = 0; i < dev->num_arl_entries; i++) {
		u64 mac_vid;
@@ -1501,13 +1508,24 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
			   B53_ARLTBL_DATA_ENTRY(i), &fwd_entry);
		b53_arl_to_entry(ent, mac_vid, fwd_entry);

		if (!(fwd_entry & ARLTBL_VALID))
		if (!(fwd_entry & ARLTBL_VALID)) {
			set_bit(i, free_bins);
			continue;
		}
		if ((mac_vid & ARLTBL_MAC_MASK) != mac)
			continue;
		if (dev->vlan_enabled &&
		    ((mac_vid >> ARLTBL_VID_S) & ARLTBL_VID_MASK) != vid)
			continue;
		*idx = i;
		return 0;
	}

	if (bitmap_weight(free_bins, dev->num_arl_entries) == 0)
		return -ENOSPC;

	*idx = find_first_bit(free_bins, dev->num_arl_entries);

	return -ENOENT;
}

@@ -1537,10 +1555,21 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
	if (op)
		return ret;

	switch (ret) {
	case -ENOSPC:
		dev_dbg(dev->dev, "{%pM,%.4d} no space left in ARL\n",
			addr, vid);
		return is_valid ? ret : 0;
	case -ENOENT:
		/* We could not find a matching MAC, so reset to a new entry */
	if (ret) {
		dev_dbg(dev->dev, "{%pM,%.4d} not found, using idx: %d\n",
			addr, vid, idx);
		fwd_entry = 0;
		idx = 1;
		break;
	default:
		dev_dbg(dev->dev, "{%pM,%.4d} found, using idx: %d\n",
			addr, vid, idx);
		break;
	}

	/* For multicast address, the port is a bitmask and the validity
@@ -1558,7 +1587,6 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
		ent.is_valid = !!(ent.port);
	}

	ent.is_valid = is_valid;
	ent.vid = vid;
	ent.is_static = true;
	ent.is_age = false;
+6 −2
Original line number Diff line number Diff line
@@ -292,6 +292,7 @@
/* ARL Table Read/Write Register (8 bit) */
#define B53_ARLTBL_RW_CTRL		0x00
#define    ARLTBL_RW			BIT(0)
#define    ARLTBL_IVL_SVL_SELECT	BIT(6)
#define    ARLTBL_START_DONE		BIT(7)

/* MAC Address Index Register (48 bit) */
@@ -304,7 +305,7 @@
 *
 * BCM5325 and BCM5365 share most definitions below
 */
#define B53_ARLTBL_MAC_VID_ENTRY(n)	(0x10 * (n))
#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
@@ -316,13 +317,16 @@
#define   ARLTBL_VALID_25		BIT(63)

/* ARL Table Data Entry N Registers (32 bit) */
#define B53_ARLTBL_DATA_ENTRY(n)	((0x10 * (n)) + 0x08)
#define B53_ARLTBL_DATA_ENTRY(n)	((0x10 * (n)) + 0x18)
#define   ARLTBL_DATA_PORT_ID_MASK	0x1ff
#define   ARLTBL_TC(tc)			((3 & tc) << 11)
#define   ARLTBL_AGE			BIT(14)
#define   ARLTBL_STATIC			BIT(15)
#define   ARLTBL_VALID			BIT(16)

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

/* ARL Search Control Register (8 bit) */
#define B53_ARL_SRCH_CTL		0x50
#define B53_ARL_SRCH_CTL_25		0x20