^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * phylink models the MAC to optional PHY connection, supporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * technologies such as SFP cages where the PHY is hot-pluggable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2015 Russell King
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/ethtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/phy_fixed.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/phylink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "sfp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "swphy.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SUPPORTED_INTERFACES \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) (SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_FIBRE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) SUPPORTED_BNC | SUPPORTED_AUI | SUPPORTED_Backplane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define ADVERTISED_INTERFACES \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) (ADVERTISED_TP | ADVERTISED_MII | ADVERTISED_FIBRE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ADVERTISED_BNC | ADVERTISED_AUI | ADVERTISED_Backplane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) PHYLINK_DISABLE_STOPPED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) PHYLINK_DISABLE_LINK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * struct phylink - internal data type for phylink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct phylink {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* private: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct net_device *netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) const struct phylink_mac_ops *mac_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) const struct phylink_pcs_ops *pcs_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct phylink_config *config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct phylink_pcs *pcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned int old_link_state:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned long phylink_disable_state; /* bitmask of disables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct phy_device *phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) phy_interface_t link_interface; /* PHY_INTERFACE_xxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u8 cfg_link_an_mode; /* MLO_AN_xxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u8 cur_link_an_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u8 link_port; /* The current non-phy ethtool port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) __ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* The link configuration settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct phylink_link_state link_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* The current settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) phy_interface_t cur_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct gpio_desc *link_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned int link_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct timer_list link_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) void (*get_fixed_state)(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct phylink_link_state *s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct mutex state_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct phylink_link_state phy_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct work_struct resolve;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) bool mac_link_dropped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct sfp_bus *sfp_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) bool sfp_may_have_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u8 sfp_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define phylink_printk(level, pl, fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if ((pl)->config->type == PHYLINK_NETDEV) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) netdev_printk(level, (pl)->netdev, fmt, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) else if ((pl)->config->type == PHYLINK_DEV) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dev_printk(level, (pl)->dev, fmt, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define phylink_err(pl, fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) phylink_printk(KERN_ERR, pl, fmt, ##__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define phylink_warn(pl, fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) phylink_printk(KERN_WARNING, pl, fmt, ##__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define phylink_info(pl, fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) phylink_printk(KERN_INFO, pl, fmt, ##__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #if defined(CONFIG_DYNAMIC_DEBUG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define phylink_dbg(pl, fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if ((pl)->config->type == PHYLINK_NETDEV) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) netdev_dbg((pl)->netdev, fmt, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) else if ((pl)->config->type == PHYLINK_DEV) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) dev_dbg((pl)->dev, fmt, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #elif defined(DEBUG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define phylink_dbg(pl, fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) phylink_printk(KERN_DEBUG, pl, fmt, ##__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define phylink_dbg(pl, fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) phylink_printk(KERN_DEBUG, pl, fmt, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * phylink_set_port_modes() - set the port type modes in the ethtool mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @mask: ethtool link mode mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Sets all the port type modes in the ethtool mask. MAC drivers should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * use this in their 'validate' callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) void phylink_set_port_modes(unsigned long *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) phylink_set(mask, TP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) phylink_set(mask, AUI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) phylink_set(mask, MII);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) phylink_set(mask, FIBRE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) phylink_set(mask, BNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) phylink_set(mask, Backplane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) EXPORT_SYMBOL_GPL(phylink_set_port_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int phylink_is_empty_linkmode(const unsigned long *linkmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp) = { 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) phylink_set_port_modes(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) phylink_set(tmp, Autoneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) phylink_set(tmp, Pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) phylink_set(tmp, Asym_Pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return linkmode_subset(linkmode, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static const char *phylink_an_mode_str(unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static const char *modestr[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) [MLO_AN_PHY] = "phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) [MLO_AN_FIXED] = "fixed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) [MLO_AN_INBAND] = "inband",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int phylink_validate(struct phylink *pl, unsigned long *supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) pl->mac_ops->validate(pl->config, supported, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int phylink_parse_fixedlink(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct fwnode_handle *fixed_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) const struct phy_setting *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct gpio_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) u32 speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) fixed_node = fwnode_get_named_child_node(fwnode, "fixed-link");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (fixed_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ret = fwnode_property_read_u32(fixed_node, "speed", &speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) pl->link_config.speed = speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) pl->link_config.duplex = DUPLEX_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (fwnode_property_read_bool(fixed_node, "full-duplex"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) pl->link_config.duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* We treat the "pause" and "asym-pause" terminology as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * defining the link partner's ability. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (fwnode_property_read_bool(fixed_node, "pause"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) __set_bit(ETHTOOL_LINK_MODE_Pause_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) pl->link_config.lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (fwnode_property_read_bool(fixed_node, "asym-pause"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) pl->link_config.lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) desc = fwnode_gpiod_get_index(fixed_node, "link", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) GPIOD_IN, "?");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (!IS_ERR(desc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) pl->link_gpio = desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) else if (desc == ERR_PTR(-EPROBE_DEFER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) ret = -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) fwnode_handle_put(fixed_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) u32 prop[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) ret = fwnode_property_read_u32_array(fwnode, "fixed-link",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (ret != ARRAY_SIZE(prop)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) phylink_err(pl, "broken fixed-link?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ret = fwnode_property_read_u32_array(fwnode, "fixed-link",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) prop, ARRAY_SIZE(prop));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) pl->link_config.duplex = prop[1] ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) DUPLEX_FULL : DUPLEX_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) pl->link_config.speed = prop[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (prop[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) __set_bit(ETHTOOL_LINK_MODE_Pause_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) pl->link_config.lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (prop[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) pl->link_config.lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (pl->link_config.speed > SPEED_1000 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) pl->link_config.duplex != DUPLEX_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) phylink_warn(pl, "fixed link specifies half duplex for %dMbps link?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) pl->link_config.speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) bitmap_fill(pl->supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) linkmode_copy(pl->link_config.advertising, pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) phylink_validate(pl, pl->supported, &pl->link_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) pl->supported, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) linkmode_zero(pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) phylink_set(pl->supported, MII);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) phylink_set(pl->supported, Pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) phylink_set(pl->supported, Asym_Pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) phylink_set(pl->supported, Autoneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (s) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) __set_bit(s->bit, pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) __set_bit(s->bit, pl->link_config.lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) phylink_warn(pl, "fixed link %s duplex %dMbps not recognised\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) pl->link_config.duplex == DUPLEX_FULL ? "full" : "half",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) pl->link_config.speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) linkmode_and(pl->link_config.advertising, pl->link_config.advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) pl->link_config.link = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) pl->link_config.an_complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct fwnode_handle *dn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) const char *managed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) dn = fwnode_get_named_child_node(fwnode, "fixed-link");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (dn || fwnode_property_present(fwnode, "fixed-link"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) pl->cfg_link_an_mode = MLO_AN_FIXED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) fwnode_handle_put(dn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (fwnode_property_read_string(fwnode, "managed", &managed) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) strcmp(managed, "in-band-status") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (pl->cfg_link_an_mode == MLO_AN_FIXED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) phylink_err(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) "can't use both fixed-link and in-band-status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) linkmode_zero(pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) phylink_set(pl->supported, MII);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) phylink_set(pl->supported, Autoneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) phylink_set(pl->supported, Asym_Pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) phylink_set(pl->supported, Pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) pl->link_config.an_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) pl->cfg_link_an_mode = MLO_AN_INBAND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) switch (pl->link_config.interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case PHY_INTERFACE_MODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) case PHY_INTERFACE_MODE_QSGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) phylink_set(pl->supported, 10baseT_Half);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) phylink_set(pl->supported, 10baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) phylink_set(pl->supported, 100baseT_Half);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) phylink_set(pl->supported, 100baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) phylink_set(pl->supported, 1000baseT_Half);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) phylink_set(pl->supported, 1000baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) case PHY_INTERFACE_MODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) phylink_set(pl->supported, 1000baseX_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) case PHY_INTERFACE_MODE_2500BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) phylink_set(pl->supported, 2500baseX_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case PHY_INTERFACE_MODE_USXGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case PHY_INTERFACE_MODE_10GKR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) case PHY_INTERFACE_MODE_10GBASER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) phylink_set(pl->supported, 10baseT_Half);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) phylink_set(pl->supported, 10baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) phylink_set(pl->supported, 100baseT_Half);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) phylink_set(pl->supported, 100baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) phylink_set(pl->supported, 1000baseT_Half);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) phylink_set(pl->supported, 1000baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) phylink_set(pl->supported, 1000baseX_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) phylink_set(pl->supported, 1000baseKX_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) phylink_set(pl->supported, 2500baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) phylink_set(pl->supported, 2500baseX_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) phylink_set(pl->supported, 5000baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) phylink_set(pl->supported, 10000baseT_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) phylink_set(pl->supported, 10000baseKR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) phylink_set(pl->supported, 10000baseKX4_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) phylink_set(pl->supported, 10000baseCR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) phylink_set(pl->supported, 10000baseSR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) phylink_set(pl->supported, 10000baseLR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) phylink_set(pl->supported, 10000baseLRM_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) phylink_set(pl->supported, 10000baseER_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case PHY_INTERFACE_MODE_XLGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) phylink_set(pl->supported, 25000baseCR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) phylink_set(pl->supported, 25000baseKR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) phylink_set(pl->supported, 25000baseSR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) phylink_set(pl->supported, 40000baseKR4_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) phylink_set(pl->supported, 40000baseCR4_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) phylink_set(pl->supported, 40000baseSR4_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) phylink_set(pl->supported, 40000baseLR4_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) phylink_set(pl->supported, 50000baseCR2_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) phylink_set(pl->supported, 50000baseKR2_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) phylink_set(pl->supported, 50000baseSR2_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) phylink_set(pl->supported, 50000baseKR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) phylink_set(pl->supported, 50000baseSR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) phylink_set(pl->supported, 50000baseCR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) phylink_set(pl->supported, 50000baseLR_ER_FR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) phylink_set(pl->supported, 50000baseDR_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) phylink_set(pl->supported, 100000baseKR4_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) phylink_set(pl->supported, 100000baseSR4_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) phylink_set(pl->supported, 100000baseCR4_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) phylink_set(pl->supported, 100000baseLR4_ER4_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) phylink_set(pl->supported, 100000baseKR2_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) phylink_set(pl->supported, 100000baseSR2_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) phylink_set(pl->supported, 100000baseCR2_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) phylink_set(pl->supported, 100000baseLR2_ER2_FR2_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) phylink_set(pl->supported, 100000baseDR2_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) phylink_err(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) "incorrect link mode %s for in-band status\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) phy_modes(pl->link_config.interface));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) linkmode_copy(pl->link_config.advertising, pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (phylink_validate(pl, pl->supported, &pl->link_config)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) phylink_err(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) "failed to validate link configuration for in-band status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* Check if MAC/PCS also supports Autoneg. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) pl->link_config.an_enabled = phylink_test(pl->supported, Autoneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static void phylink_apply_manual_flow(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* If autoneg is disabled, pause AN is also disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!state->an_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) state->pause &= ~MLO_PAUSE_AN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* Manual configuration of pause modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!(pl->link_config.pause & MLO_PAUSE_AN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) state->pause = pl->link_config.pause;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static void phylink_resolve_flow(struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) bool tx_pause, rx_pause;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) state->pause = MLO_PAUSE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (state->duplex == DUPLEX_FULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) linkmode_resolve_pause(state->advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) state->lp_advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) &tx_pause, &rx_pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (tx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) state->pause |= MLO_PAUSE_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (rx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) state->pause |= MLO_PAUSE_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static void phylink_mac_config(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) const struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) phylink_dbg(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) "%s: mode=%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) __func__, phylink_an_mode_str(pl->cur_link_an_mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) phy_modes(state->interface),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) phy_speed_to_str(state->speed),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) phy_duplex_to_str(state->duplex),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) state->pause, state->link, state->an_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static void phylink_mac_pcs_an_restart(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (pl->link_config.an_enabled &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) phy_interface_mode_is_8023z(pl->link_config.interface) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) phylink_autoneg_inband(pl->cur_link_an_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (pl->pcs_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) pl->pcs_ops->pcs_an_restart(pl->pcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) pl->mac_ops->mac_an_restart(pl->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static void phylink_major_config(struct phylink *pl, bool restart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) const struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (pl->mac_ops->mac_prepare) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) state->interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) phylink_err(pl, "mac_prepare failed: %pe\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ERR_PTR(err));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) phylink_mac_config(pl, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (pl->pcs_ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) err = pl->pcs_ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) state->interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) state->advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) !!(pl->link_config.pause &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) MLO_PAUSE_AN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) phylink_err(pl, "pcs_config failed: %pe\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ERR_PTR(err));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (err > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) restart = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (restart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) phylink_mac_pcs_an_restart(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (pl->mac_ops->mac_finish) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) state->interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) phylink_err(pl, "mac_finish failed: %pe\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) ERR_PTR(err));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * Reconfigure for a change of inband advertisement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * If we have a separate PCS, we only need to call its pcs_config() method,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * and then restart AN if it indicates something changed. Otherwise, we do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * the full MAC reconfiguration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static int phylink_change_inband_advert(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (!pl->pcs_ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* Legacy method */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) phylink_mac_config(pl, &pl->link_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) phylink_mac_pcs_an_restart(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) phylink_an_mode_str(pl->cur_link_an_mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) phy_modes(pl->link_config.interface),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) pl->link_config.pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* Modern PCS-based method; update the advert at the PCS, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * restart negotiation if the pcs_config() helper indicates that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * the programmed advertisement has changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ret = pl->pcs_ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) pl->link_config.interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) pl->link_config.advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) !!(pl->link_config.pause & MLO_PAUSE_AN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) phylink_mac_pcs_an_restart(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) static void phylink_mac_pcs_get_state(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) linkmode_copy(state->advertising, pl->link_config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) linkmode_zero(state->lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) state->interface = pl->link_config.interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) state->an_enabled = pl->link_config.an_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) state->speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) state->duplex = DUPLEX_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) state->pause = MLO_PAUSE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) state->an_complete = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) state->link = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (pl->pcs_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) pl->pcs_ops->pcs_get_state(pl->pcs, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) else if (pl->mac_ops->mac_pcs_get_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) pl->mac_ops->mac_pcs_get_state(pl->config, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) state->link = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /* The fixed state is... fixed except for the link state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * which may be determined by a GPIO or a callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static void phylink_get_fixed_state(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) *state = pl->link_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (pl->config->get_fixed_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) pl->config->get_fixed_state(pl->config, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) else if (pl->link_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) state->link = !!gpiod_get_value_cansleep(pl->link_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) phylink_resolve_flow(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static void phylink_mac_initial_config(struct phylink *pl, bool force_restart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct phylink_link_state link_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) switch (pl->cur_link_an_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) case MLO_AN_PHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) link_state = pl->phy_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) case MLO_AN_FIXED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) phylink_get_fixed_state(pl, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) case MLO_AN_INBAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) link_state = pl->link_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (link_state.interface == PHY_INTERFACE_MODE_SGMII)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) link_state.pause = MLO_PAUSE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) default: /* can't happen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) link_state.link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) phylink_apply_manual_flow(pl, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) phylink_major_config(pl, force_restart, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static const char *phylink_pause_to_str(int pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) switch (pause & MLO_PAUSE_TXRX_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) case MLO_PAUSE_TX | MLO_PAUSE_RX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return "rx/tx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) case MLO_PAUSE_TX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return "tx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) case MLO_PAUSE_RX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return "rx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return "off";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static void phylink_link_up(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct phylink_link_state link_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct net_device *ndev = pl->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) pl->cur_interface = link_state.interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (pl->pcs_ops && pl->pcs_ops->pcs_link_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) pl->pcs_ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) pl->cur_interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) link_state.speed, link_state.duplex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) pl->mac_ops->mac_link_up(pl->config, pl->phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) pl->cur_link_an_mode, pl->cur_interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) link_state.speed, link_state.duplex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) !!(link_state.pause & MLO_PAUSE_TX),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) !!(link_state.pause & MLO_PAUSE_RX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (ndev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) netif_carrier_on(ndev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) phylink_info(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) "Link is Up - %s/%s - flow control %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) phy_speed_to_str(link_state.speed),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) phy_duplex_to_str(link_state.duplex),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) phylink_pause_to_str(link_state.pause));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static void phylink_link_down(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct net_device *ndev = pl->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (ndev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) netif_carrier_off(ndev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) pl->cur_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) phylink_info(pl, "Link is Down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static void phylink_resolve(struct work_struct *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct phylink *pl = container_of(w, struct phylink, resolve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct phylink_link_state link_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct net_device *ndev = pl->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) bool mac_config = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) bool retrigger = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) bool cur_link_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) mutex_lock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (pl->netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) cur_link_state = netif_carrier_ok(ndev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) cur_link_state = pl->old_link_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (pl->phylink_disable_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) pl->mac_link_dropped = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) link_state.link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) } else if (pl->mac_link_dropped) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) link_state.link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) retrigger = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) switch (pl->cur_link_an_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) case MLO_AN_PHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) link_state = pl->phy_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) phylink_apply_manual_flow(pl, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) mac_config = link_state.link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) case MLO_AN_FIXED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) phylink_get_fixed_state(pl, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) mac_config = link_state.link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) case MLO_AN_INBAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) phylink_mac_pcs_get_state(pl, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* The PCS may have a latching link-fail indicator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * If the link was up, bring the link down and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * re-trigger the resolve. Otherwise, re-read the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * PCS state to get the current status of the link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (!link_state.link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (cur_link_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) retrigger = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) phylink_mac_pcs_get_state(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) /* If we have a phy, the "up" state is the union of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * both the PHY and the MAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) link_state.link &= pl->phy_state.link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* Only update if the PHY link is up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (pl->phydev && pl->phy_state.link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /* If the interface has changed, force a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * link down event if the link isn't already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * down, and re-resolve.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (link_state.interface !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) pl->phy_state.interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) retrigger = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) link_state.link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) link_state.interface = pl->phy_state.interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* If we have a PHY, we need to update with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * the PHY flow control bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) link_state.pause = pl->phy_state.pause;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) mac_config = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) phylink_apply_manual_flow(pl, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) break;
^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) if (mac_config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (link_state.interface != pl->link_config.interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* The interface has changed, force the link down and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * then reconfigure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (cur_link_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) phylink_link_down(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) cur_link_state = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) phylink_major_config(pl, false, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) pl->link_config.interface = link_state.interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) } else if (!pl->pcs_ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* The interface remains unchanged, only the speed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * duplex or pause settings have changed. Call the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * old mac_config() method to configure the MAC/PCS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * only if we do not have a PCS installed (an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * unconverted user.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) phylink_mac_config(pl, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (link_state.link != cur_link_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) pl->old_link_state = link_state.link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (!link_state.link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) phylink_link_down(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) phylink_link_up(pl, link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (!link_state.link && retrigger) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) pl->mac_link_dropped = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) queue_work(system_power_efficient_wq, &pl->resolve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) mutex_unlock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) static void phylink_run_resolve(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (!pl->phylink_disable_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) queue_work(system_power_efficient_wq, &pl->resolve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static void phylink_run_resolve_and_disable(struct phylink *pl, int bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) unsigned long state = pl->phylink_disable_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) set_bit(bit, &pl->phylink_disable_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (state == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) queue_work(system_power_efficient_wq, &pl->resolve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) flush_work(&pl->resolve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) static void phylink_fixed_poll(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) struct phylink *pl = container_of(t, struct phylink, link_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) mod_timer(t, jiffies + HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) phylink_run_resolve(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static const struct sfp_upstream_ops sfp_phylink_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static int phylink_register_sfp(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) struct fwnode_handle *fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) struct sfp_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (!fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) bus = sfp_bus_find_fwnode(fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (IS_ERR(bus)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) ret = PTR_ERR(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) phylink_err(pl, "unable to attach SFP bus: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) pl->sfp_bus = bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) ret = sfp_bus_add_upstream(bus, pl, &sfp_phylink_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) sfp_bus_put(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * phylink_create() - create a phylink instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * @config: a pointer to the target &struct phylink_config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * @fwnode: a pointer to a &struct fwnode_handle describing the network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * @iface: the desired link mode defined by &typedef phy_interface_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * @mac_ops: a pointer to a &struct phylink_mac_ops for the MAC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * Create a new phylink instance, and parse the link parameters found in @np.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * This will parse in-band modes, fixed-link or SFP configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * Note: the rtnl lock must not be held when calling this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * Returns a pointer to a &struct phylink, or an error-pointer value. Users
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * must use IS_ERR() to check for errors from this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct phylink *phylink_create(struct phylink_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) phy_interface_t iface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) const struct phylink_mac_ops *mac_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct phylink *pl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) pl = kzalloc(sizeof(*pl), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (!pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) mutex_init(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) INIT_WORK(&pl->resolve, phylink_resolve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) pl->config = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (config->type == PHYLINK_NETDEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) pl->netdev = to_net_dev(config->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) } else if (config->type == PHYLINK_DEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) pl->dev = config->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) kfree(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) pl->phy_state.interface = iface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) pl->link_interface = iface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (iface == PHY_INTERFACE_MODE_MOCA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) pl->link_port = PORT_BNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) pl->link_port = PORT_MII;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) pl->link_config.interface = iface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) pl->link_config.pause = MLO_PAUSE_AN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) pl->link_config.speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) pl->link_config.duplex = DUPLEX_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) pl->link_config.an_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) pl->mac_ops = mac_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) timer_setup(&pl->link_poll, phylink_fixed_poll, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) bitmap_fill(pl->supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) linkmode_copy(pl->link_config.advertising, pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) phylink_validate(pl, pl->supported, &pl->link_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) ret = phylink_parse_mode(pl, fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) kfree(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (pl->cfg_link_an_mode == MLO_AN_FIXED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ret = phylink_parse_fixedlink(pl, fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) kfree(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pl->cur_link_an_mode = pl->cfg_link_an_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) ret = phylink_register_sfp(pl, fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) kfree(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return pl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) EXPORT_SYMBOL_GPL(phylink_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * phylink_set_pcs() - set the current PCS for phylink to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * @pcs: a pointer to the &struct phylink_pcs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * Bind the MAC PCS to phylink. This may be called after phylink_create(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * in mac_prepare() or mac_config() methods if it is desired to dynamically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * change the PCS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * Please note that there are behavioural changes with the mac_config()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * callback if a PCS is present (denoting a newer setup) so removing a PCS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * is not supported, and if a PCS is going to be used, it must be registered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) * by calling phylink_set_pcs() at the latest in the first mac_config() call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) void phylink_set_pcs(struct phylink *pl, struct phylink_pcs *pcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) pl->pcs = pcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) pl->pcs_ops = pcs->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) EXPORT_SYMBOL_GPL(phylink_set_pcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * phylink_destroy() - cleanup and destroy the phylink instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * Destroy a phylink instance. Any PHY that has been attached must have been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * cleaned up via phylink_disconnect_phy() prior to calling this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * Note: the rtnl lock must not be held when calling this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) void phylink_destroy(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) sfp_bus_del_upstream(pl->sfp_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (pl->link_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) gpiod_put(pl->link_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) cancel_work_sync(&pl->resolve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) kfree(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) EXPORT_SYMBOL_GPL(phylink_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static void phylink_phy_change(struct phy_device *phydev, bool up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) struct phylink *pl = phydev->phylink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) bool tx_pause, rx_pause;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) phy_get_pause(phydev, &tx_pause, &rx_pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) mutex_lock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) pl->phy_state.speed = phydev->speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) pl->phy_state.duplex = phydev->duplex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) pl->phy_state.pause = MLO_PAUSE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (tx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) pl->phy_state.pause |= MLO_PAUSE_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (rx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) pl->phy_state.pause |= MLO_PAUSE_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) pl->phy_state.interface = phydev->interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) pl->phy_state.link = up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) mutex_unlock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) phylink_run_resolve(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) phylink_dbg(pl, "phy link %s %s/%s/%s\n", up ? "up" : "down",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) phy_modes(phydev->interface),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) phy_speed_to_str(phydev->speed),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) phy_duplex_to_str(phydev->duplex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) phy_interface_t interface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct phylink_link_state config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) __ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) char *irq_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * This is the new way of dealing with flow control for PHYs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) * as described by Timur Tabi in commit 529ed1275263 ("net: phy:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * phy drivers should not set SUPPORTED_[Asym_]Pause") except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * using our validate call to the MAC, we rely upon the MAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * clearing the bits from both supported and advertising fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) phy_support_asym_pause(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) memset(&config, 0, sizeof(config));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) linkmode_copy(supported, phy->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) linkmode_copy(config.advertising, phy->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) /* Clause 45 PHYs switch their Serdes lane between several different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) * modes, normally 10GBASE-R, SGMII. Some use 2500BASE-X for 2.5G
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) * speeds. We really need to know which interface modes the PHY and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * MAC supports to properly work out which linkmodes can be supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (phy->is_c45 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) interface != PHY_INTERFACE_MODE_RXAUI &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) interface != PHY_INTERFACE_MODE_XAUI &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) interface != PHY_INTERFACE_MODE_USXGMII)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) config.interface = PHY_INTERFACE_MODE_NA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) config.interface = interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) ret = phylink_validate(pl, supported, &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) phylink_warn(pl, "validation of %s with support %*pb and advertisement %*pb failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) phy_modes(config.interface),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) __ETHTOOL_LINK_MODE_MASK_NBITS, phy->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) __ETHTOOL_LINK_MODE_MASK_NBITS, config.advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) phy->phylink = pl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) phy->phy_link_change = phylink_phy_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) irq_str = phy_attached_info_irq(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) phylink_info(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) "PHY [%s] driver [%s] (irq=%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) dev_name(&phy->mdio.dev), phy->drv->name, irq_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) kfree(irq_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) mutex_lock(&phy->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) mutex_lock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) pl->phydev = phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) pl->phy_state.interface = interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) pl->phy_state.pause = MLO_PAUSE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) pl->phy_state.speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) pl->phy_state.duplex = DUPLEX_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) linkmode_copy(pl->supported, supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) linkmode_copy(pl->link_config.advertising, config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) /* Restrict the phy advertisement according to the MAC support. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) linkmode_copy(phy->advertising, config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) mutex_unlock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) mutex_unlock(&phy->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) phylink_dbg(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) "phy: setting supported %*pb advertising %*pb\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) __ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) __ETHTOOL_LINK_MODE_MASK_NBITS, phy->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (phy_interrupt_is_valid(phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) phy_request_interrupt(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static int phylink_attach_phy(struct phylink *pl, struct phy_device *phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) phy_interface_t interface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (WARN_ON(pl->cfg_link_an_mode == MLO_AN_FIXED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) (pl->cfg_link_an_mode == MLO_AN_INBAND &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) phy_interface_mode_is_8023z(interface))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) return phy_attach_direct(pl->netdev, phy, 0, interface);
^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) * phylink_connect_phy() - connect a PHY to the phylink instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * @phy: a pointer to a &struct phy_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * Connect @phy to the phylink instance specified by @pl by calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * phy_attach_direct(). Configure the @phy according to the MAC driver's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * capabilities, start the PHYLIB state machine and enable any interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * that the PHY supports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * This updates the phylink's ethtool supported and advertising link mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * masks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * Returns 0 on success or a negative errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) /* Use PHY device/driver interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (pl->link_interface == PHY_INTERFACE_MODE_NA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) pl->link_interface = phy->interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) pl->link_config.interface = pl->link_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) ret = phylink_attach_phy(pl, phy, pl->link_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) ret = phylink_bringup_phy(pl, phy, pl->link_config.interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) phy_detach(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) EXPORT_SYMBOL_GPL(phylink_connect_phy);
^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) * phylink_of_phy_connect() - connect the PHY specified in the DT mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) * @dn: a pointer to a &struct device_node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) * @flags: PHY-specific flags to communicate to the PHY device driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) * Connect the phy specified in the device node @dn to the phylink instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * specified by @pl. Actions specified in phylink_connect_phy() will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * performed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) * Returns 0 on success or a negative errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) struct device_node *phy_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct phy_device *phy_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /* Fixed links and 802.3z are handled without needing a PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) (pl->cfg_link_an_mode == MLO_AN_INBAND &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) phy_interface_mode_is_8023z(pl->link_interface)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) phy_node = of_parse_phandle(dn, "phy-handle", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if (!phy_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) phy_node = of_parse_phandle(dn, "phy", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (!phy_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) phy_node = of_parse_phandle(dn, "phy-device", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (!phy_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (pl->cfg_link_an_mode == MLO_AN_PHY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) phy_dev = of_phy_find_device(phy_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) /* We're done with the phy_node handle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) of_node_put(phy_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (!phy_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) ret = phy_attach_direct(pl->netdev, phy_dev, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) pl->link_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) phy_detach(phy_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) EXPORT_SYMBOL_GPL(phylink_of_phy_connect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) * phylink_disconnect_phy() - disconnect any PHY attached to the phylink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) * Disconnect any current PHY from the phylink instance described by @pl.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) void phylink_disconnect_phy(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) struct phy_device *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) phy = pl->phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (phy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) mutex_lock(&phy->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) mutex_lock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) pl->phydev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) mutex_unlock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) mutex_unlock(&phy->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) flush_work(&pl->resolve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) phy_disconnect(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) EXPORT_SYMBOL_GPL(phylink_disconnect_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * phylink_mac_change() - notify phylink of a change in MAC state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) * @up: indicates whether the link is currently up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) * The MAC driver should call this driver when the state of its link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) * changes (eg, link failure, new negotiation results, etc.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) void phylink_mac_change(struct phylink *pl, bool up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (!up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) pl->mac_link_dropped = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) phylink_run_resolve(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) phylink_dbg(pl, "mac link %s\n", up ? "up" : "down");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) EXPORT_SYMBOL_GPL(phylink_mac_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) static irqreturn_t phylink_link_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) struct phylink *pl = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) phylink_run_resolve(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) return IRQ_HANDLED;
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) * phylink_start() - start a phylink instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) * Start the phylink instance specified by @pl, configuring the MAC for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) * desired link mode(s) and negotiation style. This should be called from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) * network device driver's &struct net_device_ops ndo_open() method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) void phylink_start(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) bool poll = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) phylink_info(pl, "configuring for %s/%s link mode\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) phylink_an_mode_str(pl->cur_link_an_mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) phy_modes(pl->link_config.interface));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) /* Always set the carrier off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (pl->netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) netif_carrier_off(pl->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) /* Apply the link configuration to the MAC when starting. This allows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) * a fixed-link to start with the correct parameters, and also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * ensures that we set the appropriate advertisement for Serdes links.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * Restart autonegotiation if using 802.3z to ensure that the link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * parameters are properly negotiated. This is necessary for DSA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) * switches using 802.3z negotiation to ensure they see our modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) phylink_mac_initial_config(pl, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) phylink_run_resolve(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) int irq = gpiod_to_irq(pl->link_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (irq > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (!request_irq(irq, phylink_link_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) IRQF_TRIGGER_RISING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) IRQF_TRIGGER_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) "netdev link", pl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) pl->link_irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) poll = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) switch (pl->cfg_link_an_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) case MLO_AN_FIXED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) poll |= pl->config->poll_fixed_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) case MLO_AN_INBAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) poll |= pl->config->pcs_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (pl->pcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) poll |= pl->pcs->poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) mod_timer(&pl->link_poll, jiffies + HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) phy_start(pl->phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (pl->sfp_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) sfp_upstream_start(pl->sfp_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) EXPORT_SYMBOL_GPL(phylink_start);
^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) * phylink_stop() - stop a phylink instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * Stop the phylink instance specified by @pl. This should be called from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * network device driver's &struct net_device_ops ndo_stop() method. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * network device's carrier state should not be changed prior to calling this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) * function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) void phylink_stop(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (pl->sfp_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) sfp_upstream_stop(pl->sfp_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) phy_stop(pl->phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) del_timer_sync(&pl->link_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (pl->link_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) free_irq(pl->link_irq, pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) pl->link_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) EXPORT_SYMBOL_GPL(phylink_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) * phylink_ethtool_get_wol() - get the wake on lan parameters for the PHY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) * @wol: a pointer to &struct ethtool_wolinfo to hold the read parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) * Read the wake on lan parameters from the PHY attached to the phylink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) * instance specified by @pl. If no PHY is currently attached, report no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) * support for wake on lan.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) void phylink_ethtool_get_wol(struct phylink *pl, struct ethtool_wolinfo *wol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) wol->supported = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) wol->wolopts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) phy_ethtool_get_wol(pl->phydev, wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) EXPORT_SYMBOL_GPL(phylink_ethtool_get_wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) * phylink_ethtool_set_wol() - set wake on lan parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) * @wol: a pointer to &struct ethtool_wolinfo for the desired parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) * Set the wake on lan parameters for the PHY attached to the phylink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) * instance specified by @pl. If no PHY is attached, returns %EOPNOTSUPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) * error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) * Returns zero on success or negative errno code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) int phylink_ethtool_set_wol(struct phylink *pl, struct ethtool_wolinfo *wol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) int ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) ret = phy_ethtool_set_wol(pl->phydev, wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) EXPORT_SYMBOL_GPL(phylink_ethtool_set_wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) static void phylink_merge_link_mode(unsigned long *dst, const unsigned long *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) __ETHTOOL_DECLARE_LINK_MODE_MASK(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) linkmode_zero(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) phylink_set_port_modes(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) linkmode_and(dst, dst, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) linkmode_or(dst, dst, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) static void phylink_get_ksettings(const struct phylink_link_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) struct ethtool_link_ksettings *kset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) phylink_merge_link_mode(kset->link_modes.advertising, state->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) linkmode_copy(kset->link_modes.lp_advertising, state->lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) kset->base.speed = state->speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) kset->base.duplex = state->duplex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) kset->base.autoneg = state->an_enabled ? AUTONEG_ENABLE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) AUTONEG_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) * phylink_ethtool_ksettings_get() - get the current link settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) * @kset: a pointer to a &struct ethtool_link_ksettings to hold link settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) * Read the current link settings for the phylink instance specified by @pl.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) * This will be the link settings read from the MAC, PHY or fixed link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * settings depending on the current negotiation mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) int phylink_ethtool_ksettings_get(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) struct ethtool_link_ksettings *kset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) struct phylink_link_state link_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) if (pl->phydev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) phy_ethtool_ksettings_get(pl->phydev, kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) kset->base.port = pl->link_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) linkmode_copy(kset->link_modes.supported, pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) switch (pl->cur_link_an_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) case MLO_AN_FIXED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) /* We are using fixed settings. Report these as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * current link settings - and note that these also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * represent the supported speeds/duplex/pause modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) phylink_get_fixed_state(pl, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) phylink_get_ksettings(&link_state, kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) case MLO_AN_INBAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) /* If there is a phy attached, then use the reported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) * settings from the phy with no modification.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) phylink_mac_pcs_get_state(pl, &link_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) /* The MAC is reporting the link results from its own PCS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) * layer via in-band status. Report these as the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) * link settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) phylink_get_ksettings(&link_state, kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) * phylink_ethtool_ksettings_set() - set the link settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) * @kset: a pointer to a &struct ethtool_link_ksettings for the desired modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) int phylink_ethtool_ksettings_set(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) const struct ethtool_link_ksettings *kset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) __ETHTOOL_DECLARE_LINK_MODE_MASK(support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) struct phylink_link_state config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) const struct phy_setting *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (pl->phydev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) /* We can rely on phylib for this update; we also do not need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) * to update the pl->link_config settings:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) * - the configuration returned via ksettings_get() will come
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) * from phylib whenever a PHY is present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) * - link_config.interface will be updated by the PHY calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) * back via phylink_phy_change() and a subsequent resolve.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) * - initial link configuration for PHY mode comes from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) * last phy state updated via phylink_phy_change().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) * - other configuration changes (e.g. pause modes) are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) * performed directly via phylib.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) * - if in in-band mode with a PHY, the link configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) * is passed on the link from the PHY, and all of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) * link_config.{speed,duplex,an_enabled,pause} are not used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) * - the only possible use would be link_config.advertising
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) * pause modes when in 1000base-X mode with a PHY, but in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) * the presence of a PHY, this should not be changed as that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) * should be determined from the media side advertisement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) return phy_ethtool_ksettings_set(pl->phydev, kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) linkmode_copy(support, pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) config = pl->link_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) config.an_enabled = kset->base.autoneg == AUTONEG_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) /* Mask out unsupported advertisements, and force the autoneg bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) linkmode_and(config.advertising, kset->link_modes.advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) config.an_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) /* FIXME: should we reject autoneg if phy/mac does not support it? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) switch (kset->base.autoneg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) case AUTONEG_DISABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) /* Autonegotiation disabled, select a suitable speed and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) * duplex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) s = phy_lookup_setting(kset->base.speed, kset->base.duplex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) support, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) if (!s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) /* If we have a fixed link, refuse to change link parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) * If the link parameters match, accept them but do nothing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) if (pl->cur_link_an_mode == MLO_AN_FIXED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (s->speed != pl->link_config.speed ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) s->duplex != pl->link_config.duplex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) config.speed = s->speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) config.duplex = s->duplex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) case AUTONEG_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) /* If we have a fixed link, allow autonegotiation (since that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) * is our default case) but do not allow the advertisement to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) * be changed. If the advertisement matches, simply return.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) if (pl->cur_link_an_mode == MLO_AN_FIXED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) if (!linkmode_equal(config.advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) pl->link_config.advertising))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) config.speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) config.duplex = DUPLEX_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) /* We have ruled out the case with a PHY attached, and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) * fixed-link cases. All that is left are in-band links.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) if (phylink_validate(pl, support, &config))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) /* If autonegotiation is enabled, we must have an advertisement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (config.an_enabled && phylink_is_empty_linkmode(config.advertising))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) /* If this link is with an SFP, ensure that changes to advertised modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) * also cause the associated interface to be selected such that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) * link can be configured correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (pl->sfp_port && pl->sfp_bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) config.interface = sfp_select_interface(pl->sfp_bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) if (config.interface == PHY_INTERFACE_MODE_NA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) phylink_err(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) "selection of interface failed, advertisement %*pb\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) __ETHTOOL_LINK_MODE_MASK_NBITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) /* Revalidate with the selected interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) linkmode_copy(support, pl->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) if (phylink_validate(pl, support, &config)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) phylink_err(pl, "validation of %s/%s with support %*pb failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) phylink_an_mode_str(pl->cur_link_an_mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) phy_modes(config.interface),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) __ETHTOOL_LINK_MODE_MASK_NBITS, support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) mutex_lock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) pl->link_config.speed = config.speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) pl->link_config.duplex = config.duplex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) pl->link_config.an_enabled = config.an_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) if (pl->link_config.interface != config.interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) /* The interface changed, e.g. 1000base-X <-> 2500base-X */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) /* We need to force the link down, then change the interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (pl->old_link_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) phylink_link_down(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) pl->old_link_state = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) if (!test_bit(PHYLINK_DISABLE_STOPPED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) &pl->phylink_disable_state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) phylink_major_config(pl, false, &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) pl->link_config.interface = config.interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) linkmode_copy(pl->link_config.advertising, config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) } else if (!linkmode_equal(pl->link_config.advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) config.advertising)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) linkmode_copy(pl->link_config.advertising, config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) phylink_change_inband_advert(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) mutex_unlock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) * phylink_ethtool_nway_reset() - restart negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) * Restart negotiation for the phylink instance specified by @pl. This will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) * cause any attached phy to restart negotiation with the link partner, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) * if the MAC is in a BaseX mode, the MAC will also be requested to restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) * negotiation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) * Returns zero on success, or negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) int phylink_ethtool_nway_reset(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) ret = phy_restart_aneg(pl->phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) phylink_mac_pcs_an_restart(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) EXPORT_SYMBOL_GPL(phylink_ethtool_nway_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) * phylink_ethtool_get_pauseparam() - get the current pause parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) * @pause: a pointer to a &struct ethtool_pauseparam
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) void phylink_ethtool_get_pauseparam(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) struct ethtool_pauseparam *pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) pause->autoneg = !!(pl->link_config.pause & MLO_PAUSE_AN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) pause->rx_pause = !!(pl->link_config.pause & MLO_PAUSE_RX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) pause->tx_pause = !!(pl->link_config.pause & MLO_PAUSE_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) EXPORT_SYMBOL_GPL(phylink_ethtool_get_pauseparam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) * phylink_ethtool_set_pauseparam() - set the current pause parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) * @pause: a pointer to a &struct ethtool_pauseparam
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) int phylink_ethtool_set_pauseparam(struct phylink *pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) struct ethtool_pauseparam *pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) struct phylink_link_state *config = &pl->link_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) bool manual_changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) int pause_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) if (pl->cur_link_an_mode == MLO_AN_FIXED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) if (!phylink_test(pl->supported, Pause) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) !phylink_test(pl->supported, Asym_Pause))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if (!phylink_test(pl->supported, Asym_Pause) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) pause->rx_pause != pause->tx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) pause_state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) if (pause->autoneg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) pause_state |= MLO_PAUSE_AN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) if (pause->rx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) pause_state |= MLO_PAUSE_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) if (pause->tx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) pause_state |= MLO_PAUSE_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) mutex_lock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) * See the comments for linkmode_set_pause(), wrt the deficiencies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) * with the current implementation. A solution to this issue would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) * be:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) * ethtool Local device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) * rx tx Pause AsymDir
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) * 0 0 0 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) * 1 0 1 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) * 0 1 0 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) * 1 1 1 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) * and then use the ethtool rx/tx enablement status to mask the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) * rx/tx pause resolution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) linkmode_set_pause(config->advertising, pause->tx_pause,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) pause->rx_pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) manual_changed = (config->pause ^ pause_state) & MLO_PAUSE_AN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) (!(pause_state & MLO_PAUSE_AN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) (config->pause ^ pause_state) & MLO_PAUSE_TXRX_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) config->pause = pause_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) /* Update our in-band advertisement, triggering a renegotiation if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) * the advertisement changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (!pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) phylink_change_inband_advert(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) mutex_unlock(&pl->state_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) /* If we have a PHY, a change of the pause frame advertisement will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) * cause phylib to renegotiate (if AN is enabled) which will in turn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) * call our phylink_phy_change() and trigger a resolve. Note that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) * we can't hold our state mutex while calling phy_set_asym_pause().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) phy_set_asym_pause(pl->phydev, pause->rx_pause,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) pause->tx_pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) /* If the manual pause settings changed, make sure we trigger a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) * resolve to update their state; we can not guarantee that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) * link will cycle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) if (manual_changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) pl->mac_link_dropped = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) phylink_run_resolve(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) * phylink_ethtool_get_eee_err() - read the energy efficient ethernet error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) * counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) * @pl: a pointer to a &struct phylink returned from phylink_create().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) * Read the Energy Efficient Ethernet error counter from the PHY associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) * with the phylink instance specified by @pl.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) * Returns positive error counter value, or negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) int phylink_get_eee_err(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) ret = phy_get_eee_err(pl->phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) EXPORT_SYMBOL_GPL(phylink_get_eee_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) * phylink_init_eee() - init and check the EEE features
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) * @clk_stop_enable: allow PHY to stop receive clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) * Must be called either with RTNL held or within mac_link_up()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) int phylink_init_eee(struct phylink *pl, bool clk_stop_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) int ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) ret = phy_init_eee(pl->phydev, clk_stop_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) EXPORT_SYMBOL_GPL(phylink_init_eee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) * phylink_ethtool_get_eee() - read the energy efficient ethernet parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) * @eee: a pointer to a &struct ethtool_eee for the read parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) int phylink_ethtool_get_eee(struct phylink *pl, struct ethtool_eee *eee)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) int ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) ret = phy_ethtool_get_eee(pl->phydev, eee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) EXPORT_SYMBOL_GPL(phylink_ethtool_get_eee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) * phylink_ethtool_set_eee() - set the energy efficient ethernet parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) * @eee: a pointer to a &struct ethtool_eee for the desired parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) int phylink_ethtool_set_eee(struct phylink *pl, struct ethtool_eee *eee)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) int ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) ret = phy_ethtool_set_eee(pl->phydev, eee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) EXPORT_SYMBOL_GPL(phylink_ethtool_set_eee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) /* This emulates MII registers for a fixed-mode phy operating as per the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) * passed in state. "aneg" defines if we report negotiation is possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) * FIXME: should deal with negotiation state too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) static int phylink_mii_emul_read(unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) struct fixed_phy_status fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) unsigned long *lpa = state->lp_advertising;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) fs.link = state->link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) fs.speed = state->speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) fs.duplex = state->duplex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) fs.pause = test_bit(ETHTOOL_LINK_MODE_Pause_BIT, lpa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) fs.asym_pause = test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, lpa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) val = swphy_read_reg(reg, &fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) if (reg == MII_BMSR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (!state->an_complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) val &= ~BMSR_ANEGCOMPLETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) static int phylink_phy_read(struct phylink *pl, unsigned int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) struct phy_device *phydev = pl->phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) int prtad, devad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) if (mdio_phy_id_is_c45(phy_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) prtad = mdio_phy_id_prtad(phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) devad = mdio_phy_id_devad(phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) devad = mdiobus_c45_addr(devad, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) } else if (phydev->is_c45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) case MII_BMCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) case MII_BMSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) case MII_PHYSID1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) case MII_PHYSID2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) devad = __ffs(phydev->c45_ids.mmds_present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) case MII_ADVERTISE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) case MII_LPA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) if (!(phydev->c45_ids.mmds_present & MDIO_DEVS_AN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) devad = MDIO_MMD_AN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (reg == MII_ADVERTISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) reg = MDIO_AN_ADVERTISE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) reg = MDIO_AN_LPA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) prtad = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) devad = mdiobus_c45_addr(devad, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) prtad = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) devad = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) return mdiobus_read(pl->phydev->mdio.bus, prtad, devad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) static int phylink_phy_write(struct phylink *pl, unsigned int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) unsigned int reg, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) struct phy_device *phydev = pl->phydev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) int prtad, devad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) if (mdio_phy_id_is_c45(phy_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) prtad = mdio_phy_id_prtad(phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) devad = mdio_phy_id_devad(phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) devad = mdiobus_c45_addr(devad, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) } else if (phydev->is_c45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) case MII_BMCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) case MII_BMSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) case MII_PHYSID1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) case MII_PHYSID2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) devad = __ffs(phydev->c45_ids.mmds_present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) case MII_ADVERTISE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) case MII_LPA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) if (!(phydev->c45_ids.mmds_present & MDIO_DEVS_AN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) devad = MDIO_MMD_AN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) if (reg == MII_ADVERTISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) reg = MDIO_AN_ADVERTISE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) reg = MDIO_AN_LPA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) prtad = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) devad = mdiobus_c45_addr(devad, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) prtad = phy_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) devad = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) return mdiobus_write(phydev->mdio.bus, prtad, devad, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) static int phylink_mii_read(struct phylink *pl, unsigned int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) struct phylink_link_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) int val = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) switch (pl->cur_link_an_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) case MLO_AN_FIXED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) if (phy_id == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) phylink_get_fixed_state(pl, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) val = phylink_mii_emul_read(reg, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) case MLO_AN_PHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) case MLO_AN_INBAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) if (phy_id == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) phylink_mac_pcs_get_state(pl, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) val = phylink_mii_emul_read(reg, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) return val & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) static int phylink_mii_write(struct phylink *pl, unsigned int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) unsigned int reg, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) switch (pl->cur_link_an_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) case MLO_AN_FIXED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) case MLO_AN_PHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) case MLO_AN_INBAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) * phylink_mii_ioctl() - generic mii ioctl interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) * @ifr: a pointer to a &struct ifreq for socket ioctls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) * @cmd: ioctl cmd to execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) * Perform the specified MII ioctl on the PHY attached to the phylink instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) * specified by @pl. If no PHY is attached, emulate the presence of the PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) * Returns: zero on success or negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) * %SIOCGMIIPHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) * read register from the current PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) * %SIOCGMIIREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) * read register from the specified PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) * %SIOCSMIIREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) * set a register on the specified PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) int phylink_mii_ioctl(struct phylink *pl, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) struct mii_ioctl_data *mii = if_mii(ifr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) if (pl->phydev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) /* PHYs only exist for MLO_AN_PHY and SGMII */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) case SIOCGMIIPHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) mii->phy_id = pl->phydev->mdio.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) case SIOCGMIIREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) ret = phylink_phy_read(pl, mii->phy_id, mii->reg_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) mii->val_out = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) case SIOCSMIIREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) ret = phylink_phy_write(pl, mii->phy_id, mii->reg_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) mii->val_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) ret = phy_mii_ioctl(pl->phydev, ifr, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) case SIOCGMIIPHY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) mii->phy_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) case SIOCGMIIREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) ret = phylink_mii_read(pl, mii->phy_id, mii->reg_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) mii->val_out = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) case SIOCSMIIREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) ret = phylink_mii_write(pl, mii->phy_id, mii->reg_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) mii->val_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) EXPORT_SYMBOL_GPL(phylink_mii_ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) * phylink_speed_down() - set the non-SFP PHY to lowest speed supported by both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) * link partners
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) * @sync: perform action synchronously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) * If we have a PHY that is not part of a SFP module, then set the speed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) * as described in the phy_speed_down() function. Please see this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) * for a description of the @sync parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) * Returns zero if there is no PHY, otherwise as per phy_speed_down().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) int phylink_speed_down(struct phylink *pl, bool sync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) if (!pl->sfp_bus && pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) ret = phy_speed_down(pl->phydev, sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) EXPORT_SYMBOL_GPL(phylink_speed_down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) * phylink_speed_up() - restore the advertised speeds prior to the call to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) * phylink_speed_down()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) * @pl: a pointer to a &struct phylink returned from phylink_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) * If we have a PHY that is not part of a SFP module, then restore the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) * PHY speeds as per phy_speed_up().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) * Returns zero if there is no PHY, otherwise as per phy_speed_up().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) int phylink_speed_up(struct phylink *pl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) if (!pl->sfp_bus && pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) ret = phy_speed_up(pl->phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) EXPORT_SYMBOL_GPL(phylink_speed_up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) static void phylink_sfp_attach(void *upstream, struct sfp_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) struct phylink *pl = upstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) pl->netdev->sfp_bus = bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) static void phylink_sfp_detach(void *upstream, struct sfp_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) struct phylink *pl = upstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) pl->netdev->sfp_bus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) static int phylink_sfp_config(struct phylink *pl, u8 mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) const unsigned long *supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) const unsigned long *advertising)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) __ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) __ETHTOOL_DECLARE_LINK_MODE_MASK(support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) struct phylink_link_state config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) phy_interface_t iface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) bool changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) linkmode_copy(support, supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) memset(&config, 0, sizeof(config));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) linkmode_copy(config.advertising, advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) config.interface = PHY_INTERFACE_MODE_NA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) config.speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) config.duplex = DUPLEX_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) config.pause = MLO_PAUSE_AN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) config.an_enabled = pl->link_config.an_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) /* Ignore errors if we're expecting a PHY to attach later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) ret = phylink_validate(pl, support, &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) phylink_err(pl, "validation with support %*pb failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) iface = sfp_select_interface(pl->sfp_bus, config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) if (iface == PHY_INTERFACE_MODE_NA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) phylink_err(pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) "selection of interface failed, advertisement %*pb\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) __ETHTOOL_LINK_MODE_MASK_NBITS, config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) config.interface = iface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) linkmode_copy(support1, support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) ret = phylink_validate(pl, support1, &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) phylink_err(pl, "validation of %s/%s with support %*pb failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) phylink_an_mode_str(mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) phy_modes(config.interface),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) phylink_an_mode_str(mode), phy_modes(config.interface),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) __ETHTOOL_LINK_MODE_MASK_NBITS, support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) if (phy_interface_mode_is_8023z(iface) && pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) changed = !linkmode_equal(pl->supported, support) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) !linkmode_equal(pl->link_config.advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) if (changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) linkmode_copy(pl->supported, support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) linkmode_copy(pl->link_config.advertising, config.advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) if (pl->cur_link_an_mode != mode ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) pl->link_config.interface != config.interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) pl->link_config.interface = config.interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) pl->cur_link_an_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) phylink_info(pl, "switched to %s/%s link mode\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) phylink_an_mode_str(mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) phy_modes(config.interface));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) pl->link_port = pl->sfp_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) if (changed && !test_bit(PHYLINK_DISABLE_STOPPED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) &pl->phylink_disable_state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) phylink_mac_initial_config(pl, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) static int phylink_sfp_module_insert(void *upstream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) const struct sfp_eeprom_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) struct phylink *pl = upstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) unsigned long *support = pl->sfp_support;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) linkmode_zero(support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) sfp_parse_support(pl->sfp_bus, id, support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) /* If this module may have a PHY connecting later, defer until later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) pl->sfp_may_have_phy = sfp_may_have_phy(pl->sfp_bus, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) if (pl->sfp_may_have_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) return phylink_sfp_config(pl, MLO_AN_INBAND, support, support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) static int phylink_sfp_module_start(void *upstream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) struct phylink *pl = upstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) /* If this SFP module has a PHY, start the PHY now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) if (pl->phydev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) phy_start(pl->phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) /* If the module may have a PHY but we didn't detect one we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) * need to configure the MAC here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) if (!pl->sfp_may_have_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) return phylink_sfp_config(pl, MLO_AN_INBAND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) pl->sfp_support, pl->sfp_support);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) static void phylink_sfp_module_stop(void *upstream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) struct phylink *pl = upstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) /* If this SFP module has a PHY, stop it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) if (pl->phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) phy_stop(pl->phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) static void phylink_sfp_link_down(void *upstream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) struct phylink *pl = upstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) static void phylink_sfp_link_up(void *upstream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) struct phylink *pl = upstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) clear_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) phylink_run_resolve(pl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) /* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) * or 802.3z control word, so inband will not work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) static bool phylink_phy_no_inband(struct phy_device *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) return phy->is_c45 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) struct phylink *pl = upstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) phy_interface_t interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) u8 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) * This is the new way of dealing with flow control for PHYs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) * as described by Timur Tabi in commit 529ed1275263 ("net: phy:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) * phy drivers should not set SUPPORTED_[Asym_]Pause") except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) * using our validate call to the MAC, we rely upon the MAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) * clearing the bits from both supported and advertising fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) phy_support_asym_pause(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) if (phylink_phy_no_inband(phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) mode = MLO_AN_PHY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) mode = MLO_AN_INBAND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) /* Do the initial configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) ret = phylink_sfp_config(pl, mode, phy->supported, phy->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) interface = pl->link_config.interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) ret = phylink_attach_phy(pl, phy, interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) ret = phylink_bringup_phy(pl, phy, interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) phy_detach(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) static void phylink_sfp_disconnect_phy(void *upstream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) phylink_disconnect_phy(upstream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) static const struct sfp_upstream_ops sfp_phylink_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) .attach = phylink_sfp_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) .detach = phylink_sfp_detach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) .module_insert = phylink_sfp_module_insert,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) .module_start = phylink_sfp_module_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) .module_stop = phylink_sfp_module_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) .link_up = phylink_sfp_link_up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) .link_down = phylink_sfp_link_down,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) .connect_phy = phylink_sfp_connect_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) .disconnect_phy = phylink_sfp_disconnect_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) /* Helpers for MAC drivers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) * phylink_helper_basex_speed() - 1000BaseX/2500BaseX helper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) * @state: a pointer to a &struct phylink_link_state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) * Inspect the interface mode, advertising mask or forced speed and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) * decide whether to run at 2.5Gbit or 1Gbit appropriately, switching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) * the interface mode to suit. @state->interface is appropriately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) * updated, and the advertising mask has the "other" baseX_Full flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) * cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) void phylink_helper_basex_speed(struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) if (phy_interface_mode_is_8023z(state->interface)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) bool want_2500 = state->an_enabled ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) phylink_test(state->advertising, 2500baseX_Full) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) state->speed == SPEED_2500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) if (want_2500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) phylink_clear(state->advertising, 1000baseX_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) state->interface = PHY_INTERFACE_MODE_2500BASEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) phylink_clear(state->advertising, 2500baseX_Full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) state->interface = PHY_INTERFACE_MODE_1000BASEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) EXPORT_SYMBOL_GPL(phylink_helper_basex_speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) static void phylink_decode_c37_word(struct phylink_link_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) uint16_t config_reg, int speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) bool tx_pause, rx_pause;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) int fd_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) if (speed == SPEED_2500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) fd_bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) fd_bit = ETHTOOL_LINK_MODE_1000baseX_Full_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) mii_lpa_mod_linkmode_x(state->lp_advertising, config_reg, fd_bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) if (linkmode_test_bit(fd_bit, state->advertising) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) linkmode_test_bit(fd_bit, state->lp_advertising)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) state->speed = speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) state->duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) /* negotiation failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) state->link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) linkmode_resolve_pause(state->advertising, state->lp_advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) &tx_pause, &rx_pause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) if (tx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) state->pause |= MLO_PAUSE_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) if (rx_pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) state->pause |= MLO_PAUSE_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) static void phylink_decode_sgmii_word(struct phylink_link_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) uint16_t config_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) if (!(config_reg & LPA_SGMII_LINK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) state->link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) switch (config_reg & LPA_SGMII_SPD_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) case LPA_SGMII_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) state->speed = SPEED_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) case LPA_SGMII_100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) state->speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) case LPA_SGMII_1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) state->speed = SPEED_1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) state->link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) if (config_reg & LPA_SGMII_FULL_DUPLEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) state->duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) state->duplex = DUPLEX_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) * phylink_decode_usxgmii_word() - decode the USXGMII word from a MAC PCS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) * @state: a pointer to a struct phylink_link_state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) * @lpa: a 16 bit value which stores the USXGMII auto-negotiation word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) * Helper for MAC PCS supporting the USXGMII protocol and the auto-negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) * code word. Decode the USXGMII code word and populate the corresponding fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) * (speed, duplex) into the phylink_link_state structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) void phylink_decode_usxgmii_word(struct phylink_link_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) uint16_t lpa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) switch (lpa & MDIO_USXGMII_SPD_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) case MDIO_USXGMII_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) state->speed = SPEED_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) case MDIO_USXGMII_100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) state->speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) case MDIO_USXGMII_1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) state->speed = SPEED_1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) case MDIO_USXGMII_2500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) state->speed = SPEED_2500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) case MDIO_USXGMII_5000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) state->speed = SPEED_5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) case MDIO_USXGMII_10G:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) state->speed = SPEED_10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) state->link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) if (lpa & MDIO_USXGMII_FULL_DUPLEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) state->duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) state->duplex = DUPLEX_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) EXPORT_SYMBOL_GPL(phylink_decode_usxgmii_word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) * phylink_mii_c22_pcs_get_state() - read the MAC PCS state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) * @pcs: a pointer to a &struct mdio_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) * @state: a pointer to a &struct phylink_link_state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) * Helper for MAC PCS supporting the 802.3 clause 22 register set for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) * clause 37 negotiation and/or SGMII control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) * Read the MAC PCS state from the MII device configured in @config and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) * parse the Clause 37 or Cisco SGMII link partner negotiation word into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) * the phylink @state structure. This is suitable to be directly plugged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) * into the mac_pcs_get_state() member of the struct phylink_mac_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) * structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) struct mii_bus *bus = pcs->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) int addr = pcs->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) int bmsr, lpa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) bmsr = mdiobus_read(bus, addr, MII_BMSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) lpa = mdiobus_read(bus, addr, MII_LPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) if (bmsr < 0 || lpa < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) state->link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) state->link = !!(bmsr & BMSR_LSTATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) if (!state->link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) switch (state->interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) case PHY_INTERFACE_MODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) phylink_decode_c37_word(state, lpa, SPEED_1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) case PHY_INTERFACE_MODE_2500BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) phylink_decode_c37_word(state, lpa, SPEED_2500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) case PHY_INTERFACE_MODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) case PHY_INTERFACE_MODE_QSGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) phylink_decode_sgmii_word(state, lpa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) state->link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) * phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) * advertisement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) * @pcs: a pointer to a &struct mdio_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) * @interface: the PHY interface mode being configured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) * @advertising: the ethtool advertisement mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) * Helper for MAC PCS supporting the 802.3 clause 22 register set for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) * clause 37 negotiation and/or SGMII control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) * Configure the clause 37 PCS advertisement as specified by @state. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) * does not trigger a renegotiation; phylink will do that via the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) * mac_an_restart() method of the struct phylink_mac_ops structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) * Returns negative error code on failure to configure the advertisement,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) * zero if no change has been made, or one if the advertisement has changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) phy_interface_t interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) const unsigned long *advertising)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) struct mii_bus *bus = pcs->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) int addr = pcs->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) int val, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) u16 adv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) switch (interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) case PHY_INTERFACE_MODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) case PHY_INTERFACE_MODE_2500BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) adv = ADVERTISE_1000XFULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) advertising))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) adv |= ADVERTISE_1000XPAUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) advertising))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) adv |= ADVERTISE_1000XPSE_ASYM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) val = mdiobus_read(bus, addr, MII_ADVERTISE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) if (val == adv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) ret = mdiobus_write(bus, addr, MII_ADVERTISE, adv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) case PHY_INTERFACE_MODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) val = mdiobus_read(bus, addr, MII_ADVERTISE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) if (val == 0x0001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) ret = mdiobus_write(bus, addr, MII_ADVERTISE, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) /* Nothing to do for other modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_set_advertisement);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) * phylink_mii_c22_pcs_config() - configure clause 22 PCS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) * @pcs: a pointer to a &struct mdio_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) * @mode: link autonegotiation mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) * @interface: the PHY interface mode being configured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) * @advertising: the ethtool advertisement mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) * Configure a Clause 22 PCS PHY with the appropriate negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) * parameters for the @mode, @interface and @advertising parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) * Returns negative error number on failure, zero if the advertisement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) * has not changed, or positive if there is a change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) phy_interface_t interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) const unsigned long *advertising)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) bool changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) u16 bmcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) ret = phylink_mii_c22_pcs_set_advertisement(pcs, interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) changed = ret > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) bmcr = mode == MLO_AN_INBAND ? BMCR_ANENABLE : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) ret = mdiobus_modify(pcs->bus, pcs->addr, MII_BMCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) BMCR_ANENABLE, bmcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) return changed ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) * phylink_mii_c22_pcs_an_restart() - restart 802.3z autonegotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) * @pcs: a pointer to a &struct mdio_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) * Helper for MAC PCS supporting the 802.3 clause 22 register set for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) * clause 37 negotiation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) * Restart the clause 37 negotiation with the link partner. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) * suitable to be directly plugged into the mac_pcs_get_state() member
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) * of the struct phylink_mac_ops structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) struct mii_bus *bus = pcs->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) int val, addr = pcs->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) val = mdiobus_read(bus, addr, MII_BMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) if (val >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) val |= BMCR_ANRESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) mdiobus_write(bus, addr, MII_BMCR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_an_restart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) struct mii_bus *bus = pcs->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) int addr = pcs->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) int stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) stat = mdiobus_c45_read(bus, addr, MDIO_MMD_PCS, MDIO_STAT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) if (stat < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) state->link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) state->link = !!(stat & MDIO_STAT1_LSTATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) if (!state->link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) switch (state->interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) case PHY_INTERFACE_MODE_10GBASER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) state->speed = SPEED_10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) state->duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) EXPORT_SYMBOL_GPL(phylink_mii_c45_pcs_get_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) MODULE_LICENSE("GPL v2");