diff options
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r-- | drivers/net/dsa/Kconfig | 6 | ||||
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 18 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6171.c | 6 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6352.c | 109 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.c | 408 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.h | 42 |
6 files changed, 372 insertions, 217 deletions
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig index 7ad0a4d8e475..4c483d937481 100644 --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig | |||
@@ -46,13 +46,13 @@ config NET_DSA_MV88E6171 | |||
46 | ethernet switches chips. | 46 | ethernet switches chips. |
47 | 47 | ||
48 | config NET_DSA_MV88E6352 | 48 | config NET_DSA_MV88E6352 |
49 | tristate "Marvell 88E6172/88E6176/88E6352 ethernet switch chip support" | 49 | tristate "Marvell 88E6172/6176/6320/6321/6352 ethernet switch chip support" |
50 | depends on NET_DSA | 50 | depends on NET_DSA |
51 | select NET_DSA_MV88E6XXX | 51 | select NET_DSA_MV88E6XXX |
52 | select NET_DSA_TAG_EDSA | 52 | select NET_DSA_TAG_EDSA |
53 | ---help--- | 53 | ---help--- |
54 | This enables support for the Marvell 88E6172, 88E6176 and 88E6352 | 54 | This enables support for the Marvell 88E6172, 88E6176, 88E6320, |
55 | ethernet switch chips. | 55 | 88E6321 and 88E6352 ethernet switch chips. |
56 | 56 | ||
57 | config NET_DSA_BCM_SF2 | 57 | config NET_DSA_BCM_SF2 |
58 | tristate "Broadcom Starfighter 2 Ethernet switch support" | 58 | tristate "Broadcom Starfighter 2 Ethernet switch support" |
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 079897b3a955..289e20443d83 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c | |||
@@ -901,15 +901,11 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, | |||
901 | struct fixed_phy_status *status) | 901 | struct fixed_phy_status *status) |
902 | { | 902 | { |
903 | struct bcm_sf2_priv *priv = ds_to_priv(ds); | 903 | struct bcm_sf2_priv *priv = ds_to_priv(ds); |
904 | u32 duplex, pause, speed; | 904 | u32 duplex, pause; |
905 | u32 reg; | 905 | u32 reg; |
906 | 906 | ||
907 | duplex = core_readl(priv, CORE_DUPSTS); | 907 | duplex = core_readl(priv, CORE_DUPSTS); |
908 | pause = core_readl(priv, CORE_PAUSESTS); | 908 | pause = core_readl(priv, CORE_PAUSESTS); |
909 | speed = core_readl(priv, CORE_SPDSTS); | ||
910 | |||
911 | speed >>= (port * SPDSTS_SHIFT); | ||
912 | speed &= SPDSTS_MASK; | ||
913 | 909 | ||
914 | status->link = 0; | 910 | status->link = 0; |
915 | 911 | ||
@@ -944,18 +940,6 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, | |||
944 | reg &= ~LINK_STS; | 940 | reg &= ~LINK_STS; |
945 | core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port)); | 941 | core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port)); |
946 | 942 | ||
947 | switch (speed) { | ||
948 | case SPDSTS_10: | ||
949 | status->speed = SPEED_10; | ||
950 | break; | ||
951 | case SPDSTS_100: | ||
952 | status->speed = SPEED_100; | ||
953 | break; | ||
954 | case SPDSTS_1000: | ||
955 | status->speed = SPEED_1000; | ||
956 | break; | ||
957 | } | ||
958 | |||
959 | if ((pause & (1 << port)) && | 943 | if ((pause & (1 << port)) && |
960 | (pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT)))) { | 944 | (pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT)))) { |
961 | status->asym_pause = 1; | 945 | status->asym_pause = 1; |
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 1c7808495a9d..735f04cd83ee 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 | .fdb_add = mv88e6xxx_port_fdb_add, | 119 | .port_fdb_add = mv88e6xxx_port_fdb_add, |
120 | .fdb_del = mv88e6xxx_port_fdb_del, | 120 | .port_fdb_del = mv88e6xxx_port_fdb_del, |
121 | .fdb_getnext = mv88e6xxx_port_fdb_getnext, | 121 | .port_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 632815c10a40..a18f7c83d4cb 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c | |||
@@ -36,6 +36,18 @@ static char *mv88e6352_probe(struct device *host_dev, int sw_addr) | |||
36 | return "Marvell 88E6172"; | 36 | return "Marvell 88E6172"; |
37 | if ((ret & 0xfff0) == PORT_SWITCH_ID_6176) | 37 | if ((ret & 0xfff0) == PORT_SWITCH_ID_6176) |
38 | return "Marvell 88E6176"; | 38 | return "Marvell 88E6176"; |
39 | if (ret == PORT_SWITCH_ID_6320_A1) | ||
40 | return "Marvell 88E6320 (A1)"; | ||
41 | if (ret == PORT_SWITCH_ID_6320_A2) | ||
42 | return "Marvell 88e6320 (A2)"; | ||
43 | if ((ret & 0xfff0) == PORT_SWITCH_ID_6320) | ||
44 | return "Marvell 88E6320"; | ||
45 | if (ret == PORT_SWITCH_ID_6321_A1) | ||
46 | return "Marvell 88E6321 (A1)"; | ||
47 | if (ret == PORT_SWITCH_ID_6321_A2) | ||
48 | return "Marvell 88e6321 (A2)"; | ||
49 | if ((ret & 0xfff0) == PORT_SWITCH_ID_6321) | ||
50 | return "Marvell 88E6321"; | ||
39 | if (ret == PORT_SWITCH_ID_6352_A0) | 51 | if (ret == PORT_SWITCH_ID_6352_A0) |
40 | return "Marvell 88E6352 (A0)"; | 52 | return "Marvell 88E6352 (A0)"; |
41 | if (ret == PORT_SWITCH_ID_6352_A1) | 53 | if (ret == PORT_SWITCH_ID_6352_A1) |
@@ -80,66 +92,6 @@ static int mv88e6352_setup_global(struct dsa_switch *ds) | |||
80 | return 0; | 92 | return 0; |
81 | } | 93 | } |
82 | 94 | ||
83 | #ifdef CONFIG_NET_DSA_HWMON | ||
84 | |||
85 | static int mv88e6352_get_temp(struct dsa_switch *ds, int *temp) | ||
86 | { | ||
87 | int ret; | ||
88 | |||
89 | *temp = 0; | ||
90 | |||
91 | ret = mv88e6xxx_phy_page_read(ds, 0, 6, 27); | ||
92 | if (ret < 0) | ||
93 | return ret; | ||
94 | |||
95 | *temp = (ret & 0xff) - 25; | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int mv88e6352_get_temp_limit(struct dsa_switch *ds, int *temp) | ||
101 | { | ||
102 | int ret; | ||
103 | |||
104 | *temp = 0; | ||
105 | |||
106 | ret = mv88e6xxx_phy_page_read(ds, 0, 6, 26); | ||
107 | if (ret < 0) | ||
108 | return ret; | ||
109 | |||
110 | *temp = (((ret >> 8) & 0x1f) * 5) - 25; | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int mv88e6352_set_temp_limit(struct dsa_switch *ds, int temp) | ||
116 | { | ||
117 | int ret; | ||
118 | |||
119 | ret = mv88e6xxx_phy_page_read(ds, 0, 6, 26); | ||
120 | if (ret < 0) | ||
121 | return ret; | ||
122 | temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f); | ||
123 | return mv88e6xxx_phy_page_write(ds, 0, 6, 26, | ||
124 | (ret & 0xe0ff) | (temp << 8)); | ||
125 | } | ||
126 | |||
127 | static int mv88e6352_get_temp_alarm(struct dsa_switch *ds, bool *alarm) | ||
128 | { | ||
129 | int ret; | ||
130 | |||
131 | *alarm = false; | ||
132 | |||
133 | ret = mv88e6xxx_phy_page_read(ds, 0, 6, 26); | ||
134 | if (ret < 0) | ||
135 | return ret; | ||
136 | |||
137 | *alarm = !!(ret & 0x40); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | #endif /* CONFIG_NET_DSA_HWMON */ | ||
142 | |||
143 | static int mv88e6352_setup(struct dsa_switch *ds) | 95 | static int mv88e6352_setup(struct dsa_switch *ds) |
144 | { | 96 | { |
145 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | 97 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
@@ -171,8 +123,9 @@ static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr) | |||
171 | 123 | ||
172 | mutex_lock(&ps->eeprom_mutex); | 124 | mutex_lock(&ps->eeprom_mutex); |
173 | 125 | ||
174 | ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x14, | 126 | ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP, |
175 | 0xc000 | (addr & 0xff)); | 127 | GLOBAL2_EEPROM_OP_READ | |
128 | (addr & GLOBAL2_EEPROM_OP_ADDR_MASK)); | ||
176 | if (ret < 0) | 129 | if (ret < 0) |
177 | goto error; | 130 | goto error; |
178 | 131 | ||
@@ -180,7 +133,7 @@ static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr) | |||
180 | if (ret < 0) | 133 | if (ret < 0) |
181 | goto error; | 134 | goto error; |
182 | 135 | ||
183 | ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, 0x15); | 136 | ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_EEPROM_DATA); |
184 | error: | 137 | error: |
185 | mutex_unlock(&ps->eeprom_mutex); | 138 | mutex_unlock(&ps->eeprom_mutex); |
186 | return ret; | 139 | return ret; |
@@ -253,11 +206,11 @@ static int mv88e6352_eeprom_is_readonly(struct dsa_switch *ds) | |||
253 | { | 206 | { |
254 | int ret; | 207 | int ret; |
255 | 208 | ||
256 | ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, 0x14); | 209 | ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP); |
257 | if (ret < 0) | 210 | if (ret < 0) |
258 | return ret; | 211 | return ret; |
259 | 212 | ||
260 | if (!(ret & 0x0400)) | 213 | if (!(ret & GLOBAL2_EEPROM_OP_WRITE_EN)) |
261 | return -EROFS; | 214 | return -EROFS; |
262 | 215 | ||
263 | return 0; | 216 | return 0; |
@@ -271,12 +224,13 @@ static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr, | |||
271 | 224 | ||
272 | mutex_lock(&ps->eeprom_mutex); | 225 | mutex_lock(&ps->eeprom_mutex); |
273 | 226 | ||
274 | ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x15, data); | 227 | ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data); |
275 | if (ret < 0) | 228 | if (ret < 0) |
276 | goto error; | 229 | goto error; |
277 | 230 | ||
278 | ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x14, | 231 | ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP, |
279 | 0xb000 | (addr & 0xff)); | 232 | GLOBAL2_EEPROM_OP_WRITE | |
233 | (addr & GLOBAL2_EEPROM_OP_ADDR_MASK)); | ||
280 | if (ret < 0) | 234 | if (ret < 0) |
281 | goto error; | 235 | goto error; |
282 | 236 | ||
@@ -377,10 +331,10 @@ struct dsa_switch_driver mv88e6352_switch_driver = { | |||
377 | .set_eee = mv88e6xxx_set_eee, | 331 | .set_eee = mv88e6xxx_set_eee, |
378 | .get_eee = mv88e6xxx_get_eee, | 332 | .get_eee = mv88e6xxx_get_eee, |
379 | #ifdef CONFIG_NET_DSA_HWMON | 333 | #ifdef CONFIG_NET_DSA_HWMON |
380 | .get_temp = mv88e6352_get_temp, | 334 | .get_temp = mv88e6xxx_get_temp, |
381 | .get_temp_limit = mv88e6352_get_temp_limit, | 335 | .get_temp_limit = mv88e6xxx_get_temp_limit, |
382 | .set_temp_limit = mv88e6352_set_temp_limit, | 336 | .set_temp_limit = mv88e6xxx_set_temp_limit, |
383 | .get_temp_alarm = mv88e6352_get_temp_alarm, | 337 | .get_temp_alarm = mv88e6xxx_get_temp_alarm, |
384 | #endif | 338 | #endif |
385 | .get_eeprom = mv88e6352_get_eeprom, | 339 | .get_eeprom = mv88e6352_get_eeprom, |
386 | .set_eeprom = mv88e6352_set_eeprom, | 340 | .set_eeprom = mv88e6352_set_eeprom, |
@@ -389,10 +343,13 @@ struct dsa_switch_driver mv88e6352_switch_driver = { | |||
389 | .port_join_bridge = mv88e6xxx_join_bridge, | 343 | .port_join_bridge = mv88e6xxx_join_bridge, |
390 | .port_leave_bridge = mv88e6xxx_leave_bridge, | 344 | .port_leave_bridge = mv88e6xxx_leave_bridge, |
391 | .port_stp_update = mv88e6xxx_port_stp_update, | 345 | .port_stp_update = mv88e6xxx_port_stp_update, |
392 | .fdb_add = mv88e6xxx_port_fdb_add, | 346 | .port_fdb_add = mv88e6xxx_port_fdb_add, |
393 | .fdb_del = mv88e6xxx_port_fdb_del, | 347 | .port_fdb_del = mv88e6xxx_port_fdb_del, |
394 | .fdb_getnext = mv88e6xxx_port_fdb_getnext, | 348 | .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, |
395 | }; | 349 | }; |
396 | 350 | ||
397 | MODULE_ALIAS("platform:mv88e6352"); | ||
398 | MODULE_ALIAS("platform:mv88e6172"); | 351 | MODULE_ALIAS("platform:mv88e6172"); |
352 | MODULE_ALIAS("platform:mv88e6176"); | ||
353 | MODULE_ALIAS("platform:mv88e6320"); | ||
354 | MODULE_ALIAS("platform:mv88e6321"); | ||
355 | MODULE_ALIAS("platform:mv88e6352"); | ||
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 561342466076..9978245474a7 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c | |||
@@ -517,6 +517,18 @@ static bool mv88e6xxx_6185_family(struct dsa_switch *ds) | |||
517 | return false; | 517 | return false; |
518 | } | 518 | } |
519 | 519 | ||
520 | static bool mv88e6xxx_6320_family(struct dsa_switch *ds) | ||
521 | { | ||
522 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | ||
523 | |||
524 | switch (ps->id) { | ||
525 | case PORT_SWITCH_ID_6320: | ||
526 | case PORT_SWITCH_ID_6321: | ||
527 | return true; | ||
528 | } | ||
529 | return false; | ||
530 | } | ||
531 | |||
520 | static bool mv88e6xxx_6351_family(struct dsa_switch *ds) | 532 | static bool mv88e6xxx_6351_family(struct dsa_switch *ds) |
521 | { | 533 | { |
522 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | 534 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
@@ -565,7 +577,7 @@ static int _mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port) | |||
565 | { | 577 | { |
566 | int ret; | 578 | int ret; |
567 | 579 | ||
568 | if (mv88e6xxx_6352_family(ds)) | 580 | if (mv88e6xxx_6320_family(ds) || mv88e6xxx_6352_family(ds)) |
569 | port = (port + 1) << 5; | 581 | port = (port + 1) << 5; |
570 | 582 | ||
571 | /* Snapshot the hardware statistics counters for this port. */ | 583 | /* Snapshot the hardware statistics counters for this port. */ |
@@ -796,54 +808,6 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, | |||
796 | } | 808 | } |
797 | } | 809 | } |
798 | 810 | ||
799 | #ifdef CONFIG_NET_DSA_HWMON | ||
800 | |||
801 | int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp) | ||
802 | { | ||
803 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | ||
804 | int ret; | ||
805 | int val; | ||
806 | |||
807 | *temp = 0; | ||
808 | |||
809 | mutex_lock(&ps->smi_mutex); | ||
810 | |||
811 | ret = _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6); | ||
812 | if (ret < 0) | ||
813 | goto error; | ||
814 | |||
815 | /* Enable temperature sensor */ | ||
816 | ret = _mv88e6xxx_phy_read(ds, 0x0, 0x1a); | ||
817 | if (ret < 0) | ||
818 | goto error; | ||
819 | |||
820 | ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret | (1 << 5)); | ||
821 | if (ret < 0) | ||
822 | goto error; | ||
823 | |||
824 | /* Wait for temperature to stabilize */ | ||
825 | usleep_range(10000, 12000); | ||
826 | |||
827 | val = _mv88e6xxx_phy_read(ds, 0x0, 0x1a); | ||
828 | if (val < 0) { | ||
829 | ret = val; | ||
830 | goto error; | ||
831 | } | ||
832 | |||
833 | /* Disable temperature sensor */ | ||
834 | ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret & ~(1 << 5)); | ||
835 | if (ret < 0) | ||
836 | goto error; | ||
837 | |||
838 | *temp = ((val & 0x1f) - 5) * 5; | ||
839 | |||
840 | error: | ||
841 | _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0); | ||
842 | mutex_unlock(&ps->smi_mutex); | ||
843 | return ret; | ||
844 | } | ||
845 | #endif /* CONFIG_NET_DSA_HWMON */ | ||
846 | |||
847 | /* Must be called with SMI lock held */ | 811 | /* Must be called with SMI lock held */ |
848 | static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, | 812 | static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, |
849 | u16 mask) | 813 | u16 mask) |
@@ -1000,7 +964,7 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd) | |||
1000 | { | 964 | { |
1001 | int ret; | 965 | int ret; |
1002 | 966 | ||
1003 | ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x01, fid); | 967 | ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); |
1004 | if (ret < 0) | 968 | if (ret < 0) |
1005 | return ret; | 969 | return ret; |
1006 | 970 | ||
@@ -1127,7 +1091,7 @@ int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) | |||
1127 | ps->bridge_mask[fid] = br_port_mask; | 1091 | ps->bridge_mask[fid] = br_port_mask; |
1128 | 1092 | ||
1129 | if (fid != ps->fid[port]) { | 1093 | if (fid != ps->fid[port]) { |
1130 | ps->fid_mask |= 1 << ps->fid[port]; | 1094 | clear_bit(ps->fid[port], ps->fid_bitmap); |
1131 | ps->fid[port] = fid; | 1095 | ps->fid[port] = fid; |
1132 | ret = _mv88e6xxx_update_bridge_config(ds, fid); | 1096 | ret = _mv88e6xxx_update_bridge_config(ds, fid); |
1133 | } | 1097 | } |
@@ -1161,9 +1125,16 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) | |||
1161 | 1125 | ||
1162 | mutex_lock(&ps->smi_mutex); | 1126 | mutex_lock(&ps->smi_mutex); |
1163 | 1127 | ||
1164 | newfid = __ffs(ps->fid_mask); | 1128 | newfid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID, 1); |
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 | |||
1165 | ps->fid[port] = newfid; | 1136 | ps->fid[port] = newfid; |
1166 | ps->fid_mask &= ~(1 << newfid); | 1137 | set_bit(newfid, ps->fid_bitmap); |
1167 | ps->bridge_mask[fid] &= ~(1 << port); | 1138 | ps->bridge_mask[fid] &= ~(1 << port); |
1168 | ps->bridge_mask[newfid] = 1 << port; | 1139 | ps->bridge_mask[newfid] = 1 << port; |
1169 | 1140 | ||
@@ -1171,6 +1142,7 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) | |||
1171 | if (!ret) | 1142 | if (!ret) |
1172 | ret = _mv88e6xxx_update_bridge_config(ds, newfid); | 1143 | ret = _mv88e6xxx_update_bridge_config(ds, newfid); |
1173 | 1144 | ||
1145 | unlock: | ||
1174 | mutex_unlock(&ps->smi_mutex); | 1146 | mutex_unlock(&ps->smi_mutex); |
1175 | 1147 | ||
1176 | return ret; | 1148 | return ret; |
@@ -1210,8 +1182,8 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) | |||
1210 | return 0; | 1182 | return 0; |
1211 | } | 1183 | } |
1212 | 1184 | ||
1213 | static int __mv88e6xxx_write_addr(struct dsa_switch *ds, | 1185 | static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, |
1214 | const unsigned char *addr) | 1186 | const unsigned char *addr) |
1215 | { | 1187 | { |
1216 | int i, ret; | 1188 | int i, ret; |
1217 | 1189 | ||
@@ -1226,7 +1198,7 @@ static int __mv88e6xxx_write_addr(struct dsa_switch *ds, | |||
1226 | return 0; | 1198 | return 0; |
1227 | } | 1199 | } |
1228 | 1200 | ||
1229 | static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr) | 1201 | static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, unsigned char *addr) |
1230 | { | 1202 | { |
1231 | int i, ret; | 1203 | int i, ret; |
1232 | 1204 | ||
@@ -1242,29 +1214,74 @@ static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr) | |||
1242 | return 0; | 1214 | return 0; |
1243 | } | 1215 | } |
1244 | 1216 | ||
1245 | static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port, | 1217 | static int _mv88e6xxx_atu_load(struct dsa_switch *ds, |
1246 | const unsigned char *addr, int state) | 1218 | struct mv88e6xxx_atu_entry *entry) |
1247 | { | 1219 | { |
1248 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | 1220 | u16 reg = 0; |
1249 | u8 fid = ps->fid[port]; | ||
1250 | int ret; | 1221 | int ret; |
1251 | 1222 | ||
1252 | ret = _mv88e6xxx_atu_wait(ds); | 1223 | ret = _mv88e6xxx_atu_wait(ds); |
1253 | if (ret < 0) | 1224 | if (ret < 0) |
1254 | return ret; | 1225 | return ret; |
1255 | 1226 | ||
1256 | ret = __mv88e6xxx_write_addr(ds, addr); | 1227 | ret = _mv88e6xxx_atu_mac_write(ds, entry->mac); |
1257 | if (ret < 0) | 1228 | if (ret < 0) |
1258 | return ret; | 1229 | return ret; |
1259 | 1230 | ||
1260 | ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, | 1231 | if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) { |
1261 | (0x10 << port) | state); | 1232 | unsigned int mask, shift; |
1262 | if (ret) | 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) | ||
1263 | return ret; | 1250 | return ret; |
1264 | 1251 | ||
1265 | ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_LOAD_DB); | 1252 | return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB); |
1253 | } | ||
1254 | |||
1255 | static int _mv88e6xxx_port_vid_to_fid(struct dsa_switch *ds, int port, u16 vid) | ||
1256 | { | ||
1257 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | ||
1266 | 1258 | ||
1267 | return ret; | 1259 | if (vid == 0) |
1260 | return ps->fid[port]; | ||
1261 | |||
1262 | return -ENOENT; | ||
1263 | } | ||
1264 | |||
1265 | static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, | ||
1266 | const unsigned char *addr, u16 vid, | ||
1267 | u8 state) | ||
1268 | { | ||
1269 | struct mv88e6xxx_atu_entry entry = { 0 }; | ||
1270 | int ret; | ||
1271 | |||
1272 | ret = _mv88e6xxx_port_vid_to_fid(ds, port, vid); | ||
1273 | if (ret < 0) | ||
1274 | return ret; | ||
1275 | |||
1276 | entry.fid = ret; | ||
1277 | entry.state = state; | ||
1278 | ether_addr_copy(entry.mac, addr); | ||
1279 | if (state != GLOBAL_ATU_DATA_STATE_UNUSED) { | ||
1280 | entry.trunk = false; | ||
1281 | entry.portv_trunkid = BIT(port); | ||
1282 | } | ||
1283 | |||
1284 | return _mv88e6xxx_atu_load(ds, &entry); | ||
1268 | } | 1285 | } |
1269 | 1286 | ||
1270 | int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, | 1287 | int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, |
@@ -1277,7 +1294,7 @@ int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, | |||
1277 | int ret; | 1294 | int ret; |
1278 | 1295 | ||
1279 | mutex_lock(&ps->smi_mutex); | 1296 | mutex_lock(&ps->smi_mutex); |
1280 | ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state); | 1297 | ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid, state); |
1281 | mutex_unlock(&ps->smi_mutex); | 1298 | mutex_unlock(&ps->smi_mutex); |
1282 | 1299 | ||
1283 | return ret; | 1300 | return ret; |
@@ -1290,61 +1307,99 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, | |||
1290 | int ret; | 1307 | int ret; |
1291 | 1308 | ||
1292 | mutex_lock(&ps->smi_mutex); | 1309 | mutex_lock(&ps->smi_mutex); |
1293 | ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, | 1310 | ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid, |
1294 | GLOBAL_ATU_DATA_STATE_UNUSED); | 1311 | GLOBAL_ATU_DATA_STATE_UNUSED); |
1295 | mutex_unlock(&ps->smi_mutex); | 1312 | mutex_unlock(&ps->smi_mutex); |
1296 | 1313 | ||
1297 | return ret; | 1314 | return ret; |
1298 | } | 1315 | } |
1299 | 1316 | ||
1300 | static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port, | 1317 | static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, |
1301 | unsigned char *addr, bool *is_static) | 1318 | const unsigned char *addr, |
1319 | struct mv88e6xxx_atu_entry *entry) | ||
1302 | { | 1320 | { |
1303 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | 1321 | struct mv88e6xxx_atu_entry next = { 0 }; |
1304 | u8 fid = ps->fid[port]; | 1322 | int ret; |
1305 | int ret, state; | 1323 | |
1324 | next.fid = fid; | ||
1306 | 1325 | ||
1307 | ret = _mv88e6xxx_atu_wait(ds); | 1326 | ret = _mv88e6xxx_atu_wait(ds); |
1308 | if (ret < 0) | 1327 | if (ret < 0) |
1309 | return ret; | 1328 | return ret; |
1310 | 1329 | ||
1311 | ret = __mv88e6xxx_write_addr(ds, addr); | 1330 | ret = _mv88e6xxx_atu_mac_write(ds, addr); |
1312 | if (ret < 0) | 1331 | if (ret < 0) |
1313 | return ret; | 1332 | return ret; |
1314 | 1333 | ||
1315 | do { | 1334 | ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); |
1316 | ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); | 1335 | if (ret < 0) |
1317 | if (ret < 0) | 1336 | return ret; |
1318 | return ret; | ||
1319 | 1337 | ||
1320 | ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); | 1338 | ret = _mv88e6xxx_atu_mac_read(ds, next.mac); |
1321 | if (ret < 0) | 1339 | if (ret < 0) |
1322 | return ret; | 1340 | return ret; |
1323 | state = ret & GLOBAL_ATU_DATA_STATE_MASK; | ||
1324 | if (state == GLOBAL_ATU_DATA_STATE_UNUSED) | ||
1325 | return -ENOENT; | ||
1326 | } while (!(((ret >> 4) & 0xff) & (1 << port))); | ||
1327 | 1341 | ||
1328 | ret = __mv88e6xxx_read_addr(ds, addr); | 1342 | ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); |
1329 | if (ret < 0) | 1343 | if (ret < 0) |
1330 | return ret; | 1344 | return ret; |
1331 | 1345 | ||
1332 | *is_static = state == (is_multicast_ether_addr(addr) ? | 1346 | next.state = ret & GLOBAL_ATU_DATA_STATE_MASK; |
1333 | GLOBAL_ATU_DATA_STATE_MC_STATIC : | 1347 | if (next.state != GLOBAL_ATU_DATA_STATE_UNUSED) { |
1334 | GLOBAL_ATU_DATA_STATE_UC_STATIC); | 1348 | unsigned int mask, shift; |
1349 | |||
1350 | if (ret & GLOBAL_ATU_DATA_TRUNK) { | ||
1351 | next.trunk = true; | ||
1352 | mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK; | ||
1353 | shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT; | ||
1354 | } else { | ||
1355 | next.trunk = false; | ||
1356 | mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK; | ||
1357 | shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT; | ||
1358 | } | ||
1335 | 1359 | ||
1360 | next.portv_trunkid = (ret & mask) >> shift; | ||
1361 | } | ||
1362 | |||
1363 | *entry = next; | ||
1336 | return 0; | 1364 | return 0; |
1337 | } | 1365 | } |
1338 | 1366 | ||
1339 | /* get next entry for port */ | 1367 | /* get next entry for port */ |
1340 | int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, | 1368 | int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, |
1341 | unsigned char *addr, bool *is_static) | 1369 | unsigned char *addr, u16 *vid, bool *is_static) |
1342 | { | 1370 | { |
1343 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | 1371 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
1372 | struct mv88e6xxx_atu_entry next; | ||
1373 | u16 fid; | ||
1344 | int ret; | 1374 | int ret; |
1345 | 1375 | ||
1346 | mutex_lock(&ps->smi_mutex); | 1376 | mutex_lock(&ps->smi_mutex); |
1347 | ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static); | 1377 | |
1378 | ret = _mv88e6xxx_port_vid_to_fid(ds, port, *vid); | ||
1379 | if (ret < 0) | ||
1380 | goto unlock; | ||
1381 | fid = ret; | ||
1382 | |||
1383 | do { | ||
1384 | if (is_broadcast_ether_addr(addr)) { | ||
1385 | ret = -ENOENT; | ||
1386 | goto unlock; | ||
1387 | } | ||
1388 | |||
1389 | ret = _mv88e6xxx_atu_getnext(ds, fid, addr, &next); | ||
1390 | if (ret < 0) | ||
1391 | goto unlock; | ||
1392 | |||
1393 | ether_addr_copy(addr, next.mac); | ||
1394 | |||
1395 | if (next.state == GLOBAL_ATU_DATA_STATE_UNUSED) | ||
1396 | continue; | ||
1397 | } while (next.trunk || (next.portv_trunkid & BIT(port)) == 0); | ||
1398 | |||
1399 | *is_static = next.state == (is_multicast_ether_addr(addr) ? | ||
1400 | GLOBAL_ATU_DATA_STATE_MC_STATIC : | ||
1401 | GLOBAL_ATU_DATA_STATE_UC_STATIC); | ||
1402 | unlock: | ||
1348 | mutex_unlock(&ps->smi_mutex); | 1403 | mutex_unlock(&ps->smi_mutex); |
1349 | 1404 | ||
1350 | return ret; | 1405 | return ret; |
@@ -1377,7 +1432,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) | |||
1377 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 1432 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1378 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || | 1433 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
1379 | mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds) || | 1434 | mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds) || |
1380 | mv88e6xxx_6065_family(ds)) { | 1435 | mv88e6xxx_6065_family(ds) || mv88e6xxx_6320_family(ds)) { |
1381 | /* MAC Forcing register: don't force link, speed, | 1436 | /* MAC Forcing register: don't force link, speed, |
1382 | * duplex or flow control state to any particular | 1437 | * duplex or flow control state to any particular |
1383 | * values on physical ports, but force the CPU port | 1438 | * values on physical ports, but force the CPU port |
@@ -1423,7 +1478,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) | |||
1423 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 1478 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1424 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || | 1479 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
1425 | mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) || | 1480 | mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) || |
1426 | mv88e6xxx_6185_family(ds)) | 1481 | mv88e6xxx_6185_family(ds) || mv88e6xxx_6320_family(ds)) |
1427 | reg = PORT_CONTROL_IGMP_MLD_SNOOP | | 1482 | reg = PORT_CONTROL_IGMP_MLD_SNOOP | |
1428 | PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP | | 1483 | PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP | |
1429 | PORT_CONTROL_STATE_FORWARDING; | 1484 | PORT_CONTROL_STATE_FORWARDING; |
@@ -1431,7 +1486,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) | |||
1431 | if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) | 1486 | if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) |
1432 | reg |= PORT_CONTROL_DSA_TAG; | 1487 | reg |= PORT_CONTROL_DSA_TAG; |
1433 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 1488 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1434 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds)) { | 1489 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
1490 | mv88e6xxx_6320_family(ds)) { | ||
1435 | if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA) | 1491 | if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA) |
1436 | reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA; | 1492 | reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA; |
1437 | else | 1493 | else |
@@ -1441,14 +1497,15 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) | |||
1441 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 1497 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1442 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || | 1498 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
1443 | mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) || | 1499 | mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) || |
1444 | mv88e6xxx_6185_family(ds)) { | 1500 | mv88e6xxx_6185_family(ds) || mv88e6xxx_6320_family(ds)) { |
1445 | if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA) | 1501 | if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA) |
1446 | reg |= PORT_CONTROL_EGRESS_ADD_TAG; | 1502 | reg |= PORT_CONTROL_EGRESS_ADD_TAG; |
1447 | } | 1503 | } |
1448 | } | 1504 | } |
1449 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 1505 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1450 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || | 1506 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
1451 | mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds)) { | 1507 | mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) || |
1508 | mv88e6xxx_6320_family(ds)) { | ||
1452 | if (ds->dsa_port_mask & (1 << port)) | 1509 | if (ds->dsa_port_mask & (1 << port)) |
1453 | reg |= PORT_CONTROL_FRAME_MODE_DSA; | 1510 | reg |= PORT_CONTROL_FRAME_MODE_DSA; |
1454 | if (port == dsa_upstream_port(ds)) | 1511 | if (port == dsa_upstream_port(ds)) |
@@ -1473,11 +1530,11 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) | |||
1473 | reg = 0; | 1530 | reg = 0; |
1474 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 1531 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1475 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || | 1532 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
1476 | mv88e6xxx_6095_family(ds)) | 1533 | mv88e6xxx_6095_family(ds) || mv88e6xxx_6320_family(ds)) |
1477 | reg = PORT_CONTROL_2_MAP_DA; | 1534 | reg = PORT_CONTROL_2_MAP_DA; |
1478 | 1535 | ||
1479 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 1536 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1480 | mv88e6xxx_6165_family(ds)) | 1537 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6320_family(ds)) |
1481 | reg |= PORT_CONTROL_2_JUMBO_10240; | 1538 | reg |= PORT_CONTROL_2_JUMBO_10240; |
1482 | 1539 | ||
1483 | if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) { | 1540 | if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) { |
@@ -1514,7 +1571,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) | |||
1514 | goto abort; | 1571 | goto abort; |
1515 | 1572 | ||
1516 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 1573 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1517 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds)) { | 1574 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
1575 | mv88e6xxx_6320_family(ds)) { | ||
1518 | /* Do not limit the period of time that this port can | 1576 | /* Do not limit the period of time that this port can |
1519 | * be paused for by the remote end or the period of | 1577 | * be paused for by the remote end or the period of |
1520 | * time that this port can pause the remote end. | 1578 | * time that this port can pause the remote end. |
@@ -1564,7 +1622,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) | |||
1564 | 1622 | ||
1565 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 1623 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1566 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || | 1624 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
1567 | mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds)) { | 1625 | mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds) || |
1626 | mv88e6xxx_6320_family(ds)) { | ||
1568 | /* Rate Control: disable ingress rate limiting. */ | 1627 | /* Rate Control: disable ingress rate limiting. */ |
1569 | ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), | 1628 | ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), |
1570 | PORT_RATE_CONTROL, 0x0001); | 1629 | PORT_RATE_CONTROL, 0x0001); |
@@ -1584,9 +1643,9 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) | |||
1584 | * ports, and allow each of the 'real' ports to only talk to | 1643 | * ports, and allow each of the 'real' ports to only talk to |
1585 | * the upstream port. | 1644 | * the upstream port. |
1586 | */ | 1645 | */ |
1587 | fid = __ffs(ps->fid_mask); | 1646 | fid = port + 1; |
1588 | ps->fid[port] = fid; | 1647 | ps->fid[port] = fid; |
1589 | ps->fid_mask &= ~(1 << fid); | 1648 | set_bit(fid, ps->fid_bitmap); |
1590 | 1649 | ||
1591 | if (!dsa_is_cpu_port(ds, port)) | 1650 | if (!dsa_is_cpu_port(ds, port)) |
1592 | ps->bridge_mask[fid] = 1 << port; | 1651 | ps->bridge_mask[fid] = 1 << port; |
@@ -1683,7 +1742,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, | |||
1683 | unsigned char addr[6]; | 1742 | unsigned char addr[6]; |
1684 | int ret, data, state; | 1743 | int ret, data, state; |
1685 | 1744 | ||
1686 | ret = __mv88e6xxx_write_addr(ds, bcast); | 1745 | ret = _mv88e6xxx_atu_mac_write(ds, bcast); |
1687 | if (ret < 0) | 1746 | if (ret < 0) |
1688 | return ret; | 1747 | return ret; |
1689 | 1748 | ||
@@ -1698,7 +1757,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, | |||
1698 | state = data & GLOBAL_ATU_DATA_STATE_MASK; | 1757 | state = data & GLOBAL_ATU_DATA_STATE_MASK; |
1699 | if (state == GLOBAL_ATU_DATA_STATE_UNUSED) | 1758 | if (state == GLOBAL_ATU_DATA_STATE_UNUSED) |
1700 | break; | 1759 | break; |
1701 | ret = __mv88e6xxx_read_addr(ds, addr); | 1760 | ret = _mv88e6xxx_atu_mac_read(ds, addr); |
1702 | if (ret < 0) | 1761 | if (ret < 0) |
1703 | return ret; | 1762 | return ret; |
1704 | mv88e6xxx_atu_show_entry(s, dbnum, addr, data); | 1763 | mv88e6xxx_atu_show_entry(s, dbnum, addr, data); |
@@ -1885,8 +1944,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) | |||
1885 | 1944 | ||
1886 | ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; | 1945 | ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; |
1887 | 1946 | ||
1888 | ps->fid_mask = (1 << DSA_MAX_PORTS) - 1; | ||
1889 | |||
1890 | INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); | 1947 | INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); |
1891 | 1948 | ||
1892 | name = kasprintf(GFP_KERNEL, "dsa%d", ds->index); | 1949 | name = kasprintf(GFP_KERNEL, "dsa%d", ds->index); |
@@ -1913,6 +1970,7 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) | |||
1913 | int mv88e6xxx_setup_global(struct dsa_switch *ds) | 1970 | int mv88e6xxx_setup_global(struct dsa_switch *ds) |
1914 | { | 1971 | { |
1915 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | 1972 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
1973 | int ret; | ||
1916 | int i; | 1974 | int i; |
1917 | 1975 | ||
1918 | /* Set the default address aging time to 5 minutes, and | 1976 | /* Set the default address aging time to 5 minutes, and |
@@ -1976,7 +2034,8 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) | |||
1976 | (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT)); | 2034 | (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT)); |
1977 | 2035 | ||
1978 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 2036 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1979 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds)) { | 2037 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
2038 | mv88e6xxx_6320_family(ds)) { | ||
1980 | /* Send all frames with destination addresses matching | 2039 | /* Send all frames with destination addresses matching |
1981 | * 01:80:c2:00:00:2x to the CPU port. | 2040 | * 01:80:c2:00:00:2x to the CPU port. |
1982 | */ | 2041 | */ |
@@ -1995,7 +2054,8 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) | |||
1995 | 2054 | ||
1996 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || | 2055 | if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || |
1997 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || | 2056 | mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || |
1998 | mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds)) { | 2057 | mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds) || |
2058 | mv88e6xxx_6320_family(ds)) { | ||
1999 | /* Disable ingress rate limiting by resetting all | 2059 | /* Disable ingress rate limiting by resetting all |
2000 | * ingress rate limit registers to their initial | 2060 | * ingress rate limit registers to their initial |
2001 | * state. | 2061 | * state. |
@@ -2009,9 +2069,11 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) | |||
2009 | REG_WRITE(REG_GLOBAL, GLOBAL_STATS_OP, GLOBAL_STATS_OP_FLUSH_ALL); | 2069 | REG_WRITE(REG_GLOBAL, GLOBAL_STATS_OP, GLOBAL_STATS_OP_FLUSH_ALL); |
2010 | 2070 | ||
2011 | /* Wait for the flush to complete. */ | 2071 | /* Wait for the flush to complete. */ |
2012 | _mv88e6xxx_stats_wait(ds); | 2072 | mutex_lock(&ps->smi_mutex); |
2073 | ret = _mv88e6xxx_stats_wait(ds); | ||
2074 | mutex_unlock(&ps->smi_mutex); | ||
2013 | 2075 | ||
2014 | return 0; | 2076 | return ret; |
2015 | } | 2077 | } |
2016 | 2078 | ||
2017 | int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active) | 2079 | int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active) |
@@ -2162,6 +2224,132 @@ mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum, | |||
2162 | return ret; | 2224 | return ret; |
2163 | } | 2225 | } |
2164 | 2226 | ||
2227 | #ifdef CONFIG_NET_DSA_HWMON | ||
2228 | |||
2229 | static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp) | ||
2230 | { | ||
2231 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | ||
2232 | int ret; | ||
2233 | int val; | ||
2234 | |||
2235 | *temp = 0; | ||
2236 | |||
2237 | mutex_lock(&ps->smi_mutex); | ||
2238 | |||
2239 | ret = _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6); | ||
2240 | if (ret < 0) | ||
2241 | goto error; | ||
2242 | |||
2243 | /* Enable temperature sensor */ | ||
2244 | ret = _mv88e6xxx_phy_read(ds, 0x0, 0x1a); | ||
2245 | if (ret < 0) | ||
2246 | goto error; | ||
2247 | |||
2248 | ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret | (1 << 5)); | ||
2249 | if (ret < 0) | ||
2250 | goto error; | ||
2251 | |||
2252 | /* Wait for temperature to stabilize */ | ||
2253 | usleep_range(10000, 12000); | ||
2254 | |||
2255 | val = _mv88e6xxx_phy_read(ds, 0x0, 0x1a); | ||
2256 | if (val < 0) { | ||
2257 | ret = val; | ||
2258 | goto error; | ||
2259 | } | ||
2260 | |||
2261 | /* Disable temperature sensor */ | ||
2262 | ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret & ~(1 << 5)); | ||
2263 | if (ret < 0) | ||
2264 | goto error; | ||
2265 | |||
2266 | *temp = ((val & 0x1f) - 5) * 5; | ||
2267 | |||
2268 | error: | ||
2269 | _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0); | ||
2270 | mutex_unlock(&ps->smi_mutex); | ||
2271 | return ret; | ||
2272 | } | ||
2273 | |||
2274 | static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp) | ||
2275 | { | ||
2276 | int phy = mv88e6xxx_6320_family(ds) ? 3 : 0; | ||
2277 | int ret; | ||
2278 | |||
2279 | *temp = 0; | ||
2280 | |||
2281 | ret = mv88e6xxx_phy_page_read(ds, phy, 6, 27); | ||
2282 | if (ret < 0) | ||
2283 | return ret; | ||
2284 | |||
2285 | *temp = (ret & 0xff) - 25; | ||
2286 | |||
2287 | return 0; | ||
2288 | } | ||
2289 | |||
2290 | int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp) | ||
2291 | { | ||
2292 | if (mv88e6xxx_6320_family(ds) || mv88e6xxx_6352_family(ds)) | ||
2293 | return mv88e63xx_get_temp(ds, temp); | ||
2294 | |||
2295 | return mv88e61xx_get_temp(ds, temp); | ||
2296 | } | ||
2297 | |||
2298 | int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp) | ||
2299 | { | ||
2300 | int phy = mv88e6xxx_6320_family(ds) ? 3 : 0; | ||
2301 | int ret; | ||
2302 | |||
2303 | if (!mv88e6xxx_6320_family(ds) && !mv88e6xxx_6352_family(ds)) | ||
2304 | return -EOPNOTSUPP; | ||
2305 | |||
2306 | *temp = 0; | ||
2307 | |||
2308 | ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26); | ||
2309 | if (ret < 0) | ||
2310 | return ret; | ||
2311 | |||
2312 | *temp = (((ret >> 8) & 0x1f) * 5) - 25; | ||
2313 | |||
2314 | return 0; | ||
2315 | } | ||
2316 | |||
2317 | int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp) | ||
2318 | { | ||
2319 | int phy = mv88e6xxx_6320_family(ds) ? 3 : 0; | ||
2320 | int ret; | ||
2321 | |||
2322 | if (!mv88e6xxx_6320_family(ds) && !mv88e6xxx_6352_family(ds)) | ||
2323 | return -EOPNOTSUPP; | ||
2324 | |||
2325 | ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26); | ||
2326 | if (ret < 0) | ||
2327 | return ret; | ||
2328 | temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f); | ||
2329 | return mv88e6xxx_phy_page_write(ds, phy, 6, 26, | ||
2330 | (ret & 0xe0ff) | (temp << 8)); | ||
2331 | } | ||
2332 | |||
2333 | int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) | ||
2334 | { | ||
2335 | int phy = mv88e6xxx_6320_family(ds) ? 3 : 0; | ||
2336 | int ret; | ||
2337 | |||
2338 | if (!mv88e6xxx_6320_family(ds) && !mv88e6xxx_6352_family(ds)) | ||
2339 | return -EOPNOTSUPP; | ||
2340 | |||
2341 | *alarm = false; | ||
2342 | |||
2343 | ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26); | ||
2344 | if (ret < 0) | ||
2345 | return ret; | ||
2346 | |||
2347 | *alarm = !!(ret & 0x40); | ||
2348 | |||
2349 | return 0; | ||
2350 | } | ||
2351 | #endif /* CONFIG_NET_DSA_HWMON */ | ||
2352 | |||
2165 | static int __init mv88e6xxx_init(void) | 2353 | static int __init mv88e6xxx_init(void) |
2166 | { | 2354 | { |
2167 | #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) | 2355 | #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) |
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index a650b2656de9..10fae325671e 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h | |||
@@ -11,6 +11,8 @@ | |||
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 | |||
14 | #ifndef UINT64_MAX | 16 | #ifndef UINT64_MAX |
15 | #define UINT64_MAX (u64)(~((u64)0)) | 17 | #define UINT64_MAX (u64)(~((u64)0)) |
16 | #endif | 18 | #endif |
@@ -89,7 +91,12 @@ | |||
89 | #define PORT_SWITCH_ID_6182 0x1a60 | 91 | #define PORT_SWITCH_ID_6182 0x1a60 |
90 | #define PORT_SWITCH_ID_6185 0x1a70 | 92 | #define PORT_SWITCH_ID_6185 0x1a70 |
91 | #define PORT_SWITCH_ID_6240 0x2400 | 93 | #define PORT_SWITCH_ID_6240 0x2400 |
92 | #define PORT_SWITCH_ID_6320 0x1250 | 94 | #define PORT_SWITCH_ID_6320 0x1150 |
95 | #define PORT_SWITCH_ID_6320_A1 0x1151 | ||
96 | #define PORT_SWITCH_ID_6320_A2 0x1152 | ||
97 | #define PORT_SWITCH_ID_6321 0x3100 | ||
98 | #define PORT_SWITCH_ID_6321_A1 0x3101 | ||
99 | #define PORT_SWITCH_ID_6321_A2 0x3102 | ||
93 | #define PORT_SWITCH_ID_6350 0x3710 | 100 | #define PORT_SWITCH_ID_6350 0x3710 |
94 | #define PORT_SWITCH_ID_6351 0x3750 | 101 | #define PORT_SWITCH_ID_6351 0x3750 |
95 | #define PORT_SWITCH_ID_6352 0x3520 | 102 | #define PORT_SWITCH_ID_6352 0x3520 |
@@ -164,6 +171,7 @@ | |||
164 | #define GLOBAL_MAC_01 0x01 | 171 | #define GLOBAL_MAC_01 0x01 |
165 | #define GLOBAL_MAC_23 0x02 | 172 | #define GLOBAL_MAC_23 0x02 |
166 | #define GLOBAL_MAC_45 0x03 | 173 | #define GLOBAL_MAC_45 0x03 |
174 | #define GLOBAL_ATU_FID 0x01 /* 6097 6165 6351 6352 */ | ||
167 | #define GLOBAL_CONTROL 0x04 | 175 | #define GLOBAL_CONTROL 0x04 |
168 | #define GLOBAL_CONTROL_SW_RESET BIT(15) | 176 | #define GLOBAL_CONTROL_SW_RESET BIT(15) |
169 | #define GLOBAL_CONTROL_PPU_ENABLE BIT(14) | 177 | #define GLOBAL_CONTROL_PPU_ENABLE BIT(14) |
@@ -198,6 +206,8 @@ | |||
198 | #define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY) | 206 | #define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY) |
199 | #define GLOBAL_ATU_DATA 0x0c | 207 | #define GLOBAL_ATU_DATA 0x0c |
200 | #define GLOBAL_ATU_DATA_TRUNK BIT(15) | 208 | #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 | ||
201 | #define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0 | 211 | #define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0 |
202 | #define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4 | 212 | #define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4 |
203 | #define GLOBAL_ATU_DATA_STATE_MASK 0x0f | 213 | #define GLOBAL_ATU_DATA_STATE_MASK 0x0f |
@@ -280,8 +290,12 @@ | |||
280 | #define GLOBAL2_PRIO_OVERRIDE_FORCE_ARP BIT(3) | 290 | #define GLOBAL2_PRIO_OVERRIDE_FORCE_ARP BIT(3) |
281 | #define GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT 0 | 291 | #define GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT 0 |
282 | #define GLOBAL2_EEPROM_OP 0x14 | 292 | #define GLOBAL2_EEPROM_OP 0x14 |
283 | #define GLOBAL2_EEPROM_OP_BUSY BIT(15) | 293 | #define GLOBAL2_EEPROM_OP_BUSY BIT(15) |
284 | #define GLOBAL2_EEPROM_OP_LOAD BIT(11) | 294 | #define GLOBAL2_EEPROM_OP_WRITE ((3 << 12) | GLOBAL2_EEPROM_OP_BUSY) |
295 | #define GLOBAL2_EEPROM_OP_READ ((4 << 12) | GLOBAL2_EEPROM_OP_BUSY) | ||
296 | #define GLOBAL2_EEPROM_OP_LOAD BIT(11) | ||
297 | #define GLOBAL2_EEPROM_OP_WRITE_EN BIT(10) | ||
298 | #define GLOBAL2_EEPROM_OP_ADDR_MASK 0xff | ||
285 | #define GLOBAL2_EEPROM_DATA 0x15 | 299 | #define GLOBAL2_EEPROM_DATA 0x15 |
286 | #define GLOBAL2_PTP_AVB_OP 0x16 | 300 | #define GLOBAL2_PTP_AVB_OP 0x16 |
287 | #define GLOBAL2_PTP_AVB_DATA 0x17 | 301 | #define GLOBAL2_PTP_AVB_DATA 0x17 |
@@ -304,6 +318,14 @@ | |||
304 | #define GLOBAL2_QOS_WEIGHT 0x1c | 318 | #define GLOBAL2_QOS_WEIGHT 0x1c |
305 | #define GLOBAL2_MISC 0x1d | 319 | #define GLOBAL2_MISC 0x1d |
306 | 320 | ||
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 | |||
307 | struct mv88e6xxx_priv_state { | 329 | struct mv88e6xxx_priv_state { |
308 | /* When using multi-chip addressing, this mutex protects | 330 | /* When using multi-chip addressing, this mutex protects |
309 | * access to the indirect access registers. (In single-chip | 331 | * access to the indirect access registers. (In single-chip |
@@ -342,9 +364,9 @@ struct mv88e6xxx_priv_state { | |||
342 | 364 | ||
343 | /* hw bridging */ | 365 | /* hw bridging */ |
344 | 366 | ||
345 | u32 fid_mask; | 367 | DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */ |
346 | u8 fid[DSA_MAX_PORTS]; | 368 | u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */ |
347 | u16 bridge_mask[DSA_MAX_PORTS]; | 369 | u16 bridge_mask[DSA_MAX_PORTS]; /* br groups (indexed by FID) */ |
348 | 370 | ||
349 | unsigned long port_state_update_mask; | 371 | unsigned long port_state_update_mask; |
350 | u8 port_state[DSA_MAX_PORTS]; | 372 | u8 port_state[DSA_MAX_PORTS]; |
@@ -389,7 +411,10 @@ int mv88e6xxx_get_sset_count_basic(struct dsa_switch *ds); | |||
389 | int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port); | 411 | int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port); |
390 | void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, | 412 | void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, |
391 | struct ethtool_regs *regs, void *_p); | 413 | struct ethtool_regs *regs, void *_p); |
392 | int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp); | 414 | int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp); |
415 | int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp); | ||
416 | int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp); | ||
417 | int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm); | ||
393 | int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds); | 418 | int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds); |
394 | int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds); | 419 | int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds); |
395 | int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum); | 420 | int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum); |
@@ -406,10 +431,11 @@ int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, | |||
406 | int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, | 431 | int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, |
407 | const unsigned char *addr, u16 vid); | 432 | const unsigned char *addr, u16 vid); |
408 | int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, | 433 | int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, |
409 | unsigned char *addr, bool *is_static); | 434 | unsigned char *addr, u16 *vid, bool *is_static); |
410 | int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg); | 435 | int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg); |
411 | int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, | 436 | int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, |
412 | int reg, int val); | 437 | int reg, int val); |
438 | |||
413 | extern struct dsa_switch_driver mv88e6131_switch_driver; | 439 | extern struct dsa_switch_driver mv88e6131_switch_driver; |
414 | extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; | 440 | extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; |
415 | extern struct dsa_switch_driver mv88e6352_switch_driver; | 441 | extern struct dsa_switch_driver mv88e6352_switch_driver; |