In order to allow netlink access to phy_ports, let's add a helper to
retrieve them. When handling a port coming from phy_link_topology, the
caller must hold rtnl until it's done with it.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
drivers/net/phy/phy_link_topology.c | 8 ++++++++
include/linux/phy_link_topology.h | 26 ++++++++++++++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/drivers/net/phy/phy_link_topology.c b/drivers/net/phy/phy_link_topology.c
index 5e135ab636c0..6710a199967a 100644
--- a/drivers/net/phy/phy_link_topology.c
+++ b/drivers/net/phy/phy_link_topology.c
@@ -65,6 +65,14 @@ int phy_link_topo_add_port(struct net_device *dev, struct phy_port *port)
struct phy_link_topology *topo;
int ret;
+ /* Ports can now be queried without rtnl for ops-locked devices, which
+ * we don't support now as port retrieval is done under rtnl.
+ * We don't have phy_port enabled devices yet, let's make sure
+ * we are loudly warned about that when it happens.
+ */
+ if (WARN_ON_ONCE(netdev_need_ops_lock(dev)))
+ return -EOPNOTSUPP;
+
topo = phy_link_topo_get_or_alloc(dev);
if (IS_ERR(topo))
return PTR_ERR(topo);
diff --git a/include/linux/phy_link_topology.h b/include/linux/phy_link_topology.h
index 296ee514ba46..9585282cae3f 100644
--- a/include/linux/phy_link_topology.h
+++ b/include/linux/phy_link_topology.h
@@ -13,6 +13,7 @@
#include <linux/ethtool.h>
#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
struct xarray;
struct phy_device;
@@ -71,6 +72,25 @@ phy_link_topo_get_phy(struct net_device *dev, u32 phyindex)
return NULL;
}
+static inline struct phy_port *
+phy_link_topo_get_port(struct net_device *dev, u32 port_id)
+{
+ struct phy_link_topology *topo = dev->link_topo;
+
+ if (!topo)
+ return NULL;
+
+ /* ports in the topo are RTNL protected, but may be accessed under
+ * netdev_lock for ops-locked devices. For now keep them under rtnl
+ * protection, as no ops-locked devices have phy_port capabilities
+ * yet.
+ */
+ ASSERT_RTNL();
+
+ /* Caller must hold RTNL while handling the phy_port */
+ return xa_load(&topo->ports, port_id);
+}
+
#else
static inline int phy_link_topo_add_phy(struct net_device *dev,
struct phy_device *phy,@@ -100,6 +120,12 @@ phy_link_topo_get_phy(struct net_device *dev, u32 phyindex)
{
return NULL;
}
+
+static inline struct phy_port *
+phy_link_topo_get_port(struct net_device *dev, u32 port_id)
+{
+ return NULL;
+}
#endif
#endif /* __PHY_LINK_TOPOLOGY_H */--
2.55.0