summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dsa/ocelot/felix.c104
-rw-r--r--drivers/net/ethernet/mscc/ocelot.c61
-rw-r--r--include/net/dsa.h6
-rw-r--r--include/soc/mscc/ocelot.h3
-rw-r--r--net/dsa/dsa.c40
5 files changed, 69 insertions, 145 deletions
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 33cb124ca912..a4882e493cf4 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -42,44 +42,6 @@ static struct net_device *felix_classify_db(struct dsa_db db)
}
}
-/* We are called before felix_npi_port_init(), so ocelot->npi is -1. */
-static int felix_migrate_fdbs_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 ocelot *ocelot = ds->priv;
- int cpu = ocelot->num_phys_ports;
- int err;
-
- err = ocelot_fdb_del(ocelot, port, addr, vid, bridge_dev);
- if (err)
- return err;
-
- return ocelot_fdb_add(ocelot, cpu, addr, vid, bridge_dev);
-}
-
-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)
{
@@ -117,49 +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);
}
-/* ocelot->npi was already set to -1 by felix_npi_port_deinit, so
- * ocelot_fdb_add() will not redirect FDB entries towards the
- * CPU port module here, which is what we want.
- */
-static int
-felix_migrate_fdbs_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 ocelot *ocelot = ds->priv;
- int cpu = ocelot->num_phys_ports;
- int err;
-
- err = ocelot_fdb_del(ocelot, cpu, addr, vid, bridge_dev);
- if (err)
- return err;
-
- return ocelot_fdb_add(ocelot, port, addr, vid, bridge_dev);
-}
-
-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.
*/
@@ -488,14 +407,11 @@ static int felix_setup_tag_8021q(struct dsa_switch *ds, int cpu)
if (err)
return err;
- err = dsa_port_walk_fdbs(ds, cpu, felix_migrate_fdbs_to_tag_8021q_port);
+ err = ocelot_migrate_mdbs(ocelot, BIT(ocelot->num_phys_ports),
+ BIT(cpu));
if (err)
goto out_tag_8021q_unregister;
- err = dsa_port_walk_mdbs(ds, cpu, felix_migrate_mdbs_to_tag_8021q_port);
- if (err)
- goto out_migrate_fdbs;
-
felix_migrate_flood_to_tag_8021q_port(ds, cpu);
err = felix_update_trapping_destinations(ds, true);
@@ -515,9 +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);
-out_migrate_fdbs:
- dsa_port_walk_fdbs(ds, cpu, felix_migrate_fdbs_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;
@@ -597,24 +511,16 @@ static int felix_setup_tag_npi(struct dsa_switch *ds, int cpu)
struct ocelot *ocelot = ds->priv;
int err;
- err = dsa_port_walk_fdbs(ds, cpu, felix_migrate_fdbs_to_npi_port);
+ err = ocelot_migrate_mdbs(ocelot, BIT(cpu),
+ BIT(ocelot->num_phys_ports));
if (err)
return err;
- err = dsa_port_walk_mdbs(ds, cpu, felix_migrate_mdbs_to_npi_port);
- if (err)
- goto out_migrate_fdbs;
-
felix_migrate_flood_to_npi_port(ds, cpu);
felix_npi_port_init(ocelot, cpu);
return 0;
-
-out_migrate_fdbs:
- dsa_port_walk_fdbs(ds, cpu, felix_migrate_fdbs_to_tag_8021q_port);
-
- return err;
}
static void felix_teardown_tag_npi(struct dsa_switch *ds, int cpu)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 0825a92599a5..9336f3b00c6e 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -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.
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 934958fda962..efd33956df37 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -1239,12 +1239,6 @@ struct dsa_switch_driver {
struct net_device *dsa_dev_to_net_device(struct device *dev);
-typedef int dsa_fdb_walk_cb_t(struct dsa_switch *ds, int port,
- const unsigned char *addr, u16 vid,
- struct dsa_db db);
-
-int dsa_port_walk_fdbs(struct dsa_switch *ds, int port, dsa_fdb_walk_cb_t cb);
-int dsa_port_walk_mdbs(struct dsa_switch *ds, int port, dsa_fdb_walk_cb_t cb);
bool dsa_fdb_present_in_other_db(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid,
struct dsa_db db);
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 8d8d46778f7e..e88bcfe4b2cd 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -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);
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 0c6ae32742ec..be7b320cda76 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -458,46 +458,6 @@ struct dsa_port *dsa_port_from_netdev(struct net_device *netdev)
}
EXPORT_SYMBOL_GPL(dsa_port_from_netdev);
-int dsa_port_walk_fdbs(struct dsa_switch *ds, int port, dsa_fdb_walk_cb_t cb)
-{
- struct dsa_port *dp = dsa_to_port(ds, port);
- struct dsa_mac_addr *a;
- int err = 0;
-
- mutex_lock(&dp->addr_lists_lock);
-
- list_for_each_entry(a, &dp->fdbs, list) {
- err = cb(ds, port, a->addr, a->vid, a->db);
- if (err)
- break;
- }
-
- mutex_unlock(&dp->addr_lists_lock);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(dsa_port_walk_fdbs);
-
-int dsa_port_walk_mdbs(struct dsa_switch *ds, int port, dsa_fdb_walk_cb_t cb)
-{
- struct dsa_port *dp = dsa_to_port(ds, port);
- struct dsa_mac_addr *a;
- int err = 0;
-
- mutex_lock(&dp->addr_lists_lock);
-
- list_for_each_entry(a, &dp->mdbs, list) {
- err = cb(ds, port, a->addr, a->vid, a->db);
- if (err)
- break;
- }
-
- mutex_unlock(&dp->addr_lists_lock);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(dsa_port_walk_mdbs);
-
bool dsa_db_equal(const struct dsa_db *a, const struct dsa_db *b)
{
if (a->type != b->type)