Skip to content

Commit 3ad4b7c

Browse files
sean-anderson-secokuba-moo
authored andcommitted
net: macb: Fix several edge cases in validate
There were several cases where validate() would return bogus supported modes with unusual combinations of interfaces and capabilities. For example, if state->interface was 10GBASER and the macb had HIGH_SPEED and PCS but not GIGABIT MODE, then 10/100 modes would be set anyway. In another case, SGMII could be enabled even if the mac was not a GEM (despite this being checked for later on in mac_config()). These inconsistencies make it difficult to refactor this function cleanly. There is still the open question of what exactly the requirements for SGMII and 10GBASER are, and what SGMII actually supports. If someone from Cadence (or anyone else with access to the GEM/MACB datasheet) could comment on this, it would be greatly appreciated. In particular, what is supported by Cadence vs. vendor extension/limitation? To address this, the current logic is split into three parts. First, we determine what we support, then we eliminate unsupported interfaces, and finally we set the appropriate link modes. There is still some cruft related to NA, but this can be removed in a future patch. Signed-off-by: Sean Anderson <sean.anderson@seco.com> Reviewed-by: Parshuram Thombare <pthombar@cadence.com> Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Link: https://lore.kernel.org/r/20211112190400.1937855-1-sean.anderson@seco.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent a5bdc36 commit 3ad4b7c

File tree

1 file changed

+73
-39
lines changed

1 file changed

+73
-39
lines changed

drivers/net/ethernet/cadence/macb_main.c

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -513,29 +513,47 @@ static void macb_validate(struct phylink_config *config,
513513
struct net_device *ndev = to_net_dev(config->dev);
514514
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
515515
struct macb *bp = netdev_priv(ndev);
516+
bool have_1g, have_sgmii, have_10g;
517+
518+
/* Determine what modes are supported */
519+
if (macb_is_gem(bp) &&
520+
(bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)) {
521+
have_1g = true;
522+
if (bp->caps & MACB_CAPS_PCS)
523+
have_sgmii = true;
524+
if (bp->caps & MACB_CAPS_HIGH_SPEED)
525+
have_10g = true;
526+
}
527+
528+
/* Eliminate unsupported modes */
529+
switch (state->interface) {
530+
case PHY_INTERFACE_MODE_NA:
531+
case PHY_INTERFACE_MODE_MII:
532+
case PHY_INTERFACE_MODE_RMII:
533+
break;
516534

517-
/* We only support MII, RMII, GMII, RGMII & SGMII. */
518-
if (state->interface != PHY_INTERFACE_MODE_NA &&
519-
state->interface != PHY_INTERFACE_MODE_MII &&
520-
state->interface != PHY_INTERFACE_MODE_RMII &&
521-
state->interface != PHY_INTERFACE_MODE_GMII &&
522-
state->interface != PHY_INTERFACE_MODE_SGMII &&
523-
state->interface != PHY_INTERFACE_MODE_10GBASER &&
524-
!phy_interface_mode_is_rgmii(state->interface)) {
535+
case PHY_INTERFACE_MODE_GMII:
536+
case PHY_INTERFACE_MODE_RGMII:
537+
case PHY_INTERFACE_MODE_RGMII_ID:
538+
case PHY_INTERFACE_MODE_RGMII_RXID:
539+
case PHY_INTERFACE_MODE_RGMII_TXID:
540+
if (have_1g)
541+
break;
525542
linkmode_zero(supported);
526543
return;
527-
}
528544

529-
if (!macb_is_gem(bp) &&
530-
(state->interface == PHY_INTERFACE_MODE_GMII ||
531-
phy_interface_mode_is_rgmii(state->interface))) {
545+
case PHY_INTERFACE_MODE_SGMII:
546+
if (have_sgmii)
547+
break;
532548
linkmode_zero(supported);
533549
return;
534-
}
535550

536-
if (state->interface == PHY_INTERFACE_MODE_10GBASER &&
537-
!(bp->caps & MACB_CAPS_HIGH_SPEED &&
538-
bp->caps & MACB_CAPS_PCS)) {
551+
case PHY_INTERFACE_MODE_10GBASER:
552+
if (have_10g)
553+
break;
554+
fallthrough;
555+
556+
default:
539557
linkmode_zero(supported);
540558
return;
541559
}
@@ -544,32 +562,48 @@ static void macb_validate(struct phylink_config *config,
544562
phylink_set(mask, Autoneg);
545563
phylink_set(mask, Asym_Pause);
546564

547-
if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE &&
548-
(state->interface == PHY_INTERFACE_MODE_NA ||
549-
state->interface == PHY_INTERFACE_MODE_10GBASER)) {
550-
phylink_set_10g_modes(mask);
551-
phylink_set(mask, 10000baseKR_Full);
565+
/* And set the appropriate mask */
566+
switch (state->interface) {
567+
case PHY_INTERFACE_MODE_NA:
568+
case PHY_INTERFACE_MODE_10GBASER:
569+
if (have_10g) {
570+
phylink_set_10g_modes(mask);
571+
phylink_set(mask, 10000baseKR_Full);
572+
}
552573
if (state->interface != PHY_INTERFACE_MODE_NA)
553-
goto out;
554-
}
574+
break;
575+
fallthrough;
576+
577+
/* FIXME: Do we actually support 10/100 for SGMII? Half duplex? */
578+
case PHY_INTERFACE_MODE_SGMII:
579+
if (!have_sgmii && state->interface != PHY_INTERFACE_MODE_NA)
580+
break;
581+
fallthrough;
582+
583+
case PHY_INTERFACE_MODE_GMII:
584+
case PHY_INTERFACE_MODE_RGMII:
585+
case PHY_INTERFACE_MODE_RGMII_ID:
586+
case PHY_INTERFACE_MODE_RGMII_RXID:
587+
case PHY_INTERFACE_MODE_RGMII_TXID:
588+
if (have_1g) {
589+
phylink_set(mask, 1000baseT_Full);
590+
phylink_set(mask, 1000baseX_Full);
591+
592+
if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF))
593+
phylink_set(mask, 1000baseT_Half);
594+
} else if (state->interface != PHY_INTERFACE_MODE_NA) {
595+
break;
596+
}
597+
fallthrough;
555598

556-
phylink_set(mask, 10baseT_Half);
557-
phylink_set(mask, 10baseT_Full);
558-
phylink_set(mask, 100baseT_Half);
559-
phylink_set(mask, 100baseT_Full);
560-
561-
if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE &&
562-
(state->interface == PHY_INTERFACE_MODE_NA ||
563-
state->interface == PHY_INTERFACE_MODE_GMII ||
564-
state->interface == PHY_INTERFACE_MODE_SGMII ||
565-
phy_interface_mode_is_rgmii(state->interface))) {
566-
phylink_set(mask, 1000baseT_Full);
567-
phylink_set(mask, 1000baseX_Full);
568-
569-
if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF))
570-
phylink_set(mask, 1000baseT_Half);
599+
default:
600+
phylink_set(mask, 10baseT_Half);
601+
phylink_set(mask, 10baseT_Full);
602+
phylink_set(mask, 100baseT_Half);
603+
phylink_set(mask, 100baseT_Full);
604+
break;
571605
}
572-
out:
606+
573607
linkmode_and(supported, supported, mask);
574608
linkmode_and(state->advertising, state->advertising, mask);
575609
}

0 commit comments

Comments
 (0)