kernel: update kernel 4.9 to 4.9.37
[openwrt/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 @@ -648,6 +648,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.