lantiq: clarify VG3503J name
[oweals/openwrt.git] / target / linux / mvebu / patches-4.9 / 412-net-phy-move-phy_lookup_setting-and-guts-of-phy_supp.patch
1 From: Russell King <rmk+kernel@armlinux.org.uk>
2 Date: Thu, 5 Jan 2017 16:47:39 +0000
3 Subject: [PATCH] net: phy: move phy_lookup_setting() and guts of
4  phy_supported_speeds() to phy-core
5
6 phy_lookup_setting() provides useful functionality in ethtool code
7 outside phylib.  Move it to phy-core and allow it to be re-used (eg,
8 in phylink) rather than duplicated elsewhere.  Note that this supports
9 the larger linkmode space.
10
11 As we move the phy settings table, we also need to move the guts of
12 phy_supported_speeds() as well.
13
14 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
15 ---
16
17 --- a/drivers/net/phy/phy.c
18 +++ b/drivers/net/phy/phy.c
19 @@ -149,125 +149,6 @@ static inline int phy_aneg_done(struct p
20         return genphy_aneg_done(phydev);
21  }
22  
23 -/* A structure for mapping a particular speed and duplex
24 - * combination to a particular SUPPORTED and ADVERTISED value
25 - */
26 -struct phy_setting {
27 -       int speed;
28 -       int duplex;
29 -       int bit;
30 -};
31 -
32 -/* A mapping of all SUPPORTED settings to speed/duplex.  This table
33 - * must be grouped by speed and sorted in descending match priority
34 - * - iow, descending speed. */
35 -static const struct phy_setting settings[] = {
36 -       {
37 -               .speed = SPEED_10000,
38 -               .duplex = DUPLEX_FULL,
39 -               .bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
40 -       },
41 -       {
42 -               .speed = SPEED_10000,
43 -               .duplex = DUPLEX_FULL,
44 -               .bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
45 -       },
46 -       {
47 -               .speed = SPEED_10000,
48 -               .duplex = DUPLEX_FULL,
49 -               .bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
50 -       },
51 -       {
52 -               .speed = SPEED_2500,
53 -               .duplex = DUPLEX_FULL,
54 -               .bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
55 -       },
56 -       {
57 -               .speed = SPEED_1000,
58 -               .duplex = DUPLEX_FULL,
59 -               .bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
60 -       },
61 -       {
62 -               .speed = SPEED_1000,
63 -               .duplex = DUPLEX_FULL,
64 -               .bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
65 -       },
66 -       {
67 -               .speed = SPEED_1000,
68 -               .duplex = DUPLEX_HALF,
69 -               .bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
70 -       },
71 -       {
72 -               .speed = SPEED_100,
73 -               .duplex = DUPLEX_FULL,
74 -               .bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
75 -       },
76 -       {
77 -               .speed = SPEED_100,
78 -               .duplex = DUPLEX_HALF,
79 -               .bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
80 -       },
81 -       {
82 -               .speed = SPEED_10,
83 -               .duplex = DUPLEX_FULL,
84 -               .bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
85 -       },
86 -       {
87 -               .speed = SPEED_10,
88 -               .duplex = DUPLEX_HALF,
89 -               .bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
90 -       },
91 -};
92 -
93 -/**
94 - * phy_lookup_setting - lookup a PHY setting
95 - * @speed: speed to match
96 - * @duplex: duplex to match
97 - * @mask: allowed link modes
98 - * @maxbit: bit size of link modes
99 - * @exact: an exact match is required
100 - *
101 - * Search the settings array for a setting that matches the speed and
102 - * duplex, and which is supported.
103 - *
104 - * If @exact is unset, either an exact match or %NULL for no match will
105 - * be returned.
106 - *
107 - * If @exact is set, an exact match, the fastest supported setting at
108 - * or below the specified speed, the slowest supported setting, or if
109 - * they all fail, %NULL will be returned.
110 - */
111 -static const struct phy_setting *
112 -phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
113 -                  size_t maxbit, bool exact)
114 -{
115 -       const struct phy_setting *p, *match = NULL, *last = NULL;
116 -       int i;
117 -
118 -       for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
119 -               if (p->bit < maxbit && test_bit(p->bit, mask)) {
120 -                       last = p;
121 -                       if (p->speed == speed && p->duplex == duplex) {
122 -                               /* Exact match for speed and duplex */
123 -                               match = p;
124 -                               break;
125 -                       } else if (!exact) {
126 -                               if (!match && p->speed <= speed)
127 -                                       /* Candidate */
128 -                                       match = p;
129 -
130 -                               if (p->speed < speed)
131 -                                       break;
132 -                       }
133 -               }
134 -       }
135 -
136 -       if (!match && !exact)
137 -               match = last;
138 -
139 -       return match;
140 -}
141 -
142  /**
143   * phy_find_valid - find a PHY setting that matches the requested parameters
144   * @speed: desired speed
145 @@ -290,6 +171,25 @@ phy_find_valid(int speed, int duplex, u3
146  }
147  
148  /**
149 + * phy_supported_speeds - return all speeds currently supported by a phy device
150 + * @phy: The phy device to return supported speeds of.
151 + * @speeds: buffer to store supported speeds in.
152 + * @size:   size of speeds buffer.
153 + *
154 + * Description: Returns the number of supported speeds, and fills the speeds
155 + * buffer with the supported speeds. If speeds buffer is too small to contain
156 + * all currently supported speeds, will return as many speeds as can fit.
157 + */
158 +unsigned int phy_supported_speeds(struct phy_device *phy,
159 +                                 unsigned int *speeds,
160 +                                 unsigned int size)
161 +{
162 +       unsigned long supported = phy->supported;
163 +
164 +       return phy_speeds(speeds, size, &supported, BITS_PER_LONG);
165 +}
166 +
167 +/**
168   * phy_check_valid - check if there is a valid PHY setting which matches
169   *                  speed, duplex, and feature mask
170   * @speed: speed to match
171 --- a/drivers/net/phy/phy-core.c
172 +++ b/drivers/net/phy/phy-core.c
173 @@ -42,6 +42,132 @@ const char *phy_duplex_to_str(unsigned i
174  }
175  EXPORT_SYMBOL_GPL(phy_duplex_to_str);
176  
177 +/* A mapping of all SUPPORTED settings to speed/duplex.  This table
178 + * must be grouped by speed and sorted in descending match priority
179 + * - iow, descending speed. */
180 +static const struct phy_setting settings[] = {
181 +       {
182 +               .speed = SPEED_10000,
183 +               .duplex = DUPLEX_FULL,
184 +               .bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
185 +       },
186 +       {
187 +               .speed = SPEED_10000,
188 +               .duplex = DUPLEX_FULL,
189 +               .bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
190 +       },
191 +       {
192 +               .speed = SPEED_10000,
193 +               .duplex = DUPLEX_FULL,
194 +               .bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
195 +       },
196 +       {
197 +               .speed = SPEED_2500,
198 +               .duplex = DUPLEX_FULL,
199 +               .bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
200 +       },
201 +       {
202 +               .speed = SPEED_1000,
203 +               .duplex = DUPLEX_FULL,
204 +               .bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
205 +       },
206 +       {
207 +               .speed = SPEED_1000,
208 +               .duplex = DUPLEX_FULL,
209 +               .bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
210 +       },
211 +       {
212 +               .speed = SPEED_1000,
213 +               .duplex = DUPLEX_HALF,
214 +               .bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
215 +       },
216 +       {
217 +               .speed = SPEED_100,
218 +               .duplex = DUPLEX_FULL,
219 +               .bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
220 +       },
221 +       {
222 +               .speed = SPEED_100,
223 +               .duplex = DUPLEX_HALF,
224 +               .bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
225 +       },
226 +       {
227 +               .speed = SPEED_10,
228 +               .duplex = DUPLEX_FULL,
229 +               .bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
230 +       },
231 +       {
232 +               .speed = SPEED_10,
233 +               .duplex = DUPLEX_HALF,
234 +               .bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
235 +       },
236 +};
237 +
238 +/**
239 + * phy_lookup_setting - lookup a PHY setting
240 + * @speed: speed to match
241 + * @duplex: duplex to match
242 + * @mask: allowed link modes
243 + * @maxbit: bit size of link modes
244 + * @exact: an exact match is required
245 + *
246 + * Search the settings array for a setting that matches the speed and
247 + * duplex, and which is supported.
248 + *
249 + * If @exact is unset, either an exact match or %NULL for no match will
250 + * be returned.
251 + *
252 + * If @exact is set, an exact match, the fastest supported setting at
253 + * or below the specified speed, the slowest supported setting, or if
254 + * they all fail, %NULL will be returned.
255 + */
256 +const struct phy_setting *
257 +phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
258 +                  size_t maxbit, bool exact)
259 +{
260 +       const struct phy_setting *p, *match = NULL, *last = NULL;
261 +       int i;
262 +
263 +       for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
264 +               if (p->bit < maxbit && test_bit(p->bit, mask)) {
265 +                       last = p;
266 +                       if (p->speed == speed && p->duplex == duplex) {
267 +                               /* Exact match for speed and duplex */
268 +                               match = p;
269 +                               break;
270 +                       } else if (!exact) {
271 +                               if (!match && p->speed <= speed)
272 +                                       /* Candidate */
273 +                                       match = p;
274 +
275 +                               if (p->speed < speed)
276 +                                       break;
277 +                       }
278 +               }
279 +       }
280 +
281 +       if (!match && !exact)
282 +               match = last;
283 +
284 +       return match;
285 +}
286 +EXPORT_SYMBOL_GPL(phy_lookup_setting);
287 +
288 +size_t phy_speeds(unsigned int *speeds, size_t size,
289 +                 unsigned long *mask, size_t maxbit)
290 +{
291 +       size_t count;
292 +       int i;
293 +
294 +       for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)
295 +               if (settings[i].bit < maxbit &&
296 +                   test_bit(settings[i].bit, mask) &&
297 +                   (count == 0 || speeds[count - 1] != settings[i].speed))
298 +                       speeds[count++] = settings[i].speed;
299 +
300 +       return count;
301 +}
302 +
303  static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
304                                     int addr)
305  {
306 --- a/include/linux/phy.h
307 +++ b/include/linux/phy.h
308 @@ -645,6 +645,21 @@ struct phy_fixup {
309  const char *phy_speed_to_str(int speed);
310  const char *phy_duplex_to_str(unsigned int duplex);
311  
312 +/* A structure for mapping a particular speed and duplex
313 + * combination to a particular SUPPORTED and ADVERTISED value
314 + */
315 +struct phy_setting {
316 +       u32 speed;
317 +       u8 duplex;
318 +       u8 bit;
319 +};
320 +
321 +const struct phy_setting *
322 +phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
323 +                  size_t maxbit, bool exact);
324 +size_t phy_speeds(unsigned int *speeds, size_t size,
325 +                 unsigned long *mask, size_t maxbit);
326 +
327  /**
328   * phy_read_mmd - Convenience function for reading a register
329   * from an MMD on a given PHY.