Skip to content

Commit

Permalink
Merge branch 'net-phylink-improve-phy-validation'
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jakub Kicinski committed Nov 28, 2023
2 parents e1df520 + 7a1f9a1 commit cae0de4
Show file tree
Hide file tree
Showing 7 changed files with 353 additions and 125 deletions.
5 changes: 5 additions & 0 deletions drivers/net/phy/aquantia/aquantia.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
#define VEND1_GLOBAL_CFG_5G 0x031e
#define VEND1_GLOBAL_CFG_10G 0x031f
/* ...and now the fields */
#define VEND1_GLOBAL_CFG_SERDES_MODE GENMASK(2, 0)
#define VEND1_GLOBAL_CFG_SERDES_MODE_XFI 0
#define VEND1_GLOBAL_CFG_SERDES_MODE_SGMII 3
#define VEND1_GLOBAL_CFG_SERDES_MODE_OCSGMII 4
#define VEND1_GLOBAL_CFG_SERDES_MODE_XFI5G 6
#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7)
#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0
#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1
Expand Down
76 changes: 75 additions & 1 deletion drivers/net/phy/aquantia/aquantia_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,80 @@ static int aqr107_resume(struct phy_device *phydev)
return aqr107_wait_processor_intensive_op(phydev);
}

static const u16 aqr_global_cfg_regs[] = {
VEND1_GLOBAL_CFG_10M,
VEND1_GLOBAL_CFG_100M,
VEND1_GLOBAL_CFG_1G,
VEND1_GLOBAL_CFG_2_5G,
VEND1_GLOBAL_CFG_5G,
VEND1_GLOBAL_CFG_10G
};

static int aqr107_fill_interface_modes(struct phy_device *phydev)
{
unsigned long *possible = phydev->possible_interfaces;
unsigned int serdes_mode, rate_adapt;
phy_interface_t interface;
int i, val;

/* Walk the media-speed configuration registers to determine which
* host-side serdes modes may be used by the PHY depending on the
* negotiated media speed.
*/
for (i = 0; i < ARRAY_SIZE(aqr_global_cfg_regs); i++) {
val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
aqr_global_cfg_regs[i]);
if (val < 0)
return val;

serdes_mode = FIELD_GET(VEND1_GLOBAL_CFG_SERDES_MODE, val);
rate_adapt = FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val);

switch (serdes_mode) {
case VEND1_GLOBAL_CFG_SERDES_MODE_XFI:
if (rate_adapt == VEND1_GLOBAL_CFG_RATE_ADAPT_USX)
interface = PHY_INTERFACE_MODE_USXGMII;
else
interface = PHY_INTERFACE_MODE_10GBASER;
break;

case VEND1_GLOBAL_CFG_SERDES_MODE_XFI5G:
interface = PHY_INTERFACE_MODE_5GBASER;
break;

case VEND1_GLOBAL_CFG_SERDES_MODE_OCSGMII:
interface = PHY_INTERFACE_MODE_2500BASEX;
break;

case VEND1_GLOBAL_CFG_SERDES_MODE_SGMII:
interface = PHY_INTERFACE_MODE_SGMII;
break;

default:
phydev_warn(phydev, "unrecognised serdes mode %u\n",
serdes_mode);
interface = PHY_INTERFACE_MODE_NA;
break;
}

if (interface != PHY_INTERFACE_MODE_NA)
__set_bit(interface, possible);
}

return 0;
}

static int aqr113c_config_init(struct phy_device *phydev)
{
int ret;

ret = aqr107_config_init(phydev);
if (ret < 0)
return ret;

return aqr107_fill_interface_modes(phydev);
}

static int aqr107_probe(struct phy_device *phydev)
{
int ret;
Expand Down Expand Up @@ -794,7 +868,7 @@ static struct phy_driver aqr_driver[] = {
.name = "Aquantia AQR113C",
.probe = aqr107_probe,
.get_rate_matching = aqr107_get_rate_matching,
.config_init = aqr107_config_init,
.config_init = aqr113c_config_init,
.config_aneg = aqr_config_aneg,
.config_intr = aqr_config_intr,
.handle_interrupt = aqr_handle_interrupt,
Expand Down
12 changes: 12 additions & 0 deletions drivers/net/phy/bcm84881.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,19 @@ static int bcm84881_wait_init(struct phy_device *phydev)
100000, 2000000, false);
}

static void bcm84881_fill_possible_interfaces(struct phy_device *phydev)
{
unsigned long *possible = phydev->possible_interfaces;

__set_bit(PHY_INTERFACE_MODE_SGMII, possible);
__set_bit(PHY_INTERFACE_MODE_2500BASEX, possible);
__set_bit(PHY_INTERFACE_MODE_10GBASER, possible);
}

static int bcm84881_config_init(struct phy_device *phydev)
{
bcm84881_fill_possible_interfaces(phydev);

switch (phydev->interface) {
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_2500BASEX:
Expand All @@ -39,6 +50,7 @@ static int bcm84881_config_init(struct phy_device *phydev)
default:
return -ENODEV;
}

return 0;
}

Expand Down
Loading

0 comments on commit cae0de4

Please sign in to comment.