Thread (20 messages) 20 messages, 2 authors, 2025-02-28

Re: [PATCH net-next v3 02/13] net: phy: Use an internal, searchable storage for the linkmodes

From: Maxime Chevallier <maxime.chevallier@bootlin.com>
Date: 2025-02-28 15:55:45
Also in: linux-arm-kernel, lkml

Hello Russell,

On Fri, 28 Feb 2025 15:41:26 +0000
"Russell King (Oracle)" [off-list ref] wrote:
On Fri, Feb 28, 2025 at 03:55:27PM +0100, Maxime Chevallier wrote:
quoted
The canonical definition for all the link modes is in linux/ethtool.h,
which is complemented by the link_mode_params array stored in
net/ethtool/common.h . That array contains all the metadata about each
of these modes, including the Speed and Duplex information.

Phylib and phylink needs that information as well for internal
management of the link, which was done by duplicating that information
in locally-stored arrays and lookup functions. This makes it easy for
developpers adding new modes to forget modifying phylib and phylink
accordingly.

However, the link_mode_params array in net/ethtool/common.c is fairly
inefficient to search through, as it isn't sorted in any manner. Phylib
and phylink perform a lot of lookup operations, mostly to filter modes
by speed and/or duplex.

We therefore introduce the link_caps private array in phy_caps.c, that
indexes linkmodes in a more efficient manner. Each element associated a
tuple <speed, duplex> to a bitfield of all the linkmodes runs at these
speed/duplex.

We end-up with an array that's fairly short, easily addressable and that
it optimised for the typical use-cases of phylib/phylink.

That array is initialized at the same time as phylib. As the
link_mode_params array is part of the net stack, which phylink depends
on, it should always be accessible from phylib.

Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
[...]
quoted
+static int speed_duplex_to_capa(int speed, unsigned int duplex)
+{
+	if (duplex == DUPLEX_UNKNOWN ||
+	    (speed > SPEED_1000 && duplex != DUPLEX_FULL))
+		return -EINVAL;
+
+	switch (speed) {
+	case SPEED_10: return duplex == DUPLEX_FULL ?
+			      LINK_CAPA_10FD : LINK_CAPA_10HD;
+	case SPEED_100: return duplex == DUPLEX_FULL ?
+			       LINK_CAPA_100FD : LINK_CAPA_100HD;
+	case SPEED_1000: return duplex == DUPLEX_FULL ?
+				LINK_CAPA_1000FD : LINK_CAPA_1000HD;
+	case SPEED_2500: return LINK_CAPA_2500FD;
+	case SPEED_5000: return LINK_CAPA_5000FD;
+	case SPEED_10000: return LINK_CAPA_10000FD;
+	case SPEED_20000: return LINK_CAPA_20000FD;
+	case SPEED_25000: return LINK_CAPA_25000FD;
+	case SPEED_40000: return LINK_CAPA_40000FD;
+	case SPEED_50000: return LINK_CAPA_50000FD;
+	case SPEED_56000: return LINK_CAPA_56000FD;
+	case SPEED_100000: return LINK_CAPA_100000FD;
+	case SPEED_200000: return LINK_CAPA_200000FD;
+	case SPEED_400000: return LINK_CAPA_400000FD;
+	case SPEED_800000: return LINK_CAPA_800000FD;  
I think one of the issues you mentioned is about the need to update
several places as new linkmodes are added.

One of the side effects of adding new linkmodes is that they generally
come with faster speeds, so this is a place that needs to be updated
along with the table above.

I'm not sure whether this makes that problem better or worse - if a
new linkmode is added with a SPEED_*, the author of such a change has
to be on the ball to update these, and I'm not sure that'll happen.
That's true indeed, and it seems that's already the case today (there's
no MAC_800000FD in phylink for example). It seems to me that NICs
with very fast speeds don't care at all about phylib nor phylink...

So yeah this work does not address the complexity of adding a new speed
:(

To solve that, we could consider some macro magic to define new speeds
with an associated LINK_CAPA, however that's quite the overhaul.

Do you see that new enum for link_caps as a blocking point for that
series ? 

Maxime
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help