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

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
...@@ -1474,6 +1474,10 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op) ...@@ -1474,6 +1474,10 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)
reg |= ARLTBL_RW; reg |= ARLTBL_RW;
else else
reg &= ~ARLTBL_RW; 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); b53_write8(dev, B53_ARLIO_PAGE, B53_ARLTBL_RW_CTRL, reg);
return b53_arl_op_wait(dev); return b53_arl_op_wait(dev);
...@@ -1483,6 +1487,7 @@ static int b53_arl_read(struct b53_device *dev, u64 mac, ...@@ -1483,6 +1487,7 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
u16 vid, struct b53_arl_entry *ent, u8 *idx, u16 vid, struct b53_arl_entry *ent, u8 *idx,
bool is_valid) bool is_valid)
{ {
DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
unsigned int i; unsigned int i;
int ret; int ret;
...@@ -1490,6 +1495,8 @@ static int b53_arl_read(struct b53_device *dev, u64 mac, ...@@ -1490,6 +1495,8 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
if (ret) if (ret)
return ret; return ret;
bitmap_zero(free_bins, dev->num_arl_entries);
/* Read the bins */ /* Read the bins */
for (i = 0; i < dev->num_arl_entries; i++) { for (i = 0; i < dev->num_arl_entries; i++) {
u64 mac_vid; u64 mac_vid;
...@@ -1501,13 +1508,24 @@ static int b53_arl_read(struct b53_device *dev, u64 mac, ...@@ -1501,13 +1508,24 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,
B53_ARLTBL_DATA_ENTRY(i), &fwd_entry); B53_ARLTBL_DATA_ENTRY(i), &fwd_entry);
b53_arl_to_entry(ent, mac_vid, 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; continue;
}
if ((mac_vid & ARLTBL_MAC_MASK) != mac) if ((mac_vid & ARLTBL_MAC_MASK) != mac)
continue; continue;
if (dev->vlan_enabled &&
((mac_vid >> ARLTBL_VID_S) & ARLTBL_VID_MASK) != vid)
continue;
*idx = i; *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; return -ENOENT;
} }
...@@ -1537,10 +1555,21 @@ static int b53_arl_op(struct b53_device *dev, int op, int port, ...@@ -1537,10 +1555,21 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
if (op) if (op)
return ret; return ret;
/* We could not find a matching MAC, so reset to a new entry */ switch (ret) {
if (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 */
dev_dbg(dev->dev, "{%pM,%.4d} not found, using idx: %d\n",
addr, vid, idx);
fwd_entry = 0; 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 /* 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, ...@@ -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 = !!(ent.port);
} }
ent.is_valid = is_valid;
ent.vid = vid; ent.vid = vid;
ent.is_static = true; ent.is_static = true;
ent.is_age = false; ent.is_age = false;
......
...@@ -292,6 +292,7 @@ ...@@ -292,6 +292,7 @@
/* ARL Table Read/Write Register (8 bit) */ /* ARL Table Read/Write Register (8 bit) */
#define B53_ARLTBL_RW_CTRL 0x00 #define B53_ARLTBL_RW_CTRL 0x00
#define ARLTBL_RW BIT(0) #define ARLTBL_RW BIT(0)
#define ARLTBL_IVL_SVL_SELECT BIT(6)
#define ARLTBL_START_DONE BIT(7) #define ARLTBL_START_DONE BIT(7)
/* MAC Address Index Register (48 bit) */ /* MAC Address Index Register (48 bit) */
...@@ -304,7 +305,7 @@ ...@@ -304,7 +305,7 @@
* *
* BCM5325 and BCM5365 share most definitions below * 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_MAC_MASK 0xffffffffffffULL
#define ARLTBL_VID_S 48 #define ARLTBL_VID_S 48
#define ARLTBL_VID_MASK_25 0xff #define ARLTBL_VID_MASK_25 0xff
...@@ -316,13 +317,16 @@ ...@@ -316,13 +317,16 @@
#define ARLTBL_VALID_25 BIT(63) #define ARLTBL_VALID_25 BIT(63)
/* ARL Table Data Entry N Registers (32 bit) */ /* 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_DATA_PORT_ID_MASK 0x1ff
#define ARLTBL_TC(tc) ((3 & tc) << 11) #define ARLTBL_TC(tc) ((3 & tc) << 11)
#define ARLTBL_AGE BIT(14) #define ARLTBL_AGE BIT(14)
#define ARLTBL_STATIC BIT(15) #define ARLTBL_STATIC BIT(15)
#define ARLTBL_VALID BIT(16) #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) */ /* ARL Search Control Register (8 bit) */
#define B53_ARL_SRCH_CTL 0x50 #define B53_ARL_SRCH_CTL 0x50
#define B53_ARL_SRCH_CTL_25 0x20 #define B53_ARL_SRCH_CTL_25 0x20
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment