.. | .. |
---|
10 | 10 | |
---|
11 | 11 | |
---|
12 | 12 | #include <linux/if.h> |
---|
| 13 | +#include <linux/linkmode.h> |
---|
13 | 14 | #include <uapi/linux/mii.h> |
---|
14 | 15 | |
---|
15 | 16 | struct ethtool_cmd; |
---|
.. | .. |
---|
132 | 133 | } |
---|
133 | 134 | |
---|
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 | +static inline u32 linkmode_adv_to_mii_adv_t(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 | +/** |
---|
135 | 164 | * mii_adv_to_ethtool_adv_t |
---|
136 | 165 | * @adv: value of the MII_ADVERTISE register |
---|
137 | 166 | * |
---|
.. | .. |
---|
173 | 202 | if (ethadv & ADVERTISED_1000baseT_Half) |
---|
174 | 203 | result |= ADVERTISE_1000HALF; |
---|
175 | 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 | + */ |
---|
| 218 | +static inline u32 linkmode_adv_to_mii_ctrl1000_t(unsigned long *advertising) |
---|
| 219 | +{ |
---|
| 220 | + u32 result = 0; |
---|
| 221 | + |
---|
| 222 | + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, |
---|
| 223 | + advertising)) |
---|
| 224 | + result |= ADVERTISE_1000HALF; |
---|
| 225 | + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
---|
| 226 | + advertising)) |
---|
176 | 227 | result |= ADVERTISE_1000FULL; |
---|
177 | 228 | |
---|
178 | 229 | return result; |
---|
.. | .. |
---|
237 | 288 | } |
---|
238 | 289 | |
---|
239 | 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 | +static inline void mii_stat1000_mod_linkmode_lpa_t(unsigned long *advertising, |
---|
| 300 | + u32 lpa) |
---|
| 301 | +{ |
---|
| 302 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, |
---|
| 303 | + advertising, lpa & LPA_1000HALF); |
---|
| 304 | + |
---|
| 305 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, |
---|
| 306 | + advertising, lpa & LPA_1000FULL); |
---|
| 307 | +} |
---|
| 308 | + |
---|
| 309 | +/** |
---|
240 | 310 | * ethtool_adv_to_mii_adv_x |
---|
241 | 311 | * @ethadv: the ethtool advertisement settings |
---|
242 | 312 | * |
---|
.. | .. |
---|
285 | 355 | } |
---|
286 | 356 | |
---|
287 | 357 | /** |
---|
288 | | - * mii_lpa_to_ethtool_lpa_x |
---|
| 358 | + * mii_lpa_mod_linkmode_adv_sgmii |
---|
| 359 | + * @lp_advertising: pointer to destination link mode. |
---|
| 360 | + * @lpa: value of the MII_LPA register |
---|
| 361 | + * |
---|
| 362 | + * A small helper function that translates MII_LPA bits to |
---|
| 363 | + * linkmode advertisement settings for SGMII. |
---|
| 364 | + * Leaves other bits unchanged. |
---|
| 365 | + */ |
---|
| 366 | +static inline void |
---|
| 367 | +mii_lpa_mod_linkmode_lpa_sgmii(unsigned long *lp_advertising, u32 lpa) |
---|
| 368 | +{ |
---|
| 369 | + u32 speed_duplex = lpa & LPA_SGMII_DPX_SPD_MASK; |
---|
| 370 | + |
---|
| 371 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, lp_advertising, |
---|
| 372 | + speed_duplex == LPA_SGMII_1000HALF); |
---|
| 373 | + |
---|
| 374 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, lp_advertising, |
---|
| 375 | + speed_duplex == LPA_SGMII_1000FULL); |
---|
| 376 | + |
---|
| 377 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, lp_advertising, |
---|
| 378 | + speed_duplex == LPA_SGMII_100HALF); |
---|
| 379 | + |
---|
| 380 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, lp_advertising, |
---|
| 381 | + speed_duplex == LPA_SGMII_100FULL); |
---|
| 382 | + |
---|
| 383 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, lp_advertising, |
---|
| 384 | + speed_duplex == LPA_SGMII_10HALF); |
---|
| 385 | + |
---|
| 386 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, lp_advertising, |
---|
| 387 | + speed_duplex == LPA_SGMII_10FULL); |
---|
| 388 | +} |
---|
| 389 | + |
---|
| 390 | +/** |
---|
| 391 | + * mii_lpa_to_linkmode_adv_sgmii |
---|
| 392 | + * @advertising: pointer to destination link mode. |
---|
| 393 | + * @lpa: value of the MII_LPA register |
---|
| 394 | + * |
---|
| 395 | + * A small helper function that translates MII_ADVERTISE bits |
---|
| 396 | + * to linkmode advertisement settings when in SGMII mode. |
---|
| 397 | + * Clears the old value of advertising. |
---|
| 398 | + */ |
---|
| 399 | +static inline void mii_lpa_to_linkmode_lpa_sgmii(unsigned long *lp_advertising, |
---|
| 400 | + u32 lpa) |
---|
| 401 | +{ |
---|
| 402 | + linkmode_zero(lp_advertising); |
---|
| 403 | + |
---|
| 404 | + mii_lpa_mod_linkmode_lpa_sgmii(lp_advertising, lpa); |
---|
| 405 | +} |
---|
| 406 | + |
---|
| 407 | +/** |
---|
| 408 | + * mii_adv_mod_linkmode_adv_t |
---|
| 409 | + * @advertising:pointer to destination link mode. |
---|
| 410 | + * @adv: value of the MII_ADVERTISE register |
---|
| 411 | + * |
---|
| 412 | + * A small helper function that translates MII_ADVERTISE bits to |
---|
| 413 | + * linkmode advertisement settings. Leaves other bits unchanged. |
---|
| 414 | + */ |
---|
| 415 | +static inline void mii_adv_mod_linkmode_adv_t(unsigned long *advertising, |
---|
| 416 | + u32 adv) |
---|
| 417 | +{ |
---|
| 418 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, |
---|
| 419 | + advertising, adv & ADVERTISE_10HALF); |
---|
| 420 | + |
---|
| 421 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, |
---|
| 422 | + advertising, adv & ADVERTISE_10FULL); |
---|
| 423 | + |
---|
| 424 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, |
---|
| 425 | + advertising, adv & ADVERTISE_100HALF); |
---|
| 426 | + |
---|
| 427 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, |
---|
| 428 | + advertising, adv & ADVERTISE_100FULL); |
---|
| 429 | + |
---|
| 430 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising, |
---|
| 431 | + adv & ADVERTISE_PAUSE_CAP); |
---|
| 432 | + |
---|
| 433 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, |
---|
| 434 | + advertising, adv & ADVERTISE_PAUSE_ASYM); |
---|
| 435 | +} |
---|
| 436 | + |
---|
| 437 | +/** |
---|
| 438 | + * mii_adv_to_linkmode_adv_t |
---|
| 439 | + * @advertising:pointer to destination link mode. |
---|
| 440 | + * @adv: value of the MII_ADVERTISE register |
---|
| 441 | + * |
---|
| 442 | + * A small helper function that translates MII_ADVERTISE bits |
---|
| 443 | + * to linkmode advertisement settings. Clears the old value |
---|
| 444 | + * of advertising. |
---|
| 445 | + */ |
---|
| 446 | +static inline void mii_adv_to_linkmode_adv_t(unsigned long *advertising, |
---|
| 447 | + u32 adv) |
---|
| 448 | +{ |
---|
| 449 | + linkmode_zero(advertising); |
---|
| 450 | + |
---|
| 451 | + mii_adv_mod_linkmode_adv_t(advertising, adv); |
---|
| 452 | +} |
---|
| 453 | + |
---|
| 454 | +/** |
---|
| 455 | + * mii_lpa_to_linkmode_lpa_t |
---|
289 | 456 | * @adv: value of the MII_LPA register |
---|
290 | 457 | * |
---|
291 | | - * A small helper function that translates MII_LPA |
---|
292 | | - * bits, when in 1000Base-X mode, to ethtool |
---|
293 | | - * LP advertisement settings. |
---|
| 458 | + * A small helper function that translates MII_LPA bits, when in |
---|
| 459 | + * 1000Base-T mode, to linkmode LP advertisement settings. Clears the |
---|
| 460 | + * old value of advertising |
---|
294 | 461 | */ |
---|
295 | | -static inline u32 mii_lpa_to_ethtool_lpa_x(u32 lpa) |
---|
| 462 | +static inline void mii_lpa_to_linkmode_lpa_t(unsigned long *lp_advertising, |
---|
| 463 | + u32 lpa) |
---|
296 | 464 | { |
---|
297 | | - u32 result = 0; |
---|
| 465 | + mii_adv_to_linkmode_adv_t(lp_advertising, lpa); |
---|
298 | 466 | |
---|
299 | 467 | if (lpa & LPA_LPACK) |
---|
300 | | - result |= ADVERTISED_Autoneg; |
---|
| 468 | + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, |
---|
| 469 | + lp_advertising); |
---|
301 | 470 | |
---|
302 | | - return result | mii_adv_to_ethtool_adv_x(lpa); |
---|
| 471 | +} |
---|
| 472 | + |
---|
| 473 | +/** |
---|
| 474 | + * mii_lpa_mod_linkmode_lpa_t |
---|
| 475 | + * @adv: value of the MII_LPA register |
---|
| 476 | + * |
---|
| 477 | + * A small helper function that translates MII_LPA bits, when in |
---|
| 478 | + * 1000Base-T mode, to linkmode LP advertisement settings. Leaves |
---|
| 479 | + * other bits unchanged. |
---|
| 480 | + */ |
---|
| 481 | +static inline void mii_lpa_mod_linkmode_lpa_t(unsigned long *lp_advertising, |
---|
| 482 | + u32 lpa) |
---|
| 483 | +{ |
---|
| 484 | + mii_adv_mod_linkmode_adv_t(lp_advertising, lpa); |
---|
| 485 | + |
---|
| 486 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, |
---|
| 487 | + lp_advertising, lpa & LPA_LPACK); |
---|
| 488 | +} |
---|
| 489 | + |
---|
| 490 | +static inline void mii_ctrl1000_mod_linkmode_adv_t(unsigned long *advertising, |
---|
| 491 | + u32 ctrl1000) |
---|
| 492 | +{ |
---|
| 493 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, advertising, |
---|
| 494 | + ctrl1000 & ADVERTISE_1000HALF); |
---|
| 495 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, advertising, |
---|
| 496 | + ctrl1000 & ADVERTISE_1000FULL); |
---|
| 497 | +} |
---|
| 498 | + |
---|
| 499 | +/** |
---|
| 500 | + * linkmode_adv_to_lcl_adv_t |
---|
| 501 | + * @advertising:pointer to linkmode advertising |
---|
| 502 | + * |
---|
| 503 | + * A small helper function that translates linkmode advertising to LVL |
---|
| 504 | + * pause capabilities. |
---|
| 505 | + */ |
---|
| 506 | +static inline u32 linkmode_adv_to_lcl_adv_t(unsigned long *advertising) |
---|
| 507 | +{ |
---|
| 508 | + u32 lcl_adv = 0; |
---|
| 509 | + |
---|
| 510 | + if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, |
---|
| 511 | + advertising)) |
---|
| 512 | + lcl_adv |= ADVERTISE_PAUSE_CAP; |
---|
| 513 | + if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, |
---|
| 514 | + advertising)) |
---|
| 515 | + lcl_adv |= ADVERTISE_PAUSE_ASYM; |
---|
| 516 | + |
---|
| 517 | + return lcl_adv; |
---|
| 518 | +} |
---|
| 519 | + |
---|
| 520 | +/** |
---|
| 521 | + * mii_lpa_mod_linkmode_x - decode the link partner's config_reg to linkmodes |
---|
| 522 | + * @linkmodes: link modes array |
---|
| 523 | + * @lpa: config_reg word from link partner |
---|
| 524 | + * @fd_bit: link mode for 1000XFULL bit |
---|
| 525 | + */ |
---|
| 526 | +static inline void mii_lpa_mod_linkmode_x(unsigned long *linkmodes, u16 lpa, |
---|
| 527 | + int fd_bit) |
---|
| 528 | +{ |
---|
| 529 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, linkmodes, |
---|
| 530 | + lpa & LPA_LPACK); |
---|
| 531 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes, |
---|
| 532 | + lpa & LPA_1000XPAUSE); |
---|
| 533 | + linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes, |
---|
| 534 | + lpa & LPA_1000XPAUSE_ASYM); |
---|
| 535 | + linkmode_mod_bit(fd_bit, linkmodes, |
---|
| 536 | + lpa & LPA_1000XFULL); |
---|
| 537 | +} |
---|
| 538 | + |
---|
| 539 | +/** |
---|
| 540 | + * linkmode_adv_to_mii_adv_x - encode a linkmode to config_reg |
---|
| 541 | + * @linkmodes: linkmodes |
---|
| 542 | + * @fd_bit: full duplex bit |
---|
| 543 | + */ |
---|
| 544 | +static inline u16 linkmode_adv_to_mii_adv_x(const unsigned long *linkmodes, |
---|
| 545 | + int fd_bit) |
---|
| 546 | +{ |
---|
| 547 | + u16 adv = 0; |
---|
| 548 | + |
---|
| 549 | + if (linkmode_test_bit(fd_bit, linkmodes)) |
---|
| 550 | + adv |= ADVERTISE_1000XFULL; |
---|
| 551 | + if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes)) |
---|
| 552 | + adv |= ADVERTISE_1000XPAUSE; |
---|
| 553 | + if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes)) |
---|
| 554 | + adv |= ADVERTISE_1000XPSE_ASYM; |
---|
| 555 | + |
---|
| 556 | + return adv; |
---|
303 | 557 | } |
---|
304 | 558 | |
---|
305 | 559 | /** |
---|