linux/drivers/net/mdio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * mdio.c: Generic support for MDIO-compatible transceivers
   4 * Copyright 2006-2009 Solarflare Communications Inc.
   5 */
   6
   7#include <linux/kernel.h>
   8#include <linux/capability.h>
   9#include <linux/errno.h>
  10#include <linux/ethtool.h>
  11#include <linux/mdio.h>
  12#include <linux/module.h>
  13
  14MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers");
  15MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc.");
  16MODULE_LICENSE("GPL");
  17
  18/**
  19 * mdio45_probe - probe for an MDIO (clause 45) device
  20 * @mdio: MDIO interface
  21 * @prtad: Expected PHY address
  22 *
  23 * This sets @prtad and @mmds in the MDIO interface if successful.
  24 * Returns 0 on success, negative on error.
  25 */
  26int mdio45_probe(struct mdio_if_info *mdio, int prtad)
  27{
  28        int mmd, stat2, devs1, devs2;
  29
  30        /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY
  31         * XS or DTE XS; give up if none is present. */
  32        for (mmd = 1; mmd <= 5; mmd++) {
  33                /* Is this MMD present? */
  34                stat2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_STAT2);
  35                if (stat2 < 0 ||
  36                    (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL)
  37                        continue;
  38
  39                /* It should tell us about all the other MMDs */
  40                devs1 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS1);
  41                devs2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS2);
  42                if (devs1 < 0 || devs2 < 0)
  43                        continue;
  44
  45                mdio->prtad = prtad;
  46                mdio->mmds = devs1 | (devs2 << 16);
  47                return 0;
  48        }
  49
  50        return -ENODEV;
  51}
  52EXPORT_SYMBOL(mdio45_probe);
  53
  54/**
  55 * mdio_set_flag - set or clear flag in an MDIO register
  56 * @mdio: MDIO interface
  57 * @prtad: PHY address
  58 * @devad: MMD address
  59 * @addr: Register address
  60 * @mask: Mask for flag (single bit set)
  61 * @sense: New value of flag
  62 *
  63 * This debounces changes: it does not write the register if the flag
  64 * already has the proper value.  Returns 0 on success, negative on error.
  65 */
  66int mdio_set_flag(const struct mdio_if_info *mdio,
  67                  int prtad, int devad, u16 addr, int mask,
  68                  bool sense)
  69{
  70        int old_val = mdio->mdio_read(mdio->dev, prtad, devad, addr);
  71        int new_val;
  72
  73        if (old_val < 0)
  74                return old_val;
  75        if (sense)
  76                new_val = old_val | mask;
  77        else
  78                new_val = old_val & ~mask;
  79        if (old_val == new_val)
  80                return 0;
  81        return mdio->mdio_write(mdio->dev, prtad, devad, addr, new_val);
  82}
  83EXPORT_SYMBOL(mdio_set_flag);
  84
  85/**
  86 * mdio45_links_ok - is link status up/OK
  87 * @mdio: MDIO interface
  88 * @mmd_mask: Mask for MMDs to check
  89 *
  90 * Returns 1 if the PHY reports link status up/OK, 0 otherwise.
  91 * @mmd_mask is normally @mdio->mmds, but if loopback is enabled
  92 * the MMDs being bypassed should be excluded from the mask.
  93 */
  94int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmd_mask)
  95{
  96        int devad, reg;
  97
  98        if (!mmd_mask) {
  99                /* Use absence of XGMII faults in lieu of link state */
 100                reg = mdio->mdio_read(mdio->dev, mdio->prtad,
 101                                      MDIO_MMD_PHYXS, MDIO_STAT2);
 102                return reg >= 0 && !(reg & MDIO_STAT2_RXFAULT);
 103        }
 104
 105        for (devad = 0; mmd_mask; devad++) {
 106                if (mmd_mask & (1 << devad)) {
 107                        mmd_mask &= ~(1 << devad);
 108
 109                        /* Reset the latched status and fault flags */
 110                        mdio->mdio_read(mdio->dev, mdio->prtad,
 111                                        devad, MDIO_STAT1);
 112                        if (devad == MDIO_MMD_PMAPMD || devad == MDIO_MMD_PCS ||
 113                            devad == MDIO_MMD_PHYXS || devad == MDIO_MMD_DTEXS)
 114                                mdio->mdio_read(mdio->dev, mdio->prtad,
 115                                                devad, MDIO_STAT2);
 116
 117                        /* Check the current status and fault flags */
 118                        reg = mdio->mdio_read(mdio->dev, mdio->prtad,
 119                                              devad, MDIO_STAT1);
 120                        if (reg < 0 ||
 121                            (reg & (MDIO_STAT1_FAULT | MDIO_STAT1_LSTATUS)) !=
 122                            MDIO_STAT1_LSTATUS)
 123                                return false;
 124                }
 125        }
 126
 127        return true;
 128}
 129EXPORT_SYMBOL(mdio45_links_ok);
 130
 131/**
 132 * mdio45_nway_restart - restart auto-negotiation for this interface
 133 * @mdio: MDIO interface
 134 *
 135 * Returns 0 on success, negative on error.
 136 */
 137int mdio45_nway_restart(const struct mdio_if_info *mdio)
 138{
 139        if (!(mdio->mmds & MDIO_DEVS_AN))
 140                return -EOPNOTSUPP;
 141
 142        mdio_set_flag(mdio, mdio->prtad, MDIO_MMD_AN, MDIO_CTRL1,
 143                      MDIO_AN_CTRL1_RESTART, true);
 144        return 0;
 145}
 146EXPORT_SYMBOL(mdio45_nway_restart);
 147
 148static u32 mdio45_get_an(const struct mdio_if_info *mdio, u16 addr)
 149{
 150        u32 result = 0;
 151        int reg;
 152
 153        reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, addr);
 154        if (reg & ADVERTISE_10HALF)
 155                result |= ADVERTISED_10baseT_Half;
 156        if (reg & ADVERTISE_10FULL)
 157                result |= ADVERTISED_10baseT_Full;
 158        if (reg & ADVERTISE_100HALF)
 159                result |= ADVERTISED_100baseT_Half;
 160        if (reg & ADVERTISE_100FULL)
 161                result |= ADVERTISED_100baseT_Full;
 162        if (reg & ADVERTISE_PAUSE_CAP)
 163                result |= ADVERTISED_Pause;
 164        if (reg & ADVERTISE_PAUSE_ASYM)
 165                result |= ADVERTISED_Asym_Pause;
 166        return result;
 167}
 168
 169/**
 170 * mdio45_ethtool_gset_npage - get settings for ETHTOOL_GSET
 171 * @mdio: MDIO interface
 172 * @ecmd: Ethtool request structure
 173 * @npage_adv: Modes currently advertised on next pages
 174 * @npage_lpa: Modes advertised by link partner on next pages
 175 *
 176 * The @ecmd parameter is expected to have been cleared before calling
 177 * mdio45_ethtool_gset_npage().
 178 *
 179 * Since the CSRs for auto-negotiation using next pages are not fully
 180 * standardised, this function does not attempt to decode them.  The
 181 * caller must pass them in.
 182 */
 183void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
 184                               struct ethtool_cmd *ecmd,
 185                               u32 npage_adv, u32 npage_lpa)
 186{
 187        int reg;
 188        u32 speed;
 189
 190        BUILD_BUG_ON(MDIO_SUPPORTS_C22 != ETH_MDIO_SUPPORTS_C22);
 191        BUILD_BUG_ON(MDIO_SUPPORTS_C45 != ETH_MDIO_SUPPORTS_C45);
 192
 193        ecmd->transceiver = XCVR_INTERNAL;
 194        ecmd->phy_address = mdio->prtad;
 195        ecmd->mdio_support =
 196                mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22);
 197
 198        reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 199                              MDIO_CTRL2);
 200        switch (reg & MDIO_PMA_CTRL2_TYPE) {
 201        case MDIO_PMA_CTRL2_10GBT:
 202        case MDIO_PMA_CTRL2_1000BT:
 203        case MDIO_PMA_CTRL2_100BTX:
 204        case MDIO_PMA_CTRL2_10BT:
 205                ecmd->port = PORT_TP;
 206                ecmd->supported = SUPPORTED_TP;
 207                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 208                                      MDIO_SPEED);
 209                if (reg & MDIO_SPEED_10G)
 210                        ecmd->supported |= SUPPORTED_10000baseT_Full;
 211                if (reg & MDIO_PMA_SPEED_1000)
 212                        ecmd->supported |= (SUPPORTED_1000baseT_Full |
 213                                            SUPPORTED_1000baseT_Half);
 214                if (reg & MDIO_PMA_SPEED_100)
 215                        ecmd->supported |= (SUPPORTED_100baseT_Full |
 216                                            SUPPORTED_100baseT_Half);
 217                if (reg & MDIO_PMA_SPEED_10)
 218                        ecmd->supported |= (SUPPORTED_10baseT_Full |
 219                                            SUPPORTED_10baseT_Half);
 220                ecmd->advertising = ADVERTISED_TP;
 221                break;
 222
 223        case MDIO_PMA_CTRL2_10GBCX4:
 224                ecmd->port = PORT_OTHER;
 225                ecmd->supported = 0;
 226                ecmd->advertising = 0;
 227                break;
 228
 229        case MDIO_PMA_CTRL2_10GBKX4:
 230        case MDIO_PMA_CTRL2_10GBKR:
 231        case MDIO_PMA_CTRL2_1000BKX:
 232                ecmd->port = PORT_OTHER;
 233                ecmd->supported = SUPPORTED_Backplane;
 234                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 235                                      MDIO_PMA_EXTABLE);
 236                if (reg & MDIO_PMA_EXTABLE_10GBKX4)
 237                        ecmd->supported |= SUPPORTED_10000baseKX4_Full;
 238                if (reg & MDIO_PMA_EXTABLE_10GBKR)
 239                        ecmd->supported |= SUPPORTED_10000baseKR_Full;
 240                if (reg & MDIO_PMA_EXTABLE_1000BKX)
 241                        ecmd->supported |= SUPPORTED_1000baseKX_Full;
 242                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 243                                      MDIO_PMA_10GBR_FECABLE);
 244                if (reg & MDIO_PMA_10GBR_FECABLE_ABLE)
 245                        ecmd->supported |= SUPPORTED_10000baseR_FEC;
 246                ecmd->advertising = ADVERTISED_Backplane;
 247                break;
 248
 249        /* All the other defined modes are flavours of optical */
 250        default:
 251                ecmd->port = PORT_FIBRE;
 252                ecmd->supported = SUPPORTED_FIBRE;
 253                ecmd->advertising = ADVERTISED_FIBRE;
 254                break;
 255        }
 256
 257        if (mdio->mmds & MDIO_DEVS_AN) {
 258                ecmd->supported |= SUPPORTED_Autoneg;
 259                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
 260                                      MDIO_CTRL1);
 261                if (reg & MDIO_AN_CTRL1_ENABLE) {
 262                        ecmd->autoneg = AUTONEG_ENABLE;
 263                        ecmd->advertising |=
 264                                ADVERTISED_Autoneg |
 265                                mdio45_get_an(mdio, MDIO_AN_ADVERTISE) |
 266                                npage_adv;
 267                } else {
 268                        ecmd->autoneg = AUTONEG_DISABLE;
 269                }
 270        } else {
 271                ecmd->autoneg = AUTONEG_DISABLE;
 272        }
 273
 274        if (ecmd->autoneg) {
 275                u32 modes = 0;
 276                int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad,
 277                                              MDIO_MMD_AN, MDIO_STAT1);
 278
 279                /* If AN is complete and successful, report best common
 280                 * mode, otherwise report best advertised mode. */
 281                if (an_stat & MDIO_AN_STAT1_COMPLETE) {
 282                        ecmd->lp_advertising =
 283                                mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa;
 284                        if (an_stat & MDIO_AN_STAT1_LPABLE)
 285                                ecmd->lp_advertising |= ADVERTISED_Autoneg;
 286                        modes = ecmd->advertising & ecmd->lp_advertising;
 287                }
 288                if ((modes & ~ADVERTISED_Autoneg) == 0)
 289                        modes = ecmd->advertising;
 290
 291                if (modes & (ADVERTISED_10000baseT_Full |
 292                             ADVERTISED_10000baseKX4_Full |
 293                             ADVERTISED_10000baseKR_Full)) {
 294                        speed = SPEED_10000;
 295                        ecmd->duplex = DUPLEX_FULL;
 296                } else if (modes & (ADVERTISED_1000baseT_Full |
 297                                    ADVERTISED_1000baseT_Half |
 298                                    ADVERTISED_1000baseKX_Full)) {
 299                        speed = SPEED_1000;
 300                        ecmd->duplex = !(modes & ADVERTISED_1000baseT_Half);
 301                } else if (modes & (ADVERTISED_100baseT_Full |
 302                                    ADVERTISED_100baseT_Half)) {
 303                        speed = SPEED_100;
 304                        ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full);
 305                } else {
 306                        speed = SPEED_10;
 307                        ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full);
 308                }
 309        } else {
 310                /* Report forced settings */
 311                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 312                                      MDIO_CTRL1);
 313                speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1)
 314                         * ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10));
 315                ecmd->duplex = (reg & MDIO_CTRL1_FULLDPLX ||
 316                                speed == SPEED_10000);
 317        }
 318
 319        ethtool_cmd_speed_set(ecmd, speed);
 320
 321        /* 10GBASE-T MDI/MDI-X */
 322        if (ecmd->port == PORT_TP
 323            && (ethtool_cmd_speed(ecmd) == SPEED_10000)) {
 324                switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 325                                        MDIO_PMA_10GBT_SWAPPOL)) {
 326                case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
 327                        ecmd->eth_tp_mdix = ETH_TP_MDI;
 328                        break;
 329                case 0:
 330                        ecmd->eth_tp_mdix = ETH_TP_MDI_X;
 331                        break;
 332                default:
 333                        /* It's complicated... */
 334                        ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
 335                        break;
 336                }
 337        }
 338}
 339EXPORT_SYMBOL(mdio45_ethtool_gset_npage);
 340
 341/**
 342 * mdio45_ethtool_ksettings_get_npage - get settings for ETHTOOL_GLINKSETTINGS
 343 * @mdio: MDIO interface
 344 * @cmd: Ethtool request structure
 345 * @npage_adv: Modes currently advertised on next pages
 346 * @npage_lpa: Modes advertised by link partner on next pages
 347 *
 348 * The @cmd parameter is expected to have been cleared before calling
 349 * mdio45_ethtool_ksettings_get_npage().
 350 *
 351 * Since the CSRs for auto-negotiation using next pages are not fully
 352 * standardised, this function does not attempt to decode them.  The
 353 * caller must pass them in.
 354 */
 355void mdio45_ethtool_ksettings_get_npage(const struct mdio_if_info *mdio,
 356                                        struct ethtool_link_ksettings *cmd,
 357                                        u32 npage_adv, u32 npage_lpa)
 358{
 359        int reg;
 360        u32 speed, supported = 0, advertising = 0, lp_advertising = 0;
 361
 362        BUILD_BUG_ON(MDIO_SUPPORTS_C22 != ETH_MDIO_SUPPORTS_C22);
 363        BUILD_BUG_ON(MDIO_SUPPORTS_C45 != ETH_MDIO_SUPPORTS_C45);
 364
 365        cmd->base.phy_address = mdio->prtad;
 366        cmd->base.mdio_support =
 367                mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22);
 368
 369        reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 370                              MDIO_CTRL2);
 371        switch (reg & MDIO_PMA_CTRL2_TYPE) {
 372        case MDIO_PMA_CTRL2_10GBT:
 373        case MDIO_PMA_CTRL2_1000BT:
 374        case MDIO_PMA_CTRL2_100BTX:
 375        case MDIO_PMA_CTRL2_10BT:
 376                cmd->base.port = PORT_TP;
 377                supported = SUPPORTED_TP;
 378                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 379                                      MDIO_SPEED);
 380                if (reg & MDIO_SPEED_10G)
 381                        supported |= SUPPORTED_10000baseT_Full;
 382                if (reg & MDIO_PMA_SPEED_1000)
 383                        supported |= (SUPPORTED_1000baseT_Full |
 384                                            SUPPORTED_1000baseT_Half);
 385                if (reg & MDIO_PMA_SPEED_100)
 386                        supported |= (SUPPORTED_100baseT_Full |
 387                                            SUPPORTED_100baseT_Half);
 388                if (reg & MDIO_PMA_SPEED_10)
 389                        supported |= (SUPPORTED_10baseT_Full |
 390                                            SUPPORTED_10baseT_Half);
 391                advertising = ADVERTISED_TP;
 392                break;
 393
 394        case MDIO_PMA_CTRL2_10GBCX4:
 395                cmd->base.port = PORT_OTHER;
 396                supported = 0;
 397                advertising = 0;
 398                break;
 399
 400        case MDIO_PMA_CTRL2_10GBKX4:
 401        case MDIO_PMA_CTRL2_10GBKR:
 402        case MDIO_PMA_CTRL2_1000BKX:
 403                cmd->base.port = PORT_OTHER;
 404                supported = SUPPORTED_Backplane;
 405                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 406                                      MDIO_PMA_EXTABLE);
 407                if (reg & MDIO_PMA_EXTABLE_10GBKX4)
 408                        supported |= SUPPORTED_10000baseKX4_Full;
 409                if (reg & MDIO_PMA_EXTABLE_10GBKR)
 410                        supported |= SUPPORTED_10000baseKR_Full;
 411                if (reg & MDIO_PMA_EXTABLE_1000BKX)
 412                        supported |= SUPPORTED_1000baseKX_Full;
 413                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 414                                      MDIO_PMA_10GBR_FECABLE);
 415                if (reg & MDIO_PMA_10GBR_FECABLE_ABLE)
 416                        supported |= SUPPORTED_10000baseR_FEC;
 417                advertising = ADVERTISED_Backplane;
 418                break;
 419
 420        /* All the other defined modes are flavours of optical */
 421        default:
 422                cmd->base.port = PORT_FIBRE;
 423                supported = SUPPORTED_FIBRE;
 424                advertising = ADVERTISED_FIBRE;
 425                break;
 426        }
 427
 428        if (mdio->mmds & MDIO_DEVS_AN) {
 429                supported |= SUPPORTED_Autoneg;
 430                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
 431                                      MDIO_CTRL1);
 432                if (reg & MDIO_AN_CTRL1_ENABLE) {
 433                        cmd->base.autoneg = AUTONEG_ENABLE;
 434                        advertising |=
 435                                ADVERTISED_Autoneg |
 436                                mdio45_get_an(mdio, MDIO_AN_ADVERTISE) |
 437                                npage_adv;
 438                } else {
 439                        cmd->base.autoneg = AUTONEG_DISABLE;
 440                }
 441        } else {
 442                cmd->base.autoneg = AUTONEG_DISABLE;
 443        }
 444
 445        if (cmd->base.autoneg) {
 446                u32 modes = 0;
 447                int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad,
 448                                              MDIO_MMD_AN, MDIO_STAT1);
 449
 450                /* If AN is complete and successful, report best common
 451                 * mode, otherwise report best advertised mode.
 452                 */
 453                if (an_stat & MDIO_AN_STAT1_COMPLETE) {
 454                        lp_advertising =
 455                                mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa;
 456                        if (an_stat & MDIO_AN_STAT1_LPABLE)
 457                                lp_advertising |= ADVERTISED_Autoneg;
 458                        modes = advertising & lp_advertising;
 459                }
 460                if ((modes & ~ADVERTISED_Autoneg) == 0)
 461                        modes = advertising;
 462
 463                if (modes & (ADVERTISED_10000baseT_Full |
 464                             ADVERTISED_10000baseKX4_Full |
 465                             ADVERTISED_10000baseKR_Full)) {
 466                        speed = SPEED_10000;
 467                        cmd->base.duplex = DUPLEX_FULL;
 468                } else if (modes & (ADVERTISED_1000baseT_Full |
 469                                    ADVERTISED_1000baseT_Half |
 470                                    ADVERTISED_1000baseKX_Full)) {
 471                        speed = SPEED_1000;
 472                        cmd->base.duplex = !(modes & ADVERTISED_1000baseT_Half);
 473                } else if (modes & (ADVERTISED_100baseT_Full |
 474                                    ADVERTISED_100baseT_Half)) {
 475                        speed = SPEED_100;
 476                        cmd->base.duplex = !!(modes & ADVERTISED_100baseT_Full);
 477                } else {
 478                        speed = SPEED_10;
 479                        cmd->base.duplex = !!(modes & ADVERTISED_10baseT_Full);
 480                }
 481        } else {
 482                /* Report forced settings */
 483                reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 484                                      MDIO_CTRL1);
 485                speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1)
 486                         * ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10));
 487                cmd->base.duplex = (reg & MDIO_CTRL1_FULLDPLX ||
 488                                    speed == SPEED_10000);
 489        }
 490
 491        cmd->base.speed = speed;
 492
 493        ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
 494                                                supported);
 495        ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
 496                                                advertising);
 497        ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising,
 498                                                lp_advertising);
 499
 500        /* 10GBASE-T MDI/MDI-X */
 501        if (cmd->base.port == PORT_TP && (cmd->base.speed == SPEED_10000)) {
 502                switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
 503                                        MDIO_PMA_10GBT_SWAPPOL)) {
 504                case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
 505                        cmd->base.eth_tp_mdix = ETH_TP_MDI;
 506                        break;
 507                case 0:
 508                        cmd->base.eth_tp_mdix = ETH_TP_MDI_X;
 509                        break;
 510                default:
 511                        /* It's complicated... */
 512                        cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
 513                        break;
 514                }
 515        }
 516}
 517EXPORT_SYMBOL(mdio45_ethtool_ksettings_get_npage);
 518
 519/**
 520 * mdio_mii_ioctl - MII ioctl interface for MDIO (clause 22 or 45) PHYs
 521 * @mdio: MDIO interface
 522 * @mii_data: MII ioctl data structure
 523 * @cmd: MII ioctl command
 524 *
 525 * Returns 0 on success, negative on error.
 526 */
 527int mdio_mii_ioctl(const struct mdio_if_info *mdio,
 528                   struct mii_ioctl_data *mii_data, int cmd)
 529{
 530        int prtad, devad;
 531        u16 addr = mii_data->reg_num;
 532
 533        /* Validate/convert cmd to one of SIOC{G,S}MIIREG */
 534        switch (cmd) {
 535        case SIOCGMIIPHY:
 536                if (mdio->prtad == MDIO_PRTAD_NONE)
 537                        return -EOPNOTSUPP;
 538                mii_data->phy_id = mdio->prtad;
 539                cmd = SIOCGMIIREG;
 540                break;
 541        case SIOCGMIIREG:
 542        case SIOCSMIIREG:
 543                break;
 544        default:
 545                return -EOPNOTSUPP;
 546        }
 547
 548        /* Validate/convert phy_id */
 549        if ((mdio->mode_support & MDIO_SUPPORTS_C45) &&
 550            mdio_phy_id_is_c45(mii_data->phy_id)) {
 551                prtad = mdio_phy_id_prtad(mii_data->phy_id);
 552                devad = mdio_phy_id_devad(mii_data->phy_id);
 553        } else if ((mdio->mode_support & MDIO_SUPPORTS_C22) &&
 554                   mii_data->phy_id < 0x20) {
 555                prtad = mii_data->phy_id;
 556                devad = MDIO_DEVAD_NONE;
 557                addr &= 0x1f;
 558        } else if ((mdio->mode_support & MDIO_EMULATE_C22) &&
 559                   mdio->prtad != MDIO_PRTAD_NONE &&
 560                   mii_data->phy_id == mdio->prtad) {
 561                /* Remap commonly-used MII registers. */
 562                prtad = mdio->prtad;
 563                switch (addr) {
 564                case MII_BMCR:
 565                case MII_BMSR:
 566                case MII_PHYSID1:
 567                case MII_PHYSID2:
 568                        devad = __ffs(mdio->mmds);
 569                        break;
 570                case MII_ADVERTISE:
 571                case MII_LPA:
 572                        if (!(mdio->mmds & MDIO_DEVS_AN))
 573                                return -EINVAL;
 574                        devad = MDIO_MMD_AN;
 575                        if (addr == MII_ADVERTISE)
 576                                addr = MDIO_AN_ADVERTISE;
 577                        else
 578                                addr = MDIO_AN_LPA;
 579                        break;
 580                default:
 581                        return -EINVAL;
 582                }
 583        } else {
 584                return -EINVAL;
 585        }
 586
 587        if (cmd == SIOCGMIIREG) {
 588                int rc = mdio->mdio_read(mdio->dev, prtad, devad, addr);
 589                if (rc < 0)
 590                        return rc;
 591                mii_data->val_out = rc;
 592                return 0;
 593        } else {
 594                return mdio->mdio_write(mdio->dev, prtad, devad, addr,
 595                                        mii_data->val_in);
 596        }
 597}
 598EXPORT_SYMBOL(mdio_mii_ioctl);
 599