diff options
author | David S. Miller <davem@davemloft.net> | 2015-08-11 15:00:37 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-11 15:00:37 -0400 |
commit | cdf0969763e020923abe28fddc605add572febc2 (patch) | |
tree | bc568521de044fb42db344a3c5d2625f0029ac0f | |
parent | 2c9c3bbbbfe9f7f700c30d9ac40c1abca59d39ee (diff) |
Revert "Merge branch 'mv88e6xxx-switchdev-fdb'"
This reverts commit f1d5ca434413b20cd3f8c18ff2b634b7782149a5, reversing
changes made to 4933d85c5173832ebd261756522095837583c458.
I applied v2 instead of v3.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dsa/mv88e6171.c | 6 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6352.c | 6 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.c | 223 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.h | 31 | ||||
-rw-r--r-- | drivers/net/ethernet/rocker/rocker.c | 2 | ||||
-rw-r--r-- | include/net/dsa.h | 16 | ||||
-rw-r--r-- | include/net/switchdev.h | 3 | ||||
-rw-r--r-- | net/bridge/br_fdb.c | 2 | ||||
-rw-r--r-- | net/dsa/slave.c | 218 | ||||
-rw-r--r-- | net/switchdev/switchdev.c | 7 |
10 files changed, 197 insertions, 317 deletions
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 735f04cd83ee..1c7808495a9d 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c | |||
@@ -116,9 +116,9 @@ struct dsa_switch_driver mv88e6171_switch_driver = { | |||
116 | .port_join_bridge = mv88e6xxx_join_bridge, | 116 | .port_join_bridge = mv88e6xxx_join_bridge, |
117 | .port_leave_bridge = mv88e6xxx_leave_bridge, | 117 | .port_leave_bridge = mv88e6xxx_leave_bridge, |
118 | .port_stp_update = mv88e6xxx_port_stp_update, | 118 | .port_stp_update = mv88e6xxx_port_stp_update, |
119 | .port_fdb_add = mv88e6xxx_port_fdb_add, | 119 | .fdb_add = mv88e6xxx_port_fdb_add, |
120 | .port_fdb_del = mv88e6xxx_port_fdb_del, | 120 | .fdb_del = mv88e6xxx_port_fdb_del, |
121 | .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, | 121 | .fdb_getnext = mv88e6xxx_port_fdb_getnext, |
122 | }; | 122 | }; |
123 | 123 | ||
124 | MODULE_ALIAS("platform:mv88e6171"); | 124 | MODULE_ALIAS("platform:mv88e6171"); |
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index a18f7c83d4cb..7e935852e192 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c | |||
@@ -343,9 +343,9 @@ struct dsa_switch_driver mv88e6352_switch_driver = { | |||
343 | .port_join_bridge = mv88e6xxx_join_bridge, | 343 | .port_join_bridge = mv88e6xxx_join_bridge, |
344 | .port_leave_bridge = mv88e6xxx_leave_bridge, | 344 | .port_leave_bridge = mv88e6xxx_leave_bridge, |
345 | .port_stp_update = mv88e6xxx_port_stp_update, | 345 | .port_stp_update = mv88e6xxx_port_stp_update, |
346 | .port_fdb_add = mv88e6xxx_port_fdb_add, | 346 | .fdb_add = mv88e6xxx_port_fdb_add, |
347 | .port_fdb_del = mv88e6xxx_port_fdb_del, | 347 | .fdb_del = mv88e6xxx_port_fdb_del, |
348 | .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, | 348 | .fdb_getnext = mv88e6xxx_port_fdb_getnext, |
349 | }; | 349 | }; |
350 | 350 | ||
351 | MODULE_ALIAS("platform:mv88e6172"); | 351 | MODULE_ALIAS("platform:mv88e6172"); |
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 9c6781de533b..109452056eff 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c | |||
@@ -964,7 +964,7 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd) | |||
964 | { | 964 | { |
965 | int ret; | 965 | int ret; |
966 | 966 | ||
967 | ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); | 967 | ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x01, fid); |
968 | if (ret < 0) | 968 | if (ret < 0) |
969 | return ret; | 969 | return ret; |
970 | 970 | ||
@@ -1091,7 +1091,7 @@ int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) | |||
1091 | ps->bridge_mask[fid] = br_port_mask; | 1091 | ps->bridge_mask[fid] = br_port_mask; |
1092 | 1092 | ||
1093 | if (fid != ps->fid[port]) { | 1093 | if (fid != ps->fid[port]) { |
1094 | clear_bit(ps->fid[port], ps->fid_bitmap); | 1094 | ps->fid_mask |= 1 << ps->fid[port]; |
1095 | ps->fid[port] = fid; | 1095 | ps->fid[port] = fid; |
1096 | ret = _mv88e6xxx_update_bridge_config(ds, fid); | 1096 | ret = _mv88e6xxx_update_bridge_config(ds, fid); |
1097 | } | 1097 | } |
@@ -1125,16 +1125,9 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) | |||
1125 | 1125 | ||
1126 | mutex_lock(&ps->smi_mutex); | 1126 | mutex_lock(&ps->smi_mutex); |
1127 | 1127 | ||
1128 | newfid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID, 1); | 1128 | newfid = __ffs(ps->fid_mask); |
1129 | if (unlikely(newfid > ps->num_ports)) { | ||
1130 | netdev_err(ds->ports[port], "all first %d FIDs are used\n", | ||
1131 | ps->num_ports); | ||
1132 | ret = -ENOSPC; | ||
1133 | goto unlock; | ||
1134 | } | ||
1135 | |||
1136 | ps->fid[port] = newfid; | 1129 | ps->fid[port] = newfid; |
1137 | set_bit(newfid, ps->fid_bitmap); | 1130 | ps->fid_mask &= ~(1 << newfid); |
1138 | ps->bridge_mask[fid] &= ~(1 << port); | 1131 | ps->bridge_mask[fid] &= ~(1 << port); |
1139 | ps->bridge_mask[newfid] = 1 << port; | 1132 | ps->bridge_mask[newfid] = 1 << port; |
1140 | 1133 | ||
@@ -1142,7 +1135,6 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) | |||
1142 | if (!ret) | 1135 | if (!ret) |
1143 | ret = _mv88e6xxx_update_bridge_config(ds, newfid); | 1136 | ret = _mv88e6xxx_update_bridge_config(ds, newfid); |
1144 | 1137 | ||
1145 | unlock: | ||
1146 | mutex_unlock(&ps->smi_mutex); | 1138 | mutex_unlock(&ps->smi_mutex); |
1147 | 1139 | ||
1148 | return ret; | 1140 | return ret; |
@@ -1182,8 +1174,8 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) | |||
1182 | return 0; | 1174 | return 0; |
1183 | } | 1175 | } |
1184 | 1176 | ||
1185 | static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, | 1177 | static int __mv88e6xxx_write_addr(struct dsa_switch *ds, |
1186 | const u8 addr[ETH_ALEN]) | 1178 | const unsigned char *addr) |
1187 | { | 1179 | { |
1188 | int i, ret; | 1180 | int i, ret; |
1189 | 1181 | ||
@@ -1198,7 +1190,7 @@ static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, | |||
1198 | return 0; | 1190 | return 0; |
1199 | } | 1191 | } |
1200 | 1192 | ||
1201 | static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, u8 addr[ETH_ALEN]) | 1193 | static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr) |
1202 | { | 1194 | { |
1203 | int i, ret; | 1195 | int i, ret; |
1204 | 1196 | ||
@@ -1214,190 +1206,109 @@ static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, u8 addr[ETH_ALEN]) | |||
1214 | return 0; | 1206 | return 0; |
1215 | } | 1207 | } |
1216 | 1208 | ||
1217 | static int _mv88e6xxx_atu_load(struct dsa_switch *ds, | 1209 | static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port, |
1218 | struct mv88e6xxx_atu_entry *entry) | 1210 | const unsigned char *addr, int state) |
1219 | { | ||
1220 | u16 reg = 0; | ||
1221 | int ret; | ||
1222 | |||
1223 | ret = _mv88e6xxx_atu_wait(ds); | ||
1224 | if (ret < 0) | ||
1225 | return ret; | ||
1226 | |||
1227 | ret = _mv88e6xxx_atu_mac_write(ds, entry->mac); | ||
1228 | if (ret < 0) | ||
1229 | return ret; | ||
1230 | |||
1231 | if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) { | ||
1232 | unsigned int mask, shift; | ||
1233 | |||
1234 | if (entry->trunk) { | ||
1235 | reg |= GLOBAL_ATU_DATA_TRUNK; | ||
1236 | mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK; | ||
1237 | shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT; | ||
1238 | } else { | ||
1239 | mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK; | ||
1240 | shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT; | ||
1241 | } | ||
1242 | |||
1243 | reg |= (entry->portv_trunkid << shift) & mask; | ||
1244 | } | ||
1245 | |||
1246 | reg |= entry->state & GLOBAL_ATU_DATA_STATE_MASK; | ||
1247 | |||
1248 | ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, reg); | ||
1249 | if (ret < 0) | ||
1250 | return ret; | ||
1251 | |||
1252 | return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB); | ||
1253 | } | ||
1254 | |||
1255 | static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, | ||
1256 | const u8 addr[ETH_ALEN], | ||
1257 | struct mv88e6xxx_atu_entry *entry) | ||
1258 | { | 1211 | { |
1259 | struct mv88e6xxx_atu_entry next = { 0 }; | 1212 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
1213 | u8 fid = ps->fid[port]; | ||
1260 | int ret; | 1214 | int ret; |
1261 | 1215 | ||
1262 | next.fid = fid; | ||
1263 | |||
1264 | ret = _mv88e6xxx_atu_wait(ds); | 1216 | ret = _mv88e6xxx_atu_wait(ds); |
1265 | if (ret < 0) | 1217 | if (ret < 0) |
1266 | return ret; | 1218 | return ret; |
1267 | 1219 | ||
1268 | ret = _mv88e6xxx_atu_mac_write(ds, addr); | 1220 | ret = __mv88e6xxx_write_addr(ds, addr); |
1269 | if (ret < 0) | 1221 | if (ret < 0) |
1270 | return ret; | 1222 | return ret; |
1271 | 1223 | ||
1272 | ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); | 1224 | ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, |
1273 | if (ret < 0) | 1225 | (0x10 << port) | state); |
1274 | return ret; | 1226 | if (ret) |
1275 | |||
1276 | ret = _mv88e6xxx_atu_mac_read(ds, next.mac); | ||
1277 | if (ret < 0) | ||
1278 | return ret; | ||
1279 | |||
1280 | ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); | ||
1281 | if (ret < 0) | ||
1282 | return ret; | ||
1283 | |||
1284 | next.state = ret & GLOBAL_ATU_DATA_STATE_MASK; | ||
1285 | if (next.state != GLOBAL_ATU_DATA_STATE_UNUSED) { | ||
1286 | unsigned int mask, shift; | ||
1287 | |||
1288 | if (ret & GLOBAL_ATU_DATA_TRUNK) { | ||
1289 | next.trunk = true; | ||
1290 | mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK; | ||
1291 | shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT; | ||
1292 | } else { | ||
1293 | next.trunk = false; | ||
1294 | mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK; | ||
1295 | shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT; | ||
1296 | } | ||
1297 | |||
1298 | next.portv_trunkid = (ret & mask) >> shift; | ||
1299 | } | ||
1300 | |||
1301 | *entry = next; | ||
1302 | return 0; | ||
1303 | } | ||
1304 | |||
1305 | static int _mv88e6xxx_port_vid_to_fid(struct dsa_switch *ds, int port, u16 vid) | ||
1306 | { | ||
1307 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | ||
1308 | |||
1309 | if (vid == 0) | ||
1310 | return ps->fid[port]; | ||
1311 | |||
1312 | return -ENOENT; | ||
1313 | } | ||
1314 | |||
1315 | static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, u16 vid, | ||
1316 | const u8 addr[ETH_ALEN], u8 state) | ||
1317 | { | ||
1318 | struct mv88e6xxx_atu_entry entry = { 0 }; | ||
1319 | int ret; | ||
1320 | |||
1321 | ret = _mv88e6xxx_port_vid_to_fid(ds, port, vid); | ||
1322 | if (ret < 0) | ||
1323 | return ret; | 1227 | return ret; |
1324 | 1228 | ||
1325 | entry.fid = ret; | 1229 | ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_LOAD_DB); |
1326 | entry.state = state; | ||
1327 | ether_addr_copy(entry.mac, addr); | ||
1328 | if (state != GLOBAL_ATU_DATA_STATE_UNUSED) { | ||
1329 | entry.trunk = false; | ||
1330 | entry.portv_trunkid = BIT(port); | ||
1331 | } | ||
1332 | 1230 | ||
1333 | return _mv88e6xxx_atu_load(ds, &entry); | 1231 | return ret; |
1334 | } | 1232 | } |
1335 | 1233 | ||
1336 | int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, u16 vid, | 1234 | int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, |
1337 | const u8 addr[ETH_ALEN]) | 1235 | const unsigned char *addr, u16 vid) |
1338 | { | 1236 | { |
1339 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | 1237 | int state = is_multicast_ether_addr(addr) ? |
1340 | u8 state = is_multicast_ether_addr(addr) ? | ||
1341 | GLOBAL_ATU_DATA_STATE_MC_STATIC : | 1238 | GLOBAL_ATU_DATA_STATE_MC_STATIC : |
1342 | GLOBAL_ATU_DATA_STATE_UC_STATIC; | 1239 | GLOBAL_ATU_DATA_STATE_UC_STATIC; |
1240 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | ||
1343 | int ret; | 1241 | int ret; |
1344 | 1242 | ||
1345 | mutex_lock(&ps->smi_mutex); | 1243 | mutex_lock(&ps->smi_mutex); |
1346 | ret = _mv88e6xxx_port_fdb_load(ds, port, vid, addr, state); | 1244 | ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state); |
1347 | mutex_unlock(&ps->smi_mutex); | 1245 | mutex_unlock(&ps->smi_mutex); |
1348 | 1246 | ||
1349 | return ret; | 1247 | return ret; |
1350 | } | 1248 | } |
1351 | 1249 | ||
1352 | int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, u16 vid, | 1250 | int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, |
1353 | const u8 addr[ETH_ALEN]) | 1251 | const unsigned char *addr, u16 vid) |
1354 | { | 1252 | { |
1355 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | 1253 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
1356 | u8 state = GLOBAL_ATU_DATA_STATE_UNUSED; | ||
1357 | int ret; | 1254 | int ret; |
1358 | 1255 | ||
1359 | mutex_lock(&ps->smi_mutex); | 1256 | mutex_lock(&ps->smi_mutex); |
1360 | ret = _mv88e6xxx_port_fdb_load(ds, port, vid, addr, state); | 1257 | ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, |
1258 | GLOBAL_ATU_DATA_STATE_UNUSED); | ||
1361 | mutex_unlock(&ps->smi_mutex); | 1259 | mutex_unlock(&ps->smi_mutex); |
1362 | 1260 | ||
1363 | return ret; | 1261 | return ret; |
1364 | } | 1262 | } |
1365 | 1263 | ||
1366 | int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, u16 *vid, | 1264 | static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port, |
1367 | u8 addr[ETH_ALEN], bool *is_static) | 1265 | unsigned char *addr, bool *is_static) |
1368 | { | 1266 | { |
1369 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | 1267 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
1370 | struct mv88e6xxx_atu_entry next; | 1268 | u8 fid = ps->fid[port]; |
1371 | u16 fid; | 1269 | int ret, state; |
1372 | int ret; | ||
1373 | 1270 | ||
1374 | mutex_lock(&ps->smi_mutex); | 1271 | ret = _mv88e6xxx_atu_wait(ds); |
1272 | if (ret < 0) | ||
1273 | return ret; | ||
1375 | 1274 | ||
1376 | ret = _mv88e6xxx_port_vid_to_fid(ds, port, *vid); | 1275 | ret = __mv88e6xxx_write_addr(ds, addr); |
1377 | if (ret < 0) | 1276 | if (ret < 0) |
1378 | goto unlock; | 1277 | return ret; |
1379 | fid = ret; | ||
1380 | 1278 | ||
1381 | do { | 1279 | do { |
1382 | if (is_broadcast_ether_addr(addr)) { | 1280 | ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); |
1383 | ret = -ENOENT; | 1281 | if (ret < 0) |
1384 | goto unlock; | 1282 | return ret; |
1385 | } | ||
1386 | 1283 | ||
1387 | ret = _mv88e6xxx_atu_getnext(ds, fid, addr, &next); | 1284 | ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); |
1388 | if (ret < 0) | 1285 | if (ret < 0) |
1389 | goto unlock; | 1286 | return ret; |
1287 | state = ret & GLOBAL_ATU_DATA_STATE_MASK; | ||
1288 | if (state == GLOBAL_ATU_DATA_STATE_UNUSED) | ||
1289 | return -ENOENT; | ||
1290 | } while (!(((ret >> 4) & 0xff) & (1 << port))); | ||
1390 | 1291 | ||
1391 | ether_addr_copy(addr, next.mac); | 1292 | ret = __mv88e6xxx_read_addr(ds, addr); |
1293 | if (ret < 0) | ||
1294 | return ret; | ||
1392 | 1295 | ||
1393 | if (next.state == GLOBAL_ATU_DATA_STATE_UNUSED) | 1296 | *is_static = state == (is_multicast_ether_addr(addr) ? |
1394 | continue; | 1297 | GLOBAL_ATU_DATA_STATE_MC_STATIC : |
1395 | } while (next.trunk || (next.portv_trunkid & BIT(port)) == 0); | 1298 | GLOBAL_ATU_DATA_STATE_UC_STATIC); |
1299 | |||
1300 | return 0; | ||
1301 | } | ||
1302 | |||
1303 | /* get next entry for port */ | ||
1304 | int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, | ||
1305 | unsigned char *addr, bool *is_static) | ||
1306 | { | ||
1307 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | ||
1308 | int ret; | ||
1396 | 1309 | ||
1397 | *is_static = next.state == (is_multicast_ether_addr(addr) ? | 1310 | mutex_lock(&ps->smi_mutex); |
1398 | GLOBAL_ATU_DATA_STATE_MC_STATIC : | 1311 | ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static); |
1399 | GLOBAL_ATU_DATA_STATE_UC_STATIC); | ||
1400 | unlock: | ||
1401 | mutex_unlock(&ps->smi_mutex); | 1312 | mutex_unlock(&ps->smi_mutex); |
1402 | 1313 | ||
1403 | return ret; | 1314 | return ret; |
@@ -1641,9 +1552,9 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) | |||
1641 | * ports, and allow each of the 'real' ports to only talk to | 1552 | * ports, and allow each of the 'real' ports to only talk to |
1642 | * the upstream port. | 1553 | * the upstream port. |
1643 | */ | 1554 | */ |
1644 | fid = port + 1; | 1555 | fid = __ffs(ps->fid_mask); |
1645 | ps->fid[port] = fid; | 1556 | ps->fid[port] = fid; |
1646 | set_bit(fid, ps->fid_bitmap); | 1557 | ps->fid_mask &= ~(1 << fid); |
1647 | 1558 | ||
1648 | if (!dsa_is_cpu_port(ds, port)) | 1559 | if (!dsa_is_cpu_port(ds, port)) |
1649 | ps->bridge_mask[fid] = 1 << port; | 1560 | ps->bridge_mask[fid] = 1 << port; |
@@ -1740,7 +1651,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, | |||
1740 | unsigned char addr[6]; | 1651 | unsigned char addr[6]; |
1741 | int ret, data, state; | 1652 | int ret, data, state; |
1742 | 1653 | ||
1743 | ret = _mv88e6xxx_atu_mac_write(ds, bcast); | 1654 | ret = __mv88e6xxx_write_addr(ds, bcast); |
1744 | if (ret < 0) | 1655 | if (ret < 0) |
1745 | return ret; | 1656 | return ret; |
1746 | 1657 | ||
@@ -1755,7 +1666,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, | |||
1755 | state = data & GLOBAL_ATU_DATA_STATE_MASK; | 1666 | state = data & GLOBAL_ATU_DATA_STATE_MASK; |
1756 | if (state == GLOBAL_ATU_DATA_STATE_UNUSED) | 1667 | if (state == GLOBAL_ATU_DATA_STATE_UNUSED) |
1757 | break; | 1668 | break; |
1758 | ret = _mv88e6xxx_atu_mac_read(ds, addr); | 1669 | ret = __mv88e6xxx_read_addr(ds, addr); |
1759 | if (ret < 0) | 1670 | if (ret < 0) |
1760 | return ret; | 1671 | return ret; |
1761 | mv88e6xxx_atu_show_entry(s, dbnum, addr, data); | 1672 | mv88e6xxx_atu_show_entry(s, dbnum, addr, data); |
@@ -1942,6 +1853,8 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) | |||
1942 | 1853 | ||
1943 | ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; | 1854 | ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; |
1944 | 1855 | ||
1856 | ps->fid_mask = (1 << DSA_MAX_PORTS) - 1; | ||
1857 | |||
1945 | INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); | 1858 | INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); |
1946 | 1859 | ||
1947 | name = kasprintf(GFP_KERNEL, "dsa%d", ds->index); | 1860 | name = kasprintf(GFP_KERNEL, "dsa%d", ds->index); |
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index a94c0cbb3813..8b017d65b691 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h | |||
@@ -11,8 +11,6 @@ | |||
11 | #ifndef __MV88E6XXX_H | 11 | #ifndef __MV88E6XXX_H |
12 | #define __MV88E6XXX_H | 12 | #define __MV88E6XXX_H |
13 | 13 | ||
14 | #include <linux/if_vlan.h> | ||
15 | |||
16 | #ifndef UINT64_MAX | 14 | #ifndef UINT64_MAX |
17 | #define UINT64_MAX (u64)(~((u64)0)) | 15 | #define UINT64_MAX (u64)(~((u64)0)) |
18 | #endif | 16 | #endif |
@@ -171,7 +169,6 @@ | |||
171 | #define GLOBAL_MAC_01 0x01 | 169 | #define GLOBAL_MAC_01 0x01 |
172 | #define GLOBAL_MAC_23 0x02 | 170 | #define GLOBAL_MAC_23 0x02 |
173 | #define GLOBAL_MAC_45 0x03 | 171 | #define GLOBAL_MAC_45 0x03 |
174 | #define GLOBAL_ATU_FID 0x01 /* 6097 6165 6351 6352 */ | ||
175 | #define GLOBAL_CONTROL 0x04 | 172 | #define GLOBAL_CONTROL 0x04 |
176 | #define GLOBAL_CONTROL_SW_RESET BIT(15) | 173 | #define GLOBAL_CONTROL_SW_RESET BIT(15) |
177 | #define GLOBAL_CONTROL_PPU_ENABLE BIT(14) | 174 | #define GLOBAL_CONTROL_PPU_ENABLE BIT(14) |
@@ -206,8 +203,6 @@ | |||
206 | #define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY) | 203 | #define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY) |
207 | #define GLOBAL_ATU_DATA 0x0c | 204 | #define GLOBAL_ATU_DATA 0x0c |
208 | #define GLOBAL_ATU_DATA_TRUNK BIT(15) | 205 | #define GLOBAL_ATU_DATA_TRUNK BIT(15) |
209 | #define GLOBAL_ATU_DATA_TRUNK_ID_MASK 0x00f0 | ||
210 | #define GLOBAL_ATU_DATA_TRUNK_ID_SHIFT 4 | ||
211 | #define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0 | 206 | #define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0 |
212 | #define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4 | 207 | #define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4 |
213 | #define GLOBAL_ATU_DATA_STATE_MASK 0x0f | 208 | #define GLOBAL_ATU_DATA_STATE_MASK 0x0f |
@@ -318,14 +313,6 @@ | |||
318 | #define GLOBAL2_QOS_WEIGHT 0x1c | 313 | #define GLOBAL2_QOS_WEIGHT 0x1c |
319 | #define GLOBAL2_MISC 0x1d | 314 | #define GLOBAL2_MISC 0x1d |
320 | 315 | ||
321 | struct mv88e6xxx_atu_entry { | ||
322 | u16 fid; | ||
323 | u8 state; | ||
324 | bool trunk; | ||
325 | u16 portv_trunkid; | ||
326 | u8 mac[ETH_ALEN]; | ||
327 | }; | ||
328 | |||
329 | struct mv88e6xxx_priv_state { | 316 | struct mv88e6xxx_priv_state { |
330 | /* When using multi-chip addressing, this mutex protects | 317 | /* When using multi-chip addressing, this mutex protects |
331 | * access to the indirect access registers. (In single-chip | 318 | * access to the indirect access registers. (In single-chip |
@@ -364,9 +351,9 @@ struct mv88e6xxx_priv_state { | |||
364 | 351 | ||
365 | /* hw bridging */ | 352 | /* hw bridging */ |
366 | 353 | ||
367 | DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */ | 354 | u32 fid_mask; |
368 | u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */ | 355 | u8 fid[DSA_MAX_PORTS]; |
369 | u16 bridge_mask[DSA_MAX_PORTS]; /* br groups (indexed by FID) */ | 356 | u16 bridge_mask[DSA_MAX_PORTS]; |
370 | 357 | ||
371 | unsigned long port_state_update_mask; | 358 | unsigned long port_state_update_mask; |
372 | u8 port_state[DSA_MAX_PORTS]; | 359 | u8 port_state[DSA_MAX_PORTS]; |
@@ -426,15 +413,15 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, | |||
426 | int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); | 413 | int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); |
427 | int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); | 414 | int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); |
428 | int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); | 415 | int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); |
416 | int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, | ||
417 | const unsigned char *addr, u16 vid); | ||
418 | int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, | ||
419 | const unsigned char *addr, u16 vid); | ||
420 | int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, | ||
421 | unsigned char *addr, bool *is_static); | ||
429 | int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg); | 422 | int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg); |
430 | int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, | 423 | int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, |
431 | int reg, int val); | 424 | int reg, int val); |
432 | int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, u16 vid, | ||
433 | const u8 addr[ETH_ALEN]); | ||
434 | int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, u16 vid, | ||
435 | const u8 addr[ETH_ALEN]); | ||
436 | int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, u16 *vid, | ||
437 | u8 addr[ETH_ALEN], bool *is_static); | ||
438 | 425 | ||
439 | extern struct dsa_switch_driver mv88e6131_switch_driver; | 426 | extern struct dsa_switch_driver mv88e6131_switch_driver; |
440 | extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; | 427 | extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; |
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 80bb25c5a644..b77e0e7307d4 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c | |||
@@ -4543,7 +4543,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, | |||
4543 | hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { | 4543 | hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { |
4544 | if (found->key.pport != rocker_port->pport) | 4544 | if (found->key.pport != rocker_port->pport) |
4545 | continue; | 4545 | continue; |
4546 | ether_addr_copy(fdb->addr, found->key.addr); | 4546 | fdb->addr = found->key.addr; |
4547 | fdb->vid = rocker_port_vlan_to_vid(rocker_port, | 4547 | fdb->vid = rocker_port_vlan_to_vid(rocker_port, |
4548 | found->key.vlan_id); | 4548 | found->key.vlan_id); |
4549 | err = obj->cb(rocker_port->dev, obj); | 4549 | err = obj->cb(rocker_port->dev, obj); |
diff --git a/include/net/dsa.h b/include/net/dsa.h index 091d35f77180..fbca63ba8f73 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h | |||
@@ -296,16 +296,12 @@ struct dsa_switch_driver { | |||
296 | u32 br_port_mask); | 296 | u32 br_port_mask); |
297 | int (*port_stp_update)(struct dsa_switch *ds, int port, | 297 | int (*port_stp_update)(struct dsa_switch *ds, int port, |
298 | u8 state); | 298 | u8 state); |
299 | 299 | int (*fdb_add)(struct dsa_switch *ds, int port, | |
300 | /* | 300 | const unsigned char *addr, u16 vid); |
301 | * Forwarding database | 301 | int (*fdb_del)(struct dsa_switch *ds, int port, |
302 | */ | 302 | const unsigned char *addr, u16 vid); |
303 | int (*port_fdb_add)(struct dsa_switch *ds, int port, u16 vid, | 303 | int (*fdb_getnext)(struct dsa_switch *ds, int port, |
304 | const u8 addr[ETH_ALEN]); | 304 | unsigned char *addr, bool *is_static); |
305 | int (*port_fdb_del)(struct dsa_switch *ds, int port, u16 vid, | ||
306 | const u8 addr[ETH_ALEN]); | ||
307 | int (*port_fdb_getnext)(struct dsa_switch *ds, int port, u16 *vid, | ||
308 | u8 addr[ETH_ALEN], bool *is_static); | ||
309 | }; | 305 | }; |
310 | 306 | ||
311 | void register_switch_driver(struct dsa_switch_driver *type); | 307 | void register_switch_driver(struct dsa_switch_driver *type); |
diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 0e296b82aef3..89da8934519b 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h | |||
@@ -70,9 +70,8 @@ struct switchdev_obj { | |||
70 | u32 tb_id; | 70 | u32 tb_id; |
71 | } ipv4_fib; | 71 | } ipv4_fib; |
72 | struct switchdev_obj_fdb { /* PORT_FDB */ | 72 | struct switchdev_obj_fdb { /* PORT_FDB */ |
73 | u8 addr[ETH_ALEN]; | 73 | const unsigned char *addr; |
74 | u16 vid; | 74 | u16 vid; |
75 | bool is_static; | ||
76 | } fdb; | 75 | } fdb; |
77 | } u; | 76 | } u; |
78 | }; | 77 | }; |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 5656b44bf3de..9e9875da0a4f 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -136,11 +136,11 @@ static void fdb_del_external_learn(struct net_bridge_fdb_entry *f) | |||
136 | struct switchdev_obj obj = { | 136 | struct switchdev_obj obj = { |
137 | .id = SWITCHDEV_OBJ_PORT_FDB, | 137 | .id = SWITCHDEV_OBJ_PORT_FDB, |
138 | .u.fdb = { | 138 | .u.fdb = { |
139 | .addr = f->addr.addr, | ||
139 | .vid = f->vlan_id, | 140 | .vid = f->vlan_id, |
140 | }, | 141 | }, |
141 | }; | 142 | }; |
142 | 143 | ||
143 | ether_addr_copy(obj.u.fdb.addr, f->addr.addr); | ||
144 | switchdev_port_obj_del(f->dst->dev, &obj); | 144 | switchdev_port_obj_del(f->dst->dev, &obj); |
145 | } | 145 | } |
146 | 146 | ||
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 1dbdeaab2bb4..0010c690cc67 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <net/switchdev.h> | 19 | #include <net/switchdev.h> |
20 | #include <linux/if_bridge.h> | 20 | #include <linux/if_bridge.h> |
21 | #include <linux/netpoll.h> | 21 | #include <linux/netpoll.h> |
22 | #include <linux/if_vlan.h> | ||
23 | #include "dsa_priv.h" | 22 | #include "dsa_priv.h" |
24 | 23 | ||
25 | /* slave mii_bus handling ***************************************************/ | 24 | /* slave mii_bus handling ***************************************************/ |
@@ -201,6 +200,105 @@ out: | |||
201 | return 0; | 200 | return 0; |
202 | } | 201 | } |
203 | 202 | ||
203 | static int dsa_slave_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | ||
204 | struct net_device *dev, | ||
205 | const unsigned char *addr, u16 vid, u16 nlm_flags) | ||
206 | { | ||
207 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
208 | struct dsa_switch *ds = p->parent; | ||
209 | int ret = -EOPNOTSUPP; | ||
210 | |||
211 | if (ds->drv->fdb_add) | ||
212 | ret = ds->drv->fdb_add(ds, p->port, addr, vid); | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | static int dsa_slave_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], | ||
218 | struct net_device *dev, | ||
219 | const unsigned char *addr, u16 vid) | ||
220 | { | ||
221 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
222 | struct dsa_switch *ds = p->parent; | ||
223 | int ret = -EOPNOTSUPP; | ||
224 | |||
225 | if (ds->drv->fdb_del) | ||
226 | ret = ds->drv->fdb_del(ds, p->port, addr, vid); | ||
227 | |||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | static int dsa_slave_fill_info(struct net_device *dev, struct sk_buff *skb, | ||
232 | const unsigned char *addr, u16 vid, | ||
233 | bool is_static, | ||
234 | u32 portid, u32 seq, int type, | ||
235 | unsigned int flags) | ||
236 | { | ||
237 | struct nlmsghdr *nlh; | ||
238 | struct ndmsg *ndm; | ||
239 | |||
240 | nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags); | ||
241 | if (!nlh) | ||
242 | return -EMSGSIZE; | ||
243 | |||
244 | ndm = nlmsg_data(nlh); | ||
245 | ndm->ndm_family = AF_BRIDGE; | ||
246 | ndm->ndm_pad1 = 0; | ||
247 | ndm->ndm_pad2 = 0; | ||
248 | ndm->ndm_flags = NTF_EXT_LEARNED; | ||
249 | ndm->ndm_type = 0; | ||
250 | ndm->ndm_ifindex = dev->ifindex; | ||
251 | ndm->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE; | ||
252 | |||
253 | if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) | ||
254 | goto nla_put_failure; | ||
255 | |||
256 | if (vid && nla_put_u16(skb, NDA_VLAN, vid)) | ||
257 | goto nla_put_failure; | ||
258 | |||
259 | nlmsg_end(skb, nlh); | ||
260 | return 0; | ||
261 | |||
262 | nla_put_failure: | ||
263 | nlmsg_cancel(skb, nlh); | ||
264 | return -EMSGSIZE; | ||
265 | } | ||
266 | |||
267 | /* Dump information about entries, in response to GETNEIGH */ | ||
268 | static int dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, | ||
269 | struct net_device *dev, | ||
270 | struct net_device *filter_dev, int idx) | ||
271 | { | ||
272 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
273 | struct dsa_switch *ds = p->parent; | ||
274 | unsigned char addr[ETH_ALEN] = { 0 }; | ||
275 | int ret; | ||
276 | |||
277 | if (!ds->drv->fdb_getnext) | ||
278 | return -EOPNOTSUPP; | ||
279 | |||
280 | for (; ; idx++) { | ||
281 | bool is_static; | ||
282 | |||
283 | ret = ds->drv->fdb_getnext(ds, p->port, addr, &is_static); | ||
284 | if (ret < 0) | ||
285 | break; | ||
286 | |||
287 | if (idx < cb->args[0]) | ||
288 | continue; | ||
289 | |||
290 | ret = dsa_slave_fill_info(dev, skb, addr, 0, | ||
291 | is_static, | ||
292 | NETLINK_CB(cb->skb).portid, | ||
293 | cb->nlh->nlmsg_seq, | ||
294 | RTM_NEWNEIGH, NLM_F_MULTI); | ||
295 | if (ret < 0) | ||
296 | break; | ||
297 | } | ||
298 | |||
299 | return idx; | ||
300 | } | ||
301 | |||
204 | static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 302 | static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
205 | { | 303 | { |
206 | struct dsa_slave_priv *p = netdev_priv(dev); | 304 | struct dsa_slave_priv *p = netdev_priv(dev); |
@@ -266,115 +364,6 @@ static int dsa_slave_port_attr_set(struct net_device *dev, | |||
266 | return ret; | 364 | return ret; |
267 | } | 365 | } |
268 | 366 | ||
269 | static int dsa_slave_port_fdb_add(struct net_device *dev, | ||
270 | struct switchdev_obj *obj) | ||
271 | { | ||
272 | struct switchdev_obj_fdb *fdb = &obj->u.fdb; | ||
273 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
274 | struct dsa_switch *ds = p->parent; | ||
275 | int err; | ||
276 | |||
277 | if (obj->trans == SWITCHDEV_TRANS_PREPARE) | ||
278 | err = ds->drv->port_fdb_add ? 0 : -EOPNOTSUPP; | ||
279 | else if (obj->trans == SWITCHDEV_TRANS_COMMIT) | ||
280 | err = ds->drv->port_fdb_add(ds, p->port, fdb->vid, fdb->addr); | ||
281 | else | ||
282 | err = -EOPNOTSUPP; | ||
283 | |||
284 | return err; | ||
285 | } | ||
286 | |||
287 | static int dsa_slave_port_fdb_del(struct net_device *dev, | ||
288 | struct switchdev_obj *obj) | ||
289 | { | ||
290 | struct switchdev_obj_fdb *fdb = &obj->u.fdb; | ||
291 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
292 | struct dsa_switch *ds = p->parent; | ||
293 | |||
294 | if (!ds->drv->port_fdb_del) | ||
295 | return -EOPNOTSUPP; | ||
296 | |||
297 | return ds->drv->port_fdb_del(ds, p->port, fdb->vid, fdb->addr); | ||
298 | } | ||
299 | |||
300 | static int dsa_slave_port_fdb_dump(struct net_device *dev, | ||
301 | struct switchdev_obj *obj) | ||
302 | { | ||
303 | struct switchdev_obj_fdb *fdb = &obj->u.fdb; | ||
304 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
305 | struct dsa_switch *ds = p->parent; | ||
306 | int err; | ||
307 | |||
308 | if (!ds->drv->port_fdb_getnext) | ||
309 | return -EOPNOTSUPP; | ||
310 | |||
311 | memset(fdb, 0, sizeof(*fdb)); | ||
312 | |||
313 | for (;;) { | ||
314 | err = ds->drv->port_fdb_getnext(ds, p->port, &fdb->vid, | ||
315 | fdb->addr, &fdb->is_static); | ||
316 | if (err) | ||
317 | break; | ||
318 | |||
319 | err = obj->cb(dev, obj); | ||
320 | if (err) | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | return err == -ENOENT ? 0 : err; | ||
325 | } | ||
326 | |||
327 | static int dsa_slave_port_obj_add(struct net_device *dev, | ||
328 | struct switchdev_obj *obj) | ||
329 | { | ||
330 | int err; | ||
331 | |||
332 | switch (obj->id) { | ||
333 | case SWITCHDEV_OBJ_PORT_FDB: | ||
334 | err = dsa_slave_port_fdb_add(dev, obj); | ||
335 | break; | ||
336 | default: | ||
337 | err = -EOPNOTSUPP; | ||
338 | break; | ||
339 | } | ||
340 | |||
341 | return err; | ||
342 | } | ||
343 | |||
344 | static int dsa_slave_port_obj_del(struct net_device *dev, | ||
345 | struct switchdev_obj *obj) | ||
346 | { | ||
347 | int err; | ||
348 | |||
349 | switch (obj->id) { | ||
350 | case SWITCHDEV_OBJ_PORT_FDB: | ||
351 | err = dsa_slave_port_fdb_del(dev, obj); | ||
352 | break; | ||
353 | default: | ||
354 | err = -EOPNOTSUPP; | ||
355 | break; | ||
356 | } | ||
357 | |||
358 | return err; | ||
359 | } | ||
360 | |||
361 | static int dsa_slave_port_obj_dump(struct net_device *dev, | ||
362 | struct switchdev_obj *obj) | ||
363 | { | ||
364 | int err; | ||
365 | |||
366 | switch (obj->id) { | ||
367 | case SWITCHDEV_OBJ_PORT_FDB: | ||
368 | err = dsa_slave_port_fdb_dump(dev, obj); | ||
369 | break; | ||
370 | default: | ||
371 | err = -EOPNOTSUPP; | ||
372 | break; | ||
373 | } | ||
374 | |||
375 | return err; | ||
376 | } | ||
377 | |||
378 | static int dsa_slave_bridge_port_join(struct net_device *dev, | 367 | static int dsa_slave_bridge_port_join(struct net_device *dev, |
379 | struct net_device *br) | 368 | struct net_device *br) |
380 | { | 369 | { |
@@ -776,9 +765,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = { | |||
776 | .ndo_change_rx_flags = dsa_slave_change_rx_flags, | 765 | .ndo_change_rx_flags = dsa_slave_change_rx_flags, |
777 | .ndo_set_rx_mode = dsa_slave_set_rx_mode, | 766 | .ndo_set_rx_mode = dsa_slave_set_rx_mode, |
778 | .ndo_set_mac_address = dsa_slave_set_mac_address, | 767 | .ndo_set_mac_address = dsa_slave_set_mac_address, |
779 | .ndo_fdb_add = switchdev_port_fdb_add, | 768 | .ndo_fdb_add = dsa_slave_fdb_add, |
780 | .ndo_fdb_del = switchdev_port_fdb_del, | 769 | .ndo_fdb_del = dsa_slave_fdb_del, |
781 | .ndo_fdb_dump = switchdev_port_fdb_dump, | 770 | .ndo_fdb_dump = dsa_slave_fdb_dump, |
782 | .ndo_do_ioctl = dsa_slave_ioctl, | 771 | .ndo_do_ioctl = dsa_slave_ioctl, |
783 | .ndo_get_iflink = dsa_slave_get_iflink, | 772 | .ndo_get_iflink = dsa_slave_get_iflink, |
784 | #ifdef CONFIG_NET_POLL_CONTROLLER | 773 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -791,9 +780,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = { | |||
791 | static const struct switchdev_ops dsa_slave_switchdev_ops = { | 780 | static const struct switchdev_ops dsa_slave_switchdev_ops = { |
792 | .switchdev_port_attr_get = dsa_slave_port_attr_get, | 781 | .switchdev_port_attr_get = dsa_slave_port_attr_get, |
793 | .switchdev_port_attr_set = dsa_slave_port_attr_set, | 782 | .switchdev_port_attr_set = dsa_slave_port_attr_set, |
794 | .switchdev_port_obj_add = dsa_slave_port_obj_add, | ||
795 | .switchdev_port_obj_del = dsa_slave_port_obj_del, | ||
796 | .switchdev_port_obj_dump = dsa_slave_port_obj_dump, | ||
797 | }; | 783 | }; |
798 | 784 | ||
799 | static void dsa_slave_adjust_link(struct net_device *dev) | 785 | static void dsa_slave_adjust_link(struct net_device *dev) |
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index e9d1cacc4060..33bafa2e703e 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
16 | #include <linux/notifier.h> | 16 | #include <linux/notifier.h> |
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/etherdevice.h> | ||
19 | #include <linux/if_bridge.h> | 18 | #include <linux/if_bridge.h> |
20 | #include <net/ip_fib.h> | 19 | #include <net/ip_fib.h> |
21 | #include <net/switchdev.h> | 20 | #include <net/switchdev.h> |
@@ -743,11 +742,11 @@ int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | |||
743 | struct switchdev_obj obj = { | 742 | struct switchdev_obj obj = { |
744 | .id = SWITCHDEV_OBJ_PORT_FDB, | 743 | .id = SWITCHDEV_OBJ_PORT_FDB, |
745 | .u.fdb = { | 744 | .u.fdb = { |
745 | .addr = addr, | ||
746 | .vid = vid, | 746 | .vid = vid, |
747 | }, | 747 | }, |
748 | }; | 748 | }; |
749 | 749 | ||
750 | ether_addr_copy(obj.u.fdb.addr, addr); | ||
751 | return switchdev_port_obj_add(dev, &obj); | 750 | return switchdev_port_obj_add(dev, &obj); |
752 | } | 751 | } |
753 | EXPORT_SYMBOL_GPL(switchdev_port_fdb_add); | 752 | EXPORT_SYMBOL_GPL(switchdev_port_fdb_add); |
@@ -770,11 +769,11 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], | |||
770 | struct switchdev_obj obj = { | 769 | struct switchdev_obj obj = { |
771 | .id = SWITCHDEV_OBJ_PORT_FDB, | 770 | .id = SWITCHDEV_OBJ_PORT_FDB, |
772 | .u.fdb = { | 771 | .u.fdb = { |
772 | .addr = addr, | ||
773 | .vid = vid, | 773 | .vid = vid, |
774 | }, | 774 | }, |
775 | }; | 775 | }; |
776 | 776 | ||
777 | ether_addr_copy(obj.u.fdb.addr, addr); | ||
778 | return switchdev_port_obj_del(dev, &obj); | 777 | return switchdev_port_obj_del(dev, &obj); |
779 | } | 778 | } |
780 | EXPORT_SYMBOL_GPL(switchdev_port_fdb_del); | 779 | EXPORT_SYMBOL_GPL(switchdev_port_fdb_del); |
@@ -811,7 +810,7 @@ static int switchdev_port_fdb_dump_cb(struct net_device *dev, | |||
811 | ndm->ndm_flags = NTF_SELF; | 810 | ndm->ndm_flags = NTF_SELF; |
812 | ndm->ndm_type = 0; | 811 | ndm->ndm_type = 0; |
813 | ndm->ndm_ifindex = dev->ifindex; | 812 | ndm->ndm_ifindex = dev->ifindex; |
814 | ndm->ndm_state = obj->u.fdb.is_static ? NUD_NOARP : NUD_REACHABLE; | 813 | ndm->ndm_state = NUD_REACHABLE; |
815 | 814 | ||
816 | if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, obj->u.fdb.addr)) | 815 | if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, obj->u.fdb.addr)) |
817 | goto nla_put_failure; | 816 | goto nla_put_failure; |