1  /* SPDX-License-Identifier: GPL-2.0 */
2  /*
3   * PHY device list allow maintaining a list of PHY devices that are
4   * part of a netdevice's link topology. PHYs can for example be chained,
5   * as is the case when using a PHY that exposes an SFP module, on which an
6   * SFP transceiver that embeds a PHY is connected.
7   *
8   * This list can then be used by userspace to leverage individual PHY
9   * capabilities.
10   */
11  #ifndef __PHY_LINK_TOPOLOGY_H
12  #define __PHY_LINK_TOPOLOGY_H
13  
14  #include <linux/ethtool.h>
15  #include <linux/netdevice.h>
16  
17  struct xarray;
18  struct phy_device;
19  struct sfp_bus;
20  
21  struct phy_link_topology {
22  	struct xarray phys;
23  	u32 next_phy_index;
24  };
25  
26  struct phy_device_node {
27  	enum phy_upstream upstream_type;
28  
29  	union {
30  		struct net_device	*netdev;
31  		struct phy_device	*phydev;
32  	} upstream;
33  
34  	struct sfp_bus *parent_sfp_bus;
35  
36  	struct phy_device *phy;
37  };
38  
39  #if IS_ENABLED(CONFIG_PHYLIB)
40  int phy_link_topo_add_phy(struct net_device *dev,
41  			  struct phy_device *phy,
42  			  enum phy_upstream upt, void *upstream);
43  
44  void phy_link_topo_del_phy(struct net_device *dev, struct phy_device *phy);
45  
46  static inline struct phy_device *
phy_link_topo_get_phy(struct net_device * dev,u32 phyindex)47  phy_link_topo_get_phy(struct net_device *dev, u32 phyindex)
48  {
49  	struct phy_link_topology *topo = dev->link_topo;
50  	struct phy_device_node *pdn;
51  
52  	if (!topo)
53  		return NULL;
54  
55  	pdn = xa_load(&topo->phys, phyindex);
56  	if (pdn)
57  		return pdn->phy;
58  
59  	return NULL;
60  }
61  
62  #else
phy_link_topo_add_phy(struct net_device * dev,struct phy_device * phy,enum phy_upstream upt,void * upstream)63  static inline int phy_link_topo_add_phy(struct net_device *dev,
64  					struct phy_device *phy,
65  					enum phy_upstream upt, void *upstream)
66  {
67  	return 0;
68  }
69  
phy_link_topo_del_phy(struct net_device * dev,struct phy_device * phy)70  static inline void phy_link_topo_del_phy(struct net_device *dev,
71  					 struct phy_device *phy)
72  {
73  }
74  
75  static inline struct phy_device *
phy_link_topo_get_phy(struct net_device * dev,u32 phyindex)76  phy_link_topo_get_phy(struct net_device *dev, u32 phyindex)
77  {
78  	return NULL;
79  }
80  #endif
81  
82  #endif /* __PHY_LINK_TOPOLOGY_H */
83