Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'dsa_phy_divert'

Florian Fainelli says:

====================
net: dsa: support PHY reads/writes diversion

This patch series completes the PHY reads/writes diversion when we need to use
the slave MII bus provided by DSA and the underlying switch drivers to
implement the real PHY reads and writes. This is particularly useful when they
are conflicting MDIO bus addresses as in the case of multiple Broadcom switches
connected to each other (internal and external, or just external).
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+48 -13
+2 -1
drivers/of/of_mdio.c
··· 88 88 return 0; 89 89 } 90 90 91 - static int of_mdio_parse_addr(struct device *dev, const struct device_node *np) 91 + int of_mdio_parse_addr(struct device *dev, const struct device_node *np) 92 92 { 93 93 u32 addr; 94 94 int ret; ··· 108 108 109 109 return addr; 110 110 } 111 + EXPORT_SYMBOL(of_mdio_parse_addr); 111 112 112 113 /** 113 114 * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
+7
include/linux/of_mdio.h
··· 24 24 phy_interface_t iface); 25 25 26 26 extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np); 27 + extern int of_mdio_parse_addr(struct device *dev, const struct device_node *np); 27 28 28 29 #else /* CONFIG_OF */ 29 30 static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) ··· 60 59 static inline struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np) 61 60 { 62 61 return NULL; 62 + } 63 + 64 + static inline int of_mdio_parse_addr(struct device *dev, 65 + const struct device_node *np) 66 + { 67 + return -ENOSYS; 63 68 } 64 69 #endif /* CONFIG_OF */ 65 70
+39 -12
net/dsa/slave.c
··· 617 617 } 618 618 619 619 /* slave device setup *******************************************************/ 620 + static int dsa_slave_phy_connect(struct dsa_slave_priv *p, 621 + struct net_device *slave_dev, 622 + int addr) 623 + { 624 + struct dsa_switch *ds = p->parent; 625 + 626 + p->phy = ds->slave_mii_bus->phy_map[addr]; 627 + if (!p->phy) 628 + return -ENODEV; 629 + 630 + /* Use already configured phy mode */ 631 + p->phy_interface = p->phy->interface; 632 + phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, 633 + p->phy_interface); 634 + 635 + return 0; 636 + } 637 + 620 638 static int dsa_slave_phy_setup(struct dsa_slave_priv *p, 621 639 struct net_device *slave_dev) 622 640 { ··· 668 650 if (ds->drv->get_phy_flags) 669 651 phy_flags = ds->drv->get_phy_flags(ds, p->port); 670 652 671 - if (phy_dn) 672 - p->phy = of_phy_connect(slave_dev, phy_dn, 673 - dsa_slave_adjust_link, phy_flags, 674 - p->phy_interface); 653 + if (phy_dn) { 654 + ret = of_mdio_parse_addr(&slave_dev->dev, phy_dn); 655 + /* If this PHY address is part of phys_mii_mask, which means 656 + * that we need to divert reads and writes to/from it, then we 657 + * want to bind this device using the slave MII bus created by 658 + * DSA to make that happen. 659 + */ 660 + if (ret >= 0 && (ds->phys_mii_mask & (1 << ret))) { 661 + ret = dsa_slave_phy_connect(p, slave_dev, ret); 662 + if (ret) 663 + return ret; 664 + } else { 665 + p->phy = of_phy_connect(slave_dev, phy_dn, 666 + dsa_slave_adjust_link, 667 + phy_flags, 668 + p->phy_interface); 669 + } 670 + } 675 671 676 672 if (p->phy && phy_is_fixed) 677 673 fixed_phy_set_link_update(p->phy, dsa_slave_fixed_link_update); ··· 694 662 * MDIO bus instead 695 663 */ 696 664 if (!p->phy) { 697 - p->phy = ds->slave_mii_bus->phy_map[p->port]; 698 - if (!p->phy) 699 - return -ENODEV; 700 - 701 - /* Use already configured phy mode */ 702 - p->phy_interface = p->phy->interface; 703 - phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, 704 - p->phy_interface); 665 + ret = dsa_slave_phy_connect(p, slave_dev, p->port); 666 + if (ret) 667 + return ret; 705 668 } else { 706 669 netdev_info(slave_dev, "attached PHY at address %d [%s]\n", 707 670 p->phy->addr, p->phy->drv->name);