]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[realtek] Forcibly enable advertisement of 1000Mbps speeds
authorMichael Brown <mcb30@ipxe.org>
Thu, 23 Aug 2012 21:44:20 +0000 (22:44 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 23 Aug 2012 21:44:20 +0000 (22:44 +0100)
Some RTL8169 cards (observed with an RTL8169SC) power up advertising
only 100Mbps, despite being capable of 1000Mbps.  Forcibly enable
advertisement of 1000Mbps on any RTL8169-like card.

This change relies on the assumption that the CTRL1000 register will
not exist on 100Mbps-only RTL8169 cards such as the RTL8101.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/net/realtek.c

index 98fc02f44c689a39ea2bfaf02009d64d1e40315e..09b3fd06f13c2fdbad747385b3a5f1c77e86387a 100644 (file)
@@ -272,6 +272,75 @@ static int realtek_reset ( struct realtek_nic *rtl ) {
        return -ETIMEDOUT;
 }
 
+/**
+ * Configure PHY for Gigabit operation
+ *
+ * @v rtl              Realtek device
+ * @ret rc             Return status code
+ */
+static int realtek_phy_speed ( struct realtek_nic *rtl ) {
+       int ctrl1000;
+       int rc;
+
+       /* Read CTRL1000 register */
+       ctrl1000 = mii_read ( &rtl->mii, MII_CTRL1000 );
+       if ( ctrl1000 < 0 ) {
+               rc = ctrl1000;
+               DBGC ( rtl, "REALTEK %p could not read CTRL1000: %s\n",
+                      rtl, strerror ( rc ) );
+               return rc;
+       }
+
+       /* Advertise 1000Mbps speeds */
+       ctrl1000 |= ( ADVERTISE_1000FULL | ADVERTISE_1000HALF );
+       if ( ( rc = mii_write ( &rtl->mii, MII_CTRL1000, ctrl1000 ) ) != 0 ) {
+               DBGC ( rtl, "REALTEK %p could not write CTRL1000: %s\n",
+                      rtl, strerror ( rc ) );
+               return rc;
+       }
+
+       return 0;
+}
+
+/**
+ * Reset PHY
+ *
+ * @v rtl              Realtek device
+ * @ret rc             Return status code
+ */
+static int realtek_phy_reset ( struct realtek_nic *rtl ) {
+       int rc;
+
+       /* Do nothing if we have no separate PHY register access */
+       if ( ! rtl->have_phy_regs )
+               return 0;
+
+       /* Perform MII reset */
+       if ( ( rc = mii_reset ( &rtl->mii ) ) != 0 ) {
+               DBGC ( rtl, "REALTEK %p could not reset MII: %s\n",
+                      rtl, strerror ( rc ) );
+               return rc;
+       }
+
+       /* Some cards (e.g. RTL8169SC) do not advertise Gigabit by
+        * default.  Try to enable advertisement of Gigabit speeds.
+        */
+       if ( ( rc = realtek_phy_speed ( rtl ) ) != 0 ) {
+               /* Ignore failures, since the register may not be
+                * present on non-Gigabit PHYs (e.g. RTL8101).
+                */
+       }
+
+       /* Restart autonegotiation */
+       if ( ( rc = mii_restart ( &rtl->mii ) ) != 0 ) {
+               DBGC ( rtl, "REALTEK %p could not restart MII: %s\n",
+                      rtl, strerror ( rc ) );
+               return rc;
+       }
+
+       return 0;
+}
+
 /******************************************************************************
  *
  * Link state
@@ -970,12 +1039,8 @@ static int realtek_probe ( struct pci_device *pci ) {
 
        /* Initialise and reset MII interface */
        mii_init ( &rtl->mii, &realtek_mii_operations );
-       if ( rtl->have_phy_regs &&
-            ( ( rc = mii_reset ( &rtl->mii ) ) != 0 ) ) {
-               DBGC ( rtl, "REALTEK %p could not reset MII: %s\n",
-                      rtl, strerror ( rc ) );
-               goto err_mii_reset;
-       }
+       if ( ( rc = realtek_phy_reset ( rtl ) ) != 0 )
+               goto err_phy_reset;
 
        /* Register network device */
        if ( ( rc = register_netdev ( netdev ) ) != 0 )
@@ -996,7 +1061,7 @@ static int realtek_probe ( struct pci_device *pci ) {
  err_register_nvo:
        unregister_netdev ( netdev );
  err_register_netdev:
- err_mii_reset:
+ err_phy_reset:
  err_nvs_read:
        realtek_reset ( rtl );
  err_reset: