.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)
 
        .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)
 
 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,
 };
 
 
 
 static struct phy_driver genphy_driver;
 
+static struct phy_link_topology *phy_get_link_topology(struct phy_device *phydev)
+{
+       if (phydev->attached_dev)
+               return phydev->attached_dev->link_topo;
+
+       return NULL;
+}
+
 static LIST_HEAD(phy_fixup_list);
 static DEFINE_MUTEX(phy_fixup_lock);
 
 }
 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
 
        .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)
 
        .detach = phy_sfp_detach,
        .module_insert = qca807x_sfp_insert,
        .module_remove = qca807x_sfp_remove,
+       .connect_phy = phy_sfp_connect_phy,
+       .disconnect_phy = phy_sfp_disconnect_phy,
 };
 
 static int qca807x_probe(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,