From: John Feeney <jfeeney@redhat.com> Date: Fri, 5 Feb 2010 22:10:08 -0500 Subject: [net] tg3: update to version 3.106 for 57765 asic support Message-id: <4B6C9740.9070402@redhat.com> Patchwork-id: 23167 O-Subject: Re: [RHEL5.5 PATCH] Update tg3 to version 3.106 for 57765 asic Bugzilla: 545135 RH-Acked-by: Stanislaw Gruszka <sgruszka@redhat.com> RH-Acked-by: Ivan Vecera <ivecera@redhat.com> bz545135 https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=545135 Add support for 57765 asic revs drivers/net/tg3.c | 2801 ++++++++++++++++++++++++++++++++--------------- drivers/net/tg3.h | 256 ++++- include/linux/pci_ids.h | 1 - 3 files changed, 2135 insertions(+), 923 deletions(-) Signed-off-by: Jarod Wilson <jarod@redhat.com> diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index bcee26f..a8e39e7 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4,7 +4,7 @@ * 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-2009 Broadcom Corporation. + * Copyright (C) 2005-2010 Broadcom Corporation. * * Firmware is: * Derived from proprietary unpublished source code, @@ -67,8 +67,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.100" -#define DRV_MODULE_RELDATE "August 25, 2009" +#define DRV_MODULE_VERSION "3.106" +#define DRV_MODULE_RELDATE "January 12, 2010" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -91,7 +91,7 @@ /* hardware minimum and maximum for a single frame's data payload */ #define TG3_MIN_MTU 60 #define TG3_MAX_MTU(tp) \ - ((tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) ? 9000 : 1500) + ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) ? 9000 : 1500) /* These numbers seem to be hard coded in the NIC firmware somehow. * You can't change the ring sizes, but you can change where you place @@ -101,6 +101,7 @@ #define TG3_DEF_RX_RING_PENDING 200 #define TG3_RX_JUMBO_RING_SIZE 256 #define TG3_DEF_RX_JUMBO_RING_PENDING 100 +#define TG3_RSS_INDIR_TBL_SIZE 128 /* Do not place this n-ring entries value into the tp struct itself, * we really want to expose these constants to GCC so that modulo et @@ -109,26 +110,40 @@ * replace things like '% foo' with '& (foo - 1)'. */ #define TG3_RX_RCB_RING_SIZE(tp) \ - ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ? 512 : 1024) + (((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && \ + !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) ? 1024 : 512) #define TG3_TX_RING_SIZE 512 #define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1) #define TG3_RX_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ TG3_RX_RING_SIZE) -#define TG3_RX_JUMBO_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ - TG3_RX_JUMBO_RING_SIZE) +#define TG3_RX_JUMBO_RING_BYTES (sizeof(struct tg3_ext_rx_buffer_desc) * \ + TG3_RX_JUMBO_RING_SIZE) #define TG3_RX_RCB_RING_BYTES(tp) (sizeof(struct tg3_rx_buffer_desc) * \ - TG3_RX_RCB_RING_SIZE(tp)) + TG3_RX_RCB_RING_SIZE(tp)) #define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \ TG3_TX_RING_SIZE) #define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) -#define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64) -#define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64) +#define TG3_DMA_BYTE_ENAB 64 + +#define TG3_RX_STD_DMA_SZ 1536 +#define TG3_RX_JMB_DMA_SZ 9046 + +#define TG3_RX_DMA_TO_MAP_SZ(x) ((x) + TG3_DMA_BYTE_ENAB) + +#define TG3_RX_STD_MAP_SZ TG3_RX_DMA_TO_MAP_SZ(TG3_RX_STD_DMA_SZ) +#define TG3_RX_JMB_MAP_SZ TG3_RX_DMA_TO_MAP_SZ(TG3_RX_JMB_DMA_SZ) + +#define TG3_RX_STD_BUFF_RING_SIZE \ + (sizeof(struct ring_info) * TG3_RX_RING_SIZE) + +#define TG3_RX_JMB_BUFF_RING_SIZE \ + (sizeof(struct ring_info) * TG3_RX_JUMBO_RING_SIZE) /* minimum number of free TX descriptors required to wake up TX process */ -#define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4) +#define TG3_TX_WAKEUP_THRESH(tnapi) ((tnapi)->tx_pending / 4) #define TG3_RAW_IP_ALIGN 2 @@ -145,6 +160,8 @@ MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); +#define TG3_RSS_MIN_NUM_MSIX_VECS 2 + static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ module_param(tg3_debug, int, 0); MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); @@ -210,12 +227,21 @@ static struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761S)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5785)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5724)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, {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)}, @@ -377,7 +403,7 @@ static void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val) TG3_64BIT_REG_LOW, val); return; } - if (off == (MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW)) { + if (off == TG3_RX_STD_PROD_IDX_REG) { pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_LOW, val); return; @@ -597,39 +623,47 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) static void tg3_disable_ints(struct tg3 *tp) { + int i; + tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT)); - tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); -} - -static inline void tg3_cond_int(struct tg3 *tp) -{ - 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)); + for (i = 0; i < tp->irq_max; i++) + tw32_mailbox_f(tp->napi[i].int_mbox, 0x00000001); } static void tg3_enable_ints(struct tg3 *tp) { + int i; + u32 coal_now = 0; + tp->irq_sync = 0; wmb(); tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); - tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - (tp->last_tag << 24)); - if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) - tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - (tp->last_tag << 24)); - tg3_cond_int(tp); + + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24); + if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) + tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24); + + coal_now |= tnapi->coal_now; + } + + /* Force an initial interrupt */ + if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) && + (tp->napi[0].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 | coal_now); } -static inline unsigned int tg3_has_work(struct tg3 *tp) +static inline unsigned int tg3_has_work(struct tg3_napi *tnapi) { - struct tg3_hw_status *sblk = tp->hw_status; + struct tg3 *tp = tnapi->tp; + struct tg3_hw_status *sblk = tnapi->hw_status; unsigned int work_exists = 0; /* check for phy events */ @@ -640,22 +674,23 @@ static inline unsigned int tg3_has_work(struct tg3 *tp) work_exists = 1; } /* check for RX/TX work to do */ - if (sblk->idx[0].tx_consumer != tp->tx_cons || - sblk->idx[0].rx_producer != tp->rx_rcb_ptr) + if (sblk->idx[0].tx_consumer != tnapi->tx_cons || + *(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr) work_exists = 1; return work_exists; } -/* tg3_restart_ints +/* tg3_int_reenable * similar to tg3_enable_ints, but it accurately determines whether there * is new work pending and can return without flushing the PIO write * which reenables interrupts */ -static void tg3_restart_ints(struct tg3 *tp) +static void tg3_int_reenable(struct tg3_napi *tnapi) { - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - tp->last_tag << 24); + struct tg3 *tp = tnapi->tp; + + tw32_mailbox(tnapi->int_mbox, tnapi->last_tag << 24); mmiowb(); /* When doing tagged status, this work check is unnecessary. @@ -663,15 +698,31 @@ static void tg3_restart_ints(struct tg3 *tp) * work we've completed. */ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) && - tg3_has_work(tp)) + tg3_has_work(tnapi)) tw32(HOSTCC_MODE, tp->coalesce_mode | - (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); + HOSTCC_MODE_ENABLE | tnapi->coal_now); +} + +static void tg3_napi_disable(struct tg3 *tp) +{ + int i; + + for (i = tp->irq_cnt - 1; i >= 0; i--) + netif_poll_disable(tp->napi[i].dummy_netdev); +} + +static void tg3_napi_enable(struct tg3 *tp) +{ + int i; + + for (i = 0; i < tp->irq_cnt; i++) + netif_poll_enable(tp->napi[i].dummy_netdev); } static inline void tg3_netif_stop(struct tg3 *tp) { tp->dev->trans_start = jiffies; /* prevent tx timeout */ - netif_poll_disable(tp->dev); + tg3_napi_disable(tp); netif_tx_disable(tp->dev); } @@ -682,20 +733,22 @@ static inline void tg3_netif_start(struct tg3 *tp) * so long as all callers are assured to have free tx slots * (such as after tg3_init_hw) */ - netif_poll_enable(tp->dev); - tp->hw_status->status |= SD_STATUS_UPDATED; + tg3_napi_enable(tp); + tp->napi[0].hw_status->status |= SD_STATUS_UPDATED; tg3_enable_ints(tp); } static void tg3_switch_clocks(struct tg3 *tp) { - u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL); + u32 clock_ctrl; u32 orig_clock_ctrl; if ((tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) return; + clock_ctrl = tr32(TG3PCI_CLOCK_CTRL); + orig_clock_ctrl = clock_ctrl; clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE | @@ -735,7 +788,7 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) *val = 0x0; - frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & + frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) & MI_COM_PHY_ADDR_MASK); frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & MI_COM_REG_ADDR_MASK); @@ -786,7 +839,7 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) udelay(80); } - frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & + frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) & MI_COM_PHY_ADDR_MASK); frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & MI_COM_REG_ADDR_MASK); @@ -858,6 +911,25 @@ static void tg3_mdio_start(struct tg3 *tp) tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { + u32 funcnum, is_serdes; + + funcnum = tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC; + if (funcnum) + tp->phy_addr = 2; + else + tp->phy_addr = 1; + + if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) + is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES; + else + is_serdes = tr32(TG3_CPMU_PHY_STRAP) & + TG3_CPMU_PHY_STRAP_IS_SERDES; + if (is_serdes) + tp->phy_addr += 7; + } else + tp->phy_addr = PHY_ADDR; + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) return; @@ -865,7 +937,9 @@ static void tg3_mdio_start(struct tg3 *tp) tw32(MAC_PHYCFG2, MAC_PHYCFG2_AC131_LED_MODES); val = tr32(MAC_PHYCFG1); - val &= ~MAC_PHYCFG1_RGMII_INT; + val &= ~(MAC_PHYCFG1_RGMII_INT | + MAC_PHYCFG1_RXCLK_TO_MASK | MAC_PHYCFG1_TXCLK_TO_MASK); + val |= MAC_PHYCFG1_RXCLK_TIMEOUT | MAC_PHYCFG1_TXCLK_TIMEOUT; tw32(MAC_PHYCFG1, val); return; @@ -883,15 +957,18 @@ static void tg3_mdio_start(struct tg3 *tp) tw32(MAC_PHYCFG2, val); - val = tr32(MAC_PHYCFG1) & ~(MAC_PHYCFG1_RGMII_EXT_RX_DEC | - MAC_PHYCFG1_RGMII_SND_STAT_EN); + val = tr32(MAC_PHYCFG1); + val &= ~(MAC_PHYCFG1_RXCLK_TO_MASK | MAC_PHYCFG1_TXCLK_TO_MASK | + MAC_PHYCFG1_RGMII_EXT_RX_DEC | MAC_PHYCFG1_RGMII_SND_STAT_EN); if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) { if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) val |= MAC_PHYCFG1_RGMII_EXT_RX_DEC; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) val |= MAC_PHYCFG1_RGMII_SND_STAT_EN; } - tw32(MAC_PHYCFG1, val | MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_TXC_DRV); + val |= MAC_PHYCFG1_RXCLK_TIMEOUT | MAC_PHYCFG1_TXCLK_TIMEOUT | + MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_TXC_DRV; + tw32(MAC_PHYCFG1, val); val = tr32(MAC_EXT_RGMII_MODE); val &= ~(MAC_RGMII_MODE_RX_INT_B | @@ -1511,6 +1588,63 @@ static int tg3_phy_reset(struct tg3 *tp) tg3_phy_toggle_apd(tp, false); out: + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM50610 || + (tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM50610M) { + u32 reg; + + /* Enable SM_DSP clock and tx 6dB coding. */ + reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | + MII_TG3_AUXCTL_ACTL_SMDSP_ENA | + MII_TG3_AUXCTL_ACTL_TX_6DB; + tg3_writephy(tp, MII_TG3_AUX_CTRL, reg); + + reg = MII_TG3_DSP_EXP8_REJ2MHz; + tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, reg); + + /* Apply workaround to A0 revision parts only. */ + if (tp->phy_id == PHY_ID_BCM50610 || + tp->phy_id == PHY_ID_BCM50610M) { + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x001F); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0300); + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x601F); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0002); + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0F75); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x003C); + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0F96); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0010); + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0F97); + } + + /* Turn off SM_DSP clock. */ + reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | + MII_TG3_AUXCTL_ACTL_TX_6DB; + tg3_writephy(tp, MII_TG3_AUX_CTRL, reg); + + /* Clear all mode configuration bits. */ + reg = MII_TG3_MISC_SHDW_WREN | + MII_TG3_MISC_SHDW_RGMII_SEL; + tg3_writephy(tp, MII_TG3_MISC_SHDW, reg); + } + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM57780) { + u32 reg; + + /* Enable SM_DSP clock and tx 6dB coding. */ + reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | + MII_TG3_AUXCTL_ACTL_SMDSP_ENA | + MII_TG3_AUXCTL_ACTL_TX_6DB; + tg3_writephy(tp, MII_TG3_AUX_CTRL, reg); + + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, MII_TG3_DSP_EXP75); + tg3_readphy(tp, MII_TG3_DSP_RW_PORT, ®); + reg |= MII_TG3_DSP_EXP75_SUP_CM_OSC; + tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, reg); + + /* Turn off SM_DSP clock. */ + reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | + MII_TG3_AUXCTL_ACTL_TX_6DB; + tg3_writephy(tp, MII_TG3_AUX_CTRL, reg); + } + if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); @@ -1544,12 +1678,15 @@ out: 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 */ /* support jumbo frames */ if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { /* Cannot do read-modify-write on 5401 */ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20); - } else if (tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) { + } else if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 || + !(tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) { u32 phy_reg; /* Set bit 14 with read-modify-write to preserve other bits */ @@ -1561,7 +1698,7 @@ out: /* Set phy register 0x10 bit 0 to high fifo elasticity to support * jumbo frames transmission. */ - if (tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) { + if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { u32 phy_reg; if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &phy_reg)) @@ -1595,11 +1732,13 @@ static void tg3_frob_aux_power(struct tg3 *tp) { struct tg3 *tp_peer = tp; - if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0) + if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) return; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { struct net_device *dev_peer; dev_peer = pci_get_drvdata(tp->pdev_peer); @@ -1743,13 +1882,33 @@ static void tg3_power_down_phy(struct tg3 *tp) } if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { + u32 phytest; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { tg3_bmcr_reset(tp); val = tr32(GRC_MISC_CFG); tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); udelay(40); return; + } else if (!tg3_readphy(tp, MII_TG3_FET_TEST, &phytest)) { + u32 phy; + + tg3_writephy(tp, MII_ADVERTISE, 0); + tg3_writephy(tp, MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART); + + tg3_writephy(tp, MII_TG3_FET_TEST, + phytest | MII_TG3_FET_SHADOW_EN); + if (!tg3_readphy(tp, MII_TG3_FET_SHDW_AUXMODE4, &phy)) { + phy |= MII_TG3_FET_SHDW_AUXMODE4_SBPD; + tg3_writephy(tp, + MII_TG3_FET_SHDW_AUXMODE4, + phy); + } + tg3_writephy(tp, MII_TG3_FET_TEST, phytest); } + + return; } else if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF); @@ -1813,7 +1972,7 @@ static void tg3_nvram_unlock(struct tg3 *tp) static void tg3_enable_nvram_access(struct tg3 *tp) { if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && - !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) { + !(tp->tg3_flags3 & TG3_FLG3_PROTECTED_NVRAM)) { u32 nvaccess = tr32(NVRAM_ACCESS); tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); @@ -1824,7 +1983,7 @@ static void tg3_enable_nvram_access(struct tg3 *tp) static void tg3_disable_nvram_access(struct tg3 *tp) { if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && - !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) { + !(tp->tg3_flags3 & TG3_FLG3_PROTECTED_NVRAM)) { u32 nvaccess = tr32(NVRAM_ACCESS); tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); @@ -2820,15 +2979,6 @@ relink: pci_write_config_word(tp->pdev, tp->pcie_cap + PCI_EXP_LNKCTL, newlnkctl); - } else if (tp->tg3_flags3 & TG3_FLG3_TOGGLE_10_100_L1PLLPD) { - u32 newreg, oldreg = tr32(TG3_PCIE_LNKCTL); - if (tp->link_config.active_speed == SPEED_100 || - tp->link_config.active_speed == SPEED_10) - newreg = oldreg & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; - else - newreg = oldreg | TG3_PCIE_LNKCTL_L1_PLL_PD_EN; - if (newreg != oldreg) - tw32(TG3_PCIE_LNKCTL, newreg); } if (current_link_up != netif_carrier_ok(tp->dev)) { @@ -3510,9 +3660,9 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) else current_link_up = tg3_setup_fiber_by_hand(tp, mac_status); - tp->hw_status->status = + tp->napi[0].hw_status->status = (SD_STATUS_UPDATED | - (tp->hw_status->status & ~SD_STATUS_LINK_CHG)); + (tp->napi[0].hw_status->status & ~SD_STATUS_LINK_CHG)); for (i = 0; i < 100; i++) { tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | @@ -3878,24 +4028,25 @@ static void tg3_tx_recover(struct tg3 *tp) spin_unlock(&tp->lock); } -static inline u32 tg3_tx_avail(struct tg3 *tp) +static inline u32 tg3_tx_avail(struct tg3_napi *tnapi) { smp_mb(); - return (tp->tx_pending - - ((tp->tx_prod - tp->tx_cons) & (TG3_TX_RING_SIZE - 1))); + return tnapi->tx_pending - + ((tnapi->tx_prod - tnapi->tx_cons) & (TG3_TX_RING_SIZE - 1)); } /* Tigon3 never reports partial packet sends. So we do not * need special logic to handle SKBs that have not had all * of their frags sent yet, like SunGEM does. */ -static void tg3_tx(struct tg3 *tp) +static void tg3_tx(struct tg3_napi *tnapi) { - u32 hw_idx = tp->hw_status->idx[0].tx_consumer; - u32 sw_idx = tp->tx_cons; + struct tg3 *tp = tnapi->tp; + u32 hw_idx = tnapi->hw_status->idx[0].tx_consumer; + u32 sw_idx = tnapi->tx_cons; while (sw_idx != hw_idx) { - struct tx_ring_info *ri = &tp->tx_buffers[sw_idx]; + struct tx_ring_info *ri = &tnapi->tx_buffers[sw_idx]; struct sk_buff *skb = ri->skb; int i, tx_bug = 0; @@ -3914,7 +4065,7 @@ static void tg3_tx(struct tg3 *tp) sw_idx = NEXT_TX(sw_idx); for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - ri = &tp->tx_buffers[sw_idx]; + ri = &tnapi->tx_buffers[sw_idx]; if (unlikely(ri->skb != NULL || sw_idx == hw_idx)) tx_bug = 1; @@ -3934,7 +4085,7 @@ static void tg3_tx(struct tg3 *tp) } } - tp->tx_cons = sw_idx; + tnapi->tx_cons = sw_idx; /* Need to make the tx_cons update visible to tg3_start_xmit() * before checking for netif_queue_stopped(). Without the @@ -3944,15 +4095,26 @@ static void tg3_tx(struct tg3 *tp) smp_mb(); if (unlikely(netif_queue_stopped(tp->dev) && - (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))) { + (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))) { netif_tx_lock(tp->dev); if (netif_queue_stopped(tp->dev) && - (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))) + (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi))) netif_wake_queue(tp->dev); netif_tx_unlock(tp->dev); } } +static void tg3_rx_skb_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz) +{ + if (!ri->skb) + return; + + pci_unmap_single(tp->pdev, pci_unmap_addr(ri, mapping), + map_sz, PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(ri->skb); + ri->skb = NULL; +} + /* Returns size of skb allocated or < 0 on error. * * We only need to fill in the address because the other members @@ -3964,8 +4126,8 @@ static void tg3_tx(struct tg3 *tp) * buffers the cpu only reads the last cacheline of the RX descriptor * (to fetch the error flags, vlan tag, checksum, and opaque cookie). */ -static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, - int src_idx, u32 dest_idx_unmasked) +static int tg3_alloc_rx_skb(struct tg3 *tp, struct tg3_rx_prodring_set *tpr, + u32 opaque_key, u32 dest_idx_unmasked) { struct tg3_rx_buffer_desc *desc; struct ring_info *map, *src_map; @@ -3977,20 +4139,16 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, switch (opaque_key) { case RXD_OPAQUE_RING_STD: dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE; - desc = &tp->rx_std[dest_idx]; - map = &tp->rx_std_buffers[dest_idx]; - if (src_idx >= 0) - src_map = &tp->rx_std_buffers[src_idx]; - skb_size = tp->rx_pkt_buf_sz; + desc = &tpr->rx_std[dest_idx]; + map = &tpr->rx_std_buffers[dest_idx]; + skb_size = tp->rx_pkt_map_sz; break; case RXD_OPAQUE_RING_JUMBO: dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE; - desc = &tp->rx_jumbo[dest_idx]; - map = &tp->rx_jumbo_buffers[dest_idx]; - if (src_idx >= 0) - src_map = &tp->rx_jumbo_buffers[src_idx]; - skb_size = RX_JUMBO_PKT_BUF_SZ; + desc = &tpr->rx_jmb[dest_idx].std; + map = &tpr->rx_jmb_buffers[dest_idx]; + skb_size = TG3_RX_JMB_MAP_SZ; break; default: @@ -4003,22 +4161,18 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, * Callers depend upon this behavior and assume that * we leave everything unchanged if we fail. */ - skb = netdev_alloc_skb(tp->dev, skb_size); + skb = netdev_alloc_skb(tp->dev, skb_size + tp->rx_offset); if (skb == NULL) return -ENOMEM; skb_reserve(skb, tp->rx_offset); - mapping = pci_map_single(tp->pdev, skb->data, - skb_size - tp->rx_offset, + mapping = pci_map_single(tp->pdev, skb->data, skb_size, PCI_DMA_FROMDEVICE); map->skb = skb; pci_unmap_addr_set(map, mapping, mapping); - if (src_map != NULL) - src_map->skb = NULL; - desc->addr_hi = ((u64)mapping >> 32); desc->addr_lo = ((u64)mapping & 0xffffffff); @@ -4029,28 +4183,32 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, * members of the RX descriptor are invariant. See notes above * tg3_alloc_rx_skb for full details. */ -static void tg3_recycle_rx(struct tg3 *tp, u32 opaque_key, - int src_idx, u32 dest_idx_unmasked) +static void tg3_recycle_rx(struct tg3_napi *tnapi, + struct tg3_rx_prodring_set *dpr, + u32 opaque_key, int src_idx, + u32 dest_idx_unmasked) { + struct tg3 *tp = tnapi->tp; struct tg3_rx_buffer_desc *src_desc, *dest_desc; struct ring_info *src_map, *dest_map; int dest_idx; + struct tg3_rx_prodring_set *spr = &tp->prodring[0]; switch (opaque_key) { case RXD_OPAQUE_RING_STD: dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE; - dest_desc = &tp->rx_std[dest_idx]; - dest_map = &tp->rx_std_buffers[dest_idx]; - src_desc = &tp->rx_std[src_idx]; - src_map = &tp->rx_std_buffers[src_idx]; + dest_desc = &dpr->rx_std[dest_idx]; + dest_map = &dpr->rx_std_buffers[dest_idx]; + src_desc = &spr->rx_std[src_idx]; + src_map = &spr->rx_std_buffers[src_idx]; break; case RXD_OPAQUE_RING_JUMBO: dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE; - dest_desc = &tp->rx_jumbo[dest_idx]; - dest_map = &tp->rx_jumbo_buffers[dest_idx]; - src_desc = &tp->rx_jumbo[src_idx]; - src_map = &tp->rx_jumbo_buffers[src_idx]; + dest_desc = &dpr->rx_jmb[dest_idx].std; + dest_map = &dpr->rx_jmb_buffers[dest_idx]; + src_desc = &spr->rx_jmb[src_idx].std; + src_map = &spr->rx_jmb_buffers[src_idx]; break; default: @@ -4062,7 +4220,6 @@ static void tg3_recycle_rx(struct tg3 *tp, u32 opaque_key, pci_unmap_addr(src_map, mapping)); dest_desc->addr_hi = src_desc->addr_hi; dest_desc->addr_lo = src_desc->addr_lo; - src_map->skb = NULL; } @@ -4097,14 +4254,17 @@ static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag) * If both the host and chip were to write into the same ring, cache line * eviction could occur since both entities want it in an exclusive state. */ -static int tg3_rx(struct tg3 *tp, int budget) +static int tg3_rx(struct tg3_napi *tnapi, int budget) { + struct tg3 *tp = tnapi->tp; u32 work_mask, rx_std_posted = 0; - u32 sw_idx = tp->rx_rcb_ptr; + u32 std_prod_idx, jmb_prod_idx; + u32 sw_idx = tnapi->rx_rcb_ptr; u16 hw_idx; int received; + struct tg3_rx_prodring_set *tpr = tnapi->prodring; - hw_idx = tp->hw_status->idx[0].rx_producer; + hw_idx = *(tnapi->rx_rcb_prod_idx); /* * We need to order the read of hw_idx and the read of * the opaque cookie. @@ -4112,8 +4272,11 @@ static int tg3_rx(struct tg3 *tp, int budget) rmb(); work_mask = 0; received = 0; + std_prod_idx = tpr->rx_std_prod_idx; + jmb_prod_idx = tpr->rx_jmb_prod_idx; while (sw_idx != hw_idx && budget > 0) { - struct tg3_rx_buffer_desc *desc = &tp->rx_rcb[sw_idx]; + struct ring_info *ri; + struct tg3_rx_buffer_desc *desc = &tnapi->rx_rcb[sw_idx]; unsigned int len; struct sk_buff *skb; dma_addr_t dma_addr; @@ -4122,27 +4285,25 @@ static int tg3_rx(struct tg3 *tp, int budget) desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; if (opaque_key == RXD_OPAQUE_RING_STD) { - dma_addr = pci_unmap_addr(&tp->rx_std_buffers[desc_idx], - mapping); - skb = tp->rx_std_buffers[desc_idx].skb; - post_ptr = &tp->rx_std_ptr; + ri = &tp->prodring[0].rx_std_buffers[desc_idx]; + dma_addr = pci_unmap_addr(ri, mapping); + skb = ri->skb; + post_ptr = &std_prod_idx; rx_std_posted++; } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { - dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx], - mapping); - skb = tp->rx_jumbo_buffers[desc_idx].skb; - post_ptr = &tp->rx_jumbo_ptr; - } - else { + ri = &tp->prodring[0].rx_jmb_buffers[desc_idx]; + dma_addr = pci_unmap_addr(ri, mapping); + skb = ri->skb; + post_ptr = &jmb_prod_idx; + } else goto next_pkt_nopost; - } work_mask |= opaque_key; if ((desc->err_vlan & RXD_ERR_MASK) != 0 && (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) { drop_it: - tg3_recycle_rx(tp, opaque_key, + tg3_recycle_rx(tnapi, tpr, opaque_key, desc_idx, *post_ptr); drop_it_no_recycle: /* Other statistics kept track of by card. */ @@ -4153,29 +4314,29 @@ static int tg3_rx(struct tg3 *tp, int budget) len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - ETH_FCS_LEN; - if (len > RX_COPY_THRESHOLD - && tp->rx_offset == NET_IP_ALIGN - /* rx_offset will likely not equal NET_IP_ALIGN - * if this is a 5701 card running in PCI-X mode - * [see tg3_get_invariants()] - */ - ) { + if (len > RX_COPY_THRESHOLD && + tp->rx_offset == NET_IP_ALIGN) { + /* rx_offset will likely not equal NET_IP_ALIGN + * if this is a 5701 card running in PCI-X mode + * [see tg3_get_invariants()] + */ int skb_size; - skb_size = tg3_alloc_rx_skb(tp, opaque_key, - desc_idx, *post_ptr); + skb_size = tg3_alloc_rx_skb(tp, tpr, opaque_key, + *post_ptr); if (skb_size < 0) goto drop_it; - pci_unmap_single(tp->pdev, dma_addr, - skb_size - tp->rx_offset, + ri->skb = NULL; + + pci_unmap_single(tp->pdev, dma_addr, skb_size, PCI_DMA_FROMDEVICE); skb_put(skb, len); } else { struct sk_buff *copy_skb; - tg3_recycle_rx(tp, opaque_key, + tg3_recycle_rx(tnapi, tpr, opaque_key, desc_idx, *post_ptr); copy_skb = netdev_alloc_skb(tp->dev, @@ -4226,10 +4387,9 @@ next_pkt: (*post_ptr)++; if (unlikely(rx_std_posted >= tp->rx_std_max_post)) { - u32 idx = *post_ptr % TG3_RX_RING_SIZE; - - tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + - TG3_64BIT_REG_LOW, idx); + tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE; + tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, + tpr->rx_std_prod_idx); work_mask &= ~RXD_OPAQUE_RING_STD; rx_std_posted = 0; } @@ -4239,38 +4399,140 @@ next_pkt_nopost: /* Refresh hw_idx to see if there is new work */ if (sw_idx == hw_idx) { - hw_idx = tp->hw_status->idx[0].rx_producer; + hw_idx = *(tnapi->rx_rcb_prod_idx); rmb(); } } /* ACK the status ring. */ - tp->rx_rcb_ptr = sw_idx; - tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, sw_idx); - - /* Some platforms need to sync memory here */ - wmb(); + tnapi->rx_rcb_ptr = sw_idx; + tw32_rx_mbox(tnapi->consmbox, sw_idx); /* Refill RX ring(s). */ - if (work_mask & RXD_OPAQUE_RING_STD) { - sw_idx = tp->rx_std_ptr % TG3_RX_RING_SIZE; - tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, - sw_idx); - } - if (work_mask & RXD_OPAQUE_RING_JUMBO) { - sw_idx = tp->rx_jumbo_ptr % TG3_RX_JUMBO_RING_SIZE; - tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, - sw_idx); + if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) || tnapi == &tp->napi[1]) { + /* Some platforms need to sync memory here */ + wmb(); + + if (work_mask & RXD_OPAQUE_RING_STD) { + tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE; + tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, + tpr->rx_std_prod_idx); + + } + if (work_mask & RXD_OPAQUE_RING_JUMBO) { + tpr->rx_jmb_prod_idx = jmb_prod_idx % + TG3_RX_JUMBO_RING_SIZE; + tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, + tpr->rx_jmb_prod_idx); + } + mmiowb(); + } else if (work_mask) { + /* rx_std_buffers[] and rx_jmb_buffers[] entries must be + * updated before the producer indices can be updated. + */ + smp_wmb(); + + tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE; + tpr->rx_jmb_prod_idx = jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE; + + netif_rx_schedule(tp->napi[0].dummy_netdev); } - mmiowb(); return received; } +static void tg3_rx_prodring_xfer(struct tg3 *tp, + struct tg3_rx_prodring_set *dpr, + struct tg3_rx_prodring_set *spr) +{ + u32 si, di, cpycnt, src_prod_idx; + int i; + + while (1) { + src_prod_idx = spr->rx_std_prod_idx; + + /* Make sure updates to the rx_std_buffers[] entries and the + * standard producer index are seen in the correct order. + */ + smp_rmb(); + + if (spr->rx_std_cons_idx == src_prod_idx) + break; + + if (spr->rx_std_cons_idx < src_prod_idx) + cpycnt = src_prod_idx - spr->rx_std_cons_idx; + else + cpycnt = TG3_RX_RING_SIZE - spr->rx_std_cons_idx; + + cpycnt = min(cpycnt, TG3_RX_RING_SIZE - dpr->rx_std_prod_idx); + + si = spr->rx_std_cons_idx; + di = dpr->rx_std_prod_idx; + + memcpy(&dpr->rx_std_buffers[di], + &spr->rx_std_buffers[si], + cpycnt * sizeof(struct ring_info)); + + for (i = 0; i < cpycnt; i++, di++, si++) { + struct tg3_rx_buffer_desc *sbd, *dbd; + sbd = &spr->rx_std[si]; + dbd = &dpr->rx_std[di]; + dbd->addr_hi = sbd->addr_hi; + dbd->addr_lo = sbd->addr_lo; + } + + spr->rx_std_cons_idx = (spr->rx_std_cons_idx + cpycnt) % + TG3_RX_RING_SIZE; + dpr->rx_std_prod_idx = (dpr->rx_std_prod_idx + cpycnt) % + TG3_RX_RING_SIZE; + } + + while (1) { + src_prod_idx = spr->rx_jmb_prod_idx; + + /* Make sure updates to the rx_jmb_buffers[] entries and + * the jumbo producer index are seen in the correct order. + */ + smp_rmb(); + + if (spr->rx_jmb_cons_idx == src_prod_idx) + break; + + if (spr->rx_jmb_cons_idx < src_prod_idx) + cpycnt = src_prod_idx - spr->rx_jmb_cons_idx; + else + cpycnt = TG3_RX_JUMBO_RING_SIZE - spr->rx_jmb_cons_idx; + + cpycnt = min(cpycnt, + TG3_RX_JUMBO_RING_SIZE - dpr->rx_jmb_prod_idx); + + si = spr->rx_jmb_cons_idx; + di = dpr->rx_jmb_prod_idx; + + memcpy(&dpr->rx_jmb_buffers[di], + &spr->rx_jmb_buffers[si], + cpycnt * sizeof(struct ring_info)); + + for (i = 0; i < cpycnt; i++, di++, si++) { + struct tg3_rx_buffer_desc *sbd, *dbd; + sbd = &spr->rx_jmb[si].std; + dbd = &dpr->rx_jmb[di].std; + dbd->addr_hi = sbd->addr_hi; + dbd->addr_lo = sbd->addr_lo; + } + + spr->rx_jmb_cons_idx = (spr->rx_jmb_cons_idx + cpycnt) % + TG3_RX_JUMBO_RING_SIZE; + dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) % + TG3_RX_JUMBO_RING_SIZE; + } +} + static int tg3_poll(struct net_device *netdev, int *budget) { - struct tg3 *tp = netdev_priv(netdev); - struct tg3_hw_status *sblk = tp->hw_status; + struct tg3_napi *tnapi = netdev->priv; + struct tg3 *tp = tnapi->tp; + struct tg3_hw_status *sblk = tnapi->hw_status; int done; /* handle link change and other phy events */ @@ -4295,8 +4557,8 @@ static int tg3_poll(struct net_device *netdev, int *budget) } /* run TX completion thread */ - if (sblk->idx[0].tx_consumer != tp->tx_cons) { - tg3_tx(tp); + if (tnapi->hw_status->idx[0].tx_consumer != tnapi->tx_cons) { + tg3_tx(tnapi); if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) { netif_rx_complete(netdev); schedule_work(&tp->reset_task); @@ -4308,30 +4570,55 @@ static int tg3_poll(struct net_device *netdev, int *budget) * All RX "locking" is done by ensuring outside * code synchronizes with dev->poll() */ - if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) { + if (*(tnapi->rx_rcb_prod_idx) != tnapi->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); + work_done = tg3_rx(tnapi, orig_budget); *budget -= work_done; netdev->quota -= work_done; } if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { - tp->last_tag = sblk->status_tag; + tnapi->last_tag = sblk->status_tag; + tnapi->last_irq_tag = tnapi->last_tag; rmb(); } else sblk->status &= ~SD_STATUS_UPDATED; + if ((tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) && tnapi == &tp->napi[1]) { + int i; + u32 std_prod_idx = tp->prodring[0].rx_std_prod_idx; + u32 jmb_prod_idx = tp->prodring[0].rx_jmb_prod_idx; + + for (i = 2; i < tp->irq_cnt; i++) + tg3_rx_prodring_xfer(tp, tnapi->prodring, + tp->napi[i].prodring); + + wmb(); + + if (std_prod_idx != tp->prodring[0].rx_std_prod_idx) { + u32 mbox = TG3_RX_STD_PROD_IDX_REG; + tw32_rx_mbox(mbox, tp->prodring[0].rx_std_prod_idx); + } + + if (jmb_prod_idx != tp->prodring[0].rx_jmb_prod_idx) { + u32 mbox = TG3_RX_JMB_PROD_IDX_REG; + tw32_rx_mbox(mbox, tp->prodring[0].rx_jmb_prod_idx); + } + + mmiowb(); + } + /* if no more work, tell net stack and NIC we're done */ - done = !tg3_has_work(tp); + done = !tg3_has_work(tnapi); if (done) { netif_rx_complete(netdev); - tg3_restart_ints(tp); + tg3_int_reenable(tnapi); } return (done ? 0 : 1); @@ -4339,12 +4626,15 @@ static int tg3_poll(struct net_device *netdev, int *budget) static void tg3_irq_quiesce(struct tg3 *tp) { + int i; + BUG_ON(tp->irq_sync); tp->irq_sync = 1; smp_mb(); - synchronize_irq(tp->pdev->irq); + for (i = 0; i < tp->irq_cnt; i++) + synchronize_irq(tp->napi[i].irq_vec); } static inline int tg3_irq_sync(struct tg3 *tp) @@ -4374,14 +4664,15 @@ static inline void tg3_full_unlock(struct tg3 *tp) */ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs) { - struct net_device *dev = dev_id; - struct tg3 *tp = netdev_priv(dev); + struct tg3_napi *tnapi = dev_id; + struct tg3 *tp = tnapi->tp; - prefetch(tp->hw_status); - prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + prefetch(tnapi->hw_status); + if (tnapi->rx_rcb) + prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]); if (likely(!tg3_irq_sync(tp))) - netif_rx_schedule(dev); /* schedule NAPI poll */ + netif_rx_schedule(tnapi->dummy_netdev); return IRQ_HANDLED; } @@ -4392,11 +4683,12 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs) */ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) { - struct net_device *dev = dev_id; - struct tg3 *tp = netdev_priv(dev); + struct tg3_napi *tnapi = dev_id; + struct tg3 *tp = tnapi->tp; - prefetch(tp->hw_status); - prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + prefetch(tnapi->hw_status); + if (tnapi->rx_rcb) + prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]); /* * Writing any value to intr-mbox-0 clears PCI INTA# and * chip-internal interrupt pending events. @@ -4406,16 +4698,16 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) */ 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(tnapi->dummy_netdev); return IRQ_RETVAL(1); } static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct net_device *dev = dev_id; - struct tg3 *tp = netdev_priv(dev); - struct tg3_hw_status *sblk = tp->hw_status; + struct tg3_napi *tnapi = dev_id; + struct tg3 *tp = tnapi->tp; + struct tg3_hw_status *sblk = tnapi->hw_status; unsigned int handled = 1; /* In INTx mode, it is possible for the interrupt to arrive at @@ -4446,9 +4738,9 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) 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); /* schedule NAPI poll */ + if (likely(tg3_has_work(tnapi))) { + prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]); + netif_rx_schedule(tnapi->dummy_netdev); } else { /* No work, shared interrupt perhaps? re-enable * interrupts, and flush that PCI write @@ -4462,9 +4754,9 @@ out: static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs) { - struct net_device *dev = dev_id; - struct tg3 *tp = netdev_priv(dev); - struct tg3_hw_status *sblk = tp->hw_status; + struct tg3_napi *tnapi = dev_id; + struct tg3 *tp = tnapi->tp; + struct tg3_hw_status *sblk = tnapi->hw_status; unsigned int handled = 1; /* In INTx mode, it is possible for the interrupt to arrive at @@ -4472,7 +4764,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r * Reading the PCI State register will confirm whether the * interrupt is ours and will flush the status block. */ - if (unlikely(sblk->status_tag == tp->last_tag)) { + if (unlikely(sblk->status_tag == tnapi->last_tag)) { if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { handled = 0; @@ -4494,15 +4786,15 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); if (tg3_irq_sync(tp)) goto out; - if (netif_rx_schedule_prep(dev)) { - prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + if (netif_rx_schedule_prep(tnapi->dummy_netdev)) { + prefetch(&tnapi->rx_rcb[tnapi->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); + tnapi->last_tag = sblk->status_tag; + __netif_rx_schedule(tnapi->dummy_netdev); } out: return IRQ_RETVAL(handled); @@ -4512,9 +4804,9 @@ out: static irqreturn_t tg3_test_isr(int irq, void *dev_id, struct pt_regs *regs) { - struct net_device *dev = dev_id; - struct tg3 *tp = netdev_priv(dev); - struct tg3_hw_status *sblk = tp->hw_status; + struct tg3_napi *tnapi = dev_id; + struct tg3 *tp = tnapi->tp; + struct tg3_hw_status *sblk = tnapi->hw_status; if ((sblk->status & SD_STATUS_UPDATED) || !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { @@ -4544,7 +4836,7 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy) tg3_full_unlock(tp); del_timer_sync(&tp->timer); tp->irq_sync = 0; - netif_poll_enable(tp->dev); + tg3_napi_enable(tp); dev_close(tp->dev); tg3_full_lock(tp, 0); } @@ -4554,9 +4846,11 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy) #ifdef CONFIG_NET_POLL_CONTROLLER static void tg3_poll_controller(struct net_device *dev) { + int i; struct tg3 *tp = netdev_priv(dev); - tg3_interrupt(tp->pdev->irq, dev, NULL); + for (i = 0; i < tp->irq_cnt; i++) + tg3_interrupt(tp->napi[i].irq_vec, dev, NULL); } #endif @@ -4648,13 +4942,14 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping, #endif } -static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); +static void tg3_set_txd(struct tg3_napi *, int, dma_addr_t, int, u32, u32); /* Workaround 4GB and 40-bit hardware DMA bugs. */ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, u32 last_plus_one, u32 *start, u32 base_flags, u32 mss) { + struct tg3_napi *tnapi = &tp->napi[0]; struct sk_buff *new_skb; dma_addr_t new_addr = 0; u32 entry = *start; @@ -4680,12 +4975,13 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, /* Make sure new skb does not cross any 4G boundaries. * Drop the packet if it does. */ - if (tg3_4g_overflow_test(new_addr, new_skb->len)) { + if (ret || ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) && + tg3_4g_overflow_test(new_addr, new_skb->len))) { ret = -1; dev_kfree_skb(new_skb); new_skb = NULL; } else { - tg3_set_txd(tp, entry, new_addr, new_skb->len, + tg3_set_txd(tnapi, entry, new_addr, new_skb->len, base_flags, 1 | (mss << 1)); *start = NEXT_TX(entry); } @@ -4701,13 +4997,13 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, else len = skb_shinfo(skb)->frags[i-1].size; pci_unmap_single(tp->pdev, - pci_unmap_addr(&tp->tx_buffers[entry], mapping), + pci_unmap_addr(&tnapi->tx_buffers[entry], mapping), len, PCI_DMA_TODEVICE); if (i == 0) { - tp->tx_buffers[entry].skb = new_skb; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, new_addr); + tnapi->tx_buffers[entry].skb = new_skb; + pci_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, new_addr); } else { - tp->tx_buffers[entry].skb = NULL; + tnapi->tx_buffers[entry].skb = NULL; } entry = NEXT_TX(entry); i++; @@ -4718,11 +5014,11 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, return ret; } -static void tg3_set_txd(struct tg3 *tp, int entry, +static void tg3_set_txd(struct tg3_napi *tnapi, int entry, dma_addr_t mapping, int len, u32 flags, u32 mss_and_is_end) { - struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry]; + struct tg3_tx_buffer_desc *txd = &tnapi->tx_ring[entry]; int is_end = (mss_and_is_end & 0x1); u32 mss = (mss_and_is_end >> 1); u32 vlan_tag = 0; @@ -4749,6 +5045,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) struct tg3 *tp = netdev_priv(dev); dma_addr_t mapping; u32 len, entry, base_flags, mss; + struct tg3_napi *tnapi = &tp->napi[0]; len = skb_headlen(skb); @@ -4757,7 +5054,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { + if (unlikely(tg3_tx_avail(tnapi) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -4768,11 +5065,12 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } - entry = tp->tx_prod; + entry = tnapi->tx_prod; base_flags = 0; mss = 0; if ((mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; + u32 hdrlen; if (skb_header_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { @@ -4781,7 +5079,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - mss |= (skb_headlen(skb) - ETH_HLEN) << 9; + hdrlen = skb_headlen(skb) - ETH_HLEN; else { struct iphdr *iph = ip_hdr(skb); @@ -4790,9 +5088,18 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) iph->check = 0; iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); - mss |= (ip_tcp_len + tcp_opt_len) << 9; + hdrlen = ip_tcp_len + tcp_opt_len; } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + mss |= (hdrlen & 0xc) << 12; + if (hdrlen & 0x10) + base_flags |= 0x00000010; + base_flags |= (hdrlen & 0x3e0) << 5; + } else + mss |= hdrlen << 9; + base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); @@ -4810,10 +5117,10 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Queue skb data, a.k.a. the main skb fragment. */ mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE); - tp->tx_buffers[entry].skb = skb; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); + tnapi->tx_buffers[entry].skb = skb; + pci_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping); - tg3_set_txd(tp, entry, mapping, len, base_flags, + tg3_set_txd(tnapi, entry, mapping, len, base_flags, (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); entry = NEXT_TX(entry); @@ -4832,10 +5139,10 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) frag->page_offset, len, PCI_DMA_TODEVICE); - tp->tx_buffers[entry].skb = NULL; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); + tnapi->tx_buffers[entry].skb = NULL; + pci_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping); - tg3_set_txd(tp, entry, mapping, len, + tg3_set_txd(tnapi, entry, mapping, len, base_flags, (i == last) | (mss << 1)); entry = NEXT_TX(entry); @@ -4846,12 +5153,12 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) wmb(); /* Packets are ready, update Tx producer idx local and on card. */ - tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); + tw32_tx_mbox(tnapi->prodmbox, entry); - tp->tx_prod = entry; - if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { + tnapi->tx_prod = entry; + if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) { netif_stop_queue(dev); - if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)) + if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)) netif_wake_queue(tp->dev); } @@ -4871,11 +5178,12 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *, struct net_device *); static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) { struct sk_buff *segs, *nskb; + u32 frag_cnt_est = skb_shinfo(skb)->gso_segs * 3; /* Estimate the number of fragments in the worst case */ - if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) { + if (unlikely(tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)) { netif_stop_queue(tp->dev); - if (tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3)) + if (tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est) return NETDEV_TX_BUSY; netif_wake_queue(tp->dev); @@ -4907,6 +5215,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) dma_addr_t mapping; u32 len, entry, base_flags, mss; int would_hit_hwbug; + struct tg3_napi *tnapi = &tp->napi[0]; len = skb_headlen(skb); @@ -4915,7 +5224,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { + if (unlikely(tg3_tx_avail(tnapi) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -4926,14 +5235,14 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } - entry = tp->tx_prod; + entry = tnapi->tx_prod; base_flags = 0; if (skb->ip_summed == CHECKSUM_HW) base_flags |= TXD_FLAG_TCPUDP_CSUM; mss = 0; if ((mss = skb_shinfo(skb)->gso_size) != 0) { struct iphdr *iph; - int tcp_opt_len, ip_tcp_len, hdr_len; + u32 tcp_opt_len, ip_tcp_len, hdr_len; if (skb_header_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { @@ -4964,8 +5273,16 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) IPPROTO_TCP, 0); - if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + mss |= (hdr_len & 0xc) << 12; + if (hdr_len & 0x10) + base_flags |= 0x00000010; + base_flags |= (hdr_len & 0x3e0) << 5; + } else if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) + mss |= hdr_len << 9; + else if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { if (tcp_opt_len || iph->ihl > 5) { int tsflags; @@ -4987,20 +5304,37 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) (vlan_tx_tag_get(skb) << 16)); #endif + if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) && + !mss && skb->len > ETH_DATA_LEN) + base_flags |= TXD_FLAG_JMB_PKT; + /* Queue skb data, a.k.a. the main skb fragment. */ mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE); - tp->tx_buffers[entry].skb = skb; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); + tnapi->tx_buffers[entry].skb = skb; + pci_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping); would_hit_hwbug = 0; - if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG) + if ((tp->tg3_flags3 & TG3_FLG3_SHORT_DMA_BUG) && len <= 8) would_hit_hwbug = 1; - else if (tg3_4g_overflow_test(mapping, len)) + + if ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) && + tg3_4g_overflow_test(mapping, len)) would_hit_hwbug = 1; - tg3_set_txd(tp, entry, mapping, len, base_flags, + if ((tp->tg3_flags3 & TG3_FLG3_40BIT_DMA_LIMIT_BUG) && + tg3_40bit_overflow_test(tp, mapping, len)) + would_hit_hwbug = 1; + + if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG) + would_hit_hwbug = 1; + + if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) && + !mss && skb->len > ETH_DATA_LEN) + base_flags |= TXD_FLAG_JMB_PKT; + + tg3_set_txd(tnapi, entry, mapping, len, base_flags, (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); entry = NEXT_TX(entry); @@ -5019,20 +5353,26 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) frag->page_offset, len, PCI_DMA_TODEVICE); - tp->tx_buffers[entry].skb = NULL; - pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); + tnapi->tx_buffers[entry].skb = NULL; + pci_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping); + + if ((tp->tg3_flags3 & TG3_FLG3_SHORT_DMA_BUG) && + len <= 8) + would_hit_hwbug = 1; - if (tg3_4g_overflow_test(mapping, len)) + if ((tp->tg3_flags3 & TG3_FLG3_4G_DMA_BNDRY_BUG) && + tg3_4g_overflow_test(mapping, len)) would_hit_hwbug = 1; - if (tg3_40bit_overflow_test(tp, mapping, len)) + if ((tp->tg3_flags3 & TG3_FLG3_40BIT_DMA_LIMIT_BUG) && + tg3_40bit_overflow_test(tp, mapping, len)) would_hit_hwbug = 1; if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) - tg3_set_txd(tp, entry, mapping, len, + tg3_set_txd(tnapi, entry, mapping, len, base_flags, (i == last)|(mss << 1)); else - tg3_set_txd(tp, entry, mapping, len, + tg3_set_txd(tnapi, entry, mapping, len, base_flags, (i == last)); entry = NEXT_TX(entry); @@ -5060,12 +5400,12 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) wmb(); /* Packets are ready, update Tx producer idx local and on card. */ - tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); + tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, entry); - tp->tx_prod = entry; - if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { + tnapi->tx_prod = entry; + if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) { netif_stop_queue(dev); - if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)) + if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)) netif_wake_queue(tp->dev); } @@ -5130,75 +5470,37 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) return err; } -/* Free up pending packets in all rx/tx rings. - * - * The chip has been shut down and the driver detached from - * the networking, so no interrupts or new tx packets will - * end up in the driver. tp->{tx,}lock is not held and we are not - * in an interrupt context and thus may sleep. - */ -static void tg3_free_rings(struct tg3 *tp) +static void tg3_rx_prodring_free(struct tg3 *tp, + struct tg3_rx_prodring_set *tpr) { - struct ring_info *rxp; int i; - for (i = 0; i < TG3_RX_RING_SIZE; i++) { - rxp = &tp->rx_std_buffers[i]; - - if (rxp->skb == NULL) - continue; - pci_unmap_single(tp->pdev, - pci_unmap_addr(rxp, mapping), - tp->rx_pkt_buf_sz - tp->rx_offset, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(rxp->skb); - rxp->skb = NULL; - } - - for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) { - rxp = &tp->rx_jumbo_buffers[i]; - - if (rxp->skb == NULL) - continue; - pci_unmap_single(tp->pdev, - pci_unmap_addr(rxp, mapping), - RX_JUMBO_PKT_BUF_SZ - tp->rx_offset, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(rxp->skb); - rxp->skb = NULL; - } - - for (i = 0; i < TG3_TX_RING_SIZE; ) { - struct tx_ring_info *txp; - struct sk_buff *skb; - int j; - - txp = &tp->tx_buffers[i]; - skb = txp->skb; - - if (skb == NULL) { - i++; - continue; + if (tpr != &tp->prodring[0]) { + for (i = tpr->rx_std_cons_idx; i != tpr->rx_std_prod_idx; + i = (i + 1) % TG3_RX_RING_SIZE) + tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i], + tp->rx_pkt_map_sz); + + if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { + for (i = tpr->rx_jmb_cons_idx; + i != tpr->rx_jmb_prod_idx; + i = (i + 1) % TG3_RX_JUMBO_RING_SIZE) { + tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i], + TG3_RX_JMB_MAP_SZ); + } } - pci_unmap_single(tp->pdev, - pci_unmap_addr(txp, mapping), - skb_headlen(skb), - PCI_DMA_TODEVICE); - txp->skb = NULL; - - i++; + return; + } - for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) { - txp = &tp->tx_buffers[i & (TG3_TX_RING_SIZE - 1)]; - pci_unmap_page(tp->pdev, - pci_unmap_addr(txp, mapping), - skb_shinfo(skb)->frags[j].size, - PCI_DMA_TODEVICE); - i++; - } + for (i = 0; i < TG3_RX_RING_SIZE; i++) + tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i], + tp->rx_pkt_map_sz); - dev_kfree_skb_any(skb); + if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { + for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) + tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i], + TG3_RX_JMB_MAP_SZ); } } @@ -5209,23 +5511,32 @@ static void tg3_free_rings(struct tg3 *tp) * end up in the driver. tp->{tx,}lock are held and thus * we may not sleep. */ -static int tg3_init_rings(struct tg3 *tp) +static int tg3_rx_prodring_alloc(struct tg3 *tp, + struct tg3_rx_prodring_set *tpr) { - u32 i; + u32 i, rx_pkt_dma_sz; - /* Free up all the SKBs. */ - tg3_free_rings(tp); + tpr->rx_std_cons_idx = 0; + tpr->rx_std_prod_idx = 0; + tpr->rx_jmb_cons_idx = 0; + tpr->rx_jmb_prod_idx = 0; + + if (tpr != &tp->prodring[0]) { + memset(&tpr->rx_std_buffers[0], 0, TG3_RX_STD_BUFF_RING_SIZE); + if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) + memset(&tpr->rx_jmb_buffers[0], 0, + TG3_RX_JMB_BUFF_RING_SIZE); + goto done; + } /* Zero out all descriptors. */ - memset(tp->rx_std, 0, TG3_RX_RING_BYTES); - memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES); - memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); - memset(tp->tx_ring, 0, TG3_TX_RING_BYTES); + memset(tpr->rx_std, 0, TG3_RX_RING_BYTES); - tp->rx_pkt_buf_sz = RX_PKT_BUF_SZ; + rx_pkt_dma_sz = TG3_RX_STD_DMA_SZ; if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) && - (tp->dev->mtu > ETH_DATA_LEN)) - tp->rx_pkt_buf_sz = RX_JUMBO_PKT_BUF_SZ; + tp->dev->mtu > ETH_DATA_LEN) + rx_pkt_dma_sz = TG3_RX_JMB_DMA_SZ; + tp->rx_pkt_map_sz = TG3_RX_DMA_TO_MAP_SZ(rx_pkt_dma_sz); /* Initialize invariants of the rings, we only set this * stuff once. This works because the card does not @@ -5234,102 +5545,244 @@ static int tg3_init_rings(struct tg3 *tp) for (i = 0; i < TG3_RX_RING_SIZE; i++) { struct tg3_rx_buffer_desc *rxd; - rxd = &tp->rx_std[i]; - rxd->idx_len = (tp->rx_pkt_buf_sz - tp->rx_offset - 64) - << RXD_LEN_SHIFT; + rxd = &tpr->rx_std[i]; + rxd->idx_len = rx_pkt_dma_sz << RXD_LEN_SHIFT; rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT); rxd->opaque = (RXD_OPAQUE_RING_STD | (i << RXD_OPAQUE_INDEX_SHIFT)); } - if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { - for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) { - struct tg3_rx_buffer_desc *rxd; - - rxd = &tp->rx_jumbo[i]; - rxd->idx_len = (RX_JUMBO_PKT_BUF_SZ - tp->rx_offset - 64) - << RXD_LEN_SHIFT; - rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT) | - RXD_FLAG_JUMBO; - rxd->opaque = (RXD_OPAQUE_RING_JUMBO | - (i << RXD_OPAQUE_INDEX_SHIFT)); - } - } - /* Now allocate fresh SKBs for each rx ring. */ for (i = 0; i < tp->rx_pending; i++) { - if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD, -1, i) < 0) { + if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_STD, i) < 0) { printk(KERN_WARNING PFX "%s: Using a smaller RX standard ring, " "only %d out of %d buffers were allocated " "successfully.\n", tp->dev->name, i, tp->rx_pending); if (i == 0) - return -ENOMEM; + goto initfail; tp->rx_pending = i; break; } } + if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE)) + goto done; + + memset(tpr->rx_jmb, 0, TG3_RX_JUMBO_RING_BYTES); + if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { + for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) { + struct tg3_rx_buffer_desc *rxd; + + rxd = &tpr->rx_jmb[i].std; + rxd->idx_len = TG3_RX_JMB_DMA_SZ << RXD_LEN_SHIFT; + rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT) | + RXD_FLAG_JUMBO; + rxd->opaque = (RXD_OPAQUE_RING_JUMBO | + (i << RXD_OPAQUE_INDEX_SHIFT)); + } + for (i = 0; i < tp->rx_jumbo_pending; i++) { - if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_JUMBO, - -1, i) < 0) { + if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_JUMBO, + i) < 0) { printk(KERN_WARNING PFX "%s: Using a smaller RX jumbo ring, " "only %d out of %d buffers were " "allocated successfully.\n", tp->dev->name, i, tp->rx_jumbo_pending); - if (i == 0) { - tg3_free_rings(tp); - return -ENOMEM; - } + if (i == 0) + goto initfail; tp->rx_jumbo_pending = i; break; } } } + +done: return 0; + +initfail: + tg3_rx_prodring_free(tp, tpr); + return -ENOMEM; } -/* - * Must not be invoked with interrupt sources disabled and - * the hardware shutdown down. - */ -static void tg3_free_consistent(struct tg3 *tp) +static void tg3_rx_prodring_fini(struct tg3 *tp, + struct tg3_rx_prodring_set *tpr) { - kfree(tp->rx_std_buffers); - tp->rx_std_buffers = NULL; - if (tp->rx_std) { + kfree(tpr->rx_std_buffers); + tpr->rx_std_buffers = NULL; + kfree(tpr->rx_jmb_buffers); + tpr->rx_jmb_buffers = NULL; + if (tpr->rx_std) { pci_free_consistent(tp->pdev, TG3_RX_RING_BYTES, - tp->rx_std, tp->rx_std_mapping); - tp->rx_std = NULL; + tpr->rx_std, tpr->rx_std_mapping); + tpr->rx_std = NULL; } - if (tp->rx_jumbo) { + if (tpr->rx_jmb) { pci_free_consistent(tp->pdev, TG3_RX_JUMBO_RING_BYTES, - tp->rx_jumbo, tp->rx_jumbo_mapping); - tp->rx_jumbo = NULL; + tpr->rx_jmb, tpr->rx_jmb_mapping); + tpr->rx_jmb = NULL; } - if (tp->rx_rcb) { - pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp), - tp->rx_rcb, tp->rx_rcb_mapping); - tp->rx_rcb = NULL; +} + +static int tg3_rx_prodring_init(struct tg3 *tp, + struct tg3_rx_prodring_set *tpr) +{ + tpr->rx_std_buffers = kzalloc(TG3_RX_STD_BUFF_RING_SIZE, GFP_KERNEL); + if (!tpr->rx_std_buffers) + return -ENOMEM; + + tpr->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_RING_BYTES, + &tpr->rx_std_mapping); + if (!tpr->rx_std) + goto err_out; + + if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { + tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE, + GFP_KERNEL); + if (!tpr->rx_jmb_buffers) + goto err_out; + + tpr->rx_jmb = pci_alloc_consistent(tp->pdev, + TG3_RX_JUMBO_RING_BYTES, + &tpr->rx_jmb_mapping); + if (!tpr->rx_jmb) + goto err_out; } - if (tp->tx_ring) { - pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES, - tp->tx_ring, tp->tx_desc_mapping); - tp->tx_ring = NULL; + + return 0; + +err_out: + tg3_rx_prodring_fini(tp, tpr); + return -ENOMEM; +} + +/* Free up pending packets in all rx/tx rings. + * + * The chip has been shut down and the driver detached from + * the networking, so no interrupts or new tx packets will + * end up in the driver. tp->{tx,}lock is not held and we are not + * in an interrupt context and thus may sleep. + */ +static void tg3_free_rings(struct tg3 *tp) +{ + int i, j; + + for (j = 0; j < tp->irq_cnt; j++) { + struct tg3_napi *tnapi = &tp->napi[j]; + + if (!tnapi->tx_buffers) + continue; + + for (i = 0; i < TG3_TX_RING_SIZE; ) { + struct tx_ring_info *txp; + struct sk_buff *skb; + + txp = &tnapi->tx_buffers[i]; + skb = txp->skb; + + if (skb == NULL) { + i++; + continue; + } + + txp->skb = NULL; + + i += skb_shinfo(skb)->nr_frags + 1; + + dev_kfree_skb_any(skb); + } + + if (tp->irq_cnt == 1 || j != tp->irq_cnt - 1) + tg3_rx_prodring_free(tp, &tp->prodring[j]); } - if (tp->hw_status) { - pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE, - tp->hw_status, tp->status_mapping); - tp->hw_status = NULL; +} + +/* Initialize tx/rx rings for packet processing. + * + * The chip has been shut down and the driver detached from + * the networking, so no interrupts or new tx packets will + * end up in the driver. tp->{tx,}lock are held and thus + * we may not sleep. + */ +static int tg3_init_rings(struct tg3 *tp) +{ + int i; + + /* Free up all the SKBs. */ + tg3_free_rings(tp); + + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + + tnapi->last_tag = 0; + tnapi->last_irq_tag = 0; + tnapi->hw_status->status = 0; + tnapi->hw_status->status_tag = 0; + memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); + + tnapi->tx_prod = 0; + tnapi->tx_cons = 0; + if (tnapi->tx_ring) + memset(tnapi->tx_ring, 0, TG3_TX_RING_BYTES); + + tnapi->rx_rcb_ptr = 0; + if (tnapi->rx_rcb) + memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); + + if ((tp->irq_cnt == 1 || i != tp->irq_cnt - 1) && + tg3_rx_prodring_alloc(tp, &tp->prodring[i])) + return -ENOMEM; } + + return 0; +} + +/* + * Must not be invoked with interrupt sources disabled and + * the hardware shutdown down. + */ +static void tg3_free_consistent(struct tg3 *tp) +{ + int i; + + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + + if (tnapi->tx_ring) { + pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES, + tnapi->tx_ring, tnapi->tx_desc_mapping); + tnapi->tx_ring = NULL; + } + + kfree(tnapi->tx_buffers); + tnapi->tx_buffers = NULL; + + if (tnapi->rx_rcb) { + pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp), + tnapi->rx_rcb, + tnapi->rx_rcb_mapping); + tnapi->rx_rcb = NULL; + } + + if (tnapi->hw_status) { + pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE, + tnapi->hw_status, + tnapi->status_mapping); + tnapi->hw_status = NULL; + } + } + if (tp->hw_stats) { pci_free_consistent(tp->pdev, sizeof(struct tg3_hw_stats), tp->hw_stats, tp->stats_mapping); tp->hw_stats = NULL; } + + for (i = 0; i < (tp->irq_cnt == 1 ? 1 : tp->irq_cnt - 1); i++) + tg3_rx_prodring_fini(tp, &tp->prodring[i]); } /* @@ -5338,54 +5791,88 @@ static void tg3_free_consistent(struct tg3 *tp) */ static int tg3_alloc_consistent(struct tg3 *tp) { - tp->rx_std_buffers = kzalloc((sizeof(struct ring_info) * - (TG3_RX_RING_SIZE + - TG3_RX_JUMBO_RING_SIZE)) + - (sizeof(struct tx_ring_info) * - TG3_TX_RING_SIZE), - GFP_KERNEL); - if (!tp->rx_std_buffers) - return -ENOMEM; + int i; - 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]; + for (i = 0; i < (tp->irq_cnt == 1 ? 1 : tp->irq_cnt - 1); i++) { + if (tg3_rx_prodring_init(tp, &tp->prodring[i])) + goto err_out; + } - tp->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_RING_BYTES, - &tp->rx_std_mapping); - if (!tp->rx_std) + tp->hw_stats = pci_alloc_consistent(tp->pdev, + sizeof(struct tg3_hw_stats), + &tp->stats_mapping); + if (!tp->hw_stats) goto err_out; - tp->rx_jumbo = pci_alloc_consistent(tp->pdev, TG3_RX_JUMBO_RING_BYTES, - &tp->rx_jumbo_mapping); + memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); - if (!tp->rx_jumbo) - goto err_out; + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + struct tg3_hw_status *sblk; - tp->rx_rcb = pci_alloc_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp), - &tp->rx_rcb_mapping); - if (!tp->rx_rcb) - goto err_out; + tnapi->hw_status = pci_alloc_consistent(tp->pdev, + TG3_HW_STATUS_SIZE, + &tnapi->status_mapping); + if (!tnapi->hw_status) + goto err_out; - tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES, - &tp->tx_desc_mapping); - if (!tp->tx_ring) - goto err_out; + memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); + sblk = tnapi->hw_status; - tp->hw_status = pci_alloc_consistent(tp->pdev, - TG3_HW_STATUS_SIZE, - &tp->status_mapping); - if (!tp->hw_status) - goto err_out; + if (!i) { + tnapi->tx_buffers = kzalloc(sizeof(struct tx_ring_info) * + TG3_TX_RING_SIZE, GFP_KERNEL); + if (!tnapi->tx_buffers) + goto err_out; - tp->hw_stats = pci_alloc_consistent(tp->pdev, - sizeof(struct tg3_hw_stats), - &tp->stats_mapping); - if (!tp->hw_stats) - goto err_out; + tnapi->tx_ring = pci_alloc_consistent(tp->pdev, + TG3_TX_RING_BYTES, + &tnapi->tx_desc_mapping); + if (!tnapi->tx_ring) + goto err_out; + } - memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); - memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); + /* + * When RSS is enabled, the status block format changes + * slightly. The "rx_jumbo_consumer", "reserved", + * and "rx_mini_consumer" members get mapped to the + * other three rx return ring producer indexes. + */ + switch (i) { + default: + tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer; + break; + case 2: + tnapi->rx_rcb_prod_idx = &sblk->rx_jumbo_consumer; + break; + case 3: + tnapi->rx_rcb_prod_idx = &sblk->reserved; + break; + case 4: + tnapi->rx_rcb_prod_idx = &sblk->rx_mini_consumer; + break; + } + + if (tp->irq_cnt == 1) + tnapi->prodring = &tp->prodring[0]; + else if (i) + tnapi->prodring = &tp->prodring[i - 1]; + + /* + * If multivector RSS is enabled, vector 0 does not handle + * rx or tx interrupts. Don't allocate any resources for it. + */ + if (!i && (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) + continue; + + tnapi->rx_rcb = pci_alloc_consistent(tp->pdev, + TG3_RX_RCB_RING_BYTES(tp), + &tnapi->rx_rcb_mapping); + if (!tnapi->rx_rcb) + goto err_out; + + memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); + } return 0; @@ -5497,8 +5984,11 @@ static int tg3_abort_hw(struct tg3 *tp, int silent) err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE, silent); err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE, silent); - if (tp->hw_status) - memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + if (tnapi->hw_status) + memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); + } if (tp->hw_stats) memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); @@ -5737,13 +6227,15 @@ static void tg3_restore_pci_state(struct tg3 *tp) pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd); - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) - pcie_set_readrq(tp->pdev, 4096); - else { - pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, - tp->pci_cacheline_sz); - pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, - tp->pci_lat_timer); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) { + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) + pcie_set_readrq(tp->pdev, 4096); + else { + pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, + tp->pci_cacheline_sz); + pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, + tp->pci_lat_timer); + } } /* Make sure PCI-X relaxed ordering bit is clear. */ @@ -5784,7 +6276,7 @@ static int tg3_chip_reset(struct tg3 *tp) { u32 val; void (*write_op)(struct tg3 *, u32, u32); - int err; + int i, err; tg3_nvram_lock(tp); @@ -5822,13 +6314,19 @@ static int tg3_chip_reset(struct tg3 *tp) * 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; + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + if (tnapi->hw_status) { + tnapi->hw_status->status = 0; + tnapi->hw_status->status_tag = 0; + } + tnapi->last_tag = 0; + tnapi->last_irq_tag = 0; } - tp->last_tag = 0; smp_mb(); - synchronize_irq(tp->pdev->irq); + + for (i = 0; i < tp->irq_cnt; i++) + synchronize_irq(tp->napi[i].irq_vec); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; @@ -5975,16 +6473,43 @@ static int tg3_chip_reset(struct tg3 *tp) tw32_f(MAC_MODE, 0); udelay(40); - tg3_mdio_start(tp); - tg3_ape_unlock(tp, TG3_APE_LOCK_GRC); err = tg3_poll_fw(tp); if (err) return err; + tg3_mdio_start(tp); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { + u8 phy_addr; + + phy_addr = tp->phy_addr; + tp->phy_addr = TG3_PHY_PCIE_ADDR; + + tg3_writephy(tp, TG3_PCIEPHY_BLOCK_ADDR, + TG3_PCIEPHY_TXB_BLK << TG3_PCIEPHY_BLOCK_SHIFT); + val = TG3_PCIEPHY_TX0CTRL1_TXOCM | TG3_PCIEPHY_TX0CTRL1_RDCTL | + TG3_PCIEPHY_TX0CTRL1_TXCMV | TG3_PCIEPHY_TX0CTRL1_TKSEL | + TG3_PCIEPHY_TX0CTRL1_NB_EN; + tg3_writephy(tp, TG3_PCIEPHY_TX0CTRL1, val); + udelay(10); + + tg3_writephy(tp, TG3_PCIEPHY_BLOCK_ADDR, + TG3_PCIEPHY_XGXS_BLK1 << TG3_PCIEPHY_BLOCK_SHIFT); + val = TG3_PCIEPHY_PWRMGMT4_LOWPWR_EN | + TG3_PCIEPHY_PWRMGMT4_L1PLLPD_EN; + tg3_writephy(tp, TG3_PCIEPHY_PWRMGMT4, val); + udelay(10); + + tp->phy_addr = phy_addr; + } + if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && - tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) { + tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) { val = tr32(0x7c00); tw32(0x7c00, val | (1 << 25)); @@ -6985,24 +7510,191 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, static void __tg3_set_rx_mode(struct net_device *); static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) { - tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs); - tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs); - tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames); - tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { - tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq); - tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq); + int i; + + if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)) { + tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs); + tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames); + tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq); + } else { + tw32(HOSTCC_TXCOL_TICKS, 0); + tw32(HOSTCC_TXMAX_FRAMES, 0); + tw32(HOSTCC_TXCOAL_MAXF_INT, 0); + } + + if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) { + tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs); + tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames); + tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq); + } else { + tw32(HOSTCC_RXCOL_TICKS, 0); + tw32(HOSTCC_RXMAX_FRAMES, 0); + tw32(HOSTCC_RXCOAL_MAXF_INT, 0); } - tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq); - tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq); + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { u32 val = ec->stats_block_coalesce_usecs; + tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq); + tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq); + if (!netif_carrier_ok(tp->dev)) val = 0; tw32(HOSTCC_STAT_COAL_TICKS, val); } + + for (i = 0; i < tp->irq_cnt - 1; i++) { + u32 reg; + + reg = HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18; + tw32(reg, ec->rx_coalesce_usecs); + reg = HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18; + tw32(reg, ec->rx_max_coalesced_frames); + reg = HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18; + tw32(reg, ec->rx_max_coalesced_frames_irq); + + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) { + reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18; + tw32(reg, ec->tx_coalesce_usecs); + reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18; + tw32(reg, ec->tx_max_coalesced_frames); + reg = HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18; + tw32(reg, ec->tx_max_coalesced_frames_irq); + } + } + + for (; i < tp->irq_max - 1; i++) { + tw32(HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18, 0); + tw32(HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18, 0); + tw32(HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); + + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) { + tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0); + tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0); + tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); + } + } +} + +/* tp->lock is held. */ +static void tg3_rings_reset(struct tg3 *tp) +{ + int i; + u32 stblk, txrcb, rxrcb, limit; + struct tg3_napi *tnapi = &tp->napi[0]; + + /* Disable all transmit rings but the first. */ + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2; + else + limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE; + + for (txrcb = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE; + txrcb < limit; txrcb += TG3_BDINFO_SIZE) + tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS, + BDINFO_FLAGS_DISABLED); + + + /* Disable all receive return rings but the first. */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17; + else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4; + else + limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE; + + for (rxrcb = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE; + rxrcb < limit; rxrcb += TG3_BDINFO_SIZE) + tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS, + BDINFO_FLAGS_DISABLED); + + /* Disable interrupts */ + tw32_mailbox_f(tp->napi[0].int_mbox, 1); + + /* Zero mailbox registers. */ + if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) { + for (i = 1; i < TG3_IRQ_MAX_VECS; i++) { + tp->napi[i].tx_prod = 0; + tp->napi[i].tx_cons = 0; + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + tw32_mailbox(tp->napi[i].prodmbox, 0); + tw32_rx_mbox(tp->napi[i].consmbox, 0); + tw32_mailbox_f(tp->napi[i].int_mbox, 1); + } + if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)) + tw32_mailbox(tp->napi[0].prodmbox, 0); + } else { + tp->napi[0].tx_prod = 0; + tp->napi[0].tx_cons = 0; + tw32_mailbox(tp->napi[0].prodmbox, 0); + tw32_rx_mbox(tp->napi[0].consmbox, 0); + } + + /* Make sure the NIC-based send BD rings are disabled. */ + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + u32 mbox = MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW; + for (i = 0; i < 16; i++) + tw32_tx_mbox(mbox + i * 8, 0); + } + + txrcb = NIC_SRAM_SEND_RCB; + rxrcb = NIC_SRAM_RCV_RET_RCB; + + /* Clear status block in ram. */ + memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); + + /* Set status block DMA address */ + tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, + ((u64) tnapi->status_mapping >> 32)); + tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, + ((u64) tnapi->status_mapping & 0xffffffff)); + + if (tnapi->tx_ring) { + tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping, + (TG3_TX_RING_SIZE << + BDINFO_FLAGS_MAXLEN_SHIFT), + NIC_SRAM_TX_BUFFER_DESC); + txrcb += TG3_BDINFO_SIZE; + } + + if (tnapi->rx_rcb) { + tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping, + (TG3_RX_RCB_RING_SIZE(tp) << + BDINFO_FLAGS_MAXLEN_SHIFT), 0); + rxrcb += TG3_BDINFO_SIZE; + } + + stblk = HOSTCC_STATBLCK_RING1; + + for (i = 1, tnapi++; i < tp->irq_cnt; i++, tnapi++) { + u64 mapping = (u64)tnapi->status_mapping; + tw32(stblk + TG3_64BIT_REG_HIGH, mapping >> 32); + tw32(stblk + TG3_64BIT_REG_LOW, mapping & 0xffffffff); + + /* Clear status block in ram. */ + memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); + + if (tnapi->tx_ring) { + tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping, + (TG3_TX_RING_SIZE << + BDINFO_FLAGS_MAXLEN_SHIFT), + NIC_SRAM_TX_BUFFER_DESC); + txrcb += TG3_BDINFO_SIZE; + } + + tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping, + (TG3_RX_RCB_RING_SIZE(tp) << + BDINFO_FLAGS_MAXLEN_SHIFT), 0); + + stblk += 8; + rxrcb += TG3_BDINFO_SIZE; + } } /* tp->lock is held. */ @@ -7010,6 +7702,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) { u32 val, rdmac_mode; int i, err, limit; + struct tg3_rx_prodring_set *tpr = &tp->prodring[0]; tg3_disable_ints(tp); @@ -7062,15 +7755,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3_PCIE_EIDLE_DELAY, val | TG3_PCIE_EIDLE_DELAY_13_CLKS); tw32(TG3_CORR_ERR_STAT, TG3_CORR_ERR_STAT_CLEAR); - } - if (tp->tg3_flags3 & TG3_FLG3_TOGGLE_10_100_L1PLLPD) { - val = tr32(TG3_PCIE_LNKCTL); - if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) - val |= TG3_PCIE_LNKCTL_L1_PLL_PD_DIS; - else - val &= ~TG3_PCIE_LNKCTL_L1_PLL_PD_DIS; - tw32(TG3_PCIE_LNKCTL, val); + val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; + tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS); } /* This works around an issue with Athlon chipsets on @@ -7117,9 +7804,14 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (err) return err; - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + val = tr32(TG3PCI_DMA_RW_CTRL) & + ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT; + tw32(TG3PCI_DMA_RW_CTRL, val | tp->dma_rwctrl); + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 && + 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. */ @@ -7243,93 +7935,68 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) * configurable. */ tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->rx_std_mapping >> 32)); + ((u64) tpr->rx_std_mapping >> 32)); tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->rx_std_mapping & 0xffffffff)); - tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, - NIC_SRAM_RX_BUFFER_DESC); - - /* Don't even try to program the JUMBO/MINI buffer descriptor - * configs on 5705. - */ - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { - tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, - RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT); - } else { - tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, - RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT); + ((u64) tpr->rx_std_mapping & 0xffffffff)); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) + tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, + NIC_SRAM_RX_BUFFER_DESC); + /* Disable the mini ring */ + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) tw32(RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED); + /* Program the jumbo buffer descriptor ring control + * blocks on those devices that have them. + */ + if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && + !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { /* Setup replenish threshold. */ tw32(RCVBDI_JUMBO_THRESH, tp->rx_jumbo_pending / 8); if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->rx_jumbo_mapping >> 32)); + ((u64) tpr->rx_jmb_mapping >> 32)); tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->rx_jumbo_mapping & 0xffffffff)); + ((u64) tpr->rx_jmb_mapping & 0xffffffff)); tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, - RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT); - tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, - NIC_SRAM_RX_JUMBO_BUFFER_DESC); + (RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT) | + BDINFO_FLAGS_USE_EXT_RECV); + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, + NIC_SRAM_RX_JUMBO_BUFFER_DESC); } else { tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED); } - } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + val = (RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT) | + (RX_STD_MAX_SIZE << 2); + else + val = RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT; + } else + val = RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT; - /* There is only one send ring on 5705/5750, no need to explicitly - * disable the others. - */ - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { - /* Clear out send RCB ring in SRAM. */ - for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE) - tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); - } + tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val); - tp->tx_prod = 0; - tp->tx_cons = 0; - tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); - tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); + tpr->rx_std_prod_idx = tp->rx_pending; + tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, tpr->rx_std_prod_idx); - tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, - tp->tx_desc_mapping, - (TG3_TX_RING_SIZE << - BDINFO_FLAGS_MAXLEN_SHIFT), - NIC_SRAM_TX_BUFFER_DESC); + tpr->rx_jmb_prod_idx = (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) ? + tp->rx_jumbo_pending : 0; + tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx); - /* There is only one receive return ring on 5705/5750, no need - * to explicitly disable the others. - */ - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { - for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK; - i += TG3_BDINFO_SIZE) { - tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); - } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + tw32(STD_REPLENISH_LWM, 32); + tw32(JMB_REPLENISH_LWM, 16); } - tp->rx_rcb_ptr = 0; - tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0); - - tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB, - tp->rx_rcb_mapping, - (TG3_RX_RCB_RING_SIZE(tp) << - BDINFO_FLAGS_MAXLEN_SHIFT), - 0); - - tp->rx_std_ptr = tp->rx_pending; - tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, - tp->rx_std_ptr); - - tp->rx_jumbo_ptr = (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) ? - tp->rx_jumbo_pending : 0; - tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, - tp->rx_jumbo_ptr); + tg3_rings_reset(tp); /* Initialize MAC address and backoff seed. */ __tg3_set_mac_addr(tp, 0); @@ -7359,6 +8026,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | RDMAC_MODE_LNGREAD_ENAB); + if (tp->pci_chip_rev_id == CHIPREV_ID_5717_A0) + rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) @@ -7385,6 +8055,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) rdmac_mode |= (1 << 27); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN; + /* Receive/send statistics. */ if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { val = tr32(RCVLPC_STATS_ENABLE); @@ -7414,12 +8090,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) __tg3_set_coalesce(tp, &tp->coal); - /* set status block DMA address */ - tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->status_mapping >> 32)); - tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->status_mapping & 0xffffffff)); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { /* Status/statistics block address. See tg3_timer, * the tg3_periodic_fetch_stats call there, and @@ -7430,7 +8100,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tp->stats_mapping & 0xffffffff)); tw32(HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK); + tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK); + + /* Clear statistics and status block memory areas */ + for (i = NIC_SRAM_STATS_BLK; + i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE; + i += sizeof(u32)) { + tg3_write_mem(tp, i, 0); + udelay(40); + } } tw32(HOSTCC_MODE, HOSTCC_MODE_ENABLE | tp->coalesce_mode); @@ -7440,15 +8119,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE); - /* Clear statistics/status block in chip, and status block in ram. */ - for (i = NIC_SRAM_STATS_BLK; - i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE; - i += sizeof(u32)) { - tg3_write_mem(tp, i, 0); - udelay(40); - } - memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); - if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; /* reset to prevent losing 1st rx packet intermittently */ @@ -7500,8 +8170,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(100); - tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); - tp->last_tag = 0; + if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX) { + val = tr32(MSGINT_MODE); + val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE; + tw32(MSGINT_MODE, val); + } if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { tw32_f(DMAC_MODE, DMAC_MODE_ENABLE); @@ -7533,6 +8206,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) val |= WDMAC_MODE_STATUS_TAG_FIX; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + val |= WDMAC_MODE_BURST_ALL_DATA; + tw32_f(WDMAC_MODE, val); udelay(40); @@ -7571,7 +8247,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8); - tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE); + val = SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE; + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + val |= SNDBDI_MODE_MULTI_TXQ_EN; + tw32(SNDBDI_MODE, val); tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE); if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { @@ -7590,10 +8269,46 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32_f(MAC_TX_MODE, tp->tx_mode); udelay(100); + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) { + u32 reg = MAC_RSS_INDIR_TBL_0; + u8 *ent = (u8 *)&val; + + /* Setup the indirection table */ + for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) { + int idx = i % sizeof(val); + + ent[idx] = i % (tp->irq_cnt - 1); + if (idx == sizeof(val) - 1) { + tw32(reg, val); + reg += 4; + } + } + + /* Setup the "secret" hash key. */ + tw32(MAC_RSS_HASH_KEY_0, 0x5f865437); + tw32(MAC_RSS_HASH_KEY_1, 0xe4ac62cc); + tw32(MAC_RSS_HASH_KEY_2, 0x50103a45); + tw32(MAC_RSS_HASH_KEY_3, 0x36621985); + tw32(MAC_RSS_HASH_KEY_4, 0xbf14c0e8); + tw32(MAC_RSS_HASH_KEY_5, 0x1bc27a1e); + tw32(MAC_RSS_HASH_KEY_6, 0x84f4b556); + tw32(MAC_RSS_HASH_KEY_7, 0x094ea6fe); + tw32(MAC_RSS_HASH_KEY_8, 0x7dda01e7); + tw32(MAC_RSS_HASH_KEY_9, 0xc04d7481); + } + tp->rx_mode = RX_MODE_ENABLE; if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) + tp->rx_mode |= RX_MODE_RSS_ENABLE | + RX_MODE_RSS_ITBL_HASH_BITS_7 | + RX_MODE_RSS_IPV6_HASH_EN | + RX_MODE_RSS_TCP_IPV6_HASH_EN | + RX_MODE_RSS_IPV4_HASH_EN | + RX_MODE_RSS_TCP_IPV4_HASH_EN; + tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); @@ -7628,7 +8343,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) /* Prevent chip from dropping frames when flow control * is enabled. */ - tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + val = 1; + else + val = 2; + tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, val); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { @@ -7807,12 +8526,12 @@ static void tg3_timer(unsigned long __opaque) * IRQ status the mailbox/status_block protocol the chip * uses with the cpu is race prone. */ - if (tp->hw_status->status & SD_STATUS_UPDATED) { + if (tp->napi[0].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)); + HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW); } if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { @@ -7913,13 +8632,22 @@ restart_timer: add_timer(&tp->timer); } -static int tg3_request_irq(struct tg3 *tp) +static int tg3_request_irq(struct tg3 *tp, int irq_num) { irqreturn_t (*fn)(int, void *, struct pt_regs *); unsigned long flags; - struct net_device *dev = tp->dev; + char *name; + struct tg3_napi *tnapi = &tp->napi[irq_num]; - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { + if (tp->irq_cnt == 1) + name = tp->dev->name; + else { + name = &tnapi->irq_lbl[0]; + snprintf(name, IFNAMSIZ, "%s-%d", tp->dev->name, irq_num); + name[IFNAMSIZ-1] = 0; + } + + if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) { fn = tg3_msi; if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) fn = tg3_msi_1shot; @@ -7930,37 +8658,50 @@ static int tg3_request_irq(struct tg3 *tp) fn = tg3_interrupt_tagged; flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM; } - return (request_irq(tp->pdev->irq, fn, flags, dev->name, dev)); + + return request_irq(tnapi->irq_vec, fn, flags, name, tnapi); } static int tg3_test_interrupt(struct tg3 *tp) { + struct tg3_napi *tnapi = &tp->napi[0]; struct net_device *dev = tp->dev; int err, i, intr_ok = 0; + u32 val; if (!netif_running(dev)) return -ENODEV; tg3_disable_ints(tp); - free_irq(tp->pdev->irq, dev); + free_irq(tnapi->irq_vec, tnapi); - err = request_irq(tp->pdev->irq, tg3_test_isr, - IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev); + /* + * Turn off MSI one shot mode. Otherwise this test has no + * observable way to know whether the interrupt was delivered. + */ + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && + (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { + val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE; + tw32(MSGINT_MODE, val); + } + + err = request_irq(tnapi->irq_vec, tg3_test_isr, + IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi); if (err) return err; - tp->hw_status->status &= ~SD_STATUS_UPDATED; + tnapi->hw_status->status &= ~SD_STATUS_UPDATED; tg3_enable_ints(tp); tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | - HOSTCC_MODE_NOW); + tnapi->coal_now); for (i = 0; i < 5; i++) { u32 int_mbox, misc_host_ctrl; - int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 + - TG3_64BIT_REG_LOW); + int_mbox = tr32_mailbox(tnapi->int_mbox); misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL); if ((int_mbox != 0) || @@ -7974,15 +8715,23 @@ static int tg3_test_interrupt(struct tg3 *tp) tg3_disable_ints(tp); - free_irq(tp->pdev->irq, dev); + free_irq(tnapi->irq_vec, tnapi); - err = tg3_request_irq(tp); + err = tg3_request_irq(tp, 0); if (err) return err; - if (intr_ok) + if (intr_ok) { + /* Reenable MSI one shot mode. */ + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && + (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) { + val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE; + tw32(MSGINT_MODE, val); + } return 0; + } return -EIO; } @@ -7992,7 +8741,6 @@ static int tg3_test_interrupt(struct tg3 *tp) */ static int tg3_test_msi(struct tg3 *tp) { - struct net_device *dev = tp->dev; int err; u16 pci_cmd; @@ -8023,12 +8771,13 @@ static int tg3_test_msi(struct tg3 *tp) "the PCI maintainer and include system chipset information.\n", tp->dev->name); - free_irq(tp->pdev->irq, dev); + free_irq(tp->napi[0].irq_vec, &tp->napi[0]); + pci_disable_msi(tp->pdev); tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; - err = tg3_request_irq(tp); + err = tg3_request_irq(tp, 0); if (err) return err; @@ -8043,15 +8792,102 @@ static int tg3_test_msi(struct tg3 *tp) tg3_full_unlock(tp); if (err) - free_irq(tp->pdev->irq, dev); + free_irq(tp->napi[0].irq_vec, &tp->napi[0]); return err; } +static bool tg3_enable_msix(struct tg3 *tp) +{ + int i, rc, cpus = num_online_cpus(); + struct msix_entry msix_ent[tp->irq_max]; + + if (cpus == 1) + /* Just fallback to the simpler MSI mode. */ + return false; + + /* + * We want as many rx rings enabled as there are cpus. + * The first MSIX vector only deals with link interrupts, etc, + * so we add one to the number of vectors we are requesting. + */ + tp->irq_cnt = min_t(unsigned, cpus + 1, tp->irq_max); + + for (i = 0; i < tp->irq_max; i++) { + msix_ent[i].entry = i; + msix_ent[i].vector = 0; + } + + rc = pci_enable_msix(tp->pdev, msix_ent, tp->irq_cnt); + if (rc != 0) { + if (rc < TG3_RSS_MIN_NUM_MSIX_VECS) + return false; + if (pci_enable_msix(tp->pdev, msix_ent, rc)) + return false; + printk(KERN_NOTICE + "%s: Requested %d MSI-X vectors, received %d\n", + tp->dev->name, tp->irq_cnt, rc); + tp->irq_cnt = rc; + } + + tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS; + + for (i = 0; i < tp->irq_max; i++) + tp->napi[i].irq_vec = msix_ent[i].vector; + + return true; +} + +static void tg3_ints_init(struct tg3 *tp) +{ + if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI_OR_MSIX) && + !(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { + /* All MSI supporting chips should support tagged + * status. Assert that this is the case. + */ + + /* Hardware bug - MSI won't work if INTX disabled. */ + if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + pci_intx(tp->pdev, 1); + + printk(KERN_WARNING PFX "%s: MSI without TAGGED? " + "Not using MSI.\n", tp->dev->name); + goto defcfg; + } + + if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) && tg3_enable_msix(tp)) + tp->tg3_flags2 |= TG3_FLG2_USING_MSIX; + else if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) && + pci_enable_msi(tp->pdev) == 0) + tp->tg3_flags2 |= TG3_FLG2_USING_MSI; + + if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) { + u32 msi_mode = tr32(MSGINT_MODE); + if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX) + msi_mode |= MSGINT_MODE_MULTIVEC_EN; + tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); + } +defcfg: + if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) { + tp->irq_cnt = 1; + tp->napi[0].irq_vec = tp->pdev->irq; + } +} + +static void tg3_ints_fini(struct tg3 *tp) +{ + if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX) + pci_disable_msix(tp->pdev); + else if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) + pci_disable_msi(tp->pdev); + tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI_OR_MSIX; + tp->tg3_flags3 &= ~TG3_FLG3_ENABLE_RSS; +} + static int tg3_open(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); - int err; + int i, err; netif_carrier_off(tp->dev); @@ -8066,42 +8902,31 @@ static int tg3_open(struct net_device *dev) tg3_full_unlock(tp); + /* + * Setup interrupts first so we know how + * many NAPI resources to allocate + */ + tg3_ints_init(tp); + /* The placement of this call is tied * to the setup and use of Host TX descriptors. */ err = tg3_alloc_consistent(tp); if (err) - return err; - - if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) { - /* All MSI supporting chips should support tagged - * status. Assert that this is the case. - */ - if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { - printk(KERN_WARNING PFX "%s: MSI without TAGGED? " - "Not using MSI.\n", tp->dev->name); - } 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); + goto err_out1; - msi_mode = tr32(MSGINT_MODE); - tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); - tp->tg3_flags2 |= TG3_FLG2_USING_MSI; + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + err = tg3_request_irq(tp, i); + if (err) { + for (i--; i >= 0; i--) + free_irq(tnapi->irq_vec, tnapi); + break; } } - err = tg3_request_irq(tp); - if (err) { - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { - pci_disable_msi(tp->pdev); - tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; - } - tg3_free_consistent(tp); - return err; - } + if (err) + goto err_out2; tg3_full_lock(tp, 0); @@ -8129,42 +8954,29 @@ static int tg3_open(struct net_device *dev) tg3_full_unlock(tp); - if (err) { - free_irq(tp->pdev->irq, dev); - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { - pci_disable_msi(tp->pdev); - tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; - } - tg3_free_consistent(tp); - return err; - } + if (err) + goto err_out3; if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { err = tg3_test_msi(tp); if (err) { tg3_full_lock(tp, 0); - - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { - pci_disable_msi(tp->pdev); - tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; - } tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); - tg3_free_consistent(tp); - tg3_full_unlock(tp); - return err; + goto err_out2; } - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { - if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) { - u32 val = tr32(PCIE_TRANSACTION_CFG); + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765 && + (tp->tg3_flags2 & TG3_FLG2_USING_MSI) && + (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)) { + u32 val = tr32(PCIE_TRANSACTION_CFG); - tw32(PCIE_TRANSACTION_CFG, - val | PCIE_TRANS_CFG_1SHOT_MSI); - } + tw32(PCIE_TRANSACTION_CFG, + val | PCIE_TRANS_CFG_1SHOT_MSI); } } @@ -8179,6 +8991,19 @@ static int tg3_open(struct net_device *dev) netif_start_queue(dev); return 0; + +err_out3: + for (i = tp->irq_cnt - 1; i >= 0; i--) { + struct tg3_napi *tnapi = &tp->napi[i]; + free_irq(tnapi->irq_vec, tnapi); + } + +err_out2: + tg3_free_consistent(tp); + +err_out1: + tg3_ints_fini(tp); + return err; } #if 0 @@ -8187,6 +9012,7 @@ static int tg3_open(struct net_device *dev) u32 val32, val32_2, val32_3, val32_4, val32_5; u16 val16; int i; + struct tg3_hw_status *sblk = tp->napi[0]->hw_status; pci_read_config_word(tp->pdev, PCI_STATUS, &val16); pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &val32); @@ -8339,14 +9165,15 @@ static int tg3_open(struct net_device *dev) val32, val32_2, val32_3, val32_4, val32_5); /* SW status block */ - printk("DEBUG: Host status block [%08x:%08x:(%04x:%04x:%04x):(%04x:%04x)]\n", - tp->hw_status->status, - tp->hw_status->status_tag, - tp->hw_status->rx_jumbo_consumer, - tp->hw_status->rx_consumer, - tp->hw_status->rx_mini_consumer, - tp->hw_status->idx[0].rx_producer, - tp->hw_status->idx[0].tx_consumer); + printk(KERN_DEBUG + "Host status block [%08x:%08x:(%04x:%04x:%04x):(%04x:%04x)]\n", + sblk->status, + sblk->status_tag, + sblk->rx_jumbo_consumer, + sblk->rx_consumer, + sblk->rx_mini_consumer, + sblk->idx[0].rx_producer, + sblk->idx[0].tx_consumer); /* SW statistics block */ printk("DEBUG: Host statistics block [%08x:%08x:%08x:%08x]\n", @@ -8414,6 +9241,7 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *); static int tg3_close(struct net_device *dev) { + int i; struct tg3 *tp = netdev_priv(dev); /* Calling flush_scheduled_work() may deadlock because @@ -8440,12 +9268,13 @@ static int tg3_close(struct net_device *dev) tg3_full_unlock(tp); - free_irq(tp->pdev->irq, dev); - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { - pci_disable_msi(tp->pdev); - tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; + for (i = tp->irq_cnt - 1; i >= 0; i--) { + struct tg3_napi *tnapi = &tp->napi[i]; + free_irq(tnapi->irq_vec, tnapi); } + tg3_ints_fini(tp); + memcpy(&tp->net_stats_prev, tg3_get_stats(tp->dev), sizeof(tp->net_stats_prev)); memcpy(&tp->estats_prev, tg3_get_estats(tp), @@ -9003,7 +9832,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->speed = tp->link_config.active_speed; cmd->duplex = tp->link_config.active_duplex; } - cmd->phy_address = PHY_ADDR; + cmd->phy_address = tp->phy_addr; cmd->transceiver = XCVR_INTERNAL; cmd->autoneg = tp->link_config.autoneg; cmd->maxtxpkt = 0; @@ -9058,12 +9887,12 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (cmd->speed != SPEED_1000) return -EINVAL; - if (cmd->duplex != DUPLEX_FULL) - return -EINVAL; + if (cmd->duplex != DUPLEX_FULL) + return -EINVAL; } else { if (cmd->speed != SPEED_100 && cmd->speed != SPEED_10) - return -EINVAL; + return -EINVAL; } } @@ -9166,7 +9995,8 @@ static int tg3_set_tso(struct net_device *dev, u32 value) (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) dev->features |= NETIF_F_TSO_ECN; } else dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN); @@ -9221,13 +10051,13 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam * else ering->rx_jumbo_pending = 0; - ering->tx_pending = tp->tx_pending; + ering->tx_pending = tp->napi[0].tx_pending; } static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { struct tg3 *tp = netdev_priv(dev); - int irq_sync = 0, err = 0; + int i, irq_sync = 0, err = 0; if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || @@ -9250,7 +10080,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e tp->rx_pending > 63) tp->rx_pending = 63; tp->rx_jumbo_pending = ering->rx_jumbo_pending; - tp->tx_pending = ering->tx_pending; + + for (i = 0; i < TG3_IRQ_MAX_VECS; i++) + tp->napi[i].tx_pending = ering->tx_pending; if (netif_running(dev)) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); @@ -9867,12 +10699,27 @@ static int tg3_test_memory(struct tg3 *tp) { 0x00008000, 0x01000}, { 0x00010000, 0x01000}, { 0xffffffff, 0x00000} + }, mem_tbl_5717[] = { + { 0x00000200, 0x00008}, + { 0x00010000, 0x0a000}, + { 0x00020000, 0x13c00}, + { 0xffffffff, 0x00000} + }, mem_tbl_57765[] = { + { 0x00000200, 0x00008}, + { 0x00004000, 0x00800}, + { 0x00006000, 0x09800}, + { 0x00010000, 0x0a000}, + { 0xffffffff, 0x00000} }; struct mem_entry *mem_tbl; int err = 0; int i; - if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + mem_tbl = mem_tbl_5717; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + mem_tbl = mem_tbl_57765; + else if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) mem_tbl = mem_tbl_5755; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) mem_tbl = mem_tbl_5906; @@ -9896,12 +10743,23 @@ static int tg3_test_memory(struct tg3 *tp) static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) { u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key; - u32 desc_idx; + u32 desc_idx, coal_now; struct sk_buff *skb, *rx_skb; u8 *tx_data; dma_addr_t map; int num_pkts, tx_len, rx_len, i, err; struct tg3_rx_buffer_desc *desc; + struct tg3_napi *tnapi, *rnapi; + struct tg3_rx_prodring_set *tpr = &tp->prodring[0]; + + tnapi = &tp->napi[0]; + rnapi = &tp->napi[0]; + if (tp->irq_cnt > 1) { + rnapi = &tp->napi[1]; + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + tnapi = &tp->napi[1]; + } + coal_now = tnapi->coal_now | rnapi->coal_now; if (loopback_mode == TG3_MAC_LOOPBACK) { /* HW errata - mac loopback fails in some cases on 5780. @@ -9992,38 +10850,36 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) map = pci_map_single(tp->pdev, skb->data, tx_len, PCI_DMA_TODEVICE); tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | - HOSTCC_MODE_NOW); + rnapi->coal_now); udelay(10); - rx_start_idx = tp->hw_status->idx[0].rx_producer; + rx_start_idx = rnapi->hw_status->idx[0].rx_producer; num_pkts = 0; - tg3_set_txd(tp, tp->tx_prod, map, tx_len, 0, 1); + tg3_set_txd(tnapi, tnapi->tx_prod, map, tx_len, 0, 1); - tp->tx_prod++; + tnapi->tx_prod++; num_pkts++; /* Some platforms need to sync memory here */ wmb(); - - tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, - tp->tx_prod); - tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW); + tw32_tx_mbox(tnapi->prodmbox, tnapi->tx_prod); + tr32_mailbox(tnapi->prodmbox); udelay(10); - /* 250 usec to allow enough time on some 10/100 Mbps devices. */ - for (i = 0; i < 25; i++) { + /* 350 usec to allow enough time on some 10/100 Mbps devices. */ + for (i = 0; i < 35; i++) { tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | - HOSTCC_MODE_NOW); + coal_now); udelay(10); - tx_idx = tp->hw_status->idx[0].tx_consumer; - rx_idx = tp->hw_status->idx[0].rx_producer; - if ((tx_idx == tp->tx_prod) && + tx_idx = tnapi->hw_status->idx[0].tx_consumer; + rx_idx = rnapi->hw_status->idx[0].rx_producer; + if ((tx_idx == tnapi->tx_prod) && (rx_idx == (rx_start_idx + num_pkts))) break; } @@ -10031,13 +10887,13 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE); dev_kfree_skb(skb); - if (tx_idx != tp->tx_prod) + if (tx_idx != tnapi->tx_prod) goto out; if (rx_idx != rx_start_idx + num_pkts) goto out; - desc = &tp->rx_rcb[rx_start_idx]; + desc = &rnapi->rx_rcb[rx_start_idx]; desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; if (opaque_key != RXD_OPAQUE_RING_STD) @@ -10051,9 +10907,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) if (rx_len != tx_len) goto out; - rx_skb = tp->rx_std_buffers[desc_idx].skb; + rx_skb = tpr->rx_std_buffers[desc_idx].skb; - map = pci_unmap_addr(&tp->rx_std_buffers[desc_idx], mapping); + map = pci_unmap_addr(&tpr->rx_std_buffers[desc_idx], mapping); pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, PCI_DMA_FROMDEVICE); for (i = 14; i < tx_len; i++) { @@ -10216,7 +11072,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) switch(cmd) { case SIOCGMIIPHY: - data->phy_id = PHY_ADDR; + data->phy_id = tp->phy_addr; /* fallthru */ case SIOCGMIIREG: { @@ -10241,9 +11097,6 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) break; /* We have no PHY */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (tp->link_config.phy_is_low_power) return -EAGAIN; @@ -10460,8 +11313,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp) nvcfg1 = tr32(NVRAM_CFG1); if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { tp->tg3_flags2 |= TG3_FLG2_FLASH; - } - else { + } else { nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; tw32(NVRAM_CFG1, nvcfg1); } @@ -10469,43 +11321,69 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp) if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) { - case FLASH_VENDOR_ATMEL_FLASH_BUFFERED: - tp->nvram_jedecnum = JEDEC_ATMEL; - tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - break; - case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED: - tp->nvram_jedecnum = JEDEC_ATMEL; - tp->nvram_pagesize = ATMEL_AT25F512_PAGE_SIZE; - break; - case FLASH_VENDOR_ATMEL_EEPROM: - tp->nvram_jedecnum = JEDEC_ATMEL; - tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - break; - case FLASH_VENDOR_ST: - tp->nvram_jedecnum = JEDEC_ST; - tp->nvram_pagesize = ST_M45PEX0_PAGE_SIZE; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - break; - case FLASH_VENDOR_SAIFUN: - tp->nvram_jedecnum = JEDEC_SAIFUN; - tp->nvram_pagesize = SAIFUN_SA25F0XX_PAGE_SIZE; - break; - case FLASH_VENDOR_SST_SMALL: - case FLASH_VENDOR_SST_LARGE: - tp->nvram_jedecnum = JEDEC_SST; - tp->nvram_pagesize = SST_25VF0X0_PAGE_SIZE; - break; + case FLASH_VENDOR_ATMEL_FLASH_BUFFERED: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + break; + case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->nvram_pagesize = ATMEL_AT25F512_PAGE_SIZE; + break; + case FLASH_VENDOR_ATMEL_EEPROM: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + break; + case FLASH_VENDOR_ST: + tp->nvram_jedecnum = JEDEC_ST; + tp->nvram_pagesize = ST_M45PEX0_PAGE_SIZE; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + break; + case FLASH_VENDOR_SAIFUN: + tp->nvram_jedecnum = JEDEC_SAIFUN; + tp->nvram_pagesize = SAIFUN_SA25F0XX_PAGE_SIZE; + break; + case FLASH_VENDOR_SST_SMALL: + case FLASH_VENDOR_SST_LARGE: + tp->nvram_jedecnum = JEDEC_SST; + tp->nvram_pagesize = SST_25VF0X0_PAGE_SIZE; + break; } - } - else { + } else { tp->nvram_jedecnum = JEDEC_ATMEL; tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; } } +static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1) +{ + switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) { + case FLASH_5752PAGE_SIZE_256: + tp->nvram_pagesize = 256; + break; + case FLASH_5752PAGE_SIZE_512: + tp->nvram_pagesize = 512; + break; + case FLASH_5752PAGE_SIZE_1K: + tp->nvram_pagesize = 1024; + break; + case FLASH_5752PAGE_SIZE_2K: + tp->nvram_pagesize = 2048; + break; + case FLASH_5752PAGE_SIZE_4K: + tp->nvram_pagesize = 4096; + break; + case FLASH_5752PAGE_SIZE_264: + tp->nvram_pagesize = 264; + break; + case FLASH_5752PAGE_SIZE_528: + tp->nvram_pagesize = 528; + break; + } +} + static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -10514,51 +11392,31 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) /* NVRAM protection for TPM */ if (nvcfg1 & (1 << 27)) - tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; + tp->tg3_flags3 |= TG3_FLG3_PROTECTED_NVRAM; switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { - case FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ: - case FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ: - tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - break; - case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: - tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; - break; - case FLASH_5752VENDOR_ST_M45PE10: - case FLASH_5752VENDOR_ST_M45PE20: - case FLASH_5752VENDOR_ST_M45PE40: - tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; - break; + case FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ: + case FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + break; + case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + break; + case FLASH_5752VENDOR_ST_M45PE10: + case FLASH_5752VENDOR_ST_M45PE20: + case FLASH_5752VENDOR_ST_M45PE40: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + break; } if (tp->tg3_flags2 & TG3_FLG2_FLASH) { - switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) { - case FLASH_5752PAGE_SIZE_256: - tp->nvram_pagesize = 256; - break; - case FLASH_5752PAGE_SIZE_512: - tp->nvram_pagesize = 512; - break; - case FLASH_5752PAGE_SIZE_1K: - tp->nvram_pagesize = 1024; - break; - case FLASH_5752PAGE_SIZE_2K: - tp->nvram_pagesize = 2048; - break; - case FLASH_5752PAGE_SIZE_4K: - tp->nvram_pagesize = 4096; - break; - case FLASH_5752PAGE_SIZE_264: - tp->nvram_pagesize = 264; - break; - } - } - else { + tg3_nvram_get_pagesize(tp, nvcfg1); + } else { /* For eeprom, set pagesize to maximum eeprom size */ tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; @@ -10575,51 +11433,51 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) /* NVRAM protection for TPM */ if (nvcfg1 & (1 << 27)) { - tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; + tp->tg3_flags3 |= TG3_FLG3_PROTECTED_NVRAM; protect = 1; } 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_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 : - TG3_NVRAM_SIZE_512KB); - else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2) - tp->nvram_size = (protect ? 0x1f200 : - TG3_NVRAM_SIZE_256KB); - else - tp->nvram_size = (protect ? 0x1f200 : - TG3_NVRAM_SIZE_128KB); - break; - case FLASH_5752VENDOR_ST_M45PE10: - case FLASH_5752VENDOR_ST_M45PE20: - case FLASH_5752VENDOR_ST_M45PE40: - tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; - tp->nvram_pagesize = 256; - if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10) - tp->nvram_size = (protect ? - TG3_NVRAM_SIZE_64KB : - TG3_NVRAM_SIZE_128KB); - else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20) - tp->nvram_size = (protect ? - TG3_NVRAM_SIZE_64KB : - TG3_NVRAM_SIZE_256KB); - else - tp->nvram_size = (protect ? - TG3_NVRAM_SIZE_128KB : - TG3_NVRAM_SIZE_512KB); - break; + case FLASH_5755VENDOR_ATMEL_FLASH_1: + case FLASH_5755VENDOR_ATMEL_FLASH_2: + case FLASH_5755VENDOR_ATMEL_FLASH_3: + 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 : + TG3_NVRAM_SIZE_512KB); + else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2) + tp->nvram_size = (protect ? 0x1f200 : + TG3_NVRAM_SIZE_256KB); + else + tp->nvram_size = (protect ? 0x1f200 : + TG3_NVRAM_SIZE_128KB); + break; + case FLASH_5752VENDOR_ST_M45PE10: + case FLASH_5752VENDOR_ST_M45PE20: + case FLASH_5752VENDOR_ST_M45PE40: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 256; + if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10) + tp->nvram_size = (protect ? + TG3_NVRAM_SIZE_64KB : + TG3_NVRAM_SIZE_128KB); + else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20) + tp->nvram_size = (protect ? + TG3_NVRAM_SIZE_64KB : + TG3_NVRAM_SIZE_256KB); + else + tp->nvram_size = (protect ? + TG3_NVRAM_SIZE_128KB : + TG3_NVRAM_SIZE_512KB); + break; } } @@ -10630,34 +11488,34 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) nvcfg1 = tr32(NVRAM_CFG1); switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { - case FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ: - case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ: - case FLASH_5787VENDOR_MICRO_EEPROM_64KHZ: - case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ: - tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; + case FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ: + case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ: + case FLASH_5787VENDOR_MICRO_EEPROM_64KHZ: + case FLASH_5787VENDOR_MICRO_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: - case FLASH_5755VENDOR_ATMEL_FLASH_1: - case FLASH_5755VENDOR_ATMEL_FLASH_2: - case FLASH_5755VENDOR_ATMEL_FLASH_3: - tp->nvram_jedecnum = JEDEC_ATMEL; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; - tp->nvram_pagesize = 264; - break; - case FLASH_5752VENDOR_ST_M45PE10: - case FLASH_5752VENDOR_ST_M45PE20: - case FLASH_5752VENDOR_ST_M45PE40: - tp->nvram_jedecnum = JEDEC_ST; - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - tp->tg3_flags2 |= TG3_FLG2_FLASH; - tp->nvram_pagesize = 256; - break; + nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; + tw32(NVRAM_CFG1, nvcfg1); + break; + case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: + case FLASH_5755VENDOR_ATMEL_FLASH_1: + case FLASH_5755VENDOR_ATMEL_FLASH_2: + case FLASH_5755VENDOR_ATMEL_FLASH_3: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 264; + break; + case FLASH_5752VENDOR_ST_M45PE10: + case FLASH_5752VENDOR_ST_M45PE20: + case FLASH_5752VENDOR_ST_M45PE40: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 256; + break; } } @@ -10669,69 +11527,69 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) /* NVRAM protection for TPM */ if (nvcfg1 & (1 << 27)) { - tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; + tp->tg3_flags3 |= TG3_FLG3_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; + 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 = TG3_NVRAM_SIZE_2MB; - 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 = TG3_NVRAM_SIZE_1MB; - 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 = TG3_NVRAM_SIZE_512KB; - 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 = TG3_NVRAM_SIZE_256KB; - break; + 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 = TG3_NVRAM_SIZE_2MB; + 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 = TG3_NVRAM_SIZE_1MB; + 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 = TG3_NVRAM_SIZE_512KB; + 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 = TG3_NVRAM_SIZE_256KB; + break; } } } @@ -10810,34 +11668,84 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) return; } - switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) { - case FLASH_5752PAGE_SIZE_256: - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; - tp->nvram_pagesize = 256; - break; - case FLASH_5752PAGE_SIZE_512: + tg3_nvram_get_pagesize(tp, nvcfg1); + if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528) tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; - tp->nvram_pagesize = 512; - break; - case FLASH_5752PAGE_SIZE_1K: - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; - tp->nvram_pagesize = 1024; - break; - case FLASH_5752PAGE_SIZE_2K: - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; - tp->nvram_pagesize = 2048; - break; - case FLASH_5752PAGE_SIZE_4K: - tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; - tp->nvram_pagesize = 4096; - break; - case FLASH_5752PAGE_SIZE_264: - tp->nvram_pagesize = 264; +} + + +static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) +{ + u32 nvcfg1; + + nvcfg1 = tr32(NVRAM_CFG1); + + switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { + case FLASH_5717VENDOR_ATMEL_EEPROM: + case FLASH_5717VENDOR_MICRO_EEPROM: + 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); + return; + case FLASH_5717VENDOR_ATMEL_MDB011D: + case FLASH_5717VENDOR_ATMEL_ADB011B: + case FLASH_5717VENDOR_ATMEL_ADB011D: + case FLASH_5717VENDOR_ATMEL_MDB021D: + case FLASH_5717VENDOR_ATMEL_ADB021B: + case FLASH_5717VENDOR_ATMEL_ADB021D: + case FLASH_5717VENDOR_ATMEL_45USPT: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + + switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { + case FLASH_5717VENDOR_ATMEL_MDB021D: + case FLASH_5717VENDOR_ATMEL_ADB021B: + case FLASH_5717VENDOR_ATMEL_ADB021D: + tp->nvram_size = TG3_NVRAM_SIZE_256KB; + break; + default: + tp->nvram_size = TG3_NVRAM_SIZE_128KB; + break; + } break; - case FLASH_5752PAGE_SIZE_528: - tp->nvram_pagesize = 528; + case FLASH_5717VENDOR_ST_M_M25PE10: + case FLASH_5717VENDOR_ST_A_M25PE10: + case FLASH_5717VENDOR_ST_M_M45PE10: + case FLASH_5717VENDOR_ST_A_M45PE10: + case FLASH_5717VENDOR_ST_M_M25PE20: + case FLASH_5717VENDOR_ST_A_M25PE20: + case FLASH_5717VENDOR_ST_M_M45PE20: + case FLASH_5717VENDOR_ST_A_M45PE20: + case FLASH_5717VENDOR_ST_25USPT: + case FLASH_5717VENDOR_ST_45USPT: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + + switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { + case FLASH_5717VENDOR_ST_M_M25PE20: + case FLASH_5717VENDOR_ST_A_M25PE20: + case FLASH_5717VENDOR_ST_M_M45PE20: + case FLASH_5717VENDOR_ST_A_M45PE20: + tp->nvram_size = TG3_NVRAM_SIZE_256KB; + break; + default: + tp->nvram_size = TG3_NVRAM_SIZE_128KB; + break; + } break; + default: + tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM; + return; } + + tg3_nvram_get_pagesize(tp, nvcfg1); + if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528) + tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; } /* Chips other than 5700/5701 use the NVRAM for fetching info. */ @@ -10880,8 +11788,11 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) 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 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tg3_get_57780_nvram_info(tp); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + tg3_get_5717_nvram_info(tp); else tg3_get_nvram_info(tp); @@ -11118,7 +12029,7 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) tg3_enable_nvram_access(tp); if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && - !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) + !(tp->tg3_flags3 & TG3_FLG3_PROTECTED_NVRAM)) tw32(NVRAM_WRITE1, 0x406); grc_mode = tr32(GRC_MODE); @@ -11291,7 +12202,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->phy_id = eeprom_phy_id; if (eeprom_phy_serdes) { - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) tp->tg3_flags2 |= TG3_FLG2_MII_SERDES; else tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; @@ -11704,6 +12616,8 @@ out_not_found: else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 && tp->pdev->device == TG3PCI_DEVICE_TIGON3_57788) strcpy(tp->board_part_number, "BCM57788"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + strcpy(tp->board_part_number, "BCM57765"); else strcpy(tp->board_part_number, "none"); } @@ -11988,8 +12902,25 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) 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); + if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5724) + pci_read_config_dword(tp->pdev, + TG3PCI_GEN2_PRODID_ASICREV, + &prod_id_asic_rev); + else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795) + pci_read_config_dword(tp->pdev, + TG3PCI_GEN15_PRODID_ASICREV, + &prod_id_asic_rev); + else + pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV, + &prod_id_asic_rev); + tp->pci_chip_rev_id = prod_id_asic_rev; } @@ -12131,8 +13062,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl); - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) tp->pdev_peer = tg3_find_peer(tp); /* Intentionally exclude ASIC_REV_5906 */ @@ -12141,7 +13073,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tp->tg3_flags3 |= TG3_FLG3_5755_PLUS; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || @@ -12177,9 +13111,30 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } + tp->irq_max = 1; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + tp->tg3_flags |= TG3_FLAG_SUPPORT_MSIX; + tp->irq_max = TG3_IRQ_MAX_VECS; + } + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tp->tg3_flags3 |= TG3_FLG3_SHORT_DMA_BUG; + else if (!(tp->tg3_flags3 & TG3_FLG3_5755_PLUS)) { + tp->tg3_flags3 |= TG3_FLG3_4G_DMA_BNDRY_BUG; + tp->tg3_flags3 |= TG3_FLG3_40BIT_DMA_LIMIT_BUG; + } + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + tp->tg3_flags3 |= TG3_FLG3_USE_JUMBO_BDFLAG; + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) - tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; + (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || + (tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG)) + tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE; pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg); @@ -12314,7 +13269,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->write32 = tg3_write_flush_reg32; } - if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) || (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) { tp->write32_tx_mbox = tg3_write32_tx_mbox; @@ -12373,7 +13327,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; /* Set up tp->grc_local_ctrl before calling tg3_set_power_state(). @@ -12459,7 +13415,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && !(tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780) { + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) { 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_5784 || @@ -12497,10 +13455,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX) tp->coalesce_mode |= HOSTCC_MODE_32BYTE; - if ((tp->pci_chip_rev_id == CHIPREV_ID_57780_A1 && - tr32(RCVLPC_STATS_ENABLE) & RCVLPC_STATSENAB_ASF_FIX) || - tp->pci_chip_rev_id == CHIPREV_ID_57780_A0) - tp->tg3_flags3 |= TG3_FLG3_TOGGLE_10_100_L1PLLPD; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 && + (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0 || + (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) + return -ENOTSUPP; /* Initialize data/descriptor byte/word swapping. */ val = tr32(GRC_MODE); @@ -12634,8 +13592,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* All chips before 5787 can get confused if TX buffers * straddle the 4GB address boundary in some cases. */ - if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) && + tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) tp->dev->hard_start_xmit = tg3_start_xmit; else tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug; @@ -12714,8 +13672,10 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) tw32_f(NVRAM_CMD, NVRAM_CMD_RESET); else tg3_nvram_unlock(tp); - } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { + if (tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC) + mac_offset = 0xcc; + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) mac_offset = 0x10; /* First try to get it from MAC address mailbox. */ @@ -12799,6 +13759,12 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) #endif #endif + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + val = goal ? 0 : DMA_RWCTRL_DIS_CACHE_ALIGNMENT; + goto out; + } + if (!goal) goto out; @@ -12993,7 +13959,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp) { dma_addr_t buf_dma; u32 *buf, saved_dma_rwctrl; - int ret; + int ret = 0; buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma); if (!buf) { @@ -13006,6 +13972,10 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + goto out; + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { /* DMA read watermark not used on PCIE */ tp->dma_rwctrl |= 0x00180000; @@ -13078,7 +14048,6 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tg3_switch_clocks(tp); #endif - ret = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) goto out; @@ -13196,7 +14165,22 @@ static void __devinit tg3_init_link_config(struct tg3 *tp) static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) { - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + tp->bufmgr_config.mbuf_read_dma_low_water = + DEFAULT_MB_RDMA_LOW_WATER_5705; + tp->bufmgr_config.mbuf_mac_rx_low_water = + DEFAULT_MB_MACRX_LOW_WATER_57765; + tp->bufmgr_config.mbuf_high_water = + DEFAULT_MB_HIGH_WATER_57765; + + tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = + DEFAULT_MB_RDMA_LOW_WATER_5705; + tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo = + DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765; + tp->bufmgr_config.mbuf_high_water_jumbo = + DEFAULT_MB_HIGH_WATER_JUMBO_57765; + } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { tp->bufmgr_config.mbuf_read_dma_low_water = DEFAULT_MB_RDMA_LOW_WATER_5705; tp->bufmgr_config.mbuf_mac_rx_low_water = @@ -13256,7 +14240,10 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5756: return "5722/5756"; case PHY_ID_BCM5906: return "5906"; case PHY_ID_BCM5761: return "5761"; + case PHY_ID_BCM5718C: return "5718C"; + case PHY_ID_BCM5718S: return "5718S"; case PHY_ID_BCM57780: return "57780"; + case PHY_ID_BCM57765: return "57765"; case PHY_ID_BCM50610: return "50610"; case PHY_ID_BCM50610M: return "50610M"; case PHY_ID_BCMAC131: return "AC131"; @@ -13370,8 +14357,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, struct net_device *dev; struct tg3 *tp; int i, err, pm_cap; + u32 sndmbx, rcvmbx, intmbx; char str[40]; u64 dma_mask, persist_dma_mask; + struct tg3_napi *tnapi; if (tg3_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -13476,7 +14465,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->rx_pending = TG3_DEF_RX_RING_PENDING; tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING; - tp->tx_pending = TG3_DEF_TX_RING_PENDING; dev->open = tg3_open; dev->stop = tg3_close; @@ -13566,7 +14554,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) dev->features |= NETIF_F_TSO6; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) dev->features |= NETIF_F_TSO_ECN; } @@ -13645,6 +14634,57 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX; + intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW; + rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW; + sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW; + for (i = 0; i < TG3_IRQ_MAX_VECS; i++) { + tnapi = &tp->napi[i]; + + tnapi->tp = tp; + tnapi->tx_pending = TG3_DEF_TX_RING_PENDING; + + tnapi->int_mbox = intmbx; + if (i < 4) + intmbx += 0x8; + else + intmbx += 0x4; + + tnapi->consmbox = rcvmbx; + tnapi->prodmbox = sndmbx; + + if (i) { + tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1); + } else { + tnapi->coal_now = HOSTCC_MODE_NOW; + } + + tnapi->dummy_netdev = alloc_netdev(0, "", ether_setup); + tnapi->dummy_netdev->priv = tnapi; + tnapi->dummy_netdev->weight = 64; + tnapi->dummy_netdev->poll = tg3_poll; + set_bit(__LINK_STATE_START, &tnapi->dummy_netdev->state); + + if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX)) + break; + + /* + * If we support MSIX, we'll be using RSS. If we're using + * RSS, the first vector only handles link interrupts and the + * remaining vectors handle rx and tx interrupts. Reuse the + * mailbox values for the next iteration. The values we setup + * above are still useful for the single vectored mode. + */ + if (!i) + continue; + + rcvmbx += 0x8; + + if (sndmbx & 0x4) + sndmbx -= 0x4; + else + sndmbx += 0xc; + } + tg3_init_coal(tp); pci_set_drvdata(pdev, dev); @@ -13716,9 +14756,14 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) if (dev) { struct tg3 *tp = netdev_priv(dev); + struct tg3_napi *tnapi = &tp->napi[0]; flush_scheduled_work(); unregister_netdev(dev); + if (tnapi->dummy_netdev) { + free_netdev(tnapi->dummy_netdev); + tnapi->dummy_netdev = NULL; + } if (tp->aperegs) { iounmap(tp->aperegs); tp->aperegs = NULL; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 32f16ef..1a3a27d 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -4,6 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. + * Copyright (C) 2007-2010 Broadcom Corporation. */ #ifndef _T3_H @@ -44,7 +45,17 @@ #define TG3PCI_DEVICE_TIGON3_57760 0x1690 #define TG3PCI_DEVICE_TIGON3_57790 0x1694 #define TG3PCI_DEVICE_TIGON3_57788 0x1691 +#define TG3PCI_DEVICE_TIGON3_5785_G 0x1699 /* GPHY */ #define TG3PCI_DEVICE_TIGON3_5785_F 0x16a0 +#define TG3PCI_DEVICE_TIGON3_5717 0x1655 +#define TG3PCI_DEVICE_TIGON3_5718 0x1656 +#define TG3PCI_DEVICE_TIGON3_5724 0x165c +#define TG3PCI_DEVICE_TIGON3_57781 0x16b1 +#define TG3PCI_DEVICE_TIGON3_57785 0x16b5 +#define TG3PCI_DEVICE_TIGON3_57761 0x16b0 +#define TG3PCI_DEVICE_TIGON3_57765 0x16b4 +#define TG3PCI_DEVICE_TIGON3_57791 0x16b2 +#define TG3PCI_DEVICE_TIGON3_57795 0x16b6 /* 0x04 --> 0x64 unused */ #define TG3PCI_MSI_DATA 0x00000064 /* 0x66 --> 0x68 unused */ @@ -98,6 +109,7 @@ #define CHIPREV_ID_5906_A1 0xc001 #define CHIPREV_ID_57780_A0 0x57780000 #define CHIPREV_ID_57780_A1 0x57780001 +#define CHIPREV_ID_5717_A0 0x05717000 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 @@ -116,6 +128,8 @@ #define ASIC_REV_5761 0x5761 #define ASIC_REV_5785 0x5785 #define ASIC_REV_57780 0x57780 +#define ASIC_REV_5717 0x5717 +#define ASIC_REV_57765 0x57785 #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -135,8 +149,7 @@ #define METAL_REV_B1 0x01 #define METAL_REV_B2 0x02 #define TG3PCI_DMA_RW_CTRL 0x0000006c -#define DMA_RWCTRL_MIN_DMA 0x000000ff -#define DMA_RWCTRL_MIN_DMA_SHIFT 0 +#define DMA_RWCTRL_DIS_CACHE_ALIGNMENT 0x00000001 #define DMA_RWCTRL_READ_BNDRY_MASK 0x00000700 #define DMA_RWCTRL_READ_BNDRY_DISAB 0x00000000 #define DMA_RWCTRL_READ_BNDRY_16 0x00000100 @@ -202,20 +215,21 @@ #define TG3PCI_MEM_WIN_BASE_ADDR 0x0000007c #define TG3PCI_REG_DATA 0x00000080 #define TG3PCI_MEM_WIN_DATA 0x00000084 -#define TG3PCI_MODE_CTRL 0x00000088 -#define TG3PCI_MISC_CFG 0x0000008c #define TG3PCI_MISC_LOCAL_CTRL 0x00000090 /* 0x94 --> 0x98 unused */ #define TG3PCI_STD_RING_PROD_IDX 0x00000098 /* 64-bit */ #define TG3PCI_RCV_RET_RING_CON_IDX 0x000000a0 /* 64-bit */ -#define TG3PCI_SND_PROD_IDX 0x000000a8 /* 64-bit */ -/* 0xb0 --> 0xb8 unused */ +/* 0xa0 --> 0xb8 unused */ #define TG3PCI_DUAL_MAC_CTRL 0x000000b8 #define DUAL_MAC_CTRL_CH_MASK 0x00000003 #define DUAL_MAC_CTRL_ID 0x00000004 #define TG3PCI_PRODID_ASICREV 0x000000bc #define PROD_ID_ASIC_REV_MASK 0x0fffffff -/* 0xc0 --> 0x110 unused */ +/* 0xc0 --> 0xf4 unused */ + +#define TG3PCI_GEN2_PRODID_ASICREV 0x000000f4 +#define TG3PCI_GEN15_PRODID_ASICREV 0x000000fc +/* 0xf8 --> 0x200 unused */ #define TG3_CORR_ERR_STAT 0x00000110 #define TG3_CORR_ERR_STAT_CLEAR 0xffffffff @@ -236,7 +250,11 @@ #define MAILBOX_GENERAL_7 0x00000258 /* 64-bit */ #define MAILBOX_RELOAD_STAT 0x00000260 /* 64-bit */ #define MAILBOX_RCV_STD_PROD_IDX 0x00000268 /* 64-bit */ +#define TG3_RX_STD_PROD_IDX_REG (MAILBOX_RCV_STD_PROD_IDX + \ + TG3_64BIT_REG_LOW) #define MAILBOX_RCV_JUMBO_PROD_IDX 0x00000270 /* 64-bit */ +#define TG3_RX_JMB_PROD_IDX_REG (MAILBOX_RCV_JUMBO_PROD_IDX + \ + TG3_64BIT_REG_LOW) #define MAILBOX_RCV_MINI_PROD_IDX 0x00000278 /* 64-bit */ #define MAILBOX_RCVRET_CON_IDX_0 0x00000280 /* 64-bit */ #define MAILBOX_RCVRET_CON_IDX_1 0x00000288 /* 64-bit */ @@ -445,6 +463,12 @@ #define RX_MODE_PROMISC 0x00000100 #define RX_MODE_NO_CRC_CHECK 0x00000200 #define RX_MODE_KEEP_VLAN_TAG 0x00000400 +#define RX_MODE_RSS_IPV4_HASH_EN 0x00010000 +#define RX_MODE_RSS_TCP_IPV4_HASH_EN 0x00020000 +#define RX_MODE_RSS_IPV6_HASH_EN 0x00040000 +#define RX_MODE_RSS_TCP_IPV6_HASH_EN 0x00080000 +#define RX_MODE_RSS_ITBL_HASH_BITS_7 0x00700000 +#define RX_MODE_RSS_ENABLE 0x00800000 #define RX_MODE_IPV6_CSUM_ENABLE 0x01000000 #define MAC_RX_STATUS 0x0000046c #define RX_STATUS_REMOTE_TX_XOFFED 0x00000001 @@ -525,6 +549,10 @@ /* 0x598 --> 0x5a0 unused */ #define MAC_PHYCFG1 0x000005a0 #define MAC_PHYCFG1_RGMII_INT 0x00000001 +#define MAC_PHYCFG1_RXCLK_TO_MASK 0x00001ff0 +#define MAC_PHYCFG1_RXCLK_TIMEOUT 0x00001000 +#define MAC_PHYCFG1_TXCLK_TO_MASK 0x01ff0000 +#define MAC_PHYCFG1_TXCLK_TIMEOUT 0x01000000 #define MAC_PHYCFG1_RGMII_EXT_RX_DEC 0x02000000 #define MAC_PHYCFG1_RGMII_SND_STAT_EN 0x04000000 #define MAC_PHYCFG1_TXC_DRV 0x20000000 @@ -678,6 +706,7 @@ #define SG_DIG_PARTNER_FULL_DUPLEX 0x00020000 /* If !MRADV_CRC16_SELECT */ #define SG_DIG_PARTNER_NEXT_PAGE 0x00010000 /* If !MRADV_CRC16_SELECT */ #define SG_DIG_AUTONEG_STATE_MASK 0x00000ff0 +#define SG_DIG_IS_SERDES 0x00000100 #define SG_DIG_COMMA_DETECTOR 0x00000008 #define SG_DIG_MAC_ACK_STATUS 0x00000004 #define SG_DIG_AUTONEG_COMPLETE 0x00000002 @@ -685,7 +714,22 @@ /* 0x5b8 --> 0x600 unused */ #define MAC_TX_MAC_STATE_BASE 0x00000600 /* 16 bytes */ #define MAC_RX_MAC_STATE_BASE 0x00000610 /* 20 bytes */ -/* 0x624 --> 0x800 unused */ +/* 0x624 --> 0x670 unused */ + +#define MAC_RSS_INDIR_TBL_0 0x00000630 + +#define MAC_RSS_HASH_KEY_0 0x00000670 +#define MAC_RSS_HASH_KEY_1 0x00000674 +#define MAC_RSS_HASH_KEY_2 0x00000678 +#define MAC_RSS_HASH_KEY_3 0x0000067c +#define MAC_RSS_HASH_KEY_4 0x00000680 +#define MAC_RSS_HASH_KEY_5 0x00000684 +#define MAC_RSS_HASH_KEY_6 0x00000688 +#define MAC_RSS_HASH_KEY_7 0x0000068c +#define MAC_RSS_HASH_KEY_8 0x00000690 +#define MAC_RSS_HASH_KEY_9 0x00000694 +/* 0x698 --> 0x800 unused */ + #define MAC_TX_STATS_OCTETS 0x00000800 #define MAC_TX_STATS_RESV1 0x00000804 #define MAC_TX_STATS_COLLISIONS 0x00000808 @@ -817,6 +861,7 @@ #define SNDBDI_MODE_RESET 0x00000001 #define SNDBDI_MODE_ENABLE 0x00000002 #define SNDBDI_MODE_ATTN_ENABLE 0x00000004 +#define SNDBDI_MODE_MULTI_TXQ_EN 0x00000020 #define SNDBDI_STATUS 0x00001804 #define SNDBDI_STATUS_ERROR_ATTN 0x00000004 #define SNDBDI_IN_PROD_IDX_0 0x00001808 @@ -945,7 +990,11 @@ #define RCVBDI_MINI_THRESH 0x00002c14 #define RCVBDI_STD_THRESH 0x00002c18 #define RCVBDI_JUMBO_THRESH 0x00002c1c -/* 0x2c20 --> 0x3000 unused */ +/* 0x2c20 --> 0x2d00 unused */ + +#define STD_REPLENISH_LWM 0x00002d00 +#define JMB_REPLENISH_LWM 0x00002d04 +/* 0x2d08 --> 0x3000 unused */ /* Receive BD Completion Control Registers */ #define RCVCC_MODE 0x00003000 @@ -991,8 +1040,10 @@ #define TG3_CPMU_HST_ACC 0x0000361c #define CPMU_HST_ACC_MACCLK_MASK 0x001f0000 #define CPMU_HST_ACC_MACCLK_6_25 0x00130000 -/* 0x3620 --> 0x3630 unused */ +/* 0x3620 --> 0x362c unused */ +#define TG3_CPMU_STATUS 0x0000362c +#define TG3_CPMU_STATUS_PCIE_FUNC 0x20000000 #define TG3_CPMU_CLCK_STAT 0x00003630 #define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000 #define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000 @@ -1004,6 +1055,8 @@ #define CPMU_MUTEX_REQ_DRIVER 0x00001000 #define TG3_CPMU_MUTEX_GNT 0x00003660 #define CPMU_MUTEX_GNT_DRIVER 0x00001000 +#define TG3_CPMU_PHY_STRAP 0x00003664 +#define TG3_CPMU_PHY_STRAP_IS_SERDES 0x00000020 /* 0x3664 --> 0x3800 unused */ /* Mbuf cluster free registers */ @@ -1026,6 +1079,7 @@ #define HOSTCC_MODE_CLRTICK_TXBD 0x00000400 #define HOSTCC_MODE_NOINT_ON_NOW 0x00000800 #define HOSTCC_MODE_NOINT_ON_FORCE 0x00001000 +#define HOSTCC_MODE_COAL_VEC1_NOW 0x00002000 #define HOSTCC_STATUS 0x00003c04 #define HOSTCC_STATUS_ERROR_ATTN 0x00000004 #define HOSTCC_RXCOL_TICKS 0x00003c08 @@ -1111,7 +1165,16 @@ #define HOSTCC_SND_CON_IDX_13 0x00003cf4 #define HOSTCC_SND_CON_IDX_14 0x00003cf8 #define HOSTCC_SND_CON_IDX_15 0x00003cfc -/* 0x3d00 --> 0x4000 unused */ +#define HOSTCC_STATBLCK_RING1 0x00003d00 +/* 0x3d00 --> 0x3d80 unused */ + +#define HOSTCC_RXCOL_TICKS_VEC1 0x00003d80 +#define HOSTCC_TXCOL_TICKS_VEC1 0x00003d84 +#define HOSTCC_RXMAX_FRAMES_VEC1 0x00003d88 +#define HOSTCC_TXMAX_FRAMES_VEC1 0x00003d8c +#define HOSTCC_RXCOAL_MAXF_INT_VEC1 0x00003d90 +#define HOSTCC_TXCOAL_MAXF_INT_VEC1 0x00003d94 +/* 0x3d98 --> 0x4000 unused */ /* Memory arbiter control registers */ #define MEMARB_MODE 0x00004000 @@ -1143,14 +1206,18 @@ #define DEFAULT_MB_MACRX_LOW_WATER 0x00000020 #define DEFAULT_MB_MACRX_LOW_WATER_5705 0x00000010 #define DEFAULT_MB_MACRX_LOW_WATER_5906 0x00000004 +#define DEFAULT_MB_MACRX_LOW_WATER_57765 0x0000002a #define DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098 #define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b +#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765 0x0000007e #define BUFMGR_MB_HIGH_WATER 0x00004418 #define DEFAULT_MB_HIGH_WATER 0x00000060 #define DEFAULT_MB_HIGH_WATER_5705 0x00000060 #define DEFAULT_MB_HIGH_WATER_5906 0x00000010 +#define DEFAULT_MB_HIGH_WATER_57765 0x000000a0 #define DEFAULT_MB_HIGH_WATER_JUMBO 0x0000017c #define DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096 +#define DEFAULT_MB_HIGH_WATER_JUMBO_57765 0x000000ea #define BUFMGR_RX_MB_ALLOC_REQ 0x0000441c #define BUFMGR_MB_ALLOC_BIT 0x10000000 #define BUFMGR_RX_MB_ALLOC_RESP 0x00004420 @@ -1190,6 +1257,8 @@ #define RDMAC_MODE_MBUF_SBD_CRPT_ENAB 0x00002000 #define RDMAC_MODE_FIFO_SIZE_128 0x00020000 #define RDMAC_MODE_FIFO_LONG_BURST 0x00030000 +#define RDMAC_MODE_MULT_DMA_RD_DIS 0x01000000 +#define RDMAC_MODE_IPV6_LSO_EN 0x10000000 #define RDMAC_STATUS 0x00004804 #define RDMAC_STATUS_TGTABORT 0x00000004 #define RDMAC_STATUS_MSTABORT 0x00000008 @@ -1213,8 +1282,9 @@ #define WDMAC_MODE_FIFOURUN_ENAB 0x00000080 #define WDMAC_MODE_FIFOOREAD_ENAB 0x00000100 #define WDMAC_MODE_LNGREAD_ENAB 0x00000200 -#define WDMAC_MODE_RX_ACCEL 0x00000400 +#define WDMAC_MODE_RX_ACCEL 0x00000400 #define WDMAC_MODE_STATUS_TAG_FIX 0x20000000 +#define WDMAC_MODE_BURST_ALL_DATA 0xc0000000 #define WDMAC_STATUS 0x00004c04 #define WDMAC_STATUS_TGTABORT 0x00000004 #define WDMAC_STATUS_MSTABORT 0x00000008 @@ -1447,6 +1517,8 @@ #define MSGINT_MODE 0x00006000 #define MSGINT_MODE_RESET 0x00000001 #define MSGINT_MODE_ENABLE 0x00000002 +#define MSGINT_MODE_ONE_SHOT_DISABLE 0x00000020 +#define MSGINT_MODE_MULTIVEC_EN 0x00000080 #define MSGINT_STATUS 0x00006004 #define MSGINT_FIFO 0x00006008 /* 0x600c --> 0x6400 unused */ @@ -1642,6 +1714,25 @@ #define FLASH_57780VENDOR_ATMEL_AT45DB021B 0x03400002 #define FLASH_57780VENDOR_ATMEL_AT45DB041D 0x00400001 #define FLASH_57780VENDOR_ATMEL_AT45DB041B 0x03400001 +#define FLASH_5717VENDOR_ATMEL_EEPROM 0x02000001 +#define FLASH_5717VENDOR_MICRO_EEPROM 0x02000003 +#define FLASH_5717VENDOR_ATMEL_MDB011D 0x01000001 +#define FLASH_5717VENDOR_ATMEL_MDB021D 0x01000003 +#define FLASH_5717VENDOR_ST_M_M25PE10 0x02000000 +#define FLASH_5717VENDOR_ST_M_M25PE20 0x02000002 +#define FLASH_5717VENDOR_ST_M_M45PE10 0x00000001 +#define FLASH_5717VENDOR_ST_M_M45PE20 0x00000003 +#define FLASH_5717VENDOR_ATMEL_ADB011B 0x01400000 +#define FLASH_5717VENDOR_ATMEL_ADB021B 0x01400002 +#define FLASH_5717VENDOR_ATMEL_ADB011D 0x01400001 +#define FLASH_5717VENDOR_ATMEL_ADB021D 0x01400003 +#define FLASH_5717VENDOR_ST_A_M25PE10 0x02400000 +#define FLASH_5717VENDOR_ST_A_M25PE20 0x02400002 +#define FLASH_5717VENDOR_ST_A_M45PE10 0x02400001 +#define FLASH_5717VENDOR_ST_A_M45PE20 0x02400003 +#define FLASH_5717VENDOR_ATMEL_45USPT 0x03400000 +#define FLASH_5717VENDOR_ST_25USPT 0x03400002 +#define FLASH_5717VENDOR_ST_45USPT 0x03400001 #define NVRAM_CFG1_5752PAGE_SIZE_MASK 0x70000000 #define FLASH_5752PAGE_SIZE_256 0x00000000 #define FLASH_5752PAGE_SIZE_512 0x10000000 @@ -1910,10 +2001,34 @@ #define NIC_SRAM_MBUF_POOL_BASE5705 0x00010000 #define NIC_SRAM_MBUF_POOL_SIZE5705 0x0000e000 + /* Currently this is fixed. */ +#define TG3_PHY_PCIE_ADDR 0x00 #define PHY_ADDR 0x01 -/* Tigon3 specific PHY MII registers. */ + +/*** Tigon3 specific PHY PCIE registers. ***/ + +#define TG3_PCIEPHY_BLOCK_ADDR 0x1f +#define TG3_PCIEPHY_XGXS_BLK1 0x0801 +#define TG3_PCIEPHY_TXB_BLK 0x0861 +#define TG3_PCIEPHY_BLOCK_SHIFT 4 + +/* TG3_PCIEPHY_TXB_BLK */ +#define TG3_PCIEPHY_TX0CTRL1 0x15 +#define TG3_PCIEPHY_TX0CTRL1_TXOCM 0x0003 +#define TG3_PCIEPHY_TX0CTRL1_RDCTL 0x0008 +#define TG3_PCIEPHY_TX0CTRL1_TXCMV 0x0030 +#define TG3_PCIEPHY_TX0CTRL1_TKSEL 0x0040 +#define TG3_PCIEPHY_TX0CTRL1_NB_EN 0x0400 + +/* TG3_PCIEPHY_XGXS_BLK1 */ +#define TG3_PCIEPHY_PWRMGMT4 0x1a +#define TG3_PCIEPHY_PWRMGMT4_L1PLLPD_EN 0x0038 +#define TG3_PCIEPHY_PWRMGMT4_LOWPWR_EN 0x4000 + + +/*** Tigon3 specific PHY MII registers. ***/ #define TG3_BMCR_SPEED1000 0x0040 #define MII_TG3_CTRL 0x09 /* 1000-baseT control register */ @@ -1944,6 +2059,7 @@ #define MII_TG3_DSP_EXP8_REJ2MHz 0x0001 #define MII_TG3_DSP_EXP8_AEDW 0x0200 #define MII_TG3_DSP_EXP75 0x0f75 +#define MII_TG3_DSP_EXP75_SUP_CM_OSC 0x0001 #define MII_TG3_DSP_EXP96 0x0f96 #define MII_TG3_DSP_EXP97 0x0f97 @@ -2009,6 +2125,8 @@ #define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001 #define MII_TG3_MISC_SHDW_APD_ENABLE 0x0020 +#define MII_TG3_MISC_SHDW_RGMII_SEL 0x2c00 + #define MII_TG3_TEST1 0x1e #define MII_TG3_TEST1_TRIM_EN 0x0010 #define MII_TG3_TEST1_CRC_EN 0x8000 @@ -2021,6 +2139,9 @@ #define MII_TG3_FET_SHDW_MISCCTRL 0x10 #define MII_TG3_FET_SHDW_MISCCTRL_MDIX 0x4000 +#define MII_TG3_FET_SHDW_AUXMODE4 0x1a +#define MII_TG3_FET_SHDW_AUXMODE4_SBPD 0x0008 + #define MII_TG3_FET_SHDW_AUXSTAT2 0x1b #define MII_TG3_FET_SHDW_AUXSTAT2_APD 0x0020 @@ -2134,6 +2255,7 @@ struct tg3_tx_buffer_desc { #define TXD_FLAG_IP_CSUM 0x0002 #define TXD_FLAG_END 0x0004 #define TXD_FLAG_IP_FRAG 0x0008 +#define TXD_FLAG_JMB_PKT 0x0008 #define TXD_FLAG_IP_FRAG_END 0x0010 #define TXD_FLAG_VLAN 0x0040 #define TXD_FLAG_COAL_NOW 0x0080 @@ -2519,6 +2641,52 @@ struct tg3_ethtool_stats { u64 nic_tx_threshold_hit; }; +struct tg3_rx_prodring_set { + u32 rx_std_prod_idx; + u32 rx_std_cons_idx; + u32 rx_jmb_prod_idx; + u32 rx_jmb_cons_idx; + struct tg3_rx_buffer_desc *rx_std; + struct tg3_ext_rx_buffer_desc *rx_jmb; + struct ring_info *rx_std_buffers; + struct ring_info *rx_jmb_buffers; + dma_addr_t rx_std_mapping; + dma_addr_t rx_jmb_mapping; +}; + +#define TG3_IRQ_MAX_VECS 5 + +struct tg3_napi { + struct net_device *dummy_netdev; + struct tg3 *tp; + struct tg3_hw_status *hw_status; + + u32 last_tag; + u32 last_irq_tag; + u32 int_mbox; + u32 coal_now; + u32 tx_prod; + u32 tx_cons; + u32 tx_pending; + u32 prodmbox; + + u32 consmbox; + u32 rx_rcb_ptr; + u16 *rx_rcb_prod_idx; + struct tg3_rx_prodring_set *prodring; + + struct tg3_rx_buffer_desc *rx_rcb; + struct tg3_tx_buffer_desc *tx_ring; + struct tx_ring_info *tx_buffers; + + dma_addr_t status_mapping; + dma_addr_t rx_rcb_mapping; + dma_addr_t tx_desc_mapping; + + char irq_lbl[IFNAMSIZ]; + unsigned int irq_vec; +}; + struct tg3 { /* begin "general, frequently-used members" cacheline section */ @@ -2571,48 +2739,27 @@ struct tg3 { struct net_device *dev; struct pci_dev *pdev; - struct tg3_hw_status *hw_status; - dma_addr_t status_mapping; - u32 last_tag; - u32 msg_enable; /* begin "tx thread" cacheline section */ void (*write32_tx_mbox) (struct tg3 *, u32, u32); - u32 tx_prod; - u32 tx_cons; - u32 tx_pending; - struct tg3_tx_buffer_desc *tx_ring; - struct tx_ring_info *tx_buffers; - dma_addr_t tx_desc_mapping; + struct tg3_napi napi[TG3_IRQ_MAX_VECS]; /* begin "rx thread" cacheline section */ void (*write32_rx_mbox) (struct tg3 *, u32, u32); - u32 rx_rcb_ptr; - u32 rx_std_ptr; - u32 rx_jumbo_ptr; u32 rx_pending; u32 rx_jumbo_pending; + u32 rx_std_max_post; + u32 rx_pkt_map_sz; #if TG3_VLAN_TAG_USED struct vlan_group *vlgrp; #endif - struct tg3_rx_buffer_desc *rx_std; - struct ring_info *rx_std_buffers; - dma_addr_t rx_std_mapping; - u32 rx_std_max_post; - - struct tg3_rx_buffer_desc *rx_jumbo; - struct ring_info *rx_jumbo_buffers; - dma_addr_t rx_jumbo_mapping; + struct tg3_rx_prodring_set prodring[TG3_IRQ_MAX_VECS - 1]; - struct tg3_rx_buffer_desc *rx_rcb; - dma_addr_t rx_rcb_mapping; - - u32 rx_pkt_buf_sz; /* begin "everything else" cacheline(s) section */ struct net_device_stats net_stats; @@ -2644,6 +2791,10 @@ struct tg3 { #define TG3_FLAG_EEPROM_WRITE_PROT 0x00001000 #define TG3_FLAG_NVRAM 0x00002000 #define TG3_FLAG_NVRAM_BUFFERED 0x00004000 +#define TG3_FLAG_SUPPORT_MSI 0x00008000 +#define TG3_FLAG_SUPPORT_MSIX 0x00010000 +#define TG3_FLAG_SUPPORT_MSI_OR_MSIX (TG3_FLAG_SUPPORT_MSI | \ + TG3_FLAG_SUPPORT_MSIX) #define TG3_FLAG_PCIX_MODE 0x00020000 #define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 #define TG3_FLAG_PCI_32BIT 0x00080000 @@ -2656,7 +2807,7 @@ struct tg3 { #define TG3_FLAG_CPMU_PRESENT 0x04000000 #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 -#define TG3_FLAG_SUPPORT_MSI 0x20000000 +#define TG3_FLAG_JUMBO_CAPABLE 0x20000000 #define TG3_FLAG_CHIP_RESETTING 0x40000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000 u32 tg3_flags2; @@ -2680,9 +2831,10 @@ struct tg3 { #define TG3_FLG2_SERDES_PREEMPHASIS 0x00020000 #define TG3_FLG2_5705_PLUS 0x00040000 #define TG3_FLG2_5750_PLUS 0x00080000 -#define TG3_FLG2_PROTECTED_NVRAM 0x00100000 #define TG3_FLG2_USING_MSI 0x00200000 -#define TG3_FLG2_JUMBO_CAPABLE 0x00400000 +#define TG3_FLG2_USING_MSIX 0x00400000 +#define TG3_FLG2_USING_MSI_OR_MSIX (TG3_FLG2_USING_MSI | \ + TG3_FLG2_USING_MSIX) #define TG3_FLG2_MII_SERDES 0x00800000 #define TG3_FLG2_ANY_SERDES (TG3_FLG2_PHY_SERDES | \ TG3_FLG2_MII_SERDES) @@ -2698,6 +2850,7 @@ struct tg3 { u32 tg3_flags3; #define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001 #define TG3_FLG3_ENABLE_APE 0x00000002 +#define TG3_FLG3_PROTECTED_NVRAM 0x00000004 #define TG3_FLG3_5701_DMA_BUG 0x00000008 #define TG3_FLG3_USE_PHYLIB 0x00000010 #define TG3_FLG3_MDIOBUS_INITED 0x00000020 @@ -2741,8 +2894,13 @@ struct tg3 { #define TG3_FLG3_PHY_ENABLE_APD 0x00001000 #define TG3_FLG3_5755_PLUS 0x00002000 #define TG3_FLG3_NO_NVRAM 0x00004000 -#define TG3_FLG3_PHY_IS_FET 0x00007fff -#define TG3_FLG3_TOGGLE_10_100_L1PLLPD 0x00008000 +#define TG3_FLG3_PHY_IS_FET 0x00008000 +#define TG3_FLG3_ENABLE_RSS 0x00020000 +#define TG3_FLG3_ENABLE_TSS 0x00040000 +#define TG3_FLG3_4G_DMA_BNDRY_BUG 0x00080000 +#define TG3_FLG3_40BIT_DMA_LIMIT_BUG 0x00100000 +#define TG3_FLG3_SHORT_DMA_BUG 0x00200000 +#define TG3_FLG3_USE_JUMBO_BDFLAG 0x00400000 struct timer_list timer; u16 timer_counter; @@ -2786,6 +2944,8 @@ struct tg3 { int pcie_cap; }; + u8 phy_addr; + /* PHY info */ u32 phy_id; #define PHY_ID_MASK 0xfffffff0 @@ -2806,6 +2966,9 @@ struct tg3 { #define PHY_ID_BCM5756 0xbc050ed0 #define PHY_ID_BCM5784 0xbc050fa0 #define PHY_ID_BCM5761 0xbc050fd0 +#define PHY_ID_BCM5718C 0x5c0d8a00 +#define PHY_ID_BCM5718S 0xbc050ff0 +#define PHY_ID_BCM57765 0x5c0d8a40 #define PHY_ID_BCM5906 0xdc00ac40 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_BCM57780 0x5c0d8990 @@ -2843,7 +3006,9 @@ struct tg3 { (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \ (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM5761 || \ (X) == PHY_ID_BCM8002 || (X) == PHY_ID_BCMAC131 || \ - (X) == PHY_ID_BCM50610 || (X) == PHY_ID_BCM50610M) + (X) == PHY_ID_BCM50610 || (X) == PHY_ID_BCM50610M || \ + (X) == PHY_ID_BCM5718C || (X) == PHY_ID_BCM5718S || \ + (X) == PHY_ID_BCM57780 || (X) == PHY_ID_BCM57765) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; @@ -2883,6 +3048,9 @@ struct tg3 { #define SST_25VF0X0_PAGE_SIZE 4098 + unsigned int irq_max; + unsigned int irq_cnt; + struct ethtool_coalesce coal; }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 742a3f0..f251607 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1988,7 +1988,6 @@ #define PCI_DEVICE_ID_TIGON3_5787M 0x1693 #define PCI_DEVICE_ID_TIGON3_5782 0x1696 #define PCI_DEVICE_ID_TIGON3_5784 0x1698 -#define PCI_DEVICE_ID_TIGON3_5785 0x1699 #define PCI_DEVICE_ID_TIGON3_5786 0x169a #define PCI_DEVICE_ID_TIGON3_5787 0x169b #define PCI_DEVICE_ID_TIGON3_5788 0x169c