aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e100.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/e100.c')
-rw-r--r--drivers/net/e100.c93
1 files changed, 77 insertions, 16 deletions
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 861d2eeaa43c..0504db9ad643 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -167,7 +167,7 @@
167 167
168#define DRV_NAME "e100" 168#define DRV_NAME "e100"
169#define DRV_EXT "-NAPI" 169#define DRV_EXT "-NAPI"
170#define DRV_VERSION "3.5.23-k6"DRV_EXT 170#define DRV_VERSION "3.5.24-k2"DRV_EXT
171#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" 171#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
172#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" 172#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation"
173#define PFX DRV_NAME ": " 173#define PFX DRV_NAME ": "
@@ -240,6 +240,7 @@ static struct pci_device_id e100_id_table[] = {
240 INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), 240 INTEL_8255X_ETHERNET_DEVICE(0x1093, 7),
241 INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), 241 INTEL_8255X_ETHERNET_DEVICE(0x1094, 7),
242 INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), 242 INTEL_8255X_ETHERNET_DEVICE(0x1095, 7),
243 INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7),
243 INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), 244 INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
244 INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), 245 INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
245 INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), 246 INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
@@ -275,6 +276,7 @@ enum phy {
275 phy_82562_em = 0x032002A8, 276 phy_82562_em = 0x032002A8,
276 phy_82562_ek = 0x031002A8, 277 phy_82562_ek = 0x031002A8,
277 phy_82562_eh = 0x017002A8, 278 phy_82562_eh = 0x017002A8,
279 phy_82552_v = 0xd061004d,
278 phy_unknown = 0xFFFFFFFF, 280 phy_unknown = 0xFFFFFFFF,
279}; 281};
280 282
@@ -943,6 +945,22 @@ static int mdio_read(struct net_device *netdev, int addr, int reg)
943 945
944static void mdio_write(struct net_device *netdev, int addr, int reg, int data) 946static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
945{ 947{
948 struct nic *nic = netdev_priv(netdev);
949
950 if ((nic->phy == phy_82552_v) && (reg == MII_BMCR) &&
951 (data & (BMCR_ANRESTART | BMCR_ANENABLE))) {
952 u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
953
954 /*
955 * Workaround Si issue where sometimes the part will not
956 * autoneg to 100Mbps even when advertised.
957 */
958 if (advert & ADVERTISE_100FULL)
959 data |= BMCR_SPEED100 | BMCR_FULLDPLX;
960 else if (advert & ADVERTISE_100HALF)
961 data |= BMCR_SPEED100;
962 }
963
946 mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); 964 mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data);
947} 965}
948 966
@@ -1276,16 +1294,12 @@ static int e100_phy_init(struct nic *nic)
1276 if (addr == 32) 1294 if (addr == 32)
1277 return -EAGAIN; 1295 return -EAGAIN;
1278 1296
1279 /* Selected the phy and isolate the rest */ 1297 /* Isolate all the PHY ids */
1280 for (addr = 0; addr < 32; addr++) { 1298 for (addr = 0; addr < 32; addr++)
1281 if (addr != nic->mii.phy_id) { 1299 mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
1282 mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); 1300 /* Select the discovered PHY */
1283 } else { 1301 bmcr &= ~BMCR_ISOLATE;
1284 bmcr = mdio_read(netdev, addr, MII_BMCR); 1302 mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
1285 mdio_write(netdev, addr, MII_BMCR,
1286 bmcr & ~BMCR_ISOLATE);
1287 }
1288 }
1289 1303
1290 /* Get phy ID */ 1304 /* Get phy ID */
1291 id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); 1305 id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
@@ -1303,7 +1317,18 @@ static int e100_phy_init(struct nic *nic)
1303 mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); 1317 mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
1304 } 1318 }
1305 1319
1306 if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && 1320 if (nic->phy == phy_82552_v) {
1321 u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
1322
1323 /* Workaround Si not advertising flow-control during autoneg */
1324 advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1325 mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert);
1326
1327 /* Reset for the above changes to take effect */
1328 bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
1329 bmcr |= BMCR_RESET;
1330 mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
1331 } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
1307 (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && 1332 (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
1308 !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { 1333 !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
1309 /* enable/disable MDI/MDI-X auto-switching. */ 1334 /* enable/disable MDI/MDI-X auto-switching. */
@@ -2134,6 +2159,9 @@ err_clean_rx:
2134} 2159}
2135 2160
2136#define MII_LED_CONTROL 0x1B 2161#define MII_LED_CONTROL 0x1B
2162#define E100_82552_LED_OVERRIDE 0x19
2163#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */
2164#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */
2137static void e100_blink_led(unsigned long data) 2165static void e100_blink_led(unsigned long data)
2138{ 2166{
2139 struct nic *nic = (struct nic *)data; 2167 struct nic *nic = (struct nic *)data;
@@ -2143,10 +2171,19 @@ static void e100_blink_led(unsigned long data)
2143 led_on_559 = 0x05, 2171 led_on_559 = 0x05,
2144 led_on_557 = 0x07, 2172 led_on_557 = 0x07,
2145 }; 2173 };
2174 u16 led_reg = MII_LED_CONTROL;
2175
2176 if (nic->phy == phy_82552_v) {
2177 led_reg = E100_82552_LED_OVERRIDE;
2146 2178
2147 nic->leds = (nic->leds & led_on) ? led_off : 2179 nic->leds = (nic->leds == E100_82552_LED_ON) ?
2148 (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; 2180 E100_82552_LED_OFF : E100_82552_LED_ON;
2149 mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); 2181 } else {
2182 nic->leds = (nic->leds & led_on) ? led_off :
2183 (nic->mac < mac_82559_D101M) ? led_on_557 :
2184 led_on_559;
2185 }
2186 mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds);
2150 mod_timer(&nic->blink_timer, jiffies + HZ / 4); 2187 mod_timer(&nic->blink_timer, jiffies + HZ / 4);
2151} 2188}
2152 2189
@@ -2375,13 +2412,15 @@ static void e100_diag_test(struct net_device *netdev,
2375static int e100_phys_id(struct net_device *netdev, u32 data) 2412static int e100_phys_id(struct net_device *netdev, u32 data)
2376{ 2413{
2377 struct nic *nic = netdev_priv(netdev); 2414 struct nic *nic = netdev_priv(netdev);
2415 u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE :
2416 MII_LED_CONTROL;
2378 2417
2379 if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) 2418 if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
2380 data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); 2419 data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
2381 mod_timer(&nic->blink_timer, jiffies); 2420 mod_timer(&nic->blink_timer, jiffies);
2382 msleep_interruptible(data * 1000); 2421 msleep_interruptible(data * 1000);
2383 del_timer_sync(&nic->blink_timer); 2422 del_timer_sync(&nic->blink_timer);
2384 mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); 2423 mdio_write(netdev, nic->mii.phy_id, led_reg, 0);
2385 2424
2386 return 0; 2425 return 0;
2387} 2426}
@@ -2686,6 +2725,9 @@ static void __devexit e100_remove(struct pci_dev *pdev)
2686 } 2725 }
2687} 2726}
2688 2727
2728#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */
2729#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */
2730#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */
2689static int e100_suspend(struct pci_dev *pdev, pm_message_t state) 2731static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
2690{ 2732{
2691 struct net_device *netdev = pci_get_drvdata(pdev); 2733 struct net_device *netdev = pci_get_drvdata(pdev);
@@ -2698,6 +2740,15 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
2698 pci_save_state(pdev); 2740 pci_save_state(pdev);
2699 2741
2700 if ((nic->flags & wol_magic) | e100_asf(nic)) { 2742 if ((nic->flags & wol_magic) | e100_asf(nic)) {
2743 /* enable reverse auto-negotiation */
2744 if (nic->phy == phy_82552_v) {
2745 u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
2746 E100_82552_SMARTSPEED);
2747
2748 mdio_write(netdev, nic->mii.phy_id,
2749 E100_82552_SMARTSPEED, smartspeed |
2750 E100_82552_REV_ANEG | E100_82552_ANEG_NOW);
2751 }
2701 if (pci_enable_wake(pdev, PCI_D3cold, true)) 2752 if (pci_enable_wake(pdev, PCI_D3cold, true))
2702 pci_enable_wake(pdev, PCI_D3hot, true); 2753 pci_enable_wake(pdev, PCI_D3hot, true);
2703 } else { 2754 } else {
@@ -2721,6 +2772,16 @@ static int e100_resume(struct pci_dev *pdev)
2721 /* ack any pending wake events, disable PME */ 2772 /* ack any pending wake events, disable PME */
2722 pci_enable_wake(pdev, 0, 0); 2773 pci_enable_wake(pdev, 0, 0);
2723 2774
2775 /* disbale reverse auto-negotiation */
2776 if (nic->phy == phy_82552_v) {
2777 u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
2778 E100_82552_SMARTSPEED);
2779
2780 mdio_write(netdev, nic->mii.phy_id,
2781 E100_82552_SMARTSPEED,
2782 smartspeed & ~(E100_82552_REV_ANEG));
2783 }
2784
2724 netif_device_attach(netdev); 2785 netif_device_attach(netdev);
2725 if (netif_running(netdev)) 2786 if (netif_running(netdev))
2726 e100_up(nic); 2787 e100_up(nic);