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

net: mdio: add mdio45_ethtool_ksettings_get

There is a function in mdio for the old ethtool api gset.
We add a new function mdio45_ethtool_ksettings_get for the
new ethtool api glinksettings.

Signed-off-by: Philippe Reynes <tremyfr@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Philippe Reynes and committed by
David S. Miller
8e4881aa 525dfa2c

+199
+178
drivers/net/mdio.c
··· 342 342 EXPORT_SYMBOL(mdio45_ethtool_gset_npage); 343 343 344 344 /** 345 + * mdio45_ethtool_ksettings_get_npage - get settings for ETHTOOL_GLINKSETTINGS 346 + * @mdio: MDIO interface 347 + * @cmd: Ethtool request structure 348 + * @npage_adv: Modes currently advertised on next pages 349 + * @npage_lpa: Modes advertised by link partner on next pages 350 + * 351 + * The @cmd parameter is expected to have been cleared before calling 352 + * mdio45_ethtool_ksettings_get_npage(). 353 + * 354 + * Since the CSRs for auto-negotiation using next pages are not fully 355 + * standardised, this function does not attempt to decode them. The 356 + * caller must pass them in. 357 + */ 358 + void mdio45_ethtool_ksettings_get_npage(const struct mdio_if_info *mdio, 359 + struct ethtool_link_ksettings *cmd, 360 + u32 npage_adv, u32 npage_lpa) 361 + { 362 + int reg; 363 + u32 speed, supported = 0, advertising = 0, lp_advertising = 0; 364 + 365 + BUILD_BUG_ON(MDIO_SUPPORTS_C22 != ETH_MDIO_SUPPORTS_C22); 366 + BUILD_BUG_ON(MDIO_SUPPORTS_C45 != ETH_MDIO_SUPPORTS_C45); 367 + 368 + cmd->base.phy_address = mdio->prtad; 369 + cmd->base.mdio_support = 370 + mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22); 371 + 372 + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 373 + MDIO_CTRL2); 374 + switch (reg & MDIO_PMA_CTRL2_TYPE) { 375 + case MDIO_PMA_CTRL2_10GBT: 376 + case MDIO_PMA_CTRL2_1000BT: 377 + case MDIO_PMA_CTRL2_100BTX: 378 + case MDIO_PMA_CTRL2_10BT: 379 + cmd->base.port = PORT_TP; 380 + supported = SUPPORTED_TP; 381 + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 382 + MDIO_SPEED); 383 + if (reg & MDIO_SPEED_10G) 384 + supported |= SUPPORTED_10000baseT_Full; 385 + if (reg & MDIO_PMA_SPEED_1000) 386 + supported |= (SUPPORTED_1000baseT_Full | 387 + SUPPORTED_1000baseT_Half); 388 + if (reg & MDIO_PMA_SPEED_100) 389 + supported |= (SUPPORTED_100baseT_Full | 390 + SUPPORTED_100baseT_Half); 391 + if (reg & MDIO_PMA_SPEED_10) 392 + supported |= (SUPPORTED_10baseT_Full | 393 + SUPPORTED_10baseT_Half); 394 + advertising = ADVERTISED_TP; 395 + break; 396 + 397 + case MDIO_PMA_CTRL2_10GBCX4: 398 + cmd->base.port = PORT_OTHER; 399 + supported = 0; 400 + advertising = 0; 401 + break; 402 + 403 + case MDIO_PMA_CTRL2_10GBKX4: 404 + case MDIO_PMA_CTRL2_10GBKR: 405 + case MDIO_PMA_CTRL2_1000BKX: 406 + cmd->base.port = PORT_OTHER; 407 + supported = SUPPORTED_Backplane; 408 + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 409 + MDIO_PMA_EXTABLE); 410 + if (reg & MDIO_PMA_EXTABLE_10GBKX4) 411 + supported |= SUPPORTED_10000baseKX4_Full; 412 + if (reg & MDIO_PMA_EXTABLE_10GBKR) 413 + supported |= SUPPORTED_10000baseKR_Full; 414 + if (reg & MDIO_PMA_EXTABLE_1000BKX) 415 + supported |= SUPPORTED_1000baseKX_Full; 416 + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 417 + MDIO_PMA_10GBR_FECABLE); 418 + if (reg & MDIO_PMA_10GBR_FECABLE_ABLE) 419 + supported |= SUPPORTED_10000baseR_FEC; 420 + advertising = ADVERTISED_Backplane; 421 + break; 422 + 423 + /* All the other defined modes are flavours of optical */ 424 + default: 425 + cmd->base.port = PORT_FIBRE; 426 + supported = SUPPORTED_FIBRE; 427 + advertising = ADVERTISED_FIBRE; 428 + break; 429 + } 430 + 431 + if (mdio->mmds & MDIO_DEVS_AN) { 432 + supported |= SUPPORTED_Autoneg; 433 + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, 434 + MDIO_CTRL1); 435 + if (reg & MDIO_AN_CTRL1_ENABLE) { 436 + cmd->base.autoneg = AUTONEG_ENABLE; 437 + advertising |= 438 + ADVERTISED_Autoneg | 439 + mdio45_get_an(mdio, MDIO_AN_ADVERTISE) | 440 + npage_adv; 441 + } else { 442 + cmd->base.autoneg = AUTONEG_DISABLE; 443 + } 444 + } else { 445 + cmd->base.autoneg = AUTONEG_DISABLE; 446 + } 447 + 448 + if (cmd->base.autoneg) { 449 + u32 modes = 0; 450 + int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad, 451 + MDIO_MMD_AN, MDIO_STAT1); 452 + 453 + /* If AN is complete and successful, report best common 454 + * mode, otherwise report best advertised mode. 455 + */ 456 + if (an_stat & MDIO_AN_STAT1_COMPLETE) { 457 + lp_advertising = 458 + mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa; 459 + if (an_stat & MDIO_AN_STAT1_LPABLE) 460 + lp_advertising |= ADVERTISED_Autoneg; 461 + modes = advertising & lp_advertising; 462 + } 463 + if ((modes & ~ADVERTISED_Autoneg) == 0) 464 + modes = advertising; 465 + 466 + if (modes & (ADVERTISED_10000baseT_Full | 467 + ADVERTISED_10000baseKX4_Full | 468 + ADVERTISED_10000baseKR_Full)) { 469 + speed = SPEED_10000; 470 + cmd->base.duplex = DUPLEX_FULL; 471 + } else if (modes & (ADVERTISED_1000baseT_Full | 472 + ADVERTISED_1000baseT_Half | 473 + ADVERTISED_1000baseKX_Full)) { 474 + speed = SPEED_1000; 475 + cmd->base.duplex = !(modes & ADVERTISED_1000baseT_Half); 476 + } else if (modes & (ADVERTISED_100baseT_Full | 477 + ADVERTISED_100baseT_Half)) { 478 + speed = SPEED_100; 479 + cmd->base.duplex = !!(modes & ADVERTISED_100baseT_Full); 480 + } else { 481 + speed = SPEED_10; 482 + cmd->base.duplex = !!(modes & ADVERTISED_10baseT_Full); 483 + } 484 + } else { 485 + /* Report forced settings */ 486 + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 487 + MDIO_CTRL1); 488 + speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1) 489 + * ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10)); 490 + cmd->base.duplex = (reg & MDIO_CTRL1_FULLDPLX || 491 + speed == SPEED_10000); 492 + } 493 + 494 + cmd->base.speed = speed; 495 + 496 + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, 497 + supported); 498 + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, 499 + advertising); 500 + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, 501 + lp_advertising); 502 + 503 + /* 10GBASE-T MDI/MDI-X */ 504 + if (cmd->base.port == PORT_TP && (cmd->base.speed == SPEED_10000)) { 505 + switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 506 + MDIO_PMA_10GBT_SWAPPOL)) { 507 + case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX: 508 + cmd->base.eth_tp_mdix = ETH_TP_MDI; 509 + break; 510 + case 0: 511 + cmd->base.eth_tp_mdix = ETH_TP_MDI_X; 512 + break; 513 + default: 514 + /* It's complicated... */ 515 + cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID; 516 + break; 517 + } 518 + } 519 + } 520 + EXPORT_SYMBOL(mdio45_ethtool_ksettings_get_npage); 521 + 522 + /** 345 523 * mdio_mii_ioctl - MII ioctl interface for MDIO (clause 22 or 45) PHYs 346 524 * @mdio: MDIO interface 347 525 * @mii_data: MII ioctl data structure
+21
include/linux/mdio.h
··· 130 130 extern void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, 131 131 struct ethtool_cmd *ecmd, 132 132 u32 npage_adv, u32 npage_lpa); 133 + extern void 134 + mdio45_ethtool_ksettings_get_npage(const struct mdio_if_info *mdio, 135 + struct ethtool_link_ksettings *cmd, 136 + u32 npage_adv, u32 npage_lpa); 133 137 134 138 /** 135 139 * mdio45_ethtool_gset - get settings for ETHTOOL_GSET ··· 149 145 struct ethtool_cmd *ecmd) 150 146 { 151 147 mdio45_ethtool_gset_npage(mdio, ecmd, 0, 0); 148 + } 149 + 150 + /** 151 + * mdio45_ethtool_ksettings_get - get settings for ETHTOOL_GLINKSETTINGS 152 + * @mdio: MDIO interface 153 + * @cmd: Ethtool request structure 154 + * 155 + * Since the CSRs for auto-negotiation using next pages are not fully 156 + * standardised, this function does not attempt to decode them. Use 157 + * mdio45_ethtool_ksettings_get_npage() to specify advertisement bits 158 + * from next pages. 159 + */ 160 + static inline void 161 + mdio45_ethtool_ksettings_get(const struct mdio_if_info *mdio, 162 + struct ethtool_link_ksettings *cmd) 163 + { 164 + mdio45_ethtool_ksettings_get_npage(mdio, cmd, 0, 0); 152 165 } 153 166 154 167 extern int mdio_mii_ioctl(const struct mdio_if_info *mdio,