mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
net: phy: phy_caps: Don't skip better duplex macth on non-exact match
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: fc81e257d1 ("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>
This commit is contained in:
committed by
Jakub Kicinski
parent
27cea0e419
commit
d4e6cb324d
@@ -188,6 +188,9 @@ 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.
|
||||
*/
|
||||
@@ -195,7 +198,7 @@ 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)) {
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user