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

Merge branch 'ethtool-master-slave'

Oleksij Rempel says:

====================
provide support for PHY master/slave configuration

changes v6:
- use NL_SET_ERR_MSG_ATTR in ethnl_update_linkmodes
- add sanity checks in the ioctl interface
- use bool for ethnl_validate_master_slave_cfg()

changes v5:
- set MASTER_SLAVE_CFG_UNSUPPORTED as default value
- send a netlink error message on validation error
- more code fixes

changes v4:
- rename port_mode to master_slave
- move validation code to net/ethtool/linkmodes.c
- add UNSUPPORTED state and avoid sending unsupported fields
- more formatting and naming fixes
- tja11xx: support only force mode
- tja11xx: mark state as unsupported

changes v3:
- provide separate field for config and state.
- make state rejected on set
- add validation

changes v2:
- change names. Use MASTER_PREFERRED instead of MULTIPORT
- configure master/slave only on request. Default configuration can be
provided by PHY or eeprom
- status and configuration to the user space.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+240 -18
+19 -16
Documentation/networking/ethtool-netlink.rst
··· 392 392 393 393 Kernel response contents: 394 394 395 - ==================================== ====== ========================== 396 - ``ETHTOOL_A_LINKMODES_HEADER`` nested reply header 397 - ``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status 398 - ``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes 399 - ``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes 400 - ``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s) 401 - ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode 402 - ==================================== ====== ========================== 395 + ========================================== ====== ========================== 396 + ``ETHTOOL_A_LINKMODES_HEADER`` nested reply header 397 + ``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status 398 + ``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes 399 + ``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes 400 + ``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s) 401 + ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode 402 + ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode 403 + ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE`` u8 Master/slave port state 404 + ========================================== ====== ========================== 403 405 404 406 For ``ETHTOOL_A_LINKMODES_OURS``, value represents advertised modes and mask 405 407 represents supported modes. ``ETHTOOL_A_LINKMODES_PEER`` in the reply is a bit ··· 416 414 417 415 Request contents: 418 416 419 - ==================================== ====== ========================== 420 - ``ETHTOOL_A_LINKMODES_HEADER`` nested request header 421 - ``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status 422 - ``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes 423 - ``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes 424 - ``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s) 425 - ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode 426 - ==================================== ====== ========================== 417 + ========================================== ====== ========================== 418 + ``ETHTOOL_A_LINKMODES_HEADER`` nested request header 419 + ``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status 420 + ``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes 421 + ``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes 422 + ``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s) 423 + ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode 424 + ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode 425 + ========================================== ====== ========================== 427 426 428 427 ``ETHTOOL_A_LINKMODES_OURS`` bit set allows setting advertised link modes. If 429 428 autonegotiation is on (either set now or kept from before), advertised modes
+43
drivers/net/phy/nxp-tja11xx.c
··· 30 30 #define MII_ECTRL_WAKE_REQUEST BIT(0) 31 31 32 32 #define MII_CFG1 18 33 + #define MII_CFG1_MASTER_SLAVE BIT(15) 33 34 #define MII_CFG1_AUTO_OP BIT(14) 34 35 #define MII_CFG1_SLEEP_CONFIRM BIT(6) 35 36 #define MII_CFG1_LED_MODE_MASK GENMASK(5, 4) ··· 168 167 return genphy_soft_reset(phydev); 169 168 } 170 169 170 + static int tja11xx_config_aneg(struct phy_device *phydev) 171 + { 172 + u16 ctl = 0; 173 + int ret; 174 + 175 + switch (phydev->master_slave_set) { 176 + case MASTER_SLAVE_CFG_MASTER_FORCE: 177 + ctl |= MII_CFG1_MASTER_SLAVE; 178 + break; 179 + case MASTER_SLAVE_CFG_SLAVE_FORCE: 180 + break; 181 + case MASTER_SLAVE_CFG_UNKNOWN: 182 + case MASTER_SLAVE_CFG_UNSUPPORTED: 183 + return 0; 184 + default: 185 + phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 186 + return -ENOTSUPP; 187 + } 188 + 189 + ret = phy_modify_changed(phydev, MII_CFG1, MII_CFG1_MASTER_SLAVE, ctl); 190 + if (ret < 0) 191 + return ret; 192 + 193 + return __genphy_config_aneg(phydev, ret); 194 + } 195 + 171 196 static int tja11xx_config_init(struct phy_device *phydev) 172 197 { 173 198 int ret; ··· 251 224 { 252 225 int ret; 253 226 227 + phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; 228 + phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; 229 + 254 230 ret = genphy_update_link(phydev); 255 231 if (ret) 256 232 return ret; 233 + 234 + ret = phy_read(phydev, MII_CFG1); 235 + if (ret < 0) 236 + return ret; 237 + 238 + if (ret & MII_CFG1_MASTER_SLAVE) 239 + phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; 240 + else 241 + phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; 257 242 258 243 if (phydev->link) { 259 244 ret = phy_read(phydev, MII_COMMSTAT); ··· 543 504 .features = PHY_BASIC_T1_FEATURES, 544 505 .probe = tja11xx_probe, 545 506 .soft_reset = tja11xx_soft_reset, 507 + .config_aneg = tja11xx_config_aneg, 546 508 .config_init = tja11xx_config_init, 547 509 .read_status = tja11xx_read_status, 548 510 .suspend = genphy_suspend, ··· 559 519 .features = PHY_BASIC_T1_FEATURES, 560 520 .probe = tja11xx_probe, 561 521 .soft_reset = tja11xx_soft_reset, 522 + .config_aneg = tja11xx_config_aneg, 562 523 .config_init = tja11xx_config_init, 563 524 .read_status = tja11xx_read_status, 564 525 .suspend = genphy_suspend, ··· 574 533 .features = PHY_BASIC_T1_FEATURES, 575 534 .probe = tja1102_p0_probe, 576 535 .soft_reset = tja11xx_soft_reset, 536 + .config_aneg = tja11xx_config_aneg, 577 537 .config_init = tja11xx_config_init, 578 538 .read_status = tja11xx_read_status, 579 539 .match_phy_device = tja1102_p0_match_phy_device, ··· 593 551 .features = PHY_BASIC_T1_FEATURES, 594 552 /* currently no probe for Port 1 is need */ 595 553 .soft_reset = tja11xx_soft_reset, 554 + .config_aneg = tja11xx_config_aneg, 596 555 .config_init = tja11xx_config_init, 597 556 .read_status = tja11xx_read_status, 598 557 .match_phy_device = tja1102_p1_match_phy_device,
+3 -1
drivers/net/phy/phy.c
··· 295 295 phydev->advertising, autoneg == AUTONEG_ENABLE); 296 296 297 297 phydev->duplex = duplex; 298 - 298 + phydev->master_slave_set = cmd->base.master_slave_cfg; 299 299 phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl; 300 300 301 301 /* Restart the PHY */ ··· 314 314 315 315 cmd->base.speed = phydev->speed; 316 316 cmd->base.duplex = phydev->duplex; 317 + cmd->base.master_slave_cfg = phydev->master_slave_get; 318 + cmd->base.master_slave_state = phydev->master_slave_state; 317 319 if (phydev->interface == PHY_INTERFACE_MODE_MOCA) 318 320 cmd->base.port = PORT_BNC; 319 321 else
+94
drivers/net/phy/phy_device.c
··· 1913 1913 } 1914 1914 EXPORT_SYMBOL(genphy_setup_forced); 1915 1915 1916 + static int genphy_setup_master_slave(struct phy_device *phydev) 1917 + { 1918 + u16 ctl = 0; 1919 + 1920 + if (!phydev->is_gigabit_capable) 1921 + return 0; 1922 + 1923 + switch (phydev->master_slave_set) { 1924 + case MASTER_SLAVE_CFG_MASTER_PREFERRED: 1925 + ctl |= CTL1000_PREFER_MASTER; 1926 + break; 1927 + case MASTER_SLAVE_CFG_SLAVE_PREFERRED: 1928 + break; 1929 + case MASTER_SLAVE_CFG_MASTER_FORCE: 1930 + ctl |= CTL1000_AS_MASTER; 1931 + /* fallthrough */ 1932 + case MASTER_SLAVE_CFG_SLAVE_FORCE: 1933 + ctl |= CTL1000_ENABLE_MASTER; 1934 + break; 1935 + case MASTER_SLAVE_CFG_UNKNOWN: 1936 + case MASTER_SLAVE_CFG_UNSUPPORTED: 1937 + return 0; 1938 + default: 1939 + phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 1940 + return -EOPNOTSUPP; 1941 + } 1942 + 1943 + return phy_modify_changed(phydev, MII_CTRL1000, 1944 + (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER | 1945 + CTL1000_PREFER_MASTER), ctl); 1946 + } 1947 + 1948 + static int genphy_read_master_slave(struct phy_device *phydev) 1949 + { 1950 + int cfg, state; 1951 + u16 val; 1952 + 1953 + if (!phydev->is_gigabit_capable) { 1954 + phydev->master_slave_get = MASTER_SLAVE_CFG_UNSUPPORTED; 1955 + phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; 1956 + return 0; 1957 + } 1958 + 1959 + phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; 1960 + phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; 1961 + 1962 + val = phy_read(phydev, MII_CTRL1000); 1963 + if (val < 0) 1964 + return val; 1965 + 1966 + if (val & CTL1000_ENABLE_MASTER) { 1967 + if (val & CTL1000_AS_MASTER) 1968 + cfg = MASTER_SLAVE_CFG_MASTER_FORCE; 1969 + else 1970 + cfg = MASTER_SLAVE_CFG_SLAVE_FORCE; 1971 + } else { 1972 + if (val & CTL1000_PREFER_MASTER) 1973 + cfg = MASTER_SLAVE_CFG_MASTER_PREFERRED; 1974 + else 1975 + cfg = MASTER_SLAVE_CFG_SLAVE_PREFERRED; 1976 + } 1977 + 1978 + val = phy_read(phydev, MII_STAT1000); 1979 + if (val < 0) 1980 + return val; 1981 + 1982 + if (val & LPA_1000MSFAIL) { 1983 + state = MASTER_SLAVE_STATE_ERR; 1984 + } else if (phydev->link) { 1985 + /* this bits are valid only for active link */ 1986 + if (val & LPA_1000MSRES) 1987 + state = MASTER_SLAVE_STATE_MASTER; 1988 + else 1989 + state = MASTER_SLAVE_STATE_SLAVE; 1990 + } else { 1991 + state = MASTER_SLAVE_STATE_UNKNOWN; 1992 + } 1993 + 1994 + phydev->master_slave_get = cfg; 1995 + phydev->master_slave_state = state; 1996 + 1997 + return 0; 1998 + } 1999 + 1916 2000 /** 1917 2001 * genphy_restart_aneg - Enable and Restart Autonegotiation 1918 2002 * @phydev: target phy_device struct ··· 2053 1969 int err; 2054 1970 2055 1971 if (genphy_config_eee_advert(phydev)) 1972 + changed = true; 1973 + 1974 + err = genphy_setup_master_slave(phydev); 1975 + if (err < 0) 1976 + return err; 1977 + else if (err) 2056 1978 changed = true; 2057 1979 2058 1980 if (AUTONEG_ENABLE != phydev->autoneg) ··· 2294 2204 phydev->duplex = DUPLEX_UNKNOWN; 2295 2205 phydev->pause = 0; 2296 2206 phydev->asym_pause = 0; 2207 + 2208 + err = genphy_read_master_slave(phydev); 2209 + if (err < 0) 2210 + return err; 2297 2211 2298 2212 err = genphy_read_lpa(phydev); 2299 2213 if (err < 0)
+3
include/linux/phy.h
··· 477 477 int duplex; 478 478 int pause; 479 479 int asym_pause; 480 + u8 master_slave_get; 481 + u8 master_slave_set; 482 + u8 master_slave_state; 480 483 481 484 /* Union of PHY and Attached devices' supported link modes */ 482 485 /* See ethtool.h for more info */
+15 -1
include/uapi/linux/ethtool.h
··· 1666 1666 return 0; 1667 1667 } 1668 1668 1669 + #define MASTER_SLAVE_CFG_UNSUPPORTED 0 1670 + #define MASTER_SLAVE_CFG_UNKNOWN 1 1671 + #define MASTER_SLAVE_CFG_MASTER_PREFERRED 2 1672 + #define MASTER_SLAVE_CFG_SLAVE_PREFERRED 3 1673 + #define MASTER_SLAVE_CFG_MASTER_FORCE 4 1674 + #define MASTER_SLAVE_CFG_SLAVE_FORCE 5 1675 + #define MASTER_SLAVE_STATE_UNSUPPORTED 0 1676 + #define MASTER_SLAVE_STATE_UNKNOWN 1 1677 + #define MASTER_SLAVE_STATE_MASTER 2 1678 + #define MASTER_SLAVE_STATE_SLAVE 3 1679 + #define MASTER_SLAVE_STATE_ERR 4 1680 + 1669 1681 /* Which connector port. */ 1670 1682 #define PORT_TP 0x00 1671 1683 #define PORT_AUI 0x01 ··· 1916 1904 __u8 eth_tp_mdix_ctrl; 1917 1905 __s8 link_mode_masks_nwords; 1918 1906 __u8 transceiver; 1919 - __u8 reserved1[3]; 1907 + __u8 master_slave_cfg; 1908 + __u8 master_slave_state; 1909 + __u8 reserved1[1]; 1920 1910 __u32 reserved[7]; 1921 1911 __u32 link_mode_masks[0]; 1922 1912 /* layout of link_mode_masks fields:
+2
include/uapi/linux/ethtool_netlink.h
··· 216 216 ETHTOOL_A_LINKMODES_PEER, /* bitset */ 217 217 ETHTOOL_A_LINKMODES_SPEED, /* u32 */ 218 218 ETHTOOL_A_LINKMODES_DUPLEX, /* u8 */ 219 + ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, /* u8 */ 220 + ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, /* u8 */ 219 221 220 222 /* add new constants above here */ 221 223 __ETHTOOL_A_LINKMODES_CNT,
+2
include/uapi/linux/mii.h
··· 151 151 /* 1000BASE-T Control register */ 152 152 #define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ 153 153 #define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */ 154 + #define CTL1000_PREFER_MASTER 0x0400 /* prefer to operate as master */ 154 155 #define CTL1000_AS_MASTER 0x0800 155 156 #define CTL1000_ENABLE_MASTER 0x1000 156 157 157 158 /* 1000BASE-T Status register */ 158 159 #define LPA_1000MSFAIL 0x8000 /* Master/Slave resolution failure */ 160 + #define LPA_1000MSRES 0x4000 /* Master/Slave resolution status */ 159 161 #define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */ 160 162 #define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */ 161 163 #define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
+6
net/ethtool/ioctl.c
··· 552 552 link_ksettings.base.cmd = ETHTOOL_GLINKSETTINGS; 553 553 link_ksettings.base.link_mode_masks_nwords 554 554 = __ETHTOOL_LINK_MODE_MASK_NU32; 555 + link_ksettings.base.master_slave_cfg = MASTER_SLAVE_CFG_UNSUPPORTED; 556 + link_ksettings.base.master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; 555 557 556 558 return store_link_ksettings_for_user(useraddr, &link_ksettings); 557 559 } ··· 589 587 /* re-check nwords field, just in case */ 590 588 if (__ETHTOOL_LINK_MODE_MASK_NU32 591 589 != link_ksettings.base.link_mode_masks_nwords) 590 + return -EINVAL; 591 + 592 + if (link_ksettings.base.master_slave_cfg || 593 + link_ksettings.base.master_slave_state) 592 594 return -EINVAL; 593 595 594 596 err = dev->ethtool_ops->set_link_ksettings(dev, &link_ksettings);
+53
net/ethtool/linkmodes.c
··· 27 27 [ETHTOOL_A_LINKMODES_PEER] = { .type = NLA_REJECT }, 28 28 [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_REJECT }, 29 29 [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_REJECT }, 30 + [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .type = NLA_REJECT }, 31 + [ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE] = { .type = NLA_REJECT }, 30 32 }; 31 33 32 34 static int linkmodes_prepare_data(const struct ethnl_req_info *req_base, ··· 65 63 { 66 64 const struct linkmodes_reply_data *data = LINKMODES_REPDATA(reply_base); 67 65 const struct ethtool_link_ksettings *ksettings = &data->ksettings; 66 + const struct ethtool_link_settings *lsettings = &ksettings->base; 68 67 bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; 69 68 int len, ret; 70 69 ··· 88 85 return ret; 89 86 len += ret; 90 87 } 88 + 89 + if (lsettings->master_slave_cfg != MASTER_SLAVE_CFG_UNSUPPORTED) 90 + len += nla_total_size(sizeof(u8)); 91 + 92 + if (lsettings->master_slave_state != MASTER_SLAVE_STATE_UNSUPPORTED) 93 + len += nla_total_size(sizeof(u8)); 91 94 92 95 return len; 93 96 } ··· 129 120 130 121 if (nla_put_u32(skb, ETHTOOL_A_LINKMODES_SPEED, lsettings->speed) || 131 122 nla_put_u8(skb, ETHTOOL_A_LINKMODES_DUPLEX, lsettings->duplex)) 123 + return -EMSGSIZE; 124 + 125 + if (lsettings->master_slave_cfg != MASTER_SLAVE_CFG_UNSUPPORTED && 126 + nla_put_u8(skb, ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, 127 + lsettings->master_slave_cfg)) 128 + return -EMSGSIZE; 129 + 130 + if (lsettings->master_slave_state != MASTER_SLAVE_STATE_UNSUPPORTED && 131 + nla_put_u8(skb, ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, 132 + lsettings->master_slave_state)) 132 133 return -EMSGSIZE; 133 134 134 135 return 0; ··· 268 249 [ETHTOOL_A_LINKMODES_PEER] = { .type = NLA_REJECT }, 269 250 [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_U32 }, 270 251 [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_U8 }, 252 + [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .type = NLA_U8 }, 253 + [ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE] = { .type = NLA_REJECT }, 271 254 }; 272 255 273 256 /* Set advertised link modes to all supported modes matching requested speed ··· 308 287 __ETHTOOL_LINK_MODE_MASK_NBITS); 309 288 } 310 289 290 + static bool ethnl_validate_master_slave_cfg(u8 cfg) 291 + { 292 + switch (cfg) { 293 + case MASTER_SLAVE_CFG_MASTER_PREFERRED: 294 + case MASTER_SLAVE_CFG_SLAVE_PREFERRED: 295 + case MASTER_SLAVE_CFG_MASTER_FORCE: 296 + case MASTER_SLAVE_CFG_SLAVE_FORCE: 297 + return true; 298 + } 299 + 300 + return false; 301 + } 302 + 311 303 static int ethnl_update_linkmodes(struct genl_info *info, struct nlattr **tb, 312 304 struct ethtool_link_ksettings *ksettings, 313 305 bool *mod) 314 306 { 315 307 struct ethtool_link_settings *lsettings = &ksettings->base; 316 308 bool req_speed, req_duplex; 309 + const struct nlattr *master_slave_cfg; 317 310 int ret; 311 + 312 + master_slave_cfg = tb[ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG]; 313 + if (master_slave_cfg) { 314 + u8 cfg = nla_get_u8(master_slave_cfg); 315 + 316 + if (lsettings->master_slave_cfg == MASTER_SLAVE_CFG_UNSUPPORTED) { 317 + NL_SET_ERR_MSG_ATTR(info->extack, master_slave_cfg, 318 + "master/slave configuration not supported by device"); 319 + return -EOPNOTSUPP; 320 + } 321 + 322 + if (!ethnl_validate_master_slave_cfg(cfg)) { 323 + NL_SET_ERR_MSG_ATTR(info->extack, master_slave_cfg, 324 + "master/slave value is invalid"); 325 + return -EOPNOTSUPP; 326 + } 327 + } 318 328 319 329 *mod = false; 320 330 req_speed = tb[ETHTOOL_A_LINKMODES_SPEED]; ··· 363 311 mod); 364 312 ethnl_update_u8(&lsettings->duplex, tb[ETHTOOL_A_LINKMODES_DUPLEX], 365 313 mod); 314 + ethnl_update_u8(&lsettings->master_slave_cfg, master_slave_cfg, mod); 366 315 367 316 if (!tb[ETHTOOL_A_LINKMODES_OURS] && lsettings->autoneg && 368 317 (req_speed || req_duplex) &&