diff options
Diffstat (limited to 'openvz-sources/022.050/5108_linux-2.6.8.1-tg3-3.27.rh.patch')
-rw-r--r-- | openvz-sources/022.050/5108_linux-2.6.8.1-tg3-3.27.rh.patch | 4631 |
1 files changed, 4631 insertions, 0 deletions
diff --git a/openvz-sources/022.050/5108_linux-2.6.8.1-tg3-3.27.rh.patch b/openvz-sources/022.050/5108_linux-2.6.8.1-tg3-3.27.rh.patch new file mode 100644 index 0000000..d5146ab --- /dev/null +++ b/openvz-sources/022.050/5108_linux-2.6.8.1-tg3-3.27.rh.patch @@ -0,0 +1,4631 @@ +--- linux-2.6.8.1-t043-libata-update//drivers/net/tg3.c 2005-10-20 17:56:53.000000000 +0400 ++++ rhel4u2//drivers/net/tg3.c 2005-10-19 11:47:13.000000000 +0400 +@@ -4,12 +4,16 @@ + * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) + * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) + * Copyright (C) 2004 Sun Microsystems Inc. ++ * Copyright (C) 2005 Broadcom Corporation. ++ * ++ * Firmware is: ++ * Copyright (C) 2000-2003 Broadcom Corporation. + */ + + #include <linux/config.h> + + #include <linux/module.h> +- ++#include <linux/moduleparam.h> + #include <linux/kernel.h> + #include <linux/types.h> + #include <linux/compiler.h> +@@ -53,12 +57,13 @@ + #define TG3_TSO_SUPPORT 0 + #endif + ++#include "tg3_compat.h" + #include "tg3.h" + + #define DRV_MODULE_NAME "tg3" + #define PFX DRV_MODULE_NAME ": " +-#define DRV_MODULE_VERSION "3.8" +-#define DRV_MODULE_RELDATE "July 14, 2004" ++#define DRV_MODULE_VERSION "3.27-rh" ++#define DRV_MODULE_RELDATE "May 5, 2005" + + #define TG3_DEF_MAC_MODE 0 + #define TG3_DEF_RX_MODE 0 +@@ -81,8 +86,7 @@ + /* hardware minimum and maximum for a single frame's data payload */ + #define TG3_MIN_MTU 60 + #define TG3_MAX_MTU(tp) \ +- ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && \ +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) ? 9000 : 1500) ++ (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ? 9000 : 1500) + + /* These numbers seem to be hard coded in the NIC firmware somehow. + * You can't change the ring sizes, but you can change where you place +@@ -100,9 +104,7 @@ + * replace things like '% foo' with '& (foo - 1)'. + */ + #define TG3_RX_RCB_RING_SIZE(tp) \ +- ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || \ +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ? \ +- 512 : 1024) ++ ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ? 512 : 1024) + + #define TG3_TX_RING_SIZE 512 + #define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1) +@@ -138,10 +140,11 @@ static char version[] __devinitdata = + MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)"); + MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); + MODULE_LICENSE("GPL"); +-MODULE_PARM(tg3_debug, "i"); +-MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); ++MODULE_VERSION(DRV_MODULE_VERSION); + + static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ ++module_param(tg3_debug, int, 0); ++MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); + + static struct pci_device_id tg3_pci_tbl[] = { + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700, +@@ -202,6 +205,16 @@ static struct pci_device_id tg3_pci_tbl[ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, ++ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, ++ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, ++ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, ++ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, ++ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, +@@ -221,8 +234,8 @@ static struct pci_device_id tg3_pci_tbl[ + + MODULE_DEVICE_TABLE(pci, tg3_pci_tbl); + +-struct { +- char string[ETH_GSTRING_LEN]; ++static struct { ++ const char string[ETH_GSTRING_LEN]; + } ethtool_stats_keys[TG3_NUM_STATS] = { + { "rx_octets" }, + { "rx_fragments" }, +@@ -328,7 +341,7 @@ static void _tw32_flush(struct tg3 *tp, + pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); + spin_unlock_irqrestore(&tp->indirect_lock, flags); + } else { +- unsigned long dest = tp->regs + off; ++ void __iomem *dest = tp->regs + off; + writel(val, dest); + readl(dest); /* always flush PCI write */ + } +@@ -336,7 +349,7 @@ static void _tw32_flush(struct tg3 *tp, + + static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val) + { +- unsigned long mbox = tp->regs + off; ++ void __iomem *mbox = tp->regs + off; + writel(val, mbox); + if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) + readl(mbox); +@@ -344,7 +357,7 @@ static inline void _tw32_rx_mbox(struct + + static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val) + { +- unsigned long mbox = tp->regs + off; ++ void __iomem *mbox = tp->regs + off; + writel(val, mbox); + if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) + writel(val, mbox); +@@ -414,6 +427,43 @@ static void tg3_enable_ints(struct tg3 * + tg3_cond_int(tp); + } + ++static inline unsigned int tg3_has_work(struct tg3 *tp) ++{ ++ struct tg3_hw_status *sblk = tp->hw_status; ++ unsigned int work_exists = 0; ++ ++ /* check for phy events */ ++ if (!(tp->tg3_flags & ++ (TG3_FLAG_USE_LINKCHG_REG | ++ TG3_FLAG_POLL_SERDES))) { ++ if (sblk->status & SD_STATUS_LINK_CHG) ++ work_exists = 1; ++ } ++ /* check for RX/TX work to do */ ++ if (sblk->idx[0].tx_consumer != tp->tx_cons || ++ sblk->idx[0].rx_producer != tp->rx_rcb_ptr) ++ work_exists = 1; ++ ++ return work_exists; ++} ++ ++/* tg3_restart_ints ++ * similar to tg3_enable_ints, but it accurately determines whether there ++ * is new work pending and can return without flushing the PIO write ++ * which reenables interrupts ++ */ ++static void tg3_restart_ints(struct tg3 *tp) ++{ ++ tw32(TG3PCI_MISC_HOST_CTRL, ++ (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); ++ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000); ++ mmiowb(); ++ ++ if (tg3_has_work(tp)) ++ tw32(HOSTCC_MODE, tp->coalesce_mode | ++ (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); ++} ++ + static inline void tg3_netif_stop(struct tg3 *tp) + { + netif_poll_disable(tp->dev); +@@ -442,9 +492,13 @@ static void tg3_switch_clocks(struct tg3 + 0x1f); + tp->pci_clock_ctrl = clock_ctrl; + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && +- (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { ++ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { ++ if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) { ++ tw32_f(TG3PCI_CLOCK_CTRL, ++ clock_ctrl | CLOCK_CTRL_625_CORE); ++ udelay(40); ++ } ++ } else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { + tw32_f(TG3PCI_CLOCK_CTRL, + clock_ctrl | + (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK)); +@@ -462,7 +516,8 @@ static void tg3_switch_clocks(struct tg3 + static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) + { + u32 frame_val; +- int loops, ret; ++ unsigned int loops; ++ int ret; + + if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { + tw32_f(MAC_MI_MODE, +@@ -470,7 +525,7 @@ static int tg3_readphy(struct tg3 *tp, i + udelay(80); + } + +- *val = 0xffffffff; ++ *val = 0x0; + + frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & + MI_COM_PHY_ADDR_MASK); +@@ -481,7 +536,7 @@ static int tg3_readphy(struct tg3 *tp, i + tw32_f(MAC_MI_COM, frame_val); + + loops = PHY_BUSY_LOOPS; +- while (loops-- > 0) { ++ while (loops != 0) { + udelay(10); + frame_val = tr32(MAC_MI_COM); + +@@ -490,10 +545,11 @@ static int tg3_readphy(struct tg3 *tp, i + frame_val = tr32(MAC_MI_COM); + break; + } ++ loops -= 1; + } + + ret = -EBUSY; +- if (loops > 0) { ++ if (loops != 0) { + *val = frame_val & MI_COM_DATA_MASK; + ret = 0; + } +@@ -509,7 +565,8 @@ static int tg3_readphy(struct tg3 *tp, i + static int tg3_writephy(struct tg3 *tp, int reg, u32 val) + { + u32 frame_val; +- int loops, ret; ++ unsigned int loops; ++ int ret; + + if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { + tw32_f(MAC_MI_MODE, +@@ -527,7 +584,7 @@ static int tg3_writephy(struct tg3 *tp, + tw32_f(MAC_MI_COM, frame_val); + + loops = PHY_BUSY_LOOPS; +- while (loops-- > 0) { ++ while (loops != 0) { + udelay(10); + frame_val = tr32(MAC_MI_COM); + if ((frame_val & MI_COM_BUSY) == 0) { +@@ -535,10 +592,11 @@ static int tg3_writephy(struct tg3 *tp, + frame_val = tr32(MAC_MI_COM); + break; + } ++ loops -= 1; + } + + ret = -EBUSY; +- if (loops > 0) ++ if (loops != 0) + ret = 0; + + if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { +@@ -556,9 +614,10 @@ static void tg3_phy_set_wirespeed(struct + if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) + return; + +- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007); +- tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); +- tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); ++ if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007) && ++ !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val)) ++ tg3_writephy(tp, MII_TG3_AUX_CTRL, ++ (val | (1 << 15) | (1 << 4))); + } + + static int tg3_bmcr_reset(struct tg3 *tp) +@@ -599,9 +658,10 @@ static int tg3_wait_macro_done(struct tg + while (limit--) { + u32 tmp32; + +- tg3_readphy(tp, 0x16, &tmp32); +- if ((tmp32 & 0x1000) == 0) +- break; ++ if (!tg3_readphy(tp, 0x16, &tmp32)) { ++ if ((tmp32 & 0x1000) == 0) ++ break; ++ } + } + if (limit <= 0) + return -EBUSY; +@@ -653,9 +713,9 @@ static int tg3_phy_write_and_check_testp + for (i = 0; i < 6; i += 2) { + u32 low, high; + +- tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low); +- tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high); +- if (tg3_wait_macro_done(tp)) { ++ if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) || ++ tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) || ++ tg3_wait_macro_done(tp)) { + *resetp = 1; + return -EBUSY; + } +@@ -711,7 +771,9 @@ static int tg3_phy_reset_5703_4_5(struct + } + + /* Disable transmitter and interrupt. */ +- tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); ++ if (tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) ++ continue; ++ + reg32 |= 0x3000; + tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); + +@@ -720,7 +782,9 @@ static int tg3_phy_reset_5703_4_5(struct + BMCR_FULLDPLX | TG3_BMCR_SPEED1000); + + /* Set to master mode. */ +- tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig); ++ if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig)) ++ continue; ++ + tg3_writephy(tp, MII_TG3_CTRL, + (MII_TG3_CTRL_AS_MASTER | + MII_TG3_CTRL_ENABLE_AS_MASTER)); +@@ -758,9 +822,11 @@ static int tg3_phy_reset_5703_4_5(struct + + tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); + +- tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); +- reg32 &= ~0x3000; +- tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); ++ if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) { ++ reg32 &= ~0x3000; ++ tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); ++ } else if (!err) ++ err = -EBUSY; + + return err; + } +@@ -819,15 +885,26 @@ out: + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { + /* Cannot do read-modify-write on 5401 */ + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20); +- } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) { ++ } else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + u32 phy_reg; + + /* Set bit 14 with read-modify-write to preserve other bits */ +- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007); +- tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg); +- tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000); ++ if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007) && ++ !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg)) ++ tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000); ++ } ++ ++ /* Set phy register 0x10 bit 0 to high fifo elasticity to support ++ * jumbo frames transmission. ++ */ ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { ++ u32 phy_reg; ++ ++ if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &phy_reg)) ++ tg3_writephy(tp, MII_TG3_EXT_CTRL, ++ phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC); + } ++ + tg3_phy_set_wirespeed(tp); + return 0; + } +@@ -858,34 +935,42 @@ static void tg3_frob_aux_power(struct tg + GRC_LCLCTRL_GPIO_OUTPUT1)); + udelay(100); + } else { ++ u32 no_gpio2; ++ u32 grc_local_ctrl; ++ + if (tp_peer != tp && + (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) + return; + ++ /* On 5753 and variants, GPIO2 cannot be used. */ ++ no_gpio2 = tp->nic_sram_data_cfg & ++ NIC_SRAM_DATA_CFG_NO_GPIO2; ++ ++ grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | ++ GRC_LCLCTRL_GPIO_OE1 | ++ GRC_LCLCTRL_GPIO_OE2 | ++ GRC_LCLCTRL_GPIO_OUTPUT1 | ++ GRC_LCLCTRL_GPIO_OUTPUT2; ++ if (no_gpio2) { ++ grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | ++ GRC_LCLCTRL_GPIO_OUTPUT2); ++ } + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | +- (GRC_LCLCTRL_GPIO_OE0 | +- GRC_LCLCTRL_GPIO_OE1 | +- GRC_LCLCTRL_GPIO_OE2 | +- GRC_LCLCTRL_GPIO_OUTPUT1 | +- GRC_LCLCTRL_GPIO_OUTPUT2)); ++ grc_local_ctrl); + udelay(100); + +- tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | +- (GRC_LCLCTRL_GPIO_OE0 | +- GRC_LCLCTRL_GPIO_OE1 | +- GRC_LCLCTRL_GPIO_OE2 | +- GRC_LCLCTRL_GPIO_OUTPUT0 | +- GRC_LCLCTRL_GPIO_OUTPUT1 | +- GRC_LCLCTRL_GPIO_OUTPUT2)); +- udelay(100); ++ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0; + + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | +- (GRC_LCLCTRL_GPIO_OE0 | +- GRC_LCLCTRL_GPIO_OE1 | +- GRC_LCLCTRL_GPIO_OE2 | +- GRC_LCLCTRL_GPIO_OUTPUT0 | +- GRC_LCLCTRL_GPIO_OUTPUT1)); ++ grc_local_ctrl); + udelay(100); ++ ++ if (!no_gpio2) { ++ grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2; ++ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | ++ grc_local_ctrl); ++ udelay(100); ++ } + } + } else { + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && +@@ -918,6 +1003,7 @@ static int tg3_setup_phy(struct tg3 *, i + #define RESET_KIND_SUSPEND 2 + + static void tg3_write_sig_post_reset(struct tg3 *, int); ++static int tg3_halt_cpu(struct tg3 *, u32); + + static int tg3_set_power_state(struct tg3 *tp, int state) + { +@@ -943,8 +1029,13 @@ static int tg3_set_power_state(struct tg + pci_write_config_word(tp->pdev, + pm + PCI_PM_CTRL, + power_control); +- tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); +- udelay(100); ++ udelay(100); /* Delay after power state change */ ++ ++ /* Switch out of Vaux if it is not a LOM */ ++ if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)) { ++ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); ++ udelay(100); ++ } + + return 0; + +@@ -980,7 +1071,7 @@ static int tg3_set_power_state(struct tg + tp->link_config.orig_autoneg = tp->link_config.autoneg; + } + +- if (tp->phy_id != PHY_ID_SERDES) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + tp->link_config.speed = SPEED_10; + tp->link_config.duplex = DUPLEX_HALF; + tp->link_config.autoneg = AUTONEG_ENABLE; +@@ -992,7 +1083,7 @@ static int tg3_set_power_state(struct tg + if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) { + u32 mac_mode; + +- if (tp->phy_id != PHY_ID_SERDES) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); + udelay(40); + +@@ -1005,7 +1096,7 @@ static int tg3_set_power_state(struct tg + mac_mode = MAC_MODE_PORT_MODE_TBI; + } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) ++ if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) + tw32(MAC_LED_CTRL, tp->led_ctrl); + + if (((power_caps & PCI_PM_CAP_PME_D3cold) && +@@ -1032,7 +1123,7 @@ static int tg3_set_power_state(struct tg + CLOCK_CTRL_ALTCLK | + CLOCK_CTRL_PWRDOWN_PLL133); + udelay(40); +- } else if (!((GET_ASIC_REV(tp->pci_chip_rev_id) == 5750) && ++ } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && + (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) { + u32 newbits1, newbits2; + +@@ -1042,8 +1133,7 @@ static int tg3_set_power_state(struct tg + CLOCK_CTRL_TXCLK_DISABLE | + CLOCK_CTRL_ALTCLK); + newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; +- } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { ++ } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + newbits1 = CLOCK_CTRL_625_CORE; + newbits2 = newbits1 | CLOCK_CTRL_ALTCLK; + } else { +@@ -1057,8 +1147,7 @@ static int tg3_set_power_state(struct tg + tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2); + udelay(40); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + u32 newbits3; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || +@@ -1078,8 +1167,20 @@ static int tg3_set_power_state(struct tg + + tg3_frob_aux_power(tp); + ++ /* Workaround for unstable PLL clock */ ++ if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) || ++ (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) { ++ u32 val = tr32(0x7d00); ++ ++ val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); ++ tw32(0x7d00, val); ++ if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) ++ tg3_halt_cpu(tp, RX_CPU_BASE); ++ } ++ + /* Finally, set the new power state. */ + pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); ++ udelay(100); /* Delay after power state change */ + + tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); + +@@ -1114,29 +1215,33 @@ static void tg3_setup_flow_control(struc + u32 old_rx_mode = tp->rx_mode; + u32 old_tx_mode = tp->tx_mode; + +- if (local_adv & ADVERTISE_PAUSE_CAP) { +- if (local_adv & ADVERTISE_PAUSE_ASYM) { +- if (remote_adv & LPA_PAUSE_CAP) +- new_tg3_flags |= +- (TG3_FLAG_RX_PAUSE | +- TG3_FLAG_TX_PAUSE); +- else if (remote_adv & LPA_PAUSE_ASYM) +- new_tg3_flags |= +- (TG3_FLAG_RX_PAUSE); +- } else { +- if (remote_adv & LPA_PAUSE_CAP) +- new_tg3_flags |= +- (TG3_FLAG_RX_PAUSE | +- TG3_FLAG_TX_PAUSE); ++ if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { ++ if (local_adv & ADVERTISE_PAUSE_CAP) { ++ if (local_adv & ADVERTISE_PAUSE_ASYM) { ++ if (remote_adv & LPA_PAUSE_CAP) ++ new_tg3_flags |= ++ (TG3_FLAG_RX_PAUSE | ++ TG3_FLAG_TX_PAUSE); ++ else if (remote_adv & LPA_PAUSE_ASYM) ++ new_tg3_flags |= ++ (TG3_FLAG_RX_PAUSE); ++ } else { ++ if (remote_adv & LPA_PAUSE_CAP) ++ new_tg3_flags |= ++ (TG3_FLAG_RX_PAUSE | ++ TG3_FLAG_TX_PAUSE); ++ } ++ } else if (local_adv & ADVERTISE_PAUSE_ASYM) { ++ if ((remote_adv & LPA_PAUSE_CAP) && ++ (remote_adv & LPA_PAUSE_ASYM)) ++ new_tg3_flags |= TG3_FLAG_TX_PAUSE; + } +- } else if (local_adv & ADVERTISE_PAUSE_ASYM) { +- if ((remote_adv & LPA_PAUSE_CAP) && +- (remote_adv & LPA_PAUSE_ASYM)) +- new_tg3_flags |= TG3_FLAG_TX_PAUSE; +- } + +- tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE); +- tp->tg3_flags |= new_tg3_flags; ++ tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE); ++ tp->tg3_flags |= new_tg3_flags; ++ } else { ++ new_tg3_flags = tp->tg3_flags; ++ } + + if (new_tg3_flags & TG3_FLAG_RX_PAUSE) + tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; +@@ -1197,7 +1302,7 @@ static void tg3_aux_stat_to_speed_duplex + }; + } + +-static int tg3_phy_copper_begin(struct tg3 *tp) ++static void tg3_phy_copper_begin(struct tg3 *tp) + { + u32 new_adv; + int i; +@@ -1312,15 +1417,16 @@ static int tg3_phy_copper_begin(struct t + if (tp->link_config.duplex == DUPLEX_FULL) + bmcr |= BMCR_FULLDPLX; + +- tg3_readphy(tp, MII_BMCR, &orig_bmcr); +- if (bmcr != orig_bmcr) { ++ if (!tg3_readphy(tp, MII_BMCR, &orig_bmcr) && ++ (bmcr != orig_bmcr)) { + tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK); + for (i = 0; i < 1500; i++) { + u32 tmp; + + udelay(10); +- tg3_readphy(tp, MII_BMSR, &tmp); +- tg3_readphy(tp, MII_BMSR, &tmp); ++ if (tg3_readphy(tp, MII_BMSR, &tmp) || ++ tg3_readphy(tp, MII_BMSR, &tmp)) ++ continue; + if (!(tmp & BMSR_LSTATUS)) { + udelay(40); + break; +@@ -1333,8 +1439,6 @@ static int tg3_phy_copper_begin(struct t + tg3_writephy(tp, MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART); + } +- +- return 0; + } + + static int tg3_init_5401phy_dsp(struct tg3 *tp) +@@ -1369,7 +1473,9 @@ static int tg3_copper_is_advertising_all + { + u32 adv_reg, all_mask; + +- tg3_readphy(tp, MII_ADVERTISE, &adv_reg); ++ if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg)) ++ return 0; ++ + all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL); + if ((adv_reg & all_mask) != all_mask) +@@ -1377,7 +1483,9 @@ static int tg3_copper_is_advertising_all + if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) { + u32 tg3_ctrl; + +- tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl); ++ if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl)) ++ return 0; ++ + all_mask = (MII_TG3_CTRL_ADV_1000_HALF | + MII_TG3_CTRL_ADV_1000_FULL); + if ((tg3_ctrl & all_mask) != all_mask) +@@ -1417,8 +1525,8 @@ static int tg3_setup_copper_phy(struct t + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && + netif_carrier_ok(tp->dev)) { + tg3_readphy(tp, MII_BMSR, &bmsr); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- if (!(bmsr & BMSR_LSTATUS)) ++ if (!tg3_readphy(tp, MII_BMSR, &bmsr) && ++ !(bmsr & BMSR_LSTATUS)) + force_reset = 1; + } + if (force_reset) +@@ -1426,9 +1534,8 @@ static int tg3_setup_copper_phy(struct t + + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { + tg3_readphy(tp, MII_BMSR, &bmsr); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- +- if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) ++ if (tg3_readphy(tp, MII_BMSR, &bmsr) || ++ !(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) + bmsr = 0; + + if (!(bmsr & BMSR_LSTATUS)) { +@@ -1439,8 +1546,8 @@ static int tg3_setup_copper_phy(struct t + tg3_readphy(tp, MII_BMSR, &bmsr); + for (i = 0; i < 1000; i++) { + udelay(10); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- if (bmsr & BMSR_LSTATUS) { ++ if (!tg3_readphy(tp, MII_BMSR, &bmsr) && ++ (bmsr & BMSR_LSTATUS)) { + udelay(40); + break; + } +@@ -1487,11 +1594,23 @@ static int tg3_setup_copper_phy(struct t + current_speed = SPEED_INVALID; + current_duplex = DUPLEX_INVALID; + ++ if (tp->tg3_flags2 & TG3_FLG2_CAPACITIVE_COUPLING) { ++ u32 val; ++ ++ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007); ++ tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); ++ if (!(val & (1 << 10))) { ++ val |= (1 << 10); ++ tg3_writephy(tp, MII_TG3_AUX_CTRL, val); ++ goto relink; ++ } ++ } ++ + bmsr = 0; + for (i = 0; i < 100; i++) { + tg3_readphy(tp, MII_BMSR, &bmsr); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- if (bmsr & BMSR_LSTATUS) ++ if (!tg3_readphy(tp, MII_BMSR, &bmsr) && ++ (bmsr & BMSR_LSTATUS)) + break; + udelay(40); + } +@@ -1502,8 +1621,8 @@ static int tg3_setup_copper_phy(struct t + tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); + for (i = 0; i < 2000; i++) { + udelay(10); +- tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); +- if (aux_stat) ++ if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) && ++ aux_stat) + break; + } + +@@ -1514,7 +1633,8 @@ static int tg3_setup_copper_phy(struct t + bmcr = 0; + for (i = 0; i < 200; i++) { + tg3_readphy(tp, MII_BMCR, &bmcr); +- tg3_readphy(tp, MII_BMCR, &bmcr); ++ if (tg3_readphy(tp, MII_BMCR, &bmcr)) ++ continue; + if (bmcr && bmcr != 0x7fff) + break; + udelay(10); +@@ -1551,10 +1671,13 @@ static int tg3_setup_copper_phy(struct t + (tp->link_config.autoneg == AUTONEG_ENABLE)) { + u32 local_adv, remote_adv; + +- tg3_readphy(tp, MII_ADVERTISE, &local_adv); ++ if (tg3_readphy(tp, MII_ADVERTISE, &local_adv)) ++ local_adv = 0; + local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + +- tg3_readphy(tp, MII_LPA, &remote_adv); ++ if (tg3_readphy(tp, MII_LPA, &remote_adv)) ++ remote_adv = 0; ++ + remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM); + + /* If we are not advertising full pause capability, +@@ -1566,15 +1689,15 @@ static int tg3_setup_copper_phy(struct t + tg3_setup_flow_control(tp, local_adv, remote_adv); + } + } +- ++relink: + if (current_link_up == 0) { + u32 tmp; + + tg3_phy_copper_begin(tp); + + tg3_readphy(tp, MII_BMSR, &tmp); +- tg3_readphy(tp, MII_BMSR, &tmp); +- if (tmp & BMSR_LSTATUS) ++ if (!tg3_readphy(tp, MII_BMSR, &tmp) && ++ (tmp & BMSR_LSTATUS)) + current_link_up = 1; + } + +@@ -1616,7 +1739,7 @@ static int tg3_setup_copper_phy(struct t + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); + +- if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) { ++ if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { + /* Polled via timer. */ + tw32_f(MAC_EVENT, 0); + } else { +@@ -1965,261 +2088,399 @@ static int tg3_fiber_aneg_smachine(struc + static int fiber_autoneg(struct tg3 *tp, u32 *flags) + { + int res = 0; ++ struct tg3_fiber_aneginfo aninfo; ++ int status = ANEG_FAILED; ++ unsigned int tick; ++ u32 tmp; + +- if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) { +- u32 dig_status; +- +- dig_status = tr32(SG_DIG_STATUS); +- *flags = 0; +- if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE) +- *flags |= MR_LP_ADV_ASYM_PAUSE; +- if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE) +- *flags |= MR_LP_ADV_SYM_PAUSE; +- +- if ((dig_status & SG_DIG_AUTONEG_COMPLETE) && +- !(dig_status & (SG_DIG_AUTONEG_ERROR | +- SG_DIG_PARTNER_FAULT_MASK))) +- res = 1; +- } else { +- struct tg3_fiber_aneginfo aninfo; +- int status = ANEG_FAILED; +- unsigned int tick; +- u32 tmp; +- +- tw32_f(MAC_TX_AUTO_NEG, 0); ++ tw32_f(MAC_TX_AUTO_NEG, 0); + +- tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; +- tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); +- udelay(40); ++ tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; ++ tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); ++ udelay(40); + +- tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); +- udelay(40); ++ tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); ++ udelay(40); + +- memset(&aninfo, 0, sizeof(aninfo)); +- aninfo.flags |= MR_AN_ENABLE; +- aninfo.state = ANEG_STATE_UNKNOWN; +- aninfo.cur_time = 0; +- tick = 0; +- while (++tick < 195000) { +- status = tg3_fiber_aneg_smachine(tp, &aninfo); +- if (status == ANEG_DONE || status == ANEG_FAILED) +- break; ++ memset(&aninfo, 0, sizeof(aninfo)); ++ aninfo.flags |= MR_AN_ENABLE; ++ aninfo.state = ANEG_STATE_UNKNOWN; ++ aninfo.cur_time = 0; ++ tick = 0; ++ while (++tick < 195000) { ++ status = tg3_fiber_aneg_smachine(tp, &aninfo); ++ if (status == ANEG_DONE || status == ANEG_FAILED) ++ break; + +- udelay(1); +- } ++ udelay(1); ++ } + +- tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; +- tw32_f(MAC_MODE, tp->mac_mode); +- udelay(40); ++ tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; ++ tw32_f(MAC_MODE, tp->mac_mode); ++ udelay(40); + +- *flags = aninfo.flags; ++ *flags = aninfo.flags; + +- if (status == ANEG_DONE && +- (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | +- MR_LP_ADV_FULL_DUPLEX))) +- res = 1; +- } ++ if (status == ANEG_DONE && ++ (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | ++ MR_LP_ADV_FULL_DUPLEX))) ++ res = 1; + + return res; + } + +-static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) ++static void tg3_init_bcm8002(struct tg3 *tp) + { +- u32 orig_pause_cfg; +- u16 orig_active_speed; +- u8 orig_active_duplex; +- int current_link_up; ++ u32 mac_status = tr32(MAC_STATUS); + int i; + +- orig_pause_cfg = +- (tp->tg3_flags & (TG3_FLAG_RX_PAUSE | +- TG3_FLAG_TX_PAUSE)); +- orig_active_speed = tp->link_config.active_speed; +- orig_active_duplex = tp->link_config.active_duplex; +- +- tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); +- tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; +- tw32_f(MAC_MODE, tp->mac_mode); +- udelay(40); ++ /* Reset when initting first time or we have a link. */ ++ if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) && ++ !(mac_status & MAC_STATUS_PCS_SYNCED)) ++ return; + +- if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) { +- /* Allow time for the hardware to auto-negotiate (195ms) */ +- unsigned int tick = 0; ++ /* Set PLL lock range. */ ++ tg3_writephy(tp, 0x16, 0x8007); + +- while (++tick < 195000) { +- if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE) +- break; +- udelay(1); +- } +- if (tick >= 195000) +- printk(KERN_INFO PFX "%s: HW autoneg failed !\n", +- tp->dev->name); +- } ++ /* SW reset */ ++ tg3_writephy(tp, MII_BMCR, BMCR_RESET); + +- /* Reset when initting first time or we have a link. */ +- if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || +- (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { +- /* Set PLL lock range. */ +- tg3_writephy(tp, 0x16, 0x8007); +- +- /* SW reset */ +- tg3_writephy(tp, MII_BMCR, BMCR_RESET); +- +- /* Wait for reset to complete. */ +- /* XXX schedule_timeout() ... */ +- for (i = 0; i < 500; i++) +- udelay(10); ++ /* Wait for reset to complete. */ ++ /* XXX schedule_timeout() ... */ ++ for (i = 0; i < 500; i++) ++ udelay(10); + +- /* Config mode; select PMA/Ch 1 regs. */ +- tg3_writephy(tp, 0x10, 0x8411); ++ /* Config mode; select PMA/Ch 1 regs. */ ++ tg3_writephy(tp, 0x10, 0x8411); + +- /* Enable auto-lock and comdet, select txclk for tx. */ +- tg3_writephy(tp, 0x11, 0x0a10); ++ /* Enable auto-lock and comdet, select txclk for tx. */ ++ tg3_writephy(tp, 0x11, 0x0a10); + +- tg3_writephy(tp, 0x18, 0x00a0); +- tg3_writephy(tp, 0x16, 0x41ff); ++ tg3_writephy(tp, 0x18, 0x00a0); ++ tg3_writephy(tp, 0x16, 0x41ff); + +- /* Assert and deassert POR. */ +- tg3_writephy(tp, 0x13, 0x0400); +- udelay(40); +- tg3_writephy(tp, 0x13, 0x0000); ++ /* Assert and deassert POR. */ ++ tg3_writephy(tp, 0x13, 0x0400); ++ udelay(40); ++ tg3_writephy(tp, 0x13, 0x0000); + +- tg3_writephy(tp, 0x11, 0x0a50); +- udelay(40); +- tg3_writephy(tp, 0x11, 0x0a10); ++ tg3_writephy(tp, 0x11, 0x0a50); ++ udelay(40); ++ tg3_writephy(tp, 0x11, 0x0a10); + +- /* Wait for signal to stabilize */ +- /* XXX schedule_timeout() ... */ +- for (i = 0; i < 15000; i++) +- udelay(10); ++ /* Wait for signal to stabilize */ ++ /* XXX schedule_timeout() ... */ ++ for (i = 0; i < 15000; i++) ++ udelay(10); + +- /* Deselect the channel register so we can read the PHYID +- * later. +- */ +- tg3_writephy(tp, 0x10, 0x8011); +- } ++ /* Deselect the channel register so we can read the PHYID ++ * later. ++ */ ++ tg3_writephy(tp, 0x10, 0x8011); ++} + +- /* Enable link change interrupt unless serdes polling. */ +- if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES)) +- tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); +- else +- tw32_f(MAC_EVENT, 0); +- udelay(40); ++static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) ++{ ++ u32 sg_dig_ctrl, sg_dig_status; ++ u32 serdes_cfg, expected_sg_dig_ctrl; ++ int workaround, port_a; ++ int current_link_up; + ++ serdes_cfg = 0; ++ expected_sg_dig_ctrl = 0; ++ workaround = 0; ++ port_a = 1; + current_link_up = 0; +- if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) { +- if (tp->link_config.autoneg == AUTONEG_ENABLE) { +- u32 flags; +- +- if (fiber_autoneg(tp, &flags)) { +- u32 local_adv, remote_adv; + +- local_adv = ADVERTISE_PAUSE_CAP; +- remote_adv = 0; +- if (flags & MR_LP_ADV_SYM_PAUSE) +- remote_adv |= LPA_PAUSE_CAP; +- if (flags & MR_LP_ADV_ASYM_PAUSE) +- remote_adv |= LPA_PAUSE_ASYM; ++ if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 && ++ tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) { ++ workaround = 1; ++ if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) ++ port_a = 0; ++ ++ /* preserve bits 0-11,13,14 for signal pre-emphasis */ ++ /* preserve bits 20-23 for voltage regulator */ ++ serdes_cfg = tr32(MAC_SERDES_CFG) & 0x00f06fff; ++ } + +- tg3_setup_flow_control(tp, local_adv, remote_adv); ++ sg_dig_ctrl = tr32(SG_DIG_CTRL); + +- tp->tg3_flags |= +- TG3_FLAG_GOT_SERDES_FLOWCTL; +- current_link_up = 1; +- } +- for (i = 0; i < 60; i++) { +- udelay(20); +- tw32_f(MAC_STATUS, +- (MAC_STATUS_SYNC_CHANGED | +- MAC_STATUS_CFG_CHANGED)); +- udelay(40); +- if ((tr32(MAC_STATUS) & +- (MAC_STATUS_SYNC_CHANGED | +- MAC_STATUS_CFG_CHANGED)) == 0) +- break; +- } +- if (current_link_up == 0 && +- (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { +- current_link_up = 1; ++ if (tp->link_config.autoneg != AUTONEG_ENABLE) { ++ if (sg_dig_ctrl & (1 << 31)) { ++ if (workaround) { ++ u32 val = serdes_cfg; ++ ++ if (port_a) ++ val |= 0xc010000; ++ else ++ val |= 0x4010000; ++ tw32_f(MAC_SERDES_CFG, val); + } +- } else { +- /* Forcing 1000FD link up. */ ++ tw32_f(SG_DIG_CTRL, 0x01388400); ++ } ++ if (mac_status & MAC_STATUS_PCS_SYNCED) { ++ tg3_setup_flow_control(tp, 0, 0); + current_link_up = 1; +- tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; + } +- } else +- tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL; ++ goto out; ++ } + +- tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; +- tw32_f(MAC_MODE, tp->mac_mode); +- udelay(40); ++ /* Want auto-negotiation. */ ++ expected_sg_dig_ctrl = 0x81388400; + +- tp->hw_status->status = +- (SD_STATUS_UPDATED | +- (tp->hw_status->status & ~SD_STATUS_LINK_CHG)); ++ /* Pause capability */ ++ expected_sg_dig_ctrl |= (1 << 11); + +- for (i = 0; i < 100; i++) { +- udelay(20); +- tw32_f(MAC_STATUS, +- (MAC_STATUS_SYNC_CHANGED | +- MAC_STATUS_CFG_CHANGED)); +- udelay(40); +- if ((tr32(MAC_STATUS) & +- (MAC_STATUS_SYNC_CHANGED | +- MAC_STATUS_CFG_CHANGED)) == 0) +- break; +- } ++ /* Asymettric pause */ ++ expected_sg_dig_ctrl |= (1 << 12); + +- if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) +- current_link_up = 0; ++ if (sg_dig_ctrl != expected_sg_dig_ctrl) { ++ if (workaround) ++ tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000); ++ tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30)); ++ udelay(5); ++ tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl); + +- if (current_link_up == 1) { +- tp->link_config.active_speed = SPEED_1000; +- tp->link_config.active_duplex = DUPLEX_FULL; +- tw32(MAC_LED_CTRL, (tp->led_ctrl | +- LED_CTRL_LNKLED_OVERRIDE | +- LED_CTRL_1000MBPS_ON)); +- } else { +- tp->link_config.active_speed = SPEED_INVALID; +- tp->link_config.active_duplex = DUPLEX_INVALID; +- tw32(MAC_LED_CTRL, (tp->led_ctrl | +- LED_CTRL_LNKLED_OVERRIDE | +- LED_CTRL_TRAFFIC_OVERRIDE)); +- } ++ tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; ++ } else if (mac_status & (MAC_STATUS_PCS_SYNCED | ++ MAC_STATUS_SIGNAL_DET)) { ++ int i; + +- if (current_link_up != netif_carrier_ok(tp->dev)) { +- if (current_link_up) +- netif_carrier_on(tp->dev); +- else +- netif_carrier_off(tp->dev); +- tg3_link_report(tp); +- } else { +- u32 now_pause_cfg = +- tp->tg3_flags & (TG3_FLAG_RX_PAUSE | +- TG3_FLAG_TX_PAUSE); +- if (orig_pause_cfg != now_pause_cfg || +- orig_active_speed != tp->link_config.active_speed || +- orig_active_duplex != tp->link_config.active_duplex) +- tg3_link_report(tp); +- } ++ /* Giver time to negotiate (~200ms) */ ++ for (i = 0; i < 40000; i++) { ++ sg_dig_status = tr32(SG_DIG_STATUS); ++ if (sg_dig_status & (0x3)) ++ break; ++ udelay(5); ++ } ++ mac_status = tr32(MAC_STATUS); + +- if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) { +- tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY); +- udelay(40); +- if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) { +- tw32_f(MAC_MODE, tp->mac_mode); +- udelay(40); ++ if ((sg_dig_status & (1 << 1)) && ++ (mac_status & MAC_STATUS_PCS_SYNCED)) { ++ u32 local_adv, remote_adv; ++ ++ local_adv = ADVERTISE_PAUSE_CAP; ++ remote_adv = 0; ++ if (sg_dig_status & (1 << 19)) ++ remote_adv |= LPA_PAUSE_CAP; ++ if (sg_dig_status & (1 << 20)) ++ remote_adv |= LPA_PAUSE_ASYM; ++ ++ tg3_setup_flow_control(tp, local_adv, remote_adv); ++ current_link_up = 1; ++ tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; ++ } else if (!(sg_dig_status & (1 << 1))) { ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) ++ tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; ++ else { ++ if (workaround) { ++ u32 val = serdes_cfg; ++ ++ if (port_a) ++ val |= 0xc010000; ++ else ++ val |= 0x4010000; ++ ++ tw32_f(MAC_SERDES_CFG, val); ++ } ++ ++ tw32_f(SG_DIG_CTRL, 0x01388400); ++ udelay(40); ++ ++ /* Link parallel detection - link is up */ ++ /* only if we have PCS_SYNC and not */ ++ /* receiving config code words */ ++ mac_status = tr32(MAC_STATUS); ++ if ((mac_status & MAC_STATUS_PCS_SYNCED) && ++ !(mac_status & MAC_STATUS_RCVD_CFG)) { ++ tg3_setup_flow_control(tp, 0, 0); ++ current_link_up = 1; ++ } ++ } + } + } + +- return 0; ++out: ++ return current_link_up; + } + +-static int tg3_setup_phy(struct tg3 *tp, int force_reset) ++static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) ++{ ++ int current_link_up = 0; ++ ++ if (!(mac_status & MAC_STATUS_PCS_SYNCED)) { ++ tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL; ++ goto out; ++ } ++ ++ if (tp->link_config.autoneg == AUTONEG_ENABLE) { ++ u32 flags; ++ int i; ++ ++ if (fiber_autoneg(tp, &flags)) { ++ u32 local_adv, remote_adv; ++ ++ local_adv = ADVERTISE_PAUSE_CAP; ++ remote_adv = 0; ++ if (flags & MR_LP_ADV_SYM_PAUSE) ++ remote_adv |= LPA_PAUSE_CAP; ++ if (flags & MR_LP_ADV_ASYM_PAUSE) ++ remote_adv |= LPA_PAUSE_ASYM; ++ ++ tg3_setup_flow_control(tp, local_adv, remote_adv); ++ ++ tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; ++ current_link_up = 1; ++ } ++ for (i = 0; i < 30; i++) { ++ udelay(20); ++ tw32_f(MAC_STATUS, ++ (MAC_STATUS_SYNC_CHANGED | ++ MAC_STATUS_CFG_CHANGED)); ++ udelay(40); ++ if ((tr32(MAC_STATUS) & ++ (MAC_STATUS_SYNC_CHANGED | ++ MAC_STATUS_CFG_CHANGED)) == 0) ++ break; ++ } ++ ++ mac_status = tr32(MAC_STATUS); ++ if (current_link_up == 0 && ++ (mac_status & MAC_STATUS_PCS_SYNCED) && ++ !(mac_status & MAC_STATUS_RCVD_CFG)) ++ current_link_up = 1; ++ } else { ++ /* Forcing 1000FD link up. */ ++ current_link_up = 1; ++ tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; ++ ++ tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS)); ++ udelay(40); ++ } ++ ++out: ++ return current_link_up; ++} ++ ++static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) ++{ ++ u32 orig_pause_cfg; ++ u16 orig_active_speed; ++ u8 orig_active_duplex; ++ u32 mac_status; ++ int current_link_up; ++ int i; ++ ++ orig_pause_cfg = ++ (tp->tg3_flags & (TG3_FLAG_RX_PAUSE | ++ TG3_FLAG_TX_PAUSE)); ++ orig_active_speed = tp->link_config.active_speed; ++ orig_active_duplex = tp->link_config.active_duplex; ++ ++ if (!(tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) && ++ netif_carrier_ok(tp->dev) && ++ (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) { ++ mac_status = tr32(MAC_STATUS); ++ mac_status &= (MAC_STATUS_PCS_SYNCED | ++ MAC_STATUS_SIGNAL_DET | ++ MAC_STATUS_CFG_CHANGED | ++ MAC_STATUS_RCVD_CFG); ++ if (mac_status == (MAC_STATUS_PCS_SYNCED | ++ MAC_STATUS_SIGNAL_DET)) { ++ tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | ++ MAC_STATUS_CFG_CHANGED)); ++ return 0; ++ } ++ } ++ ++ tw32_f(MAC_TX_AUTO_NEG, 0); ++ ++ tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); ++ tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; ++ tw32_f(MAC_MODE, tp->mac_mode); ++ udelay(40); ++ ++ if (tp->phy_id == PHY_ID_BCM8002) ++ tg3_init_bcm8002(tp); ++ ++ /* Enable link change event even when serdes polling. */ ++ tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); ++ udelay(40); ++ ++ current_link_up = 0; ++ mac_status = tr32(MAC_STATUS); ++ ++ if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) ++ current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status); ++ else ++ current_link_up = tg3_setup_fiber_by_hand(tp, mac_status); ++ ++ tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; ++ tw32_f(MAC_MODE, tp->mac_mode); ++ udelay(40); ++ ++ tp->hw_status->status = ++ (SD_STATUS_UPDATED | ++ (tp->hw_status->status & ~SD_STATUS_LINK_CHG)); ++ ++ for (i = 0; i < 100; i++) { ++ tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | ++ MAC_STATUS_CFG_CHANGED)); ++ udelay(5); ++ if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED | ++ MAC_STATUS_CFG_CHANGED)) == 0) ++ break; ++ } ++ ++ mac_status = tr32(MAC_STATUS); ++ if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) { ++ current_link_up = 0; ++ if (tp->link_config.autoneg == AUTONEG_ENABLE) { ++ tw32_f(MAC_MODE, (tp->mac_mode | ++ MAC_MODE_SEND_CONFIGS)); ++ udelay(1); ++ tw32_f(MAC_MODE, tp->mac_mode); ++ } ++ } ++ ++ if (current_link_up == 1) { ++ tp->link_config.active_speed = SPEED_1000; ++ tp->link_config.active_duplex = DUPLEX_FULL; ++ tw32(MAC_LED_CTRL, (tp->led_ctrl | ++ LED_CTRL_LNKLED_OVERRIDE | ++ LED_CTRL_1000MBPS_ON)); ++ } else { ++ tp->link_config.active_speed = SPEED_INVALID; ++ tp->link_config.active_duplex = DUPLEX_INVALID; ++ tw32(MAC_LED_CTRL, (tp->led_ctrl | ++ LED_CTRL_LNKLED_OVERRIDE | ++ LED_CTRL_TRAFFIC_OVERRIDE)); ++ } ++ ++ if (current_link_up != netif_carrier_ok(tp->dev)) { ++ if (current_link_up) ++ netif_carrier_on(tp->dev); ++ else ++ netif_carrier_off(tp->dev); ++ tg3_link_report(tp); ++ } else { ++ u32 now_pause_cfg = ++ tp->tg3_flags & (TG3_FLAG_RX_PAUSE | ++ TG3_FLAG_TX_PAUSE); ++ if (orig_pause_cfg != now_pause_cfg || ++ orig_active_speed != tp->link_config.active_speed || ++ orig_active_duplex != tp->link_config.active_duplex) ++ tg3_link_report(tp); ++ } ++ ++ return 0; ++} ++ ++static int tg3_setup_phy(struct tg3 *tp, int force_reset) + { + int err; + +- if (tp->phy_id == PHY_ID_SERDES) { ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { + err = tg3_setup_fiber_phy(tp, force_reset); + } else { + err = tg3_setup_copper_phy(tp, force_reset); +@@ -2237,8 +2498,7 @@ static int tg3_setup_phy(struct tg3 *tp, + (6 << TX_LENGTHS_IPG_SHIFT) | + (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (netif_carrier_ok(tp->dev)) { + tw32(HOSTCC_STAT_COAL_TICKS, + DEFAULT_STAT_COAL_TICKS); +@@ -2450,8 +2710,8 @@ static int tg3_vlan_rx(struct tg3 *tp, s + static int tg3_rx(struct tg3 *tp, int budget) + { + u32 work_mask; +- u32 rx_rcb_ptr = tp->rx_rcb_ptr; +- u16 hw_idx, sw_idx; ++ u32 sw_idx = tp->rx_rcb_ptr; ++ u16 hw_idx; + int received; + + hw_idx = tp->hw_status->idx[0].rx_producer; +@@ -2460,7 +2720,6 @@ static int tg3_rx(struct tg3 *tp, int bu + * the opaque cookie. + */ + rmb(); +- sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp); + work_mask = 0; + received = 0; + while (sw_idx != hw_idx && budget > 0) { +@@ -2502,7 +2761,11 @@ static int tg3_rx(struct tg3 *tp, int bu + + len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */ + +- if (len > RX_COPY_THRESHOLD) { ++ if (len > RX_COPY_THRESHOLD ++ && tp->rx_offset == 2 ++ /* rx_offset != 2 iff this is a 5701 card running ++ * in PCI-X mode [see tg3_get_invariants()] */ ++ ) { + int skb_size; + + skb_size = tg3_alloc_rx_skb(tp, opaque_key, +@@ -2561,14 +2824,19 @@ static int tg3_rx(struct tg3 *tp, int bu + next_pkt: + (*post_ptr)++; + next_pkt_nopost: +- rx_rcb_ptr++; +- sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp); ++ sw_idx++; ++ sw_idx %= TG3_RX_RCB_RING_SIZE(tp); ++ ++ /* Refresh hw_idx to see if there is new work */ ++ if (sw_idx == hw_idx) { ++ hw_idx = tp->hw_status->idx[0].rx_producer; ++ rmb(); ++ } + } + + /* ACK the status ring. */ +- tp->rx_rcb_ptr = rx_rcb_ptr; +- tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, +- (rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp))); ++ tp->rx_rcb_ptr = sw_idx; ++ tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, sw_idx); + + /* Refill RX ring(s). */ + if (work_mask & RXD_OPAQUE_RING_STD) { +@@ -2581,6 +2849,7 @@ next_pkt_nopost: + tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, + sw_idx); + } ++ mmiowb(); + + return received; + } +@@ -2639,31 +2908,48 @@ static int tg3_poll(struct net_device *n + if (done) { + spin_lock_irqsave(&tp->lock, flags); + __netif_rx_complete(netdev); +- tg3_enable_ints(tp); ++ tg3_restart_ints(tp); + spin_unlock_irqrestore(&tp->lock, flags); + } + + return (done ? 0 : 1); + } + +-static inline unsigned int tg3_has_work(struct net_device *dev, struct tg3 *tp) ++/* MSI ISR - No need to check for interrupt sharing and no need to ++ * flush status block and interrupt mailbox. PCI ordering rules ++ * guarantee that MSI will arrive after the status block. ++ */ ++static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) + { ++ struct net_device *dev = dev_id; ++ struct tg3 *tp = netdev_priv(dev); + struct tg3_hw_status *sblk = tp->hw_status; +- unsigned int work_exists = 0; ++ unsigned long flags; + +- /* check for phy events */ +- if (!(tp->tg3_flags & +- (TG3_FLAG_USE_LINKCHG_REG | +- TG3_FLAG_POLL_SERDES))) { +- if (sblk->status & SD_STATUS_LINK_CHG) +- work_exists = 1; ++ spin_lock_irqsave(&tp->lock, flags); ++ ++ /* ++ * writing any value to intr-mbox-0 clears PCI INTA# and ++ * chip-internal interrupt pending events. ++ * writing non-zero to intr-mbox-0 additional tells the ++ * NIC to stop sending us irqs, engaging "in-intr-handler" ++ * event coalescing. ++ */ ++ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); ++ sblk->status &= ~SD_STATUS_UPDATED; ++ ++ if (likely(tg3_has_work(tp))) ++ netif_rx_schedule(dev); /* schedule NAPI poll */ ++ else { ++ /* no work, re-enable interrupts ++ */ ++ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, ++ 0x00000000); + } +- /* check for RX/TX work to do */ +- if (sblk->idx[0].tx_consumer != tp->tx_cons || +- sblk->idx[0].rx_producer != tp->rx_rcb_ptr) +- work_exists = 1; + +- return work_exists; ++ spin_unlock_irqrestore(&tp->lock, flags); ++ ++ return IRQ_RETVAL(1); + } + + static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +@@ -2676,7 +2962,13 @@ static irqreturn_t tg3_interrupt(int irq + + spin_lock_irqsave(&tp->lock, flags); + +- if (sblk->status & SD_STATUS_UPDATED) { ++ /* In INTx mode, it is possible for the interrupt to arrive at ++ * the CPU before the status block posted prior to the interrupt. ++ * Reading the PCI State register will confirm whether the ++ * interrupt is ours and will flush the status block. ++ */ ++ if ((sblk->status & SD_STATUS_UPDATED) || ++ !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { + /* + * writing any value to intr-mbox-0 clears PCI INTA# and + * chip-internal interrupt pending events. +@@ -2693,7 +2985,7 @@ static irqreturn_t tg3_interrupt(int irq + tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); + sblk->status &= ~SD_STATUS_UPDATED; + +- if (likely(tg3_has_work(dev, tp))) ++ if (likely(tg3_has_work(tp))) + netif_rx_schedule(dev); /* schedule NAPI poll */ + else { + /* no work, shared interrupt perhaps? re-enable +@@ -2712,13 +3004,31 @@ static irqreturn_t tg3_interrupt(int irq + return IRQ_RETVAL(handled); + } + ++/* ISR for interrupt test */ ++static irqreturn_t tg3_test_isr(int irq, void *dev_id, ++ struct pt_regs *regs) ++{ ++ struct net_device *dev = dev_id; ++ struct tg3 *tp = netdev_priv(dev); ++ struct tg3_hw_status *sblk = tp->hw_status; ++ ++ if (sblk->status & SD_STATUS_UPDATED) { ++ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, ++ 0x00000001); ++ return IRQ_RETVAL(1); ++ } ++ return IRQ_RETVAL(0); ++} ++ + static int tg3_init_hw(struct tg3 *); +-static int tg3_halt(struct tg3 *); ++static int tg3_halt(struct tg3 *, int); + + #ifdef CONFIG_NET_POLL_CONTROLLER + static void tg3_poll_controller(struct net_device *dev) + { +- tg3_interrupt(dev->irq, dev, NULL); ++ struct tg3 *tp = netdev_priv(dev); ++ ++ tg3_interrupt(tp->pdev->irq, dev, NULL); + } + #endif + +@@ -2735,14 +3045,14 @@ static void tg3_reset_task(void *_data) + restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER; + tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; + +- tg3_halt(tp); ++ tg3_halt(tp, 0); + tg3_init_hw(tp); + ++ tg3_netif_start(tp); ++ + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + +- tg3_netif_start(tp); +- + if (restart_timer) + mod_timer(&tp->timer, jiffies + 1); + } +@@ -2801,6 +3111,7 @@ static int tigon3_4gb_hwbug_workaround(s + tp->tx_buffers[entry].skb = NULL; + } + entry = NEXT_TX(entry); ++ i++; + } + + dev_kfree_skb(skb); +@@ -2812,6 +3123,7 @@ static void tg3_set_txd(struct tg3 *tp, + dma_addr_t mapping, int len, u32 flags, + u32 mss_and_is_end) + { ++ struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry]; + int is_end = (mss_and_is_end & 0x1); + u32 mss = (mss_and_is_end >> 1); + u32 vlan_tag = 0; +@@ -2823,35 +3135,11 @@ static void tg3_set_txd(struct tg3 *tp, + flags &= 0xffff; + } + vlan_tag |= (mss << TXD_MSS_SHIFT); +- if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { +- struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry]; +- +- txd->addr_hi = ((u64) mapping >> 32); +- txd->addr_lo = ((u64) mapping & 0xffffffff); +- txd->len_flags = (len << TXD_LEN_SHIFT) | flags; +- txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; +- } else { +- struct tx_ring_info *txr = &tp->tx_buffers[entry]; +- unsigned long txd; +- +- txd = (tp->regs + +- NIC_SRAM_WIN_BASE + +- NIC_SRAM_TX_BUFFER_DESC); +- txd += (entry * TXD_SIZE); + +- /* Save some PIOs */ +- if (sizeof(dma_addr_t) != sizeof(u32)) +- writel(((u64) mapping >> 32), +- txd + TXD_ADDR + TG3_64BIT_REG_HIGH); +- +- writel(((u64) mapping & 0xffffffff), +- txd + TXD_ADDR + TG3_64BIT_REG_LOW); +- writel(len << TXD_LEN_SHIFT | flags, txd + TXD_LEN_FLAGS); +- if (txr->prev_vlan_tag != vlan_tag) { +- writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG); +- txr->prev_vlan_tag = vlan_tag; +- } +- } ++ txd->addr_hi = ((u64) mapping >> 32); ++ txd->addr_lo = ((u64) mapping & 0xffffffff); ++ txd->len_flags = (len << TXD_LEN_SHIFT) | flags; ++ txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; + } + + static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) +@@ -2892,7 +3180,11 @@ static int tg3_start_xmit(struct sk_buff + * So we really do need to disable interrupts when taking + * tx_lock here. + */ +- spin_lock_irqsave(&tp->tx_lock, flags); ++ local_irq_save(flags); ++ if (!spin_trylock(&tp->tx_lock)) { ++ local_irq_restore(flags); ++ return NETDEV_TX_LOCKED; ++ } + + /* This is a hard error, log it. */ + if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { +@@ -2900,7 +3192,7 @@ static int tg3_start_xmit(struct sk_buff + spin_unlock_irqrestore(&tp->tx_lock, flags); + printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", + dev->name); +- return 1; ++ return NETDEV_TX_BUSY; + } + + entry = tp->tx_prod; +@@ -2913,6 +3205,12 @@ static int tg3_start_xmit(struct sk_buff + (mss = skb_shinfo(skb)->tso_size) != 0) { + int tcp_opt_len, ip_tcp_len; + ++ if (skb_header_cloned(skb) && ++ pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { ++ dev_kfree_skb(skb); ++ goto out_unlock; ++ } ++ + tcp_opt_len = ((skb->h.th->doff - 5) * 4); + ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); + +@@ -2921,11 +3219,19 @@ static int tg3_start_xmit(struct sk_buff + + skb->nh.iph->check = 0; + skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len); +- skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, +- skb->nh.iph->daddr, +- 0, IPPROTO_TCP, 0); ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { ++ skb->h.th->check = 0; ++ base_flags &= ~TXD_FLAG_TCPUDP_CSUM; ++ } ++ else { ++ skb->h.th->check = ++ ~csum_tcpudp_magic(skb->nh.iph->saddr, ++ skb->nh.iph->daddr, ++ 0, IPPROTO_TCP, 0); ++ } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { ++ if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) || ++ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) { + if (tcp_opt_len || skb->nh.iph->ihl > 5) { + int tsflags; + +@@ -2992,7 +3298,7 @@ static int tg3_start_xmit(struct sk_buff + would_hit_hwbug = entry + 1; + } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + tg3_set_txd(tp, entry, mapping, len, + base_flags, (i == last)|(mss << 1)); + else +@@ -3040,30 +3346,19 @@ static int tg3_start_xmit(struct sk_buff + } + + /* Packets are ready, update Tx producer idx local and on card. */ +- if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { +- tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + +- TG3_64BIT_REG_LOW), entry); +- } else { +- /* First, make sure tg3 sees last descriptor fully +- * in SRAM. +- */ +- if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) +- tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW); +- +- tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 + +- TG3_64BIT_REG_LOW), entry); +- } ++ tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); + + tp->tx_prod = entry; + if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) + netif_stop_queue(dev); + + out_unlock: ++ mmiowb(); + spin_unlock_irqrestore(&tp->tx_lock, flags); + + dev->trans_start = jiffies; + +- return 0; ++ return NETDEV_TX_OK; + } + + static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, +@@ -3096,15 +3391,16 @@ static int tg3_change_mtu(struct net_dev + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); + +- tg3_halt(tp); ++ tg3_halt(tp, 1); + + tg3_set_mtu(dev, tp, new_mtu); + + tg3_init_hw(tp); + ++ tg3_netif_start(tp); ++ + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); +- tg3_netif_start(tp); + + return 0; + } +@@ -3190,7 +3486,6 @@ static void tg3_free_rings(struct tg3 *t + */ + static void tg3_init_rings(struct tg3 *tp) + { +- unsigned long start, end; + u32 i; + + /* Free up all the SKBs. */ +@@ -3200,21 +3495,7 @@ static void tg3_init_rings(struct tg3 *t + memset(tp->rx_std, 0, TG3_RX_RING_BYTES); + memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES); + memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); +- +- if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { +- memset(tp->tx_ring, 0, TG3_TX_RING_BYTES); +- } else { +- start = (tp->regs + +- NIC_SRAM_WIN_BASE + +- NIC_SRAM_TX_BUFFER_DESC); +- end = start + TG3_TX_RING_BYTES; +- while (start < end) { +- writel(0, start); +- start += 4; +- } +- for (i = 0; i < TG3_TX_RING_SIZE; i++) +- tp->tx_buffers[i].prev_vlan_tag = 0; +- } ++ memset(tp->tx_ring, 0, TG3_TX_RING_BYTES); + + /* Initialize invariants of the rings, we only set this + * stuff once. This works because the card does not +@@ -3345,15 +3626,10 @@ static int tg3_alloc_consistent(struct t + if (!tp->rx_rcb) + goto err_out; + +- if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { +- tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES, +- &tp->tx_desc_mapping); +- if (!tp->tx_ring) +- goto err_out; +- } else { +- tp->tx_ring = NULL; +- tp->tx_desc_mapping = 0; +- } ++ tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES, ++ &tp->tx_desc_mapping); ++ if (!tp->tx_ring) ++ goto err_out; + + tp->hw_status = pci_alloc_consistent(tp->pdev, + TG3_HW_STATUS_SIZE, +@@ -3382,13 +3658,12 @@ err_out: + /* To stop a block, clear the enable bit and poll till it + * clears. tp->lock is held. + */ +-static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit) ++static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int silent) + { + unsigned int i; + u32 val; + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { ++ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + switch (ofs) { + case RCVLSC_MODE: + case DMAC_MODE: +@@ -3416,7 +3691,7 @@ static int tg3_stop_block(struct tg3 *tp + break; + } + +- if (i == MAX_WAIT_CNT) { ++ if (i == MAX_WAIT_CNT && !silent) { + printk(KERN_ERR PFX "tg3_stop_block timed out, " + "ofs=%lx enable_bit=%x\n", + ofs, enable_bit); +@@ -3427,7 +3702,7 @@ static int tg3_stop_block(struct tg3 *tp + } + + /* tp->lock is held. */ +-static int tg3_abort_hw(struct tg3 *tp) ++static int tg3_abort_hw(struct tg3 *tp, int silent) + { + int i, err; + +@@ -3437,22 +3712,20 @@ static int tg3_abort_hw(struct tg3 *tp) + tw32_f(MAC_RX_MODE, tp->rx_mode); + udelay(10); + +- err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE); +- err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE); +- err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE); +- err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE); +- err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE); +- err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE); +- +- err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE); +- err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE); +- err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); +- err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE); +- err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE); +- err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE); +- err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE); +- if (err) +- goto out; ++ err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE, silent); ++ ++ err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE, silent); + + tp->mac_mode &= ~MAC_MODE_TDE_ENABLE; + tw32_f(MAC_MODE, tp->mac_mode); +@@ -3470,27 +3743,24 @@ static int tg3_abort_hw(struct tg3 *tp) + printk(KERN_ERR PFX "tg3_abort_hw timed out for %s, " + "TX_MODE_ENABLE will not clear MAC_TX_MODE=%08x\n", + tp->dev->name, tr32(MAC_TX_MODE)); +- return -ENODEV; ++ err |= -ENODEV; + } + +- err = tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE); +- err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE); +- err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE); ++ err |= tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE, silent); + + tw32(FTQ_RESET, 0xffffffff); + tw32(FTQ_RESET, 0x00000000); + +- err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE); +- err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE); +- if (err) +- goto out; ++ err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE, silent); ++ err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE, silent); + + if (tp->hw_status) + memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); + if (tp->hw_stats) + memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); + +-out: + return err; + } + +@@ -3520,10 +3790,33 @@ static void tg3_nvram_unlock(struct tg3 + } + + /* tp->lock is held. */ ++static void tg3_enable_nvram_access(struct tg3 *tp) ++{ ++ if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && ++ !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) { ++ u32 nvaccess = tr32(NVRAM_ACCESS); ++ ++ tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); ++ } ++} ++ ++/* tp->lock is held. */ ++static void tg3_disable_nvram_access(struct tg3 *tp) ++{ ++ if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && ++ !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) { ++ u32 nvaccess = tr32(NVRAM_ACCESS); ++ ++ tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); ++ } ++} ++ ++/* tp->lock is held. */ + static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) + { +- tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, +- NIC_SRAM_FIRMWARE_MBOX_MAGIC1); ++ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) ++ tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, ++ NIC_SRAM_FIRMWARE_MBOX_MAGIC1); + + if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) { + switch (kind) { +@@ -3595,6 +3888,8 @@ static void tg3_write_sig_legacy(struct + } + } + ++static void tg3_stop_fw(struct tg3 *); ++ + /* tp->lock is held. */ + static int tg3_chip_reset(struct tg3 *tp) + { +@@ -3602,7 +3897,7 @@ static int tg3_chip_reset(struct tg3 *tp + u32 flags_save; + int i; + +- if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) ++ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) + tg3_nvram_lock(tp); + + /* +@@ -3627,8 +3922,7 @@ static int tg3_chip_reset(struct tg3 *tp + } + } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + val |= GRC_MISC_CFG_KEEP_GPHY_POWER; + tw32(GRC_MISC_CFG, val); + +@@ -3697,6 +3991,11 @@ static int tg3_chip_reset(struct tg3 *tp + + tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); + ++ if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) { ++ tg3_stop_fw(tp); ++ tw32(0x5000, 0x400); ++ } ++ + tw32(GRC_MODE, tp->grc_mode); + + if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) { +@@ -3713,26 +4012,27 @@ static int tg3_chip_reset(struct tg3 *tp + tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); + } + +- if (tp->phy_id == PHY_ID_SERDES) { ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { + tp->mac_mode = MAC_MODE_PORT_MODE_TBI; + tw32_f(MAC_MODE, tp->mac_mode); + } else + tw32_f(MAC_MODE, 0); + udelay(40); + +- /* Wait for firmware initialization to complete. */ +- for (i = 0; i < 100000; i++) { +- tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); +- if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) +- break; +- udelay(10); +- } +- if (i >= 100000 && +- !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { +- printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, " +- "firmware will not restart magic=%08x\n", +- tp->dev->name, val); +- return -ENODEV; ++ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) { ++ /* Wait for firmware initialization to complete. */ ++ for (i = 0; i < 100000; i++) { ++ tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); ++ if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) ++ break; ++ udelay(10); ++ } ++ if (i >= 100000) { ++ printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, " ++ "firmware will not restart magic=%08x\n", ++ tp->dev->name, val); ++ return -ENODEV; ++ } + } + + if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && +@@ -3752,7 +4052,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; +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) + tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; + } + } +@@ -3782,7 +4082,7 @@ static void tg3_stop_fw(struct tg3 *tp) + } + + /* tp->lock is held. */ +-static int tg3_halt(struct tg3 *tp) ++static int tg3_halt(struct tg3 *tp, int silent) + { + int err; + +@@ -3790,7 +4090,7 @@ static int tg3_halt(struct tg3 *tp) + + tg3_write_sig_pre_reset(tp, RESET_KIND_SHUTDOWN); + +- tg3_abort_hw(tp); ++ tg3_abort_hw(tp, silent); + err = tg3_chip_reset(tp); + + tg3_write_sig_legacy(tp, RESET_KIND_SHUTDOWN); +@@ -3937,7 +4237,7 @@ static int tg3_halt_cpu(struct tg3 *tp, + int i; + + if (offset == TX_CPU_BASE && +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ++ (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + BUG(); + + if (offset == RX_CPU_BASE) { +@@ -3991,14 +4291,14 @@ static int tg3_load_firmware_cpu(struct + void (*write_op)(struct tg3 *, u32, u32); + + if (cpu_base == TX_CPU_BASE && +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { ++ (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + printk(KERN_ERR PFX "tg3_load_firmware_cpu: Trying to load " + "TX cpu firmware on %s which is 5705.\n", + tp->dev->name); + return -EINVAL; + } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ++ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + write_op = tg3_write_mem; + else + write_op = tg3_write_indirect_reg32; +@@ -4399,7 +4699,7 @@ static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT + 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000, + }; + +-u32 tg3TsoFwRodata[] = { ++static u32 tg3TsoFwRodata[] = { + 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, + 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f, + 0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, +@@ -4407,7 +4707,7 @@ u32 tg3TsoFwRodata[] = { + 0x00000000, + }; + +-u32 tg3TsoFwData[] = { ++static u32 tg3TsoFwData[] = { + 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, +@@ -4588,14 +4888,14 @@ static u32 tg3Tso5FwText[(TG3_TSO5_FW_TE + 0x00000000, 0x00000000, 0x00000000, + }; + +-u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { ++static u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { + 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, + 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, + 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, + 0x00000000, 0x00000000, 0x00000000, + }; + +-u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { ++static u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { + 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, + }; +@@ -4607,7 +4907,7 @@ static int tg3_load_tso_firmware(struct + unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; + int err, i; + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + return 0; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { +@@ -4691,9 +4991,8 @@ static void __tg3_set_mac_addr(struct tg + tw32(MAC_ADDR_0_LOW + (i * 8), addr_low); + } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || ++ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { + for (i = 0; i < 12; i++) { + tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high); + tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low); +@@ -4739,7 +5038,7 @@ static void tg3_set_bdinfo(struct tg3 *t + (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS), + maxlen_flags); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + tg3_write_mem(tp, + (bdinfo_addr + TG3_BDINFO_NIC_ADDR), + nic_addr); +@@ -4760,9 +5059,7 @@ static int tg3_reset_hw(struct tg3 *tp) + tg3_write_sig_pre_reset(tp, RESET_KIND_INIT); + + if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) { +- err = tg3_abort_hw(tp); +- if (err) +- return err; ++ tg3_abort_hw(tp, 1); + } + + err = tg3_chip_reset(tp); +@@ -4810,10 +5107,7 @@ static int tg3_reset_hw(struct tg3 *tp) + GRC_MODE_4X_NIC_SEND_RINGS | + GRC_MODE_NO_TX_PHDR_CSUM | + GRC_MODE_NO_RX_PHDR_CSUM); +- if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) +- tp->grc_mode |= GRC_MODE_HOST_SENDBDS; +- else +- tp->grc_mode |= GRC_MODE_4X_NIC_SEND_RINGS; ++ tp->grc_mode |= GRC_MODE_HOST_SENDBDS; + if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM) + tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; + if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM) +@@ -4830,7 +5124,7 @@ static int tg3_reset_hw(struct tg3 *tp) + tw32(GRC_MISC_CFG, val); + + /* Initialize MBUF/DESC pool. */ +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { ++ if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { + /* Do nothing. */ + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE); +@@ -4920,8 +5214,7 @@ static int tg3_reset_hw(struct tg3 *tp) + /* Don't even try to program the JUMBO/MINI buffer descriptor + * configs on 5705. + */ +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { ++ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, + RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT); + } else { +@@ -4953,8 +5246,7 @@ static int tg3_reset_hw(struct tg3 *tp) + /* There is only one send ring on 5705/5750, no need to explicitly + * disable the others. + */ +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + /* Clear out send RCB ring in SRAM. */ + for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE) + tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, +@@ -4966,24 +5258,16 @@ static int tg3_reset_hw(struct tg3 *tp) + tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); + tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); + +- if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { +- tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, +- tp->tx_desc_mapping, +- (TG3_TX_RING_SIZE << +- BDINFO_FLAGS_MAXLEN_SHIFT), +- NIC_SRAM_TX_BUFFER_DESC); +- } else { +- tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, +- 0, +- BDINFO_FLAGS_DISABLED, +- NIC_SRAM_TX_BUFFER_DESC); +- } ++ tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, ++ tp->tx_desc_mapping, ++ (TG3_TX_RING_SIZE << ++ BDINFO_FLAGS_MAXLEN_SHIFT), ++ NIC_SRAM_TX_BUFFER_DESC); + + /* There is only one receive return ring on 5705/5750, no need + * to explicitly disable the others. + */ +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK; + i += TG3_BDINFO_SIZE) { + tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, +@@ -5037,6 +5321,8 @@ static int tg3_reset_hw(struct tg3 *tp) + RDMAC_MODE_LNGREAD_ENAB); + if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) + rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE; ++ ++ /* If statement applies to 5705 and 5750 PCI devices only */ + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && + tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) { +@@ -5050,8 +5336,11 @@ static int tg3_reset_hw(struct tg3 *tp) + } + } + ++ if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) ++ rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; ++ + #if TG3_TSO_SUPPORT != 0 +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + rdmac_mode |= (1 << 27); + #endif + +@@ -5082,8 +5371,7 @@ static int tg3_reset_hw(struct tg3 *tp) + tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS); + tw32(HOSTCC_RXMAX_FRAMES, 1); + tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES); +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + tw32(HOSTCC_RXCOAL_TICK_INT, 0); + tw32(HOSTCC_TXCOAL_TICK_INT, 0); + } +@@ -5096,8 +5384,7 @@ static int tg3_reset_hw(struct tg3 *tp) + tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, + ((u64) tp->status_mapping & 0xffffffff)); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + /* Status/statistics block address. See tg3_timer, + * the tg3_periodic_fetch_stats call there, and + * tg3_get_stats to see how this works for 5705/5750 chips. +@@ -5116,8 +5403,7 @@ static int tg3_reset_hw(struct tg3 *tp) + + tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE); + tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE); +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE); + + /* Clear statistics/status block in chip, and status block in ram. */ +@@ -5134,18 +5420,35 @@ static int tg3_reset_hw(struct tg3 *tp) + tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); + udelay(40); + +- tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM; +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) ++ /* tp->grc_local_ctrl is partially set up during tg3_get_invariants(). ++ * If TG3_FLAG_EEPROM_WRITE_PROT is set, we should read the ++ * register to preserve the GPIO settings for LOMs. The GPIOs, ++ * whether used as inputs or outputs, are set by boot code after ++ * reset. ++ */ ++ if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { ++ u32 gpio_mask; ++ ++ gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE2 | ++ GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT2; ++ ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) ++ gpio_mask |= GRC_LCLCTRL_GPIO_OE3 | ++ GRC_LCLCTRL_GPIO_OUTPUT3; ++ ++ tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask; ++ ++ /* GPIO1 must be driven high for eeprom write protect */ + tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OUTPUT1); ++ } + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); + udelay(100); + + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); + tr32(MAILBOX_INTERRUPT_0); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + tw32_f(DMAC_MODE, DMAC_MODE_ENABLE); + udelay(40); + } +@@ -5156,6 +5459,7 @@ static int tg3_reset_hw(struct tg3 *tp) + WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB | + WDMAC_MODE_LNGREAD_ENAB); + ++ /* If statement applies to 5705 and 5750 PCI devices only */ + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && + tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { +@@ -5192,8 +5496,7 @@ static int tg3_reset_hw(struct tg3 *tp) + udelay(40); + + tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE); +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) ++ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + tw32(MBFREE_MODE, MBFREE_MODE_ENABLE); + tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE); + tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE); +@@ -5201,7 +5504,7 @@ static int tg3_reset_hw(struct tg3 *tp) + tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ); + tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); + #if TG3_TSO_SUPPORT != 0 +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8); + #endif + tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE); +@@ -5243,16 +5546,18 @@ static int tg3_reset_hw(struct tg3 *tp) + tw32(MAC_LED_CTRL, tp->led_ctrl); + + tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); +- if (tp->phy_id == PHY_ID_SERDES) { ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { + tw32_f(MAC_RX_MODE, RX_MODE_RESET); + udelay(10); + } + tw32_f(MAC_RX_MODE, tp->rx_mode); + udelay(10); + +- if (tp->phy_id == PHY_ID_SERDES) { +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { ++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) && ++ !(tp->tg3_flags2 & TG3_FLG2_SERDES_PREEMPHASIS)) { + /* Set drive transmission level to 1.2V */ ++ /* only if the signal pre-emphasis bit is not set */ + val = tr32(MAC_SERDES_CFG); + val &= 0xfffff000; + val |= 0x880; +@@ -5268,22 +5573,8 @@ static int tg3_reset_hw(struct tg3 *tp) + tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && +- tp->phy_id == PHY_ID_SERDES) { +- /* Enable hardware link auto-negotiation */ +- u32 digctrl, txctrl; +- +- digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N | +- SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS | +- (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE | +- SG_DIG_GBIC_ENABLE; +- +- txctrl = tr32(MAC_SERDES_CFG); +- tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT); +- tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET); +- tr32(SG_DIG_CTRL); +- udelay(5); +- tw32_f(SG_DIG_CTRL, digctrl); +- ++ (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { ++ /* Use hardware link auto-negotiation */ + tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG; + } + +@@ -5291,13 +5582,14 @@ static int tg3_reset_hw(struct tg3 *tp) + if (err) + return err; + +- if (tp->phy_id != PHY_ID_SERDES) { ++ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + u32 tmp; + + /* Clear CRC stats. */ +- tg3_readphy(tp, 0x1e, &tmp); +- tg3_writephy(tp, 0x1e, tmp | 0x8000); +- tg3_readphy(tp, 0x14, &tmp); ++ if (!tg3_readphy(tp, 0x1e, &tmp)) { ++ tg3_writephy(tp, 0x1e, tmp | 0x8000); ++ tg3_readphy(tp, 0x14, &tmp); ++ } + } + + __tg3_set_rx_mode(tp->dev); +@@ -5308,8 +5600,7 @@ static int tg3_reset_hw(struct tg3 *tp) + tw32(MAC_RCV_RULE_1, 0x86000004 & RCV_RULE_DISABLE_MASK); + tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + limit = 8; + else + limit = 16; +@@ -5453,8 +5744,7 @@ static void tg3_timer(unsigned long __op + return; + } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + tg3_periodic_fetch_stats(tp); + + /* This part only runs once per second. */ +@@ -5483,7 +5773,8 @@ static void tg3_timer(unsigned long __op + need_setup = 1; + } + if (! netif_carrier_ok(tp->dev) && +- (mac_stat & MAC_STATUS_PCS_SYNCED)) { ++ (mac_stat & (MAC_STATUS_PCS_SYNCED | ++ MAC_STATUS_SIGNAL_DET))) { + need_setup = 1; + } + if (need_setup) { +@@ -5522,11 +5813,123 @@ static void tg3_timer(unsigned long __op + add_timer(&tp->timer); + } + +-static int tg3_open(struct net_device *dev) ++static int tg3_test_interrupt(struct tg3 *tp) + { +- struct tg3 *tp = netdev_priv(dev); +- int err; +- ++ struct net_device *dev = tp->dev; ++ int err, i; ++ u32 int_mbox = 0; ++ ++ tg3_disable_ints(tp); ++ ++ free_irq(tp->pdev->irq, dev); ++ ++ err = request_irq(tp->pdev->irq, tg3_test_isr, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); ++ if (err) ++ return err; ++ ++ tg3_enable_ints(tp); ++ ++ tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | ++ HOSTCC_MODE_NOW); ++ ++ for (i = 0; i < 5; i++) { ++ int_mbox = tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); ++ if (int_mbox != 0) ++ break; ++ msleep(10); ++ } ++ ++ tg3_disable_ints(tp); ++ ++ free_irq(tp->pdev->irq, dev); ++ ++ if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) ++ err = request_irq(tp->pdev->irq, tg3_msi, ++ SA_SAMPLE_RANDOM, dev->name, dev); ++ else ++ err = request_irq(tp->pdev->irq, tg3_interrupt, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); ++ ++ if (err) ++ return err; ++ ++ if (int_mbox != 0) ++ return 0; ++ ++ return -EIO; ++} ++ ++/* Returns 0 if MSI test succeeds or MSI test fails and INTx mode is ++ * successfully restored ++ */ ++static int tg3_test_msi(struct tg3 *tp) ++{ ++ struct net_device *dev = tp->dev; ++ int err; ++ u16 pci_cmd; ++ ++ if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSI)) ++ return 0; ++ ++ /* Turn off SERR reporting in case MSI terminates with Master ++ * Abort. ++ */ ++ pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); ++ pci_write_config_word(tp->pdev, PCI_COMMAND, ++ pci_cmd & ~PCI_COMMAND_SERR); ++ ++ err = tg3_test_interrupt(tp); ++ ++ pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); ++ ++ if (!err) ++ return 0; ++ ++ /* other failures */ ++ if (err != -EIO) ++ return err; ++ ++ /* MSI test failed, go back to INTx mode */ ++ printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " ++ "switching to INTx mode. Please report this failure to " ++ "the PCI maintainer and include system chipset information.\n", ++ tp->dev->name); ++ ++ free_irq(tp->pdev->irq, dev); ++ pci_disable_msi(tp->pdev); ++ ++ tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; ++ ++ err = request_irq(tp->pdev->irq, tg3_interrupt, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); ++ ++ if (err) ++ return err; ++ ++ /* Need to reset the chip because the MSI cycle may have terminated ++ * with Master Abort. ++ */ ++ spin_lock_irq(&tp->lock); ++ spin_lock(&tp->tx_lock); ++ ++ tg3_halt(tp, 1); ++ err = tg3_init_hw(tp); ++ ++ spin_unlock(&tp->tx_lock); ++ spin_unlock_irq(&tp->lock); ++ ++ if (err) ++ free_irq(tp->pdev->irq, dev); ++ ++ return err; ++} ++ ++static int tg3_open(struct net_device *dev) ++{ ++ struct tg3 *tp = netdev_priv(dev); ++ int err; ++ + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); + +@@ -5536,17 +5939,36 @@ static int tg3_open(struct net_device *d + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + +- /* If you move this call, make sure TG3_FLAG_HOST_TXDS in +- * tp->tg3_flags is accurate at that new place. ++ /* The placement of this call is tied ++ * to the setup and use of Host TX descriptors. + */ + err = tg3_alloc_consistent(tp); + if (err) + return err; + +- err = request_irq(dev->irq, tg3_interrupt, +- SA_SHIRQ, dev->name, dev); ++ if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && ++ (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) && ++ (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) { ++ if (pci_enable_msi(tp->pdev) == 0) { ++ u32 msi_mode; ++ ++ msi_mode = tr32(MSGINT_MODE); ++ tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); ++ tp->tg3_flags2 |= TG3_FLG2_USING_MSI; ++ } ++ } ++ if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) ++ err = request_irq(tp->pdev->irq, tg3_msi, ++ SA_SAMPLE_RANDOM, dev->name, dev); ++ else ++ err = request_irq(tp->pdev->irq, tg3_interrupt, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); + + if (err) { ++ if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { ++ pci_disable_msi(tp->pdev); ++ tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; ++ } + tg3_free_consistent(tp); + return err; + } +@@ -5556,7 +5978,7 @@ static int tg3_open(struct net_device *d + + err = tg3_init_hw(tp); + if (err) { +- tg3_halt(tp); ++ tg3_halt(tp, 1); + tg3_free_rings(tp); + } else { + tp->timer_offset = HZ / 10; +@@ -5567,23 +5989,47 @@ static int tg3_open(struct net_device *d + tp->timer.expires = jiffies + tp->timer_offset; + tp->timer.data = (unsigned long) tp; + tp->timer.function = tg3_timer; +- add_timer(&tp->timer); +- +- tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; + } + + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + + if (err) { +- free_irq(dev->irq, dev); ++ free_irq(tp->pdev->irq, dev); ++ if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { ++ pci_disable_msi(tp->pdev); ++ tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; ++ } + tg3_free_consistent(tp); + return err; + } + ++ if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { ++ err = tg3_test_msi(tp); ++ if (err) { ++ spin_lock_irq(&tp->lock); ++ spin_lock(&tp->tx_lock); ++ ++ if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { ++ pci_disable_msi(tp->pdev); ++ tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; ++ } ++ tg3_halt(tp, 1); ++ tg3_free_rings(tp); ++ tg3_free_consistent(tp); ++ ++ spin_unlock(&tp->tx_lock); ++ spin_unlock_irq(&tp->lock); ++ ++ return err; ++ } ++ } ++ + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); + ++ add_timer(&tp->timer); ++ tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; + tg3_enable_ints(tp); + + spin_unlock(&tp->tx_lock); +@@ -5841,7 +6287,7 @@ static int tg3_close(struct net_device * + + tg3_disable_ints(tp); + +- tg3_halt(tp); ++ tg3_halt(tp, 1); + tg3_free_rings(tp); + tp->tg3_flags &= + ~(TG3_FLAG_INIT_COMPLETE | +@@ -5851,7 +6297,11 @@ static int tg3_close(struct net_device * + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + +- free_irq(dev->irq, dev); ++ free_irq(tp->pdev->irq, dev); ++ if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { ++ pci_disable_msi(tp->pdev); ++ tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; ++ } + + memcpy(&tp->net_stats_prev, tg3_get_stats(tp->dev), + sizeof(tp->net_stats_prev)); +@@ -5879,16 +6329,18 @@ static unsigned long calc_crc_errors(str + { + struct tg3_hw_stats *hw_stats = tp->hw_stats; + +- if (tp->phy_id != PHY_ID_SERDES && ++ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { + unsigned long flags; + u32 val; + + spin_lock_irqsave(&tp->lock, flags); +- tg3_readphy(tp, 0x1e, &val); +- tg3_writephy(tp, 0x1e, val | 0x8000); +- tg3_readphy(tp, 0x14, &val); ++ if (!tg3_readphy(tp, 0x1e, &val)) { ++ tg3_writephy(tp, 0x1e, val | 0x8000); ++ tg3_readphy(tp, 0x14, &val); ++ } else ++ val = 0; + spin_unlock_irqrestore(&tp->lock, flags); + + tp->phy_crc_errors += val; +@@ -6152,7 +6604,9 @@ static void tg3_set_rx_mode(struct net_d + struct tg3 *tp = netdev_priv(dev); + + spin_lock_irq(&tp->lock); ++ spin_lock(&tp->tx_lock); + __tg3_set_rx_mode(dev); ++ spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + } + +@@ -6232,14 +6686,16 @@ do { p = (u32 *)(orig_p + (reg)); \ + + static int tg3_get_eeprom_len(struct net_device *dev) + { +- return EEPROM_CHIP_SIZE; ++ struct tg3 *tp = netdev_priv(dev); ++ ++ return tp->nvram_size; + } + +-static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp, +- u32 offset, u32 *val); ++static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val); ++ + static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) + { +- struct tg3 *tp = dev->priv; ++ struct tg3 *tp = netdev_priv(dev); + int ret; + u8 *pd; + u32 i, offset, len, val, b_offset, b_count; +@@ -6248,10 +6704,7 @@ static int tg3_get_eeprom(struct net_dev + len = eeprom->len; + eeprom->len = 0; + +- ret = tg3_nvram_read_using_eeprom(tp, 0, &eeprom->magic); +- if (ret) +- return ret; +- eeprom->magic = swab32(eeprom->magic); ++ eeprom->magic = TG3_EEPROM_MAGIC; + + if (offset & 3) { + /* adjustments to start on required 4 byte boundary */ +@@ -6261,9 +6714,10 @@ static int tg3_get_eeprom(struct net_dev + /* i.e. offset=1 len=2 */ + b_count = len; + } +- ret = tg3_nvram_read_using_eeprom(tp, offset-b_offset, &val); ++ ret = tg3_nvram_read(tp, offset-b_offset, &val); + if (ret) + return ret; ++ val = cpu_to_le32(val); + memcpy(data, ((char*)&val) + b_offset, b_count); + len -= b_count; + offset += b_count; +@@ -6273,12 +6727,13 @@ static int tg3_get_eeprom(struct net_dev + /* read bytes upto the last 4 byte boundary */ + pd = &data[eeprom->len]; + for (i = 0; i < (len - (len & 3)); i += 4) { +- ret = tg3_nvram_read_using_eeprom(tp, offset + i, +- (u32*)(pd + i)); ++ ret = tg3_nvram_read(tp, offset + i, &val); + if (ret) { + eeprom->len += i; + return ret; + } ++ val = cpu_to_le32(val); ++ memcpy(pd + i, &val, 4); + } + eeprom->len += i; + +@@ -6287,30 +6742,85 @@ static int tg3_get_eeprom(struct net_dev + pd = &data[eeprom->len]; + b_count = len & 3; + b_offset = offset + len - b_count; +- ret = tg3_nvram_read_using_eeprom(tp, b_offset, &val); ++ ret = tg3_nvram_read(tp, b_offset, &val); + if (ret) + return ret; ++ val = cpu_to_le32(val); + memcpy(pd, ((char*)&val), b_count); + eeprom->len += b_count; + } + return 0; + } + ++static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); ++ ++static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) ++{ ++ struct tg3 *tp = netdev_priv(dev); ++ int ret; ++ u32 offset, len, b_offset, odd_len, start, end; ++ u8 *buf; ++ ++ if (eeprom->magic != TG3_EEPROM_MAGIC) ++ return -EINVAL; ++ ++ offset = eeprom->offset; ++ len = eeprom->len; ++ ++ if ((b_offset = (offset & 3))) { ++ /* adjustments to start on required 4 byte boundary */ ++ ret = tg3_nvram_read(tp, offset-b_offset, &start); ++ if (ret) ++ return ret; ++ start = cpu_to_le32(start); ++ len += b_offset; ++ offset &= ~3; ++ if (len < 4) ++ len = 4; ++ } ++ ++ odd_len = 0; ++ if (len & 3) { ++ /* adjustments to end on required 4 byte boundary */ ++ odd_len = 1; ++ len = (len + 3) & ~3; ++ ret = tg3_nvram_read(tp, offset+len-4, &end); ++ if (ret) ++ return ret; ++ end = cpu_to_le32(end); ++ } ++ ++ buf = data; ++ if (b_offset || odd_len) { ++ buf = kmalloc(len, GFP_KERNEL); ++ if (buf == 0) ++ return -ENOMEM; ++ if (b_offset) ++ memcpy(buf, &start, 4); ++ if (odd_len) ++ memcpy(buf+len-4, &end, 4); ++ memcpy(buf + b_offset, data, eeprom->len); ++ } ++ ++ ret = tg3_nvram_write_block(tp, offset, len, buf); ++ ++ if (buf != data) ++ kfree(buf); ++ ++ return ret; ++} ++ + static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct tg3 *tp = netdev_priv(dev); + +- if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || +- tp->link_config.phy_is_low_power) +- return -EAGAIN; +- + cmd->supported = (SUPPORTED_Autoneg); + + if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) + cmd->supported |= (SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full); + +- if (tp->phy_id != PHY_ID_SERDES) ++ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) + cmd->supported |= (SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_10baseT_Half | +@@ -6320,8 +6830,10 @@ static int tg3_get_settings(struct net_d + cmd->supported |= SUPPORTED_FIBRE; + + cmd->advertising = tp->link_config.advertising; +- cmd->speed = tp->link_config.active_speed; +- cmd->duplex = tp->link_config.active_duplex; ++ if (netif_running(dev)) { ++ cmd->speed = tp->link_config.active_speed; ++ cmd->duplex = tp->link_config.active_duplex; ++ } + cmd->port = 0; + cmd->phy_address = PHY_ADDR; + cmd->transceiver = 0; +@@ -6335,11 +6847,7 @@ static int tg3_set_settings(struct net_d + { + struct tg3 *tp = netdev_priv(dev); + +- if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || +- tp->link_config.phy_is_low_power) +- return -EAGAIN; +- +- if (tp->phy_id == PHY_ID_SERDES) { ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { + /* These are the only valid advertisement bits allowed. */ + if (cmd->autoneg == AUTONEG_ENABLE && + (cmd->advertising & ~(ADVERTISED_1000baseT_Half | +@@ -6363,7 +6871,9 @@ static int tg3_set_settings(struct net_d + tp->link_config.duplex = cmd->duplex; + } + +- tg3_setup_phy(tp, 1); ++ if (netif_running(dev)) ++ tg3_setup_phy(tp, 1); ++ + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + +@@ -6397,7 +6907,7 @@ static int tg3_set_wol(struct net_device + if (wol->wolopts & ~WAKE_MAGIC) + return -EINVAL; + if ((wol->wolopts & WAKE_MAGIC) && +- tp->phy_id == PHY_ID_SERDES && ++ tp->tg3_flags2 & TG3_FLG2_PHY_SERDES && + !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) + return -EINVAL; + +@@ -6443,11 +6953,14 @@ static int tg3_nway_reset(struct net_dev + u32 bmcr; + int r; + ++ if (!netif_running(dev)) ++ return -EAGAIN; ++ + spin_lock_irq(&tp->lock); +- tg3_readphy(tp, MII_BMCR, &bmcr); +- tg3_readphy(tp, MII_BMCR, &bmcr); + r = -EINVAL; +- if (bmcr & BMCR_ANENABLE) { ++ tg3_readphy(tp, MII_BMCR, &bmcr); ++ if (!tg3_readphy(tp, MII_BMCR, &bmcr) && ++ (bmcr & BMCR_ANENABLE)) { + tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); + r = 0; + } +@@ -6479,7 +6992,9 @@ static int tg3_set_ringparam(struct net_ + (ering->tx_pending > TG3_TX_RING_SIZE - 1)) + return -EINVAL; + +- tg3_netif_stop(tp); ++ if (netif_running(dev)) ++ tg3_netif_stop(tp); ++ + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); + +@@ -6491,12 +7006,14 @@ static int tg3_set_ringparam(struct net_ + tp->rx_jumbo_pending = ering->rx_jumbo_pending; + tp->tx_pending = ering->tx_pending; + +- tg3_halt(tp); +- tg3_init_hw(tp); +- netif_wake_queue(tp->dev); ++ if (netif_running(dev)) { ++ tg3_halt(tp, 1); ++ tg3_init_hw(tp); ++ tg3_netif_start(tp); ++ } ++ + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); +- tg3_netif_start(tp); + + return 0; + } +@@ -6506,15 +7023,17 @@ static void tg3_get_pauseparam(struct ne + struct tg3 *tp = netdev_priv(dev); + + epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0; +- epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0; +- epause->tx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0; ++ epause->rx_pause = (tp->tg3_flags & TG3_FLAG_RX_PAUSE) != 0; ++ epause->tx_pause = (tp->tg3_flags & TG3_FLAG_TX_PAUSE) != 0; + } + + static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) + { + struct tg3 *tp = netdev_priv(dev); + +- tg3_netif_stop(tp); ++ if (netif_running(dev)) ++ tg3_netif_stop(tp); ++ + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); + if (epause->autoneg) +@@ -6522,18 +7041,21 @@ static int tg3_set_pauseparam(struct net + else + tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; + if (epause->rx_pause) +- tp->tg3_flags |= TG3_FLAG_PAUSE_RX; ++ tp->tg3_flags |= TG3_FLAG_RX_PAUSE; + else +- tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX; ++ tp->tg3_flags &= ~TG3_FLAG_RX_PAUSE; + if (epause->tx_pause) +- tp->tg3_flags |= TG3_FLAG_PAUSE_TX; ++ tp->tg3_flags |= TG3_FLAG_TX_PAUSE; + else +- tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX; +- tg3_halt(tp); +- tg3_init_hw(tp); ++ tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE; ++ ++ if (netif_running(dev)) { ++ tg3_halt(tp, 1); ++ tg3_init_hw(tp); ++ tg3_netif_start(tp); ++ } + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); +- tg3_netif_start(tp); + + return 0; + } +@@ -6602,7 +7124,7 @@ static void tg3_get_strings (struct net_ + static void tg3_get_ethtool_stats (struct net_device *dev, + struct ethtool_stats *estats, u64 *tmp_stats) + { +- struct tg3 *tp = dev->priv; ++ struct tg3 *tp = netdev_priv(dev); + memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); + } + +@@ -6620,7 +7142,7 @@ static int tg3_ioctl(struct net_device * + case SIOCGMIIREG: { + u32 mii_regval; + +- if (tp->phy_id == PHY_ID_SERDES) ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + break; /* We have no PHY */ + + spin_lock_irq(&tp->lock); +@@ -6633,7 +7155,7 @@ static int tg3_ioctl(struct net_device * + } + + case SIOCSMIIREG: +- if (tp->phy_id == PHY_ID_SERDES) ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + break; /* We have no PHY */ + + if (!capable(CAP_NET_ADMIN)) +@@ -6696,6 +7218,7 @@ static struct ethtool_ops tg3_ethtool_op + .get_link = ethtool_op_get_link, + .get_eeprom_len = tg3_get_eeprom_len, + .get_eeprom = tg3_get_eeprom, ++ .set_eeprom = tg3_set_eeprom, + .get_ringparam = tg3_get_ringparam, + .set_ringparam = tg3_set_ringparam, + .get_pauseparam = tg3_get_pauseparam, +@@ -6715,12 +7238,170 @@ static struct ethtool_ops tg3_ethtool_op + .get_ethtool_stats = tg3_get_ethtool_stats, + }; + ++static void __devinit tg3_get_eeprom_size(struct tg3 *tp) ++{ ++ u32 cursize, val; ++ ++ tp->nvram_size = EEPROM_CHIP_SIZE; ++ ++ if (tg3_nvram_read(tp, 0, &val) != 0) ++ return; ++ ++ if (swab32(val) != TG3_EEPROM_MAGIC) ++ return; ++ ++ /* ++ * Size the chip by reading offsets at increasing powers of two. ++ * When we encounter our validation signature, we know the addressing ++ * has wrapped around, and thus have our chip size. ++ */ ++ cursize = 0x800; ++ ++ while (cursize < tp->nvram_size) { ++ if (tg3_nvram_read(tp, cursize, &val) != 0) ++ return; ++ ++ if (swab32(val) == TG3_EEPROM_MAGIC) ++ break; ++ ++ cursize <<= 1; ++ } ++ ++ tp->nvram_size = cursize; ++} ++ ++static void __devinit tg3_get_nvram_size(struct tg3 *tp) ++{ ++ u32 val; ++ ++ if (tg3_nvram_read(tp, 0xf0, &val) == 0) { ++ if (val != 0) { ++ tp->nvram_size = (val >> 16) * 1024; ++ return; ++ } ++ } ++ tp->nvram_size = 0x20000; ++} ++ ++static void __devinit tg3_get_nvram_info(struct tg3 *tp) ++{ ++ u32 nvcfg1; ++ ++ nvcfg1 = tr32(NVRAM_CFG1); ++ if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { ++ tp->tg3_flags2 |= TG3_FLG2_FLASH; ++ } ++ else { ++ nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; ++ tw32(NVRAM_CFG1, nvcfg1); ++ } ++ ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { ++ switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) { ++ case FLASH_VENDOR_ATMEL_FLASH_BUFFERED: ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ break; ++ case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED: ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->nvram_pagesize = ATMEL_AT25F512_PAGE_SIZE; ++ break; ++ case FLASH_VENDOR_ATMEL_EEPROM: ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ break; ++ case FLASH_VENDOR_ST: ++ tp->nvram_jedecnum = JEDEC_ST; ++ tp->nvram_pagesize = ST_M45PEX0_PAGE_SIZE; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ break; ++ case FLASH_VENDOR_SAIFUN: ++ tp->nvram_jedecnum = JEDEC_SAIFUN; ++ tp->nvram_pagesize = SAIFUN_SA25F0XX_PAGE_SIZE; ++ break; ++ case FLASH_VENDOR_SST_SMALL: ++ case FLASH_VENDOR_SST_LARGE: ++ tp->nvram_jedecnum = JEDEC_SST; ++ tp->nvram_pagesize = SST_25VF0X0_PAGE_SIZE; ++ break; ++ } ++ } ++ else { ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ } ++} ++ ++static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) ++{ ++ u32 nvcfg1; ++ ++ nvcfg1 = tr32(NVRAM_CFG1); ++ ++ /* NVRAM protection for TPM */ ++ if (nvcfg1 & (1 << 27)) ++ tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; ++ ++ switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { ++ case FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ: ++ case FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ: ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ break; ++ case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ tp->tg3_flags2 |= TG3_FLG2_FLASH; ++ break; ++ case FLASH_5752VENDOR_ST_M45PE10: ++ case FLASH_5752VENDOR_ST_M45PE20: ++ case FLASH_5752VENDOR_ST_M45PE40: ++ tp->nvram_jedecnum = JEDEC_ST; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ tp->tg3_flags2 |= TG3_FLG2_FLASH; ++ break; ++ } ++ ++ if (tp->tg3_flags2 & TG3_FLG2_FLASH) { ++ switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) { ++ case FLASH_5752PAGE_SIZE_256: ++ tp->nvram_pagesize = 256; ++ break; ++ case FLASH_5752PAGE_SIZE_512: ++ tp->nvram_pagesize = 512; ++ break; ++ case FLASH_5752PAGE_SIZE_1K: ++ tp->nvram_pagesize = 1024; ++ break; ++ case FLASH_5752PAGE_SIZE_2K: ++ tp->nvram_pagesize = 2048; ++ break; ++ case FLASH_5752PAGE_SIZE_4K: ++ tp->nvram_pagesize = 4096; ++ break; ++ case FLASH_5752PAGE_SIZE_264: ++ tp->nvram_pagesize = 264; ++ break; ++ } ++ } ++ else { ++ /* For eeprom, set pagesize to maximum eeprom size */ ++ tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; ++ ++ nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; ++ tw32(NVRAM_CFG1, nvcfg1); ++ } ++} ++ + /* Chips other than 5700/5701 use the NVRAM for fetching info. */ + static void __devinit tg3_nvram_init(struct tg3 *tp) + { + int j; + +- if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) ++ if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) + return; + + tw32_f(GRC_EEPROM_ADDR, +@@ -6739,37 +7420,28 @@ static void __devinit tg3_nvram_init(str + + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { +- u32 nvcfg1; +- +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { +- u32 nvaccess = tr32(NVRAM_ACCESS); ++ tp->tg3_flags |= TG3_FLAG_NVRAM; + +- tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); +- } ++ tg3_enable_nvram_access(tp); + +- nvcfg1 = tr32(NVRAM_CFG1); ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) ++ tg3_get_5752_nvram_info(tp); ++ else ++ tg3_get_nvram_info(tp); + +- tp->tg3_flags |= TG3_FLAG_NVRAM; +- if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { +- if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE) +- tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; +- } else { +- nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; +- tw32(NVRAM_CFG1, nvcfg1); +- } ++ tg3_get_nvram_size(tp); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { +- u32 nvaccess = tr32(NVRAM_ACCESS); ++ tg3_disable_nvram_access(tp); + +- tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); +- } + } else { + tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED); ++ ++ tg3_get_eeprom_size(tp); + } + } + +-static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp, +- u32 offset, u32 *val) ++static int tg3_nvram_read_using_eeprom(struct tg3 *tp, ++ u32 offset, u32 *val) + { + u32 tmp; + int i; +@@ -6802,62 +7474,318 @@ static int __devinit tg3_nvram_read_usin + return 0; + } + +-static int __devinit tg3_nvram_read(struct tg3 *tp, +- u32 offset, u32 *val) ++#define NVRAM_CMD_TIMEOUT 10000 ++ ++static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd) + { + int i; + +- if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) { +- printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n"); ++ tw32(NVRAM_CMD, nvram_cmd); ++ for (i = 0; i < NVRAM_CMD_TIMEOUT; i++) { ++ udelay(10); ++ if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) { ++ udelay(10); ++ break; ++ } ++ } ++ if (i == NVRAM_CMD_TIMEOUT) { ++ return -EBUSY; ++ } ++ return 0; ++} ++ ++static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) ++{ ++ int ret; ++ ++ if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { ++ printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n"); + return -EINVAL; + } + + if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) + return tg3_nvram_read_using_eeprom(tp, offset, val); + +- if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) +- offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) << +- NVRAM_BUFFERED_PAGE_POS) + +- (offset % NVRAM_BUFFERED_PAGE_SIZE); ++ if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && ++ (tp->tg3_flags2 & TG3_FLG2_FLASH) && ++ (tp->nvram_jedecnum == JEDEC_ATMEL)) { ++ ++ offset = ((offset / tp->nvram_pagesize) << ++ ATMEL_AT45DB0X1B_PAGE_POS) + ++ (offset % tp->nvram_pagesize); ++ } + + if (offset > NVRAM_ADDR_MSK) + return -EINVAL; + + tg3_nvram_lock(tp); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { +- u32 nvaccess = tr32(NVRAM_ACCESS); ++ tg3_enable_nvram_access(tp); ++ ++ tw32(NVRAM_ADDR, offset); ++ ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_RD | NVRAM_CMD_GO | ++ NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); ++ ++ if (ret == 0) ++ *val = swab32(tr32(NVRAM_RDDATA)); ++ ++ tg3_nvram_unlock(tp); ++ ++ tg3_disable_nvram_access(tp); ++ ++ return ret; ++} ++ ++static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, ++ u32 offset, u32 len, u8 *buf) ++{ ++ int i, j, rc = 0; ++ u32 val; ++ ++ for (i = 0; i < len; i += 4) { ++ u32 addr, data; ++ ++ addr = offset + i; ++ ++ memcpy(&data, buf + i, 4); + +- tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); ++ tw32(GRC_EEPROM_DATA, cpu_to_le32(data)); ++ ++ val = tr32(GRC_EEPROM_ADDR); ++ tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); ++ ++ val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | ++ EEPROM_ADDR_READ); ++ tw32(GRC_EEPROM_ADDR, val | ++ (0 << EEPROM_ADDR_DEVID_SHIFT) | ++ (addr & EEPROM_ADDR_ADDR_MASK) | ++ EEPROM_ADDR_START | ++ EEPROM_ADDR_WRITE); ++ ++ for (j = 0; j < 10000; j++) { ++ val = tr32(GRC_EEPROM_ADDR); ++ ++ if (val & EEPROM_ADDR_COMPLETE) ++ break; ++ udelay(100); ++ } ++ if (!(val & EEPROM_ADDR_COMPLETE)) { ++ rc = -EBUSY; ++ break; ++ } + } + +- tw32(NVRAM_ADDR, offset); +- tw32(NVRAM_CMD, +- NVRAM_CMD_RD | NVRAM_CMD_GO | +- NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); ++ return rc; ++} + +- /* Wait for done bit to clear. */ +- for (i = 0; i < 1000; i++) { +- udelay(10); +- if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) { +- udelay(10); +- *val = swab32(tr32(NVRAM_RDDATA)); ++/* offset and length are dword aligned */ ++static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, ++ u8 *buf) ++{ ++ int ret = 0; ++ u32 pagesize = tp->nvram_pagesize; ++ u32 pagemask = pagesize - 1; ++ u32 nvram_cmd; ++ u8 *tmp; ++ ++ tmp = kmalloc(pagesize, GFP_KERNEL); ++ if (tmp == NULL) ++ return -ENOMEM; ++ ++ while (len) { ++ int j; ++ u32 phy_addr, page_off, size; ++ ++ phy_addr = offset & ~pagemask; ++ ++ for (j = 0; j < pagesize; j += 4) { ++ if ((ret = tg3_nvram_read(tp, phy_addr + j, ++ (u32 *) (tmp + j)))) ++ break; ++ } ++ if (ret) + break; ++ ++ page_off = offset & pagemask; ++ size = pagesize; ++ if (len < size) ++ size = len; ++ ++ len -= size; ++ ++ memcpy(tmp + page_off, buf, size); ++ ++ offset = offset + (pagesize - page_off); ++ ++ tg3_enable_nvram_access(tp); ++ ++ /* ++ * Before we can erase the flash page, we need ++ * to issue a special "write enable" command. ++ */ ++ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; ++ ++ if (tg3_nvram_exec_cmd(tp, nvram_cmd)) ++ break; ++ ++ /* Erase the target page */ ++ tw32(NVRAM_ADDR, phy_addr); ++ ++ nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | ++ NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; ++ ++ if (tg3_nvram_exec_cmd(tp, nvram_cmd)) ++ break; ++ ++ /* Issue another write enable to start the write. */ ++ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; ++ ++ if (tg3_nvram_exec_cmd(tp, nvram_cmd)) ++ break; ++ ++ for (j = 0; j < pagesize; j += 4) { ++ u32 data; ++ ++ data = *((u32 *) (tmp + j)); ++ tw32(NVRAM_WRDATA, cpu_to_be32(data)); ++ ++ tw32(NVRAM_ADDR, phy_addr + j); ++ ++ nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | ++ NVRAM_CMD_WR; ++ ++ if (j == 0) ++ nvram_cmd |= NVRAM_CMD_FIRST; ++ else if (j == (pagesize - 4)) ++ nvram_cmd |= NVRAM_CMD_LAST; ++ ++ if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) ++ break; + } ++ if (ret) ++ break; + } + +- tg3_nvram_unlock(tp); ++ nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; ++ tg3_nvram_exec_cmd(tp, nvram_cmd); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { +- u32 nvaccess = tr32(NVRAM_ACCESS); ++ kfree(tmp); ++ ++ return ret; ++} ++ ++/* offset and length are dword aligned */ ++static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, ++ u8 *buf) ++{ ++ int i, ret = 0; ++ ++ for (i = 0; i < len; i += 4, offset += 4) { ++ u32 data, page_off, phy_addr, nvram_cmd; ++ ++ memcpy(&data, buf + i, 4); ++ tw32(NVRAM_WRDATA, cpu_to_be32(data)); ++ ++ page_off = offset % tp->nvram_pagesize; ++ ++ if ((tp->tg3_flags2 & TG3_FLG2_FLASH) && ++ (tp->nvram_jedecnum == JEDEC_ATMEL)) { ++ ++ phy_addr = ((offset / tp->nvram_pagesize) << ++ ATMEL_AT45DB0X1B_PAGE_POS) + page_off; ++ } ++ else { ++ phy_addr = offset; ++ } ++ ++ tw32(NVRAM_ADDR, phy_addr); ++ ++ nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; ++ ++ if ((page_off == 0) || (i == 0)) ++ nvram_cmd |= NVRAM_CMD_FIRST; ++ else if (page_off == (tp->nvram_pagesize - 4)) ++ nvram_cmd |= NVRAM_CMD_LAST; ++ ++ if (i == (len - 4)) ++ nvram_cmd |= NVRAM_CMD_LAST; ++ ++ if ((tp->nvram_jedecnum == JEDEC_ST) && ++ (nvram_cmd & NVRAM_CMD_FIRST)) { + +- tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); ++ if ((ret = tg3_nvram_exec_cmd(tp, ++ NVRAM_CMD_WREN | NVRAM_CMD_GO | ++ NVRAM_CMD_DONE))) ++ ++ break; ++ } ++ if (!(tp->tg3_flags2 & TG3_FLG2_FLASH)) { ++ /* We always do complete word writes to eeprom. */ ++ nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); ++ } ++ ++ if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) ++ break; + } ++ return ret; ++} + +- if (i >= 1000) +- return -EBUSY; ++/* offset and length are dword aligned */ ++static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) ++{ ++ int ret; + +- return 0; ++ if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { ++ printk(KERN_ERR PFX "Attempt to do nvram_write on Sun 570X\n"); ++ return -EINVAL; ++ } ++ ++ if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { ++ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & ++ ~GRC_LCLCTRL_GPIO_OUTPUT1); ++ udelay(40); ++ } ++ ++ if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) { ++ ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); ++ } ++ else { ++ u32 grc_mode; ++ ++ tg3_nvram_lock(tp); ++ ++ tg3_enable_nvram_access(tp); ++ if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && ++ !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) ++ tw32(NVRAM_WRITE1, 0x406); ++ ++ grc_mode = tr32(GRC_MODE); ++ tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); ++ ++ if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) || ++ !(tp->tg3_flags2 & TG3_FLG2_FLASH)) { ++ ++ ret = tg3_nvram_write_block_buffered(tp, offset, len, ++ buf); ++ } ++ else { ++ ret = tg3_nvram_write_block_unbuffered(tp, offset, len, ++ buf); ++ } ++ ++ grc_mode = tr32(GRC_MODE); ++ tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); ++ ++ tg3_disable_nvram_access(tp); ++ tg3_nvram_unlock(tp); ++ } ++ ++ if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { ++ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); ++ udelay(40); ++ } ++ ++ return ret; + } + + struct subsys_tbl_ent { +@@ -6870,10 +7798,10 @@ static struct subsys_tbl_ent subsys_id_t + { PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */ + { PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */ + { PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */ +- { PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES }, /* BCM95700A9 */ ++ { PCI_VENDOR_ID_BROADCOM, 0x0003, 0 }, /* BCM95700A9 */ + { PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */ + { PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */ +- { PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES }, /* BCM95701A7 */ ++ { PCI_VENDOR_ID_BROADCOM, 0x0007, 0 }, /* BCM95701A7 */ + { PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */ + { PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */ + { PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */ +@@ -6882,7 +7810,7 @@ static struct subsys_tbl_ent subsys_id_t + /* 3com boards. */ + { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */ + { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */ +- { PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES }, /* 3C996SX */ ++ { PCI_VENDOR_ID_3COM, 0x1004, 0 }, /* 3C996SX */ + { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */ + { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */ + +@@ -6895,65 +7823,84 @@ static struct subsys_tbl_ent subsys_id_t + /* Compaq boards. */ + { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */ + { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */ +- { PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES }, /* CHANGELING */ ++ { PCI_VENDOR_ID_COMPAQ, 0x007d, 0 }, /* CHANGELING */ + { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */ + { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */ + + /* IBM boards. */ +- { PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */ ++ { PCI_VENDOR_ID_IBM, 0x0281, 0 } /* IBM??? */ + }; + +-static int __devinit tg3_phy_probe(struct tg3 *tp) ++static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp) + { +- u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2; +- u32 hw_phy_id, hw_phy_id_masked; +- u32 val; +- int i, eeprom_signature_found, err; ++ int i; + +- tp->phy_id = PHY_ID_INVALID; + for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) { + if ((subsys_id_to_phy_id[i].subsys_vendor == + tp->pdev->subsystem_vendor) && + (subsys_id_to_phy_id[i].subsys_devid == +- tp->pdev->subsystem_device)) { +- tp->phy_id = subsys_id_to_phy_id[i].phy_id; +- break; +- } ++ tp->pdev->subsystem_device)) ++ return &subsys_id_to_phy_id[i]; + } ++ return NULL; ++} ++ ++/* Since this function may be called in D3-hot power state during ++ * tg3_init_one(), only config cycles are allowed. ++ */ ++static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) ++{ ++ u32 val; ++ ++ /* Make sure register accesses (indirect or otherwise) ++ * will function correctly. ++ */ ++ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, ++ tp->misc_host_ctrl); ++ ++ tp->phy_id = PHY_ID_INVALID; ++ tp->led_ctrl = LED_CTRL_MODE_PHY_1; + +- eeprom_phy_id = PHY_ID_INVALID; +- eeprom_signature_found = 0; + tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); + if (val == NIC_SRAM_DATA_SIG_MAGIC) { + u32 nic_cfg, led_cfg; ++ u32 nic_phy_id, ver, cfg2 = 0, eeprom_phy_id; ++ int eeprom_phy_serdes = 0; + + tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); + tp->nic_sram_data_cfg = nic_cfg; + +- eeprom_signature_found = 1; ++ tg3_read_mem(tp, NIC_SRAM_DATA_VER, &ver); ++ ver >>= NIC_SRAM_DATA_VER_SHIFT; ++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && ++ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && ++ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703) && ++ (ver > 0) && (ver < 0x100)) ++ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2); + + if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == +- NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) { +- eeprom_phy_id = PHY_ID_SERDES; +- } else { +- u32 nic_phy_id; ++ NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) ++ eeprom_phy_serdes = 1; + +- tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id); +- if (nic_phy_id != 0) { +- u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK; +- u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK; +- +- eeprom_phy_id = (id1 >> 16) << 10; +- eeprom_phy_id |= (id2 & 0xfc00) << 16; +- eeprom_phy_id |= (id2 & 0x03ff) << 0; +- } +- } ++ tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id); ++ if (nic_phy_id != 0) { ++ u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK; ++ u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK; ++ ++ eeprom_phy_id = (id1 >> 16) << 10; ++ eeprom_phy_id |= (id2 & 0xfc00) << 16; ++ eeprom_phy_id |= (id2 & 0x03ff) << 0; ++ } else ++ eeprom_phy_id = 0; ++ ++ tp->phy_id = eeprom_phy_id; ++ if (eeprom_phy_serdes) ++ tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { +- tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg); +- led_cfg &= (NIC_SRAM_DATA_CFG_LED_MODE_MASK | ++ if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) ++ led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK | + SHASTA_EXT_LED_MODE_MASK); +- } else ++ else + led_cfg = nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK; + + switch (led_cfg) { +@@ -6996,20 +7943,34 @@ static int __devinit tg3_phy_probe(struc + tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) + tp->led_ctrl = LED_CTRL_MODE_PHY_2; + +- if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) || +- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || +- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) && ++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && ++ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && + (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) + tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; + + if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { + tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) + tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; + } + if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL) + tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP; ++ ++ if (cfg2 & (1 << 17)) ++ tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING; ++ ++ /* serdes signal pre-emphasis in register 0x590 set by */ ++ /* bootcode if bit 18 is set */ ++ if (cfg2 & (1 << 18)) ++ tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS; + } ++} ++ ++static int __devinit tg3_phy_probe(struct tg3 *tp) ++{ ++ u32 hw_phy_id_1, hw_phy_id_2; ++ u32 hw_phy_id, hw_phy_id_masked; ++ int err; + + /* Reading the PHY ID register can conflict with ASF + * firwmare access to the PHY hardware. +@@ -7035,27 +7996,37 @@ static int __devinit tg3_phy_probe(struc + + if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) { + tp->phy_id = hw_phy_id; ++ if (hw_phy_id_masked == PHY_ID_BCM8002) ++ tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + } else { +- /* phy_id currently holds the value found in the +- * subsys_id_to_phy_id[] table or PHY_ID_INVALID +- * if a match was not found there. +- */ +- if (tp->phy_id == PHY_ID_INVALID) { +- if (!eeprom_signature_found || +- !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK)) ++ if (tp->phy_id != PHY_ID_INVALID) { ++ /* Do nothing, phy ID already set up in ++ * tg3_get_eeprom_hw_cfg(). ++ */ ++ } else { ++ struct subsys_tbl_ent *p; ++ ++ /* No eeprom signature? Try the hardcoded ++ * subsys device table. ++ */ ++ p = lookup_by_subsys(tp); ++ if (!p) + return -ENODEV; +- tp->phy_id = eeprom_phy_id; ++ ++ tp->phy_id = p->phy_id; ++ if (!tp->phy_id || ++ tp->phy_id == PHY_ID_BCM8002) ++ tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + } + } + +- if (tp->phy_id != PHY_ID_SERDES && ++ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { + u32 bmsr, adv_reg, tg3_ctrl; + + tg3_readphy(tp, MII_BMSR, &bmsr); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- +- if (bmsr & BMSR_LSTATUS) ++ if (!tg3_readphy(tp, MII_BMSR, &bmsr) && ++ (bmsr & BMSR_LSTATUS)) + goto skip_phy_reset; + + err = tg3_phy_reset(tp); +@@ -7102,10 +8073,7 @@ skip_phy_reset: + err = tg3_init_5401phy_dsp(tp); + } + +- if (!eeprom_signature_found) +- tp->led_ctrl = LED_CTRL_MODE_PHY_1; +- +- if (tp->phy_id == PHY_ID_SERDES) ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + tp->link_config.advertising = + (ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | +@@ -7124,11 +8092,11 @@ static void __devinit tg3_read_partno(st + unsigned char vpd_data[256]; + int i; + +- if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) { ++ if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { + /* Sun decided not to put the necessary bits in the + * NVRAM of their onboard tg3 parts :( + */ +- strcpy(tp->board_part_number, "Sun 5704"); ++ strcpy(tp->board_part_number, "Sun 570X"); + return; + } + +@@ -7189,27 +8157,21 @@ out_not_found: + } + + #ifdef CONFIG_SPARC64 +-static int __devinit tg3_is_sun_5704(struct tg3 *tp) ++static int __devinit tg3_is_sun_570X(struct tg3 *tp) + { + struct pci_dev *pdev = tp->pdev; + struct pcidev_cookie *pcp = pdev->sysdata; + + if (pcp != NULL) { + int node = pcp->prom_node; +- u32 venid, devid; ++ u32 venid; + int err; + + err = prom_getproperty(node, "subsystem-vendor-id", + (char *) &venid, sizeof(venid)); + if (err == 0 || err == -1) + return 0; +- err = prom_getproperty(node, "subsystem-id", +- (char *) &devid, sizeof(devid)); +- if (err == 0 || err == -1) +- return 0; +- +- if (venid == PCI_VENDOR_ID_SUN && +- devid == PCI_DEVICE_ID_TIGON3_5704) ++ if (venid == PCI_VENDOR_ID_SUN) + return 1; + } + return 0; +@@ -7218,6 +8180,19 @@ static int __devinit tg3_is_sun_5704(str + + static int __devinit tg3_get_invariants(struct tg3 *tp) + { ++ static struct pci_device_id write_reorder_chipsets[] = { ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, ++ PCI_DEVICE_ID_INTEL_82801AA_8) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, ++ PCI_DEVICE_ID_INTEL_82801AB_8) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, ++ PCI_DEVICE_ID_INTEL_82801BA_11) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, ++ PCI_DEVICE_ID_INTEL_82801BA_6) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, ++ PCI_DEVICE_ID_AMD_FE_GATE_700C) }, ++ { }, ++ }; + u32 misc_ctrl_reg; + u32 cacheline_sz_reg; + u32 pci_state_reg, grc_misc_cfg; +@@ -7226,8 +8201,8 @@ static int __devinit tg3_get_invariants( + int err; + + #ifdef CONFIG_SPARC64 +- if (tg3_is_sun_5704(tp)) +- tp->tg3_flags2 |= TG3_FLG2_SUN_5704; ++ if (tg3_is_sun_570X(tp)) ++ tp->tg3_flags2 |= TG3_FLG2_SUN_570X; + #endif + + /* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write +@@ -7236,16 +8211,7 @@ static int __devinit tg3_get_invariants( + * every mailbox register write to force the writes to be + * posted to the chip in order. + */ +- if (pci_find_device(PCI_VENDOR_ID_INTEL, +- PCI_DEVICE_ID_INTEL_82801AA_8, NULL) || +- pci_find_device(PCI_VENDOR_ID_INTEL, +- PCI_DEVICE_ID_INTEL_82801AB_8, NULL) || +- pci_find_device(PCI_VENDOR_ID_INTEL, +- PCI_DEVICE_ID_INTEL_82801BA_11, NULL) || +- pci_find_device(PCI_VENDOR_ID_INTEL, +- PCI_DEVICE_ID_INTEL_82801BA_6, NULL) || +- pci_find_device(PCI_VENDOR_ID_AMD, +- PCI_DEVICE_ID_AMD_FE_GATE_700C, NULL)) ++ if (pci_dev_present(write_reorder_chipsets)) + tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; + + /* Force memory write invalidate off. If we leave it on, +@@ -7271,6 +8237,12 @@ static int __devinit tg3_get_invariants( + tp->pci_chip_rev_id = (misc_ctrl_reg >> + MISC_HOST_CTRL_CHIPREV_SHIFT); + ++ /* Wrong chip ID in 5752 A0. This code can be removed later ++ * as A0 is not in production. ++ */ ++ if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW) ++ tp->pci_chip_rev_id = CHIPREV_ID_5752_A0; ++ + /* Initialize misc host control in PCI block. */ + tp->misc_host_ctrl |= (misc_ctrl_reg & + MISC_HOST_CTRL_CHIPREV); +@@ -7285,6 +8257,17 @@ static int __devinit tg3_get_invariants( + tp->pci_hdr_type = (cacheline_sz_reg >> 16) & 0xff; + tp->pci_bist = (cacheline_sz_reg >> 24) & 0xff; + ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || ++ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) ++ tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; ++ ++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) || ++ (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) ++ tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; ++ ++ if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) ++ tp->tg3_flags2 |= TG3_FLG2_HW_TSO; ++ + if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) + tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; + +@@ -7360,6 +8343,31 @@ static int __devinit tg3_get_invariants( + pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg); + } + ++ /* Get eeprom hw config before calling tg3_set_power_state(). ++ * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be ++ * determined before calling tg3_set_power_state() so that ++ * we know whether or not to switch out of Vaux power. ++ * When the flag is set, it means that GPIO1 is used for eeprom ++ * write protect and also implies that it is a LOM where GPIOs ++ * are not used to switch power. ++ */ ++ tg3_get_eeprom_hw_cfg(tp); ++ ++ /* Set up tp->grc_local_ctrl before calling tg3_set_power_state(). ++ * GPIO1 driven high will bring 5700's external PHY out of reset. ++ * It is also used as eeprom write protect on LOMs. ++ */ ++ tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM; ++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) || ++ (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)) ++ tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | ++ GRC_LCLCTRL_GPIO_OUTPUT1); ++ /* Unused GPIO3 must be driven as output on 5752 because there ++ * are no pull-up resistors on unused GPIO pins. ++ */ ++ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) ++ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; ++ + /* Force the chip into D0. */ + err = tg3_set_power_state(tp, 0); + if (err) { +@@ -7412,8 +8420,7 @@ static int __devinit tg3_get_invariants( + if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) + tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; + + /* Only 5701 and later support tagged irq status mode. +@@ -7453,7 +8460,7 @@ static int __devinit tg3_get_invariants( + chiprevid == CHIPREV_ID_5701_B0 || + chiprevid == CHIPREV_ID_5701_B2 || + chiprevid == CHIPREV_ID_5701_B5) { +- unsigned long sram_base; ++ void __iomem *sram_base; + + /* Write some dummy words into the SRAM status block + * area, see if it reads back correctly. If the return +@@ -7472,32 +8479,17 @@ static int __devinit tg3_get_invariants( + udelay(50); + tg3_nvram_init(tp); + +- /* Always use host TXDs, it performs better in particular +- * with multi-frag packets. The tests below are kept here +- * as documentation should we change this decision again +- * in the future. +- */ +- tp->tg3_flags |= TG3_FLAG_HOST_TXDS; +- +-#if 0 +- /* Determine if TX descriptors will reside in +- * main memory or in the chip SRAM. +- */ +- if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) +- tp->tg3_flags |= TG3_FLAG_HOST_TXDS; +-#endif +- + grc_misc_cfg = tr32(GRC_MISC_CFG); + grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK; + ++ /* Broadcom's driver says that CIOBE multisplit has a bug */ ++#if 0 + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && + grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) { + tp->tg3_flags |= TG3_FLAG_SPLIT_MODE; + tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ; + } +- ++#endif + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && + (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || + grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) +@@ -7512,7 +8504,8 @@ static int __devinit tg3_get_invariants( + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 || + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || + (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && +- tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F)) ++ (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F || ++ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F))) + tp->tg3_flags |= TG3_FLAG_10_100_ONLY; + + err = tg3_phy_probe(tp); +@@ -7524,7 +8517,7 @@ static int __devinit tg3_get_invariants( + + tg3_read_partno(tp); + +- if (tp->phy_id == PHY_ID_SERDES) { ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { + tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; + } else { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) +@@ -7547,13 +8540,13 @@ static int __devinit tg3_get_invariants( + * upon subsystem IDs. + */ + if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && +- tp->phy_id != PHY_ID_SERDES) { ++ !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT | + TG3_FLAG_USE_LINKCHG_REG); + } + + /* For all SERDES we poll the MAC status register. */ +- if (tp->phy_id == PHY_ID_SERDES) ++ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + tp->tg3_flags |= TG3_FLAG_POLL_SERDES; + else + tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; +@@ -7624,7 +8617,7 @@ static int __devinit tg3_get_device_addr + + mac_offset = 0x7c; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && +- !(tp->tg3_flags & TG3_FLG2_SUN_5704)) { ++ !(tp->tg3_flags & TG3_FLG2_SUN_570X)) { + if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) + mac_offset = 0xcc; + if (tg3_nvram_lock(tp)) +@@ -7646,7 +8639,7 @@ static int __devinit tg3_get_device_addr + dev->dev_addr[5] = (lo >> 0) & 0xff; + } + /* Next, try NVRAM. */ +- else if (!(tp->tg3_flags & TG3_FLG2_SUN_5704) && ++ else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) && + !tg3_nvram_read(tp, mac_offset + 0, &hi) && + !tg3_nvram_read(tp, mac_offset + 4, &lo)) { + dev->dev_addr[0] = ((hi >> 16) & 0xff); +@@ -7819,7 +8812,8 @@ static int __devinit tg3_test_dma(struct + #endif + + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { +- tp->dma_rwctrl |= 0x001f0000; ++ /* DMA read watermark not used on PCIE */ ++ tp->dma_rwctrl |= 0x00180000; + } else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) +@@ -7988,8 +8982,9 @@ static char * __devinit tg3_phy_string(s + case PHY_ID_BCM5704: return "5704"; + case PHY_ID_BCM5705: return "5705"; + case PHY_ID_BCM5750: return "5750"; +- case PHY_ID_BCM8002: return "8002"; +- case PHY_ID_SERDES: return "serdes"; ++ case PHY_ID_BCM5752: return "5752"; ++ case PHY_ID_BCM8002: return "8002/serdes"; ++ case 0: return "serdes"; + default: return "unknown"; + }; + } +@@ -8096,6 +9091,7 @@ static int __devinit tg3_init_one(struct + + if (pci_using_dac) + dev->features |= NETIF_F_HIGHDMA; ++ dev->features |= NETIF_F_LLTX; + #if TG3_VLAN_TAG_USED + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_rx_register = tg3_vlan_rx_register; +@@ -8141,7 +9137,7 @@ static int __devinit tg3_init_one(struct + spin_lock_init(&tp->indirect_lock); + INIT_WORK(&tp->reset_task, tg3_reset_task, tp); + +- tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len); ++ tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len); + if (tp->regs == 0UL) { + printk(KERN_ERR PFX "Cannot map device registers, " + "aborting.\n"); +@@ -8181,8 +9177,7 @@ static int __devinit tg3_init_one(struct + goto err_out_iounmap; + } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || +- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { ++ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + tp->bufmgr_config.mbuf_read_dma_low_water = + DEFAULT_MB_RDMA_LOW_WATER_5705; + tp->bufmgr_config.mbuf_mac_rx_low_water = +@@ -8192,11 +9187,13 @@ static int __devinit tg3_init_one(struct + } + + #if TG3_TSO_SUPPORT != 0 +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { ++ tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; ++ } ++ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || + tp->pci_chip_rev_id == CHIPREV_ID_5705_A0 || +- ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)) { ++ (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) { + tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; + } else { + tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; +@@ -8236,7 +9233,7 @@ static int __devinit tg3_init_one(struct + (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { + pci_save_state(tp->pdev, tp->pci_cfg_state); + tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); +- tg3_halt(tp); ++ tg3_halt(tp, 1); + } + + err = tg3_test_dma(tp); +@@ -8257,6 +9254,9 @@ static int __devinit tg3_init_one(struct + if (tp->tg3_flags2 & TG3_FLG2_IS_5788) + dev->features &= ~NETIF_F_HIGHDMA; + ++ /* flow control autonegotiation is default behavior */ ++ tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; ++ + err = register_netdev(dev); + if (err) { + printk(KERN_ERR PFX "Cannot register net device, " +@@ -8288,11 +9288,10 @@ static int __devinit tg3_init_one(struct + printk("%2.2x%c", dev->dev_addr[i], + i == 5 ? '\n' : ':'); + +- printk(KERN_INFO "%s: HostTXDS[%d] RXcsums[%d] LinkChgREG[%d] " ++ printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] " + "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] " + "TSOcap[%d] \n", + dev->name, +- (tp->tg3_flags & TG3_FLAG_HOST_TXDS) != 0, + (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0, + (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, + (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0, +@@ -8304,7 +9303,7 @@ static int __devinit tg3_init_one(struct + return 0; + + err_out_iounmap: +- iounmap((void *) tp->regs); ++ iounmap(tp->regs); + + err_out_free_dev: + free_netdev(dev); +@@ -8326,7 +9325,7 @@ static void __devexit tg3_remove_one(str + struct tg3 *tp = netdev_priv(dev); + + unregister_netdev(dev); +- iounmap((void *)tp->regs); ++ iounmap(tp->regs); + free_netdev(dev); + pci_release_regions(pdev); + pci_disable_device(pdev); +@@ -8334,7 +9333,7 @@ static void __devexit tg3_remove_one(str + } + } + +-static int tg3_suspend(struct pci_dev *pdev, u32 state) ++static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) + { + struct net_device *dev = pci_get_drvdata(pdev); + struct tg3 *tp = netdev_priv(dev); +@@ -8357,11 +9356,11 @@ static int tg3_suspend(struct pci_dev *p + + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); +- tg3_halt(tp); ++ tg3_halt(tp, 1); + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + +- err = tg3_set_power_state(tp, state); ++ err = tg3_set_power_state(tp, pci_choose_state(pdev, state)); + if (err) { + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); +@@ -8371,11 +9370,11 @@ static int tg3_suspend(struct pci_dev *p + tp->timer.expires = jiffies + tp->timer_offset; + add_timer(&tp->timer); + +- spin_unlock(&tp->tx_lock); +- spin_unlock_irq(&tp->lock); +- + netif_device_attach(dev); + tg3_netif_start(tp); ++ ++ spin_unlock(&tp->tx_lock); ++ spin_unlock_irq(&tp->lock); + } + + return err; +@@ -8408,11 +9407,11 @@ static int tg3_resume(struct pci_dev *pd + + tg3_enable_ints(tp); + ++ tg3_netif_start(tp); ++ + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + +- tg3_netif_start(tp); +- + return 0; + } + +--- linux-2.6.8.1-t043-libata-update//drivers/net/tg3_compat.h 1970-01-01 03:00:00.000000000 +0300 ++++ rhel4u2//drivers/net/tg3_compat.h 2005-10-19 11:47:13.000000000 +0400 +@@ -0,0 +1,41 @@ ++#ifndef __TG3_COMPAT_H__ ++#define __TG3_COMPAT_H__ ++ ++#define skb_header_cloned(skb) 0 ++ ++#define pci_choose_state(pdev, state) (state) ++ ++typedef u32 pm_message_t; ++ ++#ifndef ADVERTISE_PAUSE ++#define ADVERTISE_PAUSE_CAP 0x0400 ++#endif ++#ifndef ADVERTISE_PAUSE_ASYM ++#define ADVERTISE_PAUSE_ASYM 0x0800 ++#endif ++#ifndef LPA_PAUSE ++#define LPA_PAUSE_CAP 0x0400 ++#endif ++#ifndef LPA_PAUSE_ASYM ++#define LPA_PAUSE_ASYM 0x0800 ++#endif ++ ++/** ++ * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not. ++ * @ids: A pointer to a null terminated list of struct pci_device_id structures ++ * that describe the type of PCI device the caller is trying to find. ++ * ++ * This is a cheap knock-off, just to help in back-porting tg3 from ++ * later kernels...beware of changes in usage... ++ */ ++static inline int pci_dev_present(const struct pci_device_id *ids) ++{ ++ const struct pci_device_id *dev; ++ ++ for (dev = ids; dev->vendor; dev++) { ++ if (pci_find_device(dev->vendor, dev->device, NULL)) ++ return 1; ++ } ++ return 0; ++} ++#endif /* __TG3_COMPAT_H__ */ +--- linux-2.6.8.1-t043-libata-update//drivers/net/tg3.h 2005-10-20 17:56:53.000000000 +0400 ++++ rhel4u2//drivers/net/tg3.h 2005-10-19 11:47:13.000000000 +0400 +@@ -124,6 +124,10 @@ + #define CHIPREV_ID_5705_A3 0x3003 + #define CHIPREV_ID_5750_A0 0x4000 + #define CHIPREV_ID_5750_A1 0x4001 ++#define CHIPREV_ID_5750_A3 0x4003 ++#define CHIPREV_ID_5752_A0_HW 0x5000 ++#define CHIPREV_ID_5752_A0 0x6000 ++#define CHIPREV_ID_5752_A1 0x6001 + #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) + #define ASIC_REV_5700 0x07 + #define ASIC_REV_5701 0x00 +@@ -131,6 +135,7 @@ + #define ASIC_REV_5704 0x02 + #define ASIC_REV_5705 0x03 + #define ASIC_REV_5750 0x04 ++#define ASIC_REV_5752 0x06 + #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) + #define CHIPREV_5700_AX 0x70 + #define CHIPREV_5700_BX 0x71 +@@ -139,6 +144,8 @@ + #define CHIPREV_5703_AX 0x10 + #define CHIPREV_5704_AX 0x20 + #define CHIPREV_5704_BX 0x21 ++#define CHIPREV_5750_AX 0x40 ++#define CHIPREV_5750_BX 0x41 + #define GET_METAL_REV(CHIP_REV_ID) ((CHIP_REV_ID) & 0xff) + #define METAL_REV_A0 0x00 + #define METAL_REV_A1 0x01 +@@ -1273,6 +1280,7 @@ + #define GRC_MODE_HOST_STACKUP 0x00010000 + #define GRC_MODE_HOST_SENDBDS 0x00020000 + #define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000 ++#define GRC_MODE_NVRAM_WR_ENABLE 0x00200000 + #define GRC_MODE_NO_RX_PHDR_CSUM 0x00800000 + #define GRC_MODE_IRQ_ON_TX_CPU_ATTN 0x01000000 + #define GRC_MODE_IRQ_ON_RX_CPU_ATTN 0x02000000 +@@ -1303,6 +1311,9 @@ + #define GRC_LCLCTRL_CLEARINT 0x00000002 + #define GRC_LCLCTRL_SETINT 0x00000004 + #define GRC_LCLCTRL_INT_ON_ATTN 0x00000008 ++#define GRC_LCLCTRL_GPIO_INPUT3 0x00000020 ++#define GRC_LCLCTRL_GPIO_OE3 0x00000040 ++#define GRC_LCLCTRL_GPIO_OUTPUT3 0x00000080 + #define GRC_LCLCTRL_GPIO_INPUT0 0x00000100 + #define GRC_LCLCTRL_GPIO_INPUT1 0x00000200 + #define GRC_LCLCTRL_GPIO_INPUT2 0x00000400 +@@ -1365,6 +1376,8 @@ + #define NVRAM_CMD_ERASE 0x00000040 + #define NVRAM_CMD_FIRST 0x00000080 + #define NVRAM_CMD_LAST 0x00000100 ++#define NVRAM_CMD_WREN 0x00010000 ++#define NVRAM_CMD_WRDI 0x00020000 + #define NVRAM_STAT 0x00007004 + #define NVRAM_WRDATA 0x00007008 + #define NVRAM_ADDR 0x0000700c +@@ -1374,8 +1387,32 @@ + #define NVRAM_CFG1_FLASHIF_ENAB 0x00000001 + #define NVRAM_CFG1_BUFFERED_MODE 0x00000002 + #define NVRAM_CFG1_PASS_THRU 0x00000004 ++#define NVRAM_CFG1_STATUS_BITS 0x00000070 + #define NVRAM_CFG1_BIT_BANG 0x00000008 ++#define NVRAM_CFG1_FLASH_SIZE 0x02000000 + #define NVRAM_CFG1_COMPAT_BYPASS 0x80000000 ++#define NVRAM_CFG1_VENDOR_MASK 0x03000003 ++#define FLASH_VENDOR_ATMEL_EEPROM 0x02000000 ++#define FLASH_VENDOR_ATMEL_FLASH_BUFFERED 0x02000003 ++#define FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED 0x00000003 ++#define FLASH_VENDOR_ST 0x03000001 ++#define FLASH_VENDOR_SAIFUN 0x01000003 ++#define FLASH_VENDOR_SST_SMALL 0x00000001 ++#define FLASH_VENDOR_SST_LARGE 0x02000001 ++#define NVRAM_CFG1_5752VENDOR_MASK 0x03c00003 ++#define FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ 0x00000000 ++#define FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ 0x02000000 ++#define FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED 0x02000003 ++#define FLASH_5752VENDOR_ST_M45PE10 0x02400000 ++#define FLASH_5752VENDOR_ST_M45PE20 0x02400002 ++#define FLASH_5752VENDOR_ST_M45PE40 0x02400001 ++#define NVRAM_CFG1_5752PAGE_SIZE_MASK 0x70000000 ++#define FLASH_5752PAGE_SIZE_256 0x00000000 ++#define FLASH_5752PAGE_SIZE_512 0x10000000 ++#define FLASH_5752PAGE_SIZE_1K 0x20000000 ++#define FLASH_5752PAGE_SIZE_2K 0x30000000 ++#define FLASH_5752PAGE_SIZE_4K 0x40000000 ++#define FLASH_5752PAGE_SIZE_264 0x50000000 + #define NVRAM_CFG2 0x00007018 + #define NVRAM_CFG3 0x0000701c + #define NVRAM_SWARB 0x00007020 +@@ -1395,15 +1432,16 @@ + #define SWARB_REQ1 0x00002000 + #define SWARB_REQ2 0x00004000 + #define SWARB_REQ3 0x00008000 +-#define NVRAM_BUFFERED_PAGE_SIZE 264 +-#define NVRAM_BUFFERED_PAGE_POS 9 + #define NVRAM_ACCESS 0x00007024 + #define ACCESS_ENABLE 0x00000001 + #define ACCESS_WR_ENABLE 0x00000002 +-/* 0x7024 --> 0x7400 unused */ ++#define NVRAM_WRITE1 0x00007028 ++/* 0x702c --> 0x7400 unused */ + + /* 0x7400 --> 0x8000 unused */ + ++#define TG3_EEPROM_MAGIC 0x669955aa ++ + /* 32K Window into NIC internal memory */ + #define NIC_SRAM_WIN_BASE 0x00008000 + +@@ -1435,6 +1473,10 @@ + #define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100 + #define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000 + #define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000 ++#define NIC_SRAM_DATA_CFG_NO_GPIO2 0x00100000 ++ ++#define NIC_SRAM_DATA_VER 0x00000b5c ++#define NIC_SRAM_DATA_VER_SHIFT 16 + + #define NIC_SRAM_DATA_PHY_ID 0x00000b74 + #define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000 +@@ -1497,6 +1539,7 @@ + #define MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000 + + #define MII_TG3_EXT_CTRL 0x10 /* Extended control register */ ++#define MII_TG3_EXT_CTRL_FIFO_ELASTIC 0x0001 + #define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002 + #define MII_TG3_EXT_CTRL_TBI 0x8000 + +@@ -1529,26 +1572,12 @@ + #define MII_TG3_INT_DUPLEXCHG 0x0008 + #define MII_TG3_INT_ANEG_PAGE_RX 0x0400 + +-/* XXX Add this to mii.h */ +-#ifndef ADVERTISE_PAUSE +-#define ADVERTISE_PAUSE_CAP 0x0400 +-#endif +-#ifndef ADVERTISE_PAUSE_ASYM +-#define ADVERTISE_PAUSE_ASYM 0x0800 +-#endif +-#ifndef LPA_PAUSE +-#define LPA_PAUSE_CAP 0x0400 +-#endif +-#ifndef LPA_PAUSE_ASYM +-#define LPA_PAUSE_ASYM 0x0800 +-#endif +- + /* There are two ways to manage the TX descriptors on the tigon3. + * Either the descriptors are in host DMA'able memory, or they + * exist only in the cards on-chip SRAM. All 16 send bds are under + * the same mode, they may not be configured individually. + * +- * The mode we use is controlled by TG3_FLAG_HOST_TXDS in tp->tg3_flags. ++ * This driver always uses host memory TX descriptors. + * + * To use host memory TX descriptors: + * 1) Set GRC_MODE_HOST_SENDBDS in GRC_MODE register. +@@ -1988,7 +2017,7 @@ struct tg3 { + spinlock_t lock; + spinlock_t indirect_lock; + +- unsigned long regs; ++ void __iomem *regs; + struct net_device *dev; + struct pci_dev *pdev; + +@@ -2004,7 +2033,6 @@ struct tg3 { + + spinlock_t tx_lock; + +- /* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */ + struct tg3_tx_buffer_desc *tx_ring; + struct tx_ring_info *tx_buffers; + dma_addr_t tx_desc_mapping; +@@ -2040,7 +2068,6 @@ struct tg3 { + + u32 rx_offset; + u32 tg3_flags; +-#define TG3_FLAG_HOST_TXDS 0x00000001 + #define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 + #define TG3_FLAG_RX_CHECKSUMS 0x00000004 + #define TG3_FLAG_USE_LINKCHG_REG 0x00000008 +@@ -2070,15 +2097,13 @@ struct tg3 { + #define TG3_FLAG_JUMBO_ENABLE 0x00800000 + #define TG3_FLAG_10_100_ONLY 0x01000000 + #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 +-#define TG3_FLAG_PAUSE_RX 0x04000000 +-#define TG3_FLAG_PAUSE_TX 0x08000000 + #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 + #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 + #define TG3_FLAG_SPLIT_MODE 0x40000000 + #define TG3_FLAG_INIT_COMPLETE 0x80000000 + u32 tg3_flags2; + #define TG3_FLG2_RESTART_TIMER 0x00000001 +-#define TG3_FLG2_SUN_5704 0x00000002 ++#define TG3_FLG2_SUN_570X 0x00000002 + #define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004 + #define TG3_FLG2_IS_5788 0x00000008 + #define TG3_FLG2_MAX_RXPEND_64 0x00000010 +@@ -2089,6 +2114,16 @@ struct tg3 { + #define TG3_FLG2_PCI_EXPRESS 0x00000200 + #define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400 + #define TG3_FLG2_HW_AUTONEG 0x00000800 ++#define TG3_FLG2_PHY_JUST_INITTED 0x00001000 ++#define TG3_FLG2_PHY_SERDES 0x00002000 ++#define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000 ++#define TG3_FLG2_FLASH 0x00008000 ++#define TG3_FLG2_HW_TSO 0x00010000 ++#define TG3_FLG2_SERDES_PREEMPHASIS 0x00020000 ++#define TG3_FLG2_5705_PLUS 0x00040000 ++#define TG3_FLG2_5750_PLUS 0x00080000 ++#define TG3_FLG2_PROTECTED_NVRAM 0x00100000 ++#define TG3_FLG2_USING_MSI 0x00200000 + + u32 split_mode_max_reqs; + #define SPLIT_MODE_5704_MAX_REQ 3 +@@ -2135,8 +2170,8 @@ struct tg3 { + #define PHY_ID_BCM5704 0x60008190 + #define PHY_ID_BCM5705 0x600081a0 + #define PHY_ID_BCM5750 0x60008180 ++#define PHY_ID_BCM5752 0x60008100 + #define PHY_ID_BCM8002 0x60010140 +-#define PHY_ID_SERDES 0xfeedbee0 + #define PHY_ID_INVALID 0xffffffff + #define PHY_ID_REV_MASK 0x0000000f + #define PHY_REV_BCM5401_B0 0x1 +@@ -2159,11 +2194,39 @@ struct tg3 { + (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ + (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ + (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ +- (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES) ++ (X) == PHY_ID_BCM8002) + + struct tg3_hw_stats *hw_stats; + dma_addr_t stats_mapping; + struct work_struct reset_task; ++ ++ u32 nvram_size; ++ u32 nvram_pagesize; ++ u32 nvram_jedecnum; ++ ++#define JEDEC_ATMEL 0x1f ++#define JEDEC_ST 0x20 ++#define JEDEC_SAIFUN 0x4f ++#define JEDEC_SST 0xbf ++ ++#define ATMEL_AT24C64_CHIP_SIZE (64 * 1024) ++#define ATMEL_AT24C64_PAGE_SIZE (32) ++ ++#define ATMEL_AT24C512_CHIP_SIZE (512 * 1024) ++#define ATMEL_AT24C512_PAGE_SIZE (128) ++ ++#define ATMEL_AT45DB0X1B_PAGE_POS 9 ++#define ATMEL_AT45DB0X1B_PAGE_SIZE 264 ++ ++#define ATMEL_AT25F512_PAGE_SIZE 256 ++ ++#define ST_M45PEX0_PAGE_SIZE 256 ++ ++#define SAIFUN_SA25F0XX_PAGE_SIZE 256 ++ ++#define SST_25VF0X0_PAGE_SIZE 4098 ++ ++ + }; + + #endif /* !(_T3_H) */ |