aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/dsa.h1
-rw-r--r--net/dsa/dsa.c5
-rw-r--r--net/dsa/dsa_priv.h4
-rw-r--r--net/dsa/slave.c76
4 files changed, 83 insertions, 3 deletions
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 597875d3f69e..dc357454ae3b 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -130,6 +130,7 @@ struct dsa_switch {
130 */ 130 */
131 u32 dsa_port_mask; 131 u32 dsa_port_mask;
132 u32 phys_port_mask; 132 u32 phys_port_mask;
133 u32 phys_mii_mask;
133 struct mii_bus *slave_mii_bus; 134 struct mii_bus *slave_mii_bus;
134 struct net_device *ports[DSA_MAX_PORTS]; 135 struct net_device *ports[DSA_MAX_PORTS];
135}; 136};
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 6a5bae673037..4dc2a16b72cf 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -144,6 +144,11 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
144 goto out; 144 goto out;
145 } 145 }
146 146
147 /* Make the built-in MII bus mask match the number of ports,
148 * switch drivers can override this later
149 */
150 ds->phys_mii_mask = ds->phys_port_mask;
151
147 /* 152 /*
148 * If the CPU connects to this switch, set the switch tree 153 * If the CPU connects to this switch, set the switch tree
149 * tagging protocol to the preferred tagging format of this 154 * tagging protocol to the preferred tagging format of this
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 218d75d16f6f..d20364ac1574 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -33,6 +33,10 @@ struct dsa_slave_priv {
33 * to this port. 33 * to this port.
34 */ 34 */
35 struct phy_device *phy; 35 struct phy_device *phy;
36 phy_interface_t phy_interface;
37 int old_link;
38 int old_pause;
39 int old_duplex;
36}; 40};
37 41
38/* dsa.c */ 42/* dsa.c */
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 5688c34253e5..03d2894a0f8a 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -12,6 +12,8 @@
12#include <linux/netdevice.h> 12#include <linux/netdevice.h>
13#include <linux/etherdevice.h> 13#include <linux/etherdevice.h>
14#include <linux/phy.h> 14#include <linux/phy.h>
15#include <linux/of_net.h>
16#include <linux/of_mdio.h>
15#include "dsa_priv.h" 17#include "dsa_priv.h"
16 18
17/* slave mii_bus handling ***************************************************/ 19/* slave mii_bus handling ***************************************************/
@@ -19,7 +21,7 @@ static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
19{ 21{
20 struct dsa_switch *ds = bus->priv; 22 struct dsa_switch *ds = bus->priv;
21 23
22 if (ds->phys_port_mask & (1 << addr)) 24 if (ds->phys_mii_mask & (1 << addr))
23 return ds->drv->phy_read(ds, addr, reg); 25 return ds->drv->phy_read(ds, addr, reg);
24 26
25 return 0xffff; 27 return 0xffff;
@@ -29,7 +31,7 @@ static int dsa_slave_phy_write(struct mii_bus *bus, int addr, int reg, u16 val)
29{ 31{
30 struct dsa_switch *ds = bus->priv; 32 struct dsa_switch *ds = bus->priv;
31 33
32 if (ds->phys_port_mask & (1 << addr)) 34 if (ds->phys_mii_mask & (1 << addr))
33 return ds->drv->phy_write(ds, addr, reg, val); 35 return ds->drv->phy_write(ds, addr, reg, val);
34 36
35 return 0; 37 return 0;
@@ -312,7 +314,70 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
312 .ndo_do_ioctl = dsa_slave_ioctl, 314 .ndo_do_ioctl = dsa_slave_ioctl,
313}; 315};
314 316
317static void dsa_slave_adjust_link(struct net_device *dev)
318{
319 struct dsa_slave_priv *p = netdev_priv(dev);
320 unsigned int status_changed = 0;
321
322 if (p->old_link != p->phy->link) {
323 status_changed = 1;
324 p->old_link = p->phy->link;
325 }
326
327 if (p->old_duplex != p->phy->duplex) {
328 status_changed = 1;
329 p->old_duplex = p->phy->duplex;
330 }
331
332 if (p->old_pause != p->phy->pause) {
333 status_changed = 1;
334 p->old_pause = p->phy->pause;
335 }
336
337 if (status_changed)
338 phy_print_status(p->phy);
339}
340
315/* slave device setup *******************************************************/ 341/* slave device setup *******************************************************/
342static void dsa_slave_phy_setup(struct dsa_slave_priv *p,
343 struct net_device *slave_dev)
344{
345 struct dsa_switch *ds = p->parent;
346 struct dsa_chip_data *cd = ds->pd;
347 struct device_node *phy_dn, *port_dn;
348 int ret;
349
350 port_dn = cd->port_dn[p->port];
351 p->phy_interface = of_get_phy_mode(port_dn);
352
353 phy_dn = of_parse_phandle(port_dn, "phy-handle", 0);
354 if (of_phy_is_fixed_link(port_dn)) {
355 /* In the case of a fixed PHY, the DT node associated
356 * to the fixed PHY is the Port DT node
357 */
358 ret = of_phy_register_fixed_link(port_dn);
359 if (ret) {
360 pr_err("failed to register fixed PHY\n");
361 return;
362 }
363 phy_dn = port_dn;
364 }
365
366 if (phy_dn)
367 p->phy = of_phy_connect(slave_dev, phy_dn,
368 dsa_slave_adjust_link, 0,
369 p->phy_interface);
370
371 /* We could not connect to a designated PHY, so use the switch internal
372 * MDIO bus instead
373 */
374 if (!p->phy)
375 p->phy = ds->slave_mii_bus->phy_map[p->port];
376 else
377 pr_info("attached PHY at address %d [%s]\n",
378 p->phy->addr, p->phy->drv->name);
379}
380
316struct net_device * 381struct net_device *
317dsa_slave_create(struct dsa_switch *ds, struct device *parent, 382dsa_slave_create(struct dsa_switch *ds, struct device *parent,
318 int port, char *name) 383 int port, char *name)
@@ -361,7 +426,12 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
361 p->dev = slave_dev; 426 p->dev = slave_dev;
362 p->parent = ds; 427 p->parent = ds;
363 p->port = port; 428 p->port = port;
364 p->phy = ds->slave_mii_bus->phy_map[port]; 429
430 p->old_pause = -1;
431 p->old_link = -1;
432 p->old_duplex = -1;
433
434 dsa_slave_phy_setup(p, slave_dev);
365 435
366 ret = register_netdev(slave_dev); 436 ret = register_netdev(slave_dev);
367 if (ret) { 437 if (ret) {