Message ID | 20220818164616.2064242-6-sean.anderson@seco.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net: phy: Add support for rate adaptation | expand |
On 8/18/22 12:46 PM, Sean Anderson wrote: > This adds a table for converting between speed/duplex and mac > capabilities. It also adds a helper for getting the max speed/duplex > from some caps. It is intended to be used by Russell King's DSA phylink > series. The table will be used directly later in this series. > > Co-developed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> > Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> > [ adapted to live in phylink.c ] > Signed-off-by: Sean Anderson <sean.anderson@seco.com> > --- > This is adapted from [1]. > > [1] https://lore.kernel.org/netdev/E1oCNlE-006e3z-3T@rmk-PC.armlinux.org.uk/ > > Changes in v4: > - Wrap docstring to 80 columns > > Changes in v3: > - New > > drivers/net/phy/phylink.c | 57 +++++++++++++++++++++++++++++++++++++++ > include/linux/phylink.h | 2 ++ > 2 files changed, 59 insertions(+) > > diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c > index 68a58ab6a8ed..8a9da7449c73 100644 > --- a/drivers/net/phy/phylink.c > +++ b/drivers/net/phy/phylink.c > @@ -304,6 +304,63 @@ void phylink_caps_to_linkmodes(unsigned long *linkmodes, unsigned long caps) > } > EXPORT_SYMBOL_GPL(phylink_caps_to_linkmodes); > > +static struct { > + unsigned long mask; > + int speed; > + unsigned int duplex; > +} phylink_caps_params[] = { > + { MAC_400000FD, SPEED_400000, DUPLEX_FULL }, > + { MAC_200000FD, SPEED_200000, DUPLEX_FULL }, > + { MAC_100000FD, SPEED_100000, DUPLEX_FULL }, > + { MAC_56000FD, SPEED_56000, DUPLEX_FULL }, > + { MAC_50000FD, SPEED_50000, DUPLEX_FULL }, > + { MAC_40000FD, SPEED_40000, DUPLEX_FULL }, > + { MAC_25000FD, SPEED_25000, DUPLEX_FULL }, > + { MAC_20000FD, SPEED_20000, DUPLEX_FULL }, > + { MAC_10000FD, SPEED_10000, DUPLEX_FULL }, > + { MAC_5000FD, SPEED_5000, DUPLEX_FULL }, > + { MAC_2500FD, SPEED_2500, DUPLEX_FULL }, > + { MAC_1000FD, SPEED_1000, DUPLEX_FULL }, > + { MAC_1000HD, SPEED_1000, DUPLEX_HALF }, > + { MAC_100FD, SPEED_100, DUPLEX_FULL }, > + { MAC_100HD, SPEED_100, DUPLEX_HALF }, > + { MAC_10FD, SPEED_10, DUPLEX_FULL }, > + { MAC_10HD, SPEED_10, DUPLEX_HALF }, > +}; > + > +/** > + * phylink_caps_find_max_speed() - Find the max speed/duplex of mac capabilities > + * @caps: A mask of mac capabilities > + * @speed: Variable to store the maximum speed > + * @duplex: Variable to store the maximum duplex > + * > + * Find the maximum speed (and associated duplex) supported by a mask of mac > + * capabilities. @speed and @duplex are always set, even if no matching mac > + * capability was found. > + * > + * Return: 0 on success, or %-EINVAL if the maximum speed/duplex could not be > + * determined. > + */ > +int phylink_caps_find_max_speed(unsigned long caps, int *speed, > + unsigned int *duplex) > +{ > + int i; > + > + *speed = SPEED_UNKNOWN; > + *duplex = DUPLEX_UNKNOWN; > + > + for (i = 0; i < ARRAY_SIZE(phylink_caps_params); i++) { > + if (caps & phylink_caps_params[i].mask) { > + *speed = phylink_caps_params[i].speed; > + *duplex = phylink_caps_params[i].duplex; > + return 0; > + } > + } > + > + return -EINVAL; > +} > +EXPORT_SYMBOL_GPL(phylink_caps_find_max_speed); > + > /** > * phylink_get_capabilities() - get capabilities for a given MAC > * @interface: phy interface mode defined by &typedef phy_interface_t > diff --git a/include/linux/phylink.h b/include/linux/phylink.h > index 661d1d4fdbec..a5a236cfacb6 100644 > --- a/include/linux/phylink.h > +++ b/include/linux/phylink.h > @@ -535,6 +535,8 @@ void pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, > #endif > > void phylink_caps_to_linkmodes(unsigned long *linkmodes, unsigned long caps); > +int phylink_caps_find_max_speed(unsigned long caps, int *speed, > + unsigned int *duplex); > unsigned long phylink_get_capabilities(phy_interface_t interface, > unsigned long mac_capabilities); > void phylink_generic_validate(struct phylink_config *config, > ...and it looks like I removed the wrong helper function (that is, phylink_cap_from_speed_duplex was removed instead of phylink_caps_find_max_speed) Will be fixed in v5 --Sean
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 68a58ab6a8ed..8a9da7449c73 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -304,6 +304,63 @@ void phylink_caps_to_linkmodes(unsigned long *linkmodes, unsigned long caps) } EXPORT_SYMBOL_GPL(phylink_caps_to_linkmodes); +static struct { + unsigned long mask; + int speed; + unsigned int duplex; +} phylink_caps_params[] = { + { MAC_400000FD, SPEED_400000, DUPLEX_FULL }, + { MAC_200000FD, SPEED_200000, DUPLEX_FULL }, + { MAC_100000FD, SPEED_100000, DUPLEX_FULL }, + { MAC_56000FD, SPEED_56000, DUPLEX_FULL }, + { MAC_50000FD, SPEED_50000, DUPLEX_FULL }, + { MAC_40000FD, SPEED_40000, DUPLEX_FULL }, + { MAC_25000FD, SPEED_25000, DUPLEX_FULL }, + { MAC_20000FD, SPEED_20000, DUPLEX_FULL }, + { MAC_10000FD, SPEED_10000, DUPLEX_FULL }, + { MAC_5000FD, SPEED_5000, DUPLEX_FULL }, + { MAC_2500FD, SPEED_2500, DUPLEX_FULL }, + { MAC_1000FD, SPEED_1000, DUPLEX_FULL }, + { MAC_1000HD, SPEED_1000, DUPLEX_HALF }, + { MAC_100FD, SPEED_100, DUPLEX_FULL }, + { MAC_100HD, SPEED_100, DUPLEX_HALF }, + { MAC_10FD, SPEED_10, DUPLEX_FULL }, + { MAC_10HD, SPEED_10, DUPLEX_HALF }, +}; + +/** + * phylink_caps_find_max_speed() - Find the max speed/duplex of mac capabilities + * @caps: A mask of mac capabilities + * @speed: Variable to store the maximum speed + * @duplex: Variable to store the maximum duplex + * + * Find the maximum speed (and associated duplex) supported by a mask of mac + * capabilities. @speed and @duplex are always set, even if no matching mac + * capability was found. + * + * Return: 0 on success, or %-EINVAL if the maximum speed/duplex could not be + * determined. + */ +int phylink_caps_find_max_speed(unsigned long caps, int *speed, + unsigned int *duplex) +{ + int i; + + *speed = SPEED_UNKNOWN; + *duplex = DUPLEX_UNKNOWN; + + for (i = 0; i < ARRAY_SIZE(phylink_caps_params); i++) { + if (caps & phylink_caps_params[i].mask) { + *speed = phylink_caps_params[i].speed; + *duplex = phylink_caps_params[i].duplex; + return 0; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(phylink_caps_find_max_speed); + /** * phylink_get_capabilities() - get capabilities for a given MAC * @interface: phy interface mode defined by &typedef phy_interface_t diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 661d1d4fdbec..a5a236cfacb6 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -535,6 +535,8 @@ void pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, #endif void phylink_caps_to_linkmodes(unsigned long *linkmodes, unsigned long caps); +int phylink_caps_find_max_speed(unsigned long caps, int *speed, + unsigned int *duplex); unsigned long phylink_get_capabilities(phy_interface_t interface, unsigned long mac_capabilities); void phylink_generic_validate(struct phylink_config *config,