Skip to content

Commit

Permalink
net: dsa: b53: Rework ARL bin logic
Browse files Browse the repository at this point in the history
When asking the ARL to read a MAC address, we will get a number of bins
returned in a single read. Out of those bins, there can essentially be 3
states:

- all bins are full, we have no space left, and we can either replace an
  existing address or return that full condition

- the MAC address was found, then we need to return its bin index and
  modify that one, and only that one

- the MAC address was not found and we have a least one bin free, we use
  that bin index location then

The code would unfortunately fail on all counts.

Fixes: 1da6df8 ("net: dsa: b53: Implement ARL add/del/dump operations")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Florian Fainelli authored and David S. Miller committed Apr 22, 2020
1 parent c2e77a1 commit 6344dbd
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 4 deletions.
30 changes: 26 additions & 4 deletions drivers/net/dsa/b53/b53_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1483,13 +1483,16 @@ 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;

ret = b53_arl_op_wait(dev);
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;
Expand All @@ -1501,16 +1504,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;
}

Expand Down Expand Up @@ -1540,10 +1551,21 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
if (op)
return ret;

/* We could not find a matching MAC, so reset to a new entry */
if (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 */
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
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/dsa/b53/b53_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@
#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
Expand Down

0 comments on commit 6344dbd

Please sign in to comment.