1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Infrastructure to handle all PHY devices connected to a given netdev, 4 * either directly or indirectly attached. 5 * 6 * Copyright (c) 2023 Maxime Chevallier<maxime.chevallier@bootlin.com> 7 */ 8 9 #include <linux/phy_link_topology.h> 10 #include <linux/phy_port.h> 11 #include <linux/phy.h> 12 #include <linux/rtnetlink.h> 13 #include <linux/xarray.h> 14 #include <net/netdev_lock.h> 15 16 static int netdev_alloc_phy_link_topology(struct net_device *dev) 17 { 18 struct phy_link_topology *topo; 19 20 topo = kzalloc_obj(*topo); 21 if (!topo) 22 return -ENOMEM; 23 24 xa_init_flags(&topo->phys, XA_FLAGS_ALLOC1); 25 topo->next_phy_index = 1; 26 27 xa_init_flags(&topo->ports, XA_FLAGS_ALLOC1); 28 topo->next_port_index = 1; 29 30 dev->link_topo = topo; 31 32 return 0; 33 } 34 35 static struct phy_link_topology *phy_link_topo_get_or_alloc(struct net_device *dev) 36 { 37 int ret; 38 39 if (dev->link_topo) 40 return dev->link_topo; 41 42 /* The topology is allocated the first time we add an object to it. 43 * It is freed alongside the netdev. It can be called on multiple 44 * contexts: 45 * - It can be called from .probe() : No rtnl, no netdev_lock 46 * - .ndo_open() : rtnl and possibly netdev_lock 47 * - SFP state machine : rtnl held or not 48 * 49 * However, we can't really have races : 50 * - If we have a PHY, phy_link_topo_add_phy() will always run first 51 * and trigger the alloc. Only then the ports can be added through 52 * phylib or sfp. 53 * - If we don't, the SFP port for the cage is registered first, and 54 * only then other ports/PHYs can be registered. 55 */ 56 ret = netdev_alloc_phy_link_topology(dev); 57 if (ret) 58 return ERR_PTR(ret); 59 60 return dev->link_topo; 61 } 62 63 int phy_link_topo_add_port(struct net_device *dev, struct phy_port *port) 64 { 65 struct phy_link_topology *topo; 66 int ret; 67 68 /* Ports can now be queried without rtnl for ops-locked devices, which 69 * we don't support now as port retrieval is done under rtnl. 70 * We don't have phy_port enabled devices yet, let's make sure 71 * we are loudly warned about that when it happens. 72 */ 73 if (WARN_ON_ONCE(dev->netdev_ops && netdev_need_ops_lock(dev))) 74 return -EOPNOTSUPP; 75 76 topo = phy_link_topo_get_or_alloc(dev); 77 if (IS_ERR(topo)) 78 return PTR_ERR(topo); 79 80 /* Attempt to re-use a previously allocated port_id */ 81 if (port->id) 82 ret = xa_insert(&topo->ports, port->id, port, GFP_KERNEL); 83 else 84 ret = xa_alloc_cyclic(&topo->ports, &port->id, port, 85 xa_limit_32b, &topo->next_port_index, 86 GFP_KERNEL); 87 88 return ret < 0 ? ret : 0; 89 } 90 EXPORT_SYMBOL_GPL(phy_link_topo_add_port); 91 92 void phy_link_topo_del_port(struct net_device *dev, struct phy_port *port) 93 { 94 struct phy_link_topology *topo = dev->link_topo; 95 96 if (!topo) 97 return; 98 99 xa_erase(&topo->ports, port->id); 100 } 101 EXPORT_SYMBOL_GPL(phy_link_topo_del_port); 102 103 int phy_link_topo_add_phy(struct net_device *dev, 104 struct phy_device *phy, 105 enum phy_upstream upt, void *upstream) 106 { 107 struct phy_link_topology *topo; 108 struct phy_device_node *pdn; 109 struct phy_port *port; 110 int ret; 111 112 /* ethtool ops may run without rtnl_lock, and rtnl_lock is what 113 * currently protects the PHY topology. No driver currently mixes 114 * the two, flag if someone tries. See also: 115 * - ethnl_req_get_phydev() 116 * - phy_detach() 117 */ 118 if (WARN_ON_ONCE(netdev_need_ops_lock(dev))) 119 return -EOPNOTSUPP; 120 121 topo = phy_link_topo_get_or_alloc(dev); 122 if (IS_ERR(topo)) 123 return PTR_ERR(topo); 124 125 pdn = kzalloc_obj(*pdn); 126 if (!pdn) 127 return -ENOMEM; 128 129 pdn->phy = phy; 130 switch (upt) { 131 case PHY_UPSTREAM_MAC: 132 pdn->upstream.netdev = (struct net_device *)upstream; 133 if (phy_on_sfp(phy)) 134 pdn->parent_sfp_bus = pdn->upstream.netdev->sfp_bus; 135 break; 136 case PHY_UPSTREAM_PHY: 137 pdn->upstream.phydev = (struct phy_device *)upstream; 138 if (phy_on_sfp(phy)) 139 pdn->parent_sfp_bus = pdn->upstream.phydev->sfp_bus; 140 break; 141 default: 142 ret = -EINVAL; 143 goto err; 144 } 145 pdn->upstream_type = upt; 146 147 /* Attempt to re-use a previously allocated phy_index */ 148 if (phy->phyindex) 149 ret = xa_insert(&topo->phys, phy->phyindex, pdn, GFP_KERNEL); 150 else 151 ret = xa_alloc_cyclic(&topo->phys, &phy->phyindex, pdn, 152 xa_limit_32b, &topo->next_phy_index, 153 GFP_KERNEL); 154 155 if (ret < 0) 156 goto err; 157 158 /* Add all the PHY's ports to the topology */ 159 list_for_each_entry(port, &phy->ports, head) { 160 ret = phy_link_topo_add_port(dev, port); 161 if (ret) 162 goto del_ports; 163 } 164 165 return 0; 166 167 del_ports: 168 list_for_each_entry_continue_reverse(port, &phy->ports, head) 169 phy_link_topo_del_port(dev, port); 170 171 xa_erase(&topo->phys, phy->phyindex); 172 err: 173 kfree(pdn); 174 return ret; 175 } 176 EXPORT_SYMBOL_GPL(phy_link_topo_add_phy); 177 178 void phy_link_topo_del_phy(struct net_device *dev, 179 struct phy_device *phy) 180 { 181 struct phy_link_topology *topo = dev->link_topo; 182 struct phy_device_node *pdn; 183 struct phy_port *port; 184 185 if (!topo) 186 return; 187 188 list_for_each_entry(port, &phy->ports, head) 189 phy_link_topo_del_port(dev, port); 190 191 pdn = xa_erase(&topo->phys, phy->phyindex); 192 193 /* We delete the PHY from the topology, however we don't re-set the 194 * phy->phyindex field. If the PHY isn't gone, we can re-assign it the 195 * same index next time it's added back to the topology 196 */ 197 198 kfree(pdn); 199 } 200 EXPORT_SYMBOL_GPL(phy_link_topo_del_phy); 201