Skip to content

Commit 07469f8

Browse files
committed
Merge branch 'dsa-mdb-support'
Vivien Didelot says: ==================== net: dsa: add MDB support This patchset adds the switchdev MDB object support to the DSA layer. The MDB support for the mv88e6xxx driver is very similar to the FDB support. The FDB operations care about unicast addresses while the MDB operations care about multicast addresses. Both operation set load/purge/dump the Address Translation Table (ATU), thus common code is used. Changes in v2 based on Andrew's comments: - drop "group" in multicast database related doc and comment - change _one for more relevant _fid in mv88e6xxx_port_db_dump_one - return -EOPNOTSUPP if switchdev obj ID is neither _FDB nor _MDB ==================== Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
2 parents dbeb714 + 7df8fbd commit 07469f8

File tree

4 files changed

+215
-42
lines changed

4 files changed

+215
-42
lines changed

Documentation/networking/dsa/dsa.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,29 @@ of DSA, would be the its port-based VLAN, used by the associated bridge device.
584584
function that the driver has to call for each MAC address known to be behind
585585
the given port. A switchdev object is used to carry the VID and FDB info.
586586

587+
- port_mdb_prepare: bridge layer function invoked when the bridge prepares the
588+
installation of a multicast database entry. If the operation is not supported,
589+
this function should return -EOPNOTSUPP to inform the bridge code to fallback
590+
to a software implementation. No hardware setup must be done in this function.
591+
See port_fdb_add for this and details.
592+
593+
- port_mdb_add: bridge layer function invoked when the bridge wants to install
594+
a multicast database entry, the switch hardware should be programmed with the
595+
specified address in the specified VLAN ID in the forwarding database
596+
associated with this VLAN ID.
597+
598+
Note: VLAN ID 0 corresponds to the port private database, which, in the context
599+
of DSA, would be the its port-based VLAN, used by the associated bridge device.
600+
601+
- port_mdb_del: bridge layer function invoked when the bridge wants to remove a
602+
multicast database entry, the switch hardware should be programmed to delete
603+
the specified MAC address from the specified VLAN ID if it was mapped into
604+
this port forwarding database.
605+
606+
- port_mdb_dump: bridge layer function invoked with a switchdev callback
607+
function that the driver has to call for each MAC address known to be behind
608+
the given port. A switchdev object is used to carry the VID and MDB info.
609+
587610
TODO
588611
====
589612

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 121 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,9 +2093,9 @@ static int _mv88e6xxx_atu_load(struct mv88e6xxx_chip *chip,
20932093
return _mv88e6xxx_atu_cmd(chip, entry->fid, GLOBAL_ATU_OP_LOAD_DB);
20942094
}
20952095

2096-
static int _mv88e6xxx_port_fdb_load(struct mv88e6xxx_chip *chip, int port,
2097-
const unsigned char *addr, u16 vid,
2098-
u8 state)
2096+
static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
2097+
const unsigned char *addr, u16 vid,
2098+
u8 state)
20992099
{
21002100
struct mv88e6xxx_atu_entry entry = { 0 };
21012101
struct mv88e6xxx_vtu_stu_entry vlan;
@@ -2134,30 +2134,27 @@ static void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
21342134
const struct switchdev_obj_port_fdb *fdb,
21352135
struct switchdev_trans *trans)
21362136
{
2137-
int state = is_multicast_ether_addr(fdb->addr) ?
2138-
GLOBAL_ATU_DATA_STATE_MC_STATIC :
2139-
GLOBAL_ATU_DATA_STATE_UC_STATIC;
21402137
struct mv88e6xxx_chip *chip = ds_to_priv(ds);
21412138

21422139
mutex_lock(&chip->reg_lock);
2143-
if (_mv88e6xxx_port_fdb_load(chip, port, fdb->addr, fdb->vid, state))
2144-
netdev_err(ds->ports[port].netdev,
2145-
"failed to load MAC address\n");
2140+
if (mv88e6xxx_port_db_load_purge(chip, port, fdb->addr, fdb->vid,
2141+
GLOBAL_ATU_DATA_STATE_UC_STATIC))
2142+
netdev_err(ds->ports[port].netdev, "failed to load unicast MAC address\n");
21462143
mutex_unlock(&chip->reg_lock);
21472144
}
21482145

21492146
static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
21502147
const struct switchdev_obj_port_fdb *fdb)
21512148
{
21522149
struct mv88e6xxx_chip *chip = ds_to_priv(ds);
2153-
int ret;
2150+
int err;
21542151

21552152
mutex_lock(&chip->reg_lock);
2156-
ret = _mv88e6xxx_port_fdb_load(chip, port, fdb->addr, fdb->vid,
2157-
GLOBAL_ATU_DATA_STATE_UNUSED);
2153+
err = mv88e6xxx_port_db_load_purge(chip, port, fdb->addr, fdb->vid,
2154+
GLOBAL_ATU_DATA_STATE_UNUSED);
21582155
mutex_unlock(&chip->reg_lock);
21592156

2160-
return ret;
2157+
return err;
21612158
}
21622159

21632160
static int _mv88e6xxx_atu_getnext(struct mv88e6xxx_chip *chip, u16 fid,
@@ -2205,10 +2202,10 @@ static int _mv88e6xxx_atu_getnext(struct mv88e6xxx_chip *chip, u16 fid,
22052202
return 0;
22062203
}
22072204

2208-
static int _mv88e6xxx_port_fdb_dump_one(struct mv88e6xxx_chip *chip,
2209-
u16 fid, u16 vid, int port,
2210-
struct switchdev_obj_port_fdb *fdb,
2211-
int (*cb)(struct switchdev_obj *obj))
2205+
static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip,
2206+
u16 fid, u16 vid, int port,
2207+
struct switchdev_obj *obj,
2208+
int (*cb)(struct switchdev_obj *obj))
22122209
{
22132210
struct mv88e6xxx_atu_entry addr = {
22142211
.mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
@@ -2222,72 +2219,98 @@ static int _mv88e6xxx_port_fdb_dump_one(struct mv88e6xxx_chip *chip,
22222219
do {
22232220
err = _mv88e6xxx_atu_getnext(chip, fid, &addr);
22242221
if (err)
2225-
break;
2222+
return err;
22262223

22272224
if (addr.state == GLOBAL_ATU_DATA_STATE_UNUSED)
22282225
break;
22292226

2230-
if (!addr.trunk && addr.portv_trunkid & BIT(port)) {
2231-
bool is_static = addr.state ==
2232-
(is_multicast_ether_addr(addr.mac) ?
2233-
GLOBAL_ATU_DATA_STATE_MC_STATIC :
2234-
GLOBAL_ATU_DATA_STATE_UC_STATIC);
2227+
if (addr.trunk || (addr.portv_trunkid & BIT(port)) == 0)
2228+
continue;
2229+
2230+
if (obj->id == SWITCHDEV_OBJ_ID_PORT_FDB) {
2231+
struct switchdev_obj_port_fdb *fdb;
2232+
2233+
if (!is_unicast_ether_addr(addr.mac))
2234+
continue;
22352235

2236+
fdb = SWITCHDEV_OBJ_PORT_FDB(obj);
22362237
fdb->vid = vid;
22372238
ether_addr_copy(fdb->addr, addr.mac);
2238-
fdb->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
2239+
if (addr.state == GLOBAL_ATU_DATA_STATE_UC_STATIC)
2240+
fdb->ndm_state = NUD_NOARP;
2241+
else
2242+
fdb->ndm_state = NUD_REACHABLE;
2243+
} else if (obj->id == SWITCHDEV_OBJ_ID_PORT_MDB) {
2244+
struct switchdev_obj_port_mdb *mdb;
22392245

2240-
err = cb(&fdb->obj);
2241-
if (err)
2242-
break;
2246+
if (!is_multicast_ether_addr(addr.mac))
2247+
continue;
2248+
2249+
mdb = SWITCHDEV_OBJ_PORT_MDB(obj);
2250+
mdb->vid = vid;
2251+
ether_addr_copy(mdb->addr, addr.mac);
2252+
} else {
2253+
return -EOPNOTSUPP;
22432254
}
2255+
2256+
err = cb(obj);
2257+
if (err)
2258+
return err;
22442259
} while (!is_broadcast_ether_addr(addr.mac));
22452260

22462261
return err;
22472262
}
22482263

2249-
static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
2250-
struct switchdev_obj_port_fdb *fdb,
2251-
int (*cb)(struct switchdev_obj *obj))
2264+
static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
2265+
struct switchdev_obj *obj,
2266+
int (*cb)(struct switchdev_obj *obj))
22522267
{
2253-
struct mv88e6xxx_chip *chip = ds_to_priv(ds);
22542268
struct mv88e6xxx_vtu_stu_entry vlan = {
22552269
.vid = GLOBAL_VTU_VID_MASK, /* all ones */
22562270
};
22572271
u16 fid;
22582272
int err;
22592273

2260-
mutex_lock(&chip->reg_lock);
2261-
22622274
/* Dump port's default Filtering Information Database (VLAN ID 0) */
22632275
err = _mv88e6xxx_port_fid_get(chip, port, &fid);
22642276
if (err)
2265-
goto unlock;
2277+
return err;
22662278

2267-
err = _mv88e6xxx_port_fdb_dump_one(chip, fid, 0, port, fdb, cb);
2279+
err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, obj, cb);
22682280
if (err)
2269-
goto unlock;
2281+
return err;
22702282

22712283
/* Dump VLANs' Filtering Information Databases */
22722284
err = _mv88e6xxx_vtu_vid_write(chip, vlan.vid);
22732285
if (err)
2274-
goto unlock;
2286+
return err;
22752287

22762288
do {
22772289
err = _mv88e6xxx_vtu_getnext(chip, &vlan);
22782290
if (err)
2279-
break;
2291+
return err;
22802292

22812293
if (!vlan.valid)
22822294
break;
22832295

2284-
err = _mv88e6xxx_port_fdb_dump_one(chip, vlan.fid, vlan.vid,
2285-
port, fdb, cb);
2296+
err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port,
2297+
obj, cb);
22862298
if (err)
2287-
break;
2299+
return err;
22882300
} while (vlan.vid < GLOBAL_VTU_VID_MASK);
22892301

2290-
unlock:
2302+
return err;
2303+
}
2304+
2305+
static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
2306+
struct switchdev_obj_port_fdb *fdb,
2307+
int (*cb)(struct switchdev_obj *obj))
2308+
{
2309+
struct mv88e6xxx_chip *chip = ds_to_priv(ds);
2310+
int err;
2311+
2312+
mutex_lock(&chip->reg_lock);
2313+
err = mv88e6xxx_port_db_dump(chip, port, &fdb->obj, cb);
22912314
mutex_unlock(&chip->reg_lock);
22922315

22932316
return err;
@@ -3980,6 +4003,58 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
39804003
return NULL;
39814004
}
39824005

4006+
static int mv88e6xxx_port_mdb_prepare(struct dsa_switch *ds, int port,
4007+
const struct switchdev_obj_port_mdb *mdb,
4008+
struct switchdev_trans *trans)
4009+
{
4010+
/* We don't need any dynamic resource from the kernel (yet),
4011+
* so skip the prepare phase.
4012+
*/
4013+
4014+
return 0;
4015+
}
4016+
4017+
static void mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port,
4018+
const struct switchdev_obj_port_mdb *mdb,
4019+
struct switchdev_trans *trans)
4020+
{
4021+
struct mv88e6xxx_chip *chip = ds_to_priv(ds);
4022+
4023+
mutex_lock(&chip->reg_lock);
4024+
if (mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
4025+
GLOBAL_ATU_DATA_STATE_MC_STATIC))
4026+
netdev_err(ds->ports[port].netdev, "failed to load multicast MAC address\n");
4027+
mutex_unlock(&chip->reg_lock);
4028+
}
4029+
4030+
static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port,
4031+
const struct switchdev_obj_port_mdb *mdb)
4032+
{
4033+
struct mv88e6xxx_chip *chip = ds_to_priv(ds);
4034+
int err;
4035+
4036+
mutex_lock(&chip->reg_lock);
4037+
err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
4038+
GLOBAL_ATU_DATA_STATE_UNUSED);
4039+
mutex_unlock(&chip->reg_lock);
4040+
4041+
return err;
4042+
}
4043+
4044+
static int mv88e6xxx_port_mdb_dump(struct dsa_switch *ds, int port,
4045+
struct switchdev_obj_port_mdb *mdb,
4046+
int (*cb)(struct switchdev_obj *obj))
4047+
{
4048+
struct mv88e6xxx_chip *chip = ds_to_priv(ds);
4049+
int err;
4050+
4051+
mutex_lock(&chip->reg_lock);
4052+
err = mv88e6xxx_port_db_dump(chip, port, &mdb->obj, cb);
4053+
mutex_unlock(&chip->reg_lock);
4054+
4055+
return err;
4056+
}
4057+
39834058
static struct dsa_switch_ops mv88e6xxx_switch_ops = {
39844059
.probe = mv88e6xxx_drv_probe,
39854060
.get_tag_protocol = mv88e6xxx_get_tag_protocol,
@@ -4015,6 +4090,10 @@ static struct dsa_switch_ops mv88e6xxx_switch_ops = {
40154090
.port_fdb_add = mv88e6xxx_port_fdb_add,
40164091
.port_fdb_del = mv88e6xxx_port_fdb_del,
40174092
.port_fdb_dump = mv88e6xxx_port_fdb_dump,
4093+
.port_mdb_prepare = mv88e6xxx_port_mdb_prepare,
4094+
.port_mdb_add = mv88e6xxx_port_mdb_add,
4095+
.port_mdb_del = mv88e6xxx_port_mdb_del,
4096+
.port_mdb_dump = mv88e6xxx_port_mdb_dump,
40184097
};
40194098

40204099
static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip,

include/net/dsa.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds)
234234
struct switchdev_trans;
235235
struct switchdev_obj;
236236
struct switchdev_obj_port_fdb;
237+
struct switchdev_obj_port_mdb;
237238
struct switchdev_obj_port_vlan;
238239

239240
struct dsa_switch_ops {
@@ -369,6 +370,21 @@ struct dsa_switch_ops {
369370
int (*port_fdb_dump)(struct dsa_switch *ds, int port,
370371
struct switchdev_obj_port_fdb *fdb,
371372
int (*cb)(struct switchdev_obj *obj));
373+
374+
/*
375+
* Multicast database
376+
*/
377+
int (*port_mdb_prepare)(struct dsa_switch *ds, int port,
378+
const struct switchdev_obj_port_mdb *mdb,
379+
struct switchdev_trans *trans);
380+
void (*port_mdb_add)(struct dsa_switch *ds, int port,
381+
const struct switchdev_obj_port_mdb *mdb,
382+
struct switchdev_trans *trans);
383+
int (*port_mdb_del)(struct dsa_switch *ds, int port,
384+
const struct switchdev_obj_port_mdb *mdb);
385+
int (*port_mdb_dump)(struct dsa_switch *ds, int port,
386+
struct switchdev_obj_port_mdb *mdb,
387+
int (*cb)(struct switchdev_obj *obj));
372388
};
373389

374390
void register_switch_driver(struct dsa_switch_ops *type);

0 commit comments

Comments
 (0)