Commit | Line | Data |
---|---|---|
a2443fd1 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2f53e904 | 2 | /* Framework for configuring and reading PHY devices |
00db8189 AF |
3 | * Based on code in sungem_phy.c and gianfar_phy.c |
4 | * | |
5 | * Author: Andy Fleming | |
6 | * | |
7 | * Copyright (c) 2004 Freescale Semiconductor, Inc. | |
0ac49527 | 8 | * Copyright (c) 2006, 2007 Maciej W. Rozycki |
00db8189 | 9 | */ |
8d242488 | 10 | |
00db8189 | 11 | #include <linux/kernel.h> |
00db8189 AF |
12 | #include <linux/string.h> |
13 | #include <linux/errno.h> | |
14 | #include <linux/unistd.h> | |
00db8189 | 15 | #include <linux/interrupt.h> |
00db8189 AF |
16 | #include <linux/delay.h> |
17 | #include <linux/netdevice.h> | |
a68a8138 | 18 | #include <linux/netlink.h> |
00db8189 AF |
19 | #include <linux/etherdevice.h> |
20 | #include <linux/skbuff.h> | |
00db8189 AF |
21 | #include <linux/mm.h> |
22 | #include <linux/module.h> | |
00db8189 AF |
23 | #include <linux/mii.h> |
24 | #include <linux/ethtool.h> | |
1dd3f212 | 25 | #include <linux/ethtool_netlink.h> |
00db8189 | 26 | #include <linux/phy.h> |
d6f8cfa3 | 27 | #include <linux/phy_led_triggers.h> |
298e54fa | 28 | #include <linux/sfp.h> |
3c3070d7 | 29 | #include <linux/workqueue.h> |
a59a4d19 | 30 | #include <linux/mdio.h> |
2f53e904 SS |
31 | #include <linux/io.h> |
32 | #include <linux/uaccess.h> | |
60063497 | 33 | #include <linux/atomic.h> |
1758bde2 | 34 | #include <linux/suspend.h> |
1dd3f212 AL |
35 | #include <net/netlink.h> |
36 | #include <net/genetlink.h> | |
37 | #include <net/sock.h> | |
2f53e904 | 38 | |
a3e51d47 | 39 | #include "phylib-internal.h" |
8c8c4a87 | 40 | #include "phy-caps.h" |
a3e51d47 | 41 | |
97b33bdf HK |
42 | #define PHY_STATE_TIME HZ |
43 | ||
3e2186e0 FF |
44 | #define PHY_STATE_STR(_state) \ |
45 | case PHY_##_state: \ | |
46 | return __stringify(_state); \ | |
47 | ||
48 | static const char *phy_state_to_str(enum phy_state st) | |
49 | { | |
50 | switch (st) { | |
51 | PHY_STATE_STR(DOWN) | |
3e2186e0 | 52 | PHY_STATE_STR(READY) |
3e2186e0 | 53 | PHY_STATE_STR(UP) |
3e2186e0 FF |
54 | PHY_STATE_STR(RUNNING) |
55 | PHY_STATE_STR(NOLINK) | |
a68a8138 | 56 | PHY_STATE_STR(CABLETEST) |
3e2186e0 | 57 | PHY_STATE_STR(HALTED) |
59088b5a | 58 | PHY_STATE_STR(ERROR) |
3e2186e0 FF |
59 | } |
60 | ||
61 | return NULL; | |
62 | } | |
63 | ||
4203d840 FF |
64 | static void phy_process_state_change(struct phy_device *phydev, |
65 | enum phy_state old_state) | |
66 | { | |
67 | if (old_state != phydev->state) { | |
68 | phydev_dbg(phydev, "PHY state change %s -> %s\n", | |
69 | phy_state_to_str(old_state), | |
70 | phy_state_to_str(phydev->state)); | |
71 | if (phydev->drv && phydev->drv->link_change_notify) | |
72 | phydev->drv->link_change_notify(phydev); | |
73 | } | |
74 | } | |
75 | ||
74a992b3 HK |
76 | static void phy_link_up(struct phy_device *phydev) |
77 | { | |
a307593a | 78 | phydev->phy_link_change(phydev, true); |
74a992b3 HK |
79 | phy_led_trigger_change_speed(phydev); |
80 | } | |
81 | ||
a307593a | 82 | static void phy_link_down(struct phy_device *phydev) |
74a992b3 | 83 | { |
a307593a | 84 | phydev->phy_link_change(phydev, false); |
74a992b3 | 85 | phy_led_trigger_change_speed(phydev); |
9a0f830f | 86 | WRITE_ONCE(phydev->link_down_events, phydev->link_down_events + 1); |
74a992b3 | 87 | } |
3e2186e0 | 88 | |
23bfaa59 HK |
89 | static const char *phy_pause_str(struct phy_device *phydev) |
90 | { | |
91 | bool local_pause, local_asym_pause; | |
92 | ||
93 | if (phydev->autoneg == AUTONEG_DISABLE) | |
94 | goto no_pause; | |
95 | ||
96 | local_pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, | |
97 | phydev->advertising); | |
98 | local_asym_pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, | |
99 | phydev->advertising); | |
100 | ||
101 | if (local_pause && phydev->pause) | |
102 | return "rx/tx"; | |
103 | ||
104 | if (local_asym_pause && phydev->asym_pause) { | |
105 | if (local_pause) | |
106 | return "rx"; | |
107 | if (phydev->pause) | |
108 | return "tx"; | |
109 | } | |
110 | ||
111 | no_pause: | |
112 | return "off"; | |
113 | } | |
114 | ||
b3df0da8 RD |
115 | /** |
116 | * phy_print_status - Convenience function to print out the current phy status | |
117 | * @phydev: the phy_device struct | |
e1393456 AF |
118 | */ |
119 | void phy_print_status(struct phy_device *phydev) | |
120 | { | |
2f53e904 | 121 | if (phydev->link) { |
df40cc88 | 122 | netdev_info(phydev->attached_dev, |
5eee3bb7 | 123 | "Link is Up - %s/%s %s- flow control %s\n", |
766d1d38 | 124 | phy_speed_to_str(phydev->speed), |
da4625ac | 125 | phy_duplex_to_str(phydev->duplex), |
5eee3bb7 | 126 | phydev->downshifted_rate ? "(downshifted) " : "", |
23bfaa59 | 127 | phy_pause_str(phydev)); |
2f53e904 | 128 | } else { |
43b6329f | 129 | netdev_info(phydev->attached_dev, "Link is Down\n"); |
2f53e904 | 130 | } |
e1393456 AF |
131 | } |
132 | EXPORT_SYMBOL(phy_print_status); | |
00db8189 | 133 | |
0c3e10cb SA |
134 | /** |
135 | * phy_get_rate_matching - determine if rate matching is supported | |
136 | * @phydev: The phy device to return rate matching for | |
137 | * @iface: The interface mode to use | |
138 | * | |
139 | * This determines the type of rate matching (if any) that @phy supports | |
140 | * using @iface. @iface may be %PHY_INTERFACE_MODE_NA to determine if any | |
141 | * interface supports rate matching. | |
142 | * | |
143 | * Return: The type of rate matching @phy supports for @iface, or | |
144 | * %RATE_MATCH_NONE. | |
145 | */ | |
146 | int phy_get_rate_matching(struct phy_device *phydev, | |
147 | phy_interface_t iface) | |
148 | { | |
149 | int ret = RATE_MATCH_NONE; | |
150 | ||
151 | if (phydev->drv->get_rate_matching) { | |
152 | mutex_lock(&phydev->lock); | |
153 | ret = phydev->drv->get_rate_matching(phydev, iface); | |
154 | mutex_unlock(&phydev->lock); | |
155 | } | |
156 | ||
157 | return ret; | |
158 | } | |
159 | EXPORT_SYMBOL_GPL(phy_get_rate_matching); | |
160 | ||
b3df0da8 RD |
161 | /** |
162 | * phy_config_interrupt - configure the PHY device for the requested interrupts | |
163 | * @phydev: the phy_device struct | |
164 | * @interrupts: interrupt flags to configure for this @phydev | |
165 | * | |
ad033506 | 166 | * Returns 0 on success or < 0 on error. |
b3df0da8 | 167 | */ |
695bce8f | 168 | static int phy_config_interrupt(struct phy_device *phydev, bool interrupts) |
00db8189 | 169 | { |
695bce8f | 170 | phydev->interrupts = interrupts ? 1 : 0; |
00db8189 | 171 | if (phydev->drv->config_intr) |
e62a768f | 172 | return phydev->drv->config_intr(phydev); |
00db8189 | 173 | |
e62a768f | 174 | return 0; |
00db8189 AF |
175 | } |
176 | ||
002ba705 RK |
177 | /** |
178 | * phy_restart_aneg - restart auto-negotiation | |
179 | * @phydev: target phy_device struct | |
180 | * | |
181 | * Restart the autonegotiation on @phydev. Returns >= 0 on success or | |
182 | * negative errno on error. | |
183 | */ | |
184 | int phy_restart_aneg(struct phy_device *phydev) | |
185 | { | |
186 | int ret; | |
187 | ||
188 | if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0))) | |
189 | ret = genphy_c45_restart_aneg(phydev); | |
190 | else | |
191 | ret = genphy_restart_aneg(phydev); | |
192 | ||
193 | return ret; | |
194 | } | |
195 | EXPORT_SYMBOL_GPL(phy_restart_aneg); | |
00db8189 | 196 | |
b3df0da8 RD |
197 | /** |
198 | * phy_aneg_done - return auto-negotiation status | |
199 | * @phydev: target phy_device struct | |
00db8189 | 200 | * |
76a423a3 FF |
201 | * Description: Return the auto-negotiation status from this @phydev |
202 | * Returns > 0 on success or < 0 on error. 0 means that auto-negotiation | |
203 | * is still pending. | |
00db8189 | 204 | */ |
372788f9 | 205 | int phy_aneg_done(struct phy_device *phydev) |
00db8189 | 206 | { |
65f2767a | 207 | if (phydev->drv && phydev->drv->aneg_done) |
76a423a3 | 208 | return phydev->drv->aneg_done(phydev); |
d7bed825 HK |
209 | else if (phydev->is_c45) |
210 | return genphy_c45_aneg_done(phydev); | |
211 | else | |
212 | return genphy_aneg_done(phydev); | |
00db8189 | 213 | } |
372788f9 | 214 | EXPORT_SYMBOL(phy_aneg_done); |
00db8189 | 215 | |
1f9127ca ZB |
216 | /** |
217 | * phy_supported_speeds - return all speeds currently supported by a phy device | |
218 | * @phy: The phy device to return supported speeds of. | |
219 | * @speeds: buffer to store supported speeds in. | |
220 | * @size: size of speeds buffer. | |
221 | * | |
222 | * Description: Returns the number of supported speeds, and fills the speeds | |
223 | * buffer with the supported speeds. If speeds buffer is too small to contain | |
224 | * all currently supported speeds, will return as many speeds as can fit. | |
225 | */ | |
226 | unsigned int phy_supported_speeds(struct phy_device *phy, | |
227 | unsigned int *speeds, | |
228 | unsigned int size) | |
229 | { | |
8c8c4a87 | 230 | return phy_caps_speeds(speeds, size, phy->supported); |
1f9127ca ZB |
231 | } |
232 | ||
54da5a8b GR |
233 | /** |
234 | * phy_check_valid - check if there is a valid PHY setting which matches | |
235 | * speed, duplex, and feature mask | |
236 | * @speed: speed to match | |
237 | * @duplex: duplex to match | |
238 | * @features: A mask of the valid settings | |
239 | * | |
240 | * Description: Returns true if there is a valid setting, false otherwise. | |
241 | */ | |
cf9f6079 | 242 | bool phy_check_valid(int speed, int duplex, unsigned long *features) |
54da5a8b | 243 | { |
87b22ce3 | 244 | return phy_caps_valid(speed, duplex, features); |
54da5a8b | 245 | } |
cf9f6079 | 246 | EXPORT_SYMBOL(phy_check_valid); |
54da5a8b | 247 | |
b3df0da8 RD |
248 | /** |
249 | * phy_sanitize_settings - make sure the PHY is set to supported speed and duplex | |
250 | * @phydev: the target phy_device struct | |
00db8189 | 251 | * |
b3df0da8 | 252 | * Description: Make sure the PHY is set to supported speeds and |
00db8189 | 253 | * duplexes. Drop down by one in this order: 1000/FULL, |
b3df0da8 | 254 | * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF. |
00db8189 | 255 | */ |
89ff05ec | 256 | static void phy_sanitize_settings(struct phy_device *phydev) |
00db8189 | 257 | { |
fc81e257 MC |
258 | const struct link_capabilities *c; |
259 | ||
260 | c = phy_caps_lookup(phydev->speed, phydev->duplex, phydev->supported, | |
261 | false); | |
00db8189 | 262 | |
fc81e257 MC |
263 | if (c) { |
264 | phydev->speed = c->speed; | |
265 | phydev->duplex = c->duplex; | |
d0613037 RK |
266 | } else { |
267 | /* We failed to find anything (no supported speeds?) */ | |
268 | phydev->speed = SPEED_UNKNOWN; | |
269 | phydev->duplex = DUPLEX_UNKNOWN; | |
270 | } | |
00db8189 | 271 | } |
00db8189 | 272 | |
5514174f | 273 | void phy_ethtool_ksettings_get(struct phy_device *phydev, |
274 | struct ethtool_link_ksettings *cmd) | |
2d55173e | 275 | { |
c10a485c | 276 | mutex_lock(&phydev->lock); |
3c1bcc86 AL |
277 | linkmode_copy(cmd->link_modes.supported, phydev->supported); |
278 | linkmode_copy(cmd->link_modes.advertising, phydev->advertising); | |
c0ec3c27 | 279 | linkmode_copy(cmd->link_modes.lp_advertising, phydev->lp_advertising); |
2d55173e PR |
280 | |
281 | cmd->base.speed = phydev->speed; | |
282 | cmd->base.duplex = phydev->duplex; | |
bdbdac76 OR |
283 | cmd->base.master_slave_cfg = phydev->master_slave_get; |
284 | cmd->base.master_slave_state = phydev->master_slave_state; | |
0c3e10cb | 285 | cmd->base.rate_matching = phydev->rate_matching; |
2d55173e PR |
286 | if (phydev->interface == PHY_INTERFACE_MODE_MOCA) |
287 | cmd->base.port = PORT_BNC; | |
288 | else | |
4217a64e | 289 | cmd->base.port = phydev->port; |
6b2edfba | 290 | cmd->base.transceiver = phydev->is_internal ? |
ceb62813 | 291 | XCVR_INTERNAL : XCVR_EXTERNAL; |
2d55173e PR |
292 | cmd->base.phy_address = phydev->mdio.addr; |
293 | cmd->base.autoneg = phydev->autoneg; | |
1004ee61 RL |
294 | cmd->base.eth_tp_mdix_ctrl = phydev->mdix_ctrl; |
295 | cmd->base.eth_tp_mdix = phydev->mdix; | |
c10a485c | 296 | mutex_unlock(&phydev->lock); |
2d55173e PR |
297 | } |
298 | EXPORT_SYMBOL(phy_ethtool_ksettings_get); | |
00db8189 | 299 | |
b3df0da8 RD |
300 | /** |
301 | * phy_mii_ioctl - generic PHY MII ioctl interface | |
302 | * @phydev: the phy_device struct | |
00c7d920 | 303 | * @ifr: &struct ifreq for socket ioctl's |
b3df0da8 RD |
304 | * @cmd: ioctl cmd to execute |
305 | * | |
306 | * Note that this function is currently incompatible with the | |
00db8189 | 307 | * PHYCONTROL layer. It changes registers without regard to |
b3df0da8 | 308 | * current state. Use at own risk. |
00db8189 | 309 | */ |
2f53e904 | 310 | int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd) |
00db8189 | 311 | { |
28b04113 | 312 | struct mii_ioctl_data *mii_data = if_mii(ifr); |
446e2305 KM |
313 | struct kernel_hwtstamp_config kernel_cfg; |
314 | struct netlink_ext_ack extack = {}; | |
00db8189 | 315 | u16 val = mii_data->val_in; |
79ce0477 | 316 | bool change_autoneg = false; |
446e2305 | 317 | struct hwtstamp_config cfg; |
cdea04c2 | 318 | int prtad, devad; |
446e2305 | 319 | int ret; |
00db8189 AF |
320 | |
321 | switch (cmd) { | |
322 | case SIOCGMIIPHY: | |
e5a03bfd | 323 | mii_data->phy_id = phydev->mdio.addr; |
df561f66 | 324 | fallthrough; |
c6d6a511 | 325 | |
00db8189 | 326 | case SIOCGMIIREG: |
cdea04c2 RK |
327 | if (mdio_phy_id_is_c45(mii_data->phy_id)) { |
328 | prtad = mdio_phy_id_prtad(mii_data->phy_id); | |
329 | devad = mdio_phy_id_devad(mii_data->phy_id); | |
569bf6d4 NS |
330 | ret = mdiobus_c45_read(phydev->mdio.bus, prtad, devad, |
331 | mii_data->reg_num); | |
332 | ||
cdea04c2 | 333 | } else { |
569bf6d4 NS |
334 | ret = mdiobus_read(phydev->mdio.bus, mii_data->phy_id, |
335 | mii_data->reg_num); | |
cdea04c2 | 336 | } |
569bf6d4 NS |
337 | |
338 | if (ret < 0) | |
339 | return ret; | |
340 | ||
341 | mii_data->val_out = ret; | |
342 | ||
e62a768f | 343 | return 0; |
00db8189 AF |
344 | |
345 | case SIOCSMIIREG: | |
cdea04c2 RK |
346 | if (mdio_phy_id_is_c45(mii_data->phy_id)) { |
347 | prtad = mdio_phy_id_prtad(mii_data->phy_id); | |
348 | devad = mdio_phy_id_devad(mii_data->phy_id); | |
cdea04c2 RK |
349 | } else { |
350 | prtad = mii_data->phy_id; | |
351 | devad = mii_data->reg_num; | |
352 | } | |
353 | if (prtad == phydev->mdio.addr) { | |
354 | switch (devad) { | |
00db8189 | 355 | case MII_BMCR: |
79ce0477 BH |
356 | if ((val & (BMCR_RESET | BMCR_ANENABLE)) == 0) { |
357 | if (phydev->autoneg == AUTONEG_ENABLE) | |
358 | change_autoneg = true; | |
00db8189 | 359 | phydev->autoneg = AUTONEG_DISABLE; |
79ce0477 BH |
360 | if (val & BMCR_FULLDPLX) |
361 | phydev->duplex = DUPLEX_FULL; | |
362 | else | |
363 | phydev->duplex = DUPLEX_HALF; | |
364 | if (val & BMCR_SPEED1000) | |
365 | phydev->speed = SPEED_1000; | |
366 | else if (val & BMCR_SPEED100) | |
367 | phydev->speed = SPEED_100; | |
368 | else phydev->speed = SPEED_10; | |
169d7a40 | 369 | } else { |
79ce0477 BH |
370 | if (phydev->autoneg == AUTONEG_DISABLE) |
371 | change_autoneg = true; | |
00db8189 | 372 | phydev->autoneg = AUTONEG_ENABLE; |
79ce0477 | 373 | } |
00db8189 AF |
374 | break; |
375 | case MII_ADVERTISE: | |
9db299c7 AL |
376 | mii_adv_mod_linkmode_adv_t(phydev->advertising, |
377 | val); | |
79ce0477 | 378 | change_autoneg = true; |
00db8189 | 379 | break; |
4cf6c57e RK |
380 | case MII_CTRL1000: |
381 | mii_ctrl1000_mod_linkmode_adv_t(phydev->advertising, | |
382 | val); | |
383 | change_autoneg = true; | |
384 | break; | |
00db8189 AF |
385 | default: |
386 | /* do nothing */ | |
387 | break; | |
388 | } | |
389 | } | |
390 | ||
260bdfea AL |
391 | if (mdio_phy_id_is_c45(mii_data->phy_id)) |
392 | mdiobus_c45_write(phydev->mdio.bus, prtad, devad, | |
393 | mii_data->reg_num, val); | |
394 | else | |
395 | mdiobus_write(phydev->mdio.bus, prtad, devad, val); | |
af1dc13e | 396 | |
cdea04c2 RK |
397 | if (prtad == phydev->mdio.addr && |
398 | devad == MII_BMCR && | |
2613f95f | 399 | val & BMCR_RESET) |
e62a768f | 400 | return phy_init_hw(phydev); |
79ce0477 BH |
401 | |
402 | if (change_autoneg) | |
403 | return phy_start_aneg(phydev); | |
404 | ||
e62a768f | 405 | return 0; |
dda93b48 | 406 | |
c1f19b51 | 407 | case SIOCSHWTSTAMP: |
446e2305 KM |
408 | if (phydev->mii_ts && phydev->mii_ts->hwtstamp) { |
409 | if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) | |
410 | return -EFAULT; | |
411 | ||
412 | hwtstamp_config_to_kernel(&kernel_cfg, &cfg); | |
413 | ret = phydev->mii_ts->hwtstamp(phydev->mii_ts, &kernel_cfg, &extack); | |
414 | if (ret) | |
415 | return ret; | |
416 | ||
417 | hwtstamp_config_from_kernel(&cfg, &kernel_cfg); | |
418 | if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) | |
419 | return -EFAULT; | |
420 | ||
421 | return 0; | |
422 | } | |
df561f66 | 423 | fallthrough; |
c1f19b51 | 424 | |
dda93b48 | 425 | default: |
c6d6a511 | 426 | return -EOPNOTSUPP; |
00db8189 | 427 | } |
00db8189 | 428 | } |
680e9fe9 | 429 | EXPORT_SYMBOL(phy_mii_ioctl); |
00db8189 | 430 | |
2ab1d925 | 431 | /** |
a7605370 | 432 | * phy_do_ioctl - generic ndo_eth_ioctl implementation |
2ab1d925 HK |
433 | * @dev: the net_device struct |
434 | * @ifr: &struct ifreq for socket ioctl's | |
435 | * @cmd: ioctl cmd to execute | |
436 | */ | |
bbbf8430 | 437 | int phy_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
2ab1d925 | 438 | { |
bbbf8430 | 439 | if (!dev->phydev) |
2ab1d925 HK |
440 | return -ENODEV; |
441 | ||
442 | return phy_mii_ioctl(dev->phydev, ifr, cmd); | |
443 | } | |
bbbf8430 HK |
444 | EXPORT_SYMBOL(phy_do_ioctl); |
445 | ||
4069a572 | 446 | /** |
a7605370 | 447 | * phy_do_ioctl_running - generic ndo_eth_ioctl implementation but test first |
4069a572 AL |
448 | * |
449 | * @dev: the net_device struct | |
450 | * @ifr: &struct ifreq for socket ioctl's | |
451 | * @cmd: ioctl cmd to execute | |
452 | * | |
453 | * Same as phy_do_ioctl, but ensures that net_device is running before | |
454 | * handling the ioctl. | |
455 | */ | |
bbbf8430 HK |
456 | int phy_do_ioctl_running(struct net_device *dev, struct ifreq *ifr, int cmd) |
457 | { | |
458 | if (!netif_running(dev)) | |
459 | return -ENODEV; | |
460 | ||
461 | return phy_do_ioctl(dev, ifr, cmd); | |
462 | } | |
3231e5d2 | 463 | EXPORT_SYMBOL(phy_do_ioctl_running); |
2ab1d925 | 464 | |
60495b66 VO |
465 | /** |
466 | * __phy_hwtstamp_get - Get hardware timestamping configuration from PHY | |
467 | * | |
468 | * @phydev: the PHY device structure | |
469 | * @config: structure holding the timestamping configuration | |
470 | * | |
471 | * Query the PHY device for its current hardware timestamping configuration. | |
472 | */ | |
473 | int __phy_hwtstamp_get(struct phy_device *phydev, | |
474 | struct kernel_hwtstamp_config *config) | |
475 | { | |
476 | if (!phydev) | |
477 | return -ENODEV; | |
478 | ||
430dc325 | 479 | return -EOPNOTSUPP; |
60495b66 VO |
480 | } |
481 | ||
482 | /** | |
483 | * __phy_hwtstamp_set - Modify PHY hardware timestamping configuration | |
484 | * | |
485 | * @phydev: the PHY device structure | |
486 | * @config: structure holding the timestamping configuration | |
487 | * @extack: netlink extended ack structure, for error reporting | |
488 | */ | |
489 | int __phy_hwtstamp_set(struct phy_device *phydev, | |
490 | struct kernel_hwtstamp_config *config, | |
491 | struct netlink_ext_ack *extack) | |
492 | { | |
493 | if (!phydev) | |
494 | return -ENODEV; | |
495 | ||
430dc325 KM |
496 | if (phydev->mii_ts && phydev->mii_ts->hwtstamp) |
497 | return phydev->mii_ts->hwtstamp(phydev->mii_ts, config, extack); | |
498 | ||
499 | return -EOPNOTSUPP; | |
60495b66 VO |
500 | } |
501 | ||
4069a572 AL |
502 | /** |
503 | * phy_queue_state_machine - Trigger the state machine to run soon | |
504 | * | |
505 | * @phydev: the phy_device struct | |
506 | * @jiffies: Run the state machine after these jiffies | |
507 | */ | |
ef6249e3 HK |
508 | static void phy_queue_state_machine(struct phy_device *phydev, |
509 | unsigned long jiffies) | |
a3320bcf HK |
510 | { |
511 | mod_delayed_work(system_power_efficient_wq, &phydev->state_queue, | |
97b33bdf | 512 | jiffies); |
a3320bcf HK |
513 | } |
514 | ||
4069a572 | 515 | /** |
69280228 | 516 | * phy_trigger_machine - Trigger the state machine to run now |
4069a572 AL |
517 | * |
518 | * @phydev: the phy_device struct | |
519 | */ | |
293e9a3d | 520 | void phy_trigger_machine(struct phy_device *phydev) |
a3320bcf HK |
521 | { |
522 | phy_queue_state_machine(phydev, 0); | |
523 | } | |
293e9a3d | 524 | EXPORT_SYMBOL(phy_trigger_machine); |
a3320bcf | 525 | |
a68a8138 AL |
526 | static void phy_abort_cable_test(struct phy_device *phydev) |
527 | { | |
528 | int err; | |
529 | ||
1dd3f212 AL |
530 | ethnl_cable_test_finished(phydev); |
531 | ||
a68a8138 AL |
532 | err = phy_init_hw(phydev); |
533 | if (err) | |
534 | phydev_err(phydev, "Error while aborting cable test"); | |
535 | } | |
536 | ||
4069a572 AL |
537 | /** |
538 | * phy_ethtool_get_strings - Get the statistic counter names | |
539 | * | |
540 | * @phydev: the phy_device struct | |
541 | * @data: Where to put the strings | |
542 | */ | |
17809516 FF |
543 | int phy_ethtool_get_strings(struct phy_device *phydev, u8 *data) |
544 | { | |
545 | if (!phydev->drv) | |
546 | return -EIO; | |
547 | ||
548 | mutex_lock(&phydev->lock); | |
549 | phydev->drv->get_strings(phydev, data); | |
550 | mutex_unlock(&phydev->lock); | |
551 | ||
552 | return 0; | |
553 | } | |
554 | EXPORT_SYMBOL(phy_ethtool_get_strings); | |
555 | ||
4069a572 AL |
556 | /** |
557 | * phy_ethtool_get_sset_count - Get the number of statistic counters | |
558 | * | |
559 | * @phydev: the phy_device struct | |
560 | */ | |
17809516 FF |
561 | int phy_ethtool_get_sset_count(struct phy_device *phydev) |
562 | { | |
563 | int ret; | |
564 | ||
565 | if (!phydev->drv) | |
566 | return -EIO; | |
567 | ||
568 | if (phydev->drv->get_sset_count && | |
569 | phydev->drv->get_strings && | |
570 | phydev->drv->get_stats) { | |
571 | mutex_lock(&phydev->lock); | |
572 | ret = phydev->drv->get_sset_count(phydev); | |
573 | mutex_unlock(&phydev->lock); | |
574 | ||
575 | return ret; | |
576 | } | |
577 | ||
578 | return -EOPNOTSUPP; | |
579 | } | |
580 | EXPORT_SYMBOL(phy_ethtool_get_sset_count); | |
581 | ||
4069a572 AL |
582 | /** |
583 | * phy_ethtool_get_stats - Get the statistic counters | |
584 | * | |
585 | * @phydev: the phy_device struct | |
586 | * @stats: What counters to get | |
587 | * @data: Where to store the counters | |
588 | */ | |
17809516 FF |
589 | int phy_ethtool_get_stats(struct phy_device *phydev, |
590 | struct ethtool_stats *stats, u64 *data) | |
591 | { | |
592 | if (!phydev->drv) | |
593 | return -EIO; | |
594 | ||
595 | mutex_lock(&phydev->lock); | |
596 | phydev->drv->get_stats(phydev, stats, data); | |
597 | mutex_unlock(&phydev->lock); | |
598 | ||
599 | return 0; | |
600 | } | |
601 | EXPORT_SYMBOL(phy_ethtool_get_stats); | |
602 | ||
b7a2c1fe JK |
603 | /** |
604 | * __phy_ethtool_get_phy_stats - Retrieve standardized PHY statistics | |
605 | * @phydev: Pointer to the PHY device | |
606 | * @phy_stats: Pointer to ethtool_eth_phy_stats structure | |
607 | * @phydev_stats: Pointer to ethtool_phy_stats structure | |
608 | * | |
609 | * Fetches PHY statistics using a kernel-defined interface for consistent | |
610 | * diagnostics. Unlike phy_ethtool_get_stats(), which allows custom stats, | |
611 | * this function enforces a standardized format for better interoperability. | |
612 | */ | |
613 | void __phy_ethtool_get_phy_stats(struct phy_device *phydev, | |
614 | struct ethtool_eth_phy_stats *phy_stats, | |
615 | struct ethtool_phy_stats *phydev_stats) | |
616 | { | |
617 | if (!phydev->drv || !phydev->drv->get_phy_stats) | |
618 | return; | |
619 | ||
620 | mutex_lock(&phydev->lock); | |
621 | phydev->drv->get_phy_stats(phydev, phy_stats, phydev_stats); | |
622 | mutex_unlock(&phydev->lock); | |
623 | } | |
624 | ||
625 | /** | |
626 | * __phy_ethtool_get_link_ext_stats - Retrieve extended link statistics for a PHY | |
627 | * @phydev: Pointer to the PHY device | |
628 | * @link_stats: Pointer to the structure to store extended link statistics | |
629 | * | |
630 | * Populates the ethtool_link_ext_stats structure with link down event counts | |
631 | * and additional driver-specific link statistics, if available. | |
632 | */ | |
633 | void __phy_ethtool_get_link_ext_stats(struct phy_device *phydev, | |
634 | struct ethtool_link_ext_stats *link_stats) | |
635 | { | |
636 | link_stats->link_down_events = READ_ONCE(phydev->link_down_events); | |
637 | ||
638 | if (!phydev->drv || !phydev->drv->get_link_stats) | |
639 | return; | |
640 | ||
641 | mutex_lock(&phydev->lock); | |
642 | phydev->drv->get_link_stats(phydev, link_stats); | |
643 | mutex_unlock(&phydev->lock); | |
644 | } | |
645 | ||
a23a1e57 PB |
646 | /** |
647 | * phy_ethtool_get_plca_cfg - Get PLCA RS configuration | |
648 | * @phydev: the phy_device struct | |
649 | * @plca_cfg: where to store the retrieved configuration | |
650 | * | |
651 | * Retrieve the PLCA configuration from the PHY. Return 0 on success or a | |
652 | * negative value if an error occurred. | |
653 | */ | |
654 | int phy_ethtool_get_plca_cfg(struct phy_device *phydev, | |
655 | struct phy_plca_cfg *plca_cfg) | |
656 | { | |
657 | int ret; | |
658 | ||
659 | if (!phydev->drv) { | |
660 | ret = -EIO; | |
661 | goto out; | |
662 | } | |
663 | ||
664 | if (!phydev->drv->get_plca_cfg) { | |
665 | ret = -EOPNOTSUPP; | |
666 | goto out; | |
667 | } | |
668 | ||
669 | mutex_lock(&phydev->lock); | |
670 | ret = phydev->drv->get_plca_cfg(phydev, plca_cfg); | |
671 | ||
672 | mutex_unlock(&phydev->lock); | |
673 | out: | |
674 | return ret; | |
675 | } | |
676 | ||
677 | /** | |
678 | * plca_check_valid - Check PLCA configuration before enabling | |
679 | * @phydev: the phy_device struct | |
680 | * @plca_cfg: current PLCA configuration | |
681 | * @extack: extack for reporting useful error messages | |
682 | * | |
683 | * Checks whether the PLCA and PHY configuration are consistent and it is safe | |
684 | * to enable PLCA. Returns 0 on success or a negative value if the PLCA or PHY | |
685 | * configuration is not consistent. | |
686 | */ | |
687 | static int plca_check_valid(struct phy_device *phydev, | |
688 | const struct phy_plca_cfg *plca_cfg, | |
689 | struct netlink_ext_ack *extack) | |
690 | { | |
691 | int ret = 0; | |
692 | ||
693 | if (!linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT, | |
694 | phydev->advertising)) { | |
695 | ret = -EOPNOTSUPP; | |
696 | NL_SET_ERR_MSG(extack, | |
697 | "Point to Multi-Point mode is not enabled"); | |
698 | } else if (plca_cfg->node_id >= 255) { | |
699 | NL_SET_ERR_MSG(extack, "PLCA node ID is not set"); | |
700 | ret = -EINVAL; | |
701 | } | |
702 | ||
703 | return ret; | |
704 | } | |
705 | ||
706 | /** | |
707 | * phy_ethtool_set_plca_cfg - Set PLCA RS configuration | |
708 | * @phydev: the phy_device struct | |
709 | * @plca_cfg: new PLCA configuration to apply | |
710 | * @extack: extack for reporting useful error messages | |
711 | * | |
712 | * Sets the PLCA configuration in the PHY. Return 0 on success or a | |
713 | * negative value if an error occurred. | |
714 | */ | |
715 | int phy_ethtool_set_plca_cfg(struct phy_device *phydev, | |
716 | const struct phy_plca_cfg *plca_cfg, | |
717 | struct netlink_ext_ack *extack) | |
718 | { | |
719 | struct phy_plca_cfg *curr_plca_cfg; | |
720 | int ret; | |
721 | ||
722 | if (!phydev->drv) { | |
723 | ret = -EIO; | |
724 | goto out; | |
725 | } | |
726 | ||
727 | if (!phydev->drv->set_plca_cfg || | |
728 | !phydev->drv->get_plca_cfg) { | |
729 | ret = -EOPNOTSUPP; | |
730 | goto out; | |
731 | } | |
732 | ||
733 | curr_plca_cfg = kmalloc(sizeof(*curr_plca_cfg), GFP_KERNEL); | |
734 | if (!curr_plca_cfg) { | |
735 | ret = -ENOMEM; | |
736 | goto out; | |
737 | } | |
738 | ||
739 | mutex_lock(&phydev->lock); | |
740 | ||
741 | ret = phydev->drv->get_plca_cfg(phydev, curr_plca_cfg); | |
742 | if (ret) | |
743 | goto out_drv; | |
744 | ||
745 | if (curr_plca_cfg->enabled < 0 && plca_cfg->enabled >= 0) { | |
746 | NL_SET_ERR_MSG(extack, | |
747 | "PHY does not support changing the PLCA 'enable' attribute"); | |
748 | ret = -EINVAL; | |
749 | goto out_drv; | |
750 | } | |
751 | ||
752 | if (curr_plca_cfg->node_id < 0 && plca_cfg->node_id >= 0) { | |
753 | NL_SET_ERR_MSG(extack, | |
754 | "PHY does not support changing the PLCA 'local node ID' attribute"); | |
755 | ret = -EINVAL; | |
756 | goto out_drv; | |
757 | } | |
758 | ||
759 | if (curr_plca_cfg->node_cnt < 0 && plca_cfg->node_cnt >= 0) { | |
760 | NL_SET_ERR_MSG(extack, | |
761 | "PHY does not support changing the PLCA 'node count' attribute"); | |
762 | ret = -EINVAL; | |
763 | goto out_drv; | |
764 | } | |
765 | ||
766 | if (curr_plca_cfg->to_tmr < 0 && plca_cfg->to_tmr >= 0) { | |
767 | NL_SET_ERR_MSG(extack, | |
768 | "PHY does not support changing the PLCA 'TO timer' attribute"); | |
769 | ret = -EINVAL; | |
770 | goto out_drv; | |
771 | } | |
772 | ||
773 | if (curr_plca_cfg->burst_cnt < 0 && plca_cfg->burst_cnt >= 0) { | |
774 | NL_SET_ERR_MSG(extack, | |
775 | "PHY does not support changing the PLCA 'burst count' attribute"); | |
776 | ret = -EINVAL; | |
777 | goto out_drv; | |
778 | } | |
779 | ||
780 | if (curr_plca_cfg->burst_tmr < 0 && plca_cfg->burst_tmr >= 0) { | |
781 | NL_SET_ERR_MSG(extack, | |
782 | "PHY does not support changing the PLCA 'burst timer' attribute"); | |
783 | ret = -EINVAL; | |
784 | goto out_drv; | |
785 | } | |
786 | ||
787 | // if enabling PLCA, perform a few sanity checks | |
788 | if (plca_cfg->enabled > 0) { | |
789 | // allow setting node_id concurrently with enabled | |
790 | if (plca_cfg->node_id >= 0) | |
791 | curr_plca_cfg->node_id = plca_cfg->node_id; | |
792 | ||
793 | ret = plca_check_valid(phydev, curr_plca_cfg, extack); | |
794 | if (ret) | |
795 | goto out_drv; | |
796 | } | |
797 | ||
798 | ret = phydev->drv->set_plca_cfg(phydev, plca_cfg); | |
799 | ||
800 | out_drv: | |
801 | kfree(curr_plca_cfg); | |
802 | mutex_unlock(&phydev->lock); | |
803 | out: | |
804 | return ret; | |
805 | } | |
806 | ||
807 | /** | |
808 | * phy_ethtool_get_plca_status - Get PLCA RS status information | |
809 | * @phydev: the phy_device struct | |
810 | * @plca_st: where to store the retrieved status information | |
811 | * | |
812 | * Retrieve the PLCA status information from the PHY. Return 0 on success or a | |
813 | * negative value if an error occurred. | |
814 | */ | |
815 | int phy_ethtool_get_plca_status(struct phy_device *phydev, | |
816 | struct phy_plca_status *plca_st) | |
817 | { | |
818 | int ret; | |
819 | ||
820 | if (!phydev->drv) { | |
821 | ret = -EIO; | |
822 | goto out; | |
823 | } | |
824 | ||
825 | if (!phydev->drv->get_plca_status) { | |
826 | ret = -EOPNOTSUPP; | |
827 | goto out; | |
828 | } | |
829 | ||
830 | mutex_lock(&phydev->lock); | |
831 | ret = phydev->drv->get_plca_status(phydev, plca_st); | |
832 | ||
833 | mutex_unlock(&phydev->lock); | |
834 | out: | |
835 | return ret; | |
836 | } | |
837 | ||
4069a572 AL |
838 | /** |
839 | * phy_start_cable_test - Start a cable test | |
840 | * | |
841 | * @phydev: the phy_device struct | |
842 | * @extack: extack for reporting useful error messages | |
843 | */ | |
a68a8138 AL |
844 | int phy_start_cable_test(struct phy_device *phydev, |
845 | struct netlink_ext_ack *extack) | |
846 | { | |
4a459bdc | 847 | struct net_device *dev = phydev->attached_dev; |
1dd3f212 | 848 | int err = -ENOMEM; |
a68a8138 AL |
849 | |
850 | if (!(phydev->drv && | |
851 | phydev->drv->cable_test_start && | |
852 | phydev->drv->cable_test_get_status)) { | |
853 | NL_SET_ERR_MSG(extack, | |
854 | "PHY driver does not support cable testing"); | |
855 | return -EOPNOTSUPP; | |
856 | } | |
857 | ||
858 | mutex_lock(&phydev->lock); | |
859 | if (phydev->state == PHY_CABLETEST) { | |
860 | NL_SET_ERR_MSG(extack, | |
861 | "PHY already performing a test"); | |
862 | err = -EBUSY; | |
863 | goto out; | |
864 | } | |
865 | ||
866 | if (phydev->state < PHY_UP || | |
867 | phydev->state > PHY_CABLETEST) { | |
868 | NL_SET_ERR_MSG(extack, | |
869 | "PHY not configured. Try setting interface up"); | |
870 | err = -EBUSY; | |
871 | goto out; | |
872 | } | |
873 | ||
1a644de2 | 874 | err = ethnl_cable_test_alloc(phydev, ETHTOOL_MSG_CABLE_TEST_NTF); |
1dd3f212 AL |
875 | if (err) |
876 | goto out; | |
877 | ||
a68a8138 | 878 | /* Mark the carrier down until the test is complete */ |
a307593a | 879 | phy_link_down(phydev); |
a68a8138 | 880 | |
4a459bdc | 881 | netif_testing_on(dev); |
a68a8138 AL |
882 | err = phydev->drv->cable_test_start(phydev); |
883 | if (err) { | |
4a459bdc | 884 | netif_testing_off(dev); |
a68a8138 | 885 | phy_link_up(phydev); |
1dd3f212 | 886 | goto out_free; |
a68a8138 AL |
887 | } |
888 | ||
889 | phydev->state = PHY_CABLETEST; | |
890 | ||
97c22438 AL |
891 | if (phy_polling_mode(phydev)) |
892 | phy_trigger_machine(phydev); | |
1dd3f212 AL |
893 | |
894 | mutex_unlock(&phydev->lock); | |
895 | ||
896 | return 0; | |
897 | ||
898 | out_free: | |
899 | ethnl_cable_test_free(phydev); | |
a68a8138 AL |
900 | out: |
901 | mutex_unlock(&phydev->lock); | |
902 | ||
903 | return err; | |
904 | } | |
905 | EXPORT_SYMBOL(phy_start_cable_test); | |
906 | ||
4069a572 AL |
907 | /** |
908 | * phy_start_cable_test_tdr - Start a raw TDR cable test | |
909 | * | |
910 | * @phydev: the phy_device struct | |
911 | * @extack: extack for reporting useful error messages | |
912 | * @config: Configuration of the test to run | |
913 | */ | |
1a644de2 | 914 | int phy_start_cable_test_tdr(struct phy_device *phydev, |
f2bc8ad3 AL |
915 | struct netlink_ext_ack *extack, |
916 | const struct phy_tdr_config *config) | |
1a644de2 AL |
917 | { |
918 | struct net_device *dev = phydev->attached_dev; | |
919 | int err = -ENOMEM; | |
920 | ||
921 | if (!(phydev->drv && | |
922 | phydev->drv->cable_test_tdr_start && | |
923 | phydev->drv->cable_test_get_status)) { | |
924 | NL_SET_ERR_MSG(extack, | |
925 | "PHY driver does not support cable test TDR"); | |
926 | return -EOPNOTSUPP; | |
927 | } | |
928 | ||
929 | mutex_lock(&phydev->lock); | |
930 | if (phydev->state == PHY_CABLETEST) { | |
931 | NL_SET_ERR_MSG(extack, | |
932 | "PHY already performing a test"); | |
933 | err = -EBUSY; | |
934 | goto out; | |
935 | } | |
936 | ||
937 | if (phydev->state < PHY_UP || | |
938 | phydev->state > PHY_CABLETEST) { | |
939 | NL_SET_ERR_MSG(extack, | |
940 | "PHY not configured. Try setting interface up"); | |
941 | err = -EBUSY; | |
942 | goto out; | |
943 | } | |
944 | ||
945 | err = ethnl_cable_test_alloc(phydev, ETHTOOL_MSG_CABLE_TEST_TDR_NTF); | |
946 | if (err) | |
947 | goto out; | |
948 | ||
949 | /* Mark the carrier down until the test is complete */ | |
950 | phy_link_down(phydev); | |
951 | ||
952 | netif_testing_on(dev); | |
f2bc8ad3 | 953 | err = phydev->drv->cable_test_tdr_start(phydev, config); |
1a644de2 AL |
954 | if (err) { |
955 | netif_testing_off(dev); | |
956 | phy_link_up(phydev); | |
957 | goto out_free; | |
958 | } | |
959 | ||
960 | phydev->state = PHY_CABLETEST; | |
961 | ||
962 | if (phy_polling_mode(phydev)) | |
963 | phy_trigger_machine(phydev); | |
964 | ||
965 | mutex_unlock(&phydev->lock); | |
966 | ||
967 | return 0; | |
968 | ||
969 | out_free: | |
970 | ethnl_cable_test_free(phydev); | |
971 | out: | |
972 | mutex_unlock(&phydev->lock); | |
973 | ||
974 | return err; | |
975 | } | |
976 | EXPORT_SYMBOL(phy_start_cable_test_tdr); | |
977 | ||
014068dc | 978 | int phy_config_aneg(struct phy_device *phydev) |
76299580 HK |
979 | { |
980 | if (phydev->drv->config_aneg) | |
981 | return phydev->drv->config_aneg(phydev); | |
34786005 CG |
982 | |
983 | /* Clause 45 PHYs that don't implement Clause 22 registers are not | |
984 | * allowed to call genphy_config_aneg() | |
985 | */ | |
986 | if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0))) | |
94acaeb5 | 987 | return genphy_c45_config_aneg(phydev); |
34786005 CG |
988 | |
989 | return genphy_config_aneg(phydev); | |
76299580 | 990 | } |
014068dc | 991 | EXPORT_SYMBOL(phy_config_aneg); |
76299580 | 992 | |
74a992b3 HK |
993 | /** |
994 | * phy_check_link_status - check link status and set state accordingly | |
995 | * @phydev: the phy_device struct | |
996 | * | |
997 | * Description: Check for link and whether autoneg was triggered / is running | |
998 | * and set state accordingly | |
999 | */ | |
1000 | static int phy_check_link_status(struct phy_device *phydev) | |
1001 | { | |
1002 | int err; | |
1003 | ||
e6e918d4 | 1004 | lockdep_assert_held(&phydev->lock); |
74a992b3 | 1005 | |
fe4a7a41 JA |
1006 | /* Keep previous state if loopback is enabled because some PHYs |
1007 | * report that Link is Down when loopback is enabled. | |
1008 | */ | |
1009 | if (phydev->loopback_enabled) | |
1010 | return 0; | |
1011 | ||
74a992b3 HK |
1012 | err = phy_read_status(phydev); |
1013 | if (err) | |
1014 | return err; | |
1015 | ||
1016 | if (phydev->link && phydev->state != PHY_RUNNING) { | |
5eee3bb7 | 1017 | phy_check_downshift(phydev); |
74a992b3 | 1018 | phydev->state = PHY_RUNNING; |
809265fe | 1019 | err = genphy_c45_eee_is_active(phydev, NULL); |
e2668c34 RKO |
1020 | phydev->eee_active = err > 0; |
1021 | phydev->enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled && | |
1022 | phydev->eee_active; | |
3e43b903 | 1023 | |
74a992b3 HK |
1024 | phy_link_up(phydev); |
1025 | } else if (!phydev->link && phydev->state != PHY_NOLINK) { | |
1026 | phydev->state = PHY_NOLINK; | |
e2668c34 | 1027 | phydev->eee_active = false; |
e3b6876a | 1028 | phydev->enable_tx_lpi = false; |
a307593a | 1029 | phy_link_down(phydev); |
74a992b3 HK |
1030 | } |
1031 | ||
1032 | return 0; | |
1033 | } | |
1034 | ||
b4c7698d RKO |
1035 | /** |
1036 | * phy_inband_caps - query which in-band signalling modes are supported | |
1037 | * @phydev: a pointer to a &struct phy_device | |
1038 | * @interface: the interface mode for the PHY | |
1039 | * | |
1040 | * Returns zero if it is unknown what in-band signalling is supported by the | |
1041 | * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise, | |
1042 | * returns a bit mask of the LINK_INBAND_* values from | |
1043 | * &enum link_inband_signalling to describe which inband modes are supported | |
1044 | * by the PHY for this interface mode. | |
1045 | */ | |
1046 | unsigned int phy_inband_caps(struct phy_device *phydev, | |
1047 | phy_interface_t interface) | |
1048 | { | |
1049 | if (phydev->drv && phydev->drv->inband_caps) | |
1050 | return phydev->drv->inband_caps(phydev, interface); | |
1051 | ||
1052 | return 0; | |
1053 | } | |
1054 | EXPORT_SYMBOL_GPL(phy_inband_caps); | |
1055 | ||
5d58a890 RKO |
1056 | /** |
1057 | * phy_config_inband - configure the desired PHY in-band mode | |
1058 | * @phydev: the phy_device struct | |
1059 | * @modes: in-band modes to configure | |
1060 | * | |
1061 | * Description: disables, enables or enables-with-bypass in-band signalling | |
1062 | * between the PHY and host system. | |
1063 | * | |
1064 | * Returns: zero on success, or negative errno value. | |
1065 | */ | |
1066 | int phy_config_inband(struct phy_device *phydev, unsigned int modes) | |
1067 | { | |
1068 | int err; | |
1069 | ||
1070 | if (!!(modes & LINK_INBAND_DISABLE) + | |
1071 | !!(modes & LINK_INBAND_ENABLE) + | |
1072 | !!(modes & LINK_INBAND_BYPASS) != 1) | |
1073 | return -EINVAL; | |
1074 | ||
1075 | mutex_lock(&phydev->lock); | |
1076 | if (!phydev->drv) | |
1077 | err = -EIO; | |
1078 | else if (!phydev->drv->config_inband) | |
1079 | err = -EOPNOTSUPP; | |
1080 | else | |
1081 | err = phydev->drv->config_inband(phydev, modes); | |
1082 | mutex_unlock(&phydev->lock); | |
1083 | ||
1084 | return err; | |
1085 | } | |
1086 | EXPORT_SYMBOL(phy_config_inband); | |
1087 | ||
b3df0da8 | 1088 | /** |
707293a5 | 1089 | * _phy_start_aneg - start auto-negotiation for this PHY device |
b3df0da8 | 1090 | * @phydev: the phy_device struct |
e1393456 | 1091 | * |
b3df0da8 RD |
1092 | * Description: Sanitizes the settings (if we're not autonegotiating |
1093 | * them), and then calls the driver's config_aneg function. | |
1094 | * If the PHYCONTROL Layer is operating, we change the state to | |
1095 | * reflect the beginning of Auto-negotiation or forcing. | |
e1393456 | 1096 | */ |
6a23c555 | 1097 | int _phy_start_aneg(struct phy_device *phydev) |
e1393456 AF |
1098 | { |
1099 | int err; | |
1100 | ||
707293a5 AL |
1101 | lockdep_assert_held(&phydev->lock); |
1102 | ||
25149ef9 FF |
1103 | if (!phydev->drv) |
1104 | return -EIO; | |
1105 | ||
e1393456 AF |
1106 | if (AUTONEG_DISABLE == phydev->autoneg) |
1107 | phy_sanitize_settings(phydev); | |
1108 | ||
76299580 | 1109 | err = phy_config_aneg(phydev); |
e1393456 | 1110 | if (err < 0) |
707293a5 | 1111 | return err; |
e1393456 | 1112 | |
2bd229df HK |
1113 | if (phy_is_started(phydev)) |
1114 | err = phy_check_link_status(phydev); | |
707293a5 AL |
1115 | |
1116 | return err; | |
1117 | } | |
6a23c555 | 1118 | EXPORT_SYMBOL(_phy_start_aneg); |
707293a5 AL |
1119 | |
1120 | /** | |
1121 | * phy_start_aneg - start auto-negotiation for this PHY device | |
1122 | * @phydev: the phy_device struct | |
1123 | * | |
1124 | * Description: Sanitizes the settings (if we're not autonegotiating | |
1125 | * them), and then calls the driver's config_aneg function. | |
1126 | * If the PHYCONTROL Layer is operating, we change the state to | |
1127 | * reflect the beginning of Auto-negotiation or forcing. | |
1128 | */ | |
1129 | int phy_start_aneg(struct phy_device *phydev) | |
1130 | { | |
1131 | int err; | |
1132 | ||
1133 | mutex_lock(&phydev->lock); | |
1134 | err = _phy_start_aneg(phydev); | |
35b5f6b1 | 1135 | mutex_unlock(&phydev->lock); |
f555f34f | 1136 | |
e1393456 AF |
1137 | return err; |
1138 | } | |
1139 | EXPORT_SYMBOL(phy_start_aneg); | |
1140 | ||
2b9672dd HK |
1141 | static int phy_poll_aneg_done(struct phy_device *phydev) |
1142 | { | |
1143 | unsigned int retries = 100; | |
1144 | int ret; | |
1145 | ||
1146 | do { | |
1147 | msleep(100); | |
1148 | ret = phy_aneg_done(phydev); | |
1149 | } while (!ret && --retries); | |
1150 | ||
1151 | if (!ret) | |
1152 | return -ETIMEDOUT; | |
1153 | ||
1154 | return ret < 0 ? ret : 0; | |
1155 | } | |
1156 | ||
64cd92d5 AL |
1157 | int phy_ethtool_ksettings_set(struct phy_device *phydev, |
1158 | const struct ethtool_link_ksettings *cmd) | |
1159 | { | |
1160 | __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); | |
1161 | u8 autoneg = cmd->base.autoneg; | |
1162 | u8 duplex = cmd->base.duplex; | |
1163 | u32 speed = cmd->base.speed; | |
1164 | ||
1165 | if (cmd->base.phy_address != phydev->mdio.addr) | |
1166 | return -EINVAL; | |
1167 | ||
1168 | linkmode_copy(advertising, cmd->link_modes.advertising); | |
1169 | ||
1170 | /* We make sure that we don't pass unsupported values in to the PHY */ | |
1171 | linkmode_and(advertising, advertising, phydev->supported); | |
1172 | ||
1173 | /* Verify the settings we care about. */ | |
1174 | if (autoneg != AUTONEG_ENABLE && autoneg != AUTONEG_DISABLE) | |
1175 | return -EINVAL; | |
1176 | ||
d4c89767 DK |
1177 | if (autoneg == AUTONEG_ENABLE && |
1178 | (linkmode_empty(advertising) || | |
1179 | !linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, | |
1180 | phydev->supported))) | |
64cd92d5 AL |
1181 | return -EINVAL; |
1182 | ||
1183 | if (autoneg == AUTONEG_DISABLE && | |
1184 | ((speed != SPEED_1000 && | |
1185 | speed != SPEED_100 && | |
1186 | speed != SPEED_10) || | |
1187 | (duplex != DUPLEX_HALF && | |
1188 | duplex != DUPLEX_FULL))) | |
1189 | return -EINVAL; | |
1190 | ||
af1a02aa | 1191 | mutex_lock(&phydev->lock); |
64cd92d5 AL |
1192 | phydev->autoneg = autoneg; |
1193 | ||
1194 | if (autoneg == AUTONEG_DISABLE) { | |
1195 | phydev->speed = speed; | |
1196 | phydev->duplex = duplex; | |
1197 | } | |
1198 | ||
1199 | linkmode_copy(phydev->advertising, advertising); | |
1200 | ||
1201 | linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, | |
1202 | phydev->advertising, autoneg == AUTONEG_ENABLE); | |
1203 | ||
1204 | phydev->master_slave_set = cmd->base.master_slave_cfg; | |
1205 | phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl; | |
1206 | ||
1207 | /* Restart the PHY */ | |
a4db9055 HK |
1208 | if (phy_is_started(phydev)) { |
1209 | phydev->state = PHY_UP; | |
1210 | phy_trigger_machine(phydev); | |
1211 | } else { | |
1212 | _phy_start_aneg(phydev); | |
1213 | } | |
64cd92d5 | 1214 | |
af1a02aa | 1215 | mutex_unlock(&phydev->lock); |
64cd92d5 AL |
1216 | return 0; |
1217 | } | |
1218 | EXPORT_SYMBOL(phy_ethtool_ksettings_set); | |
1219 | ||
2b9672dd HK |
1220 | /** |
1221 | * phy_speed_down - set speed to lowest speed supported by both link partners | |
1222 | * @phydev: the phy_device struct | |
1223 | * @sync: perform action synchronously | |
1224 | * | |
1225 | * Description: Typically used to save energy when waiting for a WoL packet | |
1226 | * | |
1227 | * WARNING: Setting sync to false may cause the system being unable to suspend | |
1228 | * in case the PHY generates an interrupt when finishing the autonegotiation. | |
1229 | * This interrupt may wake up the system immediately after suspend. | |
1230 | * Therefore use sync = false only if you're sure it's safe with the respective | |
1231 | * network chip. | |
1232 | */ | |
1233 | int phy_speed_down(struct phy_device *phydev, bool sync) | |
1234 | { | |
65b27995 | 1235 | __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp); |
2f987d48 AL |
1236 | int ret = 0; |
1237 | ||
1238 | mutex_lock(&phydev->lock); | |
2b9672dd HK |
1239 | |
1240 | if (phydev->autoneg != AUTONEG_ENABLE) | |
2f987d48 | 1241 | goto out; |
2b9672dd | 1242 | |
65b27995 HK |
1243 | linkmode_copy(adv_tmp, phydev->advertising); |
1244 | ||
1245 | ret = phy_speed_down_core(phydev); | |
1246 | if (ret) | |
2f987d48 | 1247 | goto out; |
2b9672dd | 1248 | |
65b27995 HK |
1249 | linkmode_copy(phydev->adv_old, adv_tmp); |
1250 | ||
2f987d48 AL |
1251 | if (linkmode_equal(phydev->advertising, adv_tmp)) { |
1252 | ret = 0; | |
1253 | goto out; | |
1254 | } | |
2b9672dd HK |
1255 | |
1256 | ret = phy_config_aneg(phydev); | |
1257 | if (ret) | |
2f987d48 AL |
1258 | goto out; |
1259 | ||
1260 | ret = sync ? phy_poll_aneg_done(phydev) : 0; | |
1261 | out: | |
1262 | mutex_unlock(&phydev->lock); | |
2b9672dd | 1263 | |
2f987d48 | 1264 | return ret; |
2b9672dd HK |
1265 | } |
1266 | EXPORT_SYMBOL_GPL(phy_speed_down); | |
1267 | ||
1268 | /** | |
1269 | * phy_speed_up - (re)set advertised speeds to all supported speeds | |
1270 | * @phydev: the phy_device struct | |
1271 | * | |
1272 | * Description: Used to revert the effect of phy_speed_down | |
1273 | */ | |
1274 | int phy_speed_up(struct phy_device *phydev) | |
1275 | { | |
65b27995 | 1276 | __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp); |
2f987d48 AL |
1277 | int ret = 0; |
1278 | ||
1279 | mutex_lock(&phydev->lock); | |
2b9672dd HK |
1280 | |
1281 | if (phydev->autoneg != AUTONEG_ENABLE) | |
2f987d48 | 1282 | goto out; |
2b9672dd | 1283 | |
65b27995 | 1284 | if (linkmode_empty(phydev->adv_old)) |
2f987d48 | 1285 | goto out; |
2b9672dd | 1286 | |
65b27995 HK |
1287 | linkmode_copy(adv_tmp, phydev->advertising); |
1288 | linkmode_copy(phydev->advertising, phydev->adv_old); | |
1289 | linkmode_zero(phydev->adv_old); | |
3c1bcc86 | 1290 | |
65b27995 | 1291 | if (linkmode_equal(phydev->advertising, adv_tmp)) |
2f987d48 AL |
1292 | goto out; |
1293 | ||
1294 | ret = phy_config_aneg(phydev); | |
1295 | out: | |
1296 | mutex_unlock(&phydev->lock); | |
2b9672dd | 1297 | |
2f987d48 | 1298 | return ret; |
2b9672dd HK |
1299 | } |
1300 | EXPORT_SYMBOL_GPL(phy_speed_up); | |
1301 | ||
b3df0da8 RD |
1302 | /** |
1303 | * phy_start_machine - start PHY state machine tracking | |
1304 | * @phydev: the phy_device struct | |
00db8189 | 1305 | * |
b3df0da8 | 1306 | * Description: The PHY infrastructure can run a state machine |
00db8189 | 1307 | * which tracks whether the PHY is starting up, negotiating, |
fb5e7606 FF |
1308 | * etc. This function starts the delayed workqueue which tracks |
1309 | * the state of the PHY. If you want to maintain your own state machine, | |
29935aeb | 1310 | * do not call this function. |
b3df0da8 | 1311 | */ |
29935aeb | 1312 | void phy_start_machine(struct phy_device *phydev) |
00db8189 | 1313 | { |
6384e483 | 1314 | phy_trigger_machine(phydev); |
00db8189 | 1315 | } |
5e5758d9 | 1316 | EXPORT_SYMBOL_GPL(phy_start_machine); |
00db8189 | 1317 | |
b3df0da8 RD |
1318 | /** |
1319 | * phy_stop_machine - stop the PHY state machine tracking | |
1320 | * @phydev: target phy_device struct | |
00db8189 | 1321 | * |
fb5e7606 FF |
1322 | * Description: Stops the state machine delayed workqueue, sets the |
1323 | * state to UP (unless it wasn't up yet). This function must be | |
1324 | * called BEFORE phy_detach. | |
00db8189 AF |
1325 | */ |
1326 | void phy_stop_machine(struct phy_device *phydev) | |
1327 | { | |
a390d1f3 | 1328 | cancel_delayed_work_sync(&phydev->state_queue); |
00db8189 | 1329 | |
35b5f6b1 | 1330 | mutex_lock(&phydev->lock); |
a2fc9d7e | 1331 | if (phy_is_started(phydev)) |
00db8189 | 1332 | phydev->state = PHY_UP; |
35b5f6b1 | 1333 | mutex_unlock(&phydev->lock); |
00db8189 AF |
1334 | } |
1335 | ||
323fe43c FF |
1336 | static void phy_process_error(struct phy_device *phydev) |
1337 | { | |
a0e026e7 SS |
1338 | /* phydev->lock must be held for the state change to be safe */ |
1339 | if (!mutex_is_locked(&phydev->lock)) | |
1340 | phydev_err(phydev, "PHY-device data unsafe context\n"); | |
1341 | ||
59088b5a | 1342 | phydev->state = PHY_ERROR; |
323fe43c FF |
1343 | |
1344 | phy_trigger_machine(phydev); | |
1345 | } | |
1346 | ||
1347 | static void phy_error_precise(struct phy_device *phydev, | |
1348 | const void *func, int err) | |
1349 | { | |
1350 | WARN(1, "%pS: returned: %d\n", func, err); | |
1351 | phy_process_error(phydev); | |
1352 | } | |
1353 | ||
b3df0da8 | 1354 | /** |
59088b5a | 1355 | * phy_error - enter ERROR state for this PHY device |
b3df0da8 | 1356 | * @phydev: target phy_device struct |
00db8189 | 1357 | * |
59088b5a | 1358 | * Moves the PHY to the ERROR state in response to a read |
00db8189 | 1359 | * or write error, and tells the controller the link is down. |
a0e026e7 | 1360 | * Must be called with phydev->lock held. |
00db8189 | 1361 | */ |
293e9a3d | 1362 | void phy_error(struct phy_device *phydev) |
00db8189 | 1363 | { |
fa7b28c1 | 1364 | WARN_ON(1); |
323fe43c | 1365 | phy_process_error(phydev); |
00db8189 | 1366 | } |
293e9a3d | 1367 | EXPORT_SYMBOL(phy_error); |
00db8189 | 1368 | |
a2c054a8 BM |
1369 | /** |
1370 | * phy_disable_interrupts - Disable the PHY interrupts from the PHY side | |
1371 | * @phydev: target phy_device struct | |
1372 | */ | |
3dd4ef1b | 1373 | int phy_disable_interrupts(struct phy_device *phydev) |
a2c054a8 | 1374 | { |
a2c054a8 | 1375 | /* Disable PHY interrupts */ |
6527b938 | 1376 | return phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); |
a2c054a8 BM |
1377 | } |
1378 | ||
1379 | /** | |
34d884e3 HK |
1380 | * phy_interrupt - PHY interrupt handler |
1381 | * @irq: interrupt line | |
1382 | * @phy_dat: phy_device pointer | |
1383 | * | |
1384 | * Description: Handle PHY interrupt | |
a2c054a8 | 1385 | */ |
34d884e3 | 1386 | static irqreturn_t phy_interrupt(int irq, void *phy_dat) |
a2c054a8 | 1387 | { |
34d884e3 | 1388 | struct phy_device *phydev = phy_dat; |
91a7cda1 | 1389 | irqreturn_t ret; |
a2c054a8 | 1390 | |
1758bde2 LW |
1391 | /* Wakeup interrupts may occur during a system sleep transition. |
1392 | * Postpone handling until the PHY has resumed. | |
1393 | */ | |
1394 | if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) { | |
1395 | struct net_device *netdev = phydev->attached_dev; | |
1396 | ||
1397 | if (netdev) { | |
1398 | struct device *parent = netdev->dev.parent; | |
1399 | ||
3ebbd9f6 | 1400 | if (netdev->ethtool->wol_enabled) |
1758bde2 LW |
1401 | pm_system_wakeup(); |
1402 | else if (device_may_wakeup(&netdev->dev)) | |
1403 | pm_wakeup_dev_event(&netdev->dev, 0, true); | |
1404 | else if (parent && device_may_wakeup(parent)) | |
1405 | pm_wakeup_dev_event(parent, 0, true); | |
1406 | } | |
1407 | ||
1408 | phydev->irq_rerun = 1; | |
1409 | disable_irq_nosync(irq); | |
1410 | return IRQ_HANDLED; | |
1411 | } | |
1412 | ||
91a7cda1 | 1413 | mutex_lock(&phydev->lock); |
0bd199fd | 1414 | ret = phydev->drv->handle_interrupt(phydev); |
91a7cda1 FD |
1415 | mutex_unlock(&phydev->lock); |
1416 | ||
1417 | return ret; | |
a2c054a8 BM |
1418 | } |
1419 | ||
b3df0da8 RD |
1420 | /** |
1421 | * phy_enable_interrupts - Enable the interrupts from the PHY side | |
1422 | * @phydev: target phy_device struct | |
1423 | */ | |
89ff05ec | 1424 | static int phy_enable_interrupts(struct phy_device *phydev) |
00db8189 | 1425 | { |
553fe92b | 1426 | return phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); |
00db8189 | 1427 | } |
00db8189 | 1428 | |
f2bc1c26 OR |
1429 | /** |
1430 | * phy_update_stats - Update PHY device statistics if supported. | |
1431 | * @phydev: Pointer to the PHY device structure. | |
1432 | * | |
1433 | * If the PHY driver provides an update_stats callback, this function | |
1434 | * invokes it to update the PHY statistics. If not, it returns 0. | |
1435 | * | |
1436 | * Return: 0 on success, or a negative error code if the callback fails. | |
1437 | */ | |
1438 | static int phy_update_stats(struct phy_device *phydev) | |
1439 | { | |
1440 | if (!phydev->drv->update_stats) | |
1441 | return 0; | |
1442 | ||
1443 | return phydev->drv->update_stats(phydev); | |
1444 | } | |
1445 | ||
b3df0da8 | 1446 | /** |
07b09289 | 1447 | * phy_request_interrupt - request and enable interrupt for a PHY device |
b3df0da8 | 1448 | * @phydev: target phy_device struct |
e1393456 | 1449 | * |
07b09289 | 1450 | * Description: Request and enable the interrupt for the given PHY. |
b3df0da8 | 1451 | * If this fails, then we set irq to PHY_POLL. |
e1393456 AF |
1452 | * This should only be called with a valid IRQ number. |
1453 | */ | |
434a4315 | 1454 | void phy_request_interrupt(struct phy_device *phydev) |
e1393456 | 1455 | { |
434a4315 HK |
1456 | int err; |
1457 | ||
1458 | err = request_threaded_irq(phydev->irq, NULL, phy_interrupt, | |
1459 | IRQF_ONESHOT | IRQF_SHARED, | |
1460 | phydev_name(phydev), phydev); | |
1461 | if (err) { | |
1462 | phydev_warn(phydev, "Error %d requesting IRQ %d, falling back to polling\n", | |
1463 | err, phydev->irq); | |
e1393456 | 1464 | phydev->irq = PHY_POLL; |
07b09289 HK |
1465 | } else { |
1466 | if (phy_enable_interrupts(phydev)) { | |
1467 | phydev_warn(phydev, "Can't enable interrupt, falling back to polling\n"); | |
1468 | phy_free_interrupt(phydev); | |
1469 | phydev->irq = PHY_POLL; | |
1470 | } | |
e1393456 | 1471 | } |
e1393456 | 1472 | } |
434a4315 | 1473 | EXPORT_SYMBOL(phy_request_interrupt); |
e1393456 | 1474 | |
07b09289 HK |
1475 | /** |
1476 | * phy_free_interrupt - disable and free interrupt for a PHY device | |
1477 | * @phydev: target phy_device struct | |
1478 | * | |
1479 | * Description: Disable and free the interrupt for the given PHY. | |
1480 | * This should only be called with a valid IRQ number. | |
1481 | */ | |
1482 | void phy_free_interrupt(struct phy_device *phydev) | |
1483 | { | |
1484 | phy_disable_interrupts(phydev); | |
1485 | free_irq(phydev->irq, phydev); | |
1486 | } | |
1487 | EXPORT_SYMBOL(phy_free_interrupt); | |
1488 | ||
8bf47e4d OR |
1489 | /** |
1490 | * phy_get_next_update_time - Determine the next PHY update time | |
1491 | * @phydev: Pointer to the phy_device structure | |
1492 | * | |
1493 | * This function queries the PHY driver to get the time for the next polling | |
1494 | * event. If the driver does not implement the callback, a default value is | |
1495 | * used. | |
1496 | * | |
1497 | * Return: The time for the next polling event in jiffies | |
1498 | */ | |
1499 | static unsigned int phy_get_next_update_time(struct phy_device *phydev) | |
1500 | { | |
1501 | if (phydev->drv && phydev->drv->get_next_update_time) | |
1502 | return phydev->drv->get_next_update_time(phydev); | |
1503 | ||
1504 | return PHY_STATE_TIME; | |
1505 | } | |
1506 | ||
8635c066 RKO |
1507 | enum phy_state_work { |
1508 | PHY_STATE_WORK_NONE, | |
1509 | PHY_STATE_WORK_ANEG, | |
1510 | PHY_STATE_WORK_SUSPEND, | |
1511 | }; | |
1512 | ||
1513 | static enum phy_state_work _phy_state_machine(struct phy_device *phydev) | |
00db8189 | 1514 | { |
8635c066 | 1515 | enum phy_state_work state_work = PHY_STATE_WORK_NONE; |
4a459bdc | 1516 | struct net_device *dev = phydev->attached_dev; |
8635c066 | 1517 | enum phy_state old_state = phydev->state; |
323fe43c | 1518 | const void *func = NULL; |
a68a8138 | 1519 | bool finished = false; |
00db8189 AF |
1520 | int err = 0; |
1521 | ||
e109374f FF |
1522 | switch (phydev->state) { |
1523 | case PHY_DOWN: | |
e109374f | 1524 | case PHY_READY: |
e109374f FF |
1525 | break; |
1526 | case PHY_UP: | |
8635c066 | 1527 | state_work = PHY_STATE_WORK_ANEG; |
e109374f FF |
1528 | break; |
1529 | case PHY_NOLINK: | |
c8e977ba | 1530 | case PHY_RUNNING: |
c8e977ba | 1531 | err = phy_check_link_status(phydev); |
323fe43c | 1532 | func = &phy_check_link_status; |
f2bc1c26 OR |
1533 | |
1534 | if (!err) | |
1535 | err = phy_update_stats(phydev); | |
e109374f | 1536 | break; |
a68a8138 AL |
1537 | case PHY_CABLETEST: |
1538 | err = phydev->drv->cable_test_get_status(phydev, &finished); | |
1539 | if (err) { | |
1540 | phy_abort_cable_test(phydev); | |
4a459bdc | 1541 | netif_testing_off(dev); |
8635c066 | 1542 | state_work = PHY_STATE_WORK_ANEG; |
a68a8138 AL |
1543 | phydev->state = PHY_UP; |
1544 | break; | |
1545 | } | |
1546 | ||
1547 | if (finished) { | |
1dd3f212 | 1548 | ethnl_cable_test_finished(phydev); |
4a459bdc | 1549 | netif_testing_off(dev); |
8635c066 | 1550 | state_work = PHY_STATE_WORK_ANEG; |
a68a8138 AL |
1551 | phydev->state = PHY_UP; |
1552 | } | |
1553 | break; | |
e109374f | 1554 | case PHY_HALTED: |
59088b5a | 1555 | case PHY_ERROR: |
e109374f FF |
1556 | if (phydev->link) { |
1557 | phydev->link = 0; | |
a307593a | 1558 | phy_link_down(phydev); |
e109374f | 1559 | } |
8635c066 | 1560 | state_work = PHY_STATE_WORK_SUSPEND; |
e109374f | 1561 | break; |
00db8189 AF |
1562 | } |
1563 | ||
8635c066 | 1564 | if (state_work == PHY_STATE_WORK_ANEG) { |
ea5968cd RKO |
1565 | err = _phy_start_aneg(phydev); |
1566 | func = &_phy_start_aneg; | |
1567 | } | |
1568 | ||
8635c066 RKO |
1569 | if (err == -ENODEV) |
1570 | return state_work; | |
06edf1a9 | 1571 | |
00db8189 | 1572 | if (err < 0) |
323fe43c | 1573 | phy_error_precise(phydev, func, err); |
00db8189 | 1574 | |
4203d840 | 1575 | phy_process_state_change(phydev, old_state); |
3e2186e0 | 1576 | |
d5c3d846 | 1577 | /* Only re-schedule a PHY state machine change if we are polling the |
93e8990c | 1578 | * PHY, if PHY_MAC_INTERRUPT is set, then we will be moving |
075ddebc HK |
1579 | * between states from phy_mac_interrupt(). |
1580 | * | |
1581 | * In state PHY_HALTED the PHY gets suspended, so rescheduling the | |
1582 | * state machine would be pointless and possibly error prone when | |
1583 | * called from phy_disconnect() synchronously. | |
d5c3d846 | 1584 | */ |
2b3e88ea | 1585 | if (phy_polling_mode(phydev) && phy_is_started(phydev)) |
8bf47e4d OR |
1586 | phy_queue_state_machine(phydev, |
1587 | phy_get_next_update_time(phydev)); | |
6e19b350 | 1588 | |
8635c066 RKO |
1589 | return state_work; |
1590 | } | |
1591 | ||
1592 | /* unlocked part of the PHY state machine */ | |
1593 | static void _phy_state_machine_post_work(struct phy_device *phydev, | |
1594 | enum phy_state_work state_work) | |
1595 | { | |
1596 | if (state_work == PHY_STATE_WORK_SUSPEND) | |
6e19b350 | 1597 | phy_suspend(phydev); |
35b5f6b1 | 1598 | } |
a59a4d19 | 1599 | |
8635c066 RKO |
1600 | /** |
1601 | * phy_state_machine - Handle the state machine | |
1602 | * @work: work_struct that describes the work to be done | |
1603 | */ | |
1604 | void phy_state_machine(struct work_struct *work) | |
1605 | { | |
1606 | struct delayed_work *dwork = to_delayed_work(work); | |
1607 | struct phy_device *phydev = | |
1608 | container_of(dwork, struct phy_device, state_queue); | |
1609 | enum phy_state_work state_work; | |
1610 | ||
1611 | mutex_lock(&phydev->lock); | |
1612 | state_work = _phy_state_machine(phydev); | |
1613 | mutex_unlock(&phydev->lock); | |
1614 | ||
1615 | _phy_state_machine_post_work(phydev, state_work); | |
1616 | } | |
1617 | ||
c398ef41 RKO |
1618 | /** |
1619 | * phy_stop - Bring down the PHY link, and stop checking the status | |
1620 | * @phydev: target phy_device struct | |
1621 | */ | |
1622 | void phy_stop(struct phy_device *phydev) | |
1623 | { | |
1624 | struct net_device *dev = phydev->attached_dev; | |
adcbb855 | 1625 | enum phy_state_work state_work; |
c398ef41 RKO |
1626 | enum phy_state old_state; |
1627 | ||
1628 | if (!phy_is_started(phydev) && phydev->state != PHY_DOWN && | |
1629 | phydev->state != PHY_ERROR) { | |
1630 | WARN(1, "called from state %s\n", | |
1631 | phy_state_to_str(phydev->state)); | |
1632 | return; | |
1633 | } | |
1634 | ||
1635 | mutex_lock(&phydev->lock); | |
1636 | old_state = phydev->state; | |
1637 | ||
1638 | if (phydev->state == PHY_CABLETEST) { | |
1639 | phy_abort_cable_test(phydev); | |
1640 | netif_testing_off(dev); | |
1641 | } | |
1642 | ||
1643 | if (phydev->sfp_bus) | |
1644 | sfp_upstream_stop(phydev->sfp_bus); | |
1645 | ||
1646 | phydev->state = PHY_HALTED; | |
1647 | phy_process_state_change(phydev, old_state); | |
1648 | ||
adcbb855 | 1649 | state_work = _phy_state_machine(phydev); |
c398ef41 RKO |
1650 | mutex_unlock(&phydev->lock); |
1651 | ||
adcbb855 | 1652 | _phy_state_machine_post_work(phydev, state_work); |
c398ef41 RKO |
1653 | phy_stop_machine(phydev); |
1654 | ||
1655 | /* Cannot call flush_scheduled_work() here as desired because | |
1656 | * of rtnl_lock(), but PHY_HALTED shall guarantee irq handler | |
1657 | * will not reenable interrupts. | |
1658 | */ | |
1659 | } | |
1660 | EXPORT_SYMBOL(phy_stop); | |
1661 | ||
1662 | /** | |
1663 | * phy_start - start or restart a PHY device | |
1664 | * @phydev: target phy_device struct | |
1665 | * | |
1666 | * Description: Indicates the attached device's readiness to | |
1667 | * handle PHY-related work. Used during startup to start the | |
1668 | * PHY, and after a call to phy_stop() to resume operation. | |
1669 | * Also used to indicate the MDIO bus has cleared an error | |
1670 | * condition. | |
1671 | */ | |
1672 | void phy_start(struct phy_device *phydev) | |
1673 | { | |
1674 | mutex_lock(&phydev->lock); | |
1675 | ||
1676 | if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) { | |
1677 | WARN(1, "called from state %s\n", | |
1678 | phy_state_to_str(phydev->state)); | |
1679 | goto out; | |
1680 | } | |
1681 | ||
1682 | if (phydev->sfp_bus) | |
1683 | sfp_upstream_start(phydev->sfp_bus); | |
1684 | ||
1685 | /* if phy was suspended, bring the physical link up again */ | |
1686 | __phy_resume(phydev); | |
1687 | ||
1688 | phydev->state = PHY_UP; | |
1689 | ||
1690 | phy_start_machine(phydev); | |
1691 | out: | |
1692 | mutex_unlock(&phydev->lock); | |
1693 | } | |
1694 | EXPORT_SYMBOL(phy_start); | |
1695 | ||
664fcf12 AL |
1696 | /** |
1697 | * phy_mac_interrupt - MAC says the link has changed | |
1698 | * @phydev: phy_device struct with changed link | |
664fcf12 | 1699 | * |
28b2e0d2 HK |
1700 | * The MAC layer is able to indicate there has been a change in the PHY link |
1701 | * status. Trigger the state machine and work a work queue. | |
664fcf12 | 1702 | */ |
28b2e0d2 | 1703 | void phy_mac_interrupt(struct phy_device *phydev) |
5ea94e76 | 1704 | { |
deccd16f | 1705 | /* Trigger a state machine change */ |
d73a2156 | 1706 | phy_trigger_machine(phydev); |
5ea94e76 FF |
1707 | } |
1708 | EXPORT_SYMBOL(phy_mac_interrupt); | |
1709 | ||
0d60fd50 GE |
1710 | /** |
1711 | * phy_loopback - Configure loopback mode of PHY | |
1712 | * @phydev: target phy_device struct | |
1713 | * @enable: enable or disable loopback mode | |
1714 | * @speed: enable loopback mode with speed | |
1715 | * | |
1716 | * Configure loopback mode of PHY and signal link down and link up if speed is | |
1717 | * changing. | |
1718 | * | |
1719 | * Return: 0 on success, negative error code on failure. | |
1720 | */ | |
1721 | int phy_loopback(struct phy_device *phydev, bool enable, int speed) | |
1722 | { | |
1723 | bool link_up = false; | |
1724 | int ret = 0; | |
1725 | ||
1726 | if (!phydev->drv) | |
1727 | return -EIO; | |
1728 | ||
1729 | mutex_lock(&phydev->lock); | |
1730 | ||
1731 | if (enable && phydev->loopback_enabled) { | |
1732 | ret = -EBUSY; | |
1733 | goto out; | |
1734 | } | |
1735 | ||
1736 | if (!enable && !phydev->loopback_enabled) { | |
1737 | ret = -EINVAL; | |
1738 | goto out; | |
1739 | } | |
1740 | ||
1741 | if (enable) { | |
1742 | /* | |
1743 | * Link up is signaled with a defined speed. If speed changes, | |
1744 | * then first link down and after that link up needs to be | |
1745 | * signaled. | |
1746 | */ | |
1747 | if (phydev->link && phydev->state == PHY_RUNNING) { | |
1748 | /* link is up and signaled */ | |
1749 | if (speed && phydev->speed != speed) { | |
1750 | /* signal link down and up for new speed */ | |
1751 | phydev->link = false; | |
1752 | phydev->state = PHY_NOLINK; | |
1753 | phy_link_down(phydev); | |
1754 | ||
1755 | link_up = true; | |
1756 | } | |
1757 | } else { | |
1758 | /* link is not signaled */ | |
1759 | if (speed) { | |
1760 | /* signal link up for new speed */ | |
1761 | link_up = true; | |
1762 | } | |
1763 | } | |
1764 | } | |
1765 | ||
1766 | if (phydev->drv->set_loopback) | |
1767 | ret = phydev->drv->set_loopback(phydev, enable, speed); | |
1768 | else | |
1769 | ret = genphy_loopback(phydev, enable, speed); | |
1770 | ||
1771 | if (ret) { | |
1772 | if (enable) { | |
1773 | /* try to restore link if enabling loopback fails */ | |
1774 | if (phydev->drv->set_loopback) | |
1775 | phydev->drv->set_loopback(phydev, false, 0); | |
1776 | else | |
1777 | genphy_loopback(phydev, false, 0); | |
1778 | } | |
1779 | ||
1780 | goto out; | |
1781 | } | |
1782 | ||
1783 | if (link_up) { | |
1784 | phydev->link = true; | |
1785 | phydev->state = PHY_RUNNING; | |
1786 | phy_link_up(phydev); | |
1787 | } | |
1788 | ||
1789 | phydev->loopback_enabled = enable; | |
1790 | ||
1791 | out: | |
1792 | mutex_unlock(&phydev->lock); | |
1793 | return ret; | |
1794 | } | |
1795 | EXPORT_SYMBOL(phy_loopback); | |
1796 | ||
a00e0d34 RKO |
1797 | /** |
1798 | * phy_eee_tx_clock_stop_capable() - indicate whether the MAC can stop tx clock | |
1799 | * @phydev: target phy_device struct | |
1800 | * | |
1801 | * Indicate whether the MAC can disable the transmit xMII clock while in LPI | |
1802 | * state. Returns 1 if the MAC may stop the transmit clock, 0 if the MAC must | |
1803 | * not stop the transmit clock, or negative error. | |
1804 | */ | |
1805 | int phy_eee_tx_clock_stop_capable(struct phy_device *phydev) | |
1806 | { | |
1807 | int stat1; | |
1808 | ||
1809 | stat1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1); | |
1810 | if (stat1 < 0) | |
1811 | return stat1; | |
1812 | ||
1813 | return !!(stat1 & MDIO_PCS_STAT1_CLKSTOP_CAP); | |
1814 | } | |
1815 | EXPORT_SYMBOL_GPL(phy_eee_tx_clock_stop_capable); | |
1816 | ||
cf337105 RKO |
1817 | /** |
1818 | * phy_eee_rx_clock_stop() - configure PHY receive clock in LPI | |
1819 | * @phydev: target phy_device struct | |
1820 | * @clk_stop_enable: flag to indicate whether the clock can be stopped | |
1821 | * | |
1822 | * Configure whether the PHY can disable its receive clock during LPI mode, | |
1823 | * See IEEE 802.3 sections 22.2.2.2, 35.2.2.10, and 45.2.3.1.4. | |
1824 | * | |
1825 | * Returns: 0 or negative error. | |
1826 | */ | |
1827 | int phy_eee_rx_clock_stop(struct phy_device *phydev, bool clk_stop_enable) | |
1828 | { | |
1829 | /* Configure the PHY to stop receiving xMII | |
1830 | * clock while it is signaling LPI. | |
1831 | */ | |
1832 | return phy_modify_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, | |
1833 | MDIO_PCS_CTRL1_CLKSTOP_EN, | |
1834 | clk_stop_enable ? MDIO_PCS_CTRL1_CLKSTOP_EN : 0); | |
1835 | } | |
1836 | EXPORT_SYMBOL_GPL(phy_eee_rx_clock_stop); | |
1837 | ||
a59a4d19 GC |
1838 | /** |
1839 | * phy_init_eee - init and check the EEE feature | |
1840 | * @phydev: target phy_device struct | |
1841 | * @clk_stop_enable: PHY may stop the clock during LPI | |
1842 | * | |
1843 | * Description: it checks if the Energy-Efficient Ethernet (EEE) | |
1844 | * is supported by looking at the MMD registers 3.20 and 7.60/61 | |
1845 | * and it programs the MMD register 3.0 setting the "Clock stop enable" | |
1846 | * bit if required. | |
1847 | */ | |
1848 | int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) | |
1849 | { | |
6340f9fd OR |
1850 | int ret; |
1851 | ||
25149ef9 FF |
1852 | if (!phydev->drv) |
1853 | return -EIO; | |
1854 | ||
809265fe | 1855 | ret = genphy_c45_eee_is_active(phydev, NULL); |
6340f9fd OR |
1856 | if (ret < 0) |
1857 | return ret; | |
1858 | if (!ret) | |
1859 | return -EPROTONOSUPPORT; | |
a59a4d19 | 1860 | |
6340f9fd | 1861 | if (clk_stop_enable) |
cf337105 | 1862 | ret = phy_eee_rx_clock_stop(phydev, true); |
a59a4d19 | 1863 | |
6340f9fd | 1864 | return ret < 0 ? ret : 0; |
a59a4d19 GC |
1865 | } |
1866 | EXPORT_SYMBOL(phy_init_eee); | |
1867 | ||
1868 | /** | |
1869 | * phy_get_eee_err - report the EEE wake error count | |
1870 | * @phydev: target phy_device struct | |
1871 | * | |
1872 | * Description: it is to report the number of time where the PHY | |
1873 | * failed to complete its normal wake sequence. | |
1874 | */ | |
1875 | int phy_get_eee_err(struct phy_device *phydev) | |
1876 | { | |
2f987d48 AL |
1877 | int ret; |
1878 | ||
25149ef9 FF |
1879 | if (!phydev->drv) |
1880 | return -EIO; | |
1881 | ||
2f987d48 AL |
1882 | mutex_lock(&phydev->lock); |
1883 | ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_WK_ERR); | |
1884 | mutex_unlock(&phydev->lock); | |
1885 | ||
1886 | return ret; | |
a59a4d19 GC |
1887 | } |
1888 | EXPORT_SYMBOL(phy_get_eee_err); | |
1889 | ||
1890 | /** | |
1891 | * phy_ethtool_get_eee - get EEE supported and status | |
1892 | * @phydev: target phy_device struct | |
d80a5233 | 1893 | * @data: ethtool_keee data |
a59a4d19 | 1894 | * |
f899c594 RKO |
1895 | * Description: get the current EEE settings, filling in all members of |
1896 | * @data. | |
a59a4d19 | 1897 | */ |
d80a5233 | 1898 | int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data) |
a59a4d19 | 1899 | { |
2f987d48 AL |
1900 | int ret; |
1901 | ||
25149ef9 FF |
1902 | if (!phydev->drv) |
1903 | return -EIO; | |
1904 | ||
2f987d48 AL |
1905 | mutex_lock(&phydev->lock); |
1906 | ret = genphy_c45_ethtool_get_eee(phydev, data); | |
fe0d4fd9 | 1907 | eeecfg_to_eee(data, &phydev->eee_cfg); |
2f987d48 AL |
1908 | mutex_unlock(&phydev->lock); |
1909 | ||
1910 | return ret; | |
a59a4d19 GC |
1911 | } |
1912 | EXPORT_SYMBOL(phy_ethtool_get_eee); | |
1913 | ||
3e43b903 AL |
1914 | /** |
1915 | * phy_ethtool_set_eee_noneg - Adjusts MAC LPI configuration without PHY | |
1916 | * renegotiation | |
1917 | * @phydev: pointer to the target PHY device structure | |
f26a29a0 | 1918 | * @old_cfg: pointer to the eee_config structure containing the old EEE settings |
3e43b903 AL |
1919 | * |
1920 | * This function updates the Energy Efficient Ethernet (EEE) configuration | |
1921 | * for cases where only the MAC's Low Power Idle (LPI) configuration changes, | |
1922 | * without triggering PHY renegotiation. It ensures that the MAC is properly | |
1923 | * informed of the new LPI settings by cycling the link down and up, which | |
1924 | * is necessary for the MAC to adopt the new configuration. This adjustment | |
1925 | * is done only if there is a change in the tx_lpi_enabled or tx_lpi_timer | |
1926 | * configuration. | |
1927 | */ | |
1928 | static void phy_ethtool_set_eee_noneg(struct phy_device *phydev, | |
f26a29a0 | 1929 | const struct eee_config *old_cfg) |
3e43b903 | 1930 | { |
e2668c34 RKO |
1931 | bool enable_tx_lpi; |
1932 | ||
1933 | if (!phydev->link) | |
1934 | return; | |
1935 | ||
1936 | enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled && phydev->eee_active; | |
1937 | ||
1938 | if (phydev->enable_tx_lpi != enable_tx_lpi || | |
f26a29a0 | 1939 | phydev->eee_cfg.tx_lpi_timer != old_cfg->tx_lpi_timer) { |
e2668c34 RKO |
1940 | phydev->enable_tx_lpi = false; |
1941 | phydev->link = false; | |
1942 | phy_link_down(phydev); | |
1943 | phydev->enable_tx_lpi = enable_tx_lpi; | |
1944 | phydev->link = true; | |
1945 | phy_link_up(phydev); | |
3e43b903 AL |
1946 | } |
1947 | } | |
1948 | ||
a59a4d19 GC |
1949 | /** |
1950 | * phy_ethtool_set_eee - set EEE supported and status | |
1951 | * @phydev: target phy_device struct | |
d80a5233 | 1952 | * @data: ethtool_keee data |
a59a4d19 GC |
1953 | * |
1954 | * Description: it is to program the Advertisement EEE register. | |
1955 | */ | |
d80a5233 | 1956 | int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data) |
a59a4d19 | 1957 | { |
f26a29a0 | 1958 | struct eee_config old_cfg; |
2f987d48 AL |
1959 | int ret; |
1960 | ||
25149ef9 FF |
1961 | if (!phydev->drv) |
1962 | return -EIO; | |
1963 | ||
2f987d48 | 1964 | mutex_lock(&phydev->lock); |
f26a29a0 HK |
1965 | |
1966 | old_cfg = phydev->eee_cfg; | |
1967 | eee_to_eeecfg(&phydev->eee_cfg, data); | |
1968 | ||
2f987d48 | 1969 | ret = genphy_c45_ethtool_set_eee(phydev, data); |
f26a29a0 HK |
1970 | if (ret == 0) |
1971 | phy_ethtool_set_eee_noneg(phydev, &old_cfg); | |
1972 | else if (ret < 0) | |
1973 | phydev->eee_cfg = old_cfg; | |
1974 | ||
2f987d48 AL |
1975 | mutex_unlock(&phydev->lock); |
1976 | ||
3e43b903 | 1977 | return ret < 0 ? ret : 0; |
a59a4d19 GC |
1978 | } |
1979 | EXPORT_SYMBOL(phy_ethtool_set_eee); | |
42e836eb | 1980 | |
4069a572 AL |
1981 | /** |
1982 | * phy_ethtool_set_wol - Configure Wake On LAN | |
1983 | * | |
1984 | * @phydev: target phy_device struct | |
1985 | * @wol: Configuration requested | |
1986 | */ | |
42e836eb MS |
1987 | int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) |
1988 | { | |
2f987d48 AL |
1989 | int ret; |
1990 | ||
1991 | if (phydev->drv && phydev->drv->set_wol) { | |
1992 | mutex_lock(&phydev->lock); | |
1993 | ret = phydev->drv->set_wol(phydev, wol); | |
1994 | mutex_unlock(&phydev->lock); | |
1995 | ||
1996 | return ret; | |
1997 | } | |
42e836eb MS |
1998 | |
1999 | return -EOPNOTSUPP; | |
2000 | } | |
2001 | EXPORT_SYMBOL(phy_ethtool_set_wol); | |
2002 | ||
4069a572 AL |
2003 | /** |
2004 | * phy_ethtool_get_wol - Get the current Wake On LAN configuration | |
2005 | * | |
2006 | * @phydev: target phy_device struct | |
2007 | * @wol: Store the current configuration here | |
2008 | */ | |
42e836eb MS |
2009 | void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) |
2010 | { | |
2f987d48 AL |
2011 | if (phydev->drv && phydev->drv->get_wol) { |
2012 | mutex_lock(&phydev->lock); | |
42e836eb | 2013 | phydev->drv->get_wol(phydev, wol); |
2f987d48 AL |
2014 | mutex_unlock(&phydev->lock); |
2015 | } | |
42e836eb MS |
2016 | } |
2017 | EXPORT_SYMBOL(phy_ethtool_get_wol); | |
9d9a77ce PR |
2018 | |
2019 | int phy_ethtool_get_link_ksettings(struct net_device *ndev, | |
2020 | struct ethtool_link_ksettings *cmd) | |
2021 | { | |
2022 | struct phy_device *phydev = ndev->phydev; | |
2023 | ||
2024 | if (!phydev) | |
2025 | return -ENODEV; | |
2026 | ||
5514174f | 2027 | phy_ethtool_ksettings_get(phydev, cmd); |
2028 | ||
2029 | return 0; | |
9d9a77ce PR |
2030 | } |
2031 | EXPORT_SYMBOL(phy_ethtool_get_link_ksettings); | |
2032 | ||
2033 | int phy_ethtool_set_link_ksettings(struct net_device *ndev, | |
2034 | const struct ethtool_link_ksettings *cmd) | |
2035 | { | |
2036 | struct phy_device *phydev = ndev->phydev; | |
2037 | ||
2038 | if (!phydev) | |
2039 | return -ENODEV; | |
2040 | ||
2041 | return phy_ethtool_ksettings_set(phydev, cmd); | |
2042 | } | |
2043 | EXPORT_SYMBOL(phy_ethtool_set_link_ksettings); | |
e86a8987 | 2044 | |
4069a572 AL |
2045 | /** |
2046 | * phy_ethtool_nway_reset - Restart auto negotiation | |
2047 | * @ndev: Network device to restart autoneg for | |
2048 | */ | |
e86a8987 FF |
2049 | int phy_ethtool_nway_reset(struct net_device *ndev) |
2050 | { | |
2051 | struct phy_device *phydev = ndev->phydev; | |
2f987d48 | 2052 | int ret; |
e86a8987 FF |
2053 | |
2054 | if (!phydev) | |
2055 | return -ENODEV; | |
2056 | ||
25149ef9 FF |
2057 | if (!phydev->drv) |
2058 | return -EIO; | |
2059 | ||
2f987d48 AL |
2060 | mutex_lock(&phydev->lock); |
2061 | ret = phy_restart_aneg(phydev); | |
2062 | mutex_unlock(&phydev->lock); | |
2063 | ||
2064 | return ret; | |
e86a8987 FF |
2065 | } |
2066 | EXPORT_SYMBOL(phy_ethtool_nway_reset); |