Commit e11e865b authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: sja1105: overwrite dynamic FDB entries with static ones in .port_fdb_add

The SJA1105 switch family leaves it up to software to decide where
within the FDB to install a static entry, and to concatenate destination
ports for already existing entries (the FDB is also used for multicast
entries), it is not as simple as just saying "please add this entry".

This means we first need to search for an existing FDB entry before
adding a new one. The driver currently manages to fool itself into
thinking that if an FDB entry already exists, there is nothing to be
done. But that FDB entry might be dynamically learned, case in which it
should be replaced with a static entry, but instead it is left alone.

This patch checks the LOCKEDS ("locked/static") bit from found FDB
entries, and lets the code "goto skip_finding_an_index;" if the FDB
entry was not static. So we also need to move the place where we set
LOCKEDS = true, to cover the new case where a dynamic FDB entry existed
but was dynamic.

Fixes: 291d1e72 ("net: dsa: sja1105: Add support for FDB and MDB management")
Fixes: 1da73821 ("net: dsa: sja1105: Add FDB operations for P/Q/R/S series")
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cb81698f
...@@ -1333,7 +1333,7 @@ int sja1105et_fdb_add(struct dsa_switch *ds, int port, ...@@ -1333,7 +1333,7 @@ int sja1105et_fdb_add(struct dsa_switch *ds, int port,
* mask? If yes, we need to do nothing. If not, we need * mask? If yes, we need to do nothing. If not, we need
* to rewrite the entry by adding this port to it. * to rewrite the entry by adding this port to it.
*/ */
if (l2_lookup.destports & BIT(port)) if ((l2_lookup.destports & BIT(port)) && l2_lookup.lockeds)
return 0; return 0;
l2_lookup.destports |= BIT(port); l2_lookup.destports |= BIT(port);
} else { } else {
...@@ -1364,6 +1364,7 @@ int sja1105et_fdb_add(struct dsa_switch *ds, int port, ...@@ -1364,6 +1364,7 @@ int sja1105et_fdb_add(struct dsa_switch *ds, int port,
index, NULL, false); index, NULL, false);
} }
} }
l2_lookup.lockeds = true;
l2_lookup.index = sja1105et_fdb_index(bin, way); l2_lookup.index = sja1105et_fdb_index(bin, way);
rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP, rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
...@@ -1434,10 +1435,10 @@ int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port, ...@@ -1434,10 +1435,10 @@ int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port,
rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP, rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
SJA1105_SEARCH, &l2_lookup); SJA1105_SEARCH, &l2_lookup);
if (rc == 0) { if (rc == 0) {
/* Found and this port is already in the entry's /* Found a static entry and this port is already in the entry's
* port mask => job done * port mask => job done
*/ */
if (l2_lookup.destports & BIT(port)) if ((l2_lookup.destports & BIT(port)) && l2_lookup.lockeds)
return 0; return 0;
/* l2_lookup.index is populated by the switch in case it /* l2_lookup.index is populated by the switch in case it
* found something. * found something.
...@@ -1460,10 +1461,11 @@ int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port, ...@@ -1460,10 +1461,11 @@ int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port,
dev_err(ds->dev, "FDB is full, cannot add entry.\n"); dev_err(ds->dev, "FDB is full, cannot add entry.\n");
return -EINVAL; return -EINVAL;
} }
l2_lookup.lockeds = true;
l2_lookup.index = i; l2_lookup.index = i;
skip_finding_an_index: skip_finding_an_index:
l2_lookup.lockeds = true;
rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP, rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
l2_lookup.index, &l2_lookup, l2_lookup.index, &l2_lookup,
true); true);
......
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