Blame view

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