aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dsa/mv88e6123_61_65.c31
-rw-r--r--drivers/net/dsa/mv88e6171.c70
-rw-r--r--drivers/net/dsa/mv88e6352.c39
-rw-r--r--drivers/net/dsa/mv88e6xxx.c479
-rw-r--r--drivers/net/dsa/mv88e6xxx.h46
-rw-r--r--include/net/dsa.h6
-rw-r--r--net/dsa/slave.c102
7 files changed, 679 insertions, 94 deletions
diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
index e9c736e1cef3..2d7e1ffe9fdc 100644
--- a/drivers/net/dsa/mv88e6123_61_65.c
+++ b/drivers/net/dsa/mv88e6123_61_65.c
@@ -222,28 +222,6 @@ static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p)
222 val |= 0x000c; 222 val |= 0x000c;
223 REG_WRITE(addr, 0x04, val); 223 REG_WRITE(addr, 0x04, val);
224 224
225 /* Port Control 1: disable trunking. Also, if this is the
226 * CPU port, enable learn messages to be sent to this port.
227 */
228 REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
229
230 /* Port based VLAN map: give each port its own address
231 * database, allow the CPU port to talk to each of the 'real'
232 * ports, and allow each of the 'real' ports to only talk to
233 * the upstream port.
234 */
235 val = (p & 0xf) << 12;
236 if (dsa_is_cpu_port(ds, p))
237 val |= ds->phys_port_mask;
238 else
239 val |= 1 << dsa_upstream_port(ds);
240 REG_WRITE(addr, 0x06, val);
241
242 /* Default VLAN ID and priority: don't set a default VLAN
243 * ID, and set the default packet priority to zero.
244 */
245 REG_WRITE(addr, 0x07, 0x0000);
246
247 /* Port Control 2: don't force a good FCS, set the maximum 225 /* Port Control 2: don't force a good FCS, set the maximum
248 * frame size to 10240 bytes, don't let the switch add or 226 * frame size to 10240 bytes, don't let the switch add or
249 * strip 802.1q tags, don't discard tagged or untagged frames 227 * strip 802.1q tags, don't discard tagged or untagged frames
@@ -288,18 +266,17 @@ static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p)
288 */ 266 */
289 REG_WRITE(addr, 0x19, 0x7654); 267 REG_WRITE(addr, 0x19, 0x7654);
290 268
291 return 0; 269 return mv88e6xxx_setup_port_common(ds, p);
292} 270}
293 271
294static int mv88e6123_61_65_setup(struct dsa_switch *ds) 272static int mv88e6123_61_65_setup(struct dsa_switch *ds)
295{ 273{
296 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
297 int i; 274 int i;
298 int ret; 275 int ret;
299 276
300 mutex_init(&ps->smi_mutex); 277 ret = mv88e6xxx_setup_common(ds);
301 mutex_init(&ps->stats_mutex); 278 if (ret < 0)
302 mutex_init(&ps->phy_mutex); 279 return ret;
303 280
304 ret = mv88e6123_61_65_switch_reset(ds); 281 ret = mv88e6123_61_65_switch_reset(ds);
305 if (ret < 0) 282 if (ret < 0)
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 9808c860a797..18cfead83dc9 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -17,6 +17,10 @@
17#include <net/dsa.h> 17#include <net/dsa.h>
18#include "mv88e6xxx.h" 18#include "mv88e6xxx.h"
19 19
20/* Switch product IDs */
21#define ID_6171 0x1710
22#define ID_6172 0x1720
23
20static char *mv88e6171_probe(struct device *host_dev, int sw_addr) 24static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
21{ 25{
22 struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); 26 struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
@@ -27,9 +31,9 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
27 31
28 ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); 32 ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
29 if (ret >= 0) { 33 if (ret >= 0) {
30 if ((ret & 0xfff0) == 0x1710) 34 if ((ret & 0xfff0) == ID_6171)
31 return "Marvell 88E6171"; 35 return "Marvell 88E6171";
32 if ((ret & 0xfff0) == 0x1720) 36 if ((ret & 0xfff0) == ID_6172)
33 return "Marvell 88E6172"; 37 return "Marvell 88E6172";
34 } 38 }
35 39
@@ -221,28 +225,6 @@ static int mv88e6171_setup_port(struct dsa_switch *ds, int p)
221 val |= 0x000c; 225 val |= 0x000c;
222 REG_WRITE(addr, 0x04, val); 226 REG_WRITE(addr, 0x04, val);
223 227
224 /* Port Control 1: disable trunking. Also, if this is the
225 * CPU port, enable learn messages to be sent to this port.
226 */
227 REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
228
229 /* Port based VLAN map: give each port its own address
230 * database, allow the CPU port to talk to each of the 'real'
231 * ports, and allow each of the 'real' ports to only talk to
232 * the upstream port.
233 */
234 val = (p & 0xf) << 12;
235 if (dsa_is_cpu_port(ds, p))
236 val |= ds->phys_port_mask;
237 else
238 val |= 1 << dsa_upstream_port(ds);
239 REG_WRITE(addr, 0x06, val);
240
241 /* Default VLAN ID and priority: don't set a default VLAN
242 * ID, and set the default packet priority to zero.
243 */
244 REG_WRITE(addr, 0x07, 0x0000);
245
246 /* Port Control 2: don't force a good FCS, set the maximum 228 /* Port Control 2: don't force a good FCS, set the maximum
247 * frame size to 10240 bytes, don't let the switch add or 229 * frame size to 10240 bytes, don't let the switch add or
248 * strip 802.1q tags, don't discard tagged or untagged frames 230 * strip 802.1q tags, don't discard tagged or untagged frames
@@ -287,17 +269,17 @@ static int mv88e6171_setup_port(struct dsa_switch *ds, int p)
287 */ 269 */
288 REG_WRITE(addr, 0x19, 0x7654); 270 REG_WRITE(addr, 0x19, 0x7654);
289 271
290 return 0; 272 return mv88e6xxx_setup_port_common(ds, p);
291} 273}
292 274
293static int mv88e6171_setup(struct dsa_switch *ds) 275static int mv88e6171_setup(struct dsa_switch *ds)
294{ 276{
295 struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
296 int i; 277 int i;
297 int ret; 278 int ret;
298 279
299 mutex_init(&ps->smi_mutex); 280 ret = mv88e6xxx_setup_common(ds);
300 mutex_init(&ps->stats_mutex); 281 if (ret < 0)
282 return ret;
301 283
302 ret = mv88e6171_switch_reset(ds); 284 ret = mv88e6171_switch_reset(ds);
303 if (ret < 0) 285 if (ret < 0)
@@ -318,8 +300,6 @@ static int mv88e6171_setup(struct dsa_switch *ds)
318 return ret; 300 return ret;
319 } 301 }
320 302
321 mutex_init(&ps->phy_mutex);
322
323 return 0; 303 return 0;
324} 304}
325 305
@@ -410,6 +390,28 @@ static int mv88e6171_get_sset_count(struct dsa_switch *ds)
410 return ARRAY_SIZE(mv88e6171_hw_stats); 390 return ARRAY_SIZE(mv88e6171_hw_stats);
411} 391}
412 392
393static int mv88e6171_get_eee(struct dsa_switch *ds, int port,
394 struct ethtool_eee *e)
395{
396 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
397
398 if (ps->id == ID_6172)
399 return mv88e6xxx_get_eee(ds, port, e);
400
401 return -EOPNOTSUPP;
402}
403
404static int mv88e6171_set_eee(struct dsa_switch *ds, int port,
405 struct phy_device *phydev, struct ethtool_eee *e)
406{
407 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
408
409 if (ps->id == ID_6172)
410 return mv88e6xxx_set_eee(ds, port, phydev, e);
411
412 return -EOPNOTSUPP;
413}
414
413struct dsa_switch_driver mv88e6171_switch_driver = { 415struct dsa_switch_driver mv88e6171_switch_driver = {
414 .tag_protocol = DSA_TAG_PROTO_EDSA, 416 .tag_protocol = DSA_TAG_PROTO_EDSA,
415 .priv_size = sizeof(struct mv88e6xxx_priv_state), 417 .priv_size = sizeof(struct mv88e6xxx_priv_state),
@@ -422,11 +424,19 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
422 .get_strings = mv88e6171_get_strings, 424 .get_strings = mv88e6171_get_strings,
423 .get_ethtool_stats = mv88e6171_get_ethtool_stats, 425 .get_ethtool_stats = mv88e6171_get_ethtool_stats,
424 .get_sset_count = mv88e6171_get_sset_count, 426 .get_sset_count = mv88e6171_get_sset_count,
427 .set_eee = mv88e6171_set_eee,
428 .get_eee = mv88e6171_get_eee,
425#ifdef CONFIG_NET_DSA_HWMON 429#ifdef CONFIG_NET_DSA_HWMON
426 .get_temp = mv88e6xxx_get_temp, 430 .get_temp = mv88e6xxx_get_temp,
427#endif 431#endif
428 .get_regs_len = mv88e6xxx_get_regs_len, 432 .get_regs_len = mv88e6xxx_get_regs_len,
429 .get_regs = mv88e6xxx_get_regs, 433 .get_regs = mv88e6xxx_get_regs,
434 .port_join_bridge = mv88e6xxx_join_bridge,
435 .port_leave_bridge = mv88e6xxx_leave_bridge,
436 .port_stp_update = mv88e6xxx_port_stp_update,
437 .fdb_add = mv88e6xxx_port_fdb_add,
438 .fdb_del = mv88e6xxx_port_fdb_del,
439 .fdb_getnext = mv88e6xxx_port_fdb_getnext,
430}; 440};
431 441
432MODULE_ALIAS("platform:mv88e6171"); 442MODULE_ALIAS("platform:mv88e6171");
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 7bc5998384c6..41fe3a6a72d1 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -215,28 +215,6 @@ static int mv88e6352_setup_port(struct dsa_switch *ds, int p)
215 val |= 0x000c; 215 val |= 0x000c;
216 REG_WRITE(addr, 0x04, val); 216 REG_WRITE(addr, 0x04, val);
217 217
218 /* Port Control 1: disable trunking. Also, if this is the
219 * CPU port, enable learn messages to be sent to this port.
220 */
221 REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
222
223 /* Port based VLAN map: give each port its own address
224 * database, allow the CPU port to talk to each of the 'real'
225 * ports, and allow each of the 'real' ports to only talk to
226 * the upstream port.
227 */
228 val = (p & 0xf) << 12;
229 if (dsa_is_cpu_port(ds, p))
230 val |= ds->phys_port_mask;
231 else
232 val |= 1 << dsa_upstream_port(ds);
233 REG_WRITE(addr, 0x06, val);
234
235 /* Default VLAN ID and priority: don't set a default VLAN
236 * ID, and set the default packet priority to zero.
237 */
238 REG_WRITE(addr, 0x07, 0x0000);
239
240 /* Port Control 2: don't force a good FCS, set the maximum 218 /* Port Control 2: don't force a good FCS, set the maximum
241 * frame size to 10240 bytes, don't let the switch add or 219 * frame size to 10240 bytes, don't let the switch add or
242 * strip 802.1q tags, don't discard tagged or untagged frames 220 * strip 802.1q tags, don't discard tagged or untagged frames
@@ -281,7 +259,7 @@ static int mv88e6352_setup_port(struct dsa_switch *ds, int p)
281 */ 259 */
282 REG_WRITE(addr, 0x19, 0x7654); 260 REG_WRITE(addr, 0x19, 0x7654);
283 261
284 return 0; 262 return mv88e6xxx_setup_port_common(ds, p);
285} 263}
286 264
287#ifdef CONFIG_NET_DSA_HWMON 265#ifdef CONFIG_NET_DSA_HWMON
@@ -385,12 +363,11 @@ static int mv88e6352_setup(struct dsa_switch *ds)
385 int ret; 363 int ret;
386 int i; 364 int i;
387 365
388 mutex_init(&ps->smi_mutex); 366 ret = mv88e6xxx_setup_common(ds);
389 mutex_init(&ps->stats_mutex); 367 if (ret < 0)
390 mutex_init(&ps->phy_mutex); 368 return ret;
391 mutex_init(&ps->eeprom_mutex);
392 369
393 ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0; 370 mutex_init(&ps->eeprom_mutex);
394 371
395 ret = mv88e6352_switch_reset(ds); 372 ret = mv88e6352_switch_reset(ds);
396 if (ret < 0) 373 if (ret < 0)
@@ -729,6 +706,12 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
729 .set_eeprom = mv88e6352_set_eeprom, 706 .set_eeprom = mv88e6352_set_eeprom,
730 .get_regs_len = mv88e6xxx_get_regs_len, 707 .get_regs_len = mv88e6xxx_get_regs_len,
731 .get_regs = mv88e6xxx_get_regs, 708 .get_regs = mv88e6xxx_get_regs,
709 .port_join_bridge = mv88e6xxx_join_bridge,
710 .port_leave_bridge = mv88e6xxx_leave_bridge,
711 .port_stp_update = mv88e6xxx_port_stp_update,
712 .fdb_add = mv88e6xxx_port_fdb_add,
713 .fdb_del = mv88e6xxx_port_fdb_del,
714 .fdb_getnext = mv88e6xxx_port_fdb_getnext,
732}; 715};
733 716
734MODULE_ALIAS("platform:mv88e6352"); 717MODULE_ALIAS("platform:mv88e6352");
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index c18ffc98aacc..13572cc24c6d 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -9,6 +9,8 @@
9 */ 9 */
10 10
11#include <linux/delay.h> 11#include <linux/delay.h>
12#include <linux/etherdevice.h>
13#include <linux/if_bridge.h>
12#include <linux/jiffies.h> 14#include <linux/jiffies.h>
13#include <linux/list.h> 15#include <linux/list.h>
14#include <linux/module.h> 16#include <linux/module.h>
@@ -72,19 +74,16 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
72 return ret & 0xffff; 74 return ret & 0xffff;
73} 75}
74 76
75int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg) 77/* Must be called with SMI mutex held */
78static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
76{ 79{
77 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
78 struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); 80 struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
79 int ret; 81 int ret;
80 82
81 if (bus == NULL) 83 if (bus == NULL)
82 return -EINVAL; 84 return -EINVAL;
83 85
84 mutex_lock(&ps->smi_mutex);
85 ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg); 86 ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg);
86 mutex_unlock(&ps->smi_mutex);
87
88 if (ret < 0) 87 if (ret < 0)
89 return ret; 88 return ret;
90 89
@@ -94,6 +93,18 @@ int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
94 return ret; 93 return ret;
95} 94}
96 95
96int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
97{
98 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
99 int ret;
100
101 mutex_lock(&ps->smi_mutex);
102 ret = _mv88e6xxx_reg_read(ds, addr, reg);
103 mutex_unlock(&ps->smi_mutex);
104
105 return ret;
106}
107
97int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, 108int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
98 int reg, u16 val) 109 int reg, u16 val)
99{ 110{
@@ -125,11 +136,11 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
125 return 0; 136 return 0;
126} 137}
127 138
128int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) 139/* Must be called with SMI mutex held */
140static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg,
141 u16 val)
129{ 142{
130 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
131 struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); 143 struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
132 int ret;
133 144
134 if (bus == NULL) 145 if (bus == NULL)
135 return -EINVAL; 146 return -EINVAL;
@@ -137,8 +148,16 @@ int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
137 dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n", 148 dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
138 addr, reg, val); 149 addr, reg, val);
139 150
151 return __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val);
152}
153
154int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
155{
156 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
157 int ret;
158
140 mutex_lock(&ps->smi_mutex); 159 mutex_lock(&ps->smi_mutex);
141 ret = __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val); 160 ret = _mv88e6xxx_reg_write(ds, addr, reg, val);
142 mutex_unlock(&ps->smi_mutex); 161 mutex_unlock(&ps->smi_mutex);
143 162
144 return ret; 163 return ret;
@@ -627,6 +646,31 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
627 return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x8000); 646 return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x8000);
628} 647}
629 648
649/* Must be called with SMI lock held */
650static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
651{
652 unsigned long timeout = jiffies + HZ / 10;
653
654 while (time_before(jiffies, timeout)) {
655 int ret;
656
657 ret = _mv88e6xxx_reg_read(ds, reg, offset);
658 if (ret < 0)
659 return ret;
660 if (!(ret & mask))
661 return 0;
662
663 usleep_range(1000, 2000);
664 }
665 return -ETIMEDOUT;
666}
667
668/* Must be called with SMI lock held */
669static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
670{
671 return _mv88e6xxx_wait(ds, REG_GLOBAL, 0x0b, ATU_BUSY);
672}
673
630int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum) 674int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum)
631{ 675{
632 int ret; 676 int ret;
@@ -700,6 +744,423 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
700 return 0; 744 return 0;
701} 745}
702 746
747static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd)
748{
749 int ret;
750
751 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x01, fid);
752 if (ret < 0)
753 return ret;
754
755 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0b, cmd);
756 if (ret < 0)
757 return ret;
758
759 return _mv88e6xxx_atu_wait(ds);
760}
761
762static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid)
763{
764 int ret;
765
766 ret = _mv88e6xxx_atu_wait(ds);
767 if (ret < 0)
768 return ret;
769
770 return _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_FLUSH_NONSTATIC_FID);
771}
772
773static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state)
774{
775 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
776 int reg, ret;
777 u8 oldstate;
778
779 mutex_lock(&ps->smi_mutex);
780
781 reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), 0x04);
782 if (reg < 0)
783 goto abort;
784
785 oldstate = reg & PSTATE_MASK;
786 if (oldstate != state) {
787 /* Flush forwarding database if we're moving a port
788 * from Learning or Forwarding state to Disabled or
789 * Blocking or Listening state.
790 */
791 if (oldstate >= PSTATE_LEARNING && state <= PSTATE_BLOCKING) {
792 ret = _mv88e6xxx_flush_fid(ds, ps->fid[port]);
793 if (ret)
794 goto abort;
795 }
796 reg = (reg & ~PSTATE_MASK) | state;
797 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x04, reg);
798 }
799
800abort:
801 mutex_unlock(&ps->smi_mutex);
802 return ret;
803}
804
805/* Must be called with smi lock held */
806static int _mv88e6xxx_update_port_config(struct dsa_switch *ds, int port)
807{
808 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
809 u8 fid = ps->fid[port];
810 u16 reg = fid << 12;
811
812 if (dsa_is_cpu_port(ds, port))
813 reg |= ds->phys_port_mask;
814 else
815 reg |= (ps->bridge_mask[fid] |
816 (1 << dsa_upstream_port(ds))) & ~(1 << port);
817
818 return _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x06, reg);
819}
820
821/* Must be called with smi lock held */
822static int _mv88e6xxx_update_bridge_config(struct dsa_switch *ds, int fid)
823{
824 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
825 int port;
826 u32 mask;
827 int ret;
828
829 mask = ds->phys_port_mask;
830 while (mask) {
831 port = __ffs(mask);
832 mask &= ~(1 << port);
833 if (ps->fid[port] != fid)
834 continue;
835
836 ret = _mv88e6xxx_update_port_config(ds, port);
837 if (ret)
838 return ret;
839 }
840
841 return _mv88e6xxx_flush_fid(ds, fid);
842}
843
844/* Bridge handling functions */
845
846int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
847{
848 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
849 int ret = 0;
850 u32 nmask;
851 int fid;
852
853 /* If the bridge group is not empty, join that group.
854 * Otherwise create a new group.
855 */
856 fid = ps->fid[port];
857 nmask = br_port_mask & ~(1 << port);
858 if (nmask)
859 fid = ps->fid[__ffs(nmask)];
860
861 nmask = ps->bridge_mask[fid] | (1 << port);
862 if (nmask != br_port_mask) {
863 netdev_err(ds->ports[port],
864 "join: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
865 fid, br_port_mask, nmask);
866 return -EINVAL;
867 }
868
869 mutex_lock(&ps->smi_mutex);
870
871 ps->bridge_mask[fid] = br_port_mask;
872
873 if (fid != ps->fid[port]) {
874 ps->fid_mask |= 1 << ps->fid[port];
875 ps->fid[port] = fid;
876 ret = _mv88e6xxx_update_bridge_config(ds, fid);
877 }
878
879 mutex_unlock(&ps->smi_mutex);
880
881 return ret;
882}
883
884int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
885{
886 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
887 u8 fid, newfid;
888 int ret;
889
890 fid = ps->fid[port];
891
892 if (ps->bridge_mask[fid] != br_port_mask) {
893 netdev_err(ds->ports[port],
894 "leave: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
895 fid, br_port_mask, ps->bridge_mask[fid]);
896 return -EINVAL;
897 }
898
899 /* If the port was the last port of a bridge, we are done.
900 * Otherwise assign a new fid to the port, and fix up
901 * the bridge configuration.
902 */
903 if (br_port_mask == (1 << port))
904 return 0;
905
906 mutex_lock(&ps->smi_mutex);
907
908 newfid = __ffs(ps->fid_mask);
909 ps->fid[port] = newfid;
910 ps->fid_mask &= (1 << newfid);
911 ps->bridge_mask[fid] &= ~(1 << port);
912 ps->bridge_mask[newfid] = 1 << port;
913
914 ret = _mv88e6xxx_update_bridge_config(ds, fid);
915 if (!ret)
916 ret = _mv88e6xxx_update_bridge_config(ds, newfid);
917
918 mutex_unlock(&ps->smi_mutex);
919
920 return ret;
921}
922
923int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
924{
925 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
926 int stp_state;
927
928 switch (state) {
929 case BR_STATE_DISABLED:
930 stp_state = PSTATE_DISABLED;
931 break;
932 case BR_STATE_BLOCKING:
933 case BR_STATE_LISTENING:
934 stp_state = PSTATE_BLOCKING;
935 break;
936 case BR_STATE_LEARNING:
937 stp_state = PSTATE_LEARNING;
938 break;
939 case BR_STATE_FORWARDING:
940 default:
941 stp_state = PSTATE_FORWARDING;
942 break;
943 }
944
945 netdev_dbg(ds->ports[port], "port state %d [%d]\n", state, stp_state);
946
947 /* mv88e6xxx_port_stp_update may be called with softirqs disabled,
948 * so we can not update the port state directly but need to schedule it.
949 */
950 ps->port_state[port] = stp_state;
951 set_bit(port, &ps->port_state_update_mask);
952 schedule_work(&ps->bridge_work);
953
954 return 0;
955}
956
957static int __mv88e6xxx_write_addr(struct dsa_switch *ds,
958 const unsigned char *addr)
959{
960 int i, ret;
961
962 for (i = 0; i < 3; i++) {
963 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0d + i,
964 (addr[i * 2] << 8) | addr[i * 2 + 1]);
965 if (ret < 0)
966 return ret;
967 }
968
969 return 0;
970}
971
972static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr)
973{
974 int i, ret;
975
976 for (i = 0; i < 3; i++) {
977 ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0d + i);
978 if (ret < 0)
979 return ret;
980 addr[i * 2] = ret >> 8;
981 addr[i * 2 + 1] = ret & 0xff;
982 }
983
984 return 0;
985}
986
987static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port,
988 const unsigned char *addr, int state)
989{
990 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
991 u8 fid = ps->fid[port];
992 int ret;
993
994 ret = _mv88e6xxx_atu_wait(ds);
995 if (ret < 0)
996 return ret;
997
998 ret = __mv88e6xxx_write_addr(ds, addr);
999 if (ret < 0)
1000 return ret;
1001
1002 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0c,
1003 (0x10 << port) | state);
1004 if (ret)
1005 return ret;
1006
1007 ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_LOAD_FID);
1008
1009 return ret;
1010}
1011
1012int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
1013 const unsigned char *addr, u16 vid)
1014{
1015 int state = is_multicast_ether_addr(addr) ?
1016 FDB_STATE_MC_STATIC : FDB_STATE_STATIC;
1017 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1018 int ret;
1019
1020 mutex_lock(&ps->smi_mutex);
1021 ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state);
1022 mutex_unlock(&ps->smi_mutex);
1023
1024 return ret;
1025}
1026
1027int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
1028 const unsigned char *addr, u16 vid)
1029{
1030 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1031 int ret;
1032
1033 mutex_lock(&ps->smi_mutex);
1034 ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, FDB_STATE_UNUSED);
1035 mutex_unlock(&ps->smi_mutex);
1036
1037 return ret;
1038}
1039
1040static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port,
1041 unsigned char *addr, bool *is_static)
1042{
1043 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1044 u8 fid = ps->fid[port];
1045 int ret, state;
1046
1047 ret = _mv88e6xxx_atu_wait(ds);
1048 if (ret < 0)
1049 return ret;
1050
1051 ret = __mv88e6xxx_write_addr(ds, addr);
1052 if (ret < 0)
1053 return ret;
1054
1055 do {
1056 ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_GETNEXT_FID);
1057 if (ret < 0)
1058 return ret;
1059
1060 ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0c);
1061 if (ret < 0)
1062 return ret;
1063 state = ret & FDB_STATE_MASK;
1064 if (state == FDB_STATE_UNUSED)
1065 return -ENOENT;
1066 } while (!(((ret >> 4) & 0xff) & (1 << port)));
1067
1068 ret = __mv88e6xxx_read_addr(ds, addr);
1069 if (ret < 0)
1070 return ret;
1071
1072 *is_static = state == (is_multicast_ether_addr(addr) ?
1073 FDB_STATE_MC_STATIC : FDB_STATE_STATIC);
1074
1075 return 0;
1076}
1077
1078/* get next entry for port */
1079int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
1080 unsigned char *addr, bool *is_static)
1081{
1082 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1083 int ret;
1084
1085 mutex_lock(&ps->smi_mutex);
1086 ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static);
1087 mutex_unlock(&ps->smi_mutex);
1088
1089 return ret;
1090}
1091
1092static void mv88e6xxx_bridge_work(struct work_struct *work)
1093{
1094 struct mv88e6xxx_priv_state *ps;
1095 struct dsa_switch *ds;
1096 int port;
1097
1098 ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work);
1099 ds = ((struct dsa_switch *)ps) - 1;
1100
1101 while (ps->port_state_update_mask) {
1102 port = __ffs(ps->port_state_update_mask);
1103 clear_bit(port, &ps->port_state_update_mask);
1104 mv88e6xxx_set_port_state(ds, port, ps->port_state[port]);
1105 }
1106}
1107
1108int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
1109{
1110 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1111 int ret, fid;
1112
1113 mutex_lock(&ps->smi_mutex);
1114
1115 /* Port Control 1: disable trunking, disable sending
1116 * learning messages to this port.
1117 */
1118 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x05, 0x0000);
1119 if (ret)
1120 goto abort;
1121
1122 /* Port based VLAN map: give each port its own address
1123 * database, allow the CPU port to talk to each of the 'real'
1124 * ports, and allow each of the 'real' ports to only talk to
1125 * the upstream port.
1126 */
1127 fid = __ffs(ps->fid_mask);
1128 ps->fid[port] = fid;
1129 ps->fid_mask &= ~(1 << fid);
1130
1131 if (!dsa_is_cpu_port(ds, port))
1132 ps->bridge_mask[fid] = 1 << port;
1133
1134 ret = _mv88e6xxx_update_port_config(ds, port);
1135 if (ret)
1136 goto abort;
1137
1138 /* Default VLAN ID and priority: don't set a default VLAN
1139 * ID, and set the default packet priority to zero.
1140 */
1141 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x07, 0x0000);
1142abort:
1143 mutex_unlock(&ps->smi_mutex);
1144 return ret;
1145}
1146
1147int mv88e6xxx_setup_common(struct dsa_switch *ds)
1148{
1149 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1150
1151 mutex_init(&ps->smi_mutex);
1152 mutex_init(&ps->stats_mutex);
1153 mutex_init(&ps->phy_mutex);
1154
1155 ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0;
1156
1157 ps->fid_mask = (1 << DSA_MAX_PORTS) - 1;
1158
1159 INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
1160
1161 return 0;
1162}
1163
703static int __init mv88e6xxx_init(void) 1164static int __init mv88e6xxx_init(void)
704{ 1165{
705#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) 1166#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 5fd42ced9011..aaf239aba726 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -15,6 +15,30 @@
15#define REG_GLOBAL 0x1b 15#define REG_GLOBAL 0x1b
16#define REG_GLOBAL2 0x1c 16#define REG_GLOBAL2 0x1c
17 17
18/* ATU commands */
19
20#define ATU_BUSY 0x8000
21
22#define ATU_CMD_LOAD_FID (ATU_BUSY | 0x3000)
23#define ATU_CMD_GETNEXT_FID (ATU_BUSY | 0x4000)
24#define ATU_CMD_FLUSH_NONSTATIC_FID (ATU_BUSY | 0x6000)
25
26/* port states */
27
28#define PSTATE_MASK 0x03
29#define PSTATE_DISABLED 0x00
30#define PSTATE_BLOCKING 0x01
31#define PSTATE_LEARNING 0x02
32#define PSTATE_FORWARDING 0x03
33
34/* FDB states */
35
36#define FDB_STATE_MASK 0x0f
37
38#define FDB_STATE_UNUSED 0x00
39#define FDB_STATE_MC_STATIC 0x07 /* static multicast */
40#define FDB_STATE_STATIC 0x0e /* static unicast */
41
18struct mv88e6xxx_priv_state { 42struct mv88e6xxx_priv_state {
19 /* When using multi-chip addressing, this mutex protects 43 /* When using multi-chip addressing, this mutex protects
20 * access to the indirect access registers. (In single-chip 44 * access to the indirect access registers. (In single-chip
@@ -49,6 +73,17 @@ struct mv88e6xxx_priv_state {
49 struct mutex eeprom_mutex; 73 struct mutex eeprom_mutex;
50 74
51 int id; /* switch product id */ 75 int id; /* switch product id */
76
77 /* hw bridging */
78
79 u32 fid_mask;
80 u8 fid[DSA_MAX_PORTS];
81 u16 bridge_mask[DSA_MAX_PORTS];
82
83 unsigned long port_state_update_mask;
84 u8 port_state[DSA_MAX_PORTS];
85
86 struct work_struct bridge_work;
52}; 87};
53 88
54struct mv88e6xxx_hw_stat { 89struct mv88e6xxx_hw_stat {
@@ -57,6 +92,8 @@ struct mv88e6xxx_hw_stat {
57 int reg; 92 int reg;
58}; 93};
59 94
95int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port);
96int mv88e6xxx_setup_common(struct dsa_switch *ds);
60int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg); 97int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg);
61int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg); 98int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg);
62int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, 99int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
@@ -91,6 +128,15 @@ int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
91int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e); 128int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
92int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, 129int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
93 struct phy_device *phydev, struct ethtool_eee *e); 130 struct phy_device *phydev, struct ethtool_eee *e);
131int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
132int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
133int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
134int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
135 const unsigned char *addr, u16 vid);
136int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
137 const unsigned char *addr, u16 vid);
138int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
139 unsigned char *addr, bool *is_static);
94 140
95extern struct dsa_switch_driver mv88e6131_switch_driver; 141extern struct dsa_switch_driver mv88e6131_switch_driver;
96extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; 142extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 47917e5e1e12..fbca63ba8f73 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -296,6 +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 int (*fdb_add)(struct dsa_switch *ds, int port,
300 const unsigned char *addr, u16 vid);
301 int (*fdb_del)(struct dsa_switch *ds, int port,
302 const unsigned char *addr, u16 vid);
303 int (*fdb_getnext)(struct dsa_switch *ds, int port,
304 unsigned char *addr, bool *is_static);
299}; 305};
300 306
301void register_switch_driver(struct dsa_switch_driver *type); 307void register_switch_driver(struct dsa_switch_driver *type);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 39555f3f263b..3597724ec3d8 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -201,6 +201,105 @@ out:
201 return 0; 201 return 0;
202} 202}
203 203
204static int dsa_slave_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
205 struct net_device *dev,
206 const unsigned char *addr, u16 vid, u16 nlm_flags)
207{
208 struct dsa_slave_priv *p = netdev_priv(dev);
209 struct dsa_switch *ds = p->parent;
210 int ret = -EOPNOTSUPP;
211
212 if (ds->drv->fdb_add)
213 ret = ds->drv->fdb_add(ds, p->port, addr, vid);
214
215 return ret;
216}
217
218static int dsa_slave_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
219 struct net_device *dev,
220 const unsigned char *addr, u16 vid)
221{
222 struct dsa_slave_priv *p = netdev_priv(dev);
223 struct dsa_switch *ds = p->parent;
224 int ret = -EOPNOTSUPP;
225
226 if (ds->drv->fdb_del)
227 ret = ds->drv->fdb_del(ds, p->port, addr, vid);
228
229 return ret;
230}
231
232static int dsa_slave_fill_info(struct net_device *dev, struct sk_buff *skb,
233 const unsigned char *addr, u16 vid,
234 bool is_static,
235 u32 portid, u32 seq, int type,
236 unsigned int flags)
237{
238 struct nlmsghdr *nlh;
239 struct ndmsg *ndm;
240
241 nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
242 if (!nlh)
243 return -EMSGSIZE;
244
245 ndm = nlmsg_data(nlh);
246 ndm->ndm_family = AF_BRIDGE;
247 ndm->ndm_pad1 = 0;
248 ndm->ndm_pad2 = 0;
249 ndm->ndm_flags = NTF_EXT_LEARNED;
250 ndm->ndm_type = 0;
251 ndm->ndm_ifindex = dev->ifindex;
252 ndm->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
253
254 if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
255 goto nla_put_failure;
256
257 if (vid && nla_put_u16(skb, NDA_VLAN, vid))
258 goto nla_put_failure;
259
260 nlmsg_end(skb, nlh);
261 return 0;
262
263nla_put_failure:
264 nlmsg_cancel(skb, nlh);
265 return -EMSGSIZE;
266}
267
268/* Dump information about entries, in response to GETNEIGH */
269static int dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
270 struct net_device *dev,
271 struct net_device *filter_dev, int idx)
272{
273 struct dsa_slave_priv *p = netdev_priv(dev);
274 struct dsa_switch *ds = p->parent;
275 unsigned char addr[ETH_ALEN] = { 0 };
276 int ret;
277
278 if (!ds->drv->fdb_getnext)
279 return -EOPNOTSUPP;
280
281 for (; ; idx++) {
282 bool is_static;
283
284 ret = ds->drv->fdb_getnext(ds, p->port, addr, &is_static);
285 if (ret < 0)
286 break;
287
288 if (idx < cb->args[0])
289 continue;
290
291 ret = dsa_slave_fill_info(dev, skb, addr, 0,
292 is_static,
293 NETLINK_CB(cb->skb).portid,
294 cb->nlh->nlmsg_seq,
295 RTM_NEWNEIGH, NLM_F_MULTI);
296 if (ret < 0)
297 break;
298 }
299
300 return idx;
301}
302
204static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 303static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
205{ 304{
206 struct dsa_slave_priv *p = netdev_priv(dev); 305 struct dsa_slave_priv *p = netdev_priv(dev);
@@ -572,6 +671,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
572 .ndo_change_rx_flags = dsa_slave_change_rx_flags, 671 .ndo_change_rx_flags = dsa_slave_change_rx_flags,
573 .ndo_set_rx_mode = dsa_slave_set_rx_mode, 672 .ndo_set_rx_mode = dsa_slave_set_rx_mode,
574 .ndo_set_mac_address = dsa_slave_set_mac_address, 673 .ndo_set_mac_address = dsa_slave_set_mac_address,
674 .ndo_fdb_add = dsa_slave_fdb_add,
675 .ndo_fdb_del = dsa_slave_fdb_del,
676 .ndo_fdb_dump = dsa_slave_fdb_dump,
575 .ndo_do_ioctl = dsa_slave_ioctl, 677 .ndo_do_ioctl = dsa_slave_ioctl,
576}; 678};
577 679