* 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.
+ * Copyright (C) 2005-2007 Broadcom Corporation.
*
* Firmware is:
* Derived from proprietary unpublished source code,
#include <linux/dma-mapping.h>
#include <net/checksum.h>
+#include <net/ip.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_SPARC64
+#ifdef CONFIG_SPARC
#include <asm/idprom.h>
-#include <asm/oplib.h>
-#include <asm/pbm.h>
+#include <asm/prom.h>
#endif
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define TG3_VLAN_TAG_USED 0
#endif
-#ifdef NETIF_F_TSO
#define TG3_TSO_SUPPORT 1
-#else
-#define TG3_TSO_SUPPORT 0
-#endif
#include "tg3.h"
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.65"
-#define DRV_MODULE_RELDATE "August 07, 2006"
+#define DRV_MODULE_VERSION "3.82"
+#define DRV_MODULE_RELDATE "October 5, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
#define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64)
/* minimum number of free TX descriptors required to wake up TX process */
-#define TG3_TX_WAKEUP_THRESH (TG3_TX_RING_SIZE / 4)
+#define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4)
/* number of ETHTOOL_GSTATS u64's */
#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
readl(mbox);
}
+static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off)
+{
+ return (readl(tp->regs + off + GRCMBOX_BASE));
+}
+
+static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val)
+{
+ writel(val, tp->regs + off + GRCMBOX_BASE);
+}
+
#define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val)
#define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val))
#define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val)
{
unsigned long flags;
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) &&
+ (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC))
+ return;
+
spin_lock_irqsave(&tp->indirect_lock, flags);
if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
{
unsigned long flags;
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) &&
+ (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) {
+ *val = 0;
+ return;
+ }
+
spin_lock_irqsave(&tp->indirect_lock, flags);
if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
(tp->hw_status->status & SD_STATUS_UPDATED))
tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+ else
+ tw32(HOSTCC_MODE, tp->coalesce_mode |
+ (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
}
static void tg3_enable_ints(struct tg3 *tp)
static inline void tg3_netif_stop(struct tg3 *tp)
{
tp->dev->trans_start = jiffies; /* prevent tx timeout */
- netif_poll_disable(tp->dev);
+ napi_disable(&tp->napi);
netif_tx_disable(tp->dev);
}
* so long as all callers are assured to have free tx slots
* (such as after tg3_init_hw)
*/
- netif_poll_enable(tp->dev);
+ napi_enable(&tp->napi);
tp->hw_status->status |= SD_STATUS_UPDATED;
tg3_enable_ints(tp);
}
u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
u32 orig_clock_ctrl;
- if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+ if ((tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) ||
+ (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
return;
orig_clock_ctrl = clock_ctrl;
unsigned int loops;
int ret;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
+ (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
+ return 0;
+
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
tw32_f(MAC_MI_MODE,
(tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
return ret;
}
+static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
+{
+ u32 phy;
+
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+ (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
+ return;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 ephy;
+
+ if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &ephy)) {
+ tg3_writephy(tp, MII_TG3_EPHY_TEST,
+ ephy | MII_TG3_EPHY_SHADOW_EN);
+ if (!tg3_readphy(tp, MII_TG3_EPHYTST_MISCCTRL, &phy)) {
+ if (enable)
+ phy |= MII_TG3_EPHYTST_MISCCTRL_MDIX;
+ else
+ phy &= ~MII_TG3_EPHYTST_MISCCTRL_MDIX;
+ tg3_writephy(tp, MII_TG3_EPHYTST_MISCCTRL, phy);
+ }
+ tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy);
+ }
+ } else {
+ phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC |
+ MII_TG3_AUXCTL_SHDWSEL_MISC;
+ if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) &&
+ !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) {
+ if (enable)
+ phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+ else
+ phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+ phy |= MII_TG3_AUXCTL_MISC_WREN;
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
+ }
+ }
+}
+
static void tg3_phy_set_wirespeed(struct tg3 *tp)
{
u32 val;
u32 phy_status;
int err;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 val;
+
+ val = tr32(GRC_MISC_CFG);
+ tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
+ udelay(40);
+ }
err = tg3_readphy(tp, MII_BMSR, &phy_status);
err |= tg3_readphy(tp, MII_BMSR, &phy_status);
if (err != 0)
else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
+ if (tp->tg3_flags2 & TG3_FLG2_PHY_ADJUST_TRIM) {
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
+ tg3_writephy(tp, MII_TG3_TEST1,
+ MII_TG3_TEST1_TRIM_EN | 0x4);
+ } else
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
}
/* Set Extended packet length bit (bit 14) on all chips that */
phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
}
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ /* adjust output voltage */
+ tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12);
+ }
+
+ tg3_phy_toggle_automdix(tp, 1);
tg3_phy_set_wirespeed(tp);
return 0;
}
{
struct tg3 *tp_peer = tp;
- if ((tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) != 0)
+ if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0)
return;
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
}
}
+static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
+{
+ if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
+ return 1;
+ else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) {
+ if (speed != SPEED_10)
+ return 1;
+ } else if (speed == SPEED_10)
+ return 1;
+
+ return 0;
+}
+
static int tg3_setup_phy(struct tg3 *, int);
#define RESET_KIND_SHUTDOWN 0
static void tg3_power_down_phy(struct tg3 *tp)
{
+ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
+ u32 serdes_cfg = tr32(MAC_SERDES_CFG);
+
+ sg_dig_ctrl |=
+ SG_DIG_USING_HW_AUTONEG | SG_DIG_SOFT_RESET;
+ tw32(SG_DIG_CTRL, sg_dig_ctrl);
+ tw32(MAC_SERDES_CFG, serdes_cfg | (1 << 15));
+ }
+ return;
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 val;
+
+ tg3_bmcr_reset(tp);
+ val = tr32(GRC_MISC_CFG);
+ tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
+ udelay(40);
+ return;
+ } else {
+ tg3_writephy(tp, MII_TG3_EXT_CTRL,
+ MII_TG3_EXT_CTRL_FORCE_LED_OFF);
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
+ }
+
/* The PHY should not be powered down on some chips because
* of bugs.
*/
power_control);
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))
+ /* Switch out of Vaux if it is a NIC */
+ if (tp->tg3_flags2 & TG3_FLG2_IS_NIC)
tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
return 0;
tg3_setup_phy(tp, 0);
}
- if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 val;
+
+ val = tr32(GRC_VCPU_EXT_CTRL);
+ tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL);
+ } else if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
int i;
u32 val;
msleep(1);
}
}
- tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
- WOL_DRV_STATE_SHUTDOWN |
- WOL_DRV_WOL | WOL_SET_MAGIC_PKT);
+ if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+ tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
+ WOL_DRV_STATE_SHUTDOWN |
+ WOL_DRV_WOL |
+ WOL_SET_MAGIC_PKT);
pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
udelay(40);
- mac_mode = MAC_MODE_PORT_MODE_MII;
+ if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+ mac_mode = MAC_MODE_PORT_MODE_GMII;
+ else
+ mac_mode = MAC_MODE_PORT_MODE_MII;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 ||
- !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB))
- mac_mode |= MAC_MODE_LINK_POLARITY;
+ mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5700) {
+ u32 speed = (tp->tg3_flags &
+ TG3_FLAG_WOL_SPEED_100MB) ?
+ SPEED_100 : SPEED_10;
+ if (tg3_5700_link_polarity(tp, speed))
+ mac_mode |= MAC_MODE_LINK_POLARITY;
+ else
+ mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ }
} else {
mac_mode = MAC_MODE_PORT_MODE_TBI;
}
tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK |
CLOCK_CTRL_PWRDOWN_PLL133, 40);
- } else if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
+ } else if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
+ (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) {
/* do nothing */
} else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
}
if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
- !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
- /* Turn off the PHY */
- if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
- tg3_writephy(tp, MII_TG3_EXT_CTRL,
- MII_TG3_EXT_CTRL_FORCE_LED_OFF);
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
- tg3_power_down_phy(tp);
- }
- }
+ !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+ tg3_power_down_phy(tp);
tg3_frob_aux_power(tp);
static void tg3_link_report(struct tg3 *tp)
{
if (!netif_carrier_ok(tp->dev)) {
- printk(KERN_INFO PFX "%s: Link is down.\n", tp->dev->name);
- } else {
+ if (netif_msg_link(tp))
+ printk(KERN_INFO PFX "%s: Link is down.\n",
+ tp->dev->name);
+ } else if (netif_msg_link(tp)) {
printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n",
tp->dev->name,
(tp->link_config.active_speed == SPEED_1000 ?
break;
default:
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
+ SPEED_10;
+ *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
+ DUPLEX_HALF;
+ break;
+ }
*speed = SPEED_INVALID;
*duplex = DUPLEX_INVALID;
break;
tg3_writephy(tp, MII_ADVERTISE, new_adv);
} else if (tp->link_config.speed == SPEED_INVALID) {
- tp->link_config.advertising =
- (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
- ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
- ADVERTISED_Autoneg | ADVERTISED_MII);
-
if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
tp->link_config.advertising &=
~(ADVERTISED_1000baseT_Half |
return err;
}
-static int tg3_copper_is_advertising_all(struct tg3 *tp)
+static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
{
- u32 adv_reg, all_mask;
+ u32 adv_reg, all_mask = 0;
+
+ if (mask & ADVERTISED_10baseT_Half)
+ all_mask |= ADVERTISE_10HALF;
+ if (mask & ADVERTISED_10baseT_Full)
+ all_mask |= ADVERTISE_10FULL;
+ if (mask & ADVERTISED_100baseT_Half)
+ all_mask |= ADVERTISE_100HALF;
+ if (mask & ADVERTISED_100baseT_Full)
+ all_mask |= ADVERTISE_100FULL;
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)
return 0;
if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
u32 tg3_ctrl;
+ all_mask = 0;
+ if (mask & ADVERTISED_1000baseT_Half)
+ all_mask |= ADVERTISE_1000HALF;
+ if (mask & ADVERTISED_1000baseT_Full)
+ all_mask |= ADVERTISE_1000FULL;
+
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)
return 0;
}
if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT)
tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
- else
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
tg3_writephy(tp, MII_TG3_IMASK, ~0);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
/* Force autoneg restart if we are exiting
* low power mode.
*/
- if (!tg3_copper_is_advertising_all(tp))
+ if (!tg3_copper_is_advertising_all(tp,
+ tp->link_config.advertising))
current_link_up = 0;
} else {
current_link_up = 0;
if (tp->link_config.active_duplex == DUPLEX_HALF)
tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
- tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
- if ((tp->led_ctrl == LED_CTRL_MODE_PHY_2) ||
- (current_link_up == 1 &&
- tp->link_config.active_speed == SPEED_10))
- tp->mac_mode |= MAC_MODE_LINK_POLARITY;
- } else {
- if (current_link_up == 1)
+ if (current_link_up == 1 &&
+ tg3_5700_link_polarity(tp, tp->link_config.active_speed))
tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+ else
+ tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
}
/* ??? Without this setting Netgear GA302T PHY does not
{
int current_link_up = 0;
- if (!(mac_status & MAC_STATUS_PCS_SYNCED)) {
- tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
+ if (!(mac_status & MAC_STATUS_PCS_SYNCED))
goto out;
- }
if (tp->link_config.autoneg == AUTONEG_ENABLE) {
u32 flags;
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++) {
} 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);
+
+ tw32_f(MAC_MODE, tp->mac_mode);
+ udelay(40);
}
out:
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));
}
}
+ if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) {
+ u32 val = tr32(PCIE_PWR_MGMT_THRESH);
+ if (!netif_carrier_ok(tp->dev))
+ val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) |
+ tp->pwrmgmt_thresh;
+ else
+ val |= PCIE_PWR_MGMT_L1_THRESH_MSK;
+ tw32(PCIE_PWR_MGMT_THRESH, val);
+ }
+
return err;
}
smp_mb();
if (unlikely(netif_queue_stopped(tp->dev) &&
- (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) {
+ (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))) {
netif_tx_lock(tp->dev);
if (netif_queue_stopped(tp->dev) &&
- (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))
+ (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))
netif_wake_queue(tp->dev);
netif_tx_unlock(tp->dev);
}
skb_reserve(copy_skb, 2);
skb_put(copy_skb, len);
pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
- memcpy(copy_skb->data, skb->data, len);
+ skb_copy_from_linear_data(skb, copy_skb->data, len);
pci_dma_sync_single_for_device(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
/* We'll reuse the original ring buffer. */
}
next_pkt_nopost:
sw_idx++;
- sw_idx %= TG3_RX_RCB_RING_SIZE(tp);
+ sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1);
/* Refresh hw_idx to see if there is new work */
if (sw_idx == hw_idx) {
return received;
}
-static int tg3_poll(struct net_device *netdev, int *budget)
+static int tg3_poll(struct napi_struct *napi, int budget)
{
- struct tg3 *tp = netdev_priv(netdev);
+ struct tg3 *tp = container_of(napi, struct tg3, napi);
+ struct net_device *netdev = tp->dev;
struct tg3_hw_status *sblk = tp->hw_status;
- int done;
+ int work_done = 0;
/* handle link change and other phy events */
if (!(tp->tg3_flags &
if (sblk->idx[0].tx_consumer != tp->tx_cons) {
tg3_tx(tp);
if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) {
- netif_rx_complete(netdev);
+ netif_rx_complete(netdev, napi);
schedule_work(&tp->reset_task);
return 0;
}
/* run RX thread, within the bounds set by NAPI.
* All RX "locking" is done by ensuring outside
- * code synchronizes with dev->poll()
+ * code synchronizes with tg3->napi.poll()
*/
- if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
- int orig_budget = *budget;
- int work_done;
-
- if (orig_budget > netdev->quota)
- orig_budget = netdev->quota;
-
- work_done = tg3_rx(tp, orig_budget);
-
- *budget -= work_done;
- netdev->quota -= work_done;
- }
+ if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr)
+ work_done = tg3_rx(tp, budget);
if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
tp->last_tag = sblk->status_tag;
sblk->status &= ~SD_STATUS_UPDATED;
/* if no more work, tell net stack and NIC we're done */
- done = !tg3_has_work(tp);
- if (done) {
- netif_rx_complete(netdev);
+ if (!tg3_has_work(tp)) {
+ netif_rx_complete(netdev, napi);
tg3_restart_ints(tp);
}
- return (done ? 0 : 1);
+ return work_done;
}
static void tg3_irq_quiesce(struct tg3 *tp)
*/
static inline void tg3_full_lock(struct tg3 *tp, int irq_sync)
{
+ spin_lock_bh(&tp->lock);
if (irq_sync)
tg3_irq_quiesce(tp);
- spin_lock_bh(&tp->lock);
}
static inline void tg3_full_unlock(struct tg3 *tp)
/* One-shot MSI handler - Chip automatically disables interrupt
* after sending MSI so driver doesn't have to do it.
*/
-static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_msi_1shot(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev);
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
if (likely(!tg3_irq_sync(tp)))
- netif_rx_schedule(dev); /* schedule NAPI poll */
+ netif_rx_schedule(dev, &tp->napi);
return IRQ_HANDLED;
}
* 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)
+static irqreturn_t tg3_msi(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev);
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
if (likely(!tg3_irq_sync(tp)))
- netif_rx_schedule(dev); /* schedule NAPI poll */
+ netif_rx_schedule(dev, &tp->napi);
return IRQ_RETVAL(1);
}
-static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev);
* 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.
- * 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);
- if (tg3_irq_sync(tp))
+ if (unlikely(!(sblk->status & SD_STATUS_UPDATED))) {
+ if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) ||
+ (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
+ handled = 0;
goto out;
- sblk->status &= ~SD_STATUS_UPDATED;
- if (likely(tg3_has_work(tp))) {
- prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
- netif_rx_schedule(dev); /* schedule NAPI poll */
- } else {
- /* No work, shared interrupt perhaps? re-enable
- * interrupts, and flush that PCI write
- */
- tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000000);
}
- } else { /* shared interrupt */
- handled = 0;
+ }
+
+ /*
+ * 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.
+ *
+ * Flush the mailbox to de-assert the IRQ immediately to prevent
+ * spurious interrupts. The flush impacts performance but
+ * excessive spurious interrupts can be worse in some cases.
+ */
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ if (tg3_irq_sync(tp))
+ goto out;
+ sblk->status &= ~SD_STATUS_UPDATED;
+ if (likely(tg3_has_work(tp))) {
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+ netif_rx_schedule(dev, &tp->napi);
+ } else {
+ /* No work, shared interrupt perhaps? re-enable
+ * interrupts, and flush that PCI write
+ */
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ 0x00000000);
}
out:
return IRQ_RETVAL(handled);
}
-static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev);
* Reading the PCI State register will confirm whether the
* interrupt is ours and will flush the status block.
*/
- if ((sblk->status_tag != tp->last_tag) ||
- !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
- /*
- * 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);
- if (tg3_irq_sync(tp))
+ if (unlikely(sblk->status_tag == tp->last_tag)) {
+ if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) ||
+ (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
+ handled = 0;
goto out;
- if (netif_rx_schedule_prep(dev)) {
- prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
- /* Update last_tag to mark that this status has been
- * seen. Because interrupt may be shared, we may be
- * racing with tg3_poll(), so only update last_tag
- * if tg3_poll() is not scheduled.
- */
- tp->last_tag = sblk->status_tag;
- __netif_rx_schedule(dev);
}
- } else { /* shared interrupt */
- handled = 0;
+ }
+
+ /*
+ * 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.
+ *
+ * Flush the mailbox to de-assert the IRQ immediately to prevent
+ * spurious interrupts. The flush impacts performance but
+ * excessive spurious interrupts can be worse in some cases.
+ */
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ if (tg3_irq_sync(tp))
+ goto out;
+ if (netif_rx_schedule_prep(dev, &tp->napi)) {
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+ /* Update last_tag to mark that this status has been
+ * seen. Because interrupt may be shared, we may be
+ * racing with tg3_poll(), so only update last_tag
+ * if tg3_poll() is not scheduled.
+ */
+ tp->last_tag = sblk->status_tag;
+ __netif_rx_schedule(dev, &tp->napi);
}
out:
return IRQ_RETVAL(handled);
}
/* ISR for interrupt test */
-static irqreturn_t tg3_test_isr(int irq, void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t tg3_test_isr(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev);
if ((sblk->status & SD_STATUS_UPDATED) ||
!(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000001);
+ tg3_disable_ints(tp);
return IRQ_RETVAL(1);
}
return IRQ_RETVAL(0);
tg3_full_unlock(tp);
del_timer_sync(&tp->timer);
tp->irq_sync = 0;
- netif_poll_enable(tp->dev);
+ napi_enable(&tp->napi);
dev_close(tp->dev);
tg3_full_lock(tp, 0);
}
{
struct tg3 *tp = netdev_priv(dev);
- tg3_interrupt(tp->pdev->irq, dev, NULL);
+ tg3_interrupt(tp->pdev->irq, dev);
}
#endif
-static void tg3_reset_task(void *_data)
+static void tg3_reset_task(struct work_struct *work)
{
- struct tg3 *tp = _data;
+ struct tg3 *tp = container_of(work, struct tg3, reset_task);
unsigned int restart_timer;
tg3_full_lock(tp, 0);
- tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK;
if (!netif_running(tp->dev)) {
- tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
tg3_full_unlock(tp);
return;
}
mod_timer(&tp->timer, jiffies + 1);
out:
- tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
-
tg3_full_unlock(tp);
}
+static void tg3_dump_short_state(struct tg3 *tp)
+{
+ printk(KERN_ERR PFX "DEBUG: MAC_TX_STATUS[%08x] MAC_RX_STATUS[%08x]\n",
+ tr32(MAC_TX_STATUS), tr32(MAC_RX_STATUS));
+ printk(KERN_ERR PFX "DEBUG: RDMAC_STATUS[%08x] WDMAC_STATUS[%08x]\n",
+ tr32(RDMAC_STATUS), tr32(WDMAC_STATUS));
+}
+
static void tg3_tx_timeout(struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
- printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
- dev->name);
+ if (netif_msg_tx_err(tp)) {
+ printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
+ dev->name);
+ tg3_dump_short_state(tp);
+ }
schedule_work(&tp->reset_task);
}
len = skb_headlen(skb);
/* We are running in BH disabled context with netif_tx_lock
- * and TX reclaim runs via tp->poll inside of a software
+ * and TX reclaim runs via tp->napi.poll inside of a software
* interrupt. Furthermore, IRQ processing runs lockless so we have
* no IRQ context deadlocks to worry about either. Rejoice!
*/
entry = tp->tx_prod;
base_flags = 0;
-#if TG3_TSO_SUPPORT != 0
mss = 0;
- if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
- (mss = skb_shinfo(skb)->gso_size) != 0) {
+ if ((mss = skb_shinfo(skb)->gso_size) != 0) {
int tcp_opt_len, ip_tcp_len;
if (skb_header_cloned(skb) &&
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
mss |= (skb_headlen(skb) - ETH_HLEN) << 9;
else {
- tcp_opt_len = ((skb->h.th->doff - 5) * 4);
- ip_tcp_len = (skb->nh.iph->ihl * 4) +
- sizeof(struct tcphdr);
+ struct iphdr *iph = ip_hdr(skb);
+
+ tcp_opt_len = tcp_optlen(skb);
+ ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
- skb->nh.iph->check = 0;
- skb->nh.iph->tot_len = htons(mss + ip_tcp_len +
- tcp_opt_len);
+ iph->check = 0;
+ iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
mss |= (ip_tcp_len + tcp_opt_len) << 9;
}
base_flags |= (TXD_FLAG_CPU_PRE_DMA |
TXD_FLAG_CPU_POST_DMA);
- skb->h.th->check = 0;
+ tcp_hdr(skb)->check = 0;
}
else if (skb->ip_summed == CHECKSUM_PARTIAL)
base_flags |= TXD_FLAG_TCPUDP_CSUM;
-#else
- mss = 0;
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- base_flags |= TXD_FLAG_TCPUDP_CSUM;
-#endif
#if TG3_VLAN_TAG_USED
if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
base_flags |= (TXD_FLAG_VLAN |
tp->tx_prod = entry;
if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(dev);
- if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
+ if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
netif_wake_queue(tp->dev);
}
return NETDEV_TX_OK;
}
-#if TG3_TSO_SUPPORT != 0
static int tg3_start_xmit_dma_bug(struct sk_buff *, struct net_device *);
/* Use GSO to workaround a rare TSO bug that may be triggered when the
/* Estimate the number of fragments in the worst case */
if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
netif_stop_queue(tp->dev);
- return NETDEV_TX_BUSY;
+ if (tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))
+ return NETDEV_TX_BUSY;
+
+ netif_wake_queue(tp->dev);
}
segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO);
return NETDEV_TX_OK;
}
-#endif
/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
* support TG3_FLG2_HW_TSO_1 or firmware TSO only.
len = skb_headlen(skb);
/* We are running in BH disabled context with netif_tx_lock
- * and TX reclaim runs via tp->poll inside of a software
+ * and TX reclaim runs via tp->napi.poll inside of a software
* interrupt. Furthermore, IRQ processing runs lockless so we have
* no IRQ context deadlocks to worry about either. Rejoice!
*/
base_flags = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL)
base_flags |= TXD_FLAG_TCPUDP_CSUM;
-#if TG3_TSO_SUPPORT != 0
mss = 0;
- if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
- (mss = skb_shinfo(skb)->gso_size) != 0) {
+ if ((mss = skb_shinfo(skb)->gso_size) != 0) {
+ struct iphdr *iph;
int tcp_opt_len, ip_tcp_len, hdr_len;
if (skb_header_cloned(skb) &&
goto out_unlock;
}
- tcp_opt_len = ((skb->h.th->doff - 5) * 4);
- ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
+ tcp_opt_len = tcp_optlen(skb);
+ ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
hdr_len = ip_tcp_len + tcp_opt_len;
if (unlikely((ETH_HLEN + hdr_len) > 80) &&
- (tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG))
+ (tp->tg3_flags2 & TG3_FLG2_TSO_BUG))
return (tg3_tso_bug(tp, skb));
base_flags |= (TXD_FLAG_CPU_PRE_DMA |
TXD_FLAG_CPU_POST_DMA);
- skb->nh.iph->check = 0;
- skb->nh.iph->tot_len = htons(mss + hdr_len);
+ iph = ip_hdr(skb);
+ iph->check = 0;
+ iph->tot_len = htons(mss + hdr_len);
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
- skb->h.th->check = 0;
+ tcp_hdr(skb)->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);
- }
+ } else
+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, 0,
+ IPPROTO_TCP,
+ 0);
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) {
+ if (tcp_opt_len || iph->ihl > 5) {
int tsflags;
- tsflags = ((skb->nh.iph->ihl - 5) +
- (tcp_opt_len >> 2));
+ tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
mss |= (tsflags << 11);
}
} else {
- if (tcp_opt_len || skb->nh.iph->ihl > 5) {
+ if (tcp_opt_len || iph->ihl > 5) {
int tsflags;
- tsflags = ((skb->nh.iph->ihl - 5) +
- (tcp_opt_len >> 2));
+ tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
base_flags |= tsflags << 12;
}
}
}
-#else
- mss = 0;
-#endif
#if TG3_VLAN_TAG_USED
if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
base_flags |= (TXD_FLAG_VLAN |
tp->tx_prod = entry;
if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(dev);
- if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
+ if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
netif_wake_queue(tp->dev);
}
*/
static int tg3_alloc_consistent(struct tg3 *tp)
{
- tp->rx_std_buffers = kmalloc((sizeof(struct ring_info) *
+ tp->rx_std_buffers = kzalloc((sizeof(struct ring_info) *
(TG3_RX_RING_SIZE +
TG3_RX_JUMBO_RING_SIZE)) +
(sizeof(struct tx_ring_info) *
if (!tp->rx_std_buffers)
return -ENOMEM;
- memset(tp->rx_std_buffers, 0,
- (sizeof(struct ring_info) *
- (TG3_RX_RING_SIZE +
- TG3_RX_JUMBO_RING_SIZE)) +
- (sizeof(struct tx_ring_info) *
- TG3_TX_RING_SIZE));
-
tp->rx_jumbo_buffers = &tp->rx_std_buffers[TG3_RX_RING_SIZE];
tp->tx_buffers = (struct tx_ring_info *)
&tp->rx_jumbo_buffers[TG3_RX_JUMBO_RING_SIZE];
}
}
+static int tg3_poll_fw(struct tg3 *tp)
+{
+ int i;
+ u32 val;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ /* Wait up to 20ms for init done. */
+ for (i = 0; i < 200; i++) {
+ if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
+ return 0;
+ udelay(100);
+ }
+ return -ENODEV;
+ }
+
+ /* 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);
+ }
+
+ /* Chip might not be fitted with firmware. Some Sun onboard
+ * parts are configured like that. So don't signal the timeout
+ * of the above loop as an error, but do report the lack of
+ * running firmware once.
+ */
+ if (i >= 100000 &&
+ !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
+ tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
+
+ printk(KERN_INFO PFX "%s: No firmware running.\n",
+ tp->dev->name);
+ }
+
+ return 0;
+}
+
+/* Save PCI command register before chip reset */
+static void tg3_save_pci_state(struct tg3 *tp)
+{
+ u32 val;
+
+ pci_read_config_dword(tp->pdev, TG3PCI_COMMAND, &val);
+ tp->pci_cmd = val;
+}
+
+/* Restore PCI state after chip reset */
+static void tg3_restore_pci_state(struct tg3 *tp)
+{
+ u32 val;
+
+ /* Re-enable indirect register accesses. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+
+ /* Set MAX PCI retry to zero. */
+ val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+ (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
+ val |= PCISTATE_RETRY_SAME_DMA;
+ pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
+
+ pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
+
+ /* Make sure PCI-X relaxed ordering bit is clear. */
+ if (tp->pcix_cap) {
+ u16 pcix_cmd;
+
+ pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ &pcix_cmd);
+ pcix_cmd &= ~PCI_X_CMD_ERO;
+ pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ pcix_cmd);
+ }
+
+ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
+
+ /* Chip reset on 5780 will reset MSI enable bit,
+ * so need to restore it.
+ */
+ if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+ u16 ctrl;
+
+ pci_read_config_word(tp->pdev,
+ tp->msi_cap + PCI_MSI_FLAGS,
+ &ctrl);
+ pci_write_config_word(tp->pdev,
+ tp->msi_cap + PCI_MSI_FLAGS,
+ ctrl | PCI_MSI_FLAGS_ENABLE);
+ val = tr32(MSGINT_MODE);
+ tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
+ }
+ }
+}
+
static void tg3_stop_fw(struct tg3 *);
/* tp->lock is held. */
{
u32 val;
void (*write_op)(struct tg3 *, u32, u32);
- int i;
+ int err;
tg3_nvram_lock(tp);
*/
tp->nvram_lock_cnt = 0;
+ /* GRC_MISC_CFG core clock reset will clear the memory
+ * enable bit in PCI register 4 and the MSI enable bit
+ * on some chips, so we save relevant registers here.
+ */
+ tg3_save_pci_state(tp);
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
tw32(GRC_FASTBOOT_PC, 0);
/*
if (write_op == tg3_write_flush_reg32)
tp->write32 = tg3_write32;
+ /* Prevent the irq handler from reading or writing PCI registers
+ * during chip reset when the memory enable bit in the PCI command
+ * register may be cleared. The chip does not generate interrupt
+ * at this time, but the irq handler may still be called due to irq
+ * sharing or irqpoll.
+ */
+ tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING;
+ if (tp->hw_status) {
+ tp->hw_status->status = 0;
+ tp->hw_status->status_tag = 0;
+ }
+ tp->last_tag = 0;
+ smp_mb();
+ synchronize_irq(tp->pdev->irq);
+
/* do the reset */
val = GRC_MISC_CFG_CORECLK_RESET;
}
}
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tw32(VCPU_STATUS, tr32(VCPU_STATUS) | VCPU_STATUS_DRV_RESET);
+ tw32(GRC_VCPU_EXT_CTRL,
+ tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU);
+ }
+
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
tw32(GRC_MISC_CFG, val);
pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
}
- /* Re-enable indirect register accesses. */
- pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
- tp->misc_host_ctrl);
+ tg3_restore_pci_state(tp);
- /* Set MAX PCI retry to zero. */
- val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
- if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
- (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
- val |= PCISTATE_RETRY_SAME_DMA;
- pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
-
- pci_restore_state(tp->pdev);
-
- /* Make sure PCI-X relaxed ordering bit is clear. */
- pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
- val &= ~PCIX_CAPS_RELAXED_ORDERING;
- pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
-
- if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
- u32 val;
-
- /* Chip reset on 5780 will reset MSI enable bit,
- * so need to restore it.
- */
- if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
- u16 ctrl;
-
- pci_read_config_word(tp->pdev,
- tp->msi_cap + PCI_MSI_FLAGS,
- &ctrl);
- pci_write_config_word(tp->pdev,
- tp->msi_cap + PCI_MSI_FLAGS,
- ctrl | PCI_MSI_FLAGS_ENABLE);
- val = tr32(MSGINT_MODE);
- tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
- }
+ tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
+ val = 0;
+ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
val = tr32(MEMARB_MODE);
- tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
-
- } else
- tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+ tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
tg3_stop_fw(tp);
tw32(GRC_MODE, tp->grc_mode);
if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
- u32 val = tr32(0xc4);
+ val = tr32(0xc4);
tw32(0xc4, val | (1 << 15));
}
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);
- }
-
- /* Chip might not be fitted with firmare. Some Sun onboard
- * parts are configured like that. So don't signal the timeout
- * of the above loop as an error, but do report the lack of
- * running firmware once.
- */
- if (i >= 100000 &&
- !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
- tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
-
- printk(KERN_INFO PFX "%s: No firmware running.\n",
- tp->dev->name);
- }
+ err = tg3_poll_fw(tp);
+ if (err)
+ return err;
if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
- u32 val = tr32(0x7c00);
+ val = tr32(0x7c00);
tw32(0x7c00, val | (1 << 25));
}
BUG_ON(offset == TX_CPU_BASE &&
(tp->tg3_flags2 & TG3_FLG2_5705_PLUS));
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 val = tr32(GRC_VCPU_EXT_CTRL);
+
+ tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU);
+ return 0;
+ }
if (offset == RX_CPU_BASE) {
for (i = 0; i < 10000; i++) {
tw32(offset + CPU_STATE, 0xffffffff);
return 0;
}
-#if TG3_TSO_SUPPORT != 0
#define TG3_TSO_FW_RELEASE_MAJOR 0x1
#define TG3_TSO_FW_RELASE_MINOR 0x6
return 0;
}
-#endif /* TG3_TSO_SUPPORT != 0 */
/* tp->lock is held. */
-static void __tg3_set_mac_addr(struct tg3 *tp)
+static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
{
u32 addr_high, addr_low;
int i;
(tp->dev->dev_addr[4] << 8) |
(tp->dev->dev_addr[5] << 0));
for (i = 0; i < 4; i++) {
+ if (i == 1 && skip_mac_1)
+ continue;
tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
}
{
struct tg3 *tp = netdev_priv(dev);
struct sockaddr *addr = p;
- int err = 0;
+ int err = 0, skip_mac_1 = 0;
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;
if (!netif_running(dev))
return 0;
-
- if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
- /* Reset chip so that ASF can re-init any MAC addresses it
- * needs.
- */
- tg3_netif_stop(tp);
- tg3_full_lock(tp, 1);
-
- tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
- err = tg3_restart_hw(tp, 0);
- if (!err)
- tg3_netif_start(tp);
- tg3_full_unlock(tp);
- } else {
- spin_lock_bh(&tp->lock);
- __tg3_set_mac_addr(tp);
- spin_unlock_bh(&tp->lock);
+
+ if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+ u32 addr0_high, addr0_low, addr1_high, addr1_low;
+
+ addr0_high = tr32(MAC_ADDR_0_HIGH);
+ addr0_low = tr32(MAC_ADDR_0_LOW);
+ addr1_high = tr32(MAC_ADDR_1_HIGH);
+ addr1_low = tr32(MAC_ADDR_1_LOW);
+
+ /* Skip MAC addr 1 if ASF is using it. */
+ if ((addr0_high != addr1_high || addr0_low != addr1_low) &&
+ !(addr1_high == 0 && addr1_low == 0))
+ skip_mac_1 = 1;
}
+ spin_lock_bh(&tp->lock);
+ __tg3_set_mac_addr(tp, skip_mac_1);
+ spin_unlock_bh(&tp->lock);
return err;
}
tg3_abort_hw(tp, 1);
}
- if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && reset_phy)
+ if (reset_phy)
tg3_phy_reset(tp);
err = tg3_chip_reset(tp);
tg3_write_sig_legacy(tp, RESET_KIND_INIT);
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+ val = tr32(TG3_CPMU_CTRL);
+ val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
+ tw32(TG3_CPMU_CTRL, val);
+ }
+
/* This works around an issue with Athlon chipsets on
* B3 tigon3 silicon. This bit has no effect on any
* other revision. But do not set this on PCI Express
- * chips.
+ * chips and don't even touch the clocks if the CPMU is present.
*/
- if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
- tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
- tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+ if (!(tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+ tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
+ tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+ }
if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
if (err)
return err;
- /* This value is determined during the probe time DMA
- * engine test, tg3_test_dma.
- */
- tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784) {
+ /* This value is determined during the probe time DMA
+ * engine test, tg3_test_dma.
+ */
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ }
tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS |
GRC_MODE_4X_NIC_SEND_RINGS |
tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE);
tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE);
}
-#if TG3_TSO_SUPPORT != 0
else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) {
int fw_len;
tw32(BUFMGR_MB_POOL_SIZE,
NIC_SRAM_MBUF_POOL_SIZE5705 - fw_len - 0xa00);
}
-#endif
if (tp->dev->mtu <= ETH_DATA_LEN) {
tw32(BUFMGR_MB_RDMA_LOW_WATER,
val = 1;
else if (val > tp->rx_std_max_post)
val = tp->rx_std_max_post;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1)
+ tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2);
+
+ if (val > (TG3_RX_INTERNAL_RING_SZ_5906 / 2))
+ val = TG3_RX_INTERNAL_RING_SZ_5906 / 2;
+ }
tw32(RCVBDI_STD_THRESH, val);
tp->rx_jumbo_ptr);
/* Initialize MAC address and backoff seed. */
- __tg3_set_mac_addr(tp);
+ __tg3_set_mac_addr(tp, 0);
/* MTU + ethernet header + FCS + optional VLAN tag */
tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + 8);
RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
RDMAC_MODE_LNGREAD_ENAB);
- if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
- rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+ rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB |
+ RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
+ RDMAC_MODE_MBUF_SBD_CRPT_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)) {
if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE &&
- (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
!(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
-#if TG3_TSO_SUPPORT != 0
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
rdmac_mode |= (1 << 27);
-#endif
/* Receive/send statistics. */
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+ !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+ tp->mac_mode |= MAC_MODE_LINK_POLARITY;
tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
udelay(40);
/* tp->grc_local_ctrl is partially set up during tg3_get_invariants().
- * If TG3_FLAG_EEPROM_WRITE_PROT is set, we should read the
+ * If TG3_FLG2_IS_NIC is zero, 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) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_IS_NIC)) {
u32 gpio_mask;
- gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT2;
+ gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 |
+ GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
gpio_mask |= GRC_LCLCTRL_GPIO_OE3 |
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL;
+ tp->grc_local_ctrl &= ~gpio_mask;
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);
+ if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)
+ tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+ GRC_LCLCTRL_GPIO_OUTPUT1);
}
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
udelay(100);
/* Enable host coalescing bug fix */
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787))
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784))
val |= (1 << 29);
tw32_f(WDMAC_MODE, val);
udelay(40);
- if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
- val = tr32(TG3PCI_X_CAPS);
+ if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
+ u16 pcix_cmd;
+
+ pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ &pcix_cmd);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
- val &= ~PCIX_CAPS_BURST_MASK;
- val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
+ pcix_cmd &= ~PCI_X_CMD_MAX_READ;
+ pcix_cmd |= PCI_X_CMD_READ_2K;
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
- val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
- val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
- if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
- val |= (tp->split_mode_max_reqs <<
- PCIX_CAPS_SPLIT_SHIFT);
+ pcix_cmd &= ~(PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ);
+ pcix_cmd |= PCI_X_CMD_READ_2K;
}
- tw32(TG3PCI_X_CAPS, val);
+ pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+ pcix_cmd);
}
tw32_f(RDMAC_MODE, rdmac_mode);
tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ);
tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
-#if TG3_TSO_SUPPORT != 0
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);
tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE);
return err;
}
-#if TG3_TSO_SUPPORT != 0
if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) {
err = tg3_load_tso_firmware(tp);
if (err)
return err;
}
-#endif
tp->tx_mode = TX_MODE_ENABLE;
tw32_f(MAC_TX_MODE, tp->tx_mode);
tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
}
- err = tg3_setup_phy(tp, reset_phy);
+ err = tg3_setup_phy(tp, 0);
if (err)
return err;
- if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
u32 tmp;
/* Clear CRC stats. */
- if (!tg3_readphy(tp, 0x1e, &tmp)) {
- tg3_writephy(tp, 0x1e, tmp | 0x8000);
+ if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) {
+ tg3_writephy(tp, MII_TG3_TEST1,
+ tmp | MII_TG3_TEST1_CRC_EN);
tg3_readphy(tp, 0x14, &tmp);
}
}
tp->timer_counter = tp->timer_multiplier;
}
- /* Heartbeat is only sent once every 2 seconds. */
+ /* Heartbeat is only sent once every 2 seconds.
+ *
+ * The heartbeat is to tell the ASF firmware that the host
+ * driver is still alive. In the event that the OS crashes,
+ * ASF needs to reset the hardware to free up the FIFO space
+ * that may be filled with rx packets destined for the host.
+ * If the FIFO is full, ASF will no longer function properly.
+ *
+ * Unintended resets have been reported on real time kernels
+ * where the timer doesn't run on time. Netpoll will also have
+ * same problem.
+ *
+ * The new FWCMD_NICDRV_ALIVE3 command tells the ASF firmware
+ * to check the ring condition when the heartbeat is expiring
+ * before doing the reset. This will prevent most unintended
+ * resets.
+ */
if (!--tp->asf_counter) {
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
u32 val;
tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
- FWCMD_NICDRV_ALIVE2);
+ FWCMD_NICDRV_ALIVE3);
tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
/* 5 seconds timeout */
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
static int tg3_request_irq(struct tg3 *tp)
{
- irqreturn_t (*fn)(int, void *, struct pt_regs *);
+ irq_handler_t fn;
unsigned long flags;
struct net_device *dev = tp->dev;
static int tg3_test_interrupt(struct tg3 *tp)
{
struct net_device *dev = tp->dev;
- int err, i;
- u32 int_mbox = 0;
+ int err, i, intr_ok = 0;
if (!netif_running(dev))
return -ENODEV;
HOSTCC_MODE_NOW);
for (i = 0; i < 5; i++) {
+ u32 int_mbox, misc_host_ctrl;
+
int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 +
TG3_64BIT_REG_LOW);
- if (int_mbox != 0)
+ misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
+
+ if ((int_mbox != 0) ||
+ (misc_host_ctrl & MISC_HOST_CTRL_MASK_PCI_INT)) {
+ intr_ok = 1;
break;
+ }
+
msleep(10);
}
if (err)
return err;
- if (int_mbox != 0)
+ if (intr_ok)
return 0;
return -EIO;
struct tg3 *tp = netdev_priv(dev);
int err;
+ netif_carrier_off(tp->dev);
+
tg3_full_lock(tp, 0);
err = tg3_set_power_state(tp, PCI_D0);
- if (err)
+ if (err) {
+ tg3_full_unlock(tp);
return err;
+ }
tg3_disable_ints(tp);
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
if (err)
return err;
- 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) &&
- !((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) &&
- (tp->pdev_peer == tp->pdev))) {
+ if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) {
/* All MSI supporting chips should support tagged
* status. Assert that this is the case.
*/
} else if (pci_enable_msi(tp->pdev) == 0) {
u32 msi_mode;
+ /* Hardware bug - MSI won't work if INTX disabled. */
+ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+ pci_intx(tp->pdev, 1);
+
msi_mode = tr32(MSGINT_MODE);
tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
return err;
}
+ napi_enable(&tp->napi);
+
tg3_full_lock(tp, 0);
err = tg3_init_hw(tp, 1);
tg3_full_unlock(tp);
if (err) {
+ napi_disable(&tp->napi);
free_irq(tp->pdev->irq, dev);
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
pci_disable_msi(tp->pdev);
tg3_full_unlock(tp);
+ napi_disable(&tp->napi);
+
return err;
}
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) {
- u32 val = tr32(0x7c04);
+ u32 val = tr32(PCIE_TRANSACTION_CFG);
- tw32(0x7c04, val | (1 << 29));
+ tw32(PCIE_TRANSACTION_CFG,
+ val | PCIE_TRANS_CFG_1SHOT_MSI);
}
}
}
{
struct tg3 *tp = netdev_priv(dev);
- /* Calling flush_scheduled_work() may deadlock because
- * linkwatch_event() may be on the workqueue and it will try to get
- * the rtnl_lock which we are holding.
- */
- while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK)
- msleep(1);
+ napi_disable(&tp->napi);
+ cancel_work_sync(&tp->reset_task);
netif_stop_queue(dev);
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
- tp->tg3_flags &=
- ~(TG3_FLAG_INIT_COMPLETE |
- TG3_FLAG_GOT_SERDES_FLOWCTL);
+ tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
tg3_full_unlock(tp);
u32 val;
spin_lock_bh(&tp->lock);
- if (!tg3_readphy(tp, 0x1e, &val)) {
- tg3_writephy(tp, 0x1e, val | 0x8000);
+ if (!tg3_readphy(tp, MII_TG3_TEST1, &val)) {
+ tg3_writephy(tp, MII_TG3_TEST1,
+ val | MII_TG3_TEST1_CRC_EN);
tg3_readphy(tp, 0x14, &val);
} else
val = 0;
buf = data;
if (b_offset || odd_len) {
buf = kmalloc(len, GFP_KERNEL);
- if (buf == 0)
+ if (!buf)
return -ENOMEM;
if (b_offset)
memcpy(buf, &start, 4);
tp->link_config.autoneg = cmd->autoneg;
if (cmd->autoneg == AUTONEG_ENABLE) {
- tp->link_config.advertising = cmd->advertising;
+ tp->link_config.advertising = (cmd->advertising |
+ ADVERTISED_Autoneg);
tp->link_config.speed = SPEED_INVALID;
tp->link_config.duplex = DUPLEX_INVALID;
} else {
tp->link_config.duplex = cmd->duplex;
}
+ tp->link_config.orig_speed = tp->link_config.speed;
+ tp->link_config.orig_duplex = tp->link_config.duplex;
+ tp->link_config.orig_autoneg = tp->link_config.autoneg;
+
if (netif_running(dev))
tg3_setup_phy(tp, 1);
{
struct tg3 *tp = netdev_priv(dev);
- wol->supported = WAKE_MAGIC;
+ if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+ wol->supported = WAKE_MAGIC;
+ else
+ wol->supported = 0;
wol->wolopts = 0;
if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
wol->wolopts = WAKE_MAGIC;
if (wol->wolopts & ~WAKE_MAGIC)
return -EINVAL;
if ((wol->wolopts & WAKE_MAGIC) &&
- tp->tg3_flags2 & TG3_FLG2_PHY_SERDES &&
- !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
+ !(tp->tg3_flags & TG3_FLAG_WOL_CAP))
return -EINVAL;
spin_lock_bh(&tp->lock);
tp->msg_enable = value;
}
-#if TG3_TSO_SUPPORT != 0
static int tg3_set_tso(struct net_device *dev, u32 value)
{
struct tg3 *tp = netdev_priv(dev);
return -EINVAL;
return 0;
}
- if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) {
+ if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) {
if (value)
dev->features |= NETIF_F_TSO6;
else
}
return ethtool_op_set_tso(dev, value);
}
-#endif
static int tg3_nway_reset(struct net_device *dev)
{
if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
(ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
- (ering->tx_pending > TG3_TX_RING_SIZE - 1))
+ (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
+ (ering->tx_pending <= MAX_SKB_FRAGS) ||
+ ((tp->tg3_flags2 & TG3_FLG2_TSO_BUG) &&
+ (ering->tx_pending <= (MAX_SKB_FRAGS * 3))))
return -EINVAL;
if (netif_running(dev)) {
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
- ethtool_op_set_tx_hw_csum(dev, data);
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+ ethtool_op_set_tx_ipv6_csum(dev, data);
else
ethtool_op_set_tx_csum(dev, data);
return 0;
}
-static int tg3_get_stats_count (struct net_device *dev)
+static int tg3_get_sset_count (struct net_device *dev, int sset)
{
- return TG3_NUM_STATS;
-}
-
-static int tg3_get_test_count (struct net_device *dev)
-{
- return TG3_NUM_TEST;
+ switch (sset) {
+ case ETH_SS_TEST:
+ return TG3_NUM_TEST;
+ case ETH_SS_STATS:
+ return TG3_NUM_STATS;
+ default:
+ return -EOPNOTSUPP;
+ }
}
static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
#define NVRAM_TEST_SIZE 0x100
#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_HW_SIZE 0x20
+#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
static int tg3_test_nvram(struct tg3 *tp)
{
u32 *buf, csum, magic;
- int i, j, err = 0, size;
+ int i, j, k, err = 0, size;
if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
return -EIO;
if (magic == TG3_EEPROM_MAGIC)
size = NVRAM_TEST_SIZE;
- else if ((magic & 0xff000000) == 0xa5000000) {
+ else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
if ((magic & 0xe00000) == 0x200000)
size = NVRAM_SELFBOOT_FORMAT1_SIZE;
else
return 0;
- } else
+ } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
+ size = NVRAM_SELFBOOT_HW_SIZE;
+ else
return -EIO;
buf = kmalloc(size, GFP_KERNEL);
goto out;
/* Selfboot format */
- if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) {
+ if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) ==
+ TG3_EEPROM_MAGIC_FW) {
u8 *buf8 = (u8 *) buf, csum8 = 0;
for (i = 0; i < size; i++)
goto out;
}
+ if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) ==
+ TG3_EEPROM_MAGIC_HW) {
+ u8 data[NVRAM_SELFBOOT_DATA_SIZE];
+ u8 parity[NVRAM_SELFBOOT_DATA_SIZE];
+ u8 *buf8 = (u8 *) buf;
+
+ /* Separate the parity bits and the data bytes. */
+ for (i = 0, j = 0, k = 0; i < NVRAM_SELFBOOT_HW_SIZE; i++) {
+ if ((i == 0) || (i == 8)) {
+ int l;
+ u8 msk;
+
+ for (l = 0, msk = 0x80; l < 7; l++, msk >>= 1)
+ parity[k++] = buf8[i] & msk;
+ i++;
+ }
+ else if (i == 16) {
+ int l;
+ u8 msk;
+
+ for (l = 0, msk = 0x20; l < 6; l++, msk >>= 1)
+ parity[k++] = buf8[i] & msk;
+ i++;
+
+ for (l = 0, msk = 0x80; l < 8; l++, msk >>= 1)
+ parity[k++] = buf8[i] & msk;
+ i++;
+ }
+ data[j++] = buf8[i];
+ }
+
+ err = -EIO;
+ for (i = 0; i < NVRAM_SELFBOOT_DATA_SIZE; i++) {
+ u8 hw8 = hweight8(data[i]);
+
+ if ((hw8 & 0x1) && parity[i])
+ goto out;
+ else if (!(hw8 & 0x1) && !parity[i])
+ goto out;
+ }
+ err = 0;
+ goto out;
+ }
+
/* Bootstrap checksum at offset 0x10 */
csum = calc_crc((unsigned char *) buf, 0x10);
if(csum != cpu_to_le32(buf[0x10/4]))
/* Only test the commonly used registers */
static int tg3_test_registers(struct tg3 *tp)
{
- int i, is_5705;
+ int i, is_5705, is_5750;
u32 offset, read_mask, write_mask, val, save_val, read_val;
static struct {
u16 offset;
#define TG3_FL_5705 0x1
#define TG3_FL_NOT_5705 0x2
#define TG3_FL_NOT_5788 0x4
+#define TG3_FL_NOT_5750 0x8
u32 read_mask;
u32 write_mask;
} reg_tbl[] = {
0xffffffff, 0x00000000 },
/* Buffer Manager Control Registers. */
- { BUFMGR_MB_POOL_ADDR, 0x0000,
+ { BUFMGR_MB_POOL_ADDR, TG3_FL_NOT_5750,
0x00000000, 0x007fff80 },
- { BUFMGR_MB_POOL_SIZE, 0x0000,
+ { BUFMGR_MB_POOL_SIZE, TG3_FL_NOT_5750,
0x00000000, 0x007fffff },
{ BUFMGR_MB_RDMA_LOW_WATER, 0x0000,
0x00000000, 0x0000003f },
{ 0xffff, 0x0000, 0x00000000, 0x00000000 },
};
- if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+ is_5705 = is_5750 = 0;
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
is_5705 = 1;
- else
- is_5705 = 0;
+ if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
+ is_5750 = 1;
+ }
for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705))
(reg_tbl[i].flags & TG3_FL_NOT_5788))
continue;
+ if (is_5750 && (reg_tbl[i].flags & TG3_FL_NOT_5750))
+ continue;
+
offset = (u32) reg_tbl[i].offset;
read_mask = reg_tbl[i].read_mask;
write_mask = reg_tbl[i].write_mask;
return 0;
out:
- printk(KERN_ERR PFX "Register test failed at offset %x\n", offset);
+ if (netif_msg_hw(tp))
+ printk(KERN_ERR PFX "Register test failed at offset %x\n",
+ offset);
tw32(offset, save_val);
return -EIO;
}
{ 0x00008000, 0x02000},
{ 0x00010000, 0x0c000},
{ 0xffffffff, 0x00000}
+ }, mem_tbl_5906[] = {
+ { 0x00000200, 0x00008},
+ { 0x00004000, 0x00400},
+ { 0x00006000, 0x00400},
+ { 0x00008000, 0x01000},
+ { 0x00010000, 0x01000},
+ { 0xffffffff, 0x00000}
};
struct mem_entry *mem_tbl;
int err = 0;
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
mem_tbl = mem_tbl_5755;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ mem_tbl = mem_tbl_5906;
else
mem_tbl = mem_tbl_5705;
} else
return 0;
mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
- MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
- MAC_MODE_PORT_MODE_GMII;
+ MAC_MODE_PORT_INT_LPBACK;
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+ mac_mode |= MAC_MODE_LINK_POLARITY;
+ if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
+ mac_mode |= MAC_MODE_PORT_MODE_MII;
+ else
+ mac_mode |= MAC_MODE_PORT_MODE_GMII;
tw32(MAC_MODE, mac_mode);
} else if (loopback_mode == TG3_PHY_LOOPBACK) {
- tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
- BMCR_SPEED1000);
+ u32 val;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 phytest;
+
+ if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phytest)) {
+ u32 phy;
+
+ tg3_writephy(tp, MII_TG3_EPHY_TEST,
+ phytest | MII_TG3_EPHY_SHADOW_EN);
+ if (!tg3_readphy(tp, 0x1b, &phy))
+ tg3_writephy(tp, 0x1b, phy & ~0x20);
+ tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
+ }
+ val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100;
+ } else
+ val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
+
+ tg3_phy_toggle_automdix(tp, 0);
+
+ tg3_writephy(tp, MII_BMCR, val);
udelay(40);
+
+ mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800);
+ mac_mode |= MAC_MODE_PORT_MODE_MII;
+ } else
+ mac_mode |= MAC_MODE_PORT_MODE_GMII;
+
/* reset to prevent losing 1st rx packet intermittently */
if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
tw32_f(MAC_RX_MODE, RX_MODE_RESET);
udelay(10);
tw32_f(MAC_RX_MODE, tp->rx_mode);
}
- mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
- MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
- if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
- mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+ if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+ mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411)
+ mac_mode |= MAC_MODE_LINK_POLARITY;
tg3_writephy(tp, MII_TG3_EXT_CTRL,
MII_TG3_EXT_CTRL_LNK3_LED_MODE);
}
udelay(10);
- for (i = 0; i < 10; i++) {
+ /* 250 usec to allow enough time on some 10/100 Mbps devices. */
+ for (i = 0; i < 25; i++) {
tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
HOSTCC_MODE_NOW);
/* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
__tg3_set_rx_mode(dev);
- tg3_full_unlock(tp);
-
if (netif_running(dev))
tg3_netif_start(tp);
-}
-
-static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- struct tg3 *tp = netdev_priv(dev);
- if (netif_running(dev))
- tg3_netif_stop(tp);
-
- tg3_full_lock(tp, 0);
- if (tp->vlgrp)
- tp->vlgrp->vlan_devices[vid] = NULL;
tg3_full_unlock(tp);
-
- if (netif_running(dev))
- tg3_netif_start(tp);
}
#endif
.set_pauseparam = tg3_set_pauseparam,
.get_rx_csum = tg3_get_rx_csum,
.set_rx_csum = tg3_set_rx_csum,
- .get_tx_csum = ethtool_op_get_tx_csum,
.set_tx_csum = tg3_set_tx_csum,
- .get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
-#if TG3_TSO_SUPPORT != 0
- .get_tso = ethtool_op_get_tso,
.set_tso = tg3_set_tso,
-#endif
- .self_test_count = tg3_get_test_count,
.self_test = tg3_self_test,
.get_strings = tg3_get_strings,
.phys_id = tg3_phys_id,
- .get_stats_count = tg3_get_stats_count,
.get_ethtool_stats = tg3_get_ethtool_stats,
.get_coalesce = tg3_get_coalesce,
.set_coalesce = tg3_set_coalesce,
- .get_perm_addr = ethtool_op_get_perm_addr,
+ .get_sset_count = tg3_get_sset_count,
};
static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
return;
- if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000))
+ if ((magic != TG3_EEPROM_MAGIC) &&
+ ((magic & TG3_EEPROM_MAGIC_FW_MSK) != TG3_EEPROM_MAGIC_FW) &&
+ ((magic & TG3_EEPROM_MAGIC_HW_MSK) != TG3_EEPROM_MAGIC_HW))
return;
/*
return;
}
}
- tp->nvram_size = 0x20000;
+ tp->nvram_size = 0x80000;
}
static void __devinit tg3_get_nvram_info(struct tg3 *tp)
static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
{
- u32 nvcfg1;
+ u32 nvcfg1, protect = 0;
nvcfg1 = tr32(NVRAM_CFG1);
/* NVRAM protection for TPM */
- if (nvcfg1 & (1 << 27))
+ if (nvcfg1 & (1 << 27)) {
tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
+ protect = 1;
+ }
- switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
- case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ:
- case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ:
- tp->nvram_jedecnum = JEDEC_ATMEL;
- tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
- tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
-
- nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
- tw32(NVRAM_CFG1, nvcfg1);
- break;
- case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+ nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
+ switch (nvcfg1) {
case FLASH_5755VENDOR_ATMEL_FLASH_1:
case FLASH_5755VENDOR_ATMEL_FLASH_2:
case FLASH_5755VENDOR_ATMEL_FLASH_3:
- case FLASH_5755VENDOR_ATMEL_FLASH_4:
+ case FLASH_5755VENDOR_ATMEL_FLASH_5:
tp->nvram_jedecnum = JEDEC_ATMEL;
tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
tp->tg3_flags2 |= TG3_FLG2_FLASH;
tp->nvram_pagesize = 264;
+ if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 ||
+ nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5)
+ tp->nvram_size = (protect ? 0x3e200 : 0x80000);
+ else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
+ tp->nvram_size = (protect ? 0x1f200 : 0x40000);
+ else
+ tp->nvram_size = (protect ? 0x1f200 : 0x20000);
break;
case FLASH_5752VENDOR_ST_M45PE10:
case FLASH_5752VENDOR_ST_M45PE20:
tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
tp->tg3_flags2 |= TG3_FLG2_FLASH;
tp->nvram_pagesize = 256;
+ if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10)
+ tp->nvram_size = (protect ? 0x10000 : 0x20000);
+ else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20)
+ tp->nvram_size = (protect ? 0x10000 : 0x40000);
+ else
+ tp->nvram_size = (protect ? 0x20000 : 0x80000);
break;
}
}
}
}
+static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
+{
+ u32 nvcfg1, protect = 0;
+
+ nvcfg1 = tr32(NVRAM_CFG1);
+
+ /* NVRAM protection for TPM */
+ if (nvcfg1 & (1 << 27)) {
+ tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
+ protect = 1;
+ }
+
+ nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
+ switch (nvcfg1) {
+ case FLASH_5761VENDOR_ATMEL_ADB021D:
+ case FLASH_5761VENDOR_ATMEL_ADB041D:
+ case FLASH_5761VENDOR_ATMEL_ADB081D:
+ case FLASH_5761VENDOR_ATMEL_ADB161D:
+ case FLASH_5761VENDOR_ATMEL_MDB021D:
+ case FLASH_5761VENDOR_ATMEL_MDB041D:
+ case FLASH_5761VENDOR_ATMEL_MDB081D:
+ case FLASH_5761VENDOR_ATMEL_MDB161D:
+ tp->nvram_jedecnum = JEDEC_ATMEL;
+ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+ tp->tg3_flags2 |= TG3_FLG2_FLASH;
+ tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+ tp->nvram_pagesize = 256;
+ break;
+ case FLASH_5761VENDOR_ST_A_M45PE20:
+ case FLASH_5761VENDOR_ST_A_M45PE40:
+ case FLASH_5761VENDOR_ST_A_M45PE80:
+ case FLASH_5761VENDOR_ST_A_M45PE16:
+ case FLASH_5761VENDOR_ST_M_M45PE20:
+ case FLASH_5761VENDOR_ST_M_M45PE40:
+ case FLASH_5761VENDOR_ST_M_M45PE80:
+ case FLASH_5761VENDOR_ST_M_M45PE16:
+ tp->nvram_jedecnum = JEDEC_ST;
+ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+ tp->tg3_flags2 |= TG3_FLG2_FLASH;
+ tp->nvram_pagesize = 256;
+ break;
+ }
+
+ if (protect) {
+ tp->nvram_size = tr32(NVRAM_ADDR_LOCKOUT);
+ } else {
+ switch (nvcfg1) {
+ case FLASH_5761VENDOR_ATMEL_ADB161D:
+ case FLASH_5761VENDOR_ATMEL_MDB161D:
+ case FLASH_5761VENDOR_ST_A_M45PE16:
+ case FLASH_5761VENDOR_ST_M_M45PE16:
+ tp->nvram_size = 0x100000;
+ break;
+ case FLASH_5761VENDOR_ATMEL_ADB081D:
+ case FLASH_5761VENDOR_ATMEL_MDB081D:
+ case FLASH_5761VENDOR_ST_A_M45PE80:
+ case FLASH_5761VENDOR_ST_M_M45PE80:
+ tp->nvram_size = 0x80000;
+ break;
+ case FLASH_5761VENDOR_ATMEL_ADB041D:
+ case FLASH_5761VENDOR_ATMEL_MDB041D:
+ case FLASH_5761VENDOR_ST_A_M45PE40:
+ case FLASH_5761VENDOR_ST_M_M45PE40:
+ tp->nvram_size = 0x40000;
+ break;
+ case FLASH_5761VENDOR_ATMEL_ADB021D:
+ case FLASH_5761VENDOR_ATMEL_MDB021D:
+ case FLASH_5761VENDOR_ST_A_M45PE20:
+ case FLASH_5761VENDOR_ST_M_M45PE20:
+ tp->nvram_size = 0x20000;
+ break;
+ }
+ }
+}
+
+static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
+{
+ tp->nvram_jedecnum = JEDEC_ATMEL;
+ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+ tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+}
+
/* Chips other than 5700/5701 use the NVRAM for fetching info. */
static void __devinit tg3_nvram_init(struct tg3 *tp)
{
- int j;
-
tw32_f(GRC_EEPROM_ADDR,
(EEPROM_ADDR_FSM_RESET |
(EEPROM_DEFAULT_CLOCK_PERIOD <<
EEPROM_ADDR_CLKPERD_SHIFT)));
- /* XXX schedule_timeout() ... */
- for (j = 0; j < 100; j++)
- udelay(10);
+ msleep(1);
/* Enable seeprom accesses. */
tw32_f(GRC_LOCAL_CTRL,
}
tg3_enable_nvram_access(tp);
+ tp->nvram_size = 0;
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
tg3_get_5752_nvram_info(tp);
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
tg3_get_5755_nvram_info(tp);
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
tg3_get_5787_nvram_info(tp);
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ tg3_get_5761_nvram_info(tp);
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ tg3_get_5906_nvram_info(tp);
else
tg3_get_nvram_info(tp);
- tg3_get_nvram_size(tp);
+ if (tp->nvram_size == 0)
+ tg3_get_nvram_size(tp);
tg3_disable_nvram_access(tp);
tg3_nvram_unlock(tp);
EEPROM_ADDR_ADDR_MASK) |
EEPROM_ADDR_READ | EEPROM_ADDR_START);
- for (i = 0; i < 10000; i++) {
+ for (i = 0; i < 1000; i++) {
tmp = tr32(GRC_EEPROM_ADDR);
if (tmp & EEPROM_ADDR_COMPLETE)
break;
- udelay(100);
+ msleep(1);
}
if (!(tmp & EEPROM_ADDR_COMPLETE))
return -EBUSY;
if ((tp->tg3_flags & TG3_FLAG_NVRAM) &&
(tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
(tp->tg3_flags2 & TG3_FLG2_FLASH) &&
+ !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) &&
(tp->nvram_jedecnum == JEDEC_ATMEL))
addr = ((addr / tp->nvram_pagesize) <<
if ((tp->tg3_flags & TG3_FLAG_NVRAM) &&
(tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
(tp->tg3_flags2 & TG3_FLG2_FLASH) &&
+ !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) &&
(tp->nvram_jedecnum == JEDEC_ATMEL))
addr = ((addr >> ATMEL_AT45DB0X1B_PAGE_POS) *
EEPROM_ADDR_START |
EEPROM_ADDR_WRITE);
- for (j = 0; j < 10000; j++) {
+ for (j = 0; j < 1000; j++) {
val = tr32(GRC_EEPROM_ADDR);
if (val & EEPROM_ADDR_COMPLETE)
break;
- udelay(100);
+ msleep(1);
}
if (!(val & EEPROM_ADDR_COMPLETE)) {
rc = -EBUSY;
if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784) &&
(tp->nvram_jedecnum == JEDEC_ST) &&
(nvram_cmd & NVRAM_CMD_FIRST)) {
tp->phy_id = PHY_ID_INVALID;
tp->led_ctrl = LED_CTRL_MODE_PHY_1;
- /* Assume an onboard device by default. */
- tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
+ /* Assume an onboard device and WOL capable by default. */
+ tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT | TG3_FLAG_WOL_CAP;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) {
+ tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+ tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
+ }
+ if (tr32(VCPU_CFGSHDW) & VCPU_CFGSHDW_ASPM_DBNC)
+ tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
+ return;
+ }
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
if (val == NIC_SRAM_DATA_SIG_MAGIC) {
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
- if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
+ if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
- else
+ if ((tp->pdev->subsystem_vendor ==
+ PCI_VENDOR_ID_ARIMA) &&
+ (tp->pdev->subsystem_device == 0x205a ||
+ tp->pdev->subsystem_device == 0x2063))
+ tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+ } else {
tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+ tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
+ }
if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
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 (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
+ !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL))
+ tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
if (cfg2 & (1 << 17))
tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
/* bootcode if bit 18 is set */
if (cfg2 & (1 << 18))
tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS;
+
+ if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+ u32 cfg3;
+
+ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3);
+ if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE)
+ tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
+ }
}
}
if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) &&
!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
- u32 bmsr, adv_reg, tg3_ctrl;
+ u32 bmsr, adv_reg, tg3_ctrl, mask;
tg3_readphy(tp, MII_BMSR, &bmsr);
if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
MII_TG3_CTRL_ENABLE_AS_MASTER);
}
- if (!tg3_copper_is_advertising_all(tp)) {
+ mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
+ if (!tg3_copper_is_advertising_all(tp, mask)) {
tg3_writephy(tp, MII_ADVERTISE, adv_reg);
if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY))
static void __devinit tg3_read_partno(struct tg3 *tp)
{
unsigned char vpd_data[256];
- int i;
+ unsigned int i;
u32 magic;
if (tg3_nvram_read_swab(tp, 0x0, &magic))
}
/* Now parse and find the part number. */
- for (i = 0; i < 256; ) {
+ for (i = 0; i < 254; ) {
unsigned char val = vpd_data[i];
- int block_end;
+ unsigned int block_end;
if (val == 0x82 || val == 0x91) {
i = (i + 3 +
(vpd_data[i + 1] +
(vpd_data[i + 2] << 8)));
i += 3;
- while (i < block_end) {
+
+ if (block_end > 256)
+ goto out_not_found;
+
+ while (i < (block_end - 2)) {
if (vpd_data[i + 0] == 'P' &&
vpd_data[i + 1] == 'N') {
int partno_len = vpd_data[i + 2];
- if (partno_len > 24)
+ i += 3;
+ if (partno_len > 24 || (partno_len + i) > 256)
goto out_not_found;
memcpy(tp->board_part_number,
- &vpd_data[i + 3],
- partno_len);
+ &vpd_data[i], partno_len);
/* Success. */
return;
}
+ i += 3 + vpd_data[i + 2];
}
/* Part number not found. */
}
out_not_found:
- strcpy(tp->board_part_number, "none");
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ strcpy(tp->board_part_number, "BCM95906");
+ else
+ strcpy(tp->board_part_number, "none");
}
static void __devinit tg3_read_fw_ver(struct tg3 *tp)
}
}
+static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
+
static int __devinit tg3_get_invariants(struct tg3 *tp)
{
static struct pci_device_id write_reorder_chipsets[] = {
u32 pci_state_reg, grc_misc_cfg;
u32 val;
u16 pci_cmd;
- int err;
+ int err, pcie_cap;
/* Force memory write invalidate off. If we leave it on,
* then on 5700_BX chips we have to enable a workaround.
tp->pci_chip_rev_id = (misc_ctrl_reg >>
MISC_HOST_CTRL_CHIPREV_SHIFT);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
+ u32 prod_id_asic_rev;
+
+ pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
+ &prod_id_asic_rev);
+ tp->pci_chip_rev_id = prod_id_asic_rev & PROD_ID_ASIC_REV_MASK;
+ }
/* Wrong chip ID in 5752 A0. This code can be removed later
* as A0 is not in production.
continue;
}
if (pci_id->rev != PCI_ANY_ID) {
- u8 rev;
-
- pci_read_config_byte(bridge, PCI_REVISION_ID,
- &rev);
- if (rev > pci_id->rev)
+ if (bridge->revision > pci_id->rev)
continue;
}
if (bridge->subordinate &&
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_5704) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
+ tp->pdev_peer = tg3_find_peer(tp);
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
+ tp->tg3_flags |= TG3_FLAG_SUPPORT_MSI;
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX ||
+ GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 &&
+ tp->pci_chip_rev_id <= CHIPREV_ID_5714_A2 &&
+ tp->pdev_peer == tp->pdev))
+ tp->tg3_flags &= ~TG3_FLAG_SUPPORT_MSI;
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
} else {
- tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 |
- TG3_FLG2_HW_TSO_1_BUG;
+ tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | TG3_FLG2_TSO_BUG;
if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
ASIC_REV_5750 &&
tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2)
- tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_1_BUG;
+ tp->tg3_flags2 &= ~TG3_FLG2_TSO_BUG;
}
}
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
- if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
+ pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
+ if (pcie_cap != 0) {
tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u16 lnkctl;
+
+ pci_read_config_word(tp->pdev,
+ pcie_cap + PCI_EXP_LNKCTL,
+ &lnkctl);
+ if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN)
+ tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2;
+ }
+ }
/* If we have an AMD 762 or VIA K8T800 chipset, write
* reordering to the mailbox registers done by the host
cacheline_sz_reg);
}
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+ (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+ tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
+ if (!tp->pcix_cap) {
+ printk(KERN_ERR PFX "Cannot find PCI-X "
+ "capability, aborting.\n");
+ return -EIO;
+ }
+ }
+
pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
&pci_state_reg);
- if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
+ if (tp->pcix_cap && (pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
/* If this is a 5700 BX chipset, and we are in PCI-X
*/
if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
u32 pm_reg;
- u16 pci_cmd;
tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
* space registers clobbered due to this bug.
* So explicitly force the chip into D0 here.
*/
- pci_read_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT,
+ pci_read_config_dword(tp->pdev,
+ tp->pm_cap + PCI_PM_CTRL,
&pm_reg);
pm_reg &= ~PCI_PM_CTRL_STATE_MASK;
pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */;
- pci_write_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT,
+ pci_write_config_dword(tp->pdev,
+ tp->pm_cap + PCI_PM_CTRL,
pm_reg);
/* Also, force SERR#/PERR# in PCI command. */
if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
- /* Back to back register writes can cause problems on this chip,
- * the workaround is to read back all reg writes except those to
- * mailbox regs. See tg3_write_indirect_reg32().
- *
- * PCI Express 5750_A0 rev chips need this workaround too.
- */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
- ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
- tp->pci_chip_rev_id == CHIPREV_ID_5750_A0))
- tp->tg3_flags |= TG3_FLAG_5701_REG_WRITE_BUG;
-
if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
/* Various workaround register access methods */
if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG)
tp->write32 = tg3_write_indirect_reg32;
- else if (tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG)
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
+ ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
+ tp->pci_chip_rev_id == CHIPREV_ID_5750_A0)) {
+ /*
+ * Back to back register writes can cause problems on these
+ * chips, the workaround is to read back all reg writes
+ * except those to mailbox regs.
+ *
+ * See tg3_write_indirect_reg32().
+ */
tp->write32 = tg3_write_flush_reg32;
+ }
+
if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
pci_cmd &= ~PCI_COMMAND_MEMORY;
pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
}
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tp->read32_mbox = tg3_read32_mbox_5906;
+ tp->write32_mbox = tg3_write32_mbox_5906;
+ tp->write32_tx_mbox = tg3_write32_mbox_5906;
+ tp->write32_rx_mbox = tg3_write32_mbox_5906;
+ }
if (tp->write32 == tg3_write_indirect_reg32 ||
((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
/* Get eeprom hw config before calling tg3_set_power_state().
- * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
+ * In particular, the TG3_FLG2_IS_NIC 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
*/
tg3_get_eeprom_hw_cfg(tp);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+ tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
+
/* 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.
((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
(tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
(tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) ||
(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
- tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
- else
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784) {
+ if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 &&
+ tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722)
+ tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
+ if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
+ tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
}
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))
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_5753F)))
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
+ tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
err = tg3_phy_probe(tp);
* upon subsystem IDs.
*/
if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
TG3_FLAG_USE_LINKCHG_REG);
* straddle the 4GB address boundary in some cases.
*/
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
tp->dev->hard_start_xmit = tg3_start_xmit;
else
tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug;
*/
tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
+ if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND)
+ tp->pwrmgmt_thresh = tr32(PCIE_PWR_MGMT_THRESH) &
+ PCIE_PWR_MGMT_L1_THRESH_MSK;
+
return err;
}
-#ifdef CONFIG_SPARC64
+#ifdef CONFIG_SPARC
static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
{
struct net_device *dev = tp->dev;
struct pci_dev *pdev = tp->pdev;
- struct pcidev_cookie *pcp = pdev->sysdata;
-
- if (pcp != NULL) {
- unsigned char *addr;
- int len;
-
- addr = of_get_property(pcp->prom_node, "local-mac-address",
- &len);
- if (addr && len == 6) {
- memcpy(dev->dev_addr, addr, 6);
- memcpy(dev->perm_addr, dev->dev_addr, 6);
- return 0;
- }
+ struct device_node *dp = pci_device_to_OF_node(pdev);
+ const unsigned char *addr;
+ int len;
+
+ addr = of_get_property(dp, "local-mac-address", &len);
+ if (addr && len == 6) {
+ memcpy(dev->dev_addr, addr, 6);
+ memcpy(dev->perm_addr, dev->dev_addr, 6);
+ return 0;
}
return -ENODEV;
}
u32 hi, lo, mac_offset;
int addr_ok = 0;
-#ifdef CONFIG_SPARC64
+#ifdef CONFIG_SPARC
if (!tg3_get_macaddr_sparc(tp))
return 0;
#endif
else
tg3_nvram_unlock(tp);
}
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ mac_offset = 0x10;
/* First try to get it from MAC address mailbox. */
tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
+ u32 read_water = 0x7;
/* If the 5704 is behind the EPB bridge, we can
* do the less restrictive ONE_DMA workaround for
else if (ccval == 0x6 || ccval == 0x7)
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703)
+ read_water = 4;
/* Set bit 23 to enable PCIX hw bug fix */
- tp->dma_rwctrl |= 0x009f0000;
+ tp->dma_rwctrl |=
+ (read_water << DMA_RWCTRL_READ_WATER_SHIFT) |
+ (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
+ (1 << 23);
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
/* 5780 always in PCIX mode */
tp->dma_rwctrl |= 0x00144000;
DEFAULT_MB_MACRX_LOW_WATER_5705;
tp->bufmgr_config.mbuf_high_water =
DEFAULT_MB_HIGH_WATER_5705;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ tp->bufmgr_config.mbuf_mac_rx_low_water =
+ DEFAULT_MB_MACRX_LOW_WATER_5906;
+ tp->bufmgr_config.mbuf_high_water =
+ DEFAULT_MB_HIGH_WATER_5906;
+ }
tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780;
case PHY_ID_BCM5780: return "5780";
case PHY_ID_BCM5755: return "5755";
case PHY_ID_BCM5787: return "5787";
+ case PHY_ID_BCM5784: return "5784";
+ case PHY_ID_BCM5756: return "5722/5756";
+ case PHY_ID_BCM5906: return "5906";
case PHY_ID_BCM8002: return "8002/serdes";
case 0: return "serdes";
default: return "unknown";
goto err_out_free_res;
}
- SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
#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;
- dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid;
#endif
tp = netdev_priv(dev);
#endif
spin_lock_init(&tp->lock);
spin_lock_init(&tp->indirect_lock);
- INIT_WORK(&tp->reset_task, tg3_reset_task, tp);
+ INIT_WORK(&tp->reset_task, tg3_reset_task);
tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len);
- if (tp->regs == 0UL) {
+ if (!tp->regs) {
printk(KERN_ERR PFX "Cannot map device registers, "
"aborting.\n");
err = -ENOMEM;
dev->set_mac_address = tg3_set_mac_addr;
dev->do_ioctl = tg3_ioctl;
dev->tx_timeout = tg3_tx_timeout;
- dev->poll = tg3_poll;
+ netif_napi_add(dev, &tp->napi, tg3_poll, 64);
dev->ethtool_ops = &tg3_ethtool_ops;
- dev->weight = 64;
dev->watchdog_timeo = TG3_TX_TIMEOUT;
dev->change_mtu = tg3_change_mtu;
dev->irq = pdev->irq;
tg3_init_bufmgr_config(tp);
-#if TG3_TSO_SUPPORT != 0
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 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) {
tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
} else {
- tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
+ tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG;
}
/* TSO is on by default on chips that support hardware TSO.
*/
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
dev->features |= NETIF_F_TSO;
- if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2)
+ if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906))
dev->features |= NETIF_F_TSO6;
}
-#endif
if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 &&
!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) &&
tp->rx_pending = 63;
}
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
- tp->pdev_peer = tg3_find_peer(tp);
-
err = tg3_get_device_address(tp);
if (err) {
printk(KERN_ERR PFX "Could not obtain valid ethernet address, "
*/
if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
- pci_save_state(tp->pdev);
tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
}
* checksumming.
*/
if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
- dev->features |= NETIF_F_HW_CSUM;
- else
- dev->features |= NETIF_F_IP_CSUM;
- dev->features |= NETIF_F_SG;
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+ dev->features |= NETIF_F_IPV6_CSUM;
+
tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
} else
tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
tg3_init_coal(tp);
- /* Now that we have fully setup the chip, save away a snapshot
- * of the PCI config space. We need to restore this after
- * GRC_MISC_CFG core clock resets and some resume events.
- */
- pci_save_state(tp->pdev);
+ pci_set_drvdata(pdev, dev);
err = register_netdev(dev);
if (err) {
goto err_out_iounmap;
}
- pci_set_drvdata(pdev, dev);
-
- printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ",
+ printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ",
dev->name,
tp->board_part_number,
tp->pci_chip_rev_id,
tg3_phy_string(tp),
tg3_bus_string(tp, str),
- (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
+ ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
+ ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
+ "10/100/1000Base-T")));
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i],
i == 5 ? '\n' : ':');
printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
- "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
- "TSOcap[%d] \n",
+ "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n",
dev->name,
(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,
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
- (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
(tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
(pdev->dma_mask == DMA_32BIT_MASK) ? 32 :
(((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64));
- netif_carrier_off(tp->dev);
-
return 0;
err_out_iounmap:
struct tg3 *tp = netdev_priv(dev);
int err;
+ /* PCI register 4 needs to be saved whether netif_running() or not.
+ * MSI address and data need to be saved if using MSI and
+ * netif_running().
+ */
+ pci_save_state(pdev);
+
if (!netif_running(dev))
return 0;
struct tg3 *tp = netdev_priv(dev);
int err;
+ pci_restore_state(tp->pdev);
+
if (!netif_running(dev))
return 0;
- pci_restore_state(tp->pdev);
-
err = tg3_set_power_state(tp, PCI_D0);
if (err)
return err;
+ /* Hardware bug - MSI won't work if INTX disabled. */
+ if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
+ (tp->tg3_flags2 & TG3_FLG2_USING_MSI))
+ pci_intx(tp->pdev, 1);
+
netif_device_attach(dev);
tg3_full_lock(tp, 0);