diff options
-rw-r--r-- | drivers/net/dsa/b53/b53_common.c | 16 | ||||
-rw-r--r-- | drivers/net/dsa/b53/b53_priv.h | 3 | ||||
-rw-r--r-- | drivers/net/dsa/microchip/ksz_common.c | 20 | ||||
-rw-r--r-- | drivers/net/dsa/mt7530.c | 10 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 38 | ||||
-rw-r--r-- | drivers/net/dsa/qca8k.c | 15 | ||||
-rw-r--r-- | include/net/dsa.h | 5 | ||||
-rw-r--r-- | include/net/switchdev.h | 12 | ||||
-rw-r--r-- | net/dsa/dsa_priv.h | 2 | ||||
-rw-r--r-- | net/dsa/port.c | 11 | ||||
-rw-r--r-- | net/dsa/slave.c | 100 | ||||
-rw-r--r-- | net/switchdev/switchdev.c | 84 |
12 files changed, 112 insertions, 204 deletions
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 0176d8087344..274f3679f33d 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c | |||
@@ -1227,8 +1227,7 @@ static void b53_arl_search_rd(struct b53_device *dev, u8 idx, | |||
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, | 1229 | static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, |
1230 | struct switchdev_obj_port_fdb *fdb, | 1230 | dsa_fdb_dump_cb_t *cb, void *data) |
1231 | switchdev_obj_dump_cb_t *cb) | ||
1232 | { | 1231 | { |
1233 | if (!ent->is_valid) | 1232 | if (!ent->is_valid) |
1234 | return 0; | 1233 | return 0; |
@@ -1236,16 +1235,11 @@ static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, | |||
1236 | if (port != ent->port) | 1235 | if (port != ent->port) |
1237 | return 0; | 1236 | return 0; |
1238 | 1237 | ||
1239 | ether_addr_copy(fdb->addr, ent->mac); | 1238 | return cb(ent->mac, ent->vid, ent->is_static, data); |
1240 | fdb->vid = ent->vid; | ||
1241 | fdb->ndm_state = ent->is_static ? NUD_NOARP : NUD_REACHABLE; | ||
1242 | |||
1243 | return cb(&fdb->obj); | ||
1244 | } | 1239 | } |
1245 | 1240 | ||
1246 | int b53_fdb_dump(struct dsa_switch *ds, int port, | 1241 | int b53_fdb_dump(struct dsa_switch *ds, int port, |
1247 | struct switchdev_obj_port_fdb *fdb, | 1242 | dsa_fdb_dump_cb_t *cb, void *data) |
1248 | switchdev_obj_dump_cb_t *cb) | ||
1249 | { | 1243 | { |
1250 | struct b53_device *priv = ds->priv; | 1244 | struct b53_device *priv = ds->priv; |
1251 | struct b53_arl_entry results[2]; | 1245 | struct b53_arl_entry results[2]; |
@@ -1263,13 +1257,13 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, | |||
1263 | return ret; | 1257 | return ret; |
1264 | 1258 | ||
1265 | b53_arl_search_rd(priv, 0, &results[0]); | 1259 | b53_arl_search_rd(priv, 0, &results[0]); |
1266 | ret = b53_fdb_copy(port, &results[0], fdb, cb); | 1260 | ret = b53_fdb_copy(port, &results[0], cb, data); |
1267 | if (ret) | 1261 | if (ret) |
1268 | return ret; | 1262 | return ret; |
1269 | 1263 | ||
1270 | if (priv->num_arl_entries > 2) { | 1264 | if (priv->num_arl_entries > 2) { |
1271 | b53_arl_search_rd(priv, 1, &results[1]); | 1265 | b53_arl_search_rd(priv, 1, &results[1]); |
1272 | ret = b53_fdb_copy(port, &results[1], fdb, cb); | 1266 | ret = b53_fdb_copy(port, &results[1], cb, data); |
1273 | if (ret) | 1267 | if (ret) |
1274 | return ret; | 1268 | return ret; |
1275 | 1269 | ||
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index af5d6c166bff..01bd8cbe9a3f 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h | |||
@@ -398,8 +398,7 @@ int b53_fdb_add(struct dsa_switch *ds, int port, | |||
398 | int b53_fdb_del(struct dsa_switch *ds, int port, | 398 | int b53_fdb_del(struct dsa_switch *ds, int port, |
399 | const unsigned char *addr, u16 vid); | 399 | const unsigned char *addr, u16 vid); |
400 | int b53_fdb_dump(struct dsa_switch *ds, int port, | 400 | int b53_fdb_dump(struct dsa_switch *ds, int port, |
401 | struct switchdev_obj_port_fdb *fdb, | 401 | dsa_fdb_dump_cb_t *cb, void *data); |
402 | switchdev_obj_dump_cb_t *cb); | ||
403 | int b53_mirror_add(struct dsa_switch *ds, int port, | 402 | int b53_mirror_add(struct dsa_switch *ds, int port, |
404 | struct dsa_mall_mirror_tc_entry *mirror, bool ingress); | 403 | struct dsa_mall_mirror_tc_entry *mirror, bool ingress); |
405 | void b53_mirror_del(struct dsa_switch *ds, int port, | 404 | void b53_mirror_del(struct dsa_switch *ds, int port, |
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 4de9d90a4bb3..56cd6d365352 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c | |||
@@ -805,12 +805,11 @@ static void convert_alu(struct alu_struct *alu, u32 *alu_table) | |||
805 | } | 805 | } |
806 | 806 | ||
807 | static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, | 807 | static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, |
808 | struct switchdev_obj_port_fdb *fdb, | 808 | dsa_fdb_dump_cb_t *cb, void *data) |
809 | switchdev_obj_dump_cb_t *cb) | ||
810 | { | 809 | { |
811 | struct ksz_device *dev = ds->priv; | 810 | struct ksz_device *dev = ds->priv; |
812 | int ret = 0; | 811 | int ret = 0; |
813 | u32 data; | 812 | u32 ksz_data; |
814 | u32 alu_table[4]; | 813 | u32 alu_table[4]; |
815 | struct alu_struct alu; | 814 | struct alu_struct alu; |
816 | int timeout; | 815 | int timeout; |
@@ -823,8 +822,8 @@ static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, | |||
823 | do { | 822 | do { |
824 | timeout = 1000; | 823 | timeout = 1000; |
825 | do { | 824 | do { |
826 | ksz_read32(dev, REG_SW_ALU_CTRL__4, &data); | 825 | ksz_read32(dev, REG_SW_ALU_CTRL__4, &ksz_data); |
827 | if ((data & ALU_VALID) || !(data & ALU_START)) | 826 | if ((ksz_data & ALU_VALID) || !(ksz_data & ALU_START)) |
828 | break; | 827 | break; |
829 | usleep_range(1, 10); | 828 | usleep_range(1, 10); |
830 | } while (timeout-- > 0); | 829 | } while (timeout-- > 0); |
@@ -841,18 +840,11 @@ static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, | |||
841 | convert_alu(&alu, alu_table); | 840 | convert_alu(&alu, alu_table); |
842 | 841 | ||
843 | if (alu.port_forward & BIT(port)) { | 842 | if (alu.port_forward & BIT(port)) { |
844 | fdb->vid = alu.fid; | 843 | ret = cb(alu.mac, alu.fid, alu.is_static, data); |
845 | if (alu.is_static) | ||
846 | fdb->ndm_state = NUD_NOARP; | ||
847 | else | ||
848 | fdb->ndm_state = NUD_REACHABLE; | ||
849 | ether_addr_copy(fdb->addr, alu.mac); | ||
850 | |||
851 | ret = cb(&fdb->obj); | ||
852 | if (ret) | 844 | if (ret) |
853 | goto exit; | 845 | goto exit; |
854 | } | 846 | } |
855 | } while (data & ALU_START); | 847 | } while (ksz_data & ALU_START); |
856 | 848 | ||
857 | exit: | 849 | exit: |
858 | 850 | ||
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index f92aae8947e6..12700710f26d 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c | |||
@@ -834,8 +834,7 @@ mt7530_port_fdb_del(struct dsa_switch *ds, int port, | |||
834 | 834 | ||
835 | static int | 835 | static int |
836 | mt7530_port_fdb_dump(struct dsa_switch *ds, int port, | 836 | mt7530_port_fdb_dump(struct dsa_switch *ds, int port, |
837 | struct switchdev_obj_port_fdb *fdb, | 837 | dsa_fdb_dump_cb_t *cb, void *data) |
838 | switchdev_obj_dump_cb_t *cb) | ||
839 | { | 838 | { |
840 | struct mt7530_priv *priv = ds->priv; | 839 | struct mt7530_priv *priv = ds->priv; |
841 | struct mt7530_fdb _fdb = { 0 }; | 840 | struct mt7530_fdb _fdb = { 0 }; |
@@ -853,11 +852,8 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port, | |||
853 | if (rsp & ATC_SRCH_HIT) { | 852 | if (rsp & ATC_SRCH_HIT) { |
854 | mt7530_fdb_read(priv, &_fdb); | 853 | mt7530_fdb_read(priv, &_fdb); |
855 | if (_fdb.port_mask & BIT(port)) { | 854 | if (_fdb.port_mask & BIT(port)) { |
856 | ether_addr_copy(fdb->addr, _fdb.mac); | 855 | ret = cb(_fdb.mac, _fdb.vid, _fdb.noarp, |
857 | fdb->vid = _fdb.vid; | 856 | data); |
858 | fdb->ndm_state = _fdb.noarp ? | ||
859 | NUD_NOARP : NUD_REACHABLE; | ||
860 | ret = cb(&fdb->obj); | ||
861 | if (ret < 0) | 857 | if (ret < 0) |
862 | break; | 858 | break; |
863 | } | 859 | } |
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 1f5c202b974d..918d8f0fe091 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c | |||
@@ -1381,10 +1381,10 @@ static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, | |||
1381 | 1381 | ||
1382 | static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip, | 1382 | static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip, |
1383 | u16 fid, u16 vid, int port, | 1383 | u16 fid, u16 vid, int port, |
1384 | struct switchdev_obj *obj, | 1384 | dsa_fdb_dump_cb_t *cb, void *data) |
1385 | switchdev_obj_dump_cb_t *cb) | ||
1386 | { | 1385 | { |
1387 | struct mv88e6xxx_atu_entry addr; | 1386 | struct mv88e6xxx_atu_entry addr; |
1387 | bool is_static; | ||
1388 | int err; | 1388 | int err; |
1389 | 1389 | ||
1390 | addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED; | 1390 | addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED; |
@@ -1401,24 +1401,12 @@ static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip, | |||
1401 | if (addr.trunk || (addr.portvec & BIT(port)) == 0) | 1401 | if (addr.trunk || (addr.portvec & BIT(port)) == 0) |
1402 | continue; | 1402 | continue; |
1403 | 1403 | ||
1404 | if (obj->id == SWITCHDEV_OBJ_ID_PORT_FDB) { | 1404 | if (!is_unicast_ether_addr(addr.mac)) |
1405 | struct switchdev_obj_port_fdb *fdb; | 1405 | continue; |
1406 | |||
1407 | if (!is_unicast_ether_addr(addr.mac)) | ||
1408 | continue; | ||
1409 | |||
1410 | fdb = SWITCHDEV_OBJ_PORT_FDB(obj); | ||
1411 | fdb->vid = vid; | ||
1412 | ether_addr_copy(fdb->addr, addr.mac); | ||
1413 | if (addr.state == MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC) | ||
1414 | fdb->ndm_state = NUD_NOARP; | ||
1415 | else | ||
1416 | fdb->ndm_state = NUD_REACHABLE; | ||
1417 | } else { | ||
1418 | return -EOPNOTSUPP; | ||
1419 | } | ||
1420 | 1406 | ||
1421 | err = cb(obj); | 1407 | is_static = (addr.state == |
1408 | MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); | ||
1409 | err = cb(addr.mac, vid, is_static, data); | ||
1422 | if (err) | 1410 | if (err) |
1423 | return err; | 1411 | return err; |
1424 | } while (!is_broadcast_ether_addr(addr.mac)); | 1412 | } while (!is_broadcast_ether_addr(addr.mac)); |
@@ -1427,8 +1415,7 @@ static int mv88e6xxx_port_db_dump_fid(struct mv88e6xxx_chip *chip, | |||
1427 | } | 1415 | } |
1428 | 1416 | ||
1429 | static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, | 1417 | static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, |
1430 | struct switchdev_obj *obj, | 1418 | dsa_fdb_dump_cb_t *cb, void *data) |
1431 | switchdev_obj_dump_cb_t *cb) | ||
1432 | { | 1419 | { |
1433 | struct mv88e6xxx_vtu_entry vlan = { | 1420 | struct mv88e6xxx_vtu_entry vlan = { |
1434 | .vid = chip->info->max_vid, | 1421 | .vid = chip->info->max_vid, |
@@ -1441,7 +1428,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, | |||
1441 | if (err) | 1428 | if (err) |
1442 | return err; | 1429 | return err; |
1443 | 1430 | ||
1444 | err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, obj, cb); | 1431 | err = mv88e6xxx_port_db_dump_fid(chip, fid, 0, port, cb, data); |
1445 | if (err) | 1432 | if (err) |
1446 | return err; | 1433 | return err; |
1447 | 1434 | ||
@@ -1455,7 +1442,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, | |||
1455 | break; | 1442 | break; |
1456 | 1443 | ||
1457 | err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port, | 1444 | err = mv88e6xxx_port_db_dump_fid(chip, vlan.fid, vlan.vid, port, |
1458 | obj, cb); | 1445 | cb, data); |
1459 | if (err) | 1446 | if (err) |
1460 | return err; | 1447 | return err; |
1461 | } while (vlan.vid < chip->info->max_vid); | 1448 | } while (vlan.vid < chip->info->max_vid); |
@@ -1464,14 +1451,13 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, | |||
1464 | } | 1451 | } |
1465 | 1452 | ||
1466 | static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, | 1453 | static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, |
1467 | struct switchdev_obj_port_fdb *fdb, | 1454 | dsa_fdb_dump_cb_t *cb, void *data) |
1468 | switchdev_obj_dump_cb_t *cb) | ||
1469 | { | 1455 | { |
1470 | struct mv88e6xxx_chip *chip = ds->priv; | 1456 | struct mv88e6xxx_chip *chip = ds->priv; |
1471 | int err; | 1457 | int err; |
1472 | 1458 | ||
1473 | mutex_lock(&chip->reg_lock); | 1459 | mutex_lock(&chip->reg_lock); |
1474 | err = mv88e6xxx_port_db_dump(chip, port, &fdb->obj, cb); | 1460 | err = mv88e6xxx_port_db_dump(chip, port, cb, data); |
1475 | mutex_unlock(&chip->reg_lock); | 1461 | mutex_unlock(&chip->reg_lock); |
1476 | 1462 | ||
1477 | return err; | 1463 | return err; |
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index f8ef823349bc..17977f06cb98 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c | |||
@@ -801,27 +801,20 @@ qca8k_port_fdb_del(struct dsa_switch *ds, int port, | |||
801 | 801 | ||
802 | static int | 802 | static int |
803 | qca8k_port_fdb_dump(struct dsa_switch *ds, int port, | 803 | qca8k_port_fdb_dump(struct dsa_switch *ds, int port, |
804 | struct switchdev_obj_port_fdb *fdb, | 804 | dsa_fdb_dump_cb_t *cb, void *data) |
805 | switchdev_obj_dump_cb_t *cb) | ||
806 | { | 805 | { |
807 | struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; | 806 | struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; |
808 | struct qca8k_fdb _fdb = { 0 }; | 807 | struct qca8k_fdb _fdb = { 0 }; |
809 | int cnt = QCA8K_NUM_FDB_RECORDS; | 808 | int cnt = QCA8K_NUM_FDB_RECORDS; |
809 | bool is_static; | ||
810 | int ret = 0; | 810 | int ret = 0; |
811 | 811 | ||
812 | mutex_lock(&priv->reg_mutex); | 812 | mutex_lock(&priv->reg_mutex); |
813 | while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) { | 813 | while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) { |
814 | if (!_fdb.aging) | 814 | if (!_fdb.aging) |
815 | break; | 815 | break; |
816 | 816 | is_static = (_fdb.aging == QCA8K_ATU_STATUS_STATIC); | |
817 | ether_addr_copy(fdb->addr, _fdb.mac); | 817 | ret = cb(_fdb.mac, _fdb.vid, is_static, data); |
818 | fdb->vid = _fdb.vid; | ||
819 | if (_fdb.aging == QCA8K_ATU_STATUS_STATIC) | ||
820 | fdb->ndm_state = NUD_NOARP; | ||
821 | else | ||
822 | fdb->ndm_state = NUD_REACHABLE; | ||
823 | |||
824 | ret = cb(&fdb->obj); | ||
825 | if (ret) | 818 | if (ret) |
826 | break; | 819 | break; |
827 | } | 820 | } |
diff --git a/include/net/dsa.h b/include/net/dsa.h index 4ef185997b6f..a4f66dbb4b7c 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h | |||
@@ -272,6 +272,8 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds) | |||
272 | return ds->rtable[dst->cpu_dp->ds->index]; | 272 | return ds->rtable[dst->cpu_dp->ds->index]; |
273 | } | 273 | } |
274 | 274 | ||
275 | typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid, | ||
276 | bool is_static, void *data); | ||
275 | struct dsa_switch_ops { | 277 | struct dsa_switch_ops { |
276 | /* | 278 | /* |
277 | * Legacy probing. | 279 | * Legacy probing. |
@@ -386,8 +388,7 @@ struct dsa_switch_ops { | |||
386 | int (*port_fdb_del)(struct dsa_switch *ds, int port, | 388 | int (*port_fdb_del)(struct dsa_switch *ds, int port, |
387 | const unsigned char *addr, u16 vid); | 389 | const unsigned char *addr, u16 vid); |
388 | int (*port_fdb_dump)(struct dsa_switch *ds, int port, | 390 | int (*port_fdb_dump)(struct dsa_switch *ds, int port, |
389 | struct switchdev_obj_port_fdb *fdb, | 391 | dsa_fdb_dump_cb_t *cb, void *data); |
390 | switchdev_obj_dump_cb_t *cb); | ||
391 | 392 | ||
392 | /* | 393 | /* |
393 | * Multicast database | 394 | * Multicast database |
diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 8ae9e3b6392e..d2637a685ca6 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h | |||
@@ -208,9 +208,6 @@ int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | |||
208 | int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], | 208 | int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], |
209 | struct net_device *dev, const unsigned char *addr, | 209 | struct net_device *dev, const unsigned char *addr, |
210 | u16 vid); | 210 | u16 vid); |
211 | int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, | ||
212 | struct net_device *dev, | ||
213 | struct net_device *filter_dev, int *idx); | ||
214 | void switchdev_port_fwd_mark_set(struct net_device *dev, | 211 | void switchdev_port_fwd_mark_set(struct net_device *dev, |
215 | struct net_device *group_dev, | 212 | struct net_device *group_dev, |
216 | bool joining); | 213 | bool joining); |
@@ -309,15 +306,6 @@ static inline int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], | |||
309 | return -EOPNOTSUPP; | 306 | return -EOPNOTSUPP; |
310 | } | 307 | } |
311 | 308 | ||
312 | static inline int switchdev_port_fdb_dump(struct sk_buff *skb, | ||
313 | struct netlink_callback *cb, | ||
314 | struct net_device *dev, | ||
315 | struct net_device *filter_dev, | ||
316 | int *idx) | ||
317 | { | ||
318 | return *idx; | ||
319 | } | ||
320 | |||
321 | static inline bool switchdev_port_same_parent_id(struct net_device *a, | 309 | static inline bool switchdev_port_same_parent_id(struct net_device *a, |
322 | struct net_device *b) | 310 | struct net_device *b) |
323 | { | 311 | { |
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 9c890de6e4dd..1debf9c42fc4 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h | |||
@@ -133,8 +133,6 @@ int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, | |||
133 | u16 vid); | 133 | u16 vid); |
134 | int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, | 134 | int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, |
135 | u16 vid); | 135 | u16 vid); |
136 | int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb, | ||
137 | switchdev_obj_dump_cb_t *cb); | ||
138 | int dsa_port_mdb_add(struct dsa_port *dp, | 136 | int dsa_port_mdb_add(struct dsa_port *dp, |
139 | const struct switchdev_obj_port_mdb *mdb, | 137 | const struct switchdev_obj_port_mdb *mdb, |
140 | struct switchdev_trans *trans); | 138 | struct switchdev_trans *trans); |
diff --git a/net/dsa/port.c b/net/dsa/port.c index 73787828953a..659676ba3f8b 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c | |||
@@ -173,17 +173,6 @@ int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, | |||
173 | return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info); | 173 | return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info); |
174 | } | 174 | } |
175 | 175 | ||
176 | int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb, | ||
177 | switchdev_obj_dump_cb_t *cb) | ||
178 | { | ||
179 | struct dsa_switch *ds = dp->ds; | ||
180 | |||
181 | if (ds->ops->port_fdb_dump) | ||
182 | return ds->ops->port_fdb_dump(ds, dp->index, fdb, cb); | ||
183 | |||
184 | return -EOPNOTSUPP; | ||
185 | } | ||
186 | |||
187 | int dsa_port_mdb_add(struct dsa_port *dp, | 176 | int dsa_port_mdb_add(struct dsa_port *dp, |
188 | const struct switchdev_obj_port_mdb *mdb, | 177 | const struct switchdev_obj_port_mdb *mdb, |
189 | struct switchdev_trans *trans) | 178 | struct switchdev_trans *trans) |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 5807c905fd1d..8c79011c5a83 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -199,6 +199,83 @@ out: | |||
199 | return 0; | 199 | return 0; |
200 | } | 200 | } |
201 | 201 | ||
202 | struct dsa_slave_dump_ctx { | ||
203 | struct net_device *dev; | ||
204 | struct sk_buff *skb; | ||
205 | struct netlink_callback *cb; | ||
206 | int idx; | ||
207 | }; | ||
208 | |||
209 | static int | ||
210 | dsa_slave_port_fdb_do_dump(const unsigned char *addr, u16 vid, | ||
211 | bool is_static, void *data) | ||
212 | { | ||
213 | struct dsa_slave_dump_ctx *dump = data; | ||
214 | u32 portid = NETLINK_CB(dump->cb->skb).portid; | ||
215 | u32 seq = dump->cb->nlh->nlmsg_seq; | ||
216 | struct nlmsghdr *nlh; | ||
217 | struct ndmsg *ndm; | ||
218 | |||
219 | if (dump->idx < dump->cb->args[2]) | ||
220 | goto skip; | ||
221 | |||
222 | nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH, | ||
223 | sizeof(*ndm), NLM_F_MULTI); | ||
224 | if (!nlh) | ||
225 | return -EMSGSIZE; | ||
226 | |||
227 | ndm = nlmsg_data(nlh); | ||
228 | ndm->ndm_family = AF_BRIDGE; | ||
229 | ndm->ndm_pad1 = 0; | ||
230 | ndm->ndm_pad2 = 0; | ||
231 | ndm->ndm_flags = NTF_SELF; | ||
232 | ndm->ndm_type = 0; | ||
233 | ndm->ndm_ifindex = dump->dev->ifindex; | ||
234 | ndm->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE; | ||
235 | |||
236 | if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, addr)) | ||
237 | goto nla_put_failure; | ||
238 | |||
239 | if (vid && nla_put_u16(dump->skb, NDA_VLAN, vid)) | ||
240 | goto nla_put_failure; | ||
241 | |||
242 | nlmsg_end(dump->skb, nlh); | ||
243 | |||
244 | skip: | ||
245 | dump->idx++; | ||
246 | return 0; | ||
247 | |||
248 | nla_put_failure: | ||
249 | nlmsg_cancel(dump->skb, nlh); | ||
250 | return -EMSGSIZE; | ||
251 | } | ||
252 | |||
253 | static int | ||
254 | dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, | ||
255 | struct net_device *dev, struct net_device *filter_dev, | ||
256 | int *idx) | ||
257 | { | ||
258 | struct dsa_slave_dump_ctx dump = { | ||
259 | .dev = dev, | ||
260 | .skb = skb, | ||
261 | .cb = cb, | ||
262 | .idx = *idx, | ||
263 | }; | ||
264 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
265 | struct dsa_port *dp = p->dp; | ||
266 | struct dsa_switch *ds = dp->ds; | ||
267 | int err; | ||
268 | |||
269 | if (!ds->ops->port_fdb_dump) | ||
270 | return -EOPNOTSUPP; | ||
271 | |||
272 | err = ds->ops->port_fdb_dump(ds, dp->index, | ||
273 | dsa_slave_port_fdb_do_dump, | ||
274 | &dump); | ||
275 | *idx = dump.idx; | ||
276 | return err; | ||
277 | } | ||
278 | |||
202 | static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 279 | static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
203 | { | 280 | { |
204 | struct dsa_slave_priv *p = netdev_priv(dev); | 281 | struct dsa_slave_priv *p = netdev_priv(dev); |
@@ -287,26 +364,6 @@ static int dsa_slave_port_obj_del(struct net_device *dev, | |||
287 | return err; | 364 | return err; |
288 | } | 365 | } |
289 | 366 | ||
290 | static int dsa_slave_port_obj_dump(struct net_device *dev, | ||
291 | struct switchdev_obj *obj, | ||
292 | switchdev_obj_dump_cb_t *cb) | ||
293 | { | ||
294 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
295 | struct dsa_port *dp = p->dp; | ||
296 | int err; | ||
297 | |||
298 | switch (obj->id) { | ||
299 | case SWITCHDEV_OBJ_ID_PORT_FDB: | ||
300 | err = dsa_port_fdb_dump(dp, SWITCHDEV_OBJ_PORT_FDB(obj), cb); | ||
301 | break; | ||
302 | default: | ||
303 | err = -EOPNOTSUPP; | ||
304 | break; | ||
305 | } | ||
306 | |||
307 | return err; | ||
308 | } | ||
309 | |||
310 | static int dsa_slave_port_attr_get(struct net_device *dev, | 367 | static int dsa_slave_port_attr_get(struct net_device *dev, |
311 | struct switchdev_attr *attr) | 368 | struct switchdev_attr *attr) |
312 | { | 369 | { |
@@ -974,7 +1031,7 @@ static const struct net_device_ops dsa_slave_netdev_ops = { | |||
974 | .ndo_set_mac_address = dsa_slave_set_mac_address, | 1031 | .ndo_set_mac_address = dsa_slave_set_mac_address, |
975 | .ndo_fdb_add = dsa_legacy_fdb_add, | 1032 | .ndo_fdb_add = dsa_legacy_fdb_add, |
976 | .ndo_fdb_del = dsa_legacy_fdb_del, | 1033 | .ndo_fdb_del = dsa_legacy_fdb_del, |
977 | .ndo_fdb_dump = switchdev_port_fdb_dump, | 1034 | .ndo_fdb_dump = dsa_slave_fdb_dump, |
978 | .ndo_do_ioctl = dsa_slave_ioctl, | 1035 | .ndo_do_ioctl = dsa_slave_ioctl, |
979 | .ndo_get_iflink = dsa_slave_get_iflink, | 1036 | .ndo_get_iflink = dsa_slave_get_iflink, |
980 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1037 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -992,7 +1049,6 @@ static const struct switchdev_ops dsa_slave_switchdev_ops = { | |||
992 | .switchdev_port_attr_set = dsa_slave_port_attr_set, | 1049 | .switchdev_port_attr_set = dsa_slave_port_attr_set, |
993 | .switchdev_port_obj_add = dsa_slave_port_obj_add, | 1050 | .switchdev_port_obj_add = dsa_slave_port_obj_add, |
994 | .switchdev_port_obj_del = dsa_slave_port_obj_del, | 1051 | .switchdev_port_obj_del = dsa_slave_port_obj_del, |
995 | .switchdev_port_obj_dump = dsa_slave_port_obj_dump, | ||
996 | }; | 1052 | }; |
997 | 1053 | ||
998 | static struct device_type dsa_type = { | 1054 | static struct device_type dsa_type = { |
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 25dc67ef9d37..3d32981b9aa1 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -1009,90 +1009,6 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], | |||
1009 | } | 1009 | } |
1010 | EXPORT_SYMBOL_GPL(switchdev_port_fdb_del); | 1010 | EXPORT_SYMBOL_GPL(switchdev_port_fdb_del); |
1011 | 1011 | ||
1012 | struct switchdev_fdb_dump { | ||
1013 | struct switchdev_obj_port_fdb fdb; | ||
1014 | struct net_device *dev; | ||
1015 | struct sk_buff *skb; | ||
1016 | struct netlink_callback *cb; | ||
1017 | int idx; | ||
1018 | }; | ||
1019 | |||
1020 | static int switchdev_port_fdb_dump_cb(struct switchdev_obj *obj) | ||
1021 | { | ||
1022 | struct switchdev_obj_port_fdb *fdb = SWITCHDEV_OBJ_PORT_FDB(obj); | ||
1023 | struct switchdev_fdb_dump *dump = | ||
1024 | container_of(fdb, struct switchdev_fdb_dump, fdb); | ||
1025 | u32 portid = NETLINK_CB(dump->cb->skb).portid; | ||
1026 | u32 seq = dump->cb->nlh->nlmsg_seq; | ||
1027 | struct nlmsghdr *nlh; | ||
1028 | struct ndmsg *ndm; | ||
1029 | |||
1030 | if (dump->idx < dump->cb->args[2]) | ||
1031 | goto skip; | ||
1032 | |||
1033 | nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH, | ||
1034 | sizeof(*ndm), NLM_F_MULTI); | ||
1035 | if (!nlh) | ||
1036 | return -EMSGSIZE; | ||
1037 | |||
1038 | ndm = nlmsg_data(nlh); | ||
1039 | ndm->ndm_family = AF_BRIDGE; | ||
1040 | ndm->ndm_pad1 = 0; | ||
1041 | ndm->ndm_pad2 = 0; | ||
1042 | ndm->ndm_flags = NTF_SELF; | ||
1043 | ndm->ndm_type = 0; | ||
1044 | ndm->ndm_ifindex = dump->dev->ifindex; | ||
1045 | ndm->ndm_state = fdb->ndm_state; | ||
1046 | |||
1047 | if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, fdb->addr)) | ||
1048 | goto nla_put_failure; | ||
1049 | |||
1050 | if (fdb->vid && nla_put_u16(dump->skb, NDA_VLAN, fdb->vid)) | ||
1051 | goto nla_put_failure; | ||
1052 | |||
1053 | nlmsg_end(dump->skb, nlh); | ||
1054 | |||
1055 | skip: | ||
1056 | dump->idx++; | ||
1057 | return 0; | ||
1058 | |||
1059 | nla_put_failure: | ||
1060 | nlmsg_cancel(dump->skb, nlh); | ||
1061 | return -EMSGSIZE; | ||
1062 | } | ||
1063 | |||
1064 | /** | ||
1065 | * switchdev_port_fdb_dump - Dump port FDB (MAC/VLAN) entries | ||
1066 | * | ||
1067 | * @skb: netlink skb | ||
1068 | * @cb: netlink callback | ||
1069 | * @dev: port device | ||
1070 | * @filter_dev: filter device | ||
1071 | * @idx: | ||
1072 | * | ||
1073 | * Dump FDB entries from switch device. | ||
1074 | */ | ||
1075 | int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, | ||
1076 | struct net_device *dev, | ||
1077 | struct net_device *filter_dev, int *idx) | ||
1078 | { | ||
1079 | struct switchdev_fdb_dump dump = { | ||
1080 | .fdb.obj.orig_dev = dev, | ||
1081 | .fdb.obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, | ||
1082 | .dev = dev, | ||
1083 | .skb = skb, | ||
1084 | .cb = cb, | ||
1085 | .idx = *idx, | ||
1086 | }; | ||
1087 | int err; | ||
1088 | |||
1089 | err = switchdev_port_obj_dump(dev, &dump.fdb.obj, | ||
1090 | switchdev_port_fdb_dump_cb); | ||
1091 | *idx = dump.idx; | ||
1092 | return err; | ||
1093 | } | ||
1094 | EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump); | ||
1095 | |||
1096 | bool switchdev_port_same_parent_id(struct net_device *a, | 1012 | bool switchdev_port_same_parent_id(struct net_device *a, |
1097 | struct net_device *b) | 1013 | struct net_device *b) |
1098 | { | 1014 | { |