return 0;
 }
 
-#define NVRAM_CMD_TIMEOUT 10000
+#define NVRAM_CMD_TIMEOUT 100
 
 static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd)
 {
 static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
 {
        struct tg3 *tp = netdev_priv(dev);
-       int ret;
+       int ret, cpmu_restore = 0;
        u8  *pd;
-       u32 i, offset, len, b_offset, b_count;
+       u32 i, offset, len, b_offset, b_count, cpmu_val = 0;
        __be32 val;
 
        if (tg3_flag(tp, NO_NVRAM))
 
        eeprom->magic = TG3_EEPROM_MAGIC;
 
+       /* Override clock, link aware and link idle modes */
+       if (tg3_flag(tp, CPMU_PRESENT)) {
+               cpmu_val = tr32(TG3_CPMU_CTRL);
+               if (cpmu_val & (CPMU_CTRL_LINK_AWARE_MODE |
+                               CPMU_CTRL_LINK_IDLE_MODE)) {
+                       tw32(TG3_CPMU_CTRL, cpmu_val &
+                                           ~(CPMU_CTRL_LINK_AWARE_MODE |
+                                            CPMU_CTRL_LINK_IDLE_MODE));
+                       cpmu_restore = 1;
+               }
+       }
+       tg3_override_clk(tp);
+
        if (offset & 3) {
                /* adjustments to start on required 4 byte boundary */
                b_offset = offset & 3;
                }
                ret = tg3_nvram_read_be32(tp, offset-b_offset, &val);
                if (ret)
-                       return ret;
+                       goto eeprom_done;
                memcpy(data, ((char *)&val) + b_offset, b_count);
                len -= b_count;
                offset += b_count;
        for (i = 0; i < (len - (len & 3)); i += 4) {
                ret = tg3_nvram_read_be32(tp, offset + i, &val);
                if (ret) {
+                       if (i)
+                               i -= 4;
                        eeprom->len += i;
-                       return ret;
+                       goto eeprom_done;
                }
                memcpy(pd + i, &val, 4);
+               if (need_resched()) {
+                       if (signal_pending(current)) {
+                               eeprom->len += i;
+                               ret = -EINTR;
+                               goto eeprom_done;
+                       }
+                       cond_resched();
+               }
        }
        eeprom->len += i;
 
                b_offset = offset + len - b_count;
                ret = tg3_nvram_read_be32(tp, b_offset, &val);
                if (ret)
-                       return ret;
+                       goto eeprom_done;
                memcpy(pd, &val, b_count);
                eeprom->len += b_count;
        }
-       return 0;
+       ret = 0;
+
+eeprom_done:
+       /* Restore clock, link aware and link idle modes */
+       tg3_restore_clk(tp);
+       if (cpmu_restore)
+               tw32(TG3_CPMU_CTRL, cpmu_val);
+
+       return ret;
 }
 
 static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)