net: phy: Use an internal, searchable storage for the linkmodes
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>
Link: https://patch.msgid.link/20250307173611.129125-3-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-03-07 18:35:59 +01:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/*
|
|
|
|
* link caps internal header, for link modes <-> capabilities <-> interfaces
|
|
|
|
* conversions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __PHY_CAPS_H
|
|
|
|
#define __PHY_CAPS_H
|
|
|
|
|
|
|
|
#include <linux/ethtool.h>
|
2025-03-07 18:36:10 +01:00
|
|
|
#include <linux/phy.h>
|
net: phy: Use an internal, searchable storage for the linkmodes
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>
Link: https://patch.msgid.link/20250307173611.129125-3-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-03-07 18:35:59 +01:00
|
|
|
|
|
|
|
enum {
|
|
|
|
LINK_CAPA_10HD = 0,
|
|
|
|
LINK_CAPA_10FD,
|
|
|
|
LINK_CAPA_100HD,
|
|
|
|
LINK_CAPA_100FD,
|
|
|
|
LINK_CAPA_1000HD,
|
|
|
|
LINK_CAPA_1000FD,
|
|
|
|
LINK_CAPA_2500FD,
|
|
|
|
LINK_CAPA_5000FD,
|
|
|
|
LINK_CAPA_10000FD,
|
|
|
|
LINK_CAPA_20000FD,
|
|
|
|
LINK_CAPA_25000FD,
|
|
|
|
LINK_CAPA_40000FD,
|
|
|
|
LINK_CAPA_50000FD,
|
|
|
|
LINK_CAPA_56000FD,
|
|
|
|
LINK_CAPA_100000FD,
|
|
|
|
LINK_CAPA_200000FD,
|
|
|
|
LINK_CAPA_400000FD,
|
|
|
|
LINK_CAPA_800000FD,
|
|
|
|
|
|
|
|
__LINK_CAPA_MAX,
|
|
|
|
};
|
|
|
|
|
2025-03-07 18:36:10 +01:00
|
|
|
#define LINK_CAPA_ALL GENMASK((__LINK_CAPA_MAX - 1), 0)
|
|
|
|
|
net: phy: Use an internal, searchable storage for the linkmodes
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>
Link: https://patch.msgid.link/20250307173611.129125-3-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-03-07 18:35:59 +01:00
|
|
|
struct link_capabilities {
|
|
|
|
int speed;
|
|
|
|
unsigned int duplex;
|
|
|
|
__ETHTOOL_DECLARE_LINK_MODE_MASK(linkmodes);
|
|
|
|
};
|
|
|
|
|
|
|
|
int phy_caps_init(void);
|
|
|
|
|
2025-03-07 18:36:00 +01:00
|
|
|
size_t phy_caps_speeds(unsigned int *speeds, size_t size,
|
|
|
|
unsigned long *linkmodes);
|
2025-03-07 18:36:01 +01:00
|
|
|
void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes);
|
2025-03-07 18:36:02 +01:00
|
|
|
bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes);
|
2025-03-07 18:36:09 +01:00
|
|
|
void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes);
|
2025-03-07 18:36:10 +01:00
|
|
|
unsigned long phy_caps_from_interface(phy_interface_t interface);
|
2025-03-07 18:36:01 +01:00
|
|
|
|
2025-03-07 18:36:03 +01:00
|
|
|
const struct link_capabilities *
|
|
|
|
phy_caps_lookup_by_linkmode(const unsigned long *linkmodes);
|
|
|
|
|
|
|
|
const struct link_capabilities *
|
|
|
|
phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only);
|
2025-03-07 18:36:00 +01:00
|
|
|
|
net: phy: phy_caps: Allow looking-up link caps based on speed and duplex
As the link_caps array is efficient for <speed,duplex> lookups,
implement a function for speed/duplex lookups that matches a given
mask. This replicates to some extent the phy_lookup_settings()
behaviour, matching full link_capabilities instead of a single linkmode.
phy.c's phy_santize_settings() and phylink's
phylink_ethtool_ksettings_set() performs such lookup using the
phy_settings table, but are only interested in the actual speed/duplex
that were matched, rathet than the individual linkmode.
Similar to phy_lookup_settings(), the newly introduced phy_caps_lookup()
will run through the link_caps[] array by descending speed/duplex order.
If the link_capabilities for a given <speed/duplex> tuple intersects the
passed linkmodes, we consider that a match.
Similar to phy_lookup_settings(), we also allow passing an 'exact'
boolean, allowing non-exact match. Here, we MUST always match the
linkmodes mask, but we allow matching on lower speed settings.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20250307173611.129125-8-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-03-07 18:36:04 +01:00
|
|
|
const struct link_capabilities *
|
|
|
|
phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported,
|
|
|
|
bool exact);
|
|
|
|
|
net: phy: Use an internal, searchable storage for the linkmodes
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>
Link: https://patch.msgid.link/20250307173611.129125-3-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-03-07 18:35:59 +01:00
|
|
|
#endif /* __PHY_CAPS_H */
|