diff options
Diffstat (limited to 'target/linux/mvebu/patches-4.9/412-net-phy-move-phy_lookup_setting-and-guts-of-phy_supp.patch')
-rw-r--r-- | target/linux/mvebu/patches-4.9/412-net-phy-move-phy_lookup_setting-and-guts-of-phy_supp.patch | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-4.9/412-net-phy-move-phy_lookup_setting-and-guts-of-phy_supp.patch b/target/linux/mvebu/patches-4.9/412-net-phy-move-phy_lookup_setting-and-guts-of-phy_supp.patch new file mode 100644 index 0000000000..02a8fa5748 --- /dev/null +++ b/target/linux/mvebu/patches-4.9/412-net-phy-move-phy_lookup_setting-and-guts-of-phy_supp.patch @@ -0,0 +1,329 @@ +From: Russell King <rmk+kernel@armlinux.org.uk> +Date: Thu, 5 Jan 2017 16:47:39 +0000 +Subject: [PATCH] net: phy: move phy_lookup_setting() and guts of + phy_supported_speeds() to phy-core + +phy_lookup_setting() provides useful functionality in ethtool code +outside phylib. Move it to phy-core and allow it to be re-used (eg, +in phylink) rather than duplicated elsewhere. Note that this supports +the larger linkmode space. + +As we move the phy settings table, we also need to move the guts of +phy_supported_speeds() as well. + +Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> +--- + +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -149,125 +149,6 @@ static inline int phy_aneg_done(struct p + return genphy_aneg_done(phydev); + } + +-/* A structure for mapping a particular speed and duplex +- * combination to a particular SUPPORTED and ADVERTISED value +- */ +-struct phy_setting { +- int speed; +- int duplex; +- int bit; +-}; +- +-/* A mapping of all SUPPORTED settings to speed/duplex. This table +- * must be grouped by speed and sorted in descending match priority +- * - iow, descending speed. */ +-static const struct phy_setting settings[] = { +- { +- .speed = SPEED_10000, +- .duplex = DUPLEX_FULL, +- .bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, +- }, +- { +- .speed = SPEED_10000, +- .duplex = DUPLEX_FULL, +- .bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, +- }, +- { +- .speed = SPEED_10000, +- .duplex = DUPLEX_FULL, +- .bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT, +- }, +- { +- .speed = SPEED_2500, +- .duplex = DUPLEX_FULL, +- .bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT, +- }, +- { +- .speed = SPEED_1000, +- .duplex = DUPLEX_FULL, +- .bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, +- }, +- { +- .speed = SPEED_1000, +- .duplex = DUPLEX_FULL, +- .bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT, +- }, +- { +- .speed = SPEED_1000, +- .duplex = DUPLEX_HALF, +- .bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT, +- }, +- { +- .speed = SPEED_100, +- .duplex = DUPLEX_FULL, +- .bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT, +- }, +- { +- .speed = SPEED_100, +- .duplex = DUPLEX_HALF, +- .bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT, +- }, +- { +- .speed = SPEED_10, +- .duplex = DUPLEX_FULL, +- .bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT, +- }, +- { +- .speed = SPEED_10, +- .duplex = DUPLEX_HALF, +- .bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT, +- }, +-}; +- +-/** +- * phy_lookup_setting - lookup a PHY setting +- * @speed: speed to match +- * @duplex: duplex to match +- * @mask: allowed link modes +- * @maxbit: bit size of link modes +- * @exact: an exact match is required +- * +- * Search the settings array for a setting that matches the speed and +- * duplex, and which is supported. +- * +- * If @exact is unset, either an exact match or %NULL for no match will +- * be returned. +- * +- * If @exact is set, an exact match, the fastest supported setting at +- * or below the specified speed, the slowest supported setting, or if +- * they all fail, %NULL will be returned. +- */ +-static const struct phy_setting * +-phy_lookup_setting(int speed, int duplex, const unsigned long *mask, +- size_t maxbit, bool exact) +-{ +- const struct phy_setting *p, *match = NULL, *last = NULL; +- int i; +- +- for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) { +- if (p->bit < maxbit && test_bit(p->bit, mask)) { +- last = p; +- if (p->speed == speed && p->duplex == duplex) { +- /* Exact match for speed and duplex */ +- match = p; +- break; +- } else if (!exact) { +- if (!match && p->speed <= speed) +- /* Candidate */ +- match = p; +- +- if (p->speed < speed) +- break; +- } +- } +- } +- +- if (!match && !exact) +- match = last; +- +- return match; +-} +- + /** + * phy_find_valid - find a PHY setting that matches the requested parameters + * @speed: desired speed +@@ -290,6 +171,25 @@ phy_find_valid(int speed, int duplex, u3 + } + + /** ++ * phy_supported_speeds - return all speeds currently supported by a phy device ++ * @phy: The phy device to return supported speeds of. ++ * @speeds: buffer to store supported speeds in. ++ * @size: size of speeds buffer. ++ * ++ * Description: Returns the number of supported speeds, and fills the speeds ++ * buffer with the supported speeds. If speeds buffer is too small to contain ++ * all currently supported speeds, will return as many speeds as can fit. ++ */ ++unsigned int phy_supported_speeds(struct phy_device *phy, ++ unsigned int *speeds, ++ unsigned int size) ++{ ++ unsigned long supported = phy->supported; ++ ++ return phy_speeds(speeds, size, &supported, BITS_PER_LONG); ++} ++ ++/** + * phy_check_valid - check if there is a valid PHY setting which matches + * speed, duplex, and feature mask + * @speed: speed to match +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -42,6 +42,132 @@ const char *phy_duplex_to_str(unsigned i + } + EXPORT_SYMBOL_GPL(phy_duplex_to_str); + ++/* A mapping of all SUPPORTED settings to speed/duplex. This table ++ * must be grouped by speed and sorted in descending match priority ++ * - iow, descending speed. */ ++static const struct phy_setting settings[] = { ++ { ++ .speed = SPEED_10000, ++ .duplex = DUPLEX_FULL, ++ .bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, ++ }, ++ { ++ .speed = SPEED_10000, ++ .duplex = DUPLEX_FULL, ++ .bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, ++ }, ++ { ++ .speed = SPEED_10000, ++ .duplex = DUPLEX_FULL, ++ .bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT, ++ }, ++ { ++ .speed = SPEED_2500, ++ .duplex = DUPLEX_FULL, ++ .bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT, ++ }, ++ { ++ .speed = SPEED_1000, ++ .duplex = DUPLEX_FULL, ++ .bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, ++ }, ++ { ++ .speed = SPEED_1000, ++ .duplex = DUPLEX_FULL, ++ .bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ }, ++ { ++ .speed = SPEED_1000, ++ .duplex = DUPLEX_HALF, ++ .bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ }, ++ { ++ .speed = SPEED_100, ++ .duplex = DUPLEX_FULL, ++ .bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT, ++ }, ++ { ++ .speed = SPEED_100, ++ .duplex = DUPLEX_HALF, ++ .bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT, ++ }, ++ { ++ .speed = SPEED_10, ++ .duplex = DUPLEX_FULL, ++ .bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT, ++ }, ++ { ++ .speed = SPEED_10, ++ .duplex = DUPLEX_HALF, ++ .bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT, ++ }, ++}; ++ ++/** ++ * phy_lookup_setting - lookup a PHY setting ++ * @speed: speed to match ++ * @duplex: duplex to match ++ * @mask: allowed link modes ++ * @maxbit: bit size of link modes ++ * @exact: an exact match is required ++ * ++ * Search the settings array for a setting that matches the speed and ++ * duplex, and which is supported. ++ * ++ * If @exact is unset, either an exact match or %NULL for no match will ++ * be returned. ++ * ++ * If @exact is set, an exact match, the fastest supported setting at ++ * or below the specified speed, the slowest supported setting, or if ++ * they all fail, %NULL will be returned. ++ */ ++const struct phy_setting * ++phy_lookup_setting(int speed, int duplex, const unsigned long *mask, ++ size_t maxbit, bool exact) ++{ ++ const struct phy_setting *p, *match = NULL, *last = NULL; ++ int i; ++ ++ for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) { ++ if (p->bit < maxbit && test_bit(p->bit, mask)) { ++ last = p; ++ if (p->speed == speed && p->duplex == duplex) { ++ /* Exact match for speed and duplex */ ++ match = p; ++ break; ++ } else if (!exact) { ++ if (!match && p->speed <= speed) ++ /* Candidate */ ++ match = p; ++ ++ if (p->speed < speed) ++ break; ++ } ++ } ++ } ++ ++ if (!match && !exact) ++ match = last; ++ ++ return match; ++} ++EXPORT_SYMBOL_GPL(phy_lookup_setting); ++ ++size_t phy_speeds(unsigned int *speeds, size_t size, ++ unsigned long *mask, size_t maxbit) ++{ ++ size_t count; ++ int i; ++ ++ for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++) ++ if (settings[i].bit < maxbit && ++ test_bit(settings[i].bit, mask) && ++ (count == 0 || speeds[count - 1] != settings[i].speed)) ++ speeds[count++] = settings[i].speed; ++ ++ return count; ++} ++ + static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad, + int addr) + { +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -645,6 +645,21 @@ struct phy_fixup { + const char *phy_speed_to_str(int speed); + const char *phy_duplex_to_str(unsigned int duplex); + ++/* A structure for mapping a particular speed and duplex ++ * combination to a particular SUPPORTED and ADVERTISED value ++ */ ++struct phy_setting { ++ u32 speed; ++ u8 duplex; ++ u8 bit; ++}; ++ ++const struct phy_setting * ++phy_lookup_setting(int speed, int duplex, const unsigned long *mask, ++ size_t maxbit, bool exact); ++size_t phy_speeds(unsigned int *speeds, size_t size, ++ unsigned long *mask, size_t maxbit); ++ + /** + * phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. |