net: dsa: felix: perform MDB migration based on ocelot->multicast list

The felix driver is the only user of dsa_port_walk_mdbs(), and there
isn't even a good reason for it, considering that the host MDB entries
are already saved by the ocelot switch lib in the ocelot->multicast list.

Rewrite the multicast entry migration procedure around the
ocelot->multicast list so we can delete dsa_port_walk_mdbs().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Vladimir Oltean 2022-05-05 19:22:12 +03:00 committed by Jakub Kicinski
parent a51c1c3f32
commit 28de0f9fec
3 changed files with 69 additions and 46 deletions

View File

@ -42,27 +42,6 @@ static struct net_device *felix_classify_db(struct dsa_db db)
}
}
static int felix_migrate_mdbs_to_npi_port(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct net_device *bridge_dev = felix_classify_db(db);
struct switchdev_obj_port_mdb mdb;
struct ocelot *ocelot = ds->priv;
int cpu = ocelot->num_phys_ports;
int err;
memset(&mdb, 0, sizeof(mdb));
ether_addr_copy(mdb.addr, addr);
mdb.vid = vid;
err = ocelot_port_mdb_del(ocelot, port, &mdb, bridge_dev);
if (err)
return err;
return ocelot_port_mdb_add(ocelot, cpu, &mdb, bridge_dev);
}
static void felix_migrate_pgid_bit(struct dsa_switch *ds, int from, int to,
int pgid)
{
@ -100,28 +79,6 @@ felix_migrate_flood_to_tag_8021q_port(struct dsa_switch *ds, int port)
felix_migrate_pgid_bit(ds, ocelot->num_phys_ports, port, PGID_BC);
}
static int
felix_migrate_mdbs_to_tag_8021q_port(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct net_device *bridge_dev = felix_classify_db(db);
struct switchdev_obj_port_mdb mdb;
struct ocelot *ocelot = ds->priv;
int cpu = ocelot->num_phys_ports;
int err;
memset(&mdb, 0, sizeof(mdb));
ether_addr_copy(mdb.addr, addr);
mdb.vid = vid;
err = ocelot_port_mdb_del(ocelot, cpu, &mdb, bridge_dev);
if (err)
return err;
return ocelot_port_mdb_add(ocelot, port, &mdb, bridge_dev);
}
/* Set up VCAP ES0 rules for pushing a tag_8021q VLAN towards the CPU such that
* the tagger can perform RX source port identification.
*/
@ -450,7 +407,8 @@ static int felix_setup_tag_8021q(struct dsa_switch *ds, int cpu)
if (err)
return err;
err = dsa_port_walk_mdbs(ds, cpu, felix_migrate_mdbs_to_tag_8021q_port);
err = ocelot_migrate_mdbs(ocelot, BIT(ocelot->num_phys_ports),
BIT(cpu));
if (err)
goto out_tag_8021q_unregister;
@ -473,7 +431,7 @@ static int felix_setup_tag_8021q(struct dsa_switch *ds, int cpu)
out_migrate_flood:
felix_migrate_flood_to_npi_port(ds, cpu);
dsa_port_walk_mdbs(ds, cpu, felix_migrate_mdbs_to_npi_port);
ocelot_migrate_mdbs(ocelot, BIT(cpu), BIT(ocelot->num_phys_ports));
out_tag_8021q_unregister:
dsa_tag_8021q_unregister(ds);
return err;
@ -553,7 +511,8 @@ static int felix_setup_tag_npi(struct dsa_switch *ds, int cpu)
struct ocelot *ocelot = ds->priv;
int err;
err = dsa_port_walk_mdbs(ds, cpu, felix_migrate_mdbs_to_npi_port);
err = ocelot_migrate_mdbs(ocelot, BIT(cpu),
BIT(ocelot->num_phys_ports));
if (err)
return err;

View File

@ -2610,6 +2610,67 @@ static void ocelot_setup_logical_port_ids(struct ocelot *ocelot)
}
}
static int ocelot_migrate_mc(struct ocelot *ocelot, struct ocelot_multicast *mc,
unsigned long from_mask, unsigned long to_mask)
{
unsigned char addr[ETH_ALEN];
struct ocelot_pgid *pgid;
u16 vid = mc->vid;
dev_dbg(ocelot->dev,
"Migrating multicast %pM vid %d from port mask 0x%lx to 0x%lx\n",
mc->addr, mc->vid, from_mask, to_mask);
/* First clean up the current port mask from hardware, because
* we'll be modifying it.
*/
ocelot_pgid_free(ocelot, mc->pgid);
ocelot_encode_ports_to_mdb(addr, mc);
ocelot_mact_forget(ocelot, addr, vid);
mc->ports &= ~from_mask;
mc->ports |= to_mask;
pgid = ocelot_mdb_get_pgid(ocelot, mc);
if (IS_ERR(pgid)) {
dev_err(ocelot->dev,
"Cannot allocate PGID for mdb %pM vid %d\n",
mc->addr, mc->vid);
devm_kfree(ocelot->dev, mc);
return PTR_ERR(pgid);
}
mc->pgid = pgid;
ocelot_encode_ports_to_mdb(addr, mc);
if (mc->entry_type != ENTRYTYPE_MACv4 &&
mc->entry_type != ENTRYTYPE_MACv6)
ocelot_write_rix(ocelot, pgid->ports, ANA_PGID_PGID,
pgid->index);
return ocelot_mact_learn(ocelot, pgid->index, addr, vid,
mc->entry_type);
}
int ocelot_migrate_mdbs(struct ocelot *ocelot, unsigned long from_mask,
unsigned long to_mask)
{
struct ocelot_multicast *mc;
int err;
list_for_each_entry(mc, &ocelot->multicast, list) {
if (!(mc->ports & from_mask))
continue;
err = ocelot_migrate_mc(ocelot, mc, from_mask, to_mask);
if (err)
return err;
}
return 0;
}
EXPORT_SYMBOL_GPL(ocelot_migrate_mdbs);
/* Documentation for PORTID_VAL says:
* Logical port number for front port. If port is not a member of a LLAG,
* then PORTID must be set to the physical port number.

View File

@ -998,6 +998,9 @@ int ocelot_mact_learn_streamdata(struct ocelot *ocelot, int dst_idx,
enum macaccess_entry_type type,
int sfid, int ssid);
int ocelot_migrate_mdbs(struct ocelot *ocelot, unsigned long from_mask,
unsigned long to_mask);
int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
struct ocelot_policer *pol);
int ocelot_vcap_policer_del(struct ocelot *ocelot, u32 pol_ix);