aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-03-29 16:24:05 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-29 16:24:05 -0400
commit7836b16c0dd1d3039ccc35ceeff6d75401fbba8c (patch)
tree62f92afc09fc12f37e1048147ea0090e652921c8
parent5ce58c2f13eaa8ca6d7e1041175433bd8cc55756 (diff)
parentb2a6b93a0c5730dd96f224ed22ccd0662d06b3b0 (diff)
Merge branch 'dsa-hw-bridging'
Guenter Roeck says: ==================== net: dsa: HW bridging, EEE support Patch 1 to 7 of this series prepare the drivers using the mv88e6xxx code for HW bridging support, without adding the code itself. For the most part this factors out common port initialization code. There is no functional change except for patch 3, which disables the message port bit for the CPU port to prevent packet duplication if HW bridging is configured. Patch 8 adds the infrastructure for hardware bridging support to the mv88e6xxx code. Patch 9 wires the MV88E6352 driver to support hardware bridging. Patches 10 to 12 add support for ndo_fdb functions to the dsa subsystem, and wire up the MV88E6352 driver to support those functions. Patches 13 to 16 add EEE support and HW bridging support to the mv88e6171 driver. This set of patches is from Andrew, applied on top of the first set of patches. The series applies to net-next as of 3/24/2015. Thanks a lot to Andrew Lunn for testing and valuable feedback. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-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