aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu/patches-4.9/406-net-phy-improve-phylib-correctness-for-non-autoneg-s.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mvebu/patches-4.9/406-net-phy-improve-phylib-correctness-for-non-autoneg-s.patch')
-rw-r--r--target/linux/mvebu/patches-4.9/406-net-phy-improve-phylib-correctness-for-non-autoneg-s.patch199
1 files changed, 0 insertions, 199 deletions
diff --git a/target/linux/mvebu/patches-4.9/406-net-phy-improve-phylib-correctness-for-non-autoneg-s.patch b/target/linux/mvebu/patches-4.9/406-net-phy-improve-phylib-correctness-for-non-autoneg-s.patch
deleted file mode 100644
index 16516c6846..0000000000
--- a/target/linux/mvebu/patches-4.9/406-net-phy-improve-phylib-correctness-for-non-autoneg-s.patch
+++ /dev/null
@@ -1,199 +0,0 @@
-From: Russell King <rmk+kernel@armlinux.org.uk>
-Date: Thu, 5 Jan 2017 16:32:14 +0000
-Subject: [PATCH] net: phy: improve phylib correctness for non-autoneg
- settings
-
-phylib has some undesirable behaviour when forcing a link mode through
-ethtool. phylib uses this code:
-
- idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
- features);
-
-to find an index in the settings table. phy_find_setting() starts at
-index 0, and scans upwards looking for an exact speed and duplex match.
-When it doesn't find it, it returns MAX_NUM_SETTINGS - 1, which is
-10baseT-Half duplex.
-
-phy_find_valid() then scans from the point (and effectively only checks
-one entry) before bailing out, returning MAX_NUM_SETTINGS - 1.
-
-phy_sanitize_settings() then sets ->speed to SPEED_10 and ->duplex to
-DUPLEX_HALF whether or not 10baseT-Half is supported or not. This goes
-against all the comments against these functions, and 10baseT-Half may
-not even be supported by the hardware.
-
-Rework these functions, introducing a new method of scanning the table.
-There are two modes of lookup that phylib wants: exact, and inexact.
-
-- in exact mode, we return either an exact match or failure
-- in inexact mode, we return an exact match if it exists, a match at
- the highest speed that is not greater than the requested speed
- (ignoring duplex), or failing that, the lowest supported speed, or
- failure.
-
-The biggest difference is that we always check whether the entry is
-supported before further consideration, so all unsupported entries are
-not considered as candidates.
-
-This results in arguably saner behaviour, better matches the comments,
-and is probably what users would expect.
-
-This becomes important as ethernet speeds increase, PHYs exist which do
-not support the 10Mbit speeds, and half-duplex is likely to become
-obsolete - it's already not even an option on 10Gbit and faster links.
-
-Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
----
-
---- a/drivers/net/phy/phy.c
-+++ b/drivers/net/phy/phy.c
-@@ -160,7 +160,9 @@ struct phy_setting {
- u32 setting;
- };
-
--/* A mapping of all SUPPORTED settings to speed/duplex */
-+/* 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,
-@@ -219,45 +221,70 @@ static const struct phy_setting settings
- },
- };
-
--#define MAX_NUM_SETTINGS ARRAY_SIZE(settings)
--
- /**
-- * phy_find_setting - find a PHY settings array entry that matches speed & duplex
-+ * phy_lookup_setting - lookup a PHY setting
- * @speed: speed to match
- * @duplex: duplex to match
-+ * @feature: allowed 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.
- *
-- * Description: Searches the settings array for the setting which
-- * matches the desired speed and duplex, and returns the index
-- * of that setting. Returns the index of the last setting if
-- * none of the others match.
-+ * 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 inline unsigned int phy_find_setting(int speed, int duplex)
-+static const struct phy_setting *
-+phy_lookup_setting(int speed, int duplex, u32 features, bool exact)
- {
-- unsigned int idx = 0;
-+ const struct phy_setting *p, *match = NULL, *last = NULL;
-+ int i;
-
-- while (idx < ARRAY_SIZE(settings) &&
-- (settings[idx].speed != speed || settings[idx].duplex != duplex))
-- idx++;
-+ for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
-+ if (p->setting & features) {
-+ 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;
-+ }
-+ }
-+ }
-
-- return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
-+ if (!match && !exact)
-+ match = last;
-+
-+ return match;
- }
-
- /**
-- * phy_find_valid - find a PHY setting that matches the requested features mask
-- * @idx: The first index in settings[] to search
-- * @features: A mask of the valid settings
-+ * phy_find_valid - find a PHY setting that matches the requested parameters
-+ * @speed: desired speed
-+ * @duplex: desired duplex
-+ * @supported: mask of supported link modes
- *
-- * Description: Returns the index of the first valid setting less
-- * than or equal to the one pointed to by idx, as determined by
-- * the mask in features. Returns the index of the last setting
-- * if nothing else matches.
-+ * Locate a supported phy setting that is, in priority order:
-+ * - an exact match for the specified speed and duplex mode
-+ * - a match for the specified speed, or slower speed
-+ * - the slowest supported speed
-+ * Returns the matched phy_setting entry, or %NULL if no supported phy
-+ * settings were found.
- */
--static inline unsigned int phy_find_valid(unsigned int idx, u32 features)
-+static const struct phy_setting *
-+phy_find_valid(int speed, int duplex, u32 supported)
- {
-- while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
-- idx++;
--
-- return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
-+ return phy_lookup_setting(speed, duplex, supported, false);
- }
-
- /**
-@@ -271,12 +298,7 @@ static inline unsigned int phy_find_vali
- */
- static inline bool phy_check_valid(int speed, int duplex, u32 features)
- {
-- unsigned int idx;
--
-- idx = phy_find_valid(phy_find_setting(speed, duplex), features);
--
-- return settings[idx].speed == speed && settings[idx].duplex == duplex &&
-- (settings[idx].setting & features);
-+ return !!phy_lookup_setting(speed, duplex, features, true);
- }
-
- /**
-@@ -289,18 +311,22 @@ static inline bool phy_check_valid(int s
- */
- static void phy_sanitize_settings(struct phy_device *phydev)
- {
-+ const struct phy_setting *setting;
- u32 features = phydev->supported;
-- unsigned int idx;
-
- /* Sanitize settings based on PHY capabilities */
- if ((features & SUPPORTED_Autoneg) == 0)
- phydev->autoneg = AUTONEG_DISABLE;
-
-- idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
-- features);
--
-- phydev->speed = settings[idx].speed;
-- phydev->duplex = settings[idx].duplex;
-+ setting = phy_find_valid(phydev->speed, phydev->duplex, features);
-+ if (setting) {
-+ phydev->speed = setting->speed;
-+ phydev->duplex = setting->duplex;
-+ } else {
-+ /* We failed to find anything (no supported speeds?) */
-+ phydev->speed = SPEED_UNKNOWN;
-+ phydev->duplex = DUPLEX_UNKNOWN;
-+ }
- }
-
- /**