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

net: phy: add helpers to handle sfp phy connect/disconnect

There are a few PHY drivers that can handle SFP modules through their
sfp_upstream_ops. Introduce Phylib helpers to keep track of connected
SFP PHYs in a netdevice's namespace, by adding the SFP PHY to the
upstream PHY's netdev's namespace.

By doing so, these SFP PHYs can be enumerated and exposed to users,
which will be able to use their capabilities.

Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Tested-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Maxime Chevallier and committed by
David S. Miller
b2db6f4a 4d76f115

+54
+2
drivers/net/phy/marvell-88x2222.c
··· 553 553 .link_down = mv2222_sfp_link_down, 554 554 .attach = phy_sfp_attach, 555 555 .detach = phy_sfp_detach, 556 + .connect_phy = phy_sfp_connect_phy, 557 + .disconnect_phy = phy_sfp_disconnect_phy, 556 558 }; 557 559 558 560 static int mv2222_probe(struct phy_device *phydev)
+2
drivers/net/phy/marvell.c
··· 3613 3613 .module_remove = m88e1510_sfp_remove, 3614 3614 .attach = phy_sfp_attach, 3615 3615 .detach = phy_sfp_detach, 3616 + .connect_phy = phy_sfp_connect_phy, 3617 + .disconnect_phy = phy_sfp_disconnect_phy, 3616 3618 }; 3617 3619 3618 3620 static int m88e1510_probe(struct phy_device *phydev)
+2
drivers/net/phy/marvell10g.c
··· 503 503 static const struct sfp_upstream_ops mv3310_sfp_ops = { 504 504 .attach = phy_sfp_attach, 505 505 .detach = phy_sfp_detach, 506 + .connect_phy = phy_sfp_connect_phy, 507 + .disconnect_phy = phy_sfp_disconnect_phy, 506 508 .module_insert = mv3310_sfp_insert, 507 509 }; 508 510
+42
drivers/net/phy/phy_device.c
··· 1386 1386 static DEVICE_ATTR_RO(phy_standalone); 1387 1387 1388 1388 /** 1389 + * phy_sfp_connect_phy - Connect the SFP module's PHY to the upstream PHY 1390 + * @upstream: pointer to the upstream phy device 1391 + * @phy: pointer to the SFP module's phy device 1392 + * 1393 + * This helper allows keeping track of PHY devices on the link. It adds the 1394 + * SFP module's phy to the phy namespace of the upstream phy 1395 + * 1396 + * Return: 0 on success, otherwise a negative error code. 1397 + */ 1398 + int phy_sfp_connect_phy(void *upstream, struct phy_device *phy) 1399 + { 1400 + struct phy_device *phydev = upstream; 1401 + struct net_device *dev = phydev->attached_dev; 1402 + 1403 + if (dev) 1404 + return phy_link_topo_add_phy(dev, phy, PHY_UPSTREAM_PHY, phydev); 1405 + 1406 + return 0; 1407 + } 1408 + EXPORT_SYMBOL(phy_sfp_connect_phy); 1409 + 1410 + /** 1411 + * phy_sfp_disconnect_phy - Disconnect the SFP module's PHY from the upstream PHY 1412 + * @upstream: pointer to the upstream phy device 1413 + * @phy: pointer to the SFP module's phy device 1414 + * 1415 + * This helper allows keeping track of PHY devices on the link. It removes the 1416 + * SFP module's phy to the phy namespace of the upstream phy. As the module phy 1417 + * will be destroyed, re-inserting the same module will add a new phy with a 1418 + * new index. 1419 + */ 1420 + void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy) 1421 + { 1422 + struct phy_device *phydev = upstream; 1423 + struct net_device *dev = phydev->attached_dev; 1424 + 1425 + if (dev) 1426 + phy_link_topo_del_phy(dev, phy); 1427 + } 1428 + EXPORT_SYMBOL(phy_sfp_disconnect_phy); 1429 + 1430 + /** 1389 1431 * phy_sfp_attach - attach the SFP bus to the PHY upstream network device 1390 1432 * @upstream: pointer to the phy device 1391 1433 * @bus: sfp bus representing cage being attached
+2
drivers/net/phy/qcom/at803x.c
··· 770 770 .attach = phy_sfp_attach, 771 771 .detach = phy_sfp_detach, 772 772 .module_insert = at8031_sfp_insert, 773 + .connect_phy = phy_sfp_connect_phy, 774 + .disconnect_phy = phy_sfp_disconnect_phy, 773 775 }; 774 776 775 777 static int at8031_parse_dt(struct phy_device *phydev)
+2
drivers/net/phy/qcom/qca807x.c
··· 699 699 .detach = phy_sfp_detach, 700 700 .module_insert = qca807x_sfp_insert, 701 701 .module_remove = qca807x_sfp_remove, 702 + .connect_phy = phy_sfp_connect_phy, 703 + .disconnect_phy = phy_sfp_disconnect_phy, 702 704 }; 703 705 704 706 static int qca807x_probe(struct phy_device *phydev)
+2
include/linux/phy.h
··· 1781 1781 int phy_resume(struct phy_device *phydev); 1782 1782 int __phy_resume(struct phy_device *phydev); 1783 1783 int phy_loopback(struct phy_device *phydev, bool enable); 1784 + int phy_sfp_connect_phy(void *upstream, struct phy_device *phy); 1785 + void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy); 1784 1786 void phy_sfp_attach(void *upstream, struct sfp_bus *bus); 1785 1787 void phy_sfp_detach(void *upstream, struct sfp_bus *bus); 1786 1788 int phy_sfp_probe(struct phy_device *phydev,