root/drivers/net/mdio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mdio45_probe
  2. mdio_set_flag
  3. mdio45_links_ok
  4. mdio45_nway_restart
  5. mdio45_get_an
  6. mdio45_ethtool_gset_npage
  7. mdio45_ethtool_ksettings_get_npage
  8. mdio_mii_ioctl

   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 
  14 MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers");
  15 MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc.");
  16 MODULE_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  */
  26 int 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 }
  52 EXPORT_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  */
  66 int 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 }
  83 EXPORT_SYMBOL(mdio_set_flag);
  84 
  85 /**
  86  * mdio_link_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  */
  94 int 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 }
 129 EXPORT_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  */
 137 int 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 }
 146 EXPORT_SYMBOL(mdio45_nway_restart);
 147 
 148 static 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  */
 183 void 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 }
 339 EXPORT_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  */
 355 void 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 }
 517 EXPORT_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  */
 527 int 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 }
 598 EXPORT_SYMBOL(mdio_mii_ioctl);

/* [<][>][^][v][top][bottom][index][help] */