aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-08-11 15:00:37 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-11 15:00:37 -0400
commitcdf0969763e020923abe28fddc605add572febc2 (patch)
treebc568521de044fb42db344a3c5d2625f0029ac0f
parent2c9c3bbbbfe9f7f700c30d9ac40c1abca59d39ee (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.c6
-rw-r--r--drivers/net/dsa/mv88e6352.c6
-rw-r--r--drivers/net/dsa/mv88e6xxx.c223
-rw-r--r--drivers/net/dsa/mv88e6xxx.h31
-rw-r--r--drivers/net/ethernet/rocker/rocker.c2
-rw-r--r--include/net/dsa.h16
-rw-r--r--include/net/switchdev.h3
-rw-r--r--net/bridge/br_fdb.c2
-rw-r--r--net/dsa/slave.c218
-rw-r--r--net/switchdev/switchdev.c7
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
124MODULE_ALIAS("platform:mv88e6171"); 124MODULE_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
351MODULE_ALIAS("platform:mv88e6172"); 351MODULE_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
1145unlock:
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
1185static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, 1177static 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
1201static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, u8 addr[ETH_ALEN]) 1193static 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
1217static int _mv88e6xxx_atu_load(struct dsa_switch *ds, 1209static 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
1255static 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
1305static 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
1315static 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
1336int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, u16 vid, 1234int 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
1352int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, u16 vid, 1250int 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
1366int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, u16 *vid, 1264static 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 */
1304int 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);
1400unlock:
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
321struct mv88e6xxx_atu_entry {
322 u16 fid;
323 u8 state;
324 bool trunk;
325 u16 portv_trunkid;
326 u8 mac[ETH_ALEN];
327};
328
329struct mv88e6xxx_priv_state { 316struct 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,
426int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); 413int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
427int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); 414int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
428int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); 415int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
416int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
417 const unsigned char *addr, u16 vid);
418int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
419 const unsigned char *addr, u16 vid);
420int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
421 unsigned char *addr, bool *is_static);
429int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg); 422int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg);
430int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, 423int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
431 int reg, int val); 424 int reg, int val);
432int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, u16 vid,
433 const u8 addr[ETH_ALEN]);
434int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, u16 vid,
435 const u8 addr[ETH_ALEN]);
436int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, u16 *vid,
437 u8 addr[ETH_ALEN], bool *is_static);
438 425
439extern struct dsa_switch_driver mv88e6131_switch_driver; 426extern struct dsa_switch_driver mv88e6131_switch_driver;
440extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; 427extern 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
311void register_switch_driver(struct dsa_switch_driver *type); 307void 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
203static 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
217static 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
231static 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
262nla_put_failure:
263 nlmsg_cancel(skb, nlh);
264 return -EMSGSIZE;
265}
266
267/* Dump information about entries, in response to GETNEIGH */
268static 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
204static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 302static 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
269static 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
287static 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
300static 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
327static 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
344static 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
361static 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
378static int dsa_slave_bridge_port_join(struct net_device *dev, 367static 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 = {
791static const struct switchdev_ops dsa_slave_switchdev_ops = { 780static 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
799static void dsa_slave_adjust_link(struct net_device *dev) 785static 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}
753EXPORT_SYMBOL_GPL(switchdev_port_fdb_add); 752EXPORT_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}
780EXPORT_SYMBOL_GPL(switchdev_port_fdb_del); 779EXPORT_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;