Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */
2 : : /*
3 : : * linux/mii.h: definitions for MII-compatible transceivers
4 : : * Originally drivers/net/sunhme.h.
5 : : *
6 : : * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com)
7 : : */
8 : : #ifndef __LINUX_MII_H__
9 : : #define __LINUX_MII_H__
10 : :
11 : :
12 : : #include <linux/if.h>
13 : : #include <linux/linkmode.h>
14 : : #include <uapi/linux/mii.h>
15 : :
16 : : struct ethtool_cmd;
17 : :
18 : : struct mii_if_info {
19 : : int phy_id;
20 : : int advertising;
21 : : int phy_id_mask;
22 : : int reg_num_mask;
23 : :
24 : : unsigned int full_duplex : 1; /* is full duplex? */
25 : : unsigned int force_media : 1; /* is autoneg. disabled? */
26 : : unsigned int supports_gmii : 1; /* are GMII registers supported? */
27 : :
28 : : struct net_device *dev;
29 : : int (*mdio_read) (struct net_device *dev, int phy_id, int location);
30 : : void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
31 : : };
32 : :
33 : : extern int mii_link_ok (struct mii_if_info *mii);
34 : : extern int mii_nway_restart (struct mii_if_info *mii);
35 : : extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
36 : : extern void mii_ethtool_get_link_ksettings(
37 : : struct mii_if_info *mii, struct ethtool_link_ksettings *cmd);
38 : : extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
39 : : extern int mii_ethtool_set_link_ksettings(
40 : : struct mii_if_info *mii, const struct ethtool_link_ksettings *cmd);
41 : : extern int mii_check_gmii_support(struct mii_if_info *mii);
42 : : extern void mii_check_link (struct mii_if_info *mii);
43 : : extern unsigned int mii_check_media (struct mii_if_info *mii,
44 : : unsigned int ok_to_print,
45 : : unsigned int init_media);
46 : : extern int generic_mii_ioctl(struct mii_if_info *mii_if,
47 : : struct mii_ioctl_data *mii_data, int cmd,
48 : : unsigned int *duplex_changed);
49 : :
50 : :
51 : : static inline struct mii_ioctl_data *if_mii(struct ifreq *rq)
52 : : {
53 : 0 : return (struct mii_ioctl_data *) &rq->ifr_ifru;
54 : : }
55 : :
56 : : /**
57 : : * mii_nway_result
58 : : * @negotiated: value of MII ANAR and'd with ANLPAR
59 : : *
60 : : * Given a set of MII abilities, check each bit and returns the
61 : : * currently supported media, in the priority order defined by
62 : : * IEEE 802.3u. We use LPA_xxx constants but note this is not the
63 : : * value of LPA solely, as described above.
64 : : *
65 : : * The one exception to IEEE 802.3u is that 100baseT4 is placed
66 : : * between 100T-full and 100T-half. If your phy does not support
67 : : * 100T4 this is fine. If your phy places 100T4 elsewhere in the
68 : : * priority order, you will need to roll your own function.
69 : : */
70 : : static inline unsigned int mii_nway_result (unsigned int negotiated)
71 : : {
72 : : unsigned int ret;
73 : :
74 [ # # ]: 0 : if (negotiated & LPA_100FULL)
75 : : ret = LPA_100FULL;
76 [ # # ]: 0 : else if (negotiated & LPA_100BASE4)
77 : : ret = LPA_100BASE4;
78 [ # # ]: 0 : else if (negotiated & LPA_100HALF)
79 : : ret = LPA_100HALF;
80 [ # # ]: 0 : else if (negotiated & LPA_10FULL)
81 : : ret = LPA_10FULL;
82 : : else
83 : : ret = LPA_10HALF;
84 : :
85 : : return ret;
86 : : }
87 : :
88 : : /**
89 : : * mii_duplex
90 : : * @duplex_lock: Non-zero if duplex is locked at full
91 : : * @negotiated: value of MII ANAR and'd with ANLPAR
92 : : *
93 : : * A small helper function for a common case. Returns one
94 : : * if the media is operating or locked at full duplex, and
95 : : * returns zero otherwise.
96 : : */
97 : : static inline unsigned int mii_duplex (unsigned int duplex_lock,
98 : : unsigned int negotiated)
99 : : {
100 : : if (duplex_lock)
101 : : return 1;
102 : : if (mii_nway_result(negotiated) & LPA_DUPLEX)
103 : : return 1;
104 : : return 0;
105 : : }
106 : :
107 : : /**
108 : : * ethtool_adv_to_mii_adv_t
109 : : * @ethadv: the ethtool advertisement settings
110 : : *
111 : : * A small helper function that translates ethtool advertisement
112 : : * settings to phy autonegotiation advertisements for the
113 : : * MII_ADVERTISE register.
114 : : */
115 : 0 : static inline u32 ethtool_adv_to_mii_adv_t(u32 ethadv)
116 : : {
117 : : u32 result = 0;
118 : :
119 [ # # ]: 0 : if (ethadv & ADVERTISED_10baseT_Half)
120 : : result |= ADVERTISE_10HALF;
121 [ # # ]: 0 : if (ethadv & ADVERTISED_10baseT_Full)
122 : 0 : result |= ADVERTISE_10FULL;
123 [ # # ]: 0 : if (ethadv & ADVERTISED_100baseT_Half)
124 : 0 : result |= ADVERTISE_100HALF;
125 [ # # ]: 0 : if (ethadv & ADVERTISED_100baseT_Full)
126 : 0 : result |= ADVERTISE_100FULL;
127 [ # # ]: 0 : if (ethadv & ADVERTISED_Pause)
128 : 0 : result |= ADVERTISE_PAUSE_CAP;
129 [ # # ]: 0 : if (ethadv & ADVERTISED_Asym_Pause)
130 : 0 : result |= ADVERTISE_PAUSE_ASYM;
131 : :
132 : 0 : return result;
133 : : }
134 : :
135 : : /**
136 : : * linkmode_adv_to_mii_adv_t
137 : : * @advertising: the linkmode advertisement settings
138 : : *
139 : : * A small helper function that translates linkmode advertisement
140 : : * settings to phy autonegotiation advertisements for the
141 : : * MII_ADVERTISE register.
142 : : */
143 : 0 : static inline u32 linkmode_adv_to_mii_adv_t(unsigned long *advertising)
144 : : {
145 : : u32 result = 0;
146 : :
147 [ # # ]: 0 : if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, advertising))
148 : : result |= ADVERTISE_10HALF;
149 [ # # ]: 0 : if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, advertising))
150 : 0 : result |= ADVERTISE_10FULL;
151 [ # # ]: 0 : if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, advertising))
152 : 0 : result |= ADVERTISE_100HALF;
153 [ # # ]: 0 : if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, advertising))
154 : 0 : result |= ADVERTISE_100FULL;
155 [ # # ]: 0 : if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising))
156 : 0 : result |= ADVERTISE_PAUSE_CAP;
157 [ # # ]: 0 : if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising))
158 : 0 : result |= ADVERTISE_PAUSE_ASYM;
159 : :
160 : 0 : return result;
161 : : }
162 : :
163 : : /**
164 : : * mii_adv_to_ethtool_adv_t
165 : : * @adv: value of the MII_ADVERTISE register
166 : : *
167 : : * A small helper function that translates MII_ADVERTISE bits
168 : : * to ethtool advertisement settings.
169 : : */
170 : 0 : static inline u32 mii_adv_to_ethtool_adv_t(u32 adv)
171 : : {
172 : : u32 result = 0;
173 : :
174 [ # # ]: 0 : if (adv & ADVERTISE_10HALF)
175 : : result |= ADVERTISED_10baseT_Half;
176 [ # # ]: 0 : if (adv & ADVERTISE_10FULL)
177 : 0 : result |= ADVERTISED_10baseT_Full;
178 [ # # ]: 0 : if (adv & ADVERTISE_100HALF)
179 : 0 : result |= ADVERTISED_100baseT_Half;
180 [ # # ]: 0 : if (adv & ADVERTISE_100FULL)
181 : 0 : result |= ADVERTISED_100baseT_Full;
182 [ # # ]: 0 : if (adv & ADVERTISE_PAUSE_CAP)
183 : 0 : result |= ADVERTISED_Pause;
184 [ # # ]: 0 : if (adv & ADVERTISE_PAUSE_ASYM)
185 : 0 : result |= ADVERTISED_Asym_Pause;
186 : :
187 : 0 : return result;
188 : : }
189 : :
190 : : /**
191 : : * ethtool_adv_to_mii_ctrl1000_t
192 : : * @ethadv: the ethtool advertisement settings
193 : : *
194 : : * A small helper function that translates ethtool advertisement
195 : : * settings to phy autonegotiation advertisements for the
196 : : * MII_CTRL1000 register when in 1000T mode.
197 : : */
198 : : static inline u32 ethtool_adv_to_mii_ctrl1000_t(u32 ethadv)
199 : : {
200 : : u32 result = 0;
201 : :
202 [ # # # # ]: 0 : if (ethadv & ADVERTISED_1000baseT_Half)
203 : : result |= ADVERTISE_1000HALF;
204 [ # # # # ]: 0 : if (ethadv & ADVERTISED_1000baseT_Full)
205 : 0 : result |= ADVERTISE_1000FULL;
206 : :
207 : : return result;
208 : : }
209 : :
210 : : /**
211 : : * linkmode_adv_to_mii_ctrl1000_t
212 : : * @advertising: the linkmode advertisement settings
213 : : *
214 : : * A small helper function that translates linkmode advertisement
215 : : * settings to phy autonegotiation advertisements for the
216 : : * MII_CTRL1000 register when in 1000T mode.
217 : : */
218 : : static inline u32 linkmode_adv_to_mii_ctrl1000_t(unsigned long *advertising)
219 : : {
220 : : u32 result = 0;
221 : :
222 [ # # ]: 0 : if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
223 : : advertising))
224 : : result |= ADVERTISE_1000HALF;
225 [ # # ]: 0 : if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
226 : : advertising))
227 : 0 : result |= ADVERTISE_1000FULL;
228 : :
229 : : return result;
230 : : }
231 : :
232 : : /**
233 : : * mii_ctrl1000_to_ethtool_adv_t
234 : : * @adv: value of the MII_CTRL1000 register
235 : : *
236 : : * A small helper function that translates MII_CTRL1000
237 : : * bits, when in 1000Base-T mode, to ethtool
238 : : * advertisement settings.
239 : : */
240 : : static inline u32 mii_ctrl1000_to_ethtool_adv_t(u32 adv)
241 : : {
242 : : u32 result = 0;
243 : :
244 [ # # # # ]: 0 : if (adv & ADVERTISE_1000HALF)
245 : : result |= ADVERTISED_1000baseT_Half;
246 [ # # # # ]: 0 : if (adv & ADVERTISE_1000FULL)
247 : 0 : result |= ADVERTISED_1000baseT_Full;
248 : :
249 : : return result;
250 : : }
251 : :
252 : : /**
253 : : * mii_lpa_to_ethtool_lpa_t
254 : : * @adv: value of the MII_LPA register
255 : : *
256 : : * A small helper function that translates MII_LPA
257 : : * bits, when in 1000Base-T mode, to ethtool
258 : : * LP advertisement settings.
259 : : */
260 : : static inline u32 mii_lpa_to_ethtool_lpa_t(u32 lpa)
261 : : {
262 : : u32 result = 0;
263 : :
264 [ # # ]: 0 : if (lpa & LPA_LPACK)
265 : : result |= ADVERTISED_Autoneg;
266 : :
267 : 0 : return result | mii_adv_to_ethtool_adv_t(lpa);
268 : : }
269 : :
270 : : /**
271 : : * mii_stat1000_to_ethtool_lpa_t
272 : : * @adv: value of the MII_STAT1000 register
273 : : *
274 : : * A small helper function that translates MII_STAT1000
275 : : * bits, when in 1000Base-T mode, to ethtool
276 : : * advertisement settings.
277 : : */
278 : : static inline u32 mii_stat1000_to_ethtool_lpa_t(u32 lpa)
279 : : {
280 : : u32 result = 0;
281 : :
282 [ # # # # ]: 0 : if (lpa & LPA_1000HALF)
283 : : result |= ADVERTISED_1000baseT_Half;
284 [ # # # # ]: 0 : if (lpa & LPA_1000FULL)
285 : 0 : result |= ADVERTISED_1000baseT_Full;
286 : :
287 : : return result;
288 : : }
289 : :
290 : : /**
291 : : * mii_stat1000_mod_linkmode_lpa_t
292 : : * @advertising: target the linkmode advertisement settings
293 : : * @adv: value of the MII_STAT1000 register
294 : : *
295 : : * A small helper function that translates MII_STAT1000 bits, when in
296 : : * 1000Base-T mode, to linkmode advertisement settings. Other bits in
297 : : * advertising are not changes.
298 : : */
299 : 0 : static inline void mii_stat1000_mod_linkmode_lpa_t(unsigned long *advertising,
300 : : u32 lpa)
301 : : {
302 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
303 : : advertising, lpa & LPA_1000HALF);
304 : :
305 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
306 : : advertising, lpa & LPA_1000FULL);
307 : 0 : }
308 : :
309 : : /**
310 : : * ethtool_adv_to_mii_adv_x
311 : : * @ethadv: the ethtool advertisement settings
312 : : *
313 : : * A small helper function that translates ethtool advertisement
314 : : * settings to phy autonegotiation advertisements for the
315 : : * MII_CTRL1000 register when in 1000Base-X mode.
316 : : */
317 : : static inline u32 ethtool_adv_to_mii_adv_x(u32 ethadv)
318 : : {
319 : : u32 result = 0;
320 : :
321 : : if (ethadv & ADVERTISED_1000baseT_Half)
322 : : result |= ADVERTISE_1000XHALF;
323 : : if (ethadv & ADVERTISED_1000baseT_Full)
324 : : result |= ADVERTISE_1000XFULL;
325 : : if (ethadv & ADVERTISED_Pause)
326 : : result |= ADVERTISE_1000XPAUSE;
327 : : if (ethadv & ADVERTISED_Asym_Pause)
328 : : result |= ADVERTISE_1000XPSE_ASYM;
329 : :
330 : : return result;
331 : : }
332 : :
333 : : /**
334 : : * mii_adv_to_ethtool_adv_x
335 : : * @adv: value of the MII_CTRL1000 register
336 : : *
337 : : * A small helper function that translates MII_CTRL1000
338 : : * bits, when in 1000Base-X mode, to ethtool
339 : : * advertisement settings.
340 : : */
341 : : static inline u32 mii_adv_to_ethtool_adv_x(u32 adv)
342 : : {
343 : : u32 result = 0;
344 : :
345 : : if (adv & ADVERTISE_1000XHALF)
346 : : result |= ADVERTISED_1000baseT_Half;
347 : : if (adv & ADVERTISE_1000XFULL)
348 : : result |= ADVERTISED_1000baseT_Full;
349 : : if (adv & ADVERTISE_1000XPAUSE)
350 : : result |= ADVERTISED_Pause;
351 : : if (adv & ADVERTISE_1000XPSE_ASYM)
352 : : result |= ADVERTISED_Asym_Pause;
353 : :
354 : : return result;
355 : : }
356 : :
357 : : /**
358 : : * mii_lpa_to_ethtool_lpa_x
359 : : * @adv: value of the MII_LPA register
360 : : *
361 : : * A small helper function that translates MII_LPA
362 : : * bits, when in 1000Base-X mode, to ethtool
363 : : * LP advertisement settings.
364 : : */
365 : : static inline u32 mii_lpa_to_ethtool_lpa_x(u32 lpa)
366 : : {
367 : : u32 result = 0;
368 : :
369 : : if (lpa & LPA_LPACK)
370 : : result |= ADVERTISED_Autoneg;
371 : :
372 : : return result | mii_adv_to_ethtool_adv_x(lpa);
373 : : }
374 : :
375 : : /**
376 : : * mii_adv_mod_linkmode_adv_t
377 : : * @advertising:pointer to destination link mode.
378 : : * @adv: value of the MII_ADVERTISE register
379 : : *
380 : : * A small helper function that translates MII_ADVERTISE bits to
381 : : * linkmode advertisement settings. Leaves other bits unchanged.
382 : : */
383 : 0 : static inline void mii_adv_mod_linkmode_adv_t(unsigned long *advertising,
384 : : u32 adv)
385 : : {
386 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
387 : : advertising, adv & ADVERTISE_10HALF);
388 : :
389 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
390 : : advertising, adv & ADVERTISE_10FULL);
391 : :
392 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
393 : : advertising, adv & ADVERTISE_100HALF);
394 : :
395 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
396 : : advertising, adv & ADVERTISE_100FULL);
397 : :
398 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising,
399 : : adv & ADVERTISE_PAUSE_CAP);
400 : :
401 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
402 : : advertising, adv & ADVERTISE_PAUSE_ASYM);
403 : 0 : }
404 : :
405 : : /**
406 : : * mii_adv_to_linkmode_adv_t
407 : : * @advertising:pointer to destination link mode.
408 : : * @adv: value of the MII_ADVERTISE register
409 : : *
410 : : * A small helper function that translates MII_ADVERTISE bits
411 : : * to linkmode advertisement settings. Clears the old value
412 : : * of advertising.
413 : : */
414 : 0 : static inline void mii_adv_to_linkmode_adv_t(unsigned long *advertising,
415 : : u32 adv)
416 : : {
417 : : linkmode_zero(advertising);
418 : :
419 : 0 : mii_adv_mod_linkmode_adv_t(advertising, adv);
420 : 0 : }
421 : :
422 : : /**
423 : : * mii_lpa_to_linkmode_lpa_t
424 : : * @adv: value of the MII_LPA register
425 : : *
426 : : * A small helper function that translates MII_LPA bits, when in
427 : : * 1000Base-T mode, to linkmode LP advertisement settings. Clears the
428 : : * old value of advertising
429 : : */
430 : : static inline void mii_lpa_to_linkmode_lpa_t(unsigned long *lp_advertising,
431 : : u32 lpa)
432 : : {
433 : : mii_adv_to_linkmode_adv_t(lp_advertising, lpa);
434 : :
435 : : if (lpa & LPA_LPACK)
436 : : linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
437 : : lp_advertising);
438 : :
439 : : }
440 : :
441 : : /**
442 : : * mii_lpa_mod_linkmode_lpa_t
443 : : * @adv: value of the MII_LPA register
444 : : *
445 : : * A small helper function that translates MII_LPA bits, when in
446 : : * 1000Base-T mode, to linkmode LP advertisement settings. Leaves
447 : : * other bits unchanged.
448 : : */
449 : 0 : static inline void mii_lpa_mod_linkmode_lpa_t(unsigned long *lp_advertising,
450 : : u32 lpa)
451 : : {
452 : 0 : mii_adv_mod_linkmode_adv_t(lp_advertising, lpa);
453 : :
454 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
455 : : lp_advertising, lpa & LPA_LPACK);
456 : 0 : }
457 : :
458 : 0 : static inline void mii_ctrl1000_mod_linkmode_adv_t(unsigned long *advertising,
459 : : u32 ctrl1000)
460 : : {
461 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, advertising,
462 : : ctrl1000 & ADVERTISE_1000HALF);
463 : 0 : linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, advertising,
464 : : ctrl1000 & ADVERTISE_1000FULL);
465 : 0 : }
466 : :
467 : : /**
468 : : * linkmode_adv_to_lcl_adv_t
469 : : * @advertising:pointer to linkmode advertising
470 : : *
471 : : * A small helper function that translates linkmode advertising to LVL
472 : : * pause capabilities.
473 : : */
474 : : static inline u32 linkmode_adv_to_lcl_adv_t(unsigned long *advertising)
475 : : {
476 : : u32 lcl_adv = 0;
477 : :
478 : : if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
479 : : advertising))
480 : : lcl_adv |= ADVERTISE_PAUSE_CAP;
481 : : if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
482 : : advertising))
483 : : lcl_adv |= ADVERTISE_PAUSE_ASYM;
484 : :
485 : : return lcl_adv;
486 : : }
487 : :
488 : : /**
489 : : * mii_advertise_flowctrl - get flow control advertisement flags
490 : : * @cap: Flow control capabilities (FLOW_CTRL_RX, FLOW_CTRL_TX or both)
491 : : */
492 : : static inline u16 mii_advertise_flowctrl(int cap)
493 : : {
494 : : u16 adv = 0;
495 : :
496 [ # # # # ]: 0 : if (cap & FLOW_CTRL_RX)
497 : : adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
498 [ # # # # ]: 0 : if (cap & FLOW_CTRL_TX)
499 : 0 : adv ^= ADVERTISE_PAUSE_ASYM;
500 : :
501 : : return adv;
502 : : }
503 : :
504 : : /**
505 : : * mii_resolve_flowctrl_fdx
506 : : * @lcladv: value of MII ADVERTISE register
507 : : * @rmtadv: value of MII LPA register
508 : : *
509 : : * Resolve full duplex flow control as per IEEE 802.3-2005 table 28B-3
510 : : */
511 : : static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
512 : : {
513 : : u8 cap = 0;
514 : :
515 [ # # ]: 0 : if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
516 : : cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
517 [ # # ]: 0 : } else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
518 [ # # ]: 0 : if (lcladv & ADVERTISE_PAUSE_CAP)
519 : : cap = FLOW_CTRL_RX;
520 [ # # ]: 0 : else if (rmtadv & ADVERTISE_PAUSE_CAP)
521 : : cap = FLOW_CTRL_TX;
522 : : }
523 : :
524 : : return cap;
525 : : }
526 : :
527 : : #endif /* __LINUX_MII_H__ */
|