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 : 2 : 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 : 2 : static inline u32 mii_adv_to_ethtool_adv_t(u32 adv) 171 : : { 172 : : u32 result = 0; 173 : : 174 : 2 : if (adv & ADVERTISE_10HALF) 175 : : result |= ADVERTISED_10baseT_Half; 176 : 2 : if (adv & ADVERTISE_10FULL) 177 : 2 : result |= ADVERTISED_10baseT_Full; 178 : 2 : if (adv & ADVERTISE_100HALF) 179 : 2 : result |= ADVERTISED_100baseT_Half; 180 : 2 : if (adv & ADVERTISE_100FULL) 181 : 2 : result |= ADVERTISED_100baseT_Full; 182 : 2 : if (adv & ADVERTISE_PAUSE_CAP) 183 : 2 : result |= ADVERTISED_Pause; 184 : 2 : if (adv & ADVERTISE_PAUSE_ASYM) 185 : 2 : result |= ADVERTISED_Asym_Pause; 186 : : 187 : 2 : 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 : 2 : if (lpa & LPA_LPACK) 265 : : result |= ADVERTISED_Autoneg; 266 : : 267 : 2 : 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 : 2 : if (lpa & LPA_1000HALF) 283 : : result |= ADVERTISED_1000baseT_Half; 284 : 2 : 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 : 2 : if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) { 516 : : cap = FLOW_CTRL_TX | FLOW_CTRL_RX; 517 : 2 : } else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) { 518 : 2 : 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__ */