]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/tg3.c
Merge branch 'x86/urgent' into x86/cleanups
[linux-2.6-omap-h63xx.git] / drivers / net / tg3.c
index 26aa37aa531f9d851716074f64cf0976e9f3f590..71d2c5cfdad9b9a2c2f98163446abecfdbb6e447 100644 (file)
@@ -66,8 +66,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.93"
-#define DRV_MODULE_RELDATE     "May 22, 2008"
+#define DRV_MODULE_VERSION     "3.94"
+#define DRV_MODULE_RELDATE     "August 14, 2008"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -536,6 +536,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
                return 0;
 
        switch (locknum) {
+               case TG3_APE_LOCK_GRC:
                case TG3_APE_LOCK_MEM:
                        break;
                default:
@@ -573,6 +574,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
                return;
 
        switch (locknum) {
+               case TG3_APE_LOCK_GRC:
                case TG3_APE_LOCK_MEM:
                        break;
                default:
@@ -1017,16 +1019,44 @@ static void tg3_mdio_fini(struct tg3 *tp)
        }
 }
 
+/* tp->lock is held. */
+static inline void tg3_generate_fw_event(struct tg3 *tp)
+{
+       u32 val;
+
+       val = tr32(GRC_RX_CPU_EVENT);
+       val |= GRC_RX_CPU_DRIVER_EVENT;
+       tw32_f(GRC_RX_CPU_EVENT, val);
+
+       tp->last_event_jiffies = jiffies;
+}
+
+#define TG3_FW_EVENT_TIMEOUT_USEC 2500
+
 /* tp->lock is held. */
 static void tg3_wait_for_event_ack(struct tg3 *tp)
 {
        int i;
+       unsigned int delay_cnt;
+       long time_remain;
+
+       /* If enough time has passed, no wait is necessary. */
+       time_remain = (long)(tp->last_event_jiffies + 1 +
+                     usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) -
+                     (long)jiffies;
+       if (time_remain < 0)
+               return;
+
+       /* Check if we can shorten the wait time. */
+       delay_cnt = jiffies_to_usecs(time_remain);
+       if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC)
+               delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC;
+       delay_cnt = (delay_cnt >> 3) + 1;
 
-       /* Wait for up to 2.5 milliseconds */
-       for (i = 0; i < 250000; i++) {
+       for (i = 0; i < delay_cnt; i++) {
                if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
                        break;
-               udelay(10);
+               udelay(8);
        }
 }
 
@@ -1075,9 +1105,7 @@ static void tg3_ump_link_report(struct tg3 *tp)
                val = 0;
        tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
 
-       val = tr32(GRC_RX_CPU_EVENT);
-       val |= GRC_RX_CPU_DRIVER_EVENT;
-       tw32_f(GRC_RX_CPU_EVENT, val);
+       tg3_generate_fw_event(tp);
 }
 
 static void tg3_link_report(struct tg3 *tp)
@@ -2124,6 +2152,13 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE))
                        mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
 
+               if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+                       mac_mode |= tp->mac_mode &
+                                   (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
+                       if (mac_mode & MAC_MODE_APE_TX_EN)
+                               mac_mode |= MAC_MODE_TDE_ENABLE;
+               }
+
                tw32_f(MAC_MODE, mac_mode);
                udelay(100);
 
@@ -5493,7 +5528,7 @@ static void tg3_ape_send_event(struct tg3 *tp, u32 event)
                return;
 
        apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
-       if (apedata != APE_FW_STATUS_READY)
+       if (!(apedata & APE_FW_STATUS_READY))
                return;
 
        /* Wait for up to 1 millisecond for APE to service previous event. */
@@ -5760,6 +5795,8 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        tg3_mdio_stop(tp);
 
+       tg3_ape_lock(tp, TG3_APE_LOCK_GRC);
+
        /* No matching tg3_nvram_unlock() after this because
         * chip reset below will undo the nvram lock.
         */
@@ -5908,12 +5945,19 @@ static int tg3_chip_reset(struct tg3 *tp)
        } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
                tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
                tw32_f(MAC_MODE, tp->mac_mode);
+       } else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+               tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
+               if (tp->mac_mode & MAC_MODE_APE_TX_EN)
+                       tp->mac_mode |= MAC_MODE_TDE_ENABLE;
+               tw32_f(MAC_MODE, tp->mac_mode);
        } else
                tw32_f(MAC_MODE, 0);
        udelay(40);
 
        tg3_mdio_start(tp);
 
+       tg3_ape_unlock(tp, TG3_APE_LOCK_GRC);
+
        err = tg3_poll_fw(tp);
        if (err)
                return err;
@@ -5935,6 +5979,7 @@ static int tg3_chip_reset(struct tg3 *tp)
                tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
                if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
                        tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
+                       tp->last_event_jiffies = jiffies;
                        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
                                tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
                }
@@ -5948,15 +5993,12 @@ static void tg3_stop_fw(struct tg3 *tp)
 {
        if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
           !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
-               u32 val;
-
                /* Wait for RX cpu to ACK the previous event. */
                tg3_wait_for_event_ack(tp);
 
                tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
-               val = tr32(GRC_RX_CPU_EVENT);
-               val |= GRC_RX_CPU_DRIVER_EVENT;
-               tw32(GRC_RX_CPU_EVENT, val);
+
+               tg3_generate_fw_event(tp);
 
                /* Wait for RX cpu to ACK this event. */
                tg3_wait_for_event_ack(tp);
@@ -7406,7 +7448,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                udelay(10);
        }
 
-       tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+               tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+       else
+               tp->mac_mode = 0;
+       tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
                MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
            !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
@@ -7687,21 +7733,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
  */
 static int tg3_init_hw(struct tg3 *tp, int reset_phy)
 {
-       int err;
-
-       /* Force the chip into D0. */
-       err = tg3_set_power_state(tp, PCI_D0);
-       if (err)
-               goto out;
-
        tg3_switch_clocks(tp);
 
        tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 
-       err = tg3_reset_hw(tp, reset_phy);
-
-out:
-       return err;
+       return tg3_reset_hw(tp, reset_phy);
 }
 
 #define TG3_STAT_ADD32(PSTAT, REG) \
@@ -7850,9 +7886,8 @@ static void tg3_timer(unsigned long __opaque)
         * resets.
         */
        if (!--tp->asf_counter) {
-               if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
-                       u32 val;
-
+               if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
+                   !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
                        tg3_wait_for_event_ack(tp);
 
                        tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
@@ -7860,9 +7895,8 @@ static void tg3_timer(unsigned long __opaque)
                        tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
                        /* 5 seconds timeout */
                        tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
-                       val = tr32(GRC_RX_CPU_EVENT);
-                       val |= GRC_RX_CPU_DRIVER_EVENT;
-                       tw32_f(GRC_RX_CPU_EVENT, val);
+
+                       tg3_generate_fw_event(tp);
                }
                tp->asf_counter = tp->asf_multiplier;
        }
@@ -8016,13 +8050,11 @@ static int tg3_open(struct net_device *dev)
 
        netif_carrier_off(tp->dev);
 
-       tg3_full_lock(tp, 0);
-
        err = tg3_set_power_state(tp, PCI_D0);
-       if (err) {
-               tg3_full_unlock(tp);
+       if (err)
                return err;
-       }
+
+       tg3_full_lock(tp, 0);
 
        tg3_disable_ints(tp);
        tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
@@ -8434,6 +8466,11 @@ static inline unsigned long get_stat64(tg3_stat64_t *val)
        return ret;
 }
 
+static inline u64 get_estat64(tg3_stat64_t *val)
+{
+       return ((u64)val->high << 32) | ((u64)val->low);
+}
+
 static unsigned long calc_crc_errors(struct tg3 *tp)
 {
        struct tg3_hw_stats *hw_stats = tp->hw_stats;
@@ -8462,7 +8499,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
 
 #define ESTAT_ADD(member) \
        estats->member =        old_estats->member + \
-                               get_stat64(&hw_stats->member)
+                               get_estat64(&hw_stats->member)
 
 static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
 {
@@ -12428,6 +12465,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                                       tp->misc_host_ctrl);
        }
 
+       /* Preserve the APE MAC_MODE bits */
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+               tp->mac_mode = tr32(MAC_MODE) |
+                              MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+       else
+               tp->mac_mode = TG3_DEF_MAC_MODE;
+
        /* these are limited to 10/100 only */
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
             (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
@@ -13287,7 +13331,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        tp->pdev = pdev;
        tp->dev = dev;
        tp->pm_cap = pm_cap;
-       tp->mac_mode = TG3_DEF_MAC_MODE;
        tp->rx_mode = TG3_DEF_RX_MODE;
        tp->tx_mode = TG3_DEF_TX_MODE;