Skip to content

Commit cae0de4

Browse files
committed
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>
2 parents e1df520 + 7a1f9a1 commit cae0de4

File tree

7 files changed

+353
-125
lines changed

7 files changed

+353
-125
lines changed

drivers/net/phy/aquantia/aquantia.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
#define VEND1_GLOBAL_CFG_5G 0x031e
4848
#define VEND1_GLOBAL_CFG_10G 0x031f
4949
/* ...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
5055
#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7)
5156
#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0
5257
#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1

drivers/net/phy/aquantia/aquantia_main.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,80 @@ static int aqr107_resume(struct phy_device *phydev)
656656
return aqr107_wait_processor_intensive_op(phydev);
657657
}
658658

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+
659733
static int aqr107_probe(struct phy_device *phydev)
660734
{
661735
int ret;
@@ -794,7 +868,7 @@ static struct phy_driver aqr_driver[] = {
794868
.name = "Aquantia AQR113C",
795869
.probe = aqr107_probe,
796870
.get_rate_matching = aqr107_get_rate_matching,
797-
.config_init = aqr107_config_init,
871+
.config_init = aqr113c_config_init,
798872
.config_aneg = aqr_config_aneg,
799873
.config_intr = aqr_config_intr,
800874
.handle_interrupt = aqr_handle_interrupt,

drivers/net/phy/bcm84881.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,19 @@ static int bcm84881_wait_init(struct phy_device *phydev)
2929
100000, 2000000, false);
3030
}
3131

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+
3241
static int bcm84881_config_init(struct phy_device *phydev)
3342
{
43+
bcm84881_fill_possible_interfaces(phydev);
44+
3445
switch (phydev->interface) {
3546
case PHY_INTERFACE_MODE_SGMII:
3647
case PHY_INTERFACE_MODE_2500BASEX:
@@ -39,6 +50,7 @@ static int bcm84881_config_init(struct phy_device *phydev)
3950
default:
4051
return -ENODEV;
4152
}
53+
4254
return 0;
4355
}
4456

0 commit comments

Comments
 (0)