]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: phy: add helpers to handle sfp phy connect/disconnect
authorMaxime Chevallier <maxime.chevallier@bootlin.com>
Thu, 21 Dec 2023 18:00:36 +0000 (19:00 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 1 Jan 2024 18:38:56 +0000 (18:38 +0000)
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/at803x.c
drivers/net/phy/marvell-88x2222.c
drivers/net/phy/marvell.c
drivers/net/phy/marvell10g.c
drivers/net/phy/phy_device.c
include/linux/phy.h

index 19cfbf36fe80445cb59f2cc1f9421211e32217c9..aaf6c654aaede6fb6bcd045e5bee0cd4ae3e3a04 100644 (file)
@@ -1452,6 +1452,8 @@ static const struct sfp_upstream_ops at8031_sfp_ops = {
        .attach = phy_sfp_attach,
        .detach = phy_sfp_detach,
        .module_insert = at8031_sfp_insert,
+       .connect_phy = phy_sfp_connect_phy,
+       .disconnect_phy = phy_sfp_disconnect_phy,
 };
 
 static int at8031_parse_dt(struct phy_device *phydev)
index e3aa30dad2e63843dfa17e67103e4bf8dc2bb6cf..3f77bbc7e04f1a84e82e5073d35976472351f1a1 100644 (file)
@@ -555,6 +555,8 @@ static const struct sfp_upstream_ops sfp_phy_ops = {
        .link_down = mv2222_sfp_link_down,
        .attach = phy_sfp_attach,
        .detach = phy_sfp_detach,
+       .connect_phy = phy_sfp_connect_phy,
+       .disconnect_phy = phy_sfp_disconnect_phy,
 };
 
 static int mv2222_probe(struct phy_device *phydev)
index eba652a4c1d8873ed758f267e20ea34a0880552c..674e29bce2ccb89ed1ae3e7c9b17bd48ca8fe188 100644 (file)
@@ -3254,6 +3254,8 @@ static const struct sfp_upstream_ops m88e1510_sfp_ops = {
        .module_remove = m88e1510_sfp_remove,
        .attach = phy_sfp_attach,
        .detach = phy_sfp_detach,
+       .connect_phy = phy_sfp_connect_phy,
+       .disconnect_phy = phy_sfp_disconnect_phy,
 };
 
 static int m88e1510_probe(struct phy_device *phydev)
index ad43e280930c35eaef7454813143c1a2eb8a0fae..6642eb642d4bdd3880ddd7fdbc3471bc2c78e5ea 100644 (file)
@@ -503,6 +503,8 @@ static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
 static const struct sfp_upstream_ops mv3310_sfp_ops = {
        .attach = phy_sfp_attach,
        .detach = phy_sfp_detach,
+       .connect_phy = phy_sfp_connect_phy,
+       .disconnect_phy = phy_sfp_disconnect_phy,
        .module_insert = mv3310_sfp_insert,
 };
 
index 711629c49c11336438ab9dd5ed310525e8bcbc9d..1e595762afea28e37fcc31b89726b5fbdb838a86 100644 (file)
@@ -1363,6 +1363,46 @@ phy_standalone_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RO(phy_standalone);
 
+/**
+ * phy_sfp_connect_phy - Connect the SFP module's PHY to the upstream PHY
+ * @upstream: pointer to the upstream phy device
+ * @phy: pointer to the SFP module's phy device
+ *
+ * This helper allows keeping track of PHY devices on the link. It adds the
+ * SFP module's phy to the phy namespace of the upstream phy
+ */
+int phy_sfp_connect_phy(void *upstream, struct phy_device *phy)
+{
+       struct phy_device *phydev = upstream;
+       struct phy_link_topology *topo = phy_get_link_topology(phydev);
+
+       if (topo)
+               return phy_link_topo_add_phy(topo, phy, PHY_UPSTREAM_PHY, phydev);
+
+       return 0;
+}
+EXPORT_SYMBOL(phy_sfp_connect_phy);
+
+/**
+ * phy_sfp_disconnect_phy - Disconnect the SFP module's PHY from the upstream PHY
+ * @upstream: pointer to the upstream phy device
+ * @phy: pointer to the SFP module's phy device
+ *
+ * This helper allows keeping track of PHY devices on the link. It removes the
+ * SFP module's phy to the phy namespace of the upstream phy. As the module phy
+ * will be destroyed, re-inserting the same module will add a new phy with a
+ * new index.
+ */
+void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy)
+{
+       struct phy_device *phydev = upstream;
+       struct phy_link_topology *topo = phy_get_link_topology(phydev);
+
+       if (topo)
+               phy_link_topo_del_phy(topo, phy);
+}
+EXPORT_SYMBOL(phy_sfp_disconnect_phy);
+
 /**
  * phy_sfp_attach - attach the SFP bus to the PHY upstream network device
  * @upstream: pointer to the phy device
index ea9416797b89c98dfb36e771d629591540465b3b..ac22b8e28a853af5c3b0f8b40f450089472ce65b 100644 (file)
@@ -1729,6 +1729,8 @@ int phy_suspend(struct phy_device *phydev);
 int phy_resume(struct phy_device *phydev);
 int __phy_resume(struct phy_device *phydev);
 int phy_loopback(struct phy_device *phydev, bool enable);
+int phy_sfp_connect_phy(void *upstream, struct phy_device *phy);
+void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy);
 void phy_sfp_attach(void *upstream, struct sfp_bus *bus);
 void phy_sfp_detach(void *upstream, struct sfp_bus *bus);
 int phy_sfp_probe(struct phy_device *phydev,