diff options
-rw-r--r-- | include/net/dsa.h | 1 | ||||
-rw-r--r-- | net/dsa/dsa.c | 5 | ||||
-rw-r--r-- | net/dsa/dsa_priv.h | 4 | ||||
-rw-r--r-- | net/dsa/slave.c | 76 |
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 | ||
317 | static 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 *******************************************************/ |
342 | static 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 | |||
316 | struct net_device * | 381 | struct net_device * |
317 | dsa_slave_create(struct dsa_switch *ds, struct device *parent, | 382 | dsa_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) { |