File Index
Files and directories
Sign in
FILE

mii.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/mii.h C
  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
 16struct ethtool_cmd;
 17
 18struct 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
 33extern int mii_link_ok (struct mii_if_info *mii);
 34extern int mii_nway_restart (struct mii_if_info *mii);
 35extern void mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
 36extern void mii_ethtool_get_link_ksettings(
 37	struct mii_if_info *mii, struct ethtool_link_ksettings *cmd);
 38extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
 39extern int mii_ethtool_set_link_ksettings(
 40	struct mii_if_info *mii, const struct ethtool_link_ksettings *cmd);
 41extern int mii_check_gmii_support(struct mii_if_info *mii);
 42extern void mii_check_link (struct mii_if_info *mii);
 43extern unsigned int mii_check_media (struct mii_if_info *mii,
 44				     unsigned int ok_to_print,
 45				     unsigned int init_media);
 46extern 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
 51static inline struct mii_ioctl_data *if_mii(struct ifreq *rq)
 52{
 53	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 */
 70static inline unsigned int mii_nway_result (unsigned int negotiated)
 71{
 72	unsigned int ret;
 73
 74	if (negotiated & LPA_100FULL)
 75		ret = LPA_100FULL;
 76	else if (negotiated & LPA_100BASE4)
 77		ret = LPA_100BASE4;
 78	else if (negotiated & LPA_100HALF)
 79		ret = LPA_100HALF;
 80	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 */
 97static 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 */
115static inline u32 ethtool_adv_to_mii_adv_t(u32 ethadv)
116{
117	u32 result = 0;
118
119	if (ethadv & ADVERTISED_10baseT_Half)
120		result |= ADVERTISE_10HALF;
121	if (ethadv & ADVERTISED_10baseT_Full)
122		result |= ADVERTISE_10FULL;
123	if (ethadv & ADVERTISED_100baseT_Half)
124		result |= ADVERTISE_100HALF;
125	if (ethadv & ADVERTISED_100baseT_Full)
126		result |= ADVERTISE_100FULL;
127	if (ethadv & ADVERTISED_Pause)
128		result |= ADVERTISE_PAUSE_CAP;
129	if (ethadv & ADVERTISED_Asym_Pause)
130		result |= ADVERTISE_PAUSE_ASYM;
131
132	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 */
143static inline u32 linkmode_adv_to_mii_adv_t(const unsigned long *advertising)
144{
145	u32 result = 0;
146
147	if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, advertising))
148		result |= ADVERTISE_10HALF;
149	if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, advertising))
150		result |= ADVERTISE_10FULL;
151	if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, advertising))
152		result |= ADVERTISE_100HALF;
153	if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, advertising))
154		result |= ADVERTISE_100FULL;
155	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising))
156		result |= ADVERTISE_PAUSE_CAP;
157	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising))
158		result |= ADVERTISE_PAUSE_ASYM;
159
160	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 */
170static inline u32 mii_adv_to_ethtool_adv_t(u32 adv)
171{
172	u32 result = 0;
173
174	if (adv & ADVERTISE_10HALF)
175		result |= ADVERTISED_10baseT_Half;
176	if (adv & ADVERTISE_10FULL)
177		result |= ADVERTISED_10baseT_Full;
178	if (adv & ADVERTISE_100HALF)
179		result |= ADVERTISED_100baseT_Half;
180	if (adv & ADVERTISE_100FULL)
181		result |= ADVERTISED_100baseT_Full;
182	if (adv & ADVERTISE_PAUSE_CAP)
183		result |= ADVERTISED_Pause;
184	if (adv & ADVERTISE_PAUSE_ASYM)
185		result |= ADVERTISED_Asym_Pause;
186
187	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 */
198static inline u32 ethtool_adv_to_mii_ctrl1000_t(u32 ethadv)
199{
200	u32 result = 0;
201
202	if (ethadv & ADVERTISED_1000baseT_Half)
203		result |= ADVERTISE_1000HALF;
204	if (ethadv & ADVERTISED_1000baseT_Full)
205		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 */
218static inline u32
219linkmode_adv_to_mii_ctrl1000_t(const unsigned long *advertising)
220{
221	u32 result = 0;
222
223	if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
224			      advertising))
225		result |= ADVERTISE_1000HALF;
226	if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
227			      advertising))
228		result |= ADVERTISE_1000FULL;
229
230	return result;
231}
232
233/**
234 * mii_ctrl1000_to_ethtool_adv_t
235 * @adv: value of the MII_CTRL1000 register
236 *
237 * A small helper function that translates MII_CTRL1000
238 * bits, when in 1000Base-T mode, to ethtool
239 * advertisement settings.
240 */
241static inline u32 mii_ctrl1000_to_ethtool_adv_t(u32 adv)
242{
243	u32 result = 0;
244
245	if (adv & ADVERTISE_1000HALF)
246		result |= ADVERTISED_1000baseT_Half;
247	if (adv & ADVERTISE_1000FULL)
248		result |= ADVERTISED_1000baseT_Full;
249
250	return result;
251}
252
253/**
254 * mii_lpa_to_ethtool_lpa_t
255 * @adv: value of the MII_LPA register
256 *
257 * A small helper function that translates MII_LPA
258 * bits, when in 1000Base-T mode, to ethtool
259 * LP advertisement settings.
260 */
261static inline u32 mii_lpa_to_ethtool_lpa_t(u32 lpa)
262{
263	u32 result = 0;
264
265	if (lpa & LPA_LPACK)
266		result |= ADVERTISED_Autoneg;
267
268	return result | mii_adv_to_ethtool_adv_t(lpa);
269}
270
271/**
272 * mii_stat1000_to_ethtool_lpa_t
273 * @adv: value of the MII_STAT1000 register
274 *
275 * A small helper function that translates MII_STAT1000
276 * bits, when in 1000Base-T mode, to ethtool
277 * advertisement settings.
278 */
279static inline u32 mii_stat1000_to_ethtool_lpa_t(u32 lpa)
280{
281	u32 result = 0;
282
283	if (lpa & LPA_1000HALF)
284		result |= ADVERTISED_1000baseT_Half;
285	if (lpa & LPA_1000FULL)
286		result |= ADVERTISED_1000baseT_Full;
287
288	return result;
289}
290
291/**
292 * mii_stat1000_mod_linkmode_lpa_t
293 * @advertising: target the linkmode advertisement settings
294 * @adv: value of the MII_STAT1000 register
295 *
296 * A small helper function that translates MII_STAT1000 bits, when in
297 * 1000Base-T mode, to linkmode advertisement settings. Other bits in
298 * advertising are not changes.
299 */
300static inline void mii_stat1000_mod_linkmode_lpa_t(unsigned long *advertising,
301						   u32 lpa)
302{
303	linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
304			 advertising, lpa & LPA_1000HALF);
305
306	linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
307			 advertising, lpa & LPA_1000FULL);
308}
309
310/**
311 * ethtool_adv_to_mii_adv_x
312 * @ethadv: the ethtool advertisement settings
313 *
314 * A small helper function that translates ethtool advertisement
315 * settings to phy autonegotiation advertisements for the
316 * MII_CTRL1000 register when in 1000Base-X mode.
317 */
318static inline u32 ethtool_adv_to_mii_adv_x(u32 ethadv)
319{
320	u32 result = 0;
321
322	if (ethadv & ADVERTISED_1000baseT_Half)
323		result |= ADVERTISE_1000XHALF;
324	if (ethadv & ADVERTISED_1000baseT_Full)
325		result |= ADVERTISE_1000XFULL;
326	if (ethadv & ADVERTISED_Pause)
327		result |= ADVERTISE_1000XPAUSE;
328	if (ethadv & ADVERTISED_Asym_Pause)
329		result |= ADVERTISE_1000XPSE_ASYM;
330
331	return result;
332}
333
334/**
335 * mii_adv_to_ethtool_adv_x
336 * @adv: value of the MII_CTRL1000 register
337 *
338 * A small helper function that translates MII_CTRL1000
339 * bits, when in 1000Base-X mode, to ethtool
340 * advertisement settings.
341 */
342static inline u32 mii_adv_to_ethtool_adv_x(u32 adv)
343{
344	u32 result = 0;
345
346	if (adv & ADVERTISE_1000XHALF)
347		result |= ADVERTISED_1000baseT_Half;
348	if (adv & ADVERTISE_1000XFULL)
349		result |= ADVERTISED_1000baseT_Full;
350	if (adv & ADVERTISE_1000XPAUSE)
351		result |= ADVERTISED_Pause;
352	if (adv & ADVERTISE_1000XPSE_ASYM)
353		result |= ADVERTISED_Asym_Pause;
354
355	return result;
356}
357
358/**
359 * mii_adv_mod_linkmode_adv_t
360 * @advertising:pointer to destination link mode.
361 * @adv: value of the MII_ADVERTISE register
362 *
363 * A small helper function that translates MII_ADVERTISE bits to
364 * linkmode advertisement settings. Leaves other bits unchanged.
365 */
366static inline void mii_adv_mod_linkmode_adv_t(unsigned long *advertising,
367					      u32 adv)
368{
369	linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
370			 advertising, adv & ADVERTISE_10HALF);
371
372	linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
373			 advertising, adv & ADVERTISE_10FULL);
374
375	linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
376			 advertising, adv & ADVERTISE_100HALF);
377
378	linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
379			 advertising, adv & ADVERTISE_100FULL);
380
381	linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising,
382			 adv & ADVERTISE_PAUSE_CAP);
383
384	linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
385			 advertising, adv & ADVERTISE_PAUSE_ASYM);
386}
387
388/**
389 * mii_adv_to_linkmode_adv_t
390 * @advertising:pointer to destination link mode.
391 * @adv: value of the MII_ADVERTISE register
392 *
393 * A small helper function that translates MII_ADVERTISE bits
394 * to linkmode advertisement settings. Clears the old value
395 * of advertising.
396 */
397static inline void mii_adv_to_linkmode_adv_t(unsigned long *advertising,
398					     u32 adv)
399{
400	linkmode_zero(advertising);
401
402	mii_adv_mod_linkmode_adv_t(advertising, adv);
403}
404
405/**
406 * mii_lpa_to_linkmode_lpa_t
407 * @adv: value of the MII_LPA register
408 *
409 * A small helper function that translates MII_LPA bits, when in
410 * 1000Base-T mode, to linkmode LP advertisement settings. Clears the
411 * old value of advertising
412 */
413static inline void mii_lpa_to_linkmode_lpa_t(unsigned long *lp_advertising,
414					     u32 lpa)
415{
416	mii_adv_to_linkmode_adv_t(lp_advertising, lpa);
417
418	if (lpa & LPA_LPACK)
419		linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
420				 lp_advertising);
421
422}
423
424/**
425 * mii_lpa_mod_linkmode_lpa_t
426 * @adv: value of the MII_LPA register
427 *
428 * A small helper function that translates MII_LPA bits, when in
429 * 1000Base-T mode, to linkmode LP advertisement settings. Leaves
430 * other bits unchanged.
431 */
432static inline void mii_lpa_mod_linkmode_lpa_t(unsigned long *lp_advertising,
433					      u32 lpa)
434{
435	mii_adv_mod_linkmode_adv_t(lp_advertising, lpa);
436
437	linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
438			 lp_advertising, lpa & LPA_LPACK);
439}
440
441static inline void mii_ctrl1000_mod_linkmode_adv_t(unsigned long *advertising,
442						   u32 ctrl1000)
443{
444	linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, advertising,
445			 ctrl1000 & ADVERTISE_1000HALF);
446	linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, advertising,
447			 ctrl1000 & ADVERTISE_1000FULL);
448}
449
450/**
451 * linkmode_adv_to_lcl_adv_t
452 * @advertising:pointer to linkmode advertising
453 *
454 * A small helper function that translates linkmode advertising to LVL
455 * pause capabilities.
456 */
457static inline u32 linkmode_adv_to_lcl_adv_t(const unsigned long *advertising)
458{
459	u32 lcl_adv = 0;
460
461	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
462			      advertising))
463		lcl_adv |= ADVERTISE_PAUSE_CAP;
464	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
465			      advertising))
466		lcl_adv |= ADVERTISE_PAUSE_ASYM;
467
468	return lcl_adv;
469}
470
471/**
472 * mii_lpa_mod_linkmode_x - decode the link partner's config_reg to linkmodes
473 * @linkmodes: link modes array
474 * @lpa: config_reg word from link partner
475 * @fd_bit: link mode for 1000XFULL bit
476 */
477static inline void mii_lpa_mod_linkmode_x(unsigned long *linkmodes, u16 lpa,
478					 int fd_bit)
479{
480	linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, linkmodes,
481			 lpa & LPA_LPACK);
482	linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes,
483			 lpa & LPA_1000XPAUSE);
484	linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes,
485			 lpa & LPA_1000XPAUSE_ASYM);
486	linkmode_mod_bit(fd_bit, linkmodes,
487			 lpa & LPA_1000XFULL);
488}
489
490/**
491 * linkmode_adv_to_mii_adv_x - encode a linkmode to config_reg
492 * @linkmodes: linkmodes
493 * @fd_bit: full duplex bit
494 */
495static inline u16 linkmode_adv_to_mii_adv_x(const unsigned long *linkmodes,
496					    int fd_bit)
497{
498	u16 adv = 0;
499
500	if (linkmode_test_bit(fd_bit, linkmodes))
501		adv |= ADVERTISE_1000XFULL;
502	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes))
503		adv |= ADVERTISE_1000XPAUSE;
504	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes))
505		adv |= ADVERTISE_1000XPSE_ASYM;
506
507	return adv;
508}
509
510/**
511 * mii_advertise_flowctrl - get flow control advertisement flags
512 * @cap: Flow control capabilities (FLOW_CTRL_RX, FLOW_CTRL_TX or both)
513 */
514static inline u16 mii_advertise_flowctrl(int cap)
515{
516	u16 adv = 0;
517
518	if (cap & FLOW_CTRL_RX)
519		adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
520	if (cap & FLOW_CTRL_TX)
521		adv ^= ADVERTISE_PAUSE_ASYM;
522
523	return adv;
524}
525
526/**
527 * mii_resolve_flowctrl_fdx
528 * @lcladv: value of MII ADVERTISE register
529 * @rmtadv: value of MII LPA register
530 *
531 * Resolve full duplex flow control as per IEEE 802.3-2005 table 28B-3
532 */
533static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
534{
535	u8 cap = 0;
536
537	if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
538		cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
539	} else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
540		if (lcladv & ADVERTISE_PAUSE_CAP)
541			cap = FLOW_CTRL_RX;
542		else if (rmtadv & ADVERTISE_PAUSE_CAP)
543			cap = FLOW_CTRL_TX;
544	}
545
546	return cap;
547}
548
549/**
550 * mii_bmcr_encode_fixed - encode fixed speed/duplex settings to a BMCR value
551 * @speed: a SPEED_* value
552 * @duplex: a DUPLEX_* value
553 *
554 * Encode the speed and duplex to a BMCR value. 2500, 1000, 100 and 10 Mbps are
555 * supported. 2500Mbps is encoded to 1000Mbps. Other speeds are encoded as 10
556 * Mbps. Unknown duplex values are encoded to half-duplex.
557 */
558static inline u16 mii_bmcr_encode_fixed(int speed, int duplex)
559{
560	u16 bmcr;
561
562	switch (speed) {
563	case SPEED_2500:
564	case SPEED_1000:
565		bmcr = BMCR_SPEED1000;
566		break;
567
568	case SPEED_100:
569		bmcr = BMCR_SPEED100;
570		break;
571
572	case SPEED_10:
573	default:
574		bmcr = BMCR_SPEED10;
575		break;
576	}
577
578	if (duplex == DUPLEX_FULL)
579		bmcr |= BMCR_FULLDPLX;
580
581	return bmcr;
582}
583
584#endif /* __LINUX_MII_H__ */
~/ Read-only file preview.