forked from Minki/linux
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:
parent
a51c1c3f32
commit
28de0f9fec
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user