Merge branch 'upstream' of git://lost.foo-projects.org/~ahkok/git/netdev-2.6 into...
authorJeff Garzik <jeff@garzik.org>
Wed, 5 Jul 2006 18:32:39 +0000 (14:32 -0400)
committerJeff Garzik <jeff@garzik.org>
Wed, 5 Jul 2006 18:32:39 +0000 (14:32 -0400)
Conflicts:

drivers/net/e1000/e1000_main.c

1  2 
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_main.c

@@@ -34,6 -34,7 +34,6 @@@
  #define _E1000_H_
  
  #include <linux/stddef.h>
 -#include <linux/config.h>
  #include <linux/module.h>
  #include <linux/types.h>
  #include <asm/byteorder.h>
@@@ -68,7 -69,6 +68,6 @@@
  #ifdef NETIF_F_TSO
  #include <net/checksum.h>
  #endif
- #include <linux/workqueue.h>
  #include <linux/mii.h>
  #include <linux/ethtool.h>
  #include <linux/if_vlan.h>
@@@ -143,6 -143,7 +142,7 @@@ struct e1000_adapter
  
  #define AUTO_ALL_MODES            0
  #define E1000_EEPROM_82544_APM    0x0004
+ #define E1000_EEPROM_ICH8_APME    0x0004
  #define E1000_EEPROM_APME         0x0400
  
  #ifndef E1000_MASTER_SLAVE
@@@ -254,7 -255,6 +254,6 @@@ struct e1000_adapter 
        spinlock_t tx_queue_lock;
  #endif
        atomic_t irq_sem;
-       struct work_struct watchdog_task;
        struct work_struct reset_task;
        uint8_t fc_autoneg;
  
  #ifdef NETIF_F_TSO
        boolean_t tso_force;
  #endif
+       boolean_t smart_power_down;     /* phy smart power down */
+       unsigned long flags;
  };
  
+ enum e1000_state_t {
+       __E1000_DRIVER_TESTING,
+       __E1000_RESETTING,
+ };
  
  /*  e1000_main.c  */
  extern char e1000_driver_name[];
@@@ -348,6 -354,7 +353,7 @@@ extern char e1000_driver_version[]
  int e1000_up(struct e1000_adapter *adapter);
  void e1000_down(struct e1000_adapter *adapter);
  void e1000_reset(struct e1000_adapter *adapter);
+ void e1000_reinit_locked(struct e1000_adapter *adapter);
  int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
  void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
  int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
@@@ -109,7 -109,8 +109,8 @@@ e1000_get_settings(struct net_device *n
                                   SUPPORTED_1000baseT_Full|
                                   SUPPORTED_Autoneg |
                                   SUPPORTED_TP);
+               if (hw->phy_type == e1000_phy_ife)
+                       ecmd->supported &= ~SUPPORTED_1000baseT_Full;
                ecmd->advertising = ADVERTISED_TP;
  
                if (hw->autoneg == 1) {
@@@ -203,11 -204,9 +204,9 @@@ e1000_set_settings(struct net_device *n
  
        /* reset the link */
  
-       if (netif_running(adapter->netdev)) {
-               e1000_down(adapter);
-               e1000_reset(adapter);
-               e1000_up(adapter);
-       } else
+       if (netif_running(adapter->netdev))
+               e1000_reinit_locked(adapter);
+       else
                e1000_reset(adapter);
  
        return 0;
@@@ -254,10 -253,9 +253,9 @@@ e1000_set_pauseparam(struct net_device 
        hw->original_fc = hw->fc;
  
        if (adapter->fc_autoneg == AUTONEG_ENABLE) {
-               if (netif_running(adapter->netdev)) {
-                       e1000_down(adapter);
-                       e1000_up(adapter);
-               } else
+               if (netif_running(adapter->netdev))
+                       e1000_reinit_locked(adapter);
+               else
                        e1000_reset(adapter);
        } else
                return ((hw->media_type == e1000_media_type_fiber) ?
@@@ -279,10 -277,9 +277,9 @@@ e1000_set_rx_csum(struct net_device *ne
        struct e1000_adapter *adapter = netdev_priv(netdev);
        adapter->rx_csum = data;
  
-       if (netif_running(netdev)) {
-               e1000_down(adapter);
-               e1000_up(adapter);
-       } else
+       if (netif_running(netdev))
+               e1000_reinit_locked(adapter);
+       else
                e1000_reset(adapter);
        return 0;
  }
@@@ -577,6 -574,7 +574,7 @@@ e1000_get_drvinfo(struct net_device *ne
        case e1000_82572:
        case e1000_82573:
        case e1000_80003es2lan:
+       case e1000_ich8lan:
                sprintf(firmware_version, "%d.%d-%d",
                        (eeprom_data & 0xF000) >> 12,
                        (eeprom_data & 0x0FF0) >> 4,
@@@ -631,6 -629,9 +629,9 @@@ e1000_set_ringparam(struct net_device *
        tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
        rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
  
+       while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
+               msleep(1);
        if (netif_running(adapter->netdev))
                e1000_down(adapter);
  
                adapter->rx_ring = rx_new;
                adapter->tx_ring = tx_new;
                if ((err = e1000_up(adapter)))
-                       return err;
+                       goto err_setup;
        }
  
+       clear_bit(__E1000_RESETTING, &adapter->flags);
        return 0;
  err_setup_tx:
        e1000_free_all_rx_resources(adapter);
@@@ -701,6 -704,8 +704,8 @@@ err_setup_rx
        adapter->rx_ring = rx_old;
        adapter->tx_ring = tx_old;
        e1000_up(adapter);
+ err_setup:
+       clear_bit(__E1000_RESETTING, &adapter->flags);
        return err;
  }
  
@@@ -754,6 -759,7 +759,7 @@@ e1000_reg_test(struct e1000_adapter *ad
                toggle = 0x7FFFF3FF;
                break;
        case e1000_82573:
+       case e1000_ich8lan:
                toggle = 0x7FFFF033;
                break;
        default:
        }
        /* restore previous status */
        E1000_WRITE_REG(&adapter->hw, STATUS, before);
-       REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
-       REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
-       REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
-       REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
+       if (adapter->hw.mac_type != e1000_ich8lan) {
+               REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
+               REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
+               REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
+               REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
+       }
        REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
        REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
        REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);
        REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);
  
        REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
-       REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);
+       before = (adapter->hw.mac_type == e1000_ich8lan ?
+                       0x06C3B33E : 0x06DFB3FE);
+       REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
        REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
  
        if (adapter->hw.mac_type >= e1000_82543) {
  
-               REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);
+               REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);
                REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
-               REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
+               if (adapter->hw.mac_type != e1000_ich8lan)
+                       REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
                REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
                REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
-               for (i = 0; i < E1000_RAR_ENTRIES; i++) {
-                       REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,
-                                        0xFFFFFFFF);
+               value = (adapter->hw.mac_type == e1000_ich8lan ?
+                               E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
+               for (i = 0; i < value; i++) {
                        REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
                                         0xFFFFFFFF);
                }
  
        }
  
-       for (i = 0; i < E1000_MC_TBL_SIZE; i++)
+       value = (adapter->hw.mac_type == e1000_ich8lan ?
+                       E1000_MC_TBL_SIZE_ICH8LAN : E1000_MC_TBL_SIZE);
+       for (i = 0; i < value; i++)
                REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
  
        *data = 0;
@@@ -871,10 -882,10 +882,10 @@@ e1000_intr_test(struct e1000_adapter *a
        *data = 0;
  
        /* Hook up test interrupt handler just for this test */
 -      if (!request_irq(irq, &e1000_test_intr, SA_PROBEIRQ, netdev->name,
 -                       netdev)) {
 +      if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED,
 +                       netdev->name, netdev)) {
                shared_int = FALSE;
 -      } else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
 +      } else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,
                              netdev->name, netdev)){
                *data = 1;
                return -1;
        /* Test each interrupt */
        for (; i < 10; i++) {
  
+               if (adapter->hw.mac_type == e1000_ich8lan && i == 8)
+                       continue;
                /* Interrupt to test */
                mask = 1 << i;
  
@@@ -1246,18 -1259,33 +1259,33 @@@ e1000_integrated_phy_loopback(struct e1
        } else if (adapter->hw.phy_type == e1000_phy_gg82563) {
                e1000_write_phy_reg(&adapter->hw,
                                    GG82563_PHY_KMRN_MODE_CTRL,
-                                   0x1CE);
+                                   0x1CC);
        }
-       /* force 1000, set loopback */
-       e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
  
-       /* Now set up the MAC to the same speed/duplex as the PHY. */
        ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
-       ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
-       ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
-                    E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
-                    E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
-                    E1000_CTRL_FD);     /* Force Duplex to FULL */
+       if (adapter->hw.phy_type == e1000_phy_ife) {
+               /* force 100, set loopback */
+               e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x6100);
+               /* Now set up the MAC to the same speed/duplex as the PHY. */
+               ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
+               ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
+                            E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+                            E1000_CTRL_SPD_100 |/* Force Speed to 100 */
+                            E1000_CTRL_FD);     /* Force Duplex to FULL */
+       } else {
+               /* force 1000, set loopback */
+               e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
+               /* Now set up the MAC to the same speed/duplex as the PHY. */
+               ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+               ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
+               ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
+                            E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+                            E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
+                            E1000_CTRL_FD);     /* Force Duplex to FULL */
+       }
  
        if (adapter->hw.media_type == e1000_media_type_copper &&
           adapter->hw.phy_type == e1000_phy_m88) {
@@@ -1317,6 -1345,7 +1345,7 @@@ e1000_set_phy_loopback(struct e1000_ada
        case e1000_82572:
        case e1000_82573:
        case e1000_80003es2lan:
+       case e1000_ich8lan:
                return e1000_integrated_phy_loopback(adapter);
                break;
  
@@@ -1568,6 -1597,7 +1597,7 @@@ e1000_diag_test(struct net_device *netd
        struct e1000_adapter *adapter = netdev_priv(netdev);
        boolean_t if_running = netif_running(netdev);
  
+       set_bit(__E1000_DRIVER_TESTING, &adapter->flags);
        if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
                /* Offline tests */
  
                        eth_test->flags |= ETH_TEST_FL_FAILED;
  
                if (if_running)
-                       e1000_down(adapter);
+                       /* indicate we're in test mode */
+                       dev_close(netdev);
                else
                        e1000_reset(adapter);
  
                adapter->hw.autoneg = autoneg;
  
                e1000_reset(adapter);
+               clear_bit(__E1000_DRIVER_TESTING, &adapter->flags);
                if (if_running)
-                       e1000_up(adapter);
+                       dev_open(netdev);
        } else {
                /* Online tests */
                if (e1000_link_test(adapter, &data[4]))
                data[1] = 0;
                data[2] = 0;
                data[3] = 0;
+               clear_bit(__E1000_DRIVER_TESTING, &adapter->flags);
        }
        msleep_interruptible(4 * 1000);
  }
@@@ -1778,21 -1812,18 +1812,18 @@@ e1000_phys_id(struct net_device *netdev
                mod_timer(&adapter->blink_timer, jiffies);
                msleep_interruptible(data * 1000);
                del_timer_sync(&adapter->blink_timer);
-       } else if (adapter->hw.mac_type < e1000_82573) {
-               E1000_WRITE_REG(&adapter->hw, LEDCTL,
-                       (E1000_LEDCTL_LED2_BLINK_RATE |
-                        E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
-                        (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
-                        (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
-                        (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+       } else if (adapter->hw.phy_type == e1000_phy_ife) {
+               if (!adapter->blink_timer.function) {
+                       init_timer(&adapter->blink_timer);
+                       adapter->blink_timer.function = e1000_led_blink_callback;
+                       adapter->blink_timer.data = (unsigned long) adapter;
+               }
+               mod_timer(&adapter->blink_timer, jiffies);
                msleep_interruptible(data * 1000);
+               del_timer_sync(&adapter->blink_timer);
+               e1000_write_phy_reg(&(adapter->hw), IFE_PHY_SPECIAL_CONTROL_LED, 0);
        } else {
-               E1000_WRITE_REG(&adapter->hw, LEDCTL,
-                       (E1000_LEDCTL_LED2_BLINK_RATE |
-                        E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
-                        (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
-                        (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
-                        (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
+               e1000_blink_led_start(&adapter->hw);
                msleep_interruptible(data * 1000);
        }
  
@@@ -1807,10 -1838,8 +1838,8 @@@ static in
  e1000_nway_reset(struct net_device *netdev)
  {
        struct e1000_adapter *adapter = netdev_priv(netdev);
-       if (netif_running(netdev)) {
-               e1000_down(adapter);
-               e1000_up(adapter);
-       }
+       if (netif_running(netdev))
+               e1000_reinit_locked(adapter);
        return 0;
  }
  
@@@ -36,7 -36,7 +36,7 @@@ static char e1000_driver_string[] = "In
  #else
  #define DRIVERNAPI "-NAPI"
  #endif
- #define DRV_VERSION "7.0.38-k4"DRIVERNAPI
+ #define DRV_VERSION "7.1.9-k2"DRIVERNAPI
  char e1000_driver_version[] = DRV_VERSION;
  static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
  
@@@ -73,6 -73,11 +73,11 @@@ static struct pci_device_id e1000_pci_t
        INTEL_E1000_ETHERNET_DEVICE(0x1026),
        INTEL_E1000_ETHERNET_DEVICE(0x1027),
        INTEL_E1000_ETHERNET_DEVICE(0x1028),
+       INTEL_E1000_ETHERNET_DEVICE(0x1049),
+       INTEL_E1000_ETHERNET_DEVICE(0x104A),
+       INTEL_E1000_ETHERNET_DEVICE(0x104B),
+       INTEL_E1000_ETHERNET_DEVICE(0x104C),
+       INTEL_E1000_ETHERNET_DEVICE(0x104D),
        INTEL_E1000_ETHERNET_DEVICE(0x105E),
        INTEL_E1000_ETHERNET_DEVICE(0x105F),
        INTEL_E1000_ETHERNET_DEVICE(0x1060),
        INTEL_E1000_ETHERNET_DEVICE(0x109A),
        INTEL_E1000_ETHERNET_DEVICE(0x10B5),
        INTEL_E1000_ETHERNET_DEVICE(0x10B9),
+       INTEL_E1000_ETHERNET_DEVICE(0x10BA),
+       INTEL_E1000_ETHERNET_DEVICE(0x10BB),
        /* required last entry */
        {0,}
  };
@@@ -133,7 -140,6 +140,6 @@@ static void e1000_clean_rx_ring(struct 
  static void e1000_set_multi(struct net_device *netdev);
  static void e1000_update_phy_info(unsigned long data);
  static void e1000_watchdog(unsigned long data);
- static void e1000_watchdog_task(struct e1000_adapter *adapter);
  static void e1000_82547_tx_fifo_stall(unsigned long data);
  static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
  static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
@@@ -178,8 -184,8 +184,8 @@@ static void e1000_vlan_rx_add_vid(struc
  static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
  static void e1000_restore_vlan(struct e1000_adapter *adapter);
  
- #ifdef CONFIG_PM
  static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
+ #ifdef CONFIG_PM
  static int e1000_resume(struct pci_dev *pdev);
  #endif
  static void e1000_shutdown(struct pci_dev *pdev);
@@@ -206,8 -212,8 +212,8 @@@ static struct pci_driver e1000_driver 
        .probe    = e1000_probe,
        .remove   = __devexit_p(e1000_remove),
        /* Power Managment Hooks */
- #ifdef CONFIG_PM
        .suspend  = e1000_suspend,
+ #ifdef CONFIG_PM
        .resume   = e1000_resume,
  #endif
        .shutdown = e1000_shutdown,
@@@ -261,6 -267,44 +267,44 @@@ e1000_exit_module(void
  
  module_exit(e1000_exit_module);
  
 -      flags = SA_SHIRQ | SA_SAMPLE_RANDOM;
+ static int e1000_request_irq(struct e1000_adapter *adapter)
+ {
+       struct net_device *netdev = adapter->netdev;
+       int flags, err = 0;
++      flags = IRQF_SHARED;
+ #ifdef CONFIG_PCI_MSI
+       if (adapter->hw.mac_type > e1000_82547_rev_2) {
+               adapter->have_msi = TRUE;
+               if ((err = pci_enable_msi(adapter->pdev))) {
+                       DPRINTK(PROBE, ERR,
+                        "Unable to allocate MSI interrupt Error: %d\n", err);
+                       adapter->have_msi = FALSE;
+               }
+       }
+       if (adapter->have_msi)
+               flags &= ~SA_SHIRQ;
+ #endif
+       if ((err = request_irq(adapter->pdev->irq, &e1000_intr, flags,
+                              netdev->name, netdev)))
+               DPRINTK(PROBE, ERR,
+                       "Unable to allocate interrupt Error: %d\n", err);
+       return err;
+ }
+ static void e1000_free_irq(struct e1000_adapter *adapter)
+ {
+       struct net_device *netdev = adapter->netdev;
+       free_irq(adapter->pdev->irq, netdev);
+ #ifdef CONFIG_PCI_MSI
+       if (adapter->have_msi)
+               pci_disable_msi(adapter->pdev);
+ #endif
+ }
  /**
   * e1000_irq_disable - Mask off interrupt generation on the NIC
   * @adapter: board private structure
@@@ -329,6 -373,7 +373,7 @@@ e1000_release_hw_control(struct e1000_a
  {
        uint32_t ctrl_ext;
        uint32_t swsm;
+       uint32_t extcnf;
  
        /* Let firmware taken over control of h/w */
        switch (adapter->hw.mac_type) {
                swsm = E1000_READ_REG(&adapter->hw, SWSM);
                E1000_WRITE_REG(&adapter->hw, SWSM,
                                swsm & ~E1000_SWSM_DRV_LOAD);
+       case e1000_ich8lan:
+               extcnf = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+               E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+                               extcnf & ~E1000_CTRL_EXT_DRV_LOAD);
+               break;
        default:
                break;
        }
@@@ -364,6 -414,7 +414,7 @@@ e1000_get_hw_control(struct e1000_adapt
  {
        uint32_t ctrl_ext;
        uint32_t swsm;
+       uint32_t extcnf;
        /* Let firmware know the driver has taken over */
        switch (adapter->hw.mac_type) {
        case e1000_82571:
                E1000_WRITE_REG(&adapter->hw, SWSM,
                                swsm | E1000_SWSM_DRV_LOAD);
                break;
+       case e1000_ich8lan:
+               extcnf = E1000_READ_REG(&adapter->hw, EXTCNF_CTRL);
+               E1000_WRITE_REG(&adapter->hw, EXTCNF_CTRL,
+                               extcnf | E1000_EXTCNF_CTRL_SWFLAG);
+               break;
        default:
                break;
        }
@@@ -387,18 -443,10 +443,10 @@@ in
  e1000_up(struct e1000_adapter *adapter)
  {
        struct net_device *netdev = adapter->netdev;
-       int i, err;
+       int i;
  
        /* hardware has been reset, we need to reload some things */
  
-       /* Reset the PHY if it was previously powered down */
-       if (adapter->hw.media_type == e1000_media_type_copper) {
-               uint16_t mii_reg;
-               e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
-               if (mii_reg & MII_CR_POWER_DOWN)
-                       e1000_phy_hw_reset(&adapter->hw);
-       }
        e1000_set_multi(netdev);
  
        e1000_restore_vlan(adapter);
                                      E1000_DESC_UNUSED(ring));
        }
  
- #ifdef CONFIG_PCI_MSI
-       if (adapter->hw.mac_type > e1000_82547_rev_2) {
-               adapter->have_msi = TRUE;
-               if ((err = pci_enable_msi(adapter->pdev))) {
-                       DPRINTK(PROBE, ERR,
-                        "Unable to allocate MSI interrupt Error: %d\n", err);
-                       adapter->have_msi = FALSE;
-               }
-       }
- #endif
-       if ((err = request_irq(adapter->pdev->irq, &e1000_intr,
-                             IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-                             netdev->name, netdev))) {
-               DPRINTK(PROBE, ERR,
-                   "Unable to allocate interrupt Error: %d\n", err);
-               return err;
-       }
        adapter->tx_queue_len = netdev->tx_queue_len;
  
        mod_timer(&adapter->watchdog_timer, jiffies);
        return 0;
  }
  
+ /**
+  * e1000_power_up_phy - restore link in case the phy was powered down
+  * @adapter: address of board private structure
+  *
+  * The phy may be powered down to save power and turn off link when the
+  * driver is unloaded and wake on lan is not enabled (among others)
+  * *** this routine MUST be followed by a call to e1000_reset ***
+  *
+  **/
+ static void e1000_power_up_phy(struct e1000_adapter *adapter)
+ {
+       uint16_t mii_reg = 0;
+       /* Just clear the power down bit to wake the phy back up */
+       if (adapter->hw.media_type == e1000_media_type_copper) {
+               /* according to the manual, the phy will retain its
+                * settings across a power-down/up cycle */
+               e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+               mii_reg &= ~MII_CR_POWER_DOWN;
+               e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+       }
+ }
+ static void e1000_power_down_phy(struct e1000_adapter *adapter)
+ {
+       boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) &&
+                                     e1000_check_mng_mode(&adapter->hw);
+       /* Power down the PHY so no link is implied when interface is down
+        * The PHY cannot be powered down if any of the following is TRUE
+        * (a) WoL is enabled
+        * (b) AMT is active
+        * (c) SoL/IDER session is active */
+       if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
+           adapter->hw.mac_type != e1000_ich8lan &&
+           adapter->hw.media_type == e1000_media_type_copper &&
+           !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) &&
+           !mng_mode_enabled &&
+           !e1000_check_phy_reset_block(&adapter->hw)) {
+               uint16_t mii_reg = 0;
+               e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+               mii_reg |= MII_CR_POWER_DOWN;
+               e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+               mdelay(1);
+       }
+ }
  void
  e1000_down(struct e1000_adapter *adapter)
  {
        struct net_device *netdev = adapter->netdev;
-       boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) &&
-                                    e1000_check_mng_mode(&adapter->hw);
  
        e1000_irq_disable(adapter);
  
-       free_irq(adapter->pdev->irq, netdev);
- #ifdef CONFIG_PCI_MSI
-       if (adapter->hw.mac_type > e1000_82547_rev_2 &&
-          adapter->have_msi == TRUE)
-               pci_disable_msi(adapter->pdev);
- #endif
        del_timer_sync(&adapter->tx_fifo_stall_timer);
        del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
        e1000_reset(adapter);
        e1000_clean_all_tx_rings(adapter);
        e1000_clean_all_rx_rings(adapter);
+ }
  
-       /* Power down the PHY so no link is implied when interface is down *
-        * The PHY cannot be powered down if any of the following is TRUE *
-        * (a) WoL is enabled
-        * (b) AMT is active
-        * (c) SoL/IDER session is active */
-       if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
-          adapter->hw.media_type == e1000_media_type_copper &&
-          !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) &&
-          !mng_mode_enabled &&
-          !e1000_check_phy_reset_block(&adapter->hw)) {
-               uint16_t mii_reg;
-               e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
-               mii_reg |= MII_CR_POWER_DOWN;
-               e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
-               mdelay(1);
-       }
+ void
+ e1000_reinit_locked(struct e1000_adapter *adapter)
+ {
+       WARN_ON(in_interrupt());
+       while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
+               msleep(1);
+       e1000_down(adapter);
+       e1000_up(adapter);
+       clear_bit(__E1000_RESETTING, &adapter->flags);
  }
  
  void
@@@ -518,6 -581,9 +581,9 @@@ e1000_reset(struct e1000_adapter *adapt
        case e1000_82573:
                pba = E1000_PBA_12K;
                break;
+       case e1000_ich8lan:
+               pba = E1000_PBA_8K;
+               break;
        default:
                pba = E1000_PBA_48K;
                break;
        /* Set the FC high water mark to 90% of the FIFO size.
         * Required to clear last 3 LSB */
        fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;
+       /* We can't use 90% on small FIFOs because the remainder
+        * would be less than 1 full frame.  In this case, we size
+        * it to allow at least a full frame above the high water
+        *  mark. */
+       if (pba < E1000_PBA_16K)
+               fc_high_water_mark = (pba * 1024) - 1600;
  
        adapter->hw.fc_high_water = fc_high_water_mark;
        adapter->hw.fc_low_water = fc_high_water_mark - 8;
  
        e1000_reset_adaptive(&adapter->hw);
        e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+       if (!adapter->smart_power_down &&
+           (adapter->hw.mac_type == e1000_82571 ||
+            adapter->hw.mac_type == e1000_82572)) {
+               uint16_t phy_data = 0;
+               /* speed up time to link by disabling smart power down, ignore
+                * the return value of this function because there is nothing
+                * different we would do if it failed */
+               e1000_read_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+                                  &phy_data);
+               phy_data &= ~IGP02E1000_PM_SPD;
+               e1000_write_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+                                   phy_data);
+       }
+       if (adapter->hw.mac_type < e1000_ich8lan)
+       /* FIXME: this code is duplicate and wrong for PCI Express */
        if (adapter->en_mng_pt) {
                manc = E1000_READ_REG(&adapter->hw, MANC);
                manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
@@@ -590,6 -679,7 +679,7 @@@ e1000_probe(struct pci_dev *pdev
        struct net_device *netdev;
        struct e1000_adapter *adapter;
        unsigned long mmio_start, mmio_len;
+       unsigned long flash_start, flash_len;
  
        static int cards_found = 0;
        static int e1000_ksp3_port_a = 0; /* global ksp3 port a indication */
        if ((err = pci_enable_device(pdev)))
                return err;
  
-       if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+       if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
+           !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
                pci_using_dac = 1;
        } else {
-               if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+               if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) &&
+                   (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
                        E1000_ERR("No usable DMA configuration, aborting\n");
                        return err;
                }
        if ((err = e1000_sw_init(adapter)))
                goto err_sw_init;
  
+       /* Flash BAR mapping must happen after e1000_sw_init
+        * because it depends on mac_type */
+       if ((adapter->hw.mac_type == e1000_ich8lan) &&
+          (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
+               flash_start = pci_resource_start(pdev, 1);
+               flash_len = pci_resource_len(pdev, 1);
+               adapter->hw.flash_address = ioremap(flash_start, flash_len);
+               if (!adapter->hw.flash_address) {
+                       err = -EIO;
+                       goto err_flashmap;
+               }
+       }
        if ((err = e1000_check_phy_reset_block(&adapter->hw)))
                DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
  
                                   NETIF_F_HW_VLAN_TX |
                                   NETIF_F_HW_VLAN_RX |
                                   NETIF_F_HW_VLAN_FILTER;
+               if (adapter->hw.mac_type == e1000_ich8lan)
+                       netdev->features &= ~NETIF_F_HW_VLAN_FILTER;
        }
  
  #ifdef NETIF_F_TSO
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
  
-       /* hard_start_xmit is safe against parallel locking */
        netdev->features |= NETIF_F_LLTX;
  
        adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
  
+       /* initialize eeprom parameters */
+       if (e1000_init_eeprom_params(&adapter->hw)) {
+               E1000_ERR("EEPROM initialization failed\n");
+               return -EIO;
+       }
        /* before reading the EEPROM, reset the controller to
         * put the device in a known good starting state */
  
        adapter->watchdog_timer.function = &e1000_watchdog;
        adapter->watchdog_timer.data = (unsigned long) adapter;
  
-       INIT_WORK(&adapter->watchdog_task,
-               (void (*)(void *))e1000_watchdog_task, adapter);
        init_timer(&adapter->phy_info_timer);
        adapter->phy_info_timer.function = &e1000_update_phy_info;
        adapter->phy_info_timer.data = (unsigned long) adapter;
                        EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
                eeprom_apme_mask = E1000_EEPROM_82544_APM;
                break;
+       case e1000_ich8lan:
+               e1000_read_eeprom(&adapter->hw,
+                       EEPROM_INIT_CONTROL1_REG, 1, &eeprom_data);
+               eeprom_apme_mask = E1000_EEPROM_ICH8_APME;
+               break;
        case e1000_82546:
        case e1000_82546_rev_3:
        case e1000_82571:
        return 0;
  
  err_register:
+       if (adapter->hw.flash_address)
+               iounmap(adapter->hw.flash_address);
+ err_flashmap:
  err_sw_init:
  err_eeprom:
        iounmap(adapter->hw.hw_addr);
@@@ -882,6 -1000,7 +1000,7 @@@ e1000_remove(struct pci_dev *pdev
        flush_scheduled_work();
  
        if (adapter->hw.mac_type >= e1000_82540 &&
+          adapter->hw.mac_type != e1000_ich8lan &&
           adapter->hw.media_type == e1000_media_type_copper) {
                manc = E1000_READ_REG(&adapter->hw, MANC);
                if (manc & E1000_MANC_SMBUS_EN) {
  #endif
  
        iounmap(adapter->hw.hw_addr);
+       if (adapter->hw.flash_address)
+               iounmap(adapter->hw.flash_address);
        pci_release_regions(pdev);
  
        free_netdev(netdev);
@@@ -960,13 -1081,6 +1081,6 @@@ e1000_sw_init(struct e1000_adapter *ada
                return -EIO;
        }
  
-       /* initialize eeprom parameters */
-       if (e1000_init_eeprom_params(hw)) {
-               E1000_ERR("EEPROM initialization failed\n");
-               return -EIO;
-       }
        switch (hw->mac_type) {
        default:
                break;
@@@ -1078,6 -1192,10 +1192,10 @@@ e1000_open(struct net_device *netdev
        struct e1000_adapter *adapter = netdev_priv(netdev);
        int err;
  
+       /* disallow open during test */
+       if (test_bit(__E1000_DRIVER_TESTING, &adapter->flags))
+               return -EBUSY;
        /* allocate transmit descriptors */
  
        if ((err = e1000_setup_all_tx_resources(adapter)))
        if ((err = e1000_setup_all_rx_resources(adapter)))
                goto err_setup_rx;
  
+       err = e1000_request_irq(adapter);
+       if (err)
+               goto err_up;
+       e1000_power_up_phy(adapter);
        if ((err = e1000_up(adapter)))
                goto err_up;
        adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
@@@ -1131,7 -1255,10 +1255,10 @@@ e1000_close(struct net_device *netdev
  {
        struct e1000_adapter *adapter = netdev_priv(netdev);
  
+       WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
        e1000_down(adapter);
+       e1000_power_down_phy(adapter);
+       e1000_free_irq(adapter);
  
        e1000_free_all_tx_resources(adapter);
        e1000_free_all_rx_resources(adapter);
@@@ -1189,8 -1316,7 +1316,7 @@@ e1000_setup_tx_resources(struct e1000_a
        int size;
  
        size = sizeof(struct e1000_buffer) * txdr->count;
-       txdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
+       txdr->buffer_info = vmalloc(size);
        if (!txdr->buffer_info) {
                DPRINTK(PROBE, ERR,
                "Unable to allocate memory for the transmit descriptor ring\n");
@@@ -1302,11 -1428,11 +1428,11 @@@ e1000_configure_tx(struct e1000_adapte
                tdba = adapter->tx_ring[0].dma;
                tdlen = adapter->tx_ring[0].count *
                        sizeof(struct e1000_tx_desc);
-               E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
-               E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
                E1000_WRITE_REG(hw, TDLEN, tdlen);
-               E1000_WRITE_REG(hw, TDH, 0);
+               E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
+               E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
                E1000_WRITE_REG(hw, TDT, 0);
+               E1000_WRITE_REG(hw, TDH, 0);
                adapter->tx_ring[0].tdh = E1000_TDH;
                adapter->tx_ring[0].tdt = E1000_TDT;
                break;
@@@ -1418,7 -1544,7 +1544,7 @@@ e1000_setup_rx_resources(struct e1000_a
        int size, desc_len;
  
        size = sizeof(struct e1000_buffer) * rxdr->count;
-       rxdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
+       rxdr->buffer_info = vmalloc(size);
        if (!rxdr->buffer_info) {
                DPRINTK(PROBE, ERR,
                "Unable to allocate memory for the receive descriptor ring\n");
@@@ -1560,9 -1686,6 +1686,6 @@@ e1000_setup_rctl(struct e1000_adapter *
                E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
                (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
  
-       if (adapter->hw.mac_type > e1000_82543)
-               rctl |= E1000_RCTL_SECRC;
        if (adapter->hw.tbi_compatibility_on == 1)
                rctl |= E1000_RCTL_SBP;
        else
                rfctl |= E1000_RFCTL_IPV6_DIS;
                E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
  
-               rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC;
+               rctl |= E1000_RCTL_DTYP_PS;
  
                psrctl |= adapter->rx_ps_bsize0 >>
                        E1000_PSRCTL_BSIZE0_SHIFT;
@@@ -1712,11 -1835,11 +1835,11 @@@ e1000_configure_rx(struct e1000_adapte
        case 1:
        default:
                rdba = adapter->rx_ring[0].dma;
-               E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
-               E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
                E1000_WRITE_REG(hw, RDLEN, rdlen);
-               E1000_WRITE_REG(hw, RDH, 0);
+               E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
+               E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
                E1000_WRITE_REG(hw, RDT, 0);
+               E1000_WRITE_REG(hw, RDH, 0);
                adapter->rx_ring[0].rdh = E1000_RDH;
                adapter->rx_ring[0].rdt = E1000_RDT;
                break;
                E1000_WRITE_REG(hw, RXCSUM, rxcsum);
        }
  
-       if (hw->mac_type == e1000_82573)
-               E1000_WRITE_REG(hw, ERT, 0x0100);
        /* Enable Receives */
        E1000_WRITE_REG(hw, RCTL, rctl);
  }
@@@ -2083,6 -2203,12 +2203,12 @@@ e1000_set_multi(struct net_device *netd
        uint32_t rctl;
        uint32_t hash_value;
        int i, rar_entries = E1000_RAR_ENTRIES;
+       int mta_reg_count = (hw->mac_type == e1000_ich8lan) ?
+                               E1000_NUM_MTA_REGISTERS_ICH8LAN :
+                               E1000_NUM_MTA_REGISTERS;
+       if (adapter->hw.mac_type == e1000_ich8lan)
+               rar_entries = E1000_RAR_ENTRIES_ICH8LAN;
  
        /* reserve RAR[14] for LAA over-write work-around */
        if (adapter->hw.mac_type == e1000_82571)
                        mc_ptr = mc_ptr->next;
                } else {
                        E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
+                       E1000_WRITE_FLUSH(hw);
                        E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
+                       E1000_WRITE_FLUSH(hw);
                }
        }
  
        /* clear the old settings from the multicast hash table */
  
-       for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
+       for (i = 0; i < mta_reg_count; i++) {
                E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
+               E1000_WRITE_FLUSH(hw);
+       }
  
        /* load any remaining addresses into the hash table */
  
@@@ -2201,19 -2331,19 +2331,19 @@@ static voi
  e1000_watchdog(unsigned long data)
  {
        struct e1000_adapter *adapter = (struct e1000_adapter *) data;
-       /* Do the rest outside of interrupt context */
-       schedule_work(&adapter->watchdog_task);
- }
- static void
- e1000_watchdog_task(struct e1000_adapter *adapter)
- {
        struct net_device *netdev = adapter->netdev;
        struct e1000_tx_ring *txdr = adapter->tx_ring;
        uint32_t link, tctl;
-       e1000_check_for_link(&adapter->hw);
+       int32_t ret_val;
+       ret_val = e1000_check_for_link(&adapter->hw);
+       if ((ret_val == E1000_ERR_PHY) &&
+           (adapter->hw.phy_type == e1000_phy_igp_3) &&
+           (E1000_READ_REG(&adapter->hw, CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
+               /* See e1000_kumeran_lock_loss_workaround() */
+               DPRINTK(LINK, INFO,
+                       "Gigabit has been disabled, downgrading speed\n");
+       }
        if (adapter->hw.mac_type == e1000_82573) {
                e1000_enable_tx_pkt_filtering(&adapter->hw);
                if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
@@@ -2394,7 -2524,7 +2524,7 @@@ e1000_tso(struct e1000_adapter *adapter
        uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
        int err;
  
 -      if (skb_shinfo(skb)->tso_size) {
 +      if (skb_shinfo(skb)->gso_size) {
                if (skb_header_cloned(skb)) {
                        err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
                        if (err)
                }
  
                hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
 -              mss = skb_shinfo(skb)->tso_size;
 +              mss = skb_shinfo(skb)->gso_size;
                if (skb->protocol == htons(ETH_P_IP)) {
                        skb->nh.iph->tot_len = 0;
                        skb->nh.iph->check = 0;
@@@ -2519,7 -2649,7 +2649,7 @@@ e1000_tx_map(struct e1000_adapter *adap
                 * tso gets written back prematurely before the data is fully
                 * DMA'd to the controller */
                if (!skb->data_len && tx_ring->last_tx_tso &&
 -                  !skb_shinfo(skb)->tso_size) {
 +                  !skb_shinfo(skb)->gso_size) {
                        tx_ring->last_tx_tso = 0;
                        size -= 4;
                }
@@@ -2757,7 -2887,7 +2887,7 @@@ e1000_xmit_frame(struct sk_buff *skb, s
        }
  
  #ifdef NETIF_F_TSO
 -      mss = skb_shinfo(skb)->tso_size;
 +      mss = skb_shinfo(skb)->gso_size;
        /* The controller does a simple calculation to
         * make sure there is enough room in the FIFO before
         * initiating the DMA for each buffer.  The calc is:
                        case e1000_82571:
                        case e1000_82572:
                        case e1000_82573:
+                       case e1000_ich8lan:
                                pull_size = min((unsigned int)4, skb->data_len);
                                if (!__pskb_pull_tail(skb, pull_size)) {
-                                       printk(KERN_ERR
+                                       DPRINTK(DRV, ERR,
                                                "__pskb_pull_tail failed.\n");
                                        dev_kfree_skb_any(skb);
                                        return NETDEV_TX_OK;
  #ifdef NETIF_F_TSO
        /* Controller Erratum workaround */
        if (!skb->data_len && tx_ring->last_tx_tso &&
 -          !skb_shinfo(skb)->tso_size)
 +          !skb_shinfo(skb)->gso_size)
                count++;
  #endif
  
@@@ -2919,8 -3050,7 +3050,7 @@@ e1000_reset_task(struct net_device *net
  {
        struct e1000_adapter *adapter = netdev_priv(netdev);
  
-       e1000_down(adapter);
-       e1000_up(adapter);
+       e1000_reinit_locked(adapter);
  }
  
  /**
@@@ -2964,6 -3094,7 +3094,7 @@@ e1000_change_mtu(struct net_device *net
        /* Adapter-specific max frame size limits. */
        switch (adapter->hw.mac_type) {
        case e1000_undefined ... e1000_82542_rev2_1:
+       case e1000_ich8lan:
                if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
                        DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
                        return -EINVAL;
  
        netdev->mtu = new_mtu;
  
-       if (netif_running(netdev)) {
-               e1000_down(adapter);
-               e1000_up(adapter);
-       }
+       if (netif_running(netdev))
+               e1000_reinit_locked(adapter);
  
        adapter->hw.max_frame_size = max_frame;
  
@@@ -3074,12 -3203,15 +3203,15 @@@ e1000_update_stats(struct e1000_adapte
        adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
        adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
        adapter->stats.roc += E1000_READ_REG(hw, ROC);
+       if (adapter->hw.mac_type != e1000_ich8lan) {
        adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
        adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
        adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
        adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
        adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
        adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
+       }
  
        adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
        adapter->stats.mpc += E1000_READ_REG(hw, MPC);
        adapter->stats.totl += E1000_READ_REG(hw, TOTL);
        adapter->stats.toth += E1000_READ_REG(hw, TOTH);
        adapter->stats.tpr += E1000_READ_REG(hw, TPR);
+       if (adapter->hw.mac_type != e1000_ich8lan) {
        adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
        adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
        adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
        adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
        adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
        adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
+       }
        adapter->stats.mptc += E1000_READ_REG(hw, MPTC);
        adapter->stats.bptc += E1000_READ_REG(hw, BPTC);
  
        if (hw->mac_type > e1000_82547_rev_2) {
                adapter->stats.iac += E1000_READ_REG(hw, IAC);
                adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
+               if (adapter->hw.mac_type != e1000_ich8lan) {
                adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
                adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
                adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
                adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
                adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
                adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
+               }
        }
  
        /* Fill out the OS statistics structure */
@@@ -3547,7 -3686,8 +3686,8 @@@ e1000_clean_rx_irq(struct e1000_adapte
                        /* All receives must fit into a single buffer */
                        E1000_DBG("%s: Receive packet consumed multiple"
                                  " buffers\n", netdev->name);
-                       dev_kfree_skb_irq(skb);
+                       /* recycle */
+                       buffer_info-> skb = skb;
                        goto next_desc;
                }
  
@@@ -3675,7 -3815,6 +3815,6 @@@ e1000_clean_rx_irq_ps(struct e1000_adap
        buffer_info = &rx_ring->buffer_info[i];
  
        while (staterr & E1000_RXD_STAT_DD) {
-               buffer_info = &rx_ring->buffer_info[i];
                ps_page = &rx_ring->ps_page[i];
                ps_page_dma = &rx_ring->ps_page_dma[i];
  #ifdef CONFIG_E1000_NAPI
@@@ -4180,10 -4319,9 +4319,9 @@@ e1000_mii_ioctl(struct net_device *netd
                                                return retval;
                                        }
                                }
-                               if (netif_running(adapter->netdev)) {
-                                       e1000_down(adapter);
-                                       e1000_up(adapter);
-                               } else
+                               if (netif_running(adapter->netdev))
+                                       e1000_reinit_locked(adapter);
+                               else
                                        e1000_reset(adapter);
                                break;
                        case M88E1000_PHY_SPEC_CTRL:
                        case PHY_CTRL:
                                if (mii_reg & MII_CR_POWER_DOWN)
                                        break;
-                               if (netif_running(adapter->netdev)) {
-                                       e1000_down(adapter);
-                                       e1000_up(adapter);
-                               } else
+                               if (netif_running(adapter->netdev))
+                                       e1000_reinit_locked(adapter);
+                               else
                                        e1000_reset(adapter);
                                break;
                        }
@@@ -4277,18 -4414,21 +4414,21 @@@ e1000_vlan_rx_register(struct net_devic
                ctrl |= E1000_CTRL_VME;
                E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
  
+               if (adapter->hw.mac_type != e1000_ich8lan) {
                /* enable VLAN receive filtering */
                rctl = E1000_READ_REG(&adapter->hw, RCTL);
                rctl |= E1000_RCTL_VFE;
                rctl &= ~E1000_RCTL_CFIEN;
                E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
                e1000_update_mng_vlan(adapter);
+               }
        } else {
                /* disable VLAN tag insert/strip */
                ctrl = E1000_READ_REG(&adapter->hw, CTRL);
                ctrl &= ~E1000_CTRL_VME;
                E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
  
+               if (adapter->hw.mac_type != e1000_ich8lan) {
                /* disable VLAN filtering */
                rctl = E1000_READ_REG(&adapter->hw, RCTL);
                rctl &= ~E1000_RCTL_VFE;
                        e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
                        adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
                }
+               }
        }
  
        e1000_irq_enable(adapter);
@@@ -4458,12 -4599,16 +4599,16 @@@ e1000_suspend(struct pci_dev *pdev, pm_
        struct e1000_adapter *adapter = netdev_priv(netdev);
        uint32_t ctrl, ctrl_ext, rctl, manc, status;
        uint32_t wufc = adapter->wol;
+ #ifdef CONFIG_PM
        int retval = 0;
+ #endif
  
        netif_device_detach(netdev);
  
-       if (netif_running(netdev))
+       if (netif_running(netdev)) {
+               WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
                e1000_down(adapter);
+       }
  
  #ifdef CONFIG_PM
        /* Implement our own version of pci_save_state(pdev) because pci-
                pci_enable_wake(pdev, PCI_D3cold, 0);
        }
  
+       /* FIXME: this code is incorrect for PCI Express */
        if (adapter->hw.mac_type >= e1000_82540 &&
+          adapter->hw.mac_type != e1000_ich8lan &&
           adapter->hw.media_type == e1000_media_type_copper) {
                manc = E1000_READ_REG(&adapter->hw, MANC);
                if (manc & E1000_MANC_SMBUS_EN) {
                }
        }
  
+       if (adapter->hw.phy_type == e1000_phy_igp_3)
+               e1000_phy_powerdown_workaround(&adapter->hw);
        /* Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant. */
        e1000_release_hw_control(adapter);
@@@ -4567,7 -4717,9 +4717,9 @@@ e1000_resume(struct pci_dev *pdev
  
        netif_device_attach(netdev);
  
+       /* FIXME: this code is incorrect for PCI Express */
        if (adapter->hw.mac_type >= e1000_82540 &&
+          adapter->hw.mac_type != e1000_ich8lan &&
           adapter->hw.media_type == e1000_media_type_copper) {
                manc = E1000_READ_REG(&adapter->hw, MANC);
                manc &= ~(E1000_MANC_ARP_EN);