Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'net-phylink-improve-phy-validation'

Russell King says:

====================
net: phylink: improve PHY validation

One of the issues which has concerned me about the rate matching
implenentation that we have is that phy_get_rate_matching() returns
whether rate matching will be used for a particular interface, and we
enquire only for one interface.

Aquantia PHYs can be programmed with the rate matching and interface
mode settings on a per-media speed basis using the per-speed vendor 1
global configuration registers.

Thus, it is possible for the PHY to be configured to use rate matching
for 10G, 5G, 2.5G with 10GBASE-R, and then SGMII for the remaining
speeds. Therefore, it clearly doesn't make sense to enquire about rate
matching for just one interface mode.

Also, PHYs that change their interfaces are handled sub-optimally, in
that we validate all the interface modes that the host supports, rather
than the interface modes that the PHY will use.

This patch series changes the way we validate PHYs, but in order to do
so, we need to know exactly which interface modes will be used by the
PHY. So that phylib can convey this information, we add
"possible_interfaces" to struct phy_device.

possible_interfaces is to be filled in by a phylib driver once the PHY
is configured (in other words in the PHYs .config_init method) with the
interface modes that it will switch between. This then allows users of
phylib to know which interface modes will be used by the PHY.

This allows us to solve both these issues: where possible_interfaces is
provided, we can validate which ethtool link modes can be supported by
looking at which interface modes that both the PHY and host support,
and request rate matching information for each mode.

This should improve the accuracy of the validation.

Sending this out again without RFC as Jie Luo will need it for the
QCA8084 changes. No changes except to add the attributations already
received. Thanks!
====================

Link: https://lore.kernel.org/r/ZWCWn+uNkVLPaQhn@shell.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+356 -128
+5
drivers/net/phy/aquantia/aquantia.h
··· 47 47 #define VEND1_GLOBAL_CFG_5G 0x031e 48 48 #define VEND1_GLOBAL_CFG_10G 0x031f 49 49 /* ...and now the fields */ 50 + #define VEND1_GLOBAL_CFG_SERDES_MODE GENMASK(2, 0) 51 + #define VEND1_GLOBAL_CFG_SERDES_MODE_XFI 0 52 + #define VEND1_GLOBAL_CFG_SERDES_MODE_SGMII 3 53 + #define VEND1_GLOBAL_CFG_SERDES_MODE_OCSGMII 4 54 + #define VEND1_GLOBAL_CFG_SERDES_MODE_XFI5G 6 50 55 #define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) 51 56 #define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 52 57 #define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1
+75 -1
drivers/net/phy/aquantia/aquantia_main.c
··· 656 656 return aqr107_wait_processor_intensive_op(phydev); 657 657 } 658 658 659 + static const u16 aqr_global_cfg_regs[] = { 660 + VEND1_GLOBAL_CFG_10M, 661 + VEND1_GLOBAL_CFG_100M, 662 + VEND1_GLOBAL_CFG_1G, 663 + VEND1_GLOBAL_CFG_2_5G, 664 + VEND1_GLOBAL_CFG_5G, 665 + VEND1_GLOBAL_CFG_10G 666 + }; 667 + 668 + static int aqr107_fill_interface_modes(struct phy_device *phydev) 669 + { 670 + unsigned long *possible = phydev->possible_interfaces; 671 + unsigned int serdes_mode, rate_adapt; 672 + phy_interface_t interface; 673 + int i, val; 674 + 675 + /* Walk the media-speed configuration registers to determine which 676 + * host-side serdes modes may be used by the PHY depending on the 677 + * negotiated media speed. 678 + */ 679 + for (i = 0; i < ARRAY_SIZE(aqr_global_cfg_regs); i++) { 680 + val = phy_read_mmd(phydev, MDIO_MMD_VEND1, 681 + aqr_global_cfg_regs[i]); 682 + if (val < 0) 683 + return val; 684 + 685 + serdes_mode = FIELD_GET(VEND1_GLOBAL_CFG_SERDES_MODE, val); 686 + rate_adapt = FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val); 687 + 688 + switch (serdes_mode) { 689 + case VEND1_GLOBAL_CFG_SERDES_MODE_XFI: 690 + if (rate_adapt == VEND1_GLOBAL_CFG_RATE_ADAPT_USX) 691 + interface = PHY_INTERFACE_MODE_USXGMII; 692 + else 693 + interface = PHY_INTERFACE_MODE_10GBASER; 694 + break; 695 + 696 + case VEND1_GLOBAL_CFG_SERDES_MODE_XFI5G: 697 + interface = PHY_INTERFACE_MODE_5GBASER; 698 + break; 699 + 700 + case VEND1_GLOBAL_CFG_SERDES_MODE_OCSGMII: 701 + interface = PHY_INTERFACE_MODE_2500BASEX; 702 + break; 703 + 704 + case VEND1_GLOBAL_CFG_SERDES_MODE_SGMII: 705 + interface = PHY_INTERFACE_MODE_SGMII; 706 + break; 707 + 708 + default: 709 + phydev_warn(phydev, "unrecognised serdes mode %u\n", 710 + serdes_mode); 711 + interface = PHY_INTERFACE_MODE_NA; 712 + break; 713 + } 714 + 715 + if (interface != PHY_INTERFACE_MODE_NA) 716 + __set_bit(interface, possible); 717 + } 718 + 719 + return 0; 720 + } 721 + 722 + static int aqr113c_config_init(struct phy_device *phydev) 723 + { 724 + int ret; 725 + 726 + ret = aqr107_config_init(phydev); 727 + if (ret < 0) 728 + return ret; 729 + 730 + return aqr107_fill_interface_modes(phydev); 731 + } 732 + 659 733 static int aqr107_probe(struct phy_device *phydev) 660 734 { 661 735 int ret; ··· 868 794 .name = "Aquantia AQR113C", 869 795 .probe = aqr107_probe, 870 796 .get_rate_matching = aqr107_get_rate_matching, 871 - .config_init = aqr107_config_init, 797 + .config_init = aqr113c_config_init, 872 798 .config_aneg = aqr_config_aneg, 873 799 .config_intr = aqr_config_intr, 874 800 .handle_interrupt = aqr_handle_interrupt,
+12
drivers/net/phy/bcm84881.c
··· 29 29 100000, 2000000, false); 30 30 } 31 31 32 + static void bcm84881_fill_possible_interfaces(struct phy_device *phydev) 33 + { 34 + unsigned long *possible = phydev->possible_interfaces; 35 + 36 + __set_bit(PHY_INTERFACE_MODE_SGMII, possible); 37 + __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible); 38 + __set_bit(PHY_INTERFACE_MODE_10GBASER, possible); 39 + } 40 + 32 41 static int bcm84881_config_init(struct phy_device *phydev) 33 42 { 43 + bcm84881_fill_possible_interfaces(phydev); 44 + 34 45 switch (phydev->interface) { 35 46 case PHY_INTERFACE_MODE_SGMII: 36 47 case PHY_INTERFACE_MODE_2500BASEX: ··· 50 39 default: 51 40 return -ENODEV; 52 41 } 42 + 53 43 return 0; 54 44 } 55 45
+135 -74
drivers/net/phy/marvell10g.c
··· 141 141 MV_V2_TEMP_UNKNOWN = 0x9600, /* unknown function */ 142 142 }; 143 143 144 + struct mv3310_mactype { 145 + bool valid; 146 + bool fixed_interface; 147 + phy_interface_t interface_10g; 148 + }; 149 + 144 150 struct mv3310_chip { 145 151 bool (*has_downshift)(struct phy_device *phydev); 146 152 void (*init_supported_interfaces)(unsigned long *mask); 147 153 int (*get_mactype)(struct phy_device *phydev); 148 154 int (*set_mactype)(struct phy_device *phydev, int mactype); 149 155 int (*select_mactype)(unsigned long *interfaces); 150 - int (*init_interface)(struct phy_device *phydev, int mactype); 156 + 157 + const struct mv3310_mactype *mactypes; 158 + size_t n_mactypes; 151 159 152 160 #ifdef CONFIG_HWMON 153 161 int (*hwmon_read_temp_reg)(struct phy_device *phydev); ··· 164 156 165 157 struct mv3310_priv { 166 158 DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX); 159 + const struct mv3310_mactype *mactype; 167 160 168 161 u32 firmware_ver; 169 162 bool has_downshift; 170 - bool rate_match; 171 - phy_interface_t const_interface; 172 163 173 164 struct device *hwmon_dev; 174 165 char *hwmon_name; ··· 709 702 return -1; 710 703 } 711 704 712 - static int mv2110_init_interface(struct phy_device *phydev, int mactype) 705 + static const struct mv3310_mactype mv2110_mactypes[] = { 706 + [MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII] = { 707 + .valid = true, 708 + .fixed_interface = true, 709 + .interface_10g = PHY_INTERFACE_MODE_USXGMII, 710 + }, 711 + [MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER] = { 712 + .valid = true, 713 + .interface_10g = PHY_INTERFACE_MODE_NA, 714 + }, 715 + [MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN] = { 716 + .valid = true, 717 + .interface_10g = PHY_INTERFACE_MODE_NA, 718 + }, 719 + [MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = { 720 + .valid = true, 721 + .fixed_interface = true, 722 + .interface_10g = PHY_INTERFACE_MODE_10GBASER, 723 + }, 724 + }; 725 + 726 + static const struct mv3310_mactype mv3310_mactypes[] = { 727 + [MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI] = { 728 + .valid = true, 729 + .interface_10g = PHY_INTERFACE_MODE_RXAUI, 730 + }, 731 + [MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH] = { 732 + .valid = true, 733 + .fixed_interface = true, 734 + .interface_10g = PHY_INTERFACE_MODE_XAUI, 735 + }, 736 + [MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH] = { 737 + .valid = true, 738 + .fixed_interface = true, 739 + .interface_10g = PHY_INTERFACE_MODE_RXAUI, 740 + }, 741 + [MV_V2_3310_PORT_CTRL_MACTYPE_XAUI] = { 742 + .valid = true, 743 + .interface_10g = PHY_INTERFACE_MODE_XAUI, 744 + }, 745 + [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER] = { 746 + .valid = true, 747 + .interface_10g = PHY_INTERFACE_MODE_10GBASER, 748 + }, 749 + [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN] = { 750 + .valid = true, 751 + .interface_10g = PHY_INTERFACE_MODE_10GBASER, 752 + }, 753 + [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = { 754 + .valid = true, 755 + .fixed_interface = true, 756 + .interface_10g = PHY_INTERFACE_MODE_10GBASER, 757 + }, 758 + [MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII] = { 759 + .valid = true, 760 + .fixed_interface = true, 761 + .interface_10g = PHY_INTERFACE_MODE_USXGMII, 762 + }, 763 + }; 764 + 765 + static const struct mv3310_mactype mv3340_mactypes[] = { 766 + [MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI] = { 767 + .valid = true, 768 + .interface_10g = PHY_INTERFACE_MODE_RXAUI, 769 + }, 770 + [MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN] = { 771 + .valid = true, 772 + .interface_10g = PHY_INTERFACE_MODE_RXAUI, 773 + }, 774 + [MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH] = { 775 + .valid = true, 776 + .fixed_interface = true, 777 + .interface_10g = PHY_INTERFACE_MODE_RXAUI, 778 + }, 779 + [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER] = { 780 + .valid = true, 781 + .interface_10g = PHY_INTERFACE_MODE_10GBASER, 782 + }, 783 + [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN] = { 784 + .valid = true, 785 + .interface_10g = PHY_INTERFACE_MODE_10GBASER, 786 + }, 787 + [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = { 788 + .valid = true, 789 + .fixed_interface = true, 790 + .interface_10g = PHY_INTERFACE_MODE_10GBASER, 791 + }, 792 + [MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII] = { 793 + .valid = true, 794 + .fixed_interface = true, 795 + .interface_10g = PHY_INTERFACE_MODE_USXGMII, 796 + }, 797 + }; 798 + 799 + static void mv3310_fill_possible_interfaces(struct phy_device *phydev) 713 800 { 714 801 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); 802 + unsigned long *possible = phydev->possible_interfaces; 803 + const struct mv3310_mactype *mactype = priv->mactype; 715 804 716 - priv->rate_match = false; 805 + if (mactype->interface_10g != PHY_INTERFACE_MODE_NA) 806 + __set_bit(priv->mactype->interface_10g, possible); 717 807 718 - if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH) 719 - priv->rate_match = true; 720 - 721 - if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII) 722 - priv->const_interface = PHY_INTERFACE_MODE_USXGMII; 723 - else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH) 724 - priv->const_interface = PHY_INTERFACE_MODE_10GBASER; 725 - else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER || 726 - mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN) 727 - priv->const_interface = PHY_INTERFACE_MODE_NA; 728 - else 729 - return -EINVAL; 730 - 731 - return 0; 732 - } 733 - 734 - static int mv3310_init_interface(struct phy_device *phydev, int mactype) 735 - { 736 - struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); 737 - 738 - priv->rate_match = false; 739 - 740 - if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH || 741 - mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH || 742 - mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH) 743 - priv->rate_match = true; 744 - 745 - if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII) 746 - priv->const_interface = PHY_INTERFACE_MODE_USXGMII; 747 - else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH || 748 - mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN || 749 - mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER) 750 - priv->const_interface = PHY_INTERFACE_MODE_10GBASER; 751 - else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH || 752 - mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI) 753 - priv->const_interface = PHY_INTERFACE_MODE_RXAUI; 754 - else if (mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH || 755 - mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI) 756 - priv->const_interface = PHY_INTERFACE_MODE_XAUI; 757 - else 758 - return -EINVAL; 759 - 760 - return 0; 761 - } 762 - 763 - static int mv3340_init_interface(struct phy_device *phydev, int mactype) 764 - { 765 - struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); 766 - int err = 0; 767 - 768 - priv->rate_match = false; 769 - 770 - if (mactype == MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN) 771 - priv->const_interface = PHY_INTERFACE_MODE_RXAUI; 772 - else 773 - err = mv3310_init_interface(phydev, mactype); 774 - 775 - return err; 808 + if (!mactype->fixed_interface) { 809 + __set_bit(PHY_INTERFACE_MODE_5GBASER, possible); 810 + __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible); 811 + __set_bit(PHY_INTERFACE_MODE_SGMII, possible); 812 + } 776 813 } 777 814 778 815 static int mv3310_config_init(struct phy_device *phydev) ··· 854 803 if (mactype < 0) 855 804 return mactype; 856 805 857 - err = chip->init_interface(phydev, mactype); 858 - if (err) { 806 + if (mactype >= chip->n_mactypes || !chip->mactypes[mactype].valid) { 859 807 phydev_err(phydev, "MACTYPE configuration invalid\n"); 860 - return err; 808 + return -EINVAL; 861 809 } 810 + 811 + priv->mactype = &chip->mactypes[mactype]; 812 + 813 + mv3310_fill_possible_interfaces(phydev); 862 814 863 815 /* Enable EDPD mode - saving 600mW */ 864 816 err = mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS); ··· 989 935 * 990 936 * In USXGMII mode the PHY interface mode is also fixed. 991 937 */ 992 - if (priv->rate_match || 993 - priv->const_interface == PHY_INTERFACE_MODE_USXGMII) { 994 - phydev->interface = priv->const_interface; 938 + if (priv->mactype->fixed_interface) { 939 + phydev->interface = priv->mactype->interface_10g; 995 940 return; 996 941 } 997 942 ··· 1002 949 */ 1003 950 switch (phydev->speed) { 1004 951 case SPEED_10000: 1005 - phydev->interface = priv->const_interface; 952 + phydev->interface = priv->mactype->interface_10g; 1006 953 break; 1007 954 case SPEED_5000: 1008 955 phydev->interface = PHY_INTERFACE_MODE_5GBASER; ··· 1216 1163 .get_mactype = mv3310_get_mactype, 1217 1164 .set_mactype = mv3310_set_mactype, 1218 1165 .select_mactype = mv3310_select_mactype, 1219 - .init_interface = mv3310_init_interface, 1166 + 1167 + .mactypes = mv3310_mactypes, 1168 + .n_mactypes = ARRAY_SIZE(mv3310_mactypes), 1220 1169 1221 1170 #ifdef CONFIG_HWMON 1222 1171 .hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg, ··· 1231 1176 .get_mactype = mv3310_get_mactype, 1232 1177 .set_mactype = mv3310_set_mactype, 1233 1178 .select_mactype = mv3310_select_mactype, 1234 - .init_interface = mv3340_init_interface, 1179 + 1180 + .mactypes = mv3340_mactypes, 1181 + .n_mactypes = ARRAY_SIZE(mv3340_mactypes), 1235 1182 1236 1183 #ifdef CONFIG_HWMON 1237 1184 .hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg, ··· 1245 1188 .get_mactype = mv2110_get_mactype, 1246 1189 .set_mactype = mv2110_set_mactype, 1247 1190 .select_mactype = mv2110_select_mactype, 1248 - .init_interface = mv2110_init_interface, 1191 + 1192 + .mactypes = mv2110_mactypes, 1193 + .n_mactypes = ARRAY_SIZE(mv2110_mactypes), 1249 1194 1250 1195 #ifdef CONFIG_HWMON 1251 1196 .hwmon_read_temp_reg = mv2110_hwmon_read_temp_reg, ··· 1259 1200 .get_mactype = mv2110_get_mactype, 1260 1201 .set_mactype = mv2110_set_mactype, 1261 1202 .select_mactype = mv2110_select_mactype, 1262 - .init_interface = mv2110_init_interface, 1203 + 1204 + .mactypes = mv2110_mactypes, 1205 + .n_mactypes = ARRAY_SIZE(mv2110_mactypes), 1263 1206 1264 1207 #ifdef CONFIG_HWMON 1265 1208 .hwmon_read_temp_reg = mv2110_hwmon_read_temp_reg,
+2
drivers/net/phy/phy_device.c
··· 1246 1246 if (ret < 0) 1247 1247 return ret; 1248 1248 1249 + phy_interface_zero(phydev->possible_interfaces); 1250 + 1249 1251 if (phydev->drv->config_init) { 1250 1252 ret = phydev->drv->config_init(phydev); 1251 1253 if (ret < 0)
+124 -53
drivers/net/phy/phylink.c
··· 121 121 }) 122 122 #endif 123 123 124 + static const phy_interface_t phylink_sfp_interface_preference[] = { 125 + PHY_INTERFACE_MODE_25GBASER, 126 + PHY_INTERFACE_MODE_USXGMII, 127 + PHY_INTERFACE_MODE_10GBASER, 128 + PHY_INTERFACE_MODE_5GBASER, 129 + PHY_INTERFACE_MODE_2500BASEX, 130 + PHY_INTERFACE_MODE_SGMII, 131 + PHY_INTERFACE_MODE_1000BASEX, 132 + PHY_INTERFACE_MODE_100BASEX, 133 + }; 134 + 135 + static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); 136 + 124 137 /** 125 138 * phylink_set_port_modes() - set the port type modes in the ethtool mask 126 139 * @mask: ethtool link mode mask ··· 702 689 return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; 703 690 } 704 691 705 - static int phylink_validate_mask(struct phylink *pl, unsigned long *supported, 692 + static void phylink_validate_one(struct phylink *pl, struct phy_device *phy, 693 + const unsigned long *supported, 694 + const struct phylink_link_state *state, 695 + phy_interface_t interface, 696 + unsigned long *accum_supported, 697 + unsigned long *accum_advertising) 698 + { 699 + __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_supported); 700 + struct phylink_link_state tmp_state; 701 + 702 + linkmode_copy(tmp_supported, supported); 703 + 704 + tmp_state = *state; 705 + tmp_state.interface = interface; 706 + 707 + if (phy) 708 + tmp_state.rate_matching = phy_get_rate_matching(phy, interface); 709 + 710 + if (!phylink_validate_mac_and_pcs(pl, tmp_supported, &tmp_state)) { 711 + phylink_dbg(pl, " interface %u (%s) rate match %s supports %*pbl\n", 712 + interface, phy_modes(interface), 713 + phy_rate_matching_to_str(tmp_state.rate_matching), 714 + __ETHTOOL_LINK_MODE_MASK_NBITS, tmp_supported); 715 + 716 + linkmode_or(accum_supported, accum_supported, tmp_supported); 717 + linkmode_or(accum_advertising, accum_advertising, 718 + tmp_state.advertising); 719 + } 720 + } 721 + 722 + static int phylink_validate_mask(struct phylink *pl, struct phy_device *phy, 723 + unsigned long *supported, 706 724 struct phylink_link_state *state, 707 725 const unsigned long *interfaces) 708 726 { 709 727 __ETHTOOL_DECLARE_LINK_MODE_MASK(all_adv) = { 0, }; 710 728 __ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, }; 711 - __ETHTOOL_DECLARE_LINK_MODE_MASK(s); 712 - struct phylink_link_state t; 713 729 int interface; 714 730 715 - for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) { 716 - linkmode_copy(s, supported); 717 - 718 - t = *state; 719 - t.interface = interface; 720 - if (!phylink_validate_mac_and_pcs(pl, s, &t)) { 721 - linkmode_or(all_s, all_s, s); 722 - linkmode_or(all_adv, all_adv, t.advertising); 723 - } 724 - } 731 + for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) 732 + phylink_validate_one(pl, phy, supported, state, interface, 733 + all_s, all_adv); 725 734 726 735 linkmode_copy(supported, all_s); 727 736 linkmode_copy(state->advertising, all_adv); ··· 757 722 const unsigned long *interfaces = pl->config->supported_interfaces; 758 723 759 724 if (state->interface == PHY_INTERFACE_MODE_NA) 760 - return phylink_validate_mask(pl, supported, state, interfaces); 725 + return phylink_validate_mask(pl, NULL, supported, state, 726 + interfaces); 761 727 762 728 if (!test_bit(state->interface, interfaces)) 763 729 return -EINVAL; ··· 1773 1737 phylink_pause_to_str(pl->phy_state.pause)); 1774 1738 } 1775 1739 1740 + static int phylink_validate_phy(struct phylink *pl, struct phy_device *phy, 1741 + unsigned long *supported, 1742 + struct phylink_link_state *state) 1743 + { 1744 + DECLARE_PHY_INTERFACE_MASK(interfaces); 1745 + 1746 + /* If the PHY provides a bitmap of the interfaces it will be using 1747 + * depending on the negotiated media speeds, use this to validate 1748 + * which ethtool link modes can be used. 1749 + */ 1750 + if (!phy_interface_empty(phy->possible_interfaces)) { 1751 + /* We only care about the union of the PHY's interfaces and 1752 + * those which the host supports. 1753 + */ 1754 + phy_interface_and(interfaces, phy->possible_interfaces, 1755 + pl->config->supported_interfaces); 1756 + 1757 + if (phy_interface_empty(interfaces)) { 1758 + phylink_err(pl, "PHY has no common interfaces\n"); 1759 + return -EINVAL; 1760 + } 1761 + 1762 + if (phy_on_sfp(phy)) { 1763 + /* If the PHY is on a SFP, limit the interfaces to 1764 + * those that can be used with a SFP module. 1765 + */ 1766 + phy_interface_and(interfaces, interfaces, 1767 + phylink_sfp_interfaces); 1768 + 1769 + if (phy_interface_empty(interfaces)) { 1770 + phylink_err(pl, "SFP PHY's possible interfaces becomes empty\n"); 1771 + return -EINVAL; 1772 + } 1773 + } 1774 + 1775 + phylink_dbg(pl, "PHY %s uses interfaces %*pbl, validating %*pbl\n", 1776 + phydev_name(phy), 1777 + (int)PHY_INTERFACE_MODE_MAX, 1778 + phy->possible_interfaces, 1779 + (int)PHY_INTERFACE_MODE_MAX, interfaces); 1780 + 1781 + return phylink_validate_mask(pl, phy, supported, state, 1782 + interfaces); 1783 + } 1784 + 1785 + /* Check whether we would use rate matching for the proposed interface 1786 + * mode. 1787 + */ 1788 + state->rate_matching = phy_get_rate_matching(phy, state->interface); 1789 + 1790 + /* Clause 45 PHYs may switch their Serdes lane between, e.g. 10GBASE-R, 1791 + * 5GBASE-R, 2500BASE-X and SGMII if they are not using rate matching. 1792 + * For some interface modes (e.g. RXAUI, XAUI and USXGMII) switching 1793 + * their Serdes is either unnecessary or not reasonable. 1794 + * 1795 + * For these which switch interface modes, we really need to know which 1796 + * interface modes the PHY supports to properly work out which ethtool 1797 + * linkmodes can be supported. For now, as a work-around, we validate 1798 + * against all interface modes, which may lead to more ethtool link 1799 + * modes being advertised than are actually supported. 1800 + */ 1801 + if (phy->is_c45 && state->rate_matching == RATE_MATCH_NONE && 1802 + state->interface != PHY_INTERFACE_MODE_RXAUI && 1803 + state->interface != PHY_INTERFACE_MODE_XAUI && 1804 + state->interface != PHY_INTERFACE_MODE_USXGMII) 1805 + state->interface = PHY_INTERFACE_MODE_NA; 1806 + 1807 + return phylink_validate(pl, supported, state); 1808 + } 1809 + 1776 1810 static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, 1777 1811 phy_interface_t interface) 1778 1812 { ··· 1863 1757 memset(&config, 0, sizeof(config)); 1864 1758 linkmode_copy(supported, phy->supported); 1865 1759 linkmode_copy(config.advertising, phy->advertising); 1760 + config.interface = interface; 1866 1761 1867 - /* Check whether we would use rate matching for the proposed interface 1868 - * mode. 1869 - */ 1870 - config.rate_matching = phy_get_rate_matching(phy, interface); 1871 - 1872 - /* Clause 45 PHYs may switch their Serdes lane between, e.g. 10GBASE-R, 1873 - * 5GBASE-R, 2500BASE-X and SGMII if they are not using rate matching. 1874 - * For some interface modes (e.g. RXAUI, XAUI and USXGMII) switching 1875 - * their Serdes is either unnecessary or not reasonable. 1876 - * 1877 - * For these which switch interface modes, we really need to know which 1878 - * interface modes the PHY supports to properly work out which ethtool 1879 - * linkmodes can be supported. For now, as a work-around, we validate 1880 - * against all interface modes, which may lead to more ethtool link 1881 - * modes being advertised than are actually supported. 1882 - */ 1883 - if (phy->is_c45 && config.rate_matching == RATE_MATCH_NONE && 1884 - interface != PHY_INTERFACE_MODE_RXAUI && 1885 - interface != PHY_INTERFACE_MODE_XAUI && 1886 - interface != PHY_INTERFACE_MODE_USXGMII) 1887 - config.interface = PHY_INTERFACE_MODE_NA; 1888 - else 1889 - config.interface = interface; 1890 - 1891 - ret = phylink_validate(pl, supported, &config); 1762 + ret = phylink_validate_phy(pl, phy, supported, &config); 1892 1763 if (ret) { 1893 1764 phylink_warn(pl, "validation of %s with support %*pb and advertisement %*pb failed: %pe\n", 1894 1765 phy_modes(config.interface), ··· 3086 3003 pl->netdev->sfp_bus = NULL; 3087 3004 } 3088 3005 3089 - static const phy_interface_t phylink_sfp_interface_preference[] = { 3090 - PHY_INTERFACE_MODE_25GBASER, 3091 - PHY_INTERFACE_MODE_USXGMII, 3092 - PHY_INTERFACE_MODE_10GBASER, 3093 - PHY_INTERFACE_MODE_5GBASER, 3094 - PHY_INTERFACE_MODE_2500BASEX, 3095 - PHY_INTERFACE_MODE_SGMII, 3096 - PHY_INTERFACE_MODE_1000BASEX, 3097 - PHY_INTERFACE_MODE_100BASEX, 3098 - }; 3099 - 3100 - static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); 3101 - 3102 3006 static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl, 3103 3007 const unsigned long *intf) 3104 3008 { ··· 3228 3158 /* For all the interfaces that are supported, reduce the sfp_support 3229 3159 * mask to only those link modes that can be supported. 3230 3160 */ 3231 - ret = phylink_validate_mask(pl, pl->sfp_support, &config, interfaces); 3161 + ret = phylink_validate_mask(pl, NULL, pl->sfp_support, &config, 3162 + interfaces); 3232 3163 if (ret) { 3233 3164 phylink_err(pl, "unsupported SFP module: validation with support %*pb failed\n", 3234 3165 __ETHTOOL_LINK_MODE_MASK_NBITS, support);
+3
include/linux/phy.h
··· 605 605 * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended, 606 606 * requiring a rerun of the interrupt handler after resume 607 607 * @interface: enum phy_interface_t value 608 + * @possible_interfaces: bitmap if interface modes that the attached PHY 609 + * will switch between depending on media speed. 608 610 * @skb: Netlink message for cable diagnostics 609 611 * @nest: Netlink nest used for cable diagnostics 610 612 * @ehdr: nNtlink header for cable diagnostics ··· 676 674 u32 dev_flags; 677 675 678 676 phy_interface_t interface; 677 + DECLARE_PHY_INTERFACE_MASK(possible_interfaces); 679 678 680 679 /* 681 680 * forced speed & duplex (no autoneg)