net: dsa: felix: add port fast age support

Add support for flushing the MAC table on a given port in the ocelot
switch library, and use this functionality in the felix DSA driver.

This operation is needed when a port leaves a bridge to become
standalone, and when the learning is disabled, and when the STP state
changes to a state where no FDB entry should be present.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Link: https://lore.kernel.org/r/20220107144229.244584-1-vladimir.oltean@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Vladimir Oltean 2022-01-07 16:42:29 +02:00 committed by Jakub Kicinski
parent a14e6b69f3
commit 5cad43a52e
3 changed files with 50 additions and 0 deletions

View File

@ -639,6 +639,17 @@ static int felix_set_ageing_time(struct dsa_switch *ds,
return 0;
}
static void felix_port_fast_age(struct dsa_switch *ds, int port)
{
struct ocelot *ocelot = ds->priv;
int err;
err = ocelot_mact_flush(ocelot, port);
if (err)
dev_err(ds->dev, "Flushing MAC table on port %d returned %pe\n",
port, ERR_PTR(err));
}
static int felix_fdb_dump(struct dsa_switch *ds, int port,
dsa_fdb_dump_cb_t *cb, void *data)
{
@ -1622,6 +1633,7 @@ const struct dsa_switch_ops felix_switch_ops = {
.phylink_mac_config = felix_phylink_mac_config,
.phylink_mac_link_down = felix_phylink_mac_link_down,
.phylink_mac_link_up = felix_phylink_mac_link_up,
.port_fast_age = felix_port_fast_age,
.port_fdb_dump = felix_fdb_dump,
.port_fdb_add = felix_fdb_add,
.port_fdb_del = felix_fdb_del,

View File

@ -1341,6 +1341,43 @@ static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col,
return 0;
}
int ocelot_mact_flush(struct ocelot *ocelot, int port)
{
int err;
mutex_lock(&ocelot->mact_lock);
/* Program ageing filter for a single port */
ocelot_write(ocelot, ANA_ANAGEFIL_PID_EN | ANA_ANAGEFIL_PID_VAL(port),
ANA_ANAGEFIL);
/* Flushing dynamic FDB entries requires two successive age scans */
ocelot_write(ocelot,
ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_AGE),
ANA_TABLES_MACACCESS);
err = ocelot_mact_wait_for_completion(ocelot);
if (err) {
mutex_unlock(&ocelot->mact_lock);
return err;
}
/* And second... */
ocelot_write(ocelot,
ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_AGE),
ANA_TABLES_MACACCESS);
err = ocelot_mact_wait_for_completion(ocelot);
/* Restore ageing filter */
ocelot_write(ocelot, 0, ANA_ANAGEFIL);
mutex_unlock(&ocelot->mact_lock);
return err;
}
EXPORT_SYMBOL_GPL(ocelot_mact_flush);
int ocelot_fdb_dump(struct ocelot *ocelot, int port,
dsa_fdb_dump_cb_t *cb, void *data)
{

View File

@ -833,6 +833,7 @@ void ocelot_port_bridge_join(struct ocelot *ocelot, int port,
struct net_device *bridge);
void ocelot_port_bridge_leave(struct ocelot *ocelot, int port,
struct net_device *bridge);
int ocelot_mact_flush(struct ocelot *ocelot, int port);
int ocelot_fdb_dump(struct ocelot *ocelot, int port,
dsa_fdb_dump_cb_t *cb, void *data);
int ocelot_fdb_add(struct ocelot *ocelot, int port,