X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Ftg3.c;h=327836b1014e76fc55a8ec7e3c87d20b5070e808;hb=7359bbfd85751de23079cc26cd248635aebe840b;hp=e03d1ae50c3e40d1f0dc69a5995ba93742497559;hpb=30ca3e376e82cc44488b1d377adfb10b5818548e;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e03d1ae..327836b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -15,7 +15,6 @@ * notice is accompanying it. */ -#include #include #include @@ -69,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.52" -#define DRV_MODULE_RELDATE "Mar 06, 2006" +#define DRV_MODULE_VERSION "3.66" +#define DRV_MODULE_RELDATE "September 23, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -124,9 +123,6 @@ TG3_RX_RCB_RING_SIZE(tp)) #define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \ TG3_TX_RING_SIZE) -#define TX_BUFFS_AVAIL(TP) \ - ((TP)->tx_pending - \ - (((TP)->tx_prod - (TP)->tx_cons) & (TG3_TX_RING_SIZE - 1))) #define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) #define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64) @@ -153,116 +149,71 @@ module_param(tg3_debug, int, 0); MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); static struct pci_device_id tg3_pci_tbl[] = { - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { 0, } + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)}, + {PCI_DEVICE(PCI_VENDOR_ID_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)}, + {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001)}, + {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003)}, + {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100)}, + {PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3)}, + {} }; MODULE_DEVICE_TABLE(pci, tg3_pci_tbl); -static struct { +static const struct { const char string[ETH_GSTRING_LEN]; } ethtool_stats_keys[TG3_NUM_STATS] = { { "rx_octets" }, @@ -343,7 +294,7 @@ static struct { { "nic_tx_threshold_hit" } }; -static struct { +static const struct { const char string[ETH_GSTRING_LEN]; } ethtool_test_keys[TG3_NUM_TEST] = { { "nvram test (online) " }, @@ -361,7 +312,7 @@ static void tg3_write32(struct tg3 *tp, u32 off, u32 val) static u32 tg3_read32(struct tg3 *tp, u32 off) { - return (readl(tp->regs + off)); + return (readl(tp->regs + off)); } static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) @@ -477,6 +428,16 @@ static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) readl(mbox); } +static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off) +{ + return (readl(tp->regs + off + GRCMBOX_BASE)); +} + +static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val) +{ + writel(val, tp->regs + off + GRCMBOX_BASE); +} + #define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val) #define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val)) #define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val) @@ -492,34 +453,51 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) && + (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) + return; + spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - spin_unlock_irqrestore(&tp->indirect_lock, flags); -} + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + tw32_f(TG3PCI_MEM_WIN_DATA, val); -static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val) -{ - /* If no workaround is needed, write to mem space directly */ - if (tp->write32 != tg3_write_indirect_reg32) - tw32(NIC_SRAM_WIN_BASE + off, val); - else - tg3_write_mem(tp, off, val); + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } + spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) { unsigned long flags; + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) && + (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) { + *val = 0; + return; + } + spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + *val = tr32(TG3PCI_MEM_WIN_DATA); + + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } spin_unlock_irqrestore(&tp->indirect_lock, flags); } @@ -535,6 +513,9 @@ 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)); } static void tg3_enable_ints(struct tg3 *tp) @@ -575,7 +556,7 @@ static inline unsigned int tg3_has_work(struct tg3 *tp) /* tg3_restart_ints * similar to tg3_enable_ints, but it accurately determines whether there * is new work pending and can return without flushing the PIO write - * which reenables interrupts + * which reenables interrupts */ static void tg3_restart_ints(struct tg3 *tp) { @@ -664,7 +645,7 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & MI_COM_REG_ADDR_MASK); frame_val |= (MI_COM_CMD_READ | MI_COM_START); - + tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; @@ -700,6 +681,10 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) unsigned int loops; int ret; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 && + (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL)) + return 0; + if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); @@ -712,7 +697,7 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) MI_COM_REG_ADDR_MASK); frame_val |= (val & MI_COM_DATA_MASK); frame_val |= (MI_COM_CMD_WRITE | MI_COM_START); - + tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; @@ -963,6 +948,8 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) return err; } +static void tg3_link_report(struct tg3 *); + /* This will reset the tigon3 PHY if there is no valid * link unless the FORCE argument is non-zero. */ @@ -976,6 +963,11 @@ static int tg3_phy_reset(struct tg3 *tp) if (err != 0) return -EBUSY; + if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) { + netif_carrier_off(tp->dev); + tg3_link_report(tp); + } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { @@ -1012,6 +1004,12 @@ out: tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); } + else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) { + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); + 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) { @@ -1037,6 +1035,24 @@ out: phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 phy_reg; + + /* adjust output voltage */ + tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12); + + if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) { + u32 phy_reg2; + + tg3_writephy(tp, MII_TG3_EPHY_TEST, + phy_reg | MII_TG3_EPHY_SHADOW_EN); + /* Enable auto-MDIX */ + if (!tg3_readphy(tp, 0x10, &phy_reg2)) + tg3_writephy(tp, 0x10, phy_reg2 | 0x4000); + tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg); + } + } + tg3_phy_set_wirespeed(tp); return 0; } @@ -1148,6 +1164,28 @@ static int tg3_halt_cpu(struct tg3 *, u32); static int tg3_nvram_lock(struct tg3 *); static void tg3_nvram_unlock(struct tg3 *); +static void tg3_power_down_phy(struct tg3 *tp) +{ + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + return; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) { + tg3_writephy(tp, MII_TG3_EXT_CTRL, + MII_TG3_EXT_CTRL_FORCE_LED_OFF); + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); + } + + /* The PHY should not be powered down on some chips because + * of bugs. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 && + (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) + return; + tg3_writephy(tp, MII_BMCR, BMCR_PDOWN); +} + static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) { u32 misc_host_ctrl; @@ -1219,7 +1257,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) tg3_setup_phy(tp, 0); } - if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 val; + + val = tr32(GRC_VCPU_EXT_CTRL); + tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL); + } else if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { int i; u32 val; @@ -1243,7 +1286,10 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); udelay(40); - mac_mode = MAC_MODE_PORT_MODE_MII; + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + mac_mode = MAC_MODE_PORT_MODE_GMII; + else + mac_mode = MAC_MODE_PORT_MODE_MII; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 || !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB)) @@ -1321,16 +1367,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) && - !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { - /* Turn off the PHY */ - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { - tg3_writephy(tp, MII_TG3_EXT_CTRL, - MII_TG3_EXT_CTRL_FORCE_LED_OFF); - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) - tg3_writephy(tp, MII_BMCR, BMCR_PDOWN); - } - } + !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) + tg3_power_down_phy(tp); tg3_frob_aux_power(tp); @@ -1351,12 +1389,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } } + tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); + /* Finally, set the new power state. */ pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); udelay(100); /* Delay after power state change */ - tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); - return 0; } @@ -1443,7 +1481,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv if (old_rx_mode != tp->rx_mode) { tw32_f(MAC_RX_MODE, tp->rx_mode); } - + if (new_tg3_flags & TG3_FLAG_TX_PAUSE) tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; else @@ -1488,6 +1526,13 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 break; default: + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 : + SPEED_10; + *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL : + DUPLEX_HALF; + break; + } *speed = SPEED_INVALID; *duplex = DUPLEX_INVALID; break; @@ -1770,7 +1815,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG); - else + else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) tg3_writephy(tp, MII_TG3_IMASK, ~0); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || @@ -2427,24 +2472,27 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) expected_sg_dig_ctrl |= (1 << 12); if (sg_dig_ctrl != expected_sg_dig_ctrl) { + if ((tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) && + tp->serdes_counter && + ((mac_status & (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_RCVD_CFG)) == + MAC_STATUS_PCS_SYNCED)) { + tp->serdes_counter--; + current_link_up = 1; + goto out; + } +restart_autoneg: if (workaround) tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000); tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30)); udelay(5); tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl); - tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; + tp->serdes_counter = SERDES_AN_TIMEOUT_5704S; + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; } else if (mac_status & (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DET)) { - int i; - - /* Giver time to negotiate (~200ms) */ - for (i = 0; i < 40000; i++) { - sg_dig_status = tr32(SG_DIG_STATUS); - if (sg_dig_status & (0x3)) - break; - udelay(5); - } + sg_dig_status = tr32(SG_DIG_STATUS); mac_status = tr32(MAC_STATUS); if ((sg_dig_status & (1 << 1)) && @@ -2460,10 +2508,11 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) tg3_setup_flow_control(tp, local_adv, remote_adv); current_link_up = 1; - tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + tp->serdes_counter = 0; + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; } else if (!(sg_dig_status & (1 << 1))) { - if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) - tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + if (tp->serdes_counter) + tp->serdes_counter--; else { if (workaround) { u32 val = serdes_cfg; @@ -2487,9 +2536,17 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) !(mac_status & MAC_STATUS_RCVD_CFG)) { tg3_setup_flow_control(tp, 0, 0); current_link_up = 1; - } + tp->tg3_flags2 |= + TG3_FLG2_PARALLEL_DETECT; + tp->serdes_counter = + SERDES_PARALLEL_DET_TIMEOUT; + } else + goto restart_autoneg; } } + } else { + tp->serdes_counter = SERDES_AN_TIMEOUT_5704S; + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; } out: @@ -2508,7 +2565,7 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) if (tp->link_config.autoneg == AUTONEG_ENABLE) { u32 flags; int i; - + if (fiber_autoneg(tp, &flags)) { u32 local_adv, remote_adv; @@ -2620,14 +2677,16 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) MAC_STATUS_CFG_CHANGED)); udelay(5); if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) + MAC_STATUS_CFG_CHANGED | + MAC_STATUS_LNKSTATE_CHANGED)) == 0) break; } mac_status = tr32(MAC_STATUS); if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) { current_link_up = 0; - if (tp->link_config.autoneg == AUTONEG_ENABLE) { + if (tp->link_config.autoneg == AUTONEG_ENABLE && + tp->serdes_counter == 0) { tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS)); udelay(1); @@ -2732,7 +2791,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) tg3_writephy(tp, MII_BMCR, bmcr); tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); - tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; + tp->serdes_counter = SERDES_AN_TIMEOUT_5714S; tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; return err; @@ -2837,9 +2896,9 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) static void tg3_serdes_parallel_detect(struct tg3 *tp) { - if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) { + if (tp->serdes_counter) { /* Give autoneg time to complete. */ - tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + tp->serdes_counter--; return; } if (!netif_carrier_ok(tp->dev) && @@ -2929,6 +2988,34 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) return err; } +/* This is called whenever we suspect that the system chipset is re- + * ordering the sequence of MMIO to the tx send mailbox. The symptom + * is bogus tx completions. We try to recover by setting the + * TG3_FLAG_MBOX_WRITE_REORDER flag and resetting the chip later + * in the workqueue. + */ +static void tg3_tx_recover(struct tg3 *tp) +{ + BUG_ON((tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) || + tp->write32_tx_mbox == tg3_write_indirect_mbox); + + printk(KERN_WARNING PFX "%s: The system may be re-ordering memory-" + "mapped I/O cycles to the network device, attempting to " + "recover. Please report the problem to the driver maintainer " + "and include system chipset information.\n", tp->dev->name); + + spin_lock(&tp->lock); + tp->tg3_flags |= TG3_FLAG_TX_RECOVERY_PENDING; + spin_unlock(&tp->lock); +} + +static inline u32 tg3_tx_avail(struct tg3 *tp) +{ + smp_mb(); + return (tp->tx_pending - + ((tp->tx_prod - tp->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. @@ -2941,10 +3028,12 @@ static void tg3_tx(struct tg3 *tp) while (sw_idx != hw_idx) { struct tx_ring_info *ri = &tp->tx_buffers[sw_idx]; struct sk_buff *skb = ri->skb; - int i; + int i, tx_bug = 0; - if (unlikely(skb == NULL)) - BUG(); + if (unlikely(skb == NULL)) { + tg3_tx_recover(tp); + return; + } pci_unmap_single(tp->pdev, pci_unmap_addr(ri, mapping), @@ -2956,12 +3045,9 @@ static void tg3_tx(struct tg3 *tp) sw_idx = NEXT_TX(sw_idx); for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - if (unlikely(sw_idx == hw_idx)) - BUG(); - ri = &tp->tx_buffers[sw_idx]; - if (unlikely(ri->skb != NULL)) - BUG(); + if (unlikely(ri->skb != NULL || sw_idx == hw_idx)) + tx_bug = 1; pci_unmap_page(tp->pdev, pci_unmap_addr(ri, mapping), @@ -2972,16 +3058,29 @@ static void tg3_tx(struct tg3 *tp) } dev_kfree_skb(skb); + + if (unlikely(tx_bug)) { + tg3_tx_recover(tp); + return; + } } tp->tx_cons = sw_idx; - if (unlikely(netif_queue_stopped(tp->dev))) { - spin_lock(&tp->tx_lock); + /* Need to make the tx_cons update visible to tg3_start_xmit() + * before checking for netif_queue_stopped(). Without the + * memory barrier, there is a small possibility that tg3_start_xmit() + * will miss it and cause the queue to be stopped forever. + */ + smp_mb(); + + if (unlikely(netif_queue_stopped(tp->dev) && + (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) { + netif_tx_lock(tp->dev); if (netif_queue_stopped(tp->dev) && - (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)) + (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)) netif_wake_queue(tp->dev); - spin_unlock(&tp->tx_lock); + netif_tx_unlock(tp->dev); } } @@ -3035,11 +3134,10 @@ 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 = dev_alloc_skb(skb_size); + skb = netdev_alloc_skb(tp->dev, skb_size); if (skb == NULL) return -ENOMEM; - skb->dev = tp->dev; skb_reserve(skb, tp->rx_offset); mapping = pci_map_single(tp->pdev, skb->data, @@ -3132,7 +3230,7 @@ static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag) */ static int tg3_rx(struct tg3 *tp, int budget) { - u32 work_mask; + u32 work_mask, rx_std_posted = 0; u32 sw_idx = tp->rx_rcb_ptr; u16 hw_idx; int received; @@ -3159,6 +3257,7 @@ static int tg3_rx(struct tg3 *tp, int budget) mapping); skb = tp->rx_std_buffers[desc_idx].skb; post_ptr = &tp->rx_std_ptr; + rx_std_posted++; } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx], mapping); @@ -3184,7 +3283,7 @@ static int tg3_rx(struct tg3 *tp, int budget) len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */ - if (len > RX_COPY_THRESHOLD + if (len > RX_COPY_THRESHOLD && tp->rx_offset == 2 /* rx_offset != 2 iff this is a 5701 card running * in PCI-X mode [see tg3_get_invariants()] */ @@ -3207,11 +3306,10 @@ static int tg3_rx(struct tg3 *tp, int budget) tg3_recycle_rx(tp, opaque_key, desc_idx, *post_ptr); - copy_skb = dev_alloc_skb(len + 2); + copy_skb = netdev_alloc_skb(tp->dev, len + 2); if (copy_skb == NULL) goto drop_it_no_recycle; - copy_skb->dev = tp->dev; skb_reserve(copy_skb, 2); skb_put(copy_skb, len); pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); @@ -3246,6 +3344,15 @@ static int tg3_rx(struct tg3 *tp, int budget) 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); + work_mask &= ~RXD_OPAQUE_RING_STD; + rx_std_posted = 0; + } next_pkt_nopost: sw_idx++; sw_idx %= TG3_RX_RCB_RING_SIZE(tp); @@ -3299,6 +3406,11 @@ 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 (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) { + netif_rx_complete(netdev); + schedule_work(&tp->reset_task); + return 0; + } } /* run RX thread, within the bounds set by NAPI. @@ -3359,19 +3471,17 @@ static inline void tg3_full_lock(struct tg3 *tp, int irq_sync) if (irq_sync) tg3_irq_quiesce(tp); spin_lock_bh(&tp->lock); - spin_lock(&tp->tx_lock); } static inline void tg3_full_unlock(struct tg3 *tp) { - spin_unlock(&tp->tx_lock); spin_unlock_bh(&tp->lock); } /* One-shot MSI handler - Chip automatically disables interrupt * after sending MSI so driver doesn't have to do it. */ -static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t tg3_msi_1shot(int irq, void *dev_id) { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3389,7 +3499,7 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs) * flush status block and interrupt mailbox. PCI ordering rules * guarantee that MSI will arrive after the status block. */ -static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t tg3_msi(int irq, void *dev_id) { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3410,7 +3520,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) return IRQ_RETVAL(1); } -static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t tg3_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3453,7 +3563,7 @@ out: return IRQ_RETVAL(handled); } -static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3496,8 +3606,7 @@ out: } /* ISR for interrupt test */ -static irqreturn_t tg3_test_isr(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t tg3_test_isr(int irq, void *dev_id) { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3505,22 +3614,43 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, if ((sblk->status & SD_STATUS_UPDATED) || !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000001); + tg3_disable_ints(tp); return IRQ_RETVAL(1); } return IRQ_RETVAL(0); } -static int tg3_init_hw(struct tg3 *); +static int tg3_init_hw(struct tg3 *, int); static int tg3_halt(struct tg3 *, int, int); +/* Restart hardware after configuration changes, self-test, etc. + * Invoked with tp->lock held. + */ +static int tg3_restart_hw(struct tg3 *tp, int reset_phy) +{ + int err; + + err = tg3_init_hw(tp, reset_phy); + if (err) { + printk(KERN_ERR PFX "%s: Failed to re-initialize device, " + "aborting.\n", tp->dev->name); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); + tg3_full_unlock(tp); + del_timer_sync(&tp->timer); + tp->irq_sync = 0; + netif_poll_enable(tp->dev); + dev_close(tp->dev); + tg3_full_lock(tp, 0); + } + return err; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void tg3_poll_controller(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); - tg3_interrupt(tp->pdev->irq, dev, NULL); + tg3_interrupt(tp->pdev->irq, dev); } #endif @@ -3547,14 +3677,23 @@ static void tg3_reset_task(void *_data) restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER; tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; + if (tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING) { + tp->write32_tx_mbox = tg3_write32_tx_mbox; + tp->write32_rx_mbox = tg3_write_flush_reg32; + tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; + tp->tg3_flags &= ~TG3_FLAG_TX_RECOVERY_PENDING; + } + tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); - tg3_init_hw(tp); + if (tg3_init_hw(tp, 1)) + goto out; tg3_netif_start(tp); if (restart_timer) mod_timer(&tp->timer, jiffies + 1); +out: tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; tg3_full_unlock(tp); @@ -3584,7 +3723,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping, int len) { #if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64) - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) return (((u64) mapping + len) > DMA_40BIT_MASK); return 0; #else @@ -3686,15 +3825,12 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); - /* No BH disabling for tx_lock here. We are running in BH disabled - * context and TX reclaim runs via tp->poll inside of a software + /* We are running in BH disabled context with netif_tx_lock + * and TX reclaim runs via tp->poll inside of a software * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (!spin_trylock(&tp->tx_lock)) - return NETDEV_TX_LOCKED; - - if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { + if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -3702,7 +3838,6 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " "queue awake!\n", dev->name); } - spin_unlock(&tp->tx_lock); return NETDEV_TX_BUSY; } @@ -3711,7 +3846,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) #if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { + (mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && @@ -3720,24 +3855,30 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) goto out_unlock; } - tcp_opt_len = ((skb->h.th->doff - 5) * 4); - ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + mss |= (skb_headlen(skb) - ETH_HLEN) << 9; + else { + tcp_opt_len = ((skb->h.th->doff - 5) * 4); + ip_tcp_len = (skb->nh.iph->ihl * 4) + + sizeof(struct tcphdr); + + skb->nh.iph->check = 0; + skb->nh.iph->tot_len = htons(mss + ip_tcp_len + + tcp_opt_len); + mss |= (ip_tcp_len + tcp_opt_len) << 9; + } base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); - skb->nh.iph->check = 0; - skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); - skb->h.th->check = 0; - mss |= (ip_tcp_len + tcp_opt_len) << 9; } - else if (skb->ip_summed == CHECKSUM_HW) + else if (skb->ip_summed == CHECKSUM_PARTIAL) base_flags |= TXD_FLAG_TCPUDP_CSUM; #else mss = 0; - if (skb->ip_summed == CHECKSUM_HW) + if (skb->ip_summed == CHECKSUM_PARTIAL) base_flags |= TXD_FLAG_TCPUDP_CSUM; #endif #if TG3_VLAN_TAG_USED @@ -3785,21 +3926,54 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; - if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) { + if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { netif_stop_queue(dev); - if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) + if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) netif_wake_queue(tp->dev); } out_unlock: mmiowb(); - spin_unlock(&tp->tx_lock); dev->trans_start = jiffies; return NETDEV_TX_OK; } +#if TG3_TSO_SUPPORT != 0 +static int tg3_start_xmit_dma_bug(struct sk_buff *, struct net_device *); + +/* Use GSO to workaround a rare TSO bug that may be triggered when the + * TSO header is greater than 80 bytes. + */ +static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) +{ + struct sk_buff *segs, *nskb; + + /* Estimate the number of fragments in the worst case */ + if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) { + netif_stop_queue(tp->dev); + return NETDEV_TX_BUSY; + } + + segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO); + if (unlikely(IS_ERR(segs))) + goto tg3_tso_bug_end; + + do { + nskb = segs; + segs = segs->next; + nskb->next = NULL; + tg3_start_xmit_dma_bug(nskb, tp->dev); + } while (segs); + +tg3_tso_bug_end: + dev_kfree_skb(skb); + + return NETDEV_TX_OK; +} +#endif + /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and * support TG3_FLG2_HW_TSO_1 or firmware TSO only. */ @@ -3812,15 +3986,12 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); - /* No BH disabling for tx_lock here. We are running in BH disabled - * context and TX reclaim runs via tp->poll inside of a software + /* We are running in BH disabled context with netif_tx_lock + * and TX reclaim runs via tp->poll inside of a software * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (!spin_trylock(&tp->tx_lock)) - return NETDEV_TX_LOCKED; - - if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { + if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -3828,19 +3999,18 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " "queue awake!\n", dev->name); } - spin_unlock(&tp->tx_lock); return NETDEV_TX_BUSY; } entry = tp->tx_prod; base_flags = 0; - if (skb->ip_summed == CHECKSUM_HW) + if (skb->ip_summed == CHECKSUM_PARTIAL) base_flags |= TXD_FLAG_TCPUDP_CSUM; #if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { - int tcp_opt_len, ip_tcp_len; + (mss = skb_shinfo(skb)->gso_size) != 0) { + int tcp_opt_len, ip_tcp_len, hdr_len; if (skb_header_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { @@ -3851,11 +4021,16 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) tcp_opt_len = ((skb->h.th->doff - 5) * 4); ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); + hdr_len = ip_tcp_len + tcp_opt_len; + if (unlikely((ETH_HLEN + hdr_len) > 80) && + (tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG)) + return (tg3_tso_bug(tp, skb)); + base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); skb->nh.iph->check = 0; - skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); + skb->nh.iph->tot_len = htons(mss + hdr_len); if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { skb->h.th->check = 0; base_flags &= ~TXD_FLAG_TCPUDP_CSUM; @@ -3966,15 +4141,14 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; - if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) { + if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { netif_stop_queue(dev); - if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) + if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) netif_wake_queue(tp->dev); } out_unlock: mmiowb(); - spin_unlock(&tp->tx_lock); dev->trans_start = jiffies; @@ -4003,6 +4177,7 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, static int tg3_change_mtu(struct net_device *dev, int new_mtu) { struct tg3 *tp = netdev_priv(dev); + int err; if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) return -EINVAL; @@ -4023,13 +4198,14 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) tg3_set_mtu(dev, tp, new_mtu); - tg3_init_hw(tp); + err = tg3_restart_hw(tp, 0); - tg3_netif_start(tp); + if (!err) + tg3_netif_start(tp); tg3_full_unlock(tp); - return 0; + return err; } /* Free up pending packets in all rx/tx rings. @@ -4111,7 +4287,7 @@ 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 void tg3_init_rings(struct tg3 *tp) +static int tg3_init_rings(struct tg3 *tp) { u32 i; @@ -4160,18 +4336,38 @@ static void tg3_init_rings(struct tg3 *tp) /* 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, RXD_OPAQUE_RING_STD, -1, 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; + tp->rx_pending = i; break; + } } if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { for (i = 0; i < tp->rx_jumbo_pending; i++) { if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_JUMBO, - -1, i) < 0) + -1, 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; + } + tp->rx_jumbo_pending = i; break; + } } } + return 0; } /* @@ -4453,9 +4649,8 @@ static void tg3_disable_nvram_access(struct tg3 *tp) /* tp->lock is held. */ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) { - if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) - tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, - NIC_SRAM_FIRMWARE_MBOX_MAGIC1); + tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, + NIC_SRAM_FIRMWARE_MBOX_MAGIC1); if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) { switch (kind) { @@ -4527,6 +4722,44 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind) } } +static int tg3_poll_fw(struct tg3 *tp) +{ + int i; + u32 val; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + for (i = 0; i < 400; i++) { + if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE) + return 0; + udelay(10); + } + return -ENODEV; + } + + /* Wait for firmware initialization to complete. */ + for (i = 0; i < 100000; i++) { + tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); + if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) + break; + udelay(10); + } + + /* Chip might not be fitted with firmware. Some Sun onboard + * parts are configured like that. So don't signal the timeout + * of the above loop as an error, but do report the lack of + * running firmware once. + */ + if (i >= 100000 && + !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) { + tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED; + + printk(KERN_INFO PFX "%s: No firmware running.\n", + tp->dev->name); + } + + return 0; +} + static void tg3_stop_fw(struct tg3 *); /* tp->lock is held. */ @@ -4534,17 +4767,17 @@ static int tg3_chip_reset(struct tg3 *tp) { u32 val; void (*write_op)(struct tg3 *, u32, u32); - int i; + int err; - if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) { - tg3_nvram_lock(tp); - /* No matching tg3_nvram_unlock() after this because - * chip reset below will undo the nvram lock. - */ - tp->nvram_lock_cnt = 0; - } + tg3_nvram_lock(tp); + + /* No matching tg3_nvram_unlock() after this because + * chip reset below will undo the nvram lock. + */ + tp->nvram_lock_cnt = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tw32(GRC_FASTBOOT_PC, 0); @@ -4571,6 +4804,12 @@ static int tg3_chip_reset(struct tg3 *tp) } } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + tw32(VCPU_STATUS, tr32(VCPU_STATUS) | VCPU_STATUS_DRV_RESET); + tw32(GRC_VCPU_EXT_CTRL, + tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU); + } + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) val |= GRC_MISC_CFG_KEEP_GPHY_POWER; tw32(GRC_MISC_CFG, val); @@ -4694,21 +4933,9 @@ static int tg3_chip_reset(struct tg3 *tp) tw32_f(MAC_MODE, 0); udelay(40); - if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) { - /* Wait for firmware initialization to complete. */ - for (i = 0; i < 100000; i++) { - tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); - if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) - break; - udelay(10); - } - if (i >= 100000) { - printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, " - "firmware will not restart magic=%08x\n", - tp->dev->name, val); - return -ENODEV; - } - } + err = tg3_poll_fw(tp); + if (err) + return err; if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) { @@ -4792,7 +5019,7 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent) #define TG3_FW_BSS_ADDR 0x08000a70 #define TG3_FW_BSS_LEN 0x10 -static u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { +static const u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000, 0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034, @@ -4886,7 +5113,7 @@ static u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { 0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000 }; -static u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = { +static const u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = { 0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, @@ -4911,10 +5138,15 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) { int i; - if (offset == TX_CPU_BASE && - (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) - BUG(); + BUG_ON(offset == TX_CPU_BASE && + (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 val = tr32(GRC_VCPU_EXT_CTRL); + + tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU); + return 0; + } if (offset == RX_CPU_BASE) { for (i = 0; i < 10000; i++) { tw32(offset + CPU_STATE, 0xffffffff); @@ -4952,13 +5184,13 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) struct fw_info { unsigned int text_base; unsigned int text_len; - u32 *text_data; + const u32 *text_data; unsigned int rodata_base; unsigned int rodata_len; - u32 *rodata_data; + const u32 *rodata_data; unsigned int data_base; unsigned int data_len; - u32 *data_data; + const u32 *data_data; }; /* tp->lock is held. */ @@ -5090,7 +5322,7 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) #define TG3_TSO_FW_BSS_ADDR 0x08001b80 #define TG3_TSO_FW_BSS_LEN 0x894 -static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { +static const u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { 0x0e000003, 0x00000000, 0x08001b24, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, @@ -5377,7 +5609,7 @@ static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000, }; -static u32 tg3TsoFwRodata[] = { +static const u32 tg3TsoFwRodata[] = { 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f, 0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, @@ -5385,7 +5617,7 @@ static u32 tg3TsoFwRodata[] = { 0x00000000, }; -static u32 tg3TsoFwData[] = { +static const u32 tg3TsoFwData[] = { 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -5407,7 +5639,7 @@ static u32 tg3TsoFwData[] = { #define TG3_TSO5_FW_BSS_ADDR 0x00010f50 #define TG3_TSO5_FW_BSS_LEN 0x88 -static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { +static const u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { 0x0c004003, 0x00000000, 0x00010f04, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001, 0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, @@ -5566,14 +5798,14 @@ static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { 0x00000000, 0x00000000, 0x00000000, }; -static u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { +static const u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000, 0x00000000, }; -static u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { +static const u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }; @@ -5691,6 +5923,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) { struct tg3 *tp = netdev_priv(dev); struct sockaddr *addr = p; + int err = 0; if (!is_valid_ether_addr(addr->sa_data)) return -EINVAL; @@ -5700,11 +5933,25 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) if (!netif_running(dev)) return 0; - spin_lock_bh(&tp->lock); - __tg3_set_mac_addr(tp); - spin_unlock_bh(&tp->lock); + if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { + /* Reset chip so that ASF can re-init any MAC addresses it + * needs. + */ + tg3_netif_stop(tp); + tg3_full_lock(tp, 1); - return 0; + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); + err = tg3_restart_hw(tp, 0); + if (!err) + tg3_netif_start(tp); + tg3_full_unlock(tp); + } else { + spin_lock_bh(&tp->lock); + __tg3_set_mac_addr(tp); + spin_unlock_bh(&tp->lock); + } + + return err; } /* tp->lock is held. */ @@ -5752,7 +5999,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) } /* tp->lock is held. */ -static int tg3_reset_hw(struct tg3 *tp) +static int tg3_reset_hw(struct tg3 *tp, int reset_phy) { u32 val, rdmac_mode; int i, err, limit; @@ -5767,7 +6014,7 @@ static int tg3_reset_hw(struct tg3 *tp) tg3_abort_hw(tp, 1); } - if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && reset_phy) tg3_phy_reset(tp); err = tg3_chip_reset(tp); @@ -5804,7 +6051,9 @@ static int tg3_reset_hw(struct tg3 *tp) * can only do this after the hardware has been * successfully reset. */ - tg3_init_rings(tp); + err = tg3_init_rings(tp); + if (err) + return err; /* This value is determined during the probe time DMA * engine test, tg3_test_dma. @@ -5816,10 +6065,14 @@ static int tg3_reset_hw(struct tg3 *tp) GRC_MODE_NO_TX_PHDR_CSUM | GRC_MODE_NO_RX_PHDR_CSUM); tp->grc_mode |= GRC_MODE_HOST_SENDBDS; - if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM) - tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; - if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM) - tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM; + + /* Pseudo-header checksum is done by hardware logic and not + * the offload processers, so make the chip do the pseudo- + * header checksums on receive. For transmit it is more + * convenient to do the pseudo-header checksum in software + * as Linux does that on transmit for us in all cases. + */ + tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; tw32(GRC_MODE, tp->grc_mode | @@ -5893,7 +6146,20 @@ static int tg3_reset_hw(struct tg3 *tp) } /* Setup replenish threshold. */ - tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8); + val = tp->rx_pending / 8; + if (val == 0) + val = 1; + else if (val > tp->rx_std_max_post) + val = tp->rx_std_max_post; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1) + tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2); + + if (val > (TG3_RX_INTERNAL_RING_SZ_5906 / 2)) + val = TG3_RX_INTERNAL_RING_SZ_5906 / 2; + } + + tw32(RCVBDI_STD_THRESH, val); /* Initialize TG3_BDINFO's at: * RCVDBDI_STD_BD: standard eth size rx ring @@ -6053,8 +6319,12 @@ static int tg3_reset_hw(struct tg3 *tp) #endif /* Receive/send statistics. */ - if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) && - (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { + if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { + val = tr32(RCVLPC_STATS_ENABLE); + val &= ~RCVLPC_STATSENAB_DACK_FIX; + tw32(RCVLPC_STATS_ENABLE, val); + } else if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) && + (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { val = tr32(RCVLPC_STATS_ENABLE); val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX; tw32(RCVLPC_STATS_ENABLE, val); @@ -6140,6 +6410,9 @@ static int tg3_reset_hw(struct tg3 *tp) gpio_mask |= GRC_LCLCTRL_GPIO_OE3 | GRC_LCLCTRL_GPIO_OUTPUT3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL; + tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask; /* GPIO1 must be driven high for eeprom write protect */ @@ -6179,7 +6452,8 @@ static int tg3_reset_hw(struct tg3 *tp) } /* Enable host coalescing bug fix */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) val |= (1 << 29); tw32_f(WDMAC_MODE, val); @@ -6237,6 +6511,9 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(100); tp->rx_mode = RX_MODE_ENABLE; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; + tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); @@ -6297,11 +6574,12 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); } - err = tg3_setup_phy(tp, 1); + err = tg3_setup_phy(tp, reset_phy); if (err) return err; - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) { u32 tmp; /* Clear CRC stats. */ @@ -6370,7 +6648,7 @@ static int tg3_reset_hw(struct tg3 *tp) /* Called at device open time to get the chip ready for * packet processing. Invoked with tp->lock held. */ -static int tg3_init_hw(struct tg3 *tp) +static int tg3_init_hw(struct tg3 *tp, int reset_phy) { int err; @@ -6383,7 +6661,7 @@ static int tg3_init_hw(struct tg3 *tp) tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); - err = tg3_reset_hw(tp); + err = tg3_reset_hw(tp, reset_phy); out: return err; @@ -6431,12 +6709,19 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) TG3_STAT_ADD32(&sp->rx_frame_too_long_errors, MAC_RX_STATS_FRAME_TOO_LONG); TG3_STAT_ADD32(&sp->rx_jabbers, MAC_RX_STATS_JABBERS); TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE); + + TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT); + TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT); + TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT); } static void tg3_timer(unsigned long __opaque) { struct tg3 *tp = (struct tg3 *) __opaque; + if (tp->irq_sync) + goto restart_timer; + spin_lock(&tp->lock); if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { @@ -6494,12 +6779,14 @@ static void tg3_timer(unsigned long __opaque) need_setup = 1; } if (need_setup) { - tw32_f(MAC_MODE, - (tp->mac_mode & - ~MAC_MODE_PORT_MODE_MASK)); - udelay(40); - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); + if (!tp->serdes_counter) { + tw32_f(MAC_MODE, + (tp->mac_mode & + ~MAC_MODE_PORT_MODE_MASK)); + udelay(40); + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); + } tg3_setup_phy(tp, 0); } } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) @@ -6508,16 +6795,32 @@ static void tg3_timer(unsigned long __opaque) tp->timer_counter = tp->timer_multiplier; } - /* Heartbeat is only sent once every 2 seconds. */ + /* Heartbeat is only sent once every 2 seconds. + * + * The heartbeat is to tell the ASF firmware that the host + * driver is still alive. In the event that the OS crashes, + * ASF needs to reset the hardware to free up the FIFO space + * that may be filled with rx packets destined for the host. + * If the FIFO is full, ASF will no longer function properly. + * + * Unintended resets have been reported on real time kernels + * where the timer doesn't run on time. Netpoll will also have + * same problem. + * + * The new FWCMD_NICDRV_ALIVE3 command tells the ASF firmware + * to check the ring condition when the heartbeat is expiring + * before doing the reset. This will prevent most unintended + * resets. + */ if (!--tp->asf_counter) { if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { u32 val; - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX, - FWCMD_NICDRV_ALIVE2); - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, + FWCMD_NICDRV_ALIVE3); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); /* 5 seconds timeout */ - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); val = tr32(GRC_RX_CPU_EVENT); val |= (1 << 14); tw32(GRC_RX_CPU_EVENT, val); @@ -6527,13 +6830,14 @@ static void tg3_timer(unsigned long __opaque) spin_unlock(&tp->lock); +restart_timer: tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); } static int tg3_request_irq(struct tg3 *tp) { - irqreturn_t (*fn)(int, void *, struct pt_regs *); + irq_handler_t fn; unsigned long flags; struct net_device *dev = tp->dev; @@ -6541,12 +6845,12 @@ static int tg3_request_irq(struct tg3 *tp) fn = tg3_msi; if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) fn = tg3_msi_1shot; - flags = SA_SAMPLE_RANDOM; + flags = IRQF_SAMPLE_RANDOM; } else { fn = tg3_interrupt; if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) fn = tg3_interrupt_tagged; - flags = SA_SHIRQ | SA_SAMPLE_RANDOM; + flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM; } return (request_irq(tp->pdev->irq, fn, flags, dev->name, dev)); } @@ -6554,8 +6858,7 @@ static int tg3_request_irq(struct tg3 *tp) static int tg3_test_interrupt(struct tg3 *tp) { struct net_device *dev = tp->dev; - int err, i; - u32 int_mbox = 0; + int err, i, intr_ok = 0; if (!netif_running(dev)) return -ENODEV; @@ -6565,7 +6868,7 @@ static int tg3_test_interrupt(struct tg3 *tp) free_irq(tp->pdev->irq, dev); err = request_irq(tp->pdev->irq, tg3_test_isr, - SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); + IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev); if (err) return err; @@ -6576,23 +6879,31 @@ static int tg3_test_interrupt(struct tg3 *tp) HOSTCC_MODE_NOW); for (i = 0; i < 5; i++) { + u32 int_mbox, misc_host_ctrl; + int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); - if (int_mbox != 0) + misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL); + + if ((int_mbox != 0) || + (misc_host_ctrl & MISC_HOST_CTRL_MASK_PCI_INT)) { + intr_ok = 1; break; + } + msleep(10); } tg3_disable_ints(tp); free_irq(tp->pdev->irq, dev); - + err = tg3_request_irq(tp); if (err) return err; - if (int_mbox != 0) + if (intr_ok) return 0; return -EIO; @@ -6649,7 +6960,7 @@ static int tg3_test_msi(struct tg3 *tp) tg3_full_lock(tp, 1); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - err = tg3_init_hw(tp); + err = tg3_init_hw(tp, 1); tg3_full_unlock(tp); @@ -6714,7 +7025,7 @@ static int tg3_open(struct net_device *dev) tg3_full_lock(tp, 0); - err = tg3_init_hw(tp); + err = tg3_init_hw(tp, 1); if (err) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); @@ -6769,9 +7080,10 @@ static int tg3_open(struct net_device *dev) if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) { - u32 val = tr32(0x7c04); + u32 val = tr32(PCIE_TRANSACTION_CFG); - tw32(0x7c04, val | (1 << 29)); + tw32(PCIE_TRANSACTION_CFG, + val | PCIE_TRANS_CFG_1SHOT_MSI); } } } @@ -7213,7 +7525,7 @@ static struct net_device_stats *tg3_get_stats(struct net_device *dev) get_stat64(&hw_stats->rx_ucast_packets) + get_stat64(&hw_stats->rx_mcast_packets) + get_stat64(&hw_stats->rx_bcast_packets); - + stats->tx_packets = old_stats->tx_packets + get_stat64(&hw_stats->tx_ucast_packets) + get_stat64(&hw_stats->tx_mcast_packets) + @@ -7521,7 +7833,7 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, return 0; } -static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); +static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { @@ -7585,28 +7897,30 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct tg3 *tp = netdev_priv(dev); - + cmd->supported = (SUPPORTED_Autoneg); if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) cmd->supported |= (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full); - if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) + if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) { cmd->supported |= (SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_MII); - else + cmd->port = PORT_TP; + } else { cmd->supported |= SUPPORTED_FIBRE; - + cmd->port = PORT_FIBRE; + } + cmd->advertising = tp->link_config.advertising; if (netif_running(dev)) { cmd->speed = tp->link_config.active_speed; cmd->duplex = tp->link_config.active_duplex; } - cmd->port = 0; cmd->phy_address = PHY_ADDR; cmd->transceiver = 0; cmd->autoneg = tp->link_config.autoneg; @@ -7614,12 +7928,12 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->maxrxpkt = 0; return 0; } - + static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct tg3 *tp = netdev_priv(dev); - - if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) { + + if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) { /* These are the only valid advertisement bits allowed. */ if (cmd->autoneg == AUTONEG_ENABLE && (cmd->advertising & ~(ADVERTISED_1000baseT_Half | @@ -7651,69 +7965,69 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) tp->link_config.speed = cmd->speed; tp->link_config.duplex = cmd->duplex; } - + if (netif_running(dev)) tg3_setup_phy(tp, 1); tg3_full_unlock(tp); - + return 0; } - + static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct tg3 *tp = netdev_priv(dev); - + strcpy(info->driver, DRV_MODULE_NAME); strcpy(info->version, DRV_MODULE_VERSION); strcpy(info->fw_version, tp->fw_ver); strcpy(info->bus_info, pci_name(tp->pdev)); } - + static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct tg3 *tp = netdev_priv(dev); - + wol->supported = WAKE_MAGIC; wol->wolopts = 0; if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) wol->wolopts = WAKE_MAGIC; memset(&wol->sopass, 0, sizeof(wol->sopass)); } - + static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct tg3 *tp = netdev_priv(dev); - + if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; if ((wol->wolopts & WAKE_MAGIC) && - tp->tg3_flags2 & TG3_FLG2_PHY_SERDES && + tp->tg3_flags2 & TG3_FLG2_ANY_SERDES && !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) return -EINVAL; - + spin_lock_bh(&tp->lock); if (wol->wolopts & WAKE_MAGIC) tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; else tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; spin_unlock_bh(&tp->lock); - + return 0; } - + static u32 tg3_get_msglevel(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); return tp->msg_enable; } - + static void tg3_set_msglevel(struct net_device *dev, u32 value) { struct tg3 *tp = netdev_priv(dev); tp->msg_enable = value; } - + #if TG3_TSO_SUPPORT != 0 static int tg3_set_tso(struct net_device *dev, u32 value) { @@ -7724,16 +8038,23 @@ static int tg3_set_tso(struct net_device *dev, u32 value) return -EINVAL; return 0; } + if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) { + if (value) + dev->features |= NETIF_F_TSO6; + else + dev->features &= ~NETIF_F_TSO6; + } return ethtool_op_set_tso(dev, value); } #endif - + static int tg3_nway_reset(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); u32 bmcr; int r; - + if (!netif_running(dev)) return -EAGAIN; @@ -7751,14 +8072,14 @@ static int tg3_nway_reset(struct net_device *dev) r = 0; } spin_unlock_bh(&tp->lock); - + return r; } - + static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { struct tg3 *tp = netdev_priv(dev); - + ering->rx_max_pending = TG3_RX_RING_SIZE - 1; ering->rx_mini_max_pending = 0; if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) @@ -7777,24 +8098,24 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam * ering->tx_pending = tp->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; - + int irq_sync = 0, err = 0; + if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || (ering->tx_pending > TG3_TX_RING_SIZE - 1)) return -EINVAL; - + if (netif_running(dev)) { tg3_netif_stop(tp); irq_sync = 1; } tg3_full_lock(tp, irq_sync); - + tp->rx_pending = ering->rx_pending; if ((tp->tg3_flags2 & TG3_FLG2_MAX_RXPEND_64) && @@ -7805,29 +8126,30 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e if (netif_running(dev)) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - tg3_init_hw(tp); - tg3_netif_start(tp); + err = tg3_restart_hw(tp, 1); + if (!err) + tg3_netif_start(tp); } tg3_full_unlock(tp); - - return 0; + + return err; } - + static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { struct tg3 *tp = netdev_priv(dev); - + epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0; epause->rx_pause = (tp->tg3_flags & TG3_FLAG_RX_PAUSE) != 0; epause->tx_pause = (tp->tg3_flags & TG3_FLAG_TX_PAUSE) != 0; } - + static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { struct tg3 *tp = netdev_priv(dev); - int irq_sync = 0; - + int irq_sync = 0, err = 0; + if (netif_running(dev)) { tg3_netif_stop(tp); irq_sync = 1; @@ -7850,52 +8172,54 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam if (netif_running(dev)) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - tg3_init_hw(tp); - tg3_netif_start(tp); + err = tg3_restart_hw(tp, 1); + if (!err) + tg3_netif_start(tp); } tg3_full_unlock(tp); - - return 0; + + return err; } - + static u32 tg3_get_rx_csum(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); return (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0; } - + static int tg3_set_rx_csum(struct net_device *dev, u32 data) { struct tg3 *tp = netdev_priv(dev); - + if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { if (data != 0) return -EINVAL; return 0; } - + spin_lock_bh(&tp->lock); if (data) tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; else tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; spin_unlock_bh(&tp->lock); - + return 0; } - + static int tg3_set_tx_csum(struct net_device *dev, u32 data) { struct tg3 *tp = netdev_priv(dev); - + if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { if (data != 0) return -EINVAL; return 0; } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ethtool_op_set_tx_hw_csum(dev, data); else ethtool_op_set_tx_csum(dev, data); @@ -7948,7 +8272,7 @@ static int tg3_phys_id(struct net_device *dev, u32 data) LED_CTRL_TRAFFIC_OVERRIDE | LED_CTRL_TRAFFIC_BLINK | LED_CTRL_TRAFFIC_LED); - + else tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE | LED_CTRL_TRAFFIC_OVERRIDE); @@ -7969,6 +8293,8 @@ static void tg3_get_ethtool_stats (struct net_device *dev, #define NVRAM_TEST_SIZE 0x100 #define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14 +#define NVRAM_SELFBOOT_HW_SIZE 0x20 +#define NVRAM_SELFBOOT_DATA_SIZE 0x1c static int tg3_test_nvram(struct tg3 *tp) { @@ -7980,12 +8306,14 @@ static int tg3_test_nvram(struct tg3 *tp) if (magic == TG3_EEPROM_MAGIC) size = NVRAM_TEST_SIZE; - else if ((magic & 0xff000000) == 0xa5000000) { + else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) { if ((magic & 0xe00000) == 0x200000) size = NVRAM_SELFBOOT_FORMAT1_SIZE; else return 0; - } else + } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) + size = NVRAM_SELFBOOT_HW_SIZE; + else return -EIO; buf = kmalloc(size, GFP_KERNEL); @@ -8004,15 +8332,65 @@ static int tg3_test_nvram(struct tg3 *tp) goto out; /* Selfboot format */ - if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) { + if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) == + TG3_EEPROM_MAGIC_FW) { u8 *buf8 = (u8 *) buf, csum8 = 0; for (i = 0; i < size; i++) csum8 += buf8[i]; - if (csum8 == 0) - return 0; - return -EIO; + if (csum8 == 0) { + err = 0; + goto out; + } + + err = -EIO; + goto out; + } + + if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) == + TG3_EEPROM_MAGIC_HW) { + u8 data[NVRAM_SELFBOOT_DATA_SIZE]; + u8 parity[NVRAM_SELFBOOT_DATA_SIZE]; + u8 *buf8 = (u8 *) buf; + int j, k; + + /* Separate the parity bits and the data bytes. */ + for (i = 0, j = 0, k = 0; i < NVRAM_SELFBOOT_HW_SIZE; i++) { + if ((i == 0) || (i == 8)) { + int l; + u8 msk; + + for (l = 0, msk = 0x80; l < 7; l++, msk >>= 1) + parity[k++] = buf8[i] & msk; + i++; + } + else if (i == 16) { + int l; + u8 msk; + + for (l = 0, msk = 0x20; l < 6; l++, msk >>= 1) + parity[k++] = buf8[i] & msk; + i++; + + for (l = 0, msk = 0x80; l < 8; l++, msk >>= 1) + parity[k++] = buf8[i] & msk; + i++; + } + data[j++] = buf8[i]; + } + + err = -EIO; + for (i = 0; i < NVRAM_SELFBOOT_DATA_SIZE; i++) { + u8 hw8 = hweight8(data[i]); + + if ((hw8 & 0x1) && parity[i]) + goto out; + else if (!(hw8 & 0x1) && !parity[i]) + goto out; + } + err = 0; + goto out; } /* Bootstrap checksum at offset 0x10 */ @@ -8061,7 +8439,7 @@ static int tg3_test_link(struct tg3 *tp) /* Only test the commonly used registers */ static int tg3_test_registers(struct tg3 *tp) { - int i, is_5705; + int i, is_5705, is_5750; u32 offset, read_mask, write_mask, val, save_val, read_val; static struct { u16 offset; @@ -8069,6 +8447,7 @@ static int tg3_test_registers(struct tg3 *tp) #define TG3_FL_5705 0x1 #define TG3_FL_NOT_5705 0x2 #define TG3_FL_NOT_5788 0x4 +#define TG3_FL_NOT_5750 0x8 u32 read_mask; u32 write_mask; } reg_tbl[] = { @@ -8121,7 +8500,7 @@ static int tg3_test_registers(struct tg3 *tp) 0x00000000, 0xffff0002 }, { RCVDBDI_STD_BD+0xc, 0x0000, 0x00000000, 0xffffffff }, - + /* Receive BD Initiator Control Registers. */ { RCVBDI_STD_THRESH, TG3_FL_NOT_5705, 0x00000000, 0xffffffff }, @@ -8129,7 +8508,7 @@ static int tg3_test_registers(struct tg3 *tp) 0x00000000, 0x000003ff }, { RCVBDI_JUMBO_THRESH, TG3_FL_NOT_5705, 0x00000000, 0xffffffff }, - + /* Host Coalescing Control Registers. */ { HOSTCC_MODE, TG3_FL_NOT_5705, 0x00000000, 0x00000004 }, @@ -8179,9 +8558,9 @@ static int tg3_test_registers(struct tg3 *tp) 0xffffffff, 0x00000000 }, /* Buffer Manager Control Registers. */ - { BUFMGR_MB_POOL_ADDR, 0x0000, + { BUFMGR_MB_POOL_ADDR, TG3_FL_NOT_5750, 0x00000000, 0x007fff80 }, - { BUFMGR_MB_POOL_SIZE, 0x0000, + { BUFMGR_MB_POOL_SIZE, TG3_FL_NOT_5750, 0x00000000, 0x007fffff }, { BUFMGR_MB_RDMA_LOW_WATER, 0x0000, 0x00000000, 0x0000003f }, @@ -8193,7 +8572,7 @@ static int tg3_test_registers(struct tg3 *tp) 0xffffffff, 0x00000000 }, { BUFMGR_DMA_DESC_POOL_SIZE, TG3_FL_NOT_5705, 0xffffffff, 0x00000000 }, - + /* Mailbox Registers */ { GRCMBOX_RCVSTD_PROD_IDX+4, 0x0000, 0x00000000, 0x000001ff }, @@ -8207,10 +8586,12 @@ static int tg3_test_registers(struct tg3 *tp) { 0xffff, 0x0000, 0x00000000, 0x00000000 }, }; - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + is_5705 = is_5750 = 0; + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { is_5705 = 1; - else - is_5705 = 0; + if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) + is_5750 = 1; + } for (i = 0; reg_tbl[i].offset != 0xffff; i++) { if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705)) @@ -8223,6 +8604,9 @@ static int tg3_test_registers(struct tg3 *tp) (reg_tbl[i].flags & TG3_FL_NOT_5788)) continue; + if (is_5750 && (reg_tbl[i].flags & TG3_FL_NOT_5750)) + continue; + offset = (u32) reg_tbl[i].offset; read_mask = reg_tbl[i].read_mask; write_mask = reg_tbl[i].write_mask; @@ -8314,14 +8698,24 @@ static int tg3_test_memory(struct tg3 *tp) { 0x00008000, 0x02000}, { 0x00010000, 0x0c000}, { 0xffffffff, 0x00000} + }, mem_tbl_5906[] = { + { 0x00000200, 0x00008}, + { 0x00004000, 0x00400}, + { 0x00006000, 0x00400}, + { 0x00008000, 0x01000}, + { 0x00010000, 0x01000}, + { 0xffffffff, 0x00000} }; struct mem_entry *mem_tbl; int err = 0; int i; if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) mem_tbl = mem_tbl_5755; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + mem_tbl = mem_tbl_5906; else mem_tbl = mem_tbl_5705; } else @@ -8332,7 +8726,7 @@ static int tg3_test_memory(struct tg3 *tp) mem_tbl[i].len)) != 0) break; } - + return err; } @@ -8358,13 +8752,41 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) return 0; mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | - MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY | - MAC_MODE_PORT_MODE_GMII; + MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY; + if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) + mac_mode |= MAC_MODE_PORT_MODE_MII; + else + mac_mode |= MAC_MODE_PORT_MODE_GMII; tw32(MAC_MODE, mac_mode); } else if (loopback_mode == TG3_PHY_LOOPBACK) { - tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX | - BMCR_SPEED1000); + u32 val; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 phytest; + + if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phytest)) { + u32 phy; + + tg3_writephy(tp, MII_TG3_EPHY_TEST, + phytest | MII_TG3_EPHY_SHADOW_EN); + if (!tg3_readphy(tp, 0x1b, &phy)) + tg3_writephy(tp, 0x1b, phy & ~0x20); + if (!tg3_readphy(tp, 0x10, &phy)) + tg3_writephy(tp, 0x10, phy & ~0x4000); + tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest); + } + } + val = BMCR_LOOPBACK | BMCR_FULLDPLX; + if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) + val |= BMCR_SPEED100; + else + val |= BMCR_SPEED1000; + + tg3_writephy(tp, MII_BMCR, val); udelay(40); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800); + /* reset to prevent losing 1st rx packet intermittently */ if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { tw32_f(MAC_RX_MODE, RX_MODE_RESET); @@ -8372,9 +8794,16 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) tw32_f(MAC_RX_MODE, tp->rx_mode); } mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | - MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) + MAC_MODE_LINK_POLARITY; + if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) + mac_mode |= MAC_MODE_PORT_MODE_MII; + else + mac_mode |= MAC_MODE_PORT_MODE_GMII; + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { mac_mode &= ~MAC_MODE_LINK_POLARITY; + tg3_writephy(tp, MII_TG3_EXT_CTRL, + MII_TG3_EXT_CTRL_LNK3_LED_MODE); + } tw32(MAC_MODE, mac_mode); } else @@ -8383,7 +8812,10 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) err = -EIO; tx_len = 1514; - skb = dev_alloc_skb(tx_len); + skb = netdev_alloc_skb(tp->dev, tx_len); + if (!skb) + return -ENOMEM; + tx_data = skb_put(skb, tx_len); memcpy(tx_data, tp->dev->dev_addr, 6); memset(tx_data + 6, 0x0, 8); @@ -8415,7 +8847,8 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) udelay(10); - for (i = 0; i < 10; i++) { + /* 250 usec to allow enough time on some 10/100 Mbps devices. */ + for (i = 0; i < 25; i++) { tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW); @@ -8461,7 +8894,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) goto out; } err = 0; - + /* tg3_free_rings will unmap and free the rx_skb */ out: return err; @@ -8479,7 +8912,9 @@ static int tg3_test_loopback(struct tg3 *tp) if (!netif_running(tp->dev)) return TG3_LOOPBACK_FAILED; - tg3_reset_hw(tp); + err = tg3_reset_hw(tp, 1); + if (err) + return TG3_LOOPBACK_FAILED; if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) err |= TG3_MAC_LOOPBACK_FAILED; @@ -8553,8 +8988,8 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); if (netif_running(dev)) { tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - tg3_init_hw(tp); - tg3_netif_start(tp); + if (!tg3_restart_hw(tp, 1)) + tg3_netif_start(tp); } tg3_full_unlock(tp); @@ -8621,6 +9056,9 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { struct tg3 *tp = netdev_priv(dev); + if (netif_running(dev)) + tg3_netif_stop(tp); + tg3_full_lock(tp, 0); tp->vlgrp = grp; @@ -8629,16 +9067,25 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) __tg3_set_rx_mode(dev); tg3_full_unlock(tp); + + if (netif_running(dev)) + tg3_netif_start(tp); } static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct tg3 *tp = netdev_priv(dev); + if (netif_running(dev)) + tg3_netif_stop(tp); + tg3_full_lock(tp, 0); if (tp->vlgrp) tp->vlgrp->vlan_devices[vid] = NULL; tg3_full_unlock(tp); + + if (netif_running(dev)) + tg3_netif_start(tp); } #endif @@ -8704,7 +9151,7 @@ static int tg3_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) return 0; } -static struct ethtool_ops tg3_ethtool_ops = { +static const struct ethtool_ops tg3_ethtool_ops = { .get_settings = tg3_get_settings, .set_settings = tg3_set_settings, .get_drvinfo = tg3_get_drvinfo, @@ -8753,7 +9200,9 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp) if (tg3_nvram_read_swab(tp, 0, &magic) != 0) return; - if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000)) + if ((magic != TG3_EEPROM_MAGIC) && + ((magic & TG3_EEPROM_MAGIC_FW_MSK) != TG3_EEPROM_MAGIC_FW) && + ((magic & TG3_EEPROM_MAGIC_HW_MSK) != TG3_EEPROM_MAGIC_HW)) return; /* @@ -8775,7 +9224,7 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp) tp->nvram_size = cursize; } - + static void __devinit tg3_get_nvram_size(struct tg3 *tp) { u32 val; @@ -8912,6 +9361,47 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) } } +static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) +{ + u32 nvcfg1; + + nvcfg1 = tr32(NVRAM_CFG1); + + /* NVRAM protection for TPM */ + if (nvcfg1 & (1 << 27)) + tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; + + switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { + case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ: + case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; + + nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; + tw32(NVRAM_CFG1, nvcfg1); + break; + case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: + case FLASH_5755VENDOR_ATMEL_FLASH_1: + case FLASH_5755VENDOR_ATMEL_FLASH_2: + case FLASH_5755VENDOR_ATMEL_FLASH_3: + case FLASH_5755VENDOR_ATMEL_FLASH_4: + 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; + } +} + static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -8950,14 +9440,18 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) } } +static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp) +{ + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; +} + /* Chips other than 5700/5701 use the NVRAM for fetching info. */ static void __devinit tg3_nvram_init(struct tg3 *tp) { int j; - if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) - return; - tw32_f(GRC_EEPROM_ADDR, (EEPROM_ADDR_FSM_RESET | (EEPROM_DEFAULT_CLOCK_PERIOD << @@ -8985,8 +9479,12 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tg3_get_5752_nvram_info(tp); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tg3_get_5755_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tg3_get_5787_nvram_info(tp); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tg3_get_5906_nvram_info(tp); else tg3_get_nvram_info(tp); @@ -9088,11 +9586,6 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) { int ret; - if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { - printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n"); - return -EINVAL; - } - if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) return tg3_nvram_read_using_eeprom(tp, offset, val); @@ -9156,7 +9649,7 @@ static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, (addr & EEPROM_ADDR_ADDR_MASK) | EEPROM_ADDR_START | EEPROM_ADDR_WRITE); - + for (j = 0; j < 10000; j++) { val = tr32(GRC_EEPROM_ADDR); @@ -9192,7 +9685,7 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, u32 phy_addr, page_off, size; phy_addr = offset & ~pagemask; - + for (j = 0; j < pagesize; j += 4) { if ((ret = tg3_nvram_read(tp, phy_addr + j, (u32 *) (tmp + j)))) @@ -9291,13 +9784,14 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, if ((page_off == 0) || (i == 0)) nvram_cmd |= NVRAM_CMD_FIRST; - else if (page_off == (tp->nvram_pagesize - 4)) + if (page_off == (tp->nvram_pagesize - 4)) nvram_cmd |= NVRAM_CMD_LAST; if (i == (len - 4)) nvram_cmd |= NVRAM_CMD_LAST; if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { @@ -9324,11 +9818,6 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { int ret; - if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { - printk(KERN_ERR PFX "Attempt to do nvram_write on Sun 570X\n"); - return -EINVAL; - } - if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & ~GRC_LCLCTRL_GPIO_OUTPUT1); @@ -9436,12 +9925,18 @@ static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp) return NULL; } -/* Since this function may be called in D3-hot power state during - * tg3_init_one(), only config cycles are allowed. - */ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) { u32 val; + u16 pmcsr; + + /* On some early chips the SRAM cannot be accessed in D3hot state, + * so need make sure we're in D0. + */ + pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr); + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; + pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr); + msleep(1); /* Make sure register accesses (indirect or otherwise) * will function correctly. @@ -9449,12 +9944,25 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl); + /* The memory arbiter has to be enabled in order for SRAM accesses + * to succeed. Normally on powerup the tg3 chip firmware will make + * sure it is enabled, but other entities such as system netboot + * code might disable it. + */ + val = tr32(MEMARB_MODE); + tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); + tp->phy_id = PHY_ID_INVALID; tp->led_ctrl = LED_CTRL_MODE_PHY_1; - /* Do not even try poking around in here on Sun parts. */ - if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) + /* Assume an onboard device by default. */ + tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) + tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; return; + } tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { @@ -9552,10 +10060,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) tp->led_ctrl = LED_CTRL_MODE_PHY_2; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && - (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && - (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) + if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; + else + tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; @@ -9639,7 +10147,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) if (!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) goto skip_phy_reset; - + err = tg3_phy_reset(tp); if (err) return err; @@ -9704,16 +10212,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp) int i; u32 magic; - if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { - /* Sun decided not to put the necessary bits in the - * NVRAM of their onboard tg3 parts :( - */ - strcpy(tp->board_part_number, "Sun 570X"); - return; - } - if (tg3_nvram_read_swab(tp, 0x0, &magic)) - return; + goto out_not_found; if (magic == TG3_EEPROM_MAGIC) { for (i = 0; i < 256; i += 4) { @@ -9744,6 +10244,9 @@ static void __devinit tg3_read_partno(struct tg3 *tp) break; msleep(1); } + if (!(tmp16 & 0x8000)) + goto out_not_found; + pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA, &tmp); tmp = cpu_to_le32(tmp); @@ -9792,7 +10295,10 @@ static void __devinit tg3_read_partno(struct tg3 *tp) } out_not_found: - strcpy(tp->board_part_number, "none"); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + strcpy(tp->board_part_number, "BCM95906"); + else + strcpy(tp->board_part_number, "none"); } static void __devinit tg3_read_fw_ver(struct tg3 *tp) @@ -9835,42 +10341,13 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) } } -#ifdef CONFIG_SPARC64 -static int __devinit tg3_is_sun_570X(struct tg3 *tp) -{ - struct pci_dev *pdev = tp->pdev; - struct pcidev_cookie *pcp = pdev->sysdata; - - if (pcp != NULL) { - int node = pcp->prom_node; - u32 venid; - int err; - - err = prom_getproperty(node, "subsystem-vendor-id", - (char *) &venid, sizeof(venid)); - if (err == 0 || err == -1) - return 0; - if (venid == PCI_VENDOR_ID_SUN) - return 1; - - /* TG3 chips onboard the SunBlade-2500 don't have the - * subsystem-vendor-id set to PCI_VENDOR_ID_SUN but they - * are distinguishable from non-Sun variants by being - * named "network" by the firmware. Non-Sun cards will - * show up as being named "ethernet". - */ - if (!strcmp(pcp->prom_name, "network")) - return 1; - } - return 0; -} -#endif - static int __devinit tg3_get_invariants(struct tg3 *tp) { static struct pci_device_id write_reorder_chipsets[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_8131_BRIDGE) }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8385_0) }, { }, @@ -9882,11 +10359,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) u16 pci_cmd; int err; -#ifdef CONFIG_SPARC64 - if (tg3_is_sun_570X(tp)) - tp->tg3_flags2 |= TG3_FLG2_SUN_570X; -#endif - /* Force memory write invalidate off. If we leave it on, * then on 5700_BX chips we have to enable a workaround. * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary @@ -10026,7 +10498,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; @@ -10035,17 +10509,27 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { + 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_5906) { tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; - } else - tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1; + } else { + tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | + TG3_FLG2_HW_TSO_1_BUG; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == + ASIC_REV_5750 && + tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2) + tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_1_BUG; + } } if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) + 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_5906) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) @@ -10175,6 +10659,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) pci_cmd &= ~PCI_COMMAND_MEMORY; pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + tp->read32_mbox = tg3_read32_mbox_5906; + tp->write32_mbox = tg3_write32_mbox_5906; + tp->write32_tx_mbox = tg3_write32_mbox_5906; + tp->write32_rx_mbox = tg3_write32_mbox_5906; + } + + if (tp->write32 == tg3_write_indirect_reg32 || + ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) && + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701))) + tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG; /* Get eeprom hw config before calling tg3_set_power_state(). * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be @@ -10183,7 +10679,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * When the flag is set, it means that GPIO1 is used for eeprom * write protect and also implies that it is a LOM where GPIOs * are not used to switch power. - */ + */ tg3_get_eeprom_hw_cfg(tp); /* Set up tp->grc_local_ctrl before calling tg3_set_power_state(). @@ -10201,6 +10697,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + /* Force the chip into D0. */ err = tg3_set_power_state(tp, PCI_D0); if (err) { @@ -10215,15 +10714,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0) tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS; - /* Pseudo-header checksum is done by hardware logic and not - * the offload processers, so make the chip do the pseudo- - * header checksums on receive. For transmit it is more - * convenient to do the pseudo-header checksum in software - * as Linux does that on transmit for us in all cases. - */ - tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM; - tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM; - /* Derive initial jumbo mode from MTU assigned in * ether_setup() via the alloc_etherdev() call */ @@ -10246,6 +10736,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) && (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) || (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED; @@ -10255,9 +10746,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; - if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && - (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)) - tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) + tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; + } tp->coalesce_mode = 0; if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX && @@ -10345,7 +10840,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F))) + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->tg3_flags |= TG3_FLAG_10_100_ONLY; err = tg3_phy_probe(tp); @@ -10395,7 +10891,9 @@ 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 (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + 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_5906) tp->dev->hard_start_xmit = tg3_start_xmit; else tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug; @@ -10405,6 +10903,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) tp->rx_offset = 0; + tp->rx_std_max_post = TG3_RX_RING_SIZE; + + /* Increment the rx prod index on the rx std ring by at most + * 8 for these chips to workaround hw errata. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->rx_std_max_post = 8; + /* By default, disable wake-on-lan. User can change this * using ETHTOOL_SWOL. */ @@ -10421,11 +10929,13 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp) struct pcidev_cookie *pcp = pdev->sysdata; if (pcp != NULL) { - int node = pcp->prom_node; + unsigned char *addr; + int len; - if (prom_getproplen(node, "local-mac-address") == 6) { - prom_getproperty(node, "local-mac-address", - dev->dev_addr, 6); + addr = of_get_property(pcp->prom_node, "local-mac-address", + &len); + if (addr && len == 6) { + memcpy(dev->dev_addr, addr, 6); memcpy(dev->perm_addr, dev->dev_addr, 6); return 0; } @@ -10447,6 +10957,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) { struct net_device *dev = tp->dev; u32 hi, lo, mac_offset; + int addr_ok = 0; #ifdef CONFIG_SPARC64 if (!tg3_get_macaddr_sparc(tp)) @@ -10454,8 +10965,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) #endif mac_offset = 0x7c; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - !(tp->tg3_flags & TG3_FLG2_SUN_570X)) || + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) mac_offset = 0xcc; @@ -10464,6 +10974,8 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) else tg3_nvram_unlock(tp); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + mac_offset = 0x10; /* First try to get it from MAC address mailbox. */ tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi); @@ -10476,29 +10988,33 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) dev->dev_addr[3] = (lo >> 16) & 0xff; dev->dev_addr[4] = (lo >> 8) & 0xff; dev->dev_addr[5] = (lo >> 0) & 0xff; - } - /* Next, try NVRAM. */ - else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) && - !tg3_nvram_read(tp, mac_offset + 0, &hi) && - !tg3_nvram_read(tp, mac_offset + 4, &lo)) { - dev->dev_addr[0] = ((hi >> 16) & 0xff); - dev->dev_addr[1] = ((hi >> 24) & 0xff); - dev->dev_addr[2] = ((lo >> 0) & 0xff); - dev->dev_addr[3] = ((lo >> 8) & 0xff); - dev->dev_addr[4] = ((lo >> 16) & 0xff); - dev->dev_addr[5] = ((lo >> 24) & 0xff); - } - /* Finally just fetch it out of the MAC control regs. */ - else { - hi = tr32(MAC_ADDR_0_HIGH); - lo = tr32(MAC_ADDR_0_LOW); - dev->dev_addr[5] = lo & 0xff; - dev->dev_addr[4] = (lo >> 8) & 0xff; - dev->dev_addr[3] = (lo >> 16) & 0xff; - dev->dev_addr[2] = (lo >> 24) & 0xff; - dev->dev_addr[1] = hi & 0xff; - dev->dev_addr[0] = (hi >> 8) & 0xff; + /* Some old bootcode may report a 0 MAC address in SRAM */ + addr_ok = is_valid_ether_addr(&dev->dev_addr[0]); + } + if (!addr_ok) { + /* Next, try NVRAM. */ + if (!tg3_nvram_read(tp, mac_offset + 0, &hi) && + !tg3_nvram_read(tp, mac_offset + 4, &lo)) { + dev->dev_addr[0] = ((hi >> 16) & 0xff); + dev->dev_addr[1] = ((hi >> 24) & 0xff); + dev->dev_addr[2] = ((lo >> 0) & 0xff); + dev->dev_addr[3] = ((lo >> 8) & 0xff); + dev->dev_addr[4] = ((lo >> 16) & 0xff); + dev->dev_addr[5] = ((lo >> 24) & 0xff); + } + /* Finally just fetch it out of the MAC control regs. */ + else { + hi = tr32(MAC_ADDR_0_HIGH); + lo = tr32(MAC_ADDR_0_LOW); + + dev->dev_addr[5] = lo & 0xff; + dev->dev_addr[4] = (lo >> 8) & 0xff; + dev->dev_addr[3] = (lo >> 16) & 0xff; + dev->dev_addr[2] = (lo >> 24) & 0xff; + dev->dev_addr[1] = hi & 0xff; + dev->dev_addr[0] = (hi >> 8) & 0xff; + } } if (!is_valid_ether_addr(&dev->dev_addr[0])) { @@ -10943,6 +11459,12 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) DEFAULT_MB_MACRX_LOW_WATER_5705; tp->bufmgr_config.mbuf_high_water = DEFAULT_MB_HIGH_WATER_5705; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + tp->bufmgr_config.mbuf_mac_rx_low_water = + DEFAULT_MB_MACRX_LOW_WATER_5906; + tp->bufmgr_config.mbuf_high_water = + DEFAULT_MB_HIGH_WATER_5906; + } tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780; @@ -10984,7 +11506,10 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5752: return "5752"; case PHY_ID_BCM5714: return "5714"; case PHY_ID_BCM5780: return "5780"; + case PHY_ID_BCM5755: return "5755"; case PHY_ID_BCM5787: return "5787"; + case PHY_ID_BCM5756: return "5722/5756"; + case PHY_ID_BCM5906: return "5906"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; @@ -11145,7 +11670,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - dev->features |= NETIF_F_LLTX; #if TG3_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register = tg3_vlan_rx_register; @@ -11187,7 +11711,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA; #endif spin_lock_init(&tp->lock); - spin_lock_init(&tp->tx_lock); spin_lock_init(&tp->indirect_lock); INIT_WORK(&tp->reset_task, tg3_reset_task, tp); @@ -11287,8 +11810,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * Firmware TSO on older chips gives lower performance, so it * is off by default, but can be enabled using ethtool. */ - if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { dev->features |= NETIF_F_TSO; + if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) + dev->features |= NETIF_F_TSO6; + } #endif @@ -11332,7 +11859,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * checksumming. */ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) dev->features |= NETIF_F_HW_CSUM; else dev->features |= NETIF_F_IP_CSUM; @@ -11461,7 +11989,8 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) tg3_full_lock(tp, 0); tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - tg3_init_hw(tp); + if (tg3_restart_hw(tp, 1)) + goto out; tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); @@ -11469,6 +11998,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_attach(dev); tg3_netif_start(tp); +out: tg3_full_unlock(tp); } @@ -11495,16 +12025,19 @@ static int tg3_resume(struct pci_dev *pdev) tg3_full_lock(tp, 0); tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - tg3_init_hw(tp); + err = tg3_restart_hw(tp, 1); + if (err) + goto out; tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); tg3_netif_start(tp); +out: tg3_full_unlock(tp); - return 0; + return err; } static struct pci_driver tg3_driver = { @@ -11518,7 +12051,7 @@ static struct pci_driver tg3_driver = { static int __init tg3_init(void) { - return pci_module_init(&tg3_driver); + return pci_register_driver(&tg3_driver); } static void __exit tg3_cleanup(void)