Skip to content

Commit

Permalink
net: phy: phy_caps: Don't skip better duplex macth on non-exact match
Browse files Browse the repository at this point in the history
When performing a non-exact phy_caps lookup, we are looking for a
supported mode that matches as closely as possible the passed speed/duplex.

Blamed patch broke that logic by returning a match too early in case
the caller asks for half-duplex, as a full-duplex linkmode may match
first, and returned as a non-exact match without even trying to mach on
half-duplex modes.

Reported-by: Jijie Shao <shaojijie@huawei.com>
Closes: https://lore.kernel.org/netdev/20250603102500.4ec743cf@fedora/T/#m22ed60ca635c67dc7d9cbb47e8995b2beb5c1576
Tested-by: Jijie Shao <shaojijie@huawei.com>
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Fixes: fc81e25 ("net: phy: phy_caps: Allow looking-up link caps based on speed and duplex")
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20250606094321.483602-1-maxime.chevallier@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Maxime Chevallier authored and Jakub Kicinski committed Jun 12, 2025
1 parent 27cea0e commit d4e6cb3
Showing 1 changed file with 12 additions and 6 deletions.
18 changes: 12 additions & 6 deletions drivers/net/phy/phy_caps.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,17 @@ phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only)
* When @exact is not set, we return either an exact match, or matching capabilities
* at lower speed, or the lowest matching speed, or NULL.
*
* Non-exact matches will try to return an exact speed and duplex match, but may
* return matching capabilities with same speed but a different duplex.
*
* Returns: a matched link_capabilities according to the above process, NULL
* otherwise.
*/
const struct link_capabilities *
phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported,
bool exact)
{
const struct link_capabilities *lcap, *last = NULL;
const struct link_capabilities *lcap, *match = NULL, *last = NULL;

for_each_link_caps_desc_speed(lcap) {
if (linkmode_intersects(lcap->linkmodes, supported)) {
Expand All @@ -204,16 +207,19 @@ phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported,
if (lcap->speed == speed && lcap->duplex == duplex) {
return lcap;
} else if (!exact) {
if (lcap->speed <= speed)
return lcap;
if (!match && lcap->speed <= speed)
match = lcap;

if (lcap->speed < speed)
break;
}
}
}

if (!exact)
return last;
if (!match && !exact)
match = last;

return NULL;
return match;
}
EXPORT_SYMBOL_GPL(phy_caps_lookup);

Expand Down

0 comments on commit d4e6cb3

Please sign in to comment.