[PATCH] e1000: Fix SoL/IDER link and loopback
[pandora-kernel.git] / drivers / net / e1000 / e1000_ethtool.c
index 6b9acc7..c929277 100644 (file)
@@ -183,7 +183,15 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
 
-       if(ecmd->autoneg == AUTONEG_ENABLE) {
+       /* When SoL/IDER sessions are active, autoneg/speed/duplex
+        * cannot be changed */
+       if (e1000_check_phy_reset_block(hw)) {
+               DPRINTK(DRV, ERR, "Cannot change link characteristics "
+                       "when SoL/IDER is active.\n");
+               return -EINVAL;
+       }
+
+       if (ecmd->autoneg == AUTONEG_ENABLE) {
                hw->autoneg = 1;
                if(hw->media_type == e1000_media_type_fiber)
                        hw->autoneg_advertised = ADVERTISED_1000baseT_Full |
@@ -960,16 +968,19 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
                }
        }
 
-       if(txdr->desc)
+       if(txdr->desc) {
                pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
-       if(rxdr->desc)
+               txdr->desc = NULL;
+       }
+       if(rxdr->desc) {
                pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
+               rxdr->desc = NULL;
+       }
 
-       if(txdr->buffer_info)
-               kfree(txdr->buffer_info);
-       if(rxdr->buffer_info)
-               kfree(rxdr->buffer_info);
-
+       kfree(txdr->buffer_info);
+       txdr->buffer_info = NULL;
+       kfree(rxdr->buffer_info);
+       rxdr->buffer_info = NULL;
        return;
 }
 
@@ -1442,12 +1453,25 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
 static int
 e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
 {
-       if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
-       if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback;
+       /* PHY loopback cannot be performed if SoL/IDER
+        * sessions are active */
+       if (e1000_check_phy_reset_block(&adapter->hw)) {
+               DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
+                       "when SoL/IDER is active.\n");
+               *data = 0;
+               goto out;
+       }
+
+       if ((*data = e1000_setup_desc_rings(adapter)))
+               goto out;
+       if ((*data = e1000_setup_loopback_test(adapter)))
+               goto err_loopback;
        *data = e1000_run_loopback_test(adapter);
        e1000_loopback_cleanup(adapter);
-       e1000_free_desc_rings(adapter);
+
 err_loopback:
+       e1000_free_desc_rings(adapter);
+out:
        return *data;
 }
 
@@ -1742,7 +1766,7 @@ e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
        }
 }
 
-struct ethtool_ops e1000_ethtool_ops = {
+static struct ethtool_ops e1000_ethtool_ops = {
        .get_settings           = e1000_get_settings,
        .set_settings           = e1000_set_settings,
        .get_drvinfo            = e1000_get_drvinfo,