^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Framework for configuring and reading PHY devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Based on code in sungem_phy.c and gianfar_phy.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Andy Fleming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2004 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2006, 2007 Maciej W. Rozycki
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/ethtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/ethtool_netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/phy_led_triggers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/sfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <net/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define PHY_STATE_TIME HZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define PHY_STATE_STR(_state) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) case PHY_##_state: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return __stringify(_state); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const char *phy_state_to_str(enum phy_state st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) switch (st) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) PHY_STATE_STR(DOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) PHY_STATE_STR(READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) PHY_STATE_STR(UP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) PHY_STATE_STR(RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) PHY_STATE_STR(NOLINK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) PHY_STATE_STR(CABLETEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) PHY_STATE_STR(HALTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static void phy_link_up(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) phydev->phy_link_change(phydev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) phy_led_trigger_change_speed(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static void phy_link_down(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) phydev->phy_link_change(phydev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) phy_led_trigger_change_speed(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static const char *phy_pause_str(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) bool local_pause, local_asym_pause;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (phydev->autoneg == AUTONEG_DISABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) goto no_pause;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) local_pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) local_asym_pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (local_pause && phydev->pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return "rx/tx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (local_asym_pause && phydev->asym_pause) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (local_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return "rx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (phydev->pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return "tx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) no_pause:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return "off";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * phy_print_status - Convenience function to print out the current phy status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) void phy_print_status(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (phydev->link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) netdev_info(phydev->attached_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) "Link is Up - %s/%s %s- flow control %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) phy_speed_to_str(phydev->speed),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) phy_duplex_to_str(phydev->duplex),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) phydev->downshifted_rate ? "(downshifted) " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) phy_pause_str(phydev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) netdev_info(phydev->attached_dev, "Link is Down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) EXPORT_SYMBOL(phy_print_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * phy_clear_interrupt - Ack the phy device's interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * If the @phydev driver has an ack_interrupt function, call it to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * ack and clear the phy device's interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Returns 0 on success or < 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int phy_clear_interrupt(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (phydev->drv->ack_interrupt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return phydev->drv->ack_interrupt(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * phy_config_interrupt - configure the PHY device for the requested interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * @interrupts: interrupt flags to configure for this @phydev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * Returns 0 on success or < 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int phy_config_interrupt(struct phy_device *phydev, bool interrupts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) phydev->interrupts = interrupts ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (phydev->drv->config_intr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return phydev->drv->config_intr(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * phy_restart_aneg - restart auto-negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Restart the autonegotiation on @phydev. Returns >= 0 on success or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * negative errno on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int phy_restart_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ret = genphy_c45_restart_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ret = genphy_restart_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) EXPORT_SYMBOL_GPL(phy_restart_aneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * phy_aneg_done - return auto-negotiation status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * Description: Return the auto-negotiation status from this @phydev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * Returns > 0 on success or < 0 on error. 0 means that auto-negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * is still pending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int phy_aneg_done(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (phydev->drv && phydev->drv->aneg_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return phydev->drv->aneg_done(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) else if (phydev->is_c45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return genphy_c45_aneg_done(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return genphy_aneg_done(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) EXPORT_SYMBOL(phy_aneg_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * phy_find_valid - find a PHY setting that matches the requested parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * @speed: desired speed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * @duplex: desired duplex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * @supported: mask of supported link modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * Locate a supported phy setting that is, in priority order:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * - an exact match for the specified speed and duplex mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * - a match for the specified speed, or slower speed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * - the slowest supported speed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * Returns the matched phy_setting entry, or %NULL if no supported phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * settings were found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static const struct phy_setting *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) phy_find_valid(int speed, int duplex, unsigned long *supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return phy_lookup_setting(speed, duplex, supported, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * phy_supported_speeds - return all speeds currently supported by a phy device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @phy: The phy device to return supported speeds of.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @speeds: buffer to store supported speeds in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * @size: size of speeds buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * Description: Returns the number of supported speeds, and fills the speeds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * buffer with the supported speeds. If speeds buffer is too small to contain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * all currently supported speeds, will return as many speeds as can fit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) unsigned int phy_supported_speeds(struct phy_device *phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) unsigned int *speeds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return phy_speeds(speeds, size, phy->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * phy_check_valid - check if there is a valid PHY setting which matches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * speed, duplex, and feature mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * @speed: speed to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * @duplex: duplex to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * @features: A mask of the valid settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * Description: Returns true if there is a valid setting, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static inline bool phy_check_valid(int speed, int duplex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) unsigned long *features)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return !!phy_lookup_setting(speed, duplex, features, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * phy_sanitize_settings - make sure the PHY is set to supported speed and duplex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * @phydev: the target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * Description: Make sure the PHY is set to supported speeds and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * duplexes. Drop down by one in this order: 1000/FULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static void phy_sanitize_settings(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) const struct phy_setting *setting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) setting = phy_find_valid(phydev->speed, phydev->duplex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (setting) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) phydev->speed = setting->speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) phydev->duplex = setting->duplex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* We failed to find anything (no supported speeds?) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) phydev->speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) phydev->duplex = DUPLEX_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) void phy_ethtool_ksettings_get(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct ethtool_link_ksettings *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) linkmode_copy(cmd->link_modes.supported, phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) linkmode_copy(cmd->link_modes.advertising, phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) linkmode_copy(cmd->link_modes.lp_advertising, phydev->lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) cmd->base.speed = phydev->speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) cmd->base.duplex = phydev->duplex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) cmd->base.master_slave_cfg = phydev->master_slave_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) cmd->base.master_slave_state = phydev->master_slave_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (phydev->interface == PHY_INTERFACE_MODE_MOCA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) cmd->base.port = PORT_BNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) cmd->base.port = phydev->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) cmd->base.transceiver = phy_is_internal(phydev) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) XCVR_INTERNAL : XCVR_EXTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) cmd->base.phy_address = phydev->mdio.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) cmd->base.autoneg = phydev->autoneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) cmd->base.eth_tp_mdix_ctrl = phydev->mdix_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) cmd->base.eth_tp_mdix = phydev->mdix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) EXPORT_SYMBOL(phy_ethtool_ksettings_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * phy_mii_ioctl - generic PHY MII ioctl interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * @ifr: &struct ifreq for socket ioctl's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * @cmd: ioctl cmd to execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * Note that this function is currently incompatible with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * PHYCONTROL layer. It changes registers without regard to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * current state. Use at own risk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct mii_ioctl_data *mii_data = if_mii(ifr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u16 val = mii_data->val_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) bool change_autoneg = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int prtad, devad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case SIOCGMIIPHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) mii_data->phy_id = phydev->mdio.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) case SIOCGMIIREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (mdio_phy_id_is_c45(mii_data->phy_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) prtad = mdio_phy_id_prtad(mii_data->phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) devad = mdio_phy_id_devad(mii_data->phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) devad = mdiobus_c45_addr(devad, mii_data->reg_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) prtad = mii_data->phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) devad = mii_data->reg_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) mii_data->val_out = mdiobus_read(phydev->mdio.bus, prtad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) devad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) case SIOCSMIIREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (mdio_phy_id_is_c45(mii_data->phy_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) prtad = mdio_phy_id_prtad(mii_data->phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) devad = mdio_phy_id_devad(mii_data->phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) devad = mdiobus_c45_addr(devad, mii_data->reg_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) prtad = mii_data->phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) devad = mii_data->reg_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (prtad == phydev->mdio.addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) switch (devad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case MII_BMCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if ((val & (BMCR_RESET | BMCR_ANENABLE)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (phydev->autoneg == AUTONEG_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) change_autoneg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) phydev->autoneg = AUTONEG_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (val & BMCR_FULLDPLX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) phydev->duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) phydev->duplex = DUPLEX_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (val & BMCR_SPEED1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) phydev->speed = SPEED_1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) else if (val & BMCR_SPEED100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) phydev->speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) else phydev->speed = SPEED_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (phydev->autoneg == AUTONEG_DISABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) change_autoneg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) phydev->autoneg = AUTONEG_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) case MII_ADVERTISE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) mii_adv_mod_linkmode_adv_t(phydev->advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) change_autoneg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) case MII_CTRL1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) mii_ctrl1000_mod_linkmode_adv_t(phydev->advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) change_autoneg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) mdiobus_write(phydev->mdio.bus, prtad, devad, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (prtad == phydev->mdio.addr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) devad == MII_BMCR &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) val & BMCR_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return phy_init_hw(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (change_autoneg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return phy_start_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case SIOCSHWTSTAMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (phydev->mii_ts && phydev->mii_ts->hwtstamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return phydev->mii_ts->hwtstamp(phydev->mii_ts, ifr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) EXPORT_SYMBOL(phy_mii_ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * phy_do_ioctl - generic ndo_do_ioctl implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * @dev: the net_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * @ifr: &struct ifreq for socket ioctl's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * @cmd: ioctl cmd to execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int phy_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (!dev->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return phy_mii_ioctl(dev->phydev, ifr, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) EXPORT_SYMBOL(phy_do_ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * phy_do_ioctl_running - generic ndo_do_ioctl implementation but test first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * @dev: the net_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * @ifr: &struct ifreq for socket ioctl's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * @cmd: ioctl cmd to execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * Same as phy_do_ioctl, but ensures that net_device is running before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * handling the ioctl.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int phy_do_ioctl_running(struct net_device *dev, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!netif_running(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return phy_do_ioctl(dev, ifr, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) EXPORT_SYMBOL(phy_do_ioctl_running);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * phy_queue_state_machine - Trigger the state machine to run soon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * @jiffies: Run the state machine after these jiffies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) void phy_queue_state_machine(struct phy_device *phydev, unsigned long jiffies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) mod_delayed_work(system_power_efficient_wq, &phydev->state_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) EXPORT_SYMBOL(phy_queue_state_machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * phy_queue_state_machine - Trigger the state machine to run now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static void phy_trigger_machine(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) phy_queue_state_machine(phydev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) static void phy_abort_cable_test(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ethnl_cable_test_finished(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) err = phy_init_hw(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) phydev_err(phydev, "Error while aborting cable test");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * phy_ethtool_get_strings - Get the statistic counter names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * @data: Where to put the strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int phy_ethtool_get_strings(struct phy_device *phydev, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!phydev->drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) phydev->drv->get_strings(phydev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) EXPORT_SYMBOL(phy_ethtool_get_strings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * phy_ethtool_get_sset_count - Get the number of statistic counters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) int phy_ethtool_get_sset_count(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (!phydev->drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (phydev->drv->get_sset_count &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) phydev->drv->get_strings &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) phydev->drv->get_stats) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) ret = phydev->drv->get_sset_count(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) EXPORT_SYMBOL(phy_ethtool_get_sset_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * phy_ethtool_get_stats - Get the statistic counters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * @stats: What counters to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * @data: Where to store the counters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) int phy_ethtool_get_stats(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct ethtool_stats *stats, u64 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (!phydev->drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) phydev->drv->get_stats(phydev, stats, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) EXPORT_SYMBOL(phy_ethtool_get_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * phy_start_cable_test - Start a cable test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * @extack: extack for reporting useful error messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) int phy_start_cable_test(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct net_device *dev = phydev->attached_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (!(phydev->drv &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) phydev->drv->cable_test_start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) phydev->drv->cable_test_get_status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) NL_SET_ERR_MSG(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) "PHY driver does not support cable testing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (phydev->state == PHY_CABLETEST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) NL_SET_ERR_MSG(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) "PHY already performing a test");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (phydev->state < PHY_UP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) phydev->state > PHY_CABLETEST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) NL_SET_ERR_MSG(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) "PHY not configured. Try setting interface up");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) err = ethnl_cable_test_alloc(phydev, ETHTOOL_MSG_CABLE_TEST_NTF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* Mark the carrier down until the test is complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) phy_link_down(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) netif_testing_on(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) err = phydev->drv->cable_test_start(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) netif_testing_off(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) phy_link_up(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) phydev->state = PHY_CABLETEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (phy_polling_mode(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) phy_trigger_machine(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) ethnl_cable_test_free(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) EXPORT_SYMBOL(phy_start_cable_test);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * phy_start_cable_test_tdr - Start a raw TDR cable test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * @extack: extack for reporting useful error messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * @config: Configuration of the test to run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int phy_start_cable_test_tdr(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct netlink_ext_ack *extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) const struct phy_tdr_config *config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct net_device *dev = phydev->attached_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (!(phydev->drv &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) phydev->drv->cable_test_tdr_start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) phydev->drv->cable_test_get_status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) NL_SET_ERR_MSG(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) "PHY driver does not support cable test TDR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (phydev->state == PHY_CABLETEST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) NL_SET_ERR_MSG(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) "PHY already performing a test");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (phydev->state < PHY_UP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) phydev->state > PHY_CABLETEST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) NL_SET_ERR_MSG(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) "PHY not configured. Try setting interface up");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) err = ethnl_cable_test_alloc(phydev, ETHTOOL_MSG_CABLE_TEST_TDR_NTF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) /* Mark the carrier down until the test is complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) phy_link_down(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) netif_testing_on(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) err = phydev->drv->cable_test_tdr_start(phydev, config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) netif_testing_off(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) phy_link_up(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) phydev->state = PHY_CABLETEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (phy_polling_mode(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) phy_trigger_machine(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) ethnl_cable_test_free(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) EXPORT_SYMBOL(phy_start_cable_test_tdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static int phy_config_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (phydev->drv->config_aneg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return phydev->drv->config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /* Clause 45 PHYs that don't implement Clause 22 registers are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * allowed to call genphy_config_aneg()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return genphy_c45_config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return genphy_config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * phy_check_link_status - check link status and set state accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * Description: Check for link and whether autoneg was triggered / is running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * and set state accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static int phy_check_link_status(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) WARN_ON(!mutex_is_locked(&phydev->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* Keep previous state if loopback is enabled because some PHYs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * report that Link is Down when loopback is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (phydev->loopback_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) err = phy_read_status(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (phydev->link && phydev->state != PHY_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) phy_check_downshift(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) phydev->state = PHY_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) phy_link_up(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) } else if (!phydev->link && phydev->state != PHY_NOLINK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) phydev->state = PHY_NOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) phy_link_down(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * _phy_start_aneg - start auto-negotiation for this PHY device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * Description: Sanitizes the settings (if we're not autonegotiating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * them), and then calls the driver's config_aneg function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * If the PHYCONTROL Layer is operating, we change the state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * reflect the beginning of Auto-negotiation or forcing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static int _phy_start_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) lockdep_assert_held(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (!phydev->drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (AUTONEG_DISABLE == phydev->autoneg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) phy_sanitize_settings(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) err = phy_config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (phy_is_started(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) err = phy_check_link_status(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * phy_start_aneg - start auto-negotiation for this PHY device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * Description: Sanitizes the settings (if we're not autonegotiating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * them), and then calls the driver's config_aneg function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * If the PHYCONTROL Layer is operating, we change the state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * reflect the beginning of Auto-negotiation or forcing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) int phy_start_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) err = _phy_start_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) EXPORT_SYMBOL(phy_start_aneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static int phy_poll_aneg_done(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) unsigned int retries = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ret = phy_aneg_done(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) } while (!ret && --retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return ret < 0 ? ret : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) int phy_ethtool_ksettings_set(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) const struct ethtool_link_ksettings *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) u8 autoneg = cmd->base.autoneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) u8 duplex = cmd->base.duplex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) u32 speed = cmd->base.speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (cmd->base.phy_address != phydev->mdio.addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) linkmode_copy(advertising, cmd->link_modes.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* We make sure that we don't pass unsupported values in to the PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) linkmode_and(advertising, advertising, phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /* Verify the settings we care about. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (autoneg != AUTONEG_ENABLE && autoneg != AUTONEG_DISABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (autoneg == AUTONEG_ENABLE && linkmode_empty(advertising))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (autoneg == AUTONEG_DISABLE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) ((speed != SPEED_1000 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) speed != SPEED_100 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) speed != SPEED_10) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) (duplex != DUPLEX_HALF &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) duplex != DUPLEX_FULL)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) phydev->autoneg = autoneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (autoneg == AUTONEG_DISABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) phydev->speed = speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) phydev->duplex = duplex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) linkmode_copy(phydev->advertising, advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) phydev->advertising, autoneg == AUTONEG_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) phydev->master_slave_set = cmd->base.master_slave_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /* Restart the PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (phy_is_started(phydev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) phydev->state = PHY_UP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) phy_trigger_machine(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) _phy_start_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) EXPORT_SYMBOL(phy_ethtool_ksettings_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * phy_speed_down - set speed to lowest speed supported by both link partners
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * @sync: perform action synchronously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * Description: Typically used to save energy when waiting for a WoL packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * WARNING: Setting sync to false may cause the system being unable to suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * in case the PHY generates an interrupt when finishing the autonegotiation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * This interrupt may wake up the system immediately after suspend.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * Therefore use sync = false only if you're sure it's safe with the respective
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * network chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) int phy_speed_down(struct phy_device *phydev, bool sync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (phydev->autoneg != AUTONEG_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) linkmode_copy(adv_tmp, phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) ret = phy_speed_down_core(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) linkmode_copy(phydev->adv_old, adv_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (linkmode_equal(phydev->advertising, adv_tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) ret = phy_config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return sync ? phy_poll_aneg_done(phydev) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) EXPORT_SYMBOL_GPL(phy_speed_down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * phy_speed_up - (re)set advertised speeds to all supported speeds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) * Description: Used to revert the effect of phy_speed_down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) int phy_speed_up(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (phydev->autoneg != AUTONEG_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (linkmode_empty(phydev->adv_old))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) linkmode_copy(adv_tmp, phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) linkmode_copy(phydev->advertising, phydev->adv_old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) linkmode_zero(phydev->adv_old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (linkmode_equal(phydev->advertising, adv_tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return phy_config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) EXPORT_SYMBOL_GPL(phy_speed_up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * phy_start_machine - start PHY state machine tracking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * @phydev: the phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * Description: The PHY infrastructure can run a state machine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * which tracks whether the PHY is starting up, negotiating,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * etc. This function starts the delayed workqueue which tracks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * the state of the PHY. If you want to maintain your own state machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * do not call this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) void phy_start_machine(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) phy_trigger_machine(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) EXPORT_SYMBOL_GPL(phy_start_machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * phy_stop_machine - stop the PHY state machine tracking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * Description: Stops the state machine delayed workqueue, sets the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) * state to UP (unless it wasn't up yet). This function must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) * called BEFORE phy_detach.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) void phy_stop_machine(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) cancel_delayed_work_sync(&phydev->state_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (phy_is_started(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) phydev->state = PHY_UP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) * phy_error - enter HALTED state for this PHY device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * Moves the PHY to the HALTED state in response to a read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) * or write error, and tells the controller the link is down.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) * Must not be called from interrupt context, or while the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * phydev->lock is held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static void phy_error(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) phydev->state = PHY_HALTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) phy_trigger_machine(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * phy_disable_interrupts - Disable the PHY interrupts from the PHY side
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) int phy_disable_interrupts(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) /* Disable PHY interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) /* Clear the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return phy_clear_interrupt(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * phy_interrupt - PHY interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) * @irq: interrupt line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) * @phy_dat: phy_device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * Description: Handle PHY interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) static irqreturn_t phy_interrupt(int irq, void *phy_dat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct phy_device *phydev = phy_dat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) struct phy_driver *drv = phydev->drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (drv->handle_interrupt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return drv->handle_interrupt(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (drv->did_interrupt && !drv->did_interrupt(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) /* reschedule state queue work to run as soon as possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) phy_trigger_machine(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /* did_interrupt() may have cleared the interrupt already */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (!drv->did_interrupt && phy_clear_interrupt(phydev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) phy_error(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * phy_enable_interrupts - Enable the interrupts from the PHY side
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static int phy_enable_interrupts(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) int err = phy_clear_interrupt(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * phy_request_interrupt - request and enable interrupt for a PHY device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * Description: Request and enable the interrupt for the given PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) * If this fails, then we set irq to PHY_POLL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) * This should only be called with a valid IRQ number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) void phy_request_interrupt(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) err = request_threaded_irq(phydev->irq, NULL, phy_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) IRQF_ONESHOT | IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) phydev_name(phydev), phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) phydev_warn(phydev, "Error %d requesting IRQ %d, falling back to polling\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) err, phydev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) phydev->irq = PHY_POLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (phy_enable_interrupts(phydev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) phydev_warn(phydev, "Can't enable interrupt, falling back to polling\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) phy_free_interrupt(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) phydev->irq = PHY_POLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) EXPORT_SYMBOL(phy_request_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * phy_free_interrupt - disable and free interrupt for a PHY device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * Description: Disable and free the interrupt for the given PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * This should only be called with a valid IRQ number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) void phy_free_interrupt(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) phy_disable_interrupts(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) free_irq(phydev->irq, phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) EXPORT_SYMBOL(phy_free_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) * phy_stop - Bring down the PHY link, and stop checking the status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) void phy_stop(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) struct net_device *dev = phydev->attached_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) WARN(1, "called from state %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) phy_state_to_str(phydev->state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (phydev->state == PHY_CABLETEST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) phy_abort_cable_test(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) netif_testing_off(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (phydev->sfp_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) sfp_upstream_stop(phydev->sfp_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) phydev->state = PHY_HALTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) phy_state_machine(&phydev->state_queue.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) phy_stop_machine(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) /* Cannot call flush_scheduled_work() here as desired because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) * of rtnl_lock(), but PHY_HALTED shall guarantee irq handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * will not reenable interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) EXPORT_SYMBOL(phy_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) * phy_start - start or restart a PHY device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * Description: Indicates the attached device's readiness to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * handle PHY-related work. Used during startup to start the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) * PHY, and after a call to phy_stop() to resume operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) * Also used to indicate the MDIO bus has cleared an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) void phy_start(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) WARN(1, "called from state %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) phy_state_to_str(phydev->state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (phydev->sfp_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) sfp_upstream_start(phydev->sfp_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) /* if phy was suspended, bring the physical link up again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) __phy_resume(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) phydev->state = PHY_UP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) phy_start_machine(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) EXPORT_SYMBOL(phy_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) * phy_state_machine - Handle the state machine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * @work: work_struct that describes the work to be done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) void phy_state_machine(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) struct delayed_work *dwork = to_delayed_work(work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) struct phy_device *phydev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) container_of(dwork, struct phy_device, state_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) struct net_device *dev = phydev->attached_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) bool needs_aneg = false, do_suspend = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) enum phy_state old_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) bool finished = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) old_state = phydev->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) switch (phydev->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) case PHY_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) case PHY_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) case PHY_UP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) needs_aneg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) case PHY_NOLINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) case PHY_RUNNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) err = phy_check_link_status(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) case PHY_CABLETEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) err = phydev->drv->cable_test_get_status(phydev, &finished);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) phy_abort_cable_test(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) netif_testing_off(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) needs_aneg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) phydev->state = PHY_UP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (finished) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) ethnl_cable_test_finished(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) netif_testing_off(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) needs_aneg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) phydev->state = PHY_UP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) case PHY_HALTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (phydev->link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) phydev->link = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) phy_link_down(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) do_suspend = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (needs_aneg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) err = phy_start_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) else if (do_suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) phy_suspend(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) phy_error(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if (old_state != phydev->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) phydev_dbg(phydev, "PHY state change %s -> %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) phy_state_to_str(old_state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) phy_state_to_str(phydev->state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (phydev->drv && phydev->drv->link_change_notify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) phydev->drv->link_change_notify(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) /* Only re-schedule a PHY state machine change if we are polling the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) * PHY, if PHY_IGNORE_INTERRUPT is set, then we will be moving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * between states from phy_mac_interrupt().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) * In state PHY_HALTED the PHY gets suspended, so rescheduling the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) * state machine would be pointless and possibly error prone when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * called from phy_disconnect() synchronously.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) mutex_lock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (phy_polling_mode(phydev) && phy_is_started(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) phy_queue_state_machine(phydev, PHY_STATE_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) mutex_unlock(&phydev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * phy_mac_interrupt - MAC says the link has changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) * @phydev: phy_device struct with changed link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * The MAC layer is able to indicate there has been a change in the PHY link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) * status. Trigger the state machine and work a work queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) void phy_mac_interrupt(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) /* Trigger a state machine change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) phy_trigger_machine(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) EXPORT_SYMBOL(phy_mac_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) static void mmd_eee_adv_to_linkmode(unsigned long *advertising, u16 eee_adv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) linkmode_zero(advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (eee_adv & MDIO_EEE_100TX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (eee_adv & MDIO_EEE_1000T)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (eee_adv & MDIO_EEE_10GT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (eee_adv & MDIO_EEE_1000KX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (eee_adv & MDIO_EEE_10GKX4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (eee_adv & MDIO_EEE_10GKR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) * phy_init_eee - init and check the EEE feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) * @clk_stop_enable: PHY may stop the clock during LPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * Description: it checks if the Energy-Efficient Ethernet (EEE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * is supported by looking at the MMD registers 3.20 and 7.60/61
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) * and it programs the MMD register 3.0 setting the "Clock stop enable"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) * bit if required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (!phydev->drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) /* According to 802.3az,the EEE is supported only in full duplex-mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (phydev->duplex == DUPLEX_FULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) __ETHTOOL_DECLARE_LINK_MODE_MASK(lp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) __ETHTOOL_DECLARE_LINK_MODE_MASK(adv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) int eee_lp, eee_cap, eee_adv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) u32 cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) /* Read phy status to properly get the right settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) status = phy_read_status(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) /* First check if the EEE ability is supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) eee_cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (eee_cap <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) goto eee_exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (!cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) goto eee_exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) /* Check which link settings negotiated and verify it in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) * the EEE advertising registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) eee_lp = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (eee_lp <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) goto eee_exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) eee_adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (eee_adv <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) goto eee_exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) mmd_eee_adv_to_linkmode(adv, eee_adv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) mmd_eee_adv_to_linkmode(lp, eee_lp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) linkmode_and(common, adv, lp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (!phy_check_valid(phydev->speed, phydev->duplex, common))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) goto eee_exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (clk_stop_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) /* Configure the PHY to stop receiving xMII
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * clock while it is signaling LPI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) MDIO_PCS_CTRL1_CLKSTOP_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) return 0; /* EEE supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) eee_exit_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return -EPROTONOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) EXPORT_SYMBOL(phy_init_eee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) * phy_get_eee_err - report the EEE wake error count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) * Description: it is to report the number of time where the PHY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) * failed to complete its normal wake sequence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) int phy_get_eee_err(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (!phydev->drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_WK_ERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) EXPORT_SYMBOL(phy_get_eee_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) * phy_ethtool_get_eee - get EEE supported and status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * @data: ethtool_eee data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) * Description: it reportes the Supported/Advertisement/LP Advertisement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) * capabilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (!phydev->drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) /* Get Supported EEE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* Get advertisement EEE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) data->eee_enabled = !!data->advertised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) /* Get LP advertisement EEE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) data->eee_active = !!(data->advertised & data->lp_advertised);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) EXPORT_SYMBOL(phy_ethtool_get_eee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * phy_ethtool_set_eee - set EEE supported and status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) * @data: ethtool_eee data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) * Description: it is to program the Advertisement EEE register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) int cap, old_adv, adv = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (!phydev->drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) /* Get Supported EEE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) if (cap < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) return cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) old_adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) if (old_adv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) return old_adv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if (data->eee_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) adv = !data->advertised ? cap :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) /* Mask prohibited EEE modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) adv &= ~phydev->eee_broken_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if (old_adv != adv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) /* Restart autonegotiation so the new modes get sent to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) * link partner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (phydev->autoneg == AUTONEG_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) ret = phy_restart_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) EXPORT_SYMBOL(phy_ethtool_set_eee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) * phy_ethtool_set_wol - Configure Wake On LAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) * @wol: Configuration requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (phydev->drv && phydev->drv->set_wol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) return phydev->drv->set_wol(phydev, wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) EXPORT_SYMBOL(phy_ethtool_set_wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) * phy_ethtool_get_wol - Get the current Wake On LAN configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) * @wol: Store the current configuration here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) if (phydev->drv && phydev->drv->get_wol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) phydev->drv->get_wol(phydev, wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) EXPORT_SYMBOL(phy_ethtool_get_wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) int phy_ethtool_get_link_ksettings(struct net_device *ndev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) struct ethtool_link_ksettings *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) struct phy_device *phydev = ndev->phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) if (!phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) phy_ethtool_ksettings_get(phydev, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) EXPORT_SYMBOL(phy_ethtool_get_link_ksettings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) int phy_ethtool_set_link_ksettings(struct net_device *ndev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) const struct ethtool_link_ksettings *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) struct phy_device *phydev = ndev->phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (!phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) return phy_ethtool_ksettings_set(phydev, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) EXPORT_SYMBOL(phy_ethtool_set_link_ksettings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) * phy_ethtool_nway_reset - Restart auto negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) * @ndev: Network device to restart autoneg for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) int phy_ethtool_nway_reset(struct net_device *ndev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) struct phy_device *phydev = ndev->phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (!phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (!phydev->drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) return phy_restart_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) EXPORT_SYMBOL(phy_ethtool_nway_reset);