]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/mdio.c
ixgbe: Fix usage of second flags bitmap when using LRO/RSC
[mv-sheeva.git] / drivers / net / mdio.c
index 2fb0d16b61f72c4e9bec7f2e61f3ddb39aba58de..6851bdb2ce29957b2293e4bb59e7bb1b37e6ae4c 100644 (file)
 #include <linux/mdio.h>
 #include <linux/module.h>
 
+MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers");
+MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc.");
+MODULE_LICENSE("GPL");
+
 /**
  * mdio45_probe - probe for an MDIO (clause 45) device
  * @mdio: MDIO interface
@@ -173,6 +177,8 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
 
        ecmd->transceiver = XCVR_INTERNAL;
        ecmd->phy_address = mdio->prtad;
+       ecmd->mdio_support =
+               mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22);
 
        reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
                              MDIO_CTRL2);
@@ -200,12 +206,29 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
                break;
 
        case MDIO_PMA_CTRL2_10GBCX4:
+               ecmd->port = PORT_OTHER;
+               ecmd->supported = 0;
+               ecmd->advertising = 0;
+               break;
+
        case MDIO_PMA_CTRL2_10GBKX4:
        case MDIO_PMA_CTRL2_10GBKR:
        case MDIO_PMA_CTRL2_1000BKX:
                ecmd->port = PORT_OTHER;
-               ecmd->supported = 0;
-               ecmd->advertising = 0;
+               ecmd->supported = SUPPORTED_Backplane;
+               reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
+                                     MDIO_PMA_EXTABLE);
+               if (reg & MDIO_PMA_EXTABLE_10GBKX4)
+                       ecmd->supported |= SUPPORTED_10000baseKX4_Full;
+               if (reg & MDIO_PMA_EXTABLE_10GBKR)
+                       ecmd->supported |= SUPPORTED_10000baseKR_Full;
+               if (reg & MDIO_PMA_EXTABLE_1000BKX)
+                       ecmd->supported |= SUPPORTED_1000baseKX_Full;
+               reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
+                                     MDIO_PMA_10GBR_FECABLE);
+               if (reg & MDIO_PMA_10GBR_FECABLE_ABLE)
+                       ecmd->supported |= SUPPORTED_10000baseR_FEC;
+               ecmd->advertising = ADVERTISED_Backplane;
                break;
 
        /* All the other defined modes are flavours of optical */
@@ -235,25 +258,31 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
 
        if (ecmd->autoneg) {
                u32 modes = 0;
+               int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad,
+                                             MDIO_MMD_AN, MDIO_STAT1);
 
                /* If AN is complete and successful, report best common
                 * mode, otherwise report best advertised mode. */
-               if (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
-                                   MDIO_STAT1) &
-                   MDIO_AN_STAT1_COMPLETE)
-                       modes = (ecmd->advertising &
-                                (mdio45_get_an(mdio, MDIO_AN_LPA) |
-                                 npage_lpa));
-               if (modes == 0)
+               if (an_stat & MDIO_AN_STAT1_COMPLETE) {
+                       ecmd->lp_advertising =
+                               mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa;
+                       if (an_stat & MDIO_AN_STAT1_LPABLE)
+                               ecmd->lp_advertising |= ADVERTISED_Autoneg;
+                       modes = ecmd->advertising & ecmd->lp_advertising;
+               }
+               if ((modes & ~ADVERTISED_Autoneg) == 0)
                        modes = ecmd->advertising;
 
-               if (modes & ADVERTISED_10000baseT_Full) {
+               if (modes & (ADVERTISED_10000baseT_Full |
+                            ADVERTISED_10000baseKX4_Full |
+                            ADVERTISED_10000baseKR_Full)) {
                        ecmd->speed = SPEED_10000;
                        ecmd->duplex = DUPLEX_FULL;
                } else if (modes & (ADVERTISED_1000baseT_Full |
-                                   ADVERTISED_1000baseT_Half)) {
+                                   ADVERTISED_1000baseT_Half |
+                                   ADVERTISED_1000baseKX_Full)) {
                        ecmd->speed = SPEED_1000;
-                       ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full);
+                       ecmd->duplex = !(modes & ADVERTISED_1000baseT_Half);
                } else if (modes & (ADVERTISED_100baseT_Full |
                                    ADVERTISED_100baseT_Half)) {
                        ecmd->speed = SPEED_100;
@@ -271,6 +300,23 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
                ecmd->duplex = (reg & MDIO_CTRL1_FULLDPLX ||
                                ecmd->speed == SPEED_10000);
        }
+
+       /* 10GBASE-T MDI/MDI-X */
+       if (ecmd->port == PORT_TP && ecmd->speed == SPEED_10000) {
+               switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
+                                       MDIO_PMA_10GBT_SWAPPOL)) {
+               case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
+                       ecmd->eth_tp_mdix = ETH_TP_MDI;
+                       break;
+               case 0:
+                       ecmd->eth_tp_mdix = ETH_TP_MDI_X;
+                       break;
+               default:
+                       /* It's complicated... */
+                       ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
+                       break;
+               }
+       }
 }
 EXPORT_SYMBOL(mdio45_ethtool_gset_npage);