diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/tg3.c')
| -rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 6374 |
1 files changed, 4245 insertions, 2129 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index a1f2e0fed78..8afa579e7c4 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -4,7 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. - * Copyright (C) 2005-2011 Broadcom Corporation. + * Copyright (C) 2005-2014 Broadcom Corporation. * * Firmware is: * Derived from proprietary unpublished source code, @@ -25,7 +25,6 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/in.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/pci.h> @@ -37,6 +36,7 @@ #include <linux/mii.h> #include <linux/phy.h> #include <linux/brcmphy.h> +#include <linux/if.h> #include <linux/if_vlan.h> #include <linux/ip.h> #include <linux/tcp.h> @@ -44,15 +44,20 @@ #include <linux/prefetch.h> #include <linux/dma-mapping.h> #include <linux/firmware.h> +#include <linux/ssb/ssb_driver_gige.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> #include <net/checksum.h> #include <net/ip.h> -#include <asm/system.h> #include <linux/io.h> #include <asm/byteorder.h> #include <linux/uaccess.h> +#include <uapi/linux/net_tstamp.h> +#include <linux/ptp_clock_kernel.h> + #ifdef CONFIG_SPARC #include <asm/idprom.h> #include <asm/prom.h> @@ -89,10 +94,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 122 +#define TG3_MIN_NUM 137 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "December 7, 2011" +#define DRV_MODULE_RELDATE "May 11, 2014" #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 @@ -203,13 +208,18 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define TG3_RAW_IP_ALIGN 2 +#define TG3_MAX_UCAST_ADDR(tp) (tg3_flag((tp), ENABLE_ASF) ? 2 : 3) +#define TG3_UCAST_ADDR_IDX(tp) (tg3_flag((tp), ENABLE_ASF) ? 2 : 1) + #define TG3_FW_UPDATE_TIMEOUT_SEC 5 +#define TG3_FW_UPDATE_FREQ_SEC (TG3_FW_UPDATE_TIMEOUT_SEC / 2) #define FIRMWARE_TG3 "tigon/tg3.bin" +#define FIRMWARE_TG357766 "tigon/tg357766.bin" #define FIRMWARE_TG3TSO "tigon/tg3_tso.bin" #define FIRMWARE_TG3TSO5 "tigon/tg3_tso5.bin" -static char version[] __devinitdata = +static char version[] = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")"; MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)"); @@ -224,6 +234,9 @@ static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ module_param(tg3_debug, int, 0); MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); +#define TG3_DRV_DATA_FLAG_10_100_ONLY 0x0001 +#define TG3_DRV_DATA_FLAG_5705_10_100 0x0002 + static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)}, @@ -243,20 +256,29 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {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_5901), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY | + TG3_DRV_DATA_FLAG_5705_10_100}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY | + TG3_DRV_DATA_FLAG_5705_10_100}, {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_5705F), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY | + TG3_DRV_DATA_FLAG_5705_10_100}, {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_5751M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {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_5753F), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {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)}, @@ -264,8 +286,13 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {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_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5787M, + PCI_VENDOR_ID_LENOVO, + TG3PCI_SUBDEVICE_ID_LENOVO_5787M), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {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)}, @@ -284,20 +311,40 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)}, + {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780, + PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_A), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, + {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780, + PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_B), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717_C)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57766)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5762)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5725)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5727)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57764)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57767)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57787)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57782)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57786)}, {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)}, @@ -395,19 +442,27 @@ static const struct { }; #define TG3_NUM_STATS ARRAY_SIZE(ethtool_stats_keys) +#define TG3_NVRAM_TEST 0 +#define TG3_LINK_TEST 1 +#define TG3_REGISTER_TEST 2 +#define TG3_MEMORY_TEST 3 +#define TG3_MAC_LOOPB_TEST 4 +#define TG3_PHY_LOOPB_TEST 5 +#define TG3_EXT_LOOPB_TEST 6 +#define TG3_INTERRUPT_TEST 7 static const struct { const char string[ETH_GSTRING_LEN]; } ethtool_test_keys[] = { - { "nvram test (online) " }, - { "link test (online) " }, - { "register test (offline)" }, - { "memory test (offline)" }, - { "mac loopback test (offline)" }, - { "phy loopback test (offline)" }, - { "ext loopback test (offline)" }, - { "interrupt test (offline)" }, + [TG3_NVRAM_TEST] = { "nvram test (online) " }, + [TG3_LINK_TEST] = { "link test (online) " }, + [TG3_REGISTER_TEST] = { "register test (offline)" }, + [TG3_MEMORY_TEST] = { "memory test (offline)" }, + [TG3_MAC_LOOPB_TEST] = { "mac loopback test (offline)" }, + [TG3_PHY_LOOPB_TEST] = { "phy loopback test (offline)" }, + [TG3_EXT_LOOPB_TEST] = { "ext loopback test (offline)" }, + [TG3_INTERRUPT_TEST] = { "interrupt test (offline)" }, }; #define TG3_NUM_TEST ARRAY_SIZE(ethtool_test_keys) @@ -530,7 +585,9 @@ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait) static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) { tp->write32_mbox(tp, off, val); - if (!tg3_flag(tp, MBOX_WRITE_REORDER) && !tg3_flag(tp, ICH_WORKAROUND)) + if (tg3_flag(tp, FLUSH_POSTED_WRITES) || + (!tg3_flag(tp, MBOX_WRITE_REORDER) && + !tg3_flag(tp, ICH_WORKAROUND))) tp->read32_mbox(tp, off); } @@ -540,7 +597,8 @@ static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) writel(val, mbox); if (tg3_flag(tp, TXD_MBOX_HWBUG)) writel(val, mbox); - if (tg3_flag(tp, MBOX_WRITE_REORDER)) + if (tg3_flag(tp, MBOX_WRITE_REORDER) || + tg3_flag(tp, FLUSH_POSTED_WRITES)) readl(mbox); } @@ -569,7 +627,7 @@ 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 && + if (tg3_asic_rev(tp) == ASIC_REV_5906 && (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) return; @@ -594,7 +652,7 @@ 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 && + if (tg3_asic_rev(tp) == ASIC_REV_5906 && (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) { *val = 0; return; @@ -622,7 +680,7 @@ static void tg3_ape_lock_init(struct tg3 *tp) int i; u32 regbase, bit; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + if (tg3_asic_rev(tp) == ASIC_REV_5761) regbase = TG3_APE_LOCK_GRANT; else regbase = TG3_APE_PER_LOCK_GRANT; @@ -658,7 +716,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) switch (locknum) { case TG3_APE_LOCK_GPIO: - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + if (tg3_asic_rev(tp) == ASIC_REV_5761) return 0; case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: @@ -667,11 +725,17 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) else bit = 1 << tp->pci_fn; break; + case TG3_APE_LOCK_PHY0: + case TG3_APE_LOCK_PHY1: + case TG3_APE_LOCK_PHY2: + case TG3_APE_LOCK_PHY3: + bit = APE_LOCK_REQ_DRIVER; + break; default: return -EINVAL; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { + if (tg3_asic_rev(tp) == ASIC_REV_5761) { req = TG3_APE_LOCK_REQ; gnt = TG3_APE_LOCK_GRANT; } else { @@ -688,6 +752,9 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) status = tg3_ape_read32(tp, gnt + off); if (status == bit) break; + if (pci_channel_offline(tp->pdev)) + break; + udelay(10); } @@ -709,7 +776,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) switch (locknum) { case TG3_APE_LOCK_GPIO: - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + if (tg3_asic_rev(tp) == ASIC_REV_5761) return; case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: @@ -718,11 +785,17 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) else bit = 1 << tp->pci_fn; break; + case TG3_APE_LOCK_PHY0: + case TG3_APE_LOCK_PHY1: + case TG3_APE_LOCK_PHY2: + case TG3_APE_LOCK_PHY3: + bit = APE_LOCK_GRANT_DRIVER; + break; default: return; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + if (tg3_asic_rev(tp) == ASIC_REV_5761) gnt = TG3_APE_LOCK_GRANT; else gnt = TG3_APE_PER_LOCK_GRANT; @@ -730,44 +803,132 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) tg3_ape_write32(tp, gnt + 4 * locknum, bit); } -static void tg3_ape_send_event(struct tg3 *tp, u32 event) +static int tg3_ape_event_lock(struct tg3 *tp, u32 timeout_us) { - int i; u32 apedata; - /* NCSI does not support APE events */ - if (tg3_flag(tp, APE_HAS_NCSI)) - return; + while (timeout_us) { + if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM)) + return -EBUSY; + + apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + break; + + tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); + + udelay(10); + timeout_us -= (timeout_us > 10) ? 10 : timeout_us; + } + + return timeout_us ? 0 : -EBUSY; +} + +static int tg3_ape_wait_for_event(struct tg3 *tp, u32 timeout_us) +{ + u32 i, apedata; + + for (i = 0; i < timeout_us / 10; i++) { + apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); + + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + break; + + udelay(10); + } + + return i == timeout_us / 10; +} + +static int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off, + u32 len) +{ + int err; + u32 i, bufoff, msgoff, maxlen, apedata; + + if (!tg3_flag(tp, APE_HAS_NCSI)) + return 0; apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); if (apedata != APE_SEG_SIG_MAGIC) - return; + return -ENODEV; apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); if (!(apedata & APE_FW_STATUS_READY)) - return; + return -EAGAIN; - /* Wait for up to 1 millisecond for APE to service previous event. */ - for (i = 0; i < 10; i++) { - if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM)) - return; + bufoff = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_OFF) + + TG3_APE_SHMEM_BASE; + msgoff = bufoff + 2 * sizeof(u32); + maxlen = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_LEN); - apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); + while (len) { + u32 length; - if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) - tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, - event | APE_EVENT_STATUS_EVENT_PENDING); + /* Cap xfer sizes to scratchpad limits. */ + length = (len > maxlen) ? maxlen : len; + len -= length; + + apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); + if (!(apedata & APE_FW_STATUS_READY)) + return -EAGAIN; + + /* Wait for up to 1 msec for APE to service previous event. */ + err = tg3_ape_event_lock(tp, 1000); + if (err) + return err; + + apedata = APE_EVENT_STATUS_DRIVER_EVNT | + APE_EVENT_STATUS_SCRTCHPD_READ | + APE_EVENT_STATUS_EVENT_PENDING; + tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, apedata); + + tg3_ape_write32(tp, bufoff, base_off); + tg3_ape_write32(tp, bufoff + sizeof(u32), length); tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); + tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); - if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) - break; + base_off += length; - udelay(100); + if (tg3_ape_wait_for_event(tp, 30000)) + return -EAGAIN; + + for (i = 0; length; i += 4, length -= 4) { + u32 val = tg3_ape_read32(tp, msgoff + i); + memcpy(data, &val, sizeof(u32)); + data++; + } } - if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) - tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); + return 0; +} + +static int tg3_ape_send_event(struct tg3 *tp, u32 event) +{ + int err; + u32 apedata; + + apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); + if (apedata != APE_SEG_SIG_MAGIC) + return -EAGAIN; + + apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); + if (!(apedata & APE_FW_STATUS_READY)) + return -EAGAIN; + + /* Wait for up to 1 millisecond for APE to service previous event. */ + err = tg3_ape_event_lock(tp, 1000); + if (err) + return err; + + tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, + event | APE_EVENT_STATUS_EVENT_PENDING); + + tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); + tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); + + return 0; } static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) @@ -815,9 +976,6 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) event = APE_EVENT_STATUS_STATE_UNLOAD; break; - case RESET_KIND_SUSPEND: - event = APE_EVENT_STATUS_STATE_SUSPEND; - break; default: return; } @@ -879,8 +1037,13 @@ static inline unsigned int tg3_has_work(struct tg3_napi *tnapi) if (sblk->status & SD_STATUS_LINK_CHG) work_exists = 1; } - /* check for RX/TX work to do */ - if (sblk->idx[0].tx_consumer != tnapi->tx_cons || + + /* check for TX work to do */ + if (sblk->idx[0].tx_consumer != tnapi->tx_cons) + work_exists = 1; + + /* check for RX work to do */ + if (tnapi->rx_rcb_prod_idx && *(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr) work_exists = 1; @@ -943,7 +1106,8 @@ static void tg3_switch_clocks(struct tg3 *tp) #define PHY_BUSY_LOOPS 5000 -static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) +static int __tg3_readphy(struct tg3 *tp, unsigned int phy_addr, int reg, + u32 *val) { u32 frame_val; unsigned int loops; @@ -955,9 +1119,11 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) udelay(80); } + tg3_ape_lock(tp, tp->phy_ape_lock); + *val = 0x0; - frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) & + frame_val = ((phy_addr << MI_COM_PHY_ADDR_SHIFT) & MI_COM_PHY_ADDR_MASK); frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & MI_COM_REG_ADDR_MASK); @@ -989,10 +1155,18 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) udelay(80); } + tg3_ape_unlock(tp, tp->phy_ape_lock); + return ret; } -static int tg3_writephy(struct tg3 *tp, int reg, u32 val) +static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) +{ + return __tg3_readphy(tp, tp->phy_addr, reg, val); +} + +static int __tg3_writephy(struct tg3 *tp, unsigned int phy_addr, int reg, + u32 val) { u32 frame_val; unsigned int loops; @@ -1008,7 +1182,9 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) udelay(80); } - frame_val = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) & + tg3_ape_lock(tp, tp->phy_ape_lock); + + frame_val = ((phy_addr << MI_COM_PHY_ADDR_SHIFT) & MI_COM_PHY_ADDR_MASK); frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & MI_COM_REG_ADDR_MASK); @@ -1038,9 +1214,16 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) udelay(80); } + tg3_ape_unlock(tp, tp->phy_ape_lock); + return ret; } +static int tg3_writephy(struct tg3 *tp, int reg, u32 val) +{ + return __tg3_writephy(tp, tp->phy_addr, reg, val); +} + static int tg3_phy_cl45_write(struct tg3 *tp, u32 devad, u32 addr, u32 val) { int err; @@ -1130,14 +1313,32 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set) return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); } -#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ - MII_TG3_AUXCTL_ACTL_TX_6DB) +static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable) +{ + u32 val; + int err; -#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_TX_6DB); + err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); + + if (err) + return err; + + if (enable) + val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + else + val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + + err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, + val | MII_TG3_AUXCTL_ACTL_TX_6DB); + + return err; +} + +static int tg3_phy_shdw_write(struct tg3 *tp, int reg, u32 val) +{ + return tg3_writephy(tp, MII_TG3_MISC_SHDW, + reg | val | MII_TG3_MISC_SHDW_WREN); +} static int tg3_bmcr_reset(struct tg3 *tp) { @@ -1177,7 +1378,7 @@ static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg) spin_lock_bh(&tp->lock); - if (tg3_readphy(tp, reg, &val)) + if (__tg3_readphy(tp, mii_id, reg, &val)) val = -EIO; spin_unlock_bh(&tp->lock); @@ -1192,7 +1393,7 @@ static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val) spin_lock_bh(&tp->lock); - if (tg3_writephy(tp, reg, val)) + if (__tg3_writephy(tp, mii_id, reg, val)) ret = -EIO; spin_unlock_bh(&tp->lock); @@ -1200,17 +1401,12 @@ static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val) return ret; } -static int tg3_mdio_reset(struct mii_bus *bp) -{ - return 0; -} - static void tg3_mdio_config_5785(struct tg3 *tp) { u32 val; struct phy_device *phydev; - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) { case PHY_ID_BCM50610: case PHY_ID_BCM50610M: @@ -1293,7 +1489,7 @@ static void tg3_mdio_start(struct tg3 *tp) udelay(80); if (tg3_flag(tp, MDIOBUS_INITED) && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + tg3_asic_rev(tp) == ASIC_REV_5785) tg3_mdio_config_5785(tp); } @@ -1308,13 +1504,20 @@ static int tg3_mdio_init(struct tg3 *tp) tp->phy_addr = tp->pci_fn + 1; - if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) + if (tg3_chip_rev_id(tp) != CHIPREV_ID_5717_A0) is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES; else is_serdes = tr32(TG3_CPMU_PHY_STRAP) & TG3_CPMU_PHY_STRAP_IS_SERDES; if (is_serdes) tp->phy_addr += 7; + } else if (tg3_flag(tp, IS_SSB_CORE) && tg3_flag(tp, ROBOSWITCH)) { + int addr; + + addr = ssb_gige_get_phyaddr(tp->pdev); + if (addr < 0) + return addr; + tp->phy_addr = addr; } else tp->phy_addr = TG3_PHY_MII_ADDR; @@ -1334,8 +1537,7 @@ static int tg3_mdio_init(struct tg3 *tp) tp->mdio_bus->parent = &tp->pdev->dev; tp->mdio_bus->read = &tg3_mdio_read; tp->mdio_bus->write = &tg3_mdio_write; - tp->mdio_bus->reset = &tg3_mdio_reset; - tp->mdio_bus->phy_mask = ~(1 << TG3_PHY_MII_ADDR); + tp->mdio_bus->phy_mask = ~(1 << tp->phy_addr); tp->mdio_bus->irq = &tp->mdio_irq[0]; for (i = 0; i < PHY_MAX_ADDR; i++) @@ -1356,7 +1558,7 @@ static int tg3_mdio_init(struct tg3 *tp) return i; } - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; if (!phydev || !phydev->drv) { dev_warn(&tp->pdev->dev, "No PHY devices\n"); @@ -1396,7 +1598,7 @@ static int tg3_mdio_init(struct tg3 *tp) tg3_flag_set(tp, MDIOBUS_INITED); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + if (tg3_asic_rev(tp) == ASIC_REV_5785) tg3_mdio_config_5785(tp); return 0; @@ -1448,38 +1650,31 @@ static void tg3_wait_for_event_ack(struct tg3 *tp) for (i = 0; i < delay_cnt; i++) { if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT)) break; + if (pci_channel_offline(tp->pdev)) + break; + udelay(8); } } /* tp->lock is held. */ -static void tg3_ump_link_report(struct tg3 *tp) +static void tg3_phy_gather_ump_data(struct tg3 *tp, u32 *data) { - u32 reg; - u32 val; - - if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF)) - return; - - tg3_wait_for_event_ack(tp); - - tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE); - - tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14); + u32 reg, val; val = 0; if (!tg3_readphy(tp, MII_BMCR, ®)) val = reg << 16; if (!tg3_readphy(tp, MII_BMSR, ®)) val |= (reg & 0xffff); - tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val); + *data++ = val; val = 0; if (!tg3_readphy(tp, MII_ADVERTISE, ®)) val = reg << 16; if (!tg3_readphy(tp, MII_LPA, ®)) val |= (reg & 0xffff); - tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val); + *data++ = val; val = 0; if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) { @@ -1488,13 +1683,33 @@ static void tg3_ump_link_report(struct tg3 *tp) if (!tg3_readphy(tp, MII_STAT1000, ®)) val |= (reg & 0xffff); } - tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val); + *data++ = val; if (!tg3_readphy(tp, MII_PHYADDR, ®)) val = reg << 16; else val = 0; - tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val); + *data++ = val; +} + +/* tp->lock is held. */ +static void tg3_ump_link_report(struct tg3 *tp) +{ + u32 data[4]; + + if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF)) + return; + + tg3_phy_gather_ump_data(tp, data); + + tg3_wait_for_event_ack(tp); + + tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x0, data[0]); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x4, data[1]); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x8, data[2]); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0xc, data[3]); tg3_generate_fw_event(tp); } @@ -1542,10 +1757,6 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) break; } } - - if (kind == RESET_KIND_INIT || - kind == RESET_KIND_SUSPEND) - tg3_ape_driver_state_change(tp, kind); } /* tp->lock is held. */ @@ -1567,9 +1778,6 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind) break; } } - - if (kind == RESET_KIND_SHUTDOWN) - tg3_ape_driver_state_change(tp, kind); } /* tp->lock is held. */ @@ -1603,11 +1811,22 @@ static int tg3_poll_fw(struct tg3 *tp) int i; u32 val; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (tg3_flag(tp, NO_FWARE_REPORTED)) + return 0; + + if (tg3_flag(tp, IS_SSB_CORE)) { + /* We don't use firmware. */ + return 0; + } + + if (tg3_asic_rev(tp) == ASIC_REV_5906) { /* Wait up to 20ms for init done. */ for (i = 0; i < 200; i++) { if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE) return 0; + if (pci_channel_offline(tp->pdev)) + return -ENODEV; + udelay(100); } return -ENODEV; @@ -1618,6 +1837,15 @@ static int tg3_poll_fw(struct tg3 *tp) tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) break; + if (pci_channel_offline(tp->pdev)) { + if (!tg3_flag(tp, NO_FWARE_REPORTED)) { + tg3_flag_set(tp, NO_FWARE_REPORTED); + netdev_info(tp->dev, "No firmware running\n"); + } + + break; + } + udelay(10); } @@ -1632,7 +1860,7 @@ static int tg3_poll_fw(struct tg3 *tp) netdev_info(tp->dev, "No firmware running\n"); } - if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) { + if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0) { /* The 57765 A0 needs a little more * time to do some important work. */ @@ -1668,6 +1896,22 @@ static void tg3_link_report(struct tg3 *tp) tg3_ump_link_report(tp); } + + tp->link_up = netif_carrier_ok(tp->dev); +} + +static u32 tg3_decode_flowctrl_1000T(u32 adv) +{ + u32 flowctrl = 0; + + if (adv & ADVERTISE_PAUSE_CAP) { + flowctrl |= FLOW_CTRL_RX; + if (!(adv & ADVERTISE_PAUSE_ASYM)) + flowctrl |= FLOW_CTRL_TX; + } else if (adv & ADVERTISE_PAUSE_ASYM) + flowctrl |= FLOW_CTRL_TX; + + return flowctrl; } static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) @@ -1686,6 +1930,20 @@ static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) return miireg; } +static u32 tg3_decode_flowctrl_1000X(u32 adv) +{ + u32 flowctrl = 0; + + if (adv & ADVERTISE_1000XPAUSE) { + flowctrl |= FLOW_CTRL_RX; + if (!(adv & ADVERTISE_1000XPSE_ASYM)) + flowctrl |= FLOW_CTRL_TX; + } else if (adv & ADVERTISE_1000XPSE_ASYM) + flowctrl |= FLOW_CTRL_TX; + + return flowctrl; +} + static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv) { u8 cap = 0; @@ -1710,7 +1968,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv) u32 old_tx_mode = tp->tx_mode; if (tg3_flag(tp, USE_PHYLIB)) - autoneg = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]->autoneg; + autoneg = tp->mdio_bus->phy_map[tp->phy_addr]->autoneg; else autoneg = tp->link_config.autoneg; @@ -1746,7 +2004,7 @@ static void tg3_adjust_link(struct net_device *dev) u8 oldflowctrl, linkmesg = 0; u32 mac_mode, lcl_adv, rmt_adv; struct tg3 *tp = netdev_priv(dev); - struct phy_device *phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + struct phy_device *phydev = tp->mdio_bus->phy_map[tp->phy_addr]; spin_lock_bh(&tp->lock); @@ -1762,7 +2020,7 @@ static void tg3_adjust_link(struct net_device *dev) if (phydev->speed == SPEED_100 || phydev->speed == SPEED_10) mac_mode |= MAC_MODE_PORT_MODE_MII; else if (phydev->speed == SPEED_1000 || - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) + tg3_asic_rev(tp) != ASIC_REV_5785) mac_mode |= MAC_MODE_PORT_MODE_GMII; else mac_mode |= MAC_MODE_PORT_MODE_MII; @@ -1789,7 +2047,7 @@ static void tg3_adjust_link(struct net_device *dev) udelay(40); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { + if (tg3_asic_rev(tp) == ASIC_REV_5785) { if (phydev->speed == SPEED_10) tw32(MAC_MI_STAT, MAC_MI_STAT_10MBPS_MODE | @@ -1809,13 +2067,13 @@ static void tg3_adjust_link(struct net_device *dev) (6 << TX_LENGTHS_IPG_SHIFT) | (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); - if ((phydev->link && tp->link_config.active_speed == SPEED_INVALID) || - (!phydev->link && tp->link_config.active_speed != SPEED_INVALID) || + if (phydev->link != tp->old_link || phydev->speed != tp->link_config.active_speed || phydev->duplex != tp->link_config.active_duplex || oldflowctrl != tp->link_config.active_flowctrl) linkmesg = 1; + tp->old_link = phydev->link; tp->link_config.active_speed = phydev->speed; tp->link_config.active_duplex = phydev->duplex; @@ -1835,11 +2093,11 @@ static int tg3_phy_init(struct tg3 *tp) /* Bring the PHY back to a known state. */ tg3_bmcr_reset(tp); - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; /* Attach the MAC to the PHY. */ - phydev = phy_connect(tp->dev, dev_name(&phydev->dev), tg3_adjust_link, - phydev->dev_flags, phydev->interface); + phydev = phy_connect(tp->dev, dev_name(&phydev->dev), + tg3_adjust_link, phydev->interface); if (IS_ERR(phydev)) { dev_err(&tp->pdev->dev, "Could not attach to PHY\n"); return PTR_ERR(phydev); @@ -1862,7 +2120,7 @@ static int tg3_phy_init(struct tg3 *tp) SUPPORTED_Asym_Pause); break; default: - phy_disconnect(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]); + phy_disconnect(tp->mdio_bus->phy_map[tp->phy_addr]); return -EINVAL; } @@ -1880,14 +2138,14 @@ static void tg3_phy_start(struct tg3 *tp) if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return; - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER; - phydev->speed = tp->link_config.orig_speed; - phydev->duplex = tp->link_config.orig_duplex; - phydev->autoneg = tp->link_config.orig_autoneg; - phydev->advertising = tp->link_config.orig_advertising; + phydev->speed = tp->link_config.speed; + phydev->duplex = tp->link_config.duplex; + phydev->autoneg = tp->link_config.autoneg; + phydev->advertising = tp->link_config.advertising; } phy_start(phydev); @@ -1900,13 +2158,13 @@ static void tg3_phy_stop(struct tg3 *tp) if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return; - phy_stop(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]); + phy_stop(tp->mdio_bus->phy_map[tp->phy_addr]); } static void tg3_phy_fini(struct tg3 *tp) { if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) { - phy_disconnect(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]); + phy_disconnect(tp->mdio_bus->phy_map[tp->phy_addr]); tp->phy_flags &= ~TG3_PHYFLG_IS_CONNECTED; } } @@ -1975,28 +2233,24 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable) return; } - reg = MII_TG3_MISC_SHDW_WREN | - MII_TG3_MISC_SHDW_SCR5_SEL | - MII_TG3_MISC_SHDW_SCR5_LPED | + reg = MII_TG3_MISC_SHDW_SCR5_LPED | MII_TG3_MISC_SHDW_SCR5_DLPTLM | MII_TG3_MISC_SHDW_SCR5_SDTL | MII_TG3_MISC_SHDW_SCR5_C125OE; - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 || !enable) + if (tg3_asic_rev(tp) != ASIC_REV_5784 || !enable) reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD; - tg3_writephy(tp, MII_TG3_MISC_SHDW, reg); + tg3_phy_shdw_write(tp, MII_TG3_MISC_SHDW_SCR5_SEL, reg); - reg = MII_TG3_MISC_SHDW_WREN | - MII_TG3_MISC_SHDW_APD_SEL | - MII_TG3_MISC_SHDW_APD_WKTM_84MS; + reg = MII_TG3_MISC_SHDW_APD_WKTM_84MS; if (enable) reg |= MII_TG3_MISC_SHDW_APD_ENABLE; - tg3_writephy(tp, MII_TG3_MISC_SHDW, reg); + tg3_phy_shdw_write(tp, MII_TG3_MISC_SHDW_APD_SEL, reg); } -static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) +static void tg3_phy_toggle_automdix(struct tg3 *tp, bool enable) { u32 phy; @@ -2060,7 +2314,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) otp = tp->phy_otp; - if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) + if (tg3_phy_toggle_auxctl_smdsp(tp, true)) return; phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); @@ -2085,10 +2339,50 @@ static void tg3_phy_apply_otp(struct tg3 *tp) ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); +} + +static void tg3_eee_pull_config(struct tg3 *tp, struct ethtool_eee *eee) +{ + u32 val; + struct ethtool_eee *dest = &tp->eee; + + if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) + return; + + if (eee) + dest = eee; + + if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, TG3_CL45_D7_EEERES_STAT, &val)) + return; + + /* Pull eee_active */ + if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T || + val == TG3_CL45_D7_EEERES_STAT_LP_100TX) { + dest->eee_active = 1; + } else + dest->eee_active = 0; + + /* Pull lp advertised settings */ + if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE, &val)) + return; + dest->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val); + + /* Pull advertised and eee_enabled settings */ + if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &val)) + return; + dest->eee_enabled = !!val; + dest->advertised = mmd_eee_adv_to_ethtool_adv_t(val); + + /* Pull tx_lpi_enabled */ + val = tr32(TG3_CPMU_EEE_MODE); + dest->tx_lpi_enabled = !!(val & TG3_CPMU_EEEMD_LPI_IN_TX); + + /* Pull lpi timer value */ + dest->tx_lpi_timer = tr32(TG3_CPMU_EEE_DBTMR1) & 0xffff; } -static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) +static void tg3_phy_eee_adjust(struct tg3 *tp, bool current_link_up) { u32 val; @@ -2098,7 +2392,7 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) tp->setlpicnt = 0; if (tp->link_config.autoneg == AUTONEG_ENABLE && - current_link_up == 1 && + current_link_up && tp->link_config.active_duplex == DUPLEX_FULL && (tp->link_config.active_speed == SPEED_100 || tp->link_config.active_speed == SPEED_1000)) { @@ -2111,19 +2405,16 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) tw32(TG3_CPMU_EEE_CTRL, eeectl); - tg3_phy_cl45_read(tp, MDIO_MMD_AN, - TG3_CL45_D7_EEERES_STAT, &val); - - if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T || - val == TG3_CL45_D7_EEERES_STAT_LP_100TX) + tg3_eee_pull_config(tp, NULL); + if (tp->eee.eee_active) tp->setlpicnt = 2; } if (!tp->setlpicnt) { - if (current_link_up == 1 && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (current_link_up && + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2136,14 +2427,14 @@ static void tg3_phy_eee_enable(struct tg3 *tp) u32 val; if (tp->link_config.active_speed == SPEED_1000 && - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719 || tg3_flag(tp, 57765_CLASS)) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { val = MII_TG3_DSP_TAP26_ALNOKO | MII_TG3_DSP_TAP26_RMRXSTO; tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2287,7 +2578,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_CTRL1000, CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (err) return err; @@ -2308,17 +2599,31 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); tg3_writephy(tp, MII_CTRL1000, phy9_orig); - if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) { - reg32 &= ~0x3000; - tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); - } else if (!err) - err = -EBUSY; + err = tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); + if (err) + return err; - return err; + reg32 &= ~0x3000; + tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); + + return 0; +} + +static void tg3_carrier_off(struct tg3 *tp) +{ + netif_carrier_off(tp->dev); + tp->link_up = false; +} + +static void tg3_warn_mgmt_link_flap(struct tg3 *tp) +{ + if (tg3_flag(tp, ENABLE_ASF)) + netdev_warn(tp->dev, + "Management side-band traffic will be interrupted during phy settings change\n"); } /* This will reset the tigon3 PHY if there is no valid @@ -2329,7 +2634,7 @@ static int tg3_phy_reset(struct tg3 *tp) u32 val, cpmuctrl; int err; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (tg3_asic_rev(tp) == ASIC_REV_5906) { val = tr32(GRC_MISC_CFG); tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ); udelay(40); @@ -2339,14 +2644,14 @@ static int tg3_phy_reset(struct tg3 *tp) if (err != 0) return -EBUSY; - if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) { + if (netif_running(tp->dev) && tp->link_up) { 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) { + if (tg3_asic_rev(tp) == ASIC_REV_5703 || + tg3_asic_rev(tp) == ASIC_REV_5704 || + tg3_asic_rev(tp) == ASIC_REV_5705) { err = tg3_phy_reset_5703_4_5(tp); if (err) return err; @@ -2354,8 +2659,8 @@ static int tg3_phy_reset(struct tg3 *tp) } cpmuctrl = 0; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && - GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) { + if (tg3_asic_rev(tp) == ASIC_REV_5784 && + tg3_chip_rev(tp) != CHIPREV_5784_AX) { cpmuctrl = tr32(TG3_CPMU_CTRL); if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) tw32(TG3_CPMU_CTRL, @@ -2373,8 +2678,8 @@ static int tg3_phy_reset(struct tg3 *tp) tw32(TG3_CPMU_CTRL, cpmuctrl); } - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX || - GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) { + if (tg3_chip_rev(tp) == CHIPREV_5784_AX || + tg3_chip_rev(tp) == CHIPREV_5761_AX) { val = tr32(TG3_CPMU_LSPD_1000MB_CLK); if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) == CPMU_LSPD_1000MB_MACCLK_12_5) { @@ -2397,10 +2702,10 @@ static int tg3_phy_reset(struct tg3 *tp) out: if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x201f, 0x2aaa); tg3_phydsp_write(tp, 0x000a, 0x0323); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { @@ -2409,14 +2714,14 @@ out: } if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x000a, 0x310b); tg3_phydsp_write(tp, 0x201f, 0x9506); tg3_phydsp_write(tp, 0x401f, 0x14e2); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); @@ -2425,7 +2730,7 @@ out: } else tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } @@ -2452,12 +2757,15 @@ out: val | MII_TG3_EXT_CTRL_FIFO_ELASTIC); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (tg3_asic_rev(tp) == ASIC_REV_5906) { /* adjust output voltage */ tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12); } - tg3_phy_toggle_automdix(tp, 1); + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5762_A0) + tg3_phydsp_write(tp, 0xffb, 0x4000); + + tg3_phy_toggle_automdix(tp, true); tg3_phy_set_wirespeed(tp); return 0; } @@ -2482,8 +2790,8 @@ static inline u32 tg3_set_function_status(struct tg3 *tp, u32 newstat) { u32 status, shift; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719) status = tg3_ape_read32(tp, TG3_APE_GPIO_MSG); else status = tr32(TG3_CPMU_DRV_STATUS); @@ -2492,8 +2800,8 @@ static inline u32 tg3_set_function_status(struct tg3 *tp, u32 newstat) status &= ~(TG3_GPIO_MSG_MASK << shift); status |= (newstat << shift); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719) tg3_ape_write32(tp, TG3_APE_GPIO_MSG, status); else tw32(TG3_CPMU_DRV_STATUS, status); @@ -2506,9 +2814,9 @@ static inline int tg3_pwrsrc_switch_to_vmain(struct tg3 *tp) if (!tg3_flag(tp, IS_NIC)) return 0; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720) { if (tg3_ape_lock(tp, TG3_APE_LOCK_GPIO)) return -EIO; @@ -2531,8 +2839,8 @@ static void tg3_pwrsrc_die_with_vmain(struct tg3 *tp) u32 grc_local_ctrl; if (!tg3_flag(tp, IS_NIC) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) + tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701) return; grc_local_ctrl = tp->grc_local_ctrl | GRC_LCLCTRL_GPIO_OE1; @@ -2555,8 +2863,8 @@ static void tg3_pwrsrc_switch_to_vaux(struct tg3 *tp) if (!tg3_flag(tp, IS_NIC)) return; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { + if (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701) { tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | @@ -2588,7 +2896,7 @@ static void tg3_pwrsrc_switch_to_vaux(struct tg3 *tp) u32 grc_local_ctrl = 0; /* Workaround to prevent overdrawing Amps. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { + if (tg3_asic_rev(tp) == ASIC_REV_5714) { grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | grc_local_ctrl, @@ -2660,9 +2968,9 @@ static void tg3_frob_aux_power(struct tg3 *tp, bool include_wol) if (!tg3_flag(tp, IS_NIC) || tg3_flag(tp, 57765_CLASS)) return; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720) { tg3_frob_aux_power_5717(tp, include_wol ? tg3_flag(tp, WOL_ENABLE) != 0 : 0); return; @@ -2709,15 +3017,54 @@ static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed) return 0; } -static int tg3_setup_phy(struct tg3 *, int); -static int tg3_halt_cpu(struct tg3 *, u32); +static bool tg3_phy_power_bug(struct tg3 *tp) +{ + switch (tg3_asic_rev(tp)) { + case ASIC_REV_5700: + case ASIC_REV_5704: + return true; + case ASIC_REV_5780: + if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) + return true; + return false; + case ASIC_REV_5717: + if (!tp->pci_fn) + return true; + return false; + case ASIC_REV_5719: + case ASIC_REV_5720: + if ((tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && + !tp->pci_fn) + return true; + return false; + } + + return false; +} + +static bool tg3_phy_led_bug(struct tg3 *tp) +{ + switch (tg3_asic_rev(tp)) { + case ASIC_REV_5719: + case ASIC_REV_5720: + if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && + !tp->pci_fn) + return true; + return false; + } + + return false; +} static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) { u32 val; + if (tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) + return; + if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { + if (tg3_asic_rev(tp) == ASIC_REV_5704) { u32 sg_dig_ctrl = tr32(SG_DIG_CTRL); u32 serdes_cfg = tr32(MAC_SERDES_CFG); @@ -2729,7 +3076,7 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) return; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (tg3_asic_rev(tp) == ASIC_REV_5906) { tg3_bmcr_reset(tp); val = tr32(GRC_MISC_CFG); tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); @@ -2756,8 +3103,9 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) } return; } else if (do_low_power) { - tg3_writephy(tp, MII_TG3_EXT_CTRL, - MII_TG3_EXT_CTRL_FORCE_LED_OFF); + if (!tg3_phy_led_bug(tp)) + tg3_writephy(tp, MII_TG3_EXT_CTRL, + MII_TG3_EXT_CTRL_FORCE_LED_OFF); val = MII_TG3_AUXCTL_PCTL_100TX_LPWR | MII_TG3_AUXCTL_PCTL_SPR_ISOLATE | @@ -2768,14 +3116,11 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) /* 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->phy_flags & TG3_PHYFLG_MII_SERDES))) + if (tg3_phy_power_bug(tp)) return; - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX || - GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) { + if (tg3_chip_rev(tp) == CHIPREV_5784_AX || + tg3_chip_rev(tp) == CHIPREV_5761_AX) { val = tr32(TG3_CPMU_LSPD_1000MB_CLK); val &= ~CPMU_LSPD_1000MB_MACCLK_MASK; val |= CPMU_LSPD_1000MB_MACCLK_12_5; @@ -2879,7 +3224,7 @@ static int tg3_nvram_read_using_eeprom(struct tg3 *tp, return 0; } -#define NVRAM_CMD_TIMEOUT 10000 +#define NVRAM_CMD_TIMEOUT 5000 static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd) { @@ -2887,7 +3232,7 @@ static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd) tw32(NVRAM_CMD, nvram_cmd); for (i = 0; i < NVRAM_CMD_TIMEOUT; i++) { - udelay(10); + usleep_range(10, 40); if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) { udelay(10); break; @@ -2978,47 +3323,342 @@ static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, __be32 *val) return res; } +static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, + u32 offset, u32 len, u8 *buf) +{ + int i, j, rc = 0; + u32 val; + + for (i = 0; i < len; i += 4) { + u32 addr; + __be32 data; + + addr = offset + i; + + memcpy(&data, buf + i, 4); + + /* + * The SEEPROM interface expects the data to always be opposite + * the native endian format. We accomplish this by reversing + * all the operations that would have been performed on the + * data from a call to tg3_nvram_read_be32(). + */ + tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data))); + + val = tr32(GRC_EEPROM_ADDR); + tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); + + val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | + EEPROM_ADDR_READ); + tw32(GRC_EEPROM_ADDR, val | + (0 << EEPROM_ADDR_DEVID_SHIFT) | + (addr & EEPROM_ADDR_ADDR_MASK) | + EEPROM_ADDR_START | + EEPROM_ADDR_WRITE); + + for (j = 0; j < 1000; j++) { + val = tr32(GRC_EEPROM_ADDR); + + if (val & EEPROM_ADDR_COMPLETE) + break; + msleep(1); + } + if (!(val & EEPROM_ADDR_COMPLETE)) { + rc = -EBUSY; + break; + } + } + + return rc; +} + +/* offset and length are dword aligned */ +static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, + u8 *buf) +{ + int ret = 0; + u32 pagesize = tp->nvram_pagesize; + u32 pagemask = pagesize - 1; + u32 nvram_cmd; + u8 *tmp; + + tmp = kmalloc(pagesize, GFP_KERNEL); + if (tmp == NULL) + return -ENOMEM; + + while (len) { + int j; + u32 phy_addr, page_off, size; + + phy_addr = offset & ~pagemask; + + for (j = 0; j < pagesize; j += 4) { + ret = tg3_nvram_read_be32(tp, phy_addr + j, + (__be32 *) (tmp + j)); + if (ret) + break; + } + if (ret) + break; + + page_off = offset & pagemask; + size = pagesize; + if (len < size) + size = len; + + len -= size; + + memcpy(tmp + page_off, buf, size); + + offset = offset + (pagesize - page_off); + + tg3_enable_nvram_access(tp); + + /* + * Before we can erase the flash page, we need + * to issue a special "write enable" command. + */ + nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; + + if (tg3_nvram_exec_cmd(tp, nvram_cmd)) + break; + + /* Erase the target page */ + tw32(NVRAM_ADDR, phy_addr); + + nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | + NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; + + if (tg3_nvram_exec_cmd(tp, nvram_cmd)) + break; + + /* Issue another write enable to start the write. */ + nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; + + if (tg3_nvram_exec_cmd(tp, nvram_cmd)) + break; + + for (j = 0; j < pagesize; j += 4) { + __be32 data; + + data = *((__be32 *) (tmp + j)); + + tw32(NVRAM_WRDATA, be32_to_cpu(data)); + + tw32(NVRAM_ADDR, phy_addr + j); + + nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | + NVRAM_CMD_WR; + + if (j == 0) + nvram_cmd |= NVRAM_CMD_FIRST; + else if (j == (pagesize - 4)) + nvram_cmd |= NVRAM_CMD_LAST; + + ret = tg3_nvram_exec_cmd(tp, nvram_cmd); + if (ret) + break; + } + if (ret) + break; + } + + nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; + tg3_nvram_exec_cmd(tp, nvram_cmd); + + kfree(tmp); + + return ret; +} + +/* offset and length are dword aligned */ +static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, + u8 *buf) +{ + int i, ret = 0; + + for (i = 0; i < len; i += 4, offset += 4) { + u32 page_off, phy_addr, nvram_cmd; + __be32 data; + + memcpy(&data, buf + i, 4); + tw32(NVRAM_WRDATA, be32_to_cpu(data)); + + page_off = offset % tp->nvram_pagesize; + + phy_addr = tg3_nvram_phys_addr(tp, offset); + + nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; + + if (page_off == 0 || i == 0) + nvram_cmd |= NVRAM_CMD_FIRST; + if (page_off == (tp->nvram_pagesize - 4)) + nvram_cmd |= NVRAM_CMD_LAST; + + if (i == (len - 4)) + nvram_cmd |= NVRAM_CMD_LAST; + + if ((nvram_cmd & NVRAM_CMD_FIRST) || + !tg3_flag(tp, FLASH) || + !tg3_flag(tp, 57765_PLUS)) + tw32(NVRAM_ADDR, phy_addr); + + if (tg3_asic_rev(tp) != ASIC_REV_5752 && + !tg3_flag(tp, 5755_PLUS) && + (tp->nvram_jedecnum == JEDEC_ST) && + (nvram_cmd & NVRAM_CMD_FIRST)) { + u32 cmd; + + cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; + ret = tg3_nvram_exec_cmd(tp, cmd); + if (ret) + break; + } + if (!tg3_flag(tp, FLASH)) { + /* We always do complete word writes to eeprom. */ + nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); + } + + ret = tg3_nvram_exec_cmd(tp, nvram_cmd); + if (ret) + break; + } + return ret; +} + +/* offset and length are dword aligned */ +static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) +{ + int ret; + + if (tg3_flag(tp, EEPROM_WRITE_PROT)) { + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & + ~GRC_LCLCTRL_GPIO_OUTPUT1); + udelay(40); + } + + if (!tg3_flag(tp, NVRAM)) { + ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); + } else { + u32 grc_mode; + + ret = tg3_nvram_lock(tp); + if (ret) + return ret; + + tg3_enable_nvram_access(tp); + if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) + tw32(NVRAM_WRITE1, 0x406); + + grc_mode = tr32(GRC_MODE); + tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); + + if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) { + ret = tg3_nvram_write_block_buffered(tp, offset, len, + buf); + } else { + ret = tg3_nvram_write_block_unbuffered(tp, offset, len, + buf); + } + + grc_mode = tr32(GRC_MODE); + tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); + + tg3_disable_nvram_access(tp); + tg3_nvram_unlock(tp); + } + + if (tg3_flag(tp, EEPROM_WRITE_PROT)) { + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); + udelay(40); + } + + return ret; +} + #define RX_CPU_SCRATCH_BASE 0x30000 #define RX_CPU_SCRATCH_SIZE 0x04000 #define TX_CPU_SCRATCH_BASE 0x34000 #define TX_CPU_SCRATCH_SIZE 0x04000 /* tp->lock is held. */ -static int tg3_halt_cpu(struct tg3 *tp, u32 offset) +static int tg3_pause_cpu(struct tg3 *tp, u32 cpu_base) { int i; + const int iters = 10000; + + for (i = 0; i < iters; i++) { + tw32(cpu_base + CPU_STATE, 0xffffffff); + tw32(cpu_base + CPU_MODE, CPU_MODE_HALT); + if (tr32(cpu_base + CPU_MODE) & CPU_MODE_HALT) + break; + if (pci_channel_offline(tp->pdev)) + return -EBUSY; + } + + return (i == iters) ? -EBUSY : 0; +} + +/* tp->lock is held. */ +static int tg3_rxcpu_pause(struct tg3 *tp) +{ + int rc = tg3_pause_cpu(tp, RX_CPU_BASE); + + tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); + tw32_f(RX_CPU_BASE + CPU_MODE, CPU_MODE_HALT); + udelay(10); + + return rc; +} + +/* tp->lock is held. */ +static int tg3_txcpu_pause(struct tg3 *tp) +{ + return tg3_pause_cpu(tp, TX_CPU_BASE); +} - BUG_ON(offset == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)); +/* tp->lock is held. */ +static void tg3_resume_cpu(struct tg3 *tp, u32 cpu_base) +{ + tw32(cpu_base + CPU_STATE, 0xffffffff); + tw32_f(cpu_base + CPU_MODE, 0x00000000); +} - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { +/* tp->lock is held. */ +static void tg3_rxcpu_resume(struct tg3 *tp) +{ + tg3_resume_cpu(tp, RX_CPU_BASE); +} + +/* tp->lock is held. */ +static int tg3_halt_cpu(struct tg3 *tp, u32 cpu_base) +{ + int rc; + + BUG_ON(cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)); + + if (tg3_asic_rev(tp) == 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); - tw32(offset + CPU_MODE, CPU_MODE_HALT); - if (tr32(offset + CPU_MODE) & CPU_MODE_HALT) - break; - } - - tw32(offset + CPU_STATE, 0xffffffff); - tw32_f(offset + CPU_MODE, CPU_MODE_HALT); - udelay(10); + if (cpu_base == RX_CPU_BASE) { + rc = tg3_rxcpu_pause(tp); } else { - for (i = 0; i < 10000; i++) { - tw32(offset + CPU_STATE, 0xffffffff); - tw32(offset + CPU_MODE, CPU_MODE_HALT); - if (tr32(offset + CPU_MODE) & CPU_MODE_HALT) - break; - } + /* + * There is only an Rx CPU for the 5750 derivative in the + * BCM4785. + */ + if (tg3_flag(tp, IS_SSB_CORE)) + return 0; + + rc = tg3_txcpu_pause(tp); } - if (i >= 10000) { + if (rc) { netdev_err(tp->dev, "%s timed out, %s CPU\n", - __func__, offset == RX_CPU_BASE ? "RX" : "TX"); + __func__, cpu_base == RX_CPU_BASE ? "RX" : "TX"); return -ENODEV; } @@ -3028,19 +3668,41 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) return 0; } -struct fw_info { - unsigned int fw_base; - unsigned int fw_len; - const __be32 *fw_data; -}; +static int tg3_fw_data_len(struct tg3 *tp, + const struct tg3_firmware_hdr *fw_hdr) +{ + int fw_len; + + /* Non fragmented firmware have one firmware header followed by a + * contiguous chunk of data to be written. The length field in that + * header is not the length of data to be written but the complete + * length of the bss. The data length is determined based on + * tp->fw->size minus headers. + * + * Fragmented firmware have a main header followed by multiple + * fragments. Each fragment is identical to non fragmented firmware + * with a firmware header followed by a contiguous chunk of data. In + * the main header, the length field is unused and set to 0xffffffff. + * In each fragment header the length is the entire size of that + * fragment i.e. fragment data + header length. Data length is + * therefore length field in the header minus TG3_FW_HDR_LEN. + */ + if (tp->fw_len == 0xffffffff) + fw_len = be32_to_cpu(fw_hdr->len); + else + fw_len = tp->fw->size; + + return (fw_len - TG3_FW_HDR_LEN) / sizeof(u32); +} /* tp->lock is held. */ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base, int cpu_scratch_size, - struct fw_info *info) + const struct tg3_firmware_hdr *fw_hdr) { - int err, lock_err, i; + int err, i; void (*write_op)(struct tg3 *, u32, u32); + int total_len = tp->fw->size; if (cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)) { netdev_err(tp->dev, @@ -3049,30 +3711,49 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, return -EINVAL; } - if (tg3_flag(tp, 5705_PLUS)) + if (tg3_flag(tp, 5705_PLUS) && tg3_asic_rev(tp) != ASIC_REV_57766) write_op = tg3_write_mem; else write_op = tg3_write_indirect_reg32; - /* It is possible that bootcode is still loading at this point. - * Get the nvram lock first before halting the cpu. - */ - lock_err = tg3_nvram_lock(tp); - err = tg3_halt_cpu(tp, cpu_base); - if (!lock_err) - tg3_nvram_unlock(tp); - if (err) - goto out; + if (tg3_asic_rev(tp) != ASIC_REV_57766) { + /* It is possible that bootcode is still loading at this point. + * Get the nvram lock first before halting the cpu. + */ + int lock_err = tg3_nvram_lock(tp); + err = tg3_halt_cpu(tp, cpu_base); + if (!lock_err) + tg3_nvram_unlock(tp); + if (err) + goto out; - for (i = 0; i < cpu_scratch_size; i += sizeof(u32)) - write_op(tp, cpu_scratch_base + i, 0); - tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT); - for (i = 0; i < (info->fw_len / sizeof(u32)); i++) - write_op(tp, (cpu_scratch_base + - (info->fw_base & 0xffff) + - (i * sizeof(u32))), - be32_to_cpu(info->fw_data[i])); + for (i = 0; i < cpu_scratch_size; i += sizeof(u32)) + write_op(tp, cpu_scratch_base + i, 0); + tw32(cpu_base + CPU_STATE, 0xffffffff); + tw32(cpu_base + CPU_MODE, + tr32(cpu_base + CPU_MODE) | CPU_MODE_HALT); + } else { + /* Subtract additional main header for fragmented firmware and + * advance to the first fragment + */ + total_len -= TG3_FW_HDR_LEN; + fw_hdr++; + } + + do { + u32 *fw_data = (u32 *)(fw_hdr + 1); + for (i = 0; i < tg3_fw_data_len(tp, fw_hdr); i++) + write_op(tp, cpu_scratch_base + + (be32_to_cpu(fw_hdr->base_addr) & 0xffff) + + (i * sizeof(u32)), + be32_to_cpu(fw_data[i])); + + total_len -= be32_to_cpu(fw_hdr->len); + + /* Advance to next fragment */ + fw_hdr = (struct tg3_firmware_hdr *) + ((void *)fw_hdr + be32_to_cpu(fw_hdr->len)); + } while (total_len > 0); err = 0; @@ -3081,13 +3762,33 @@ out: } /* tp->lock is held. */ +static int tg3_pause_cpu_and_set_pc(struct tg3 *tp, u32 cpu_base, u32 pc) +{ + int i; + const int iters = 5; + + tw32(cpu_base + CPU_STATE, 0xffffffff); + tw32_f(cpu_base + CPU_PC, pc); + + for (i = 0; i < iters; i++) { + if (tr32(cpu_base + CPU_PC) == pc) + break; + tw32(cpu_base + CPU_STATE, 0xffffffff); + tw32(cpu_base + CPU_MODE, CPU_MODE_HALT); + tw32_f(cpu_base + CPU_PC, pc); + udelay(1000); + } + + return (i == iters) ? -EBUSY : 0; +} + +/* tp->lock is held. */ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) { - struct fw_info info; - const __be32 *fw_data; - int err, i; + const struct tg3_firmware_hdr *fw_hdr; + int err; - fw_data = (void *)tp->fw->data; + fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data; /* Firmware blob starts with version numbers, followed by start address and length. We are setting complete length. @@ -3095,60 +3796,117 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) Remainder is the blob to be loaded contiguously from start address. */ - info.fw_base = be32_to_cpu(fw_data[1]); - info.fw_len = tp->fw->size - 12; - info.fw_data = &fw_data[3]; - err = tg3_load_firmware_cpu(tp, RX_CPU_BASE, RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE, - &info); + fw_hdr); if (err) return err; err = tg3_load_firmware_cpu(tp, TX_CPU_BASE, TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE, - &info); + fw_hdr); if (err) return err; /* Now startup only the RX cpu. */ - tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base); - - for (i = 0; i < 5; i++) { - if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base) - break; - tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32(RX_CPU_BASE + CPU_MODE, CPU_MODE_HALT); - tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base); - udelay(1000); - } - if (i >= 5) { + err = tg3_pause_cpu_and_set_pc(tp, RX_CPU_BASE, + be32_to_cpu(fw_hdr->base_addr)); + if (err) { netdev_err(tp->dev, "%s fails to set RX CPU PC, is %08x " "should be %08x\n", __func__, - tr32(RX_CPU_BASE + CPU_PC), info.fw_base); + tr32(RX_CPU_BASE + CPU_PC), + be32_to_cpu(fw_hdr->base_addr)); return -ENODEV; } - tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32_f(RX_CPU_BASE + CPU_MODE, 0x00000000); + + tg3_rxcpu_resume(tp); + + return 0; +} + +static int tg3_validate_rxcpu_state(struct tg3 *tp) +{ + const int iters = 1000; + int i; + u32 val; + + /* Wait for boot code to complete initialization and enter service + * loop. It is then safe to download service patches + */ + for (i = 0; i < iters; i++) { + if (tr32(RX_CPU_HWBKPT) == TG3_SBROM_IN_SERVICE_LOOP) + break; + + udelay(10); + } + + if (i == iters) { + netdev_err(tp->dev, "Boot code not ready for service patches\n"); + return -EBUSY; + } + + val = tg3_read_indirect_reg32(tp, TG3_57766_FW_HANDSHAKE); + if (val & 0xff) { + netdev_warn(tp->dev, + "Other patches exist. Not downloading EEE patch\n"); + return -EEXIST; + } return 0; } /* tp->lock is held. */ +static void tg3_load_57766_firmware(struct tg3 *tp) +{ + struct tg3_firmware_hdr *fw_hdr; + + if (!tg3_flag(tp, NO_NVRAM)) + return; + + if (tg3_validate_rxcpu_state(tp)) + return; + + if (!tp->fw) + return; + + /* This firmware blob has a different format than older firmware + * releases as given below. The main difference is we have fragmented + * data to be written to non-contiguous locations. + * + * In the beginning we have a firmware header identical to other + * firmware which consists of version, base addr and length. The length + * here is unused and set to 0xffffffff. + * + * This is followed by a series of firmware fragments which are + * individually identical to previous firmware. i.e. they have the + * firmware header and followed by data for that fragment. The version + * field of the individual fragment header is unused. + */ + + fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data; + if (be32_to_cpu(fw_hdr->base_addr) != TG3_57766_FW_BASE_ADDR) + return; + + if (tg3_rxcpu_pause(tp)) + return; + + /* tg3_load_firmware_cpu() will always succeed for the 57766 */ + tg3_load_firmware_cpu(tp, 0, TG3_57766_FW_BASE_ADDR, 0, fw_hdr); + + tg3_rxcpu_resume(tp); +} + +/* tp->lock is held. */ static int tg3_load_tso_firmware(struct tg3 *tp) { - struct fw_info info; - const __be32 *fw_data; + const struct tg3_firmware_hdr *fw_hdr; unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; - int err, i; + int err; - if (tg3_flag(tp, HW_TSO_1) || - tg3_flag(tp, HW_TSO_2) || - tg3_flag(tp, HW_TSO_3)) + if (!tg3_flag(tp, FW_TSO)) return 0; - fw_data = (void *)tp->fw->data; + fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data; /* Firmware blob starts with version numbers, followed by start address and length. We are setting complete length. @@ -3156,12 +3914,9 @@ static int tg3_load_tso_firmware(struct tg3 *tp) Remainder is the blob to be loaded contiguously from start address. */ - info.fw_base = be32_to_cpu(fw_data[1]); cpu_scratch_size = tp->fw_len; - info.fw_len = tp->fw->size - 12; - info.fw_data = &fw_data[3]; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + if (tg3_asic_rev(tp) == ASIC_REV_5705) { cpu_base = RX_CPU_BASE; cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705; } else { @@ -3172,59 +3927,60 @@ static int tg3_load_tso_firmware(struct tg3 *tp) err = tg3_load_firmware_cpu(tp, cpu_base, cpu_scratch_base, cpu_scratch_size, - &info); + fw_hdr); if (err) return err; /* Now startup the cpu. */ - tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32_f(cpu_base + CPU_PC, info.fw_base); - - for (i = 0; i < 5; i++) { - if (tr32(cpu_base + CPU_PC) == info.fw_base) - break; - tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32(cpu_base + CPU_MODE, CPU_MODE_HALT); - tw32_f(cpu_base + CPU_PC, info.fw_base); - udelay(1000); - } - if (i >= 5) { + err = tg3_pause_cpu_and_set_pc(tp, cpu_base, + be32_to_cpu(fw_hdr->base_addr)); + if (err) { netdev_err(tp->dev, "%s fails to set CPU PC, is %08x should be %08x\n", - __func__, tr32(cpu_base + CPU_PC), info.fw_base); + __func__, tr32(cpu_base + CPU_PC), + be32_to_cpu(fw_hdr->base_addr)); return -ENODEV; } - tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32_f(cpu_base + CPU_MODE, 0x00000000); + + tg3_resume_cpu(tp, cpu_base); return 0; } - /* tp->lock is held. */ -static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1) +static void __tg3_set_one_mac_addr(struct tg3 *tp, u8 *mac_addr, int index) { u32 addr_high, addr_low; + + addr_high = ((mac_addr[0] << 8) | mac_addr[1]); + addr_low = ((mac_addr[2] << 24) | (mac_addr[3] << 16) | + (mac_addr[4] << 8) | mac_addr[5]); + + if (index < 4) { + tw32(MAC_ADDR_0_HIGH + (index * 8), addr_high); + tw32(MAC_ADDR_0_LOW + (index * 8), addr_low); + } else { + index -= 4; + tw32(MAC_EXTADDR_0_HIGH + (index * 8), addr_high); + tw32(MAC_EXTADDR_0_LOW + (index * 8), addr_low); + } +} + +/* tp->lock is held. */ +static void __tg3_set_mac_addr(struct tg3 *tp, bool skip_mac_1) +{ + u32 addr_high; int i; - addr_high = ((tp->dev->dev_addr[0] << 8) | - tp->dev->dev_addr[1]); - addr_low = ((tp->dev->dev_addr[2] << 24) | - (tp->dev->dev_addr[3] << 16) | - (tp->dev->dev_addr[4] << 8) | - (tp->dev->dev_addr[5] << 0)); for (i = 0; i < 4; i++) { if (i == 1 && skip_mac_1) continue; - tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high); - tw32(MAC_ADDR_0_LOW + (i * 8), addr_low); + __tg3_set_one_mac_addr(tp, tp->dev->dev_addr, i); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { - for (i = 0; i < 12; i++) { - tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high); - tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low); - } + if (tg3_asic_rev(tp) == ASIC_REV_5703 || + tg3_asic_rev(tp) == ASIC_REV_5704) { + for (i = 4; i < 16; i++) + __tg3_set_one_mac_addr(tp, tp->dev->dev_addr, i); } addr_high = (tp->dev->dev_addr[0] + @@ -3264,6 +4020,8 @@ static int tg3_power_up(struct tg3 *tp) return err; } +static int tg3_setup_phy(struct tg3 *, bool); + static int tg3_power_down_prepare(struct tg3 *tp) { u32 misc_host_ctrl; @@ -3272,17 +4030,9 @@ static int tg3_power_down_prepare(struct tg3 *tp) tg3_enable_register_access(tp); /* Restore the CLKREQ setting. */ - if (tg3_flag(tp, CLKREQ_BUG)) { - u16 lnkctl; - - pci_read_config_word(tp->pdev, - pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL, - &lnkctl); - lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(tp->pdev, - pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL, - lnkctl); - } + if (tg3_flag(tp, CLKREQ_BUG)) + pcie_capability_set_word(tp->pdev, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CLKREQ_EN); misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL); tw32(TG3PCI_MISC_HOST_CTRL, @@ -3298,14 +4048,14 @@ static int tg3_power_down_prepare(struct tg3 *tp) struct phy_device *phydev; u32 phyid, advertising; - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER; - tp->link_config.orig_speed = phydev->speed; - tp->link_config.orig_duplex = phydev->duplex; - tp->link_config.orig_autoneg = phydev->autoneg; - tp->link_config.orig_advertising = phydev->advertising; + tp->link_config.speed = phydev->speed; + tp->link_config.duplex = phydev->duplex; + tp->link_config.autoneg = phydev->autoneg; + tp->link_config.advertising = phydev->advertising; advertising = ADVERTISED_TP | ADVERTISED_Pause | @@ -3338,22 +4088,14 @@ static int tg3_power_down_prepare(struct tg3 *tp) } else { do_low_power = true; - if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { + if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER; - tp->link_config.orig_speed = tp->link_config.speed; - tp->link_config.orig_duplex = tp->link_config.duplex; - tp->link_config.orig_autoneg = tp->link_config.autoneg; - } - if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) { - tp->link_config.speed = SPEED_10; - tp->link_config.duplex = DUPLEX_HALF; - tp->link_config.autoneg = AUTONEG_ENABLE; - tg3_setup_phy(tp, 0); - } + if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) + tg3_setup_phy(tp, false); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (tg3_asic_rev(tp) == ASIC_REV_5906) { u32 val; val = tr32(GRC_VCPU_EXT_CTRL); @@ -3391,12 +4133,17 @@ static int tg3_power_down_prepare(struct tg3 *tp) if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) mac_mode = MAC_MODE_PORT_MODE_GMII; - else + else if (tp->phy_flags & + TG3_PHYFLG_KEEP_LINK_ON_PWRDN) { + if (tp->link_config.active_speed == SPEED_1000) + mac_mode = MAC_MODE_PORT_MODE_GMII; + else + mac_mode = MAC_MODE_PORT_MODE_MII; + } else mac_mode = MAC_MODE_PORT_MODE_MII; mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == - ASIC_REV_5700) { + if (tg3_asic_rev(tp) == ASIC_REV_5700) { u32 speed = tg3_flag(tp, WOL_SPEED_100MB) ? SPEED_100 : SPEED_10; if (tg3_5700_link_polarity(tp, speed)) @@ -3429,8 +4176,8 @@ static int tg3_power_down_prepare(struct tg3 *tp) } if (!tg3_flag(tp, WOL_SPEED_100MB) && - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { + (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701)) { u32 base_val; base_val = tp->pci_clock_ctrl; @@ -3441,13 +4188,13 @@ static int tg3_power_down_prepare(struct tg3 *tp) CLOCK_CTRL_PWRDOWN_PLL133, 40); } else if (tg3_flag(tp, 5780_CLASS) || tg3_flag(tp, CPMU_PRESENT) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + tg3_asic_rev(tp) == ASIC_REV_5906) { /* do nothing */ } else if (!(tg3_flag(tp, 5750_PLUS) && tg3_flag(tp, ENABLE_ASF))) { u32 newbits1, newbits2; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { + if (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701) { newbits1 = (CLOCK_CTRL_RXCLK_DISABLE | CLOCK_CTRL_TXCLK_DISABLE | CLOCK_CTRL_ALTCLK); @@ -3469,8 +4216,8 @@ static int tg3_power_down_prepare(struct tg3 *tp) if (!tg3_flag(tp, 5705_PLUS)) { u32 newbits3; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { + if (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701) { newbits3 = (CLOCK_CTRL_RXCLK_DISABLE | CLOCK_CTRL_TXCLK_DISABLE | CLOCK_CTRL_44MHZ_CORE); @@ -3489,8 +4236,9 @@ static int tg3_power_down_prepare(struct tg3 *tp) tg3_frob_aux_power(tp, true); /* Workaround for unstable PLL clock */ - if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) || - (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) { + if ((!tg3_flag(tp, IS_SSB_CORE)) && + ((tg3_chip_rev(tp) == CHIPREV_5750_AX) || + (tg3_chip_rev(tp) == CHIPREV_5750_BX))) { u32 val = tr32(0x7d00); val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); @@ -3507,13 +4255,13 @@ static int tg3_power_down_prepare(struct tg3 *tp) tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); + tg3_ape_driver_state_change(tp, RESET_KIND_SHUTDOWN); + return 0; } static void tg3_power_down(struct tg3 *tp) { - tg3_power_down_prepare(tp); - pci_wake_from_d3(tp->pdev, tg3_flag(tp, WOL_ENABLE)); pci_set_power_state(tp->pdev, PCI_D3hot); } @@ -3559,8 +4307,8 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 DUPLEX_HALF; break; } - *speed = SPEED_INVALID; - *duplex = DUPLEX_INVALID; + *speed = SPEED_UNKNOWN; + *duplex = DUPLEX_UNKNOWN; break; } } @@ -3581,8 +4329,8 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { new_adv = ethtool_adv_to_mii_ctrl1000_t(advertise); - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5701_B0) new_adv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER; err = tg3_writephy(tp, MII_CTRL1000, new_adv); @@ -3596,7 +4344,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) tw32(TG3_CPMU_EEE_MODE, tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (!err) { u32 err2; @@ -3607,11 +4355,21 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) /* Advertise 1000-BaseT EEE ability */ if (advertise & ADVERTISED_1000baseT_Full) val |= MDIO_AN_EEE_ADV_1000T; + + if (!tp->eee.eee_enabled) { + val = 0; + tp->eee.advertised = 0; + } else { + tp->eee.advertised = advertise & + (ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full); + } + err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); if (err) val = 0; - switch (GET_ASIC_REV(tp->pci_chip_rev_id)) { + switch (tg3_asic_rev(tp)) { case ASIC_REV_5717: case ASIC_REV_57765: case ASIC_REV_57766: @@ -3624,12 +4382,13 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); /* Fall through */ case ASIC_REV_5720: + case ASIC_REV_5762: if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val)) tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val | MII_TG3_DSP_CH34TP2_HIBW01); } - err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + err2 = tg3_phy_toggle_auxctl_smdsp(tp, false); if (!err) err = err2; } @@ -3640,56 +4399,62 @@ done: static void tg3_phy_copper_begin(struct tg3 *tp) { - u32 new_adv; - int i; - - if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { - new_adv = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full; - if (tg3_flag(tp, WOL_SPEED_100MB)) - new_adv |= ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full; - - tg3_phy_autoneg_cfg(tp, new_adv, - FLOW_CTRL_TX | FLOW_CTRL_RX); - } else if (tp->link_config.speed == SPEED_INVALID) { - if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) - tp->link_config.advertising &= - ~(ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); + if (tp->link_config.autoneg == AUTONEG_ENABLE || + (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { + u32 adv, fc; + + if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) && + !(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN)) { + adv = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full; + if (tg3_flag(tp, WOL_SPEED_100MB)) + adv |= ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full; + if (tp->phy_flags & TG3_PHYFLG_1G_ON_VAUX_OK) { + if (!(tp->phy_flags & + TG3_PHYFLG_DISABLE_1G_HD_ADV)) + adv |= ADVERTISED_1000baseT_Half; + adv |= ADVERTISED_1000baseT_Full; + } - tg3_phy_autoneg_cfg(tp, tp->link_config.advertising, - tp->link_config.flowctrl); - } else { - /* Asking for a specific link mode. */ - if (tp->link_config.speed == SPEED_1000) { - if (tp->link_config.duplex == DUPLEX_FULL) - new_adv = ADVERTISED_1000baseT_Full; - else - new_adv = ADVERTISED_1000baseT_Half; - } else if (tp->link_config.speed == SPEED_100) { - if (tp->link_config.duplex == DUPLEX_FULL) - new_adv = ADVERTISED_100baseT_Full; - else - new_adv = ADVERTISED_100baseT_Half; + fc = FLOW_CTRL_TX | FLOW_CTRL_RX; } else { - if (tp->link_config.duplex == DUPLEX_FULL) - new_adv = ADVERTISED_10baseT_Full; - else - new_adv = ADVERTISED_10baseT_Half; + adv = tp->link_config.advertising; + if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) + adv &= ~(ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full); + + fc = tp->link_config.flowctrl; } - tg3_phy_autoneg_cfg(tp, new_adv, - tp->link_config.flowctrl); - } + tg3_phy_autoneg_cfg(tp, adv, fc); - if (tp->link_config.autoneg == AUTONEG_DISABLE && - tp->link_config.speed != SPEED_INVALID) { + if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) && + (tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN)) { + /* Normally during power down we want to autonegotiate + * the lowest possible speed for WOL. However, to avoid + * link flap, we leave it untouched. + */ + return; + } + + tg3_writephy(tp, MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART); + } else { + int i; u32 bmcr, orig_bmcr; tp->link_config.active_speed = tp->link_config.speed; tp->link_config.active_duplex = tp->link_config.duplex; + if (tg3_asic_rev(tp) == ASIC_REV_5714) { + /* With autoneg disabled, 5715 only links up when the + * advertisement register has the configured speed + * enabled. + */ + tg3_writephy(tp, MII_ADVERTISE, ADVERTISE_ALL); + } + bmcr = 0; switch (tp->link_config.speed) { default: @@ -3726,10 +4491,104 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tg3_writephy(tp, MII_BMCR, bmcr); udelay(40); } + } +} + +static int tg3_phy_pull_config(struct tg3 *tp) +{ + int err; + u32 val; + + err = tg3_readphy(tp, MII_BMCR, &val); + if (err) + goto done; + + if (!(val & BMCR_ANENABLE)) { + tp->link_config.autoneg = AUTONEG_DISABLE; + tp->link_config.advertising = 0; + tg3_flag_clear(tp, PAUSE_AUTONEG); + + err = -EIO; + + switch (val & (BMCR_SPEED1000 | BMCR_SPEED100)) { + case 0: + if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES) + goto done; + + tp->link_config.speed = SPEED_10; + break; + case BMCR_SPEED100: + if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES) + goto done; + + tp->link_config.speed = SPEED_100; + break; + case BMCR_SPEED1000: + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { + tp->link_config.speed = SPEED_1000; + break; + } + /* Fall through */ + default: + goto done; + } + + if (val & BMCR_FULLDPLX) + tp->link_config.duplex = DUPLEX_FULL; + else + tp->link_config.duplex = DUPLEX_HALF; + + tp->link_config.flowctrl = FLOW_CTRL_RX | FLOW_CTRL_TX; + + err = 0; + goto done; + } + + tp->link_config.autoneg = AUTONEG_ENABLE; + tp->link_config.advertising = ADVERTISED_Autoneg; + tg3_flag_set(tp, PAUSE_AUTONEG); + + if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) { + u32 adv; + + err = tg3_readphy(tp, MII_ADVERTISE, &val); + if (err) + goto done; + + adv = mii_adv_to_ethtool_adv_t(val & ADVERTISE_ALL); + tp->link_config.advertising |= adv | ADVERTISED_TP; + + tp->link_config.flowctrl = tg3_decode_flowctrl_1000T(val); } else { - tg3_writephy(tp, MII_BMCR, - BMCR_ANENABLE | BMCR_ANRESTART); + tp->link_config.advertising |= ADVERTISED_FIBRE; } + + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { + u32 adv; + + if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) { + err = tg3_readphy(tp, MII_CTRL1000, &val); + if (err) + goto done; + + adv = mii_ctrl1000_to_ethtool_adv_t(val); + } else { + err = tg3_readphy(tp, MII_ADVERTISE, &val); + if (err) + goto done; + + adv = tg3_decode_flowctrl_1000X(val); + tp->link_config.flowctrl = adv; + + val &= (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL); + adv = mii_adv_to_ethtool_adv_x(val); + } + + tp->link_config.advertising |= adv; + } + +done: + return err; } static int tg3_init_5401phy_dsp(struct tg3 *tp) @@ -3751,6 +4610,29 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp) return err; } +static bool tg3_phy_eee_config_ok(struct tg3 *tp) +{ + struct ethtool_eee eee; + + if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) + return true; + + tg3_eee_pull_config(tp, &eee); + + if (tp->eee.eee_enabled) { + if (tp->eee.advertised != eee.advertised || + tp->eee.tx_lpi_timer != eee.tx_lpi_timer || + tp->eee.tx_lpi_enabled != eee.tx_lpi_enabled) + return false; + } else { + /* EEE is disabled but we're advertising */ + if (eee.advertised) + return false; + } + + return true; +} + static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv) { u32 advmsk, tgtadv, advertising; @@ -3778,7 +4660,16 @@ static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv) if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl)) return false; - tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL); + if (tgtadv && + (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5701_B0)) { + tgtadv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER; + tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL | + CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); + } else { + tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL); + } + if (tg3_ctrl != tgtadv) return false; } @@ -3808,23 +4699,82 @@ static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv) return true; } -static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) +static bool tg3_test_and_report_link_chg(struct tg3 *tp, bool curr_link_up) +{ + if (curr_link_up != tp->link_up) { + if (curr_link_up) { + netif_carrier_on(tp->dev); + } else { + netif_carrier_off(tp->dev); + if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; + } + + tg3_link_report(tp); + return true; + } + + return false; +} + +static void tg3_clear_mac_status(struct tg3 *tp) { - int current_link_up; + tw32(MAC_EVENT, 0); + + tw32_f(MAC_STATUS, + MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED | + MAC_STATUS_MI_COMPLETION | + MAC_STATUS_LNKSTATE_CHANGED); + udelay(40); +} + +static void tg3_setup_eee(struct tg3 *tp) +{ + u32 val; + + val = TG3_CPMU_EEE_LNKIDL_PCIE_NL0 | + TG3_CPMU_EEE_LNKIDL_UART_IDL; + if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0) + val |= TG3_CPMU_EEE_LNKIDL_APE_TX_MT; + + tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, val); + + tw32_f(TG3_CPMU_EEE_CTRL, + TG3_CPMU_EEE_CTRL_EXIT_20_1_US); + + val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET | + (tp->eee.tx_lpi_enabled ? TG3_CPMU_EEEMD_LPI_IN_TX : 0) | + TG3_CPMU_EEEMD_LPI_IN_RX | + TG3_CPMU_EEEMD_EEE_ENABLE; + + if (tg3_asic_rev(tp) != ASIC_REV_5717) + val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN; + + if (tg3_flag(tp, ENABLE_APE)) + val |= TG3_CPMU_EEEMD_APE_TX_DET_EN; + + tw32_f(TG3_CPMU_EEE_MODE, tp->eee.eee_enabled ? val : 0); + + tw32_f(TG3_CPMU_EEE_DBTMR1, + TG3_CPMU_DBTMR1_PCIEXIT_2047US | + (tp->eee.tx_lpi_timer & 0xffff)); + + tw32_f(TG3_CPMU_EEE_DBTMR2, + TG3_CPMU_DBTMR2_APE_TX_2047US | + TG3_CPMU_DBTMR2_TXIDXEQ_2047US); +} + +static int tg3_setup_copper_phy(struct tg3 *tp, bool force_reset) +{ + bool current_link_up; u32 bmsr, val; u32 lcl_adv, rmt_adv; u16 current_speed; u8 current_duplex; int i, err; - tw32(MAC_EVENT, 0); - - tw32_f(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED | - MAC_STATUS_MI_COMPLETION | - MAC_STATUS_LNKSTATE_CHANGED)); - udelay(40); + tg3_clear_mac_status(tp); if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, @@ -3837,14 +4787,14 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) /* Some third-party PHYs need to be reset on link going * down. */ - 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) && - netif_carrier_ok(tp->dev)) { + if ((tg3_asic_rev(tp) == ASIC_REV_5703 || + tg3_asic_rev(tp) == ASIC_REV_5704 || + tg3_asic_rev(tp) == ASIC_REV_5705) && + tp->link_up) { tg3_readphy(tp, MII_BMSR, &bmsr); if (!tg3_readphy(tp, MII_BMSR, &bmsr) && !(bmsr & BMSR_LSTATUS)) - force_reset = 1; + force_reset = true; } if (force_reset) tg3_phy_reset(tp); @@ -3881,8 +4831,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) return err; } } - } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) { + } else if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5701_B0) { /* 5701 {A0,B0} CRC bug workaround */ tg3_writephy(tp, 0x15, 0x0a75); tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68); @@ -3899,8 +4849,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET)) tg3_writephy(tp, MII_TG3_IMASK, ~0); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { + if (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701) { if (tp->led_ctrl == LED_CTRL_MODE_PHY_1) tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_LNK3_LED_MODE); @@ -3908,9 +4858,9 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) tg3_writephy(tp, MII_TG3_EXT_CTRL, 0); } - current_link_up = 0; - current_speed = SPEED_INVALID; - current_duplex = DUPLEX_INVALID; + current_link_up = false; + current_speed = SPEED_UNKNOWN; + current_duplex = DUPLEX_UNKNOWN; tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE; tp->link_config.rmt_adv = 0; @@ -3967,21 +4917,33 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) tp->link_config.active_duplex = current_duplex; if (tp->link_config.autoneg == AUTONEG_ENABLE) { + bool eee_config_ok = tg3_phy_eee_config_ok(tp); + if ((bmcr & BMCR_ANENABLE) && + eee_config_ok && tg3_phy_copper_an_config_ok(tp, &lcl_adv) && tg3_phy_copper_fetch_rmtadv(tp, &rmt_adv)) - current_link_up = 1; + current_link_up = true; + + /* EEE settings changes take effect only after a phy + * reset. If we have skipped a reset due to Link Flap + * Avoidance being enabled, do it now. + */ + if (!eee_config_ok && + (tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) && + !force_reset) { + tg3_setup_eee(tp); + tg3_phy_reset(tp); + } } else { if (!(bmcr & BMCR_ANENABLE) && tp->link_config.speed == current_speed && - tp->link_config.duplex == current_duplex && - tp->link_config.flowctrl == - tp->link_config.active_flowctrl) { - current_link_up = 1; + tp->link_config.duplex == current_duplex) { + current_link_up = true; } } - if (current_link_up == 1 && + if (current_link_up && tp->link_config.active_duplex == DUPLEX_FULL) { u32 reg, bit; @@ -4001,17 +4963,26 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) } relink: - if (current_link_up == 0 || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { + if (!current_link_up || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) { tg3_phy_copper_begin(tp); + if (tg3_flag(tp, ROBOSWITCH)) { + current_link_up = true; + /* FIXME: when BCM5325 switch is used use 100 MBit/s */ + current_speed = SPEED_1000; + current_duplex = DUPLEX_FULL; + tp->link_config.active_speed = current_speed; + tp->link_config.active_duplex = current_duplex; + } + tg3_readphy(tp, MII_BMSR, &bmsr); if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) || (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)) - current_link_up = 1; + current_link_up = true; } tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK; - if (current_link_up == 1) { + if (current_link_up) { if (tp->link_config.active_speed == SPEED_100 || tp->link_config.active_speed == SPEED_10) tp->mac_mode |= MAC_MODE_PORT_MODE_MII; @@ -4022,12 +4993,32 @@ relink: else tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; + /* In order for the 5750 core in BCM4785 chip to work properly + * in RGMII mode, the Led Control Register must be set up. + */ + if (tg3_flag(tp, RGMII_MODE)) { + u32 led_ctrl = tr32(MAC_LED_CTRL); + led_ctrl &= ~(LED_CTRL_1000MBPS_ON | LED_CTRL_100MBPS_ON); + + if (tp->link_config.active_speed == SPEED_10) + led_ctrl |= LED_CTRL_LNKLED_OVERRIDE; + else if (tp->link_config.active_speed == SPEED_100) + led_ctrl |= (LED_CTRL_LNKLED_OVERRIDE | + LED_CTRL_100MBPS_ON); + else if (tp->link_config.active_speed == SPEED_1000) + led_ctrl |= (LED_CTRL_LNKLED_OVERRIDE | + LED_CTRL_1000MBPS_ON); + + tw32(MAC_LED_CTRL, led_ctrl); + udelay(40); + } + tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX; if (tp->link_config.active_duplex == DUPLEX_HALF) tp->mac_mode |= MAC_MODE_HALF_DUPLEX; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { - if (current_link_up == 1 && + if (tg3_asic_rev(tp) == ASIC_REV_5700) { + if (current_link_up && tg3_5700_link_polarity(tp, tp->link_config.active_speed)) tp->mac_mode |= MAC_MODE_LINK_POLARITY; else @@ -4038,7 +5029,7 @@ relink: * ??? send/receive packets... */ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 && - tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) { + tg3_chip_rev_id(tp) == CHIPREV_ID_5700_ALTIMA) { tp->mi_mode |= MAC_MI_MODE_AUTO_POLL; tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); @@ -4057,8 +5048,8 @@ relink: } udelay(40); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 && - current_link_up == 1 && + if (tg3_asic_rev(tp) == ASIC_REV_5700 && + current_link_up && tp->link_config.active_speed == SPEED_1000 && (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) { udelay(120); @@ -4073,29 +5064,16 @@ relink: /* Prevent send BD corruption. */ if (tg3_flag(tp, CLKREQ_BUG)) { - u16 oldlnkctl, newlnkctl; - - pci_read_config_word(tp->pdev, - pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL, - &oldlnkctl); if (tp->link_config.active_speed == SPEED_100 || tp->link_config.active_speed == SPEED_10) - newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN; + pcie_capability_clear_word(tp->pdev, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CLKREQ_EN); else - newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN; - if (newlnkctl != oldlnkctl) - pci_write_config_word(tp->pdev, - pci_pcie_cap(tp->pdev) + - PCI_EXP_LNKCTL, newlnkctl); + pcie_capability_set_word(tp->pdev, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CLKREQ_EN); } - if (current_link_up != netif_carrier_ok(tp->dev)) { - if (current_link_up) - netif_carrier_on(tp->dev); - else - netif_carrier_off(tp->dev); - tg3_link_report(tp); - } + tg3_test_and_report_link_chg(tp, current_link_up); return 0; } @@ -4511,22 +5489,22 @@ static void tg3_init_bcm8002(struct tg3 *tp) tg3_writephy(tp, 0x10, 0x8011); } -static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) +static bool tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) { u16 flowctrl; + bool current_link_up; u32 sg_dig_ctrl, sg_dig_status; u32 serdes_cfg, expected_sg_dig_ctrl; int workaround, port_a; - int current_link_up; serdes_cfg = 0; expected_sg_dig_ctrl = 0; workaround = 0; port_a = 1; - current_link_up = 0; + current_link_up = false; - if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 && - tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) { + if (tg3_chip_rev_id(tp) != CHIPREV_ID_5704_A0 && + tg3_chip_rev_id(tp) != CHIPREV_ID_5704_A1) { workaround = 1; if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) port_a = 0; @@ -4554,7 +5532,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) } if (mac_status & MAC_STATUS_PCS_SYNCED) { tg3_setup_flow_control(tp, 0, 0); - current_link_up = 1; + current_link_up = true; } goto out; } @@ -4575,7 +5553,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) MAC_STATUS_RCVD_CFG)) == MAC_STATUS_PCS_SYNCED)) { tp->serdes_counter--; - current_link_up = 1; + current_link_up = true; goto out; } restart_autoneg: @@ -4610,7 +5588,7 @@ restart_autoneg: mii_adv_to_ethtool_adv_x(remote_adv); tg3_setup_flow_control(tp, local_adv, remote_adv); - current_link_up = 1; + current_link_up = true; tp->serdes_counter = 0; tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; } else if (!(sg_dig_status & SG_DIG_AUTONEG_COMPLETE)) { @@ -4638,7 +5616,7 @@ restart_autoneg: if ((mac_status & MAC_STATUS_PCS_SYNCED) && !(mac_status & MAC_STATUS_RCVD_CFG)) { tg3_setup_flow_control(tp, 0, 0); - current_link_up = 1; + current_link_up = true; tp->phy_flags |= TG3_PHYFLG_PARALLEL_DETECT; tp->serdes_counter = @@ -4656,9 +5634,9 @@ out: return current_link_up; } -static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) +static bool tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) { - int current_link_up = 0; + bool current_link_up = false; if (!(mac_status & MAC_STATUS_PCS_SYNCED)) goto out; @@ -4685,7 +5663,7 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) tg3_setup_flow_control(tp, local_adv, remote_adv); - current_link_up = 1; + current_link_up = true; } for (i = 0; i < 30; i++) { udelay(20); @@ -4700,15 +5678,15 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) } mac_status = tr32(MAC_STATUS); - if (current_link_up == 0 && + if (!current_link_up && (mac_status & MAC_STATUS_PCS_SYNCED) && !(mac_status & MAC_STATUS_RCVD_CFG)) - current_link_up = 1; + current_link_up = true; } else { tg3_setup_flow_control(tp, 0, 0); /* Forcing 1000FD link up. */ - current_link_up = 1; + current_link_up = true; tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS)); udelay(40); @@ -4721,13 +5699,13 @@ out: return current_link_up; } -static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) +static int tg3_setup_fiber_phy(struct tg3 *tp, bool force_reset) { u32 orig_pause_cfg; u16 orig_active_speed; u8 orig_active_duplex; u32 mac_status; - int current_link_up; + bool current_link_up; int i; orig_pause_cfg = tp->link_config.active_flowctrl; @@ -4735,7 +5713,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) orig_active_duplex = tp->link_config.active_duplex; if (!tg3_flag(tp, HW_AUTONEG) && - netif_carrier_ok(tp->dev) && + tp->link_up && tg3_flag(tp, INIT_COMPLETE)) { mac_status = tr32(MAC_STATUS); mac_status &= (MAC_STATUS_PCS_SYNCED | @@ -4764,7 +5742,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); udelay(40); - current_link_up = 0; + current_link_up = false; tp->link_config.rmt_adv = 0; mac_status = tr32(MAC_STATUS); @@ -4789,7 +5767,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) mac_status = tr32(MAC_STATUS); if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) { - current_link_up = 0; + current_link_up = false; if (tp->link_config.autoneg == AUTONEG_ENABLE && tp->serdes_counter == 0) { tw32_f(MAC_MODE, (tp->mac_mode | @@ -4799,27 +5777,21 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) } } - if (current_link_up == 1) { + if (current_link_up) { tp->link_config.active_speed = SPEED_1000; tp->link_config.active_duplex = DUPLEX_FULL; tw32(MAC_LED_CTRL, (tp->led_ctrl | LED_CTRL_LNKLED_OVERRIDE | LED_CTRL_1000MBPS_ON)); } else { - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; + tp->link_config.active_speed = SPEED_UNKNOWN; + tp->link_config.active_duplex = DUPLEX_UNKNOWN; tw32(MAC_LED_CTRL, (tp->led_ctrl | LED_CTRL_LNKLED_OVERRIDE | LED_CTRL_TRAFFIC_OVERRIDE)); } - if (current_link_up != netif_carrier_ok(tp->dev)) { - if (current_link_up) - netif_carrier_on(tp->dev); - else - netif_carrier_off(tp->dev); - tg3_link_report(tp); - } else { + if (!tg3_test_and_report_link_chg(tp, current_link_up)) { u32 now_pause_cfg = tp->link_config.active_flowctrl; if (orig_pause_cfg != now_pause_cfg || orig_active_speed != tp->link_config.active_speed || @@ -4830,38 +5802,68 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) return 0; } -static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) +static int tg3_setup_fiber_mii_phy(struct tg3 *tp, bool force_reset) { - int current_link_up, err = 0; + int err = 0; u32 bmsr, bmcr; - u16 current_speed; - u8 current_duplex; - u32 local_adv, remote_adv; + u16 current_speed = SPEED_UNKNOWN; + u8 current_duplex = DUPLEX_UNKNOWN; + bool current_link_up = false; + u32 local_adv, remote_adv, sgsr; + + if ((tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720) && + !tg3_readphy(tp, SERDES_TG3_1000X_STATUS, &sgsr) && + (sgsr & SERDES_TG3_SGMII_MODE)) { + + if (force_reset) + tg3_phy_reset(tp); + + tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK; + + if (!(sgsr & SERDES_TG3_LINK_UP)) { + tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; + } else { + current_link_up = true; + if (sgsr & SERDES_TG3_SPEED_1000) { + current_speed = SPEED_1000; + tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; + } else if (sgsr & SERDES_TG3_SPEED_100) { + current_speed = SPEED_100; + tp->mac_mode |= MAC_MODE_PORT_MODE_MII; + } else { + current_speed = SPEED_10; + tp->mac_mode |= MAC_MODE_PORT_MODE_MII; + } + + if (sgsr & SERDES_TG3_FULL_DUPLEX) + current_duplex = DUPLEX_FULL; + else + current_duplex = DUPLEX_HALF; + } + + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); + + tg3_clear_mac_status(tp); + + goto fiber_setup_done; + } tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; tw32_f(MAC_MODE, tp->mac_mode); udelay(40); - tw32(MAC_EVENT, 0); - - tw32_f(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED | - MAC_STATUS_MI_COMPLETION | - MAC_STATUS_LNKSTATE_CHANGED)); - udelay(40); + tg3_clear_mac_status(tp); if (force_reset) tg3_phy_reset(tp); - current_link_up = 0; - current_speed = SPEED_INVALID; - current_duplex = DUPLEX_INVALID; tp->link_config.rmt_adv = 0; err |= tg3_readphy(tp, MII_BMSR, &bmsr); err |= tg3_readphy(tp, MII_BMSR, &bmsr); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { + if (tg3_asic_rev(tp) == ASIC_REV_5714) { if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP) bmsr |= BMSR_LSTATUS; else @@ -4912,7 +5914,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) new_bmcr |= BMCR_SPEED1000; /* Force a linkdown */ - if (netif_carrier_ok(tp->dev)) { + if (tp->link_up) { u32 adv; err |= tg3_readphy(tp, MII_ADVERTISE, &adv); @@ -4924,14 +5926,13 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) BMCR_ANRESTART | BMCR_ANENABLE); udelay(10); - netif_carrier_off(tp->dev); + tg3_carrier_off(tp); } tg3_writephy(tp, MII_BMCR, new_bmcr); bmcr = new_bmcr; err |= tg3_readphy(tp, MII_BMSR, &bmsr); err |= tg3_readphy(tp, MII_BMSR, &bmsr); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == - ASIC_REV_5714) { + if (tg3_asic_rev(tp) == ASIC_REV_5714) { if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP) bmsr |= BMSR_LSTATUS; else @@ -4943,7 +5944,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) if (bmsr & BMSR_LSTATUS) { current_speed = SPEED_1000; - current_link_up = 1; + current_link_up = true; if (bmcr & BMCR_FULLDPLX) current_duplex = DUPLEX_FULL; else @@ -4970,12 +5971,13 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) } else if (!tg3_flag(tp, 5780_CLASS)) { /* Link is up via parallel detect */ } else { - current_link_up = 0; + current_link_up = false; } } } - if (current_link_up == 1 && current_duplex == DUPLEX_FULL) +fiber_setup_done: + if (current_link_up && current_duplex == DUPLEX_FULL) tg3_setup_flow_control(tp, local_adv, remote_adv); tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX; @@ -4990,15 +5992,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) tp->link_config.active_speed = current_speed; tp->link_config.active_duplex = current_duplex; - if (current_link_up != netif_carrier_ok(tp->dev)) { - if (current_link_up) - netif_carrier_on(tp->dev); - else { - netif_carrier_off(tp->dev); - tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; - } - tg3_link_report(tp); - } + tg3_test_and_report_link_chg(tp, current_link_up); return err; } @@ -5010,7 +6004,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp) return; } - if (!netif_carrier_ok(tp->dev) && + if (!tp->link_up && (tp->link_config.autoneg == AUTONEG_ENABLE)) { u32 bmcr; @@ -5040,7 +6034,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp) tp->phy_flags |= TG3_PHYFLG_PARALLEL_DETECT; } } - } else if (netif_carrier_ok(tp->dev) && + } else if (tp->link_up && (tp->link_config.autoneg == AUTONEG_ENABLE) && (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) { u32 phy2; @@ -5062,7 +6056,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp) } } -static int tg3_setup_phy(struct tg3 *tp, int force_reset) +static int tg3_setup_phy(struct tg3 *tp, bool force_reset) { u32 val; int err; @@ -5074,7 +6068,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) else err = tg3_setup_copper_phy(tp, force_reset); - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) { + if (tg3_chip_rev(tp) == CHIPREV_5784_AX) { u32 scale; val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK; @@ -5092,7 +6086,8 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) val = (2 << TX_LENGTHS_IPG_CRS_SHIFT) | (6 << TX_LENGTHS_IPG_SHIFT); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + if (tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_5762) val |= tr32(MAC_TX_LENGTHS) & (TX_LENGTHS_JMB_FRM_LEN_MSK | TX_LENGTHS_CNT_DWN_VAL_MSK); @@ -5106,7 +6101,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) (32 << TX_LENGTHS_SLOT_TIME_SHIFT)); if (!tg3_flag(tp, 5705_PLUS)) { - if (netif_carrier_ok(tp->dev)) { + if (tp->link_up) { tw32(HOSTCC_STAT_COAL_TICKS, tp->coal.stats_block_coalesce_usecs); } else { @@ -5116,7 +6111,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) if (tg3_flag(tp, ASPM_WORKAROUND)) { val = tr32(PCIE_PWR_MGMT_THRESH); - if (!netif_carrier_ok(tp->dev)) + if (!tp->link_up) val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) | tp->pwrmgmt_thresh; else @@ -5127,6 +6122,249 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) return err; } +/* tp->lock must be held */ +static u64 tg3_refclk_read(struct tg3 *tp) +{ + u64 stamp = tr32(TG3_EAV_REF_CLCK_LSB); + return stamp | (u64)tr32(TG3_EAV_REF_CLCK_MSB) << 32; +} + +/* tp->lock must be held */ +static void tg3_refclk_write(struct tg3 *tp, u64 newval) +{ + u32 clock_ctl = tr32(TG3_EAV_REF_CLCK_CTL); + + tw32(TG3_EAV_REF_CLCK_CTL, clock_ctl | TG3_EAV_REF_CLCK_CTL_STOP); + tw32(TG3_EAV_REF_CLCK_LSB, newval & 0xffffffff); + tw32(TG3_EAV_REF_CLCK_MSB, newval >> 32); + tw32_f(TG3_EAV_REF_CLCK_CTL, clock_ctl | TG3_EAV_REF_CLCK_CTL_RESUME); +} + +static inline void tg3_full_lock(struct tg3 *tp, int irq_sync); +static inline void tg3_full_unlock(struct tg3 *tp); +static int tg3_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) +{ + struct tg3 *tp = netdev_priv(dev); + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + + if (tg3_flag(tp, PTP_CAPABLE)) { + info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + } + + if (tp->ptp_clock) + info->phc_index = ptp_clock_index(tp->ptp_clock); + else + info->phc_index = -1; + + info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); + + info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | + (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | + (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT); + return 0; +} + +static int tg3_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + struct tg3 *tp = container_of(ptp, struct tg3, ptp_info); + bool neg_adj = false; + u32 correction = 0; + + if (ppb < 0) { + neg_adj = true; + ppb = -ppb; + } + + /* Frequency adjustment is performed using hardware with a 24 bit + * accumulator and a programmable correction value. On each clk, the + * correction value gets added to the accumulator and when it + * overflows, the time counter is incremented/decremented. + * + * So conversion from ppb to correction value is + * ppb * (1 << 24) / 1000000000 + */ + correction = div_u64((u64)ppb * (1 << 24), 1000000000ULL) & + TG3_EAV_REF_CLK_CORRECT_MASK; + + tg3_full_lock(tp, 0); + + if (correction) + tw32(TG3_EAV_REF_CLK_CORRECT_CTL, + TG3_EAV_REF_CLK_CORRECT_EN | + (neg_adj ? TG3_EAV_REF_CLK_CORRECT_NEG : 0) | correction); + else + tw32(TG3_EAV_REF_CLK_CORRECT_CTL, 0); + + tg3_full_unlock(tp); + + return 0; +} + +static int tg3_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct tg3 *tp = container_of(ptp, struct tg3, ptp_info); + + tg3_full_lock(tp, 0); + tp->ptp_adjust += delta; + tg3_full_unlock(tp); + + return 0; +} + +static int tg3_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts) +{ + u64 ns; + u32 remainder; + struct tg3 *tp = container_of(ptp, struct tg3, ptp_info); + + tg3_full_lock(tp, 0); + ns = tg3_refclk_read(tp); + ns += tp->ptp_adjust; + tg3_full_unlock(tp); + + ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); + ts->tv_nsec = remainder; + + return 0; +} + +static int tg3_ptp_settime(struct ptp_clock_info *ptp, + const struct timespec *ts) +{ + u64 ns; + struct tg3 *tp = container_of(ptp, struct tg3, ptp_info); + + ns = timespec_to_ns(ts); + + tg3_full_lock(tp, 0); + tg3_refclk_write(tp, ns); + tp->ptp_adjust = 0; + tg3_full_unlock(tp); + + return 0; +} + +static int tg3_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct tg3 *tp = container_of(ptp, struct tg3, ptp_info); + u32 clock_ctl; + int rval = 0; + + switch (rq->type) { + case PTP_CLK_REQ_PEROUT: + if (rq->perout.index != 0) + return -EINVAL; + + tg3_full_lock(tp, 0); + clock_ctl = tr32(TG3_EAV_REF_CLCK_CTL); + clock_ctl &= ~TG3_EAV_CTL_TSYNC_GPIO_MASK; + + if (on) { + u64 nsec; + + nsec = rq->perout.start.sec * 1000000000ULL + + rq->perout.start.nsec; + + if (rq->perout.period.sec || rq->perout.period.nsec) { + netdev_warn(tp->dev, + "Device supports only a one-shot timesync output, period must be 0\n"); + rval = -EINVAL; + goto err_out; + } + + if (nsec & (1ULL << 63)) { + netdev_warn(tp->dev, + "Start value (nsec) is over limit. Maximum size of start is only 63 bits\n"); + rval = -EINVAL; + goto err_out; + } + + tw32(TG3_EAV_WATCHDOG0_LSB, (nsec & 0xffffffff)); + tw32(TG3_EAV_WATCHDOG0_MSB, + TG3_EAV_WATCHDOG0_EN | + ((nsec >> 32) & TG3_EAV_WATCHDOG_MSB_MASK)); + + tw32(TG3_EAV_REF_CLCK_CTL, + clock_ctl | TG3_EAV_CTL_TSYNC_WDOG0); + } else { + tw32(TG3_EAV_WATCHDOG0_MSB, 0); + tw32(TG3_EAV_REF_CLCK_CTL, clock_ctl); + } + +err_out: + tg3_full_unlock(tp); + return rval; + + default: + break; + } + + return -EOPNOTSUPP; +} + +static const struct ptp_clock_info tg3_ptp_caps = { + .owner = THIS_MODULE, + .name = "tg3 clock", + .max_adj = 250000000, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 1, + .n_pins = 0, + .pps = 0, + .adjfreq = tg3_ptp_adjfreq, + .adjtime = tg3_ptp_adjtime, + .gettime = tg3_ptp_gettime, + .settime = tg3_ptp_settime, + .enable = tg3_ptp_enable, +}; + +static void tg3_hwclock_to_timestamp(struct tg3 *tp, u64 hwclock, + struct skb_shared_hwtstamps *timestamp) +{ + memset(timestamp, 0, sizeof(struct skb_shared_hwtstamps)); + timestamp->hwtstamp = ns_to_ktime((hwclock & TG3_TSTAMP_MASK) + + tp->ptp_adjust); +} + +/* tp->lock must be held */ +static void tg3_ptp_init(struct tg3 *tp) +{ + if (!tg3_flag(tp, PTP_CAPABLE)) + return; + + /* Initialize the hardware clock to the system time. */ + tg3_refclk_write(tp, ktime_to_ns(ktime_get_real())); + tp->ptp_adjust = 0; + tp->ptp_info = tg3_ptp_caps; +} + +/* tp->lock must be held */ +static void tg3_ptp_resume(struct tg3 *tp) +{ + if (!tg3_flag(tp, PTP_CAPABLE)) + return; + + tg3_refclk_write(tp, ktime_to_ns(ktime_get_real()) + tp->ptp_adjust); + tp->ptp_adjust = 0; +} + +static void tg3_ptp_fini(struct tg3 *tp) +{ + if (!tg3_flag(tp, PTP_CAPABLE) || !tp->ptp_clock) + return; + + ptp_clock_unregister(tp->ptp_clock); + tp->ptp_clock = NULL; + tp->ptp_adjust = 0; +} + static inline int tg3_irq_sync(struct tg3 *tp) { return tp->irq_sync; @@ -5197,10 +6435,8 @@ static void tg3_dump_state(struct tg3 *tp) u32 *regs; regs = kzalloc(TG3_REG_BLK_SIZE, GFP_ATOMIC); - if (!regs) { - netdev_err(tp->dev, "Failed allocating register dump buffer\n"); + if (!regs) return; - } if (tg3_flag(tp, PCI_EXPRESS)) { /* Read up to but not including private PCI registers */ @@ -5266,9 +6502,7 @@ static void tg3_tx_recover(struct tg3 *tp) "Please report the problem to the driver maintainer " "and include system chipset information.\n"); - spin_lock(&tp->lock); tg3_flag_set(tp, TX_RECOVERY_PENDING); - spin_unlock(&tp->lock); } static inline u32 tg3_tx_avail(struct tg3_napi *tnapi) @@ -5307,6 +6541,16 @@ static void tg3_tx(struct tg3_napi *tnapi) return; } + if (tnapi->tx_ring[sw_idx].len_flags & TXD_FLAG_HWTSTAMP) { + struct skb_shared_hwtstamps timestamp; + u64 hwclock = tr32(TG3_TX_TSTAMP_LSB); + hwclock |= (u64)tr32(TG3_TX_TSTAMP_MSB) << 32; + + tg3_hwclock_to_timestamp(tp, hwclock, ×tamp); + + skb_tstamp_tx(skb, ×tamp); + } + pci_unmap_single(tp->pdev, dma_unmap_addr(ri, mapping), skb_headlen(skb), @@ -5344,7 +6588,7 @@ static void tg3_tx(struct tg3_napi *tnapi) pkts_compl++; bytes_compl += skb->len; - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); if (unlikely(tx_bug)) { tg3_tx_recover(tp); @@ -5352,7 +6596,7 @@ static void tg3_tx(struct tg3_napi *tnapi) } } - netdev_completed_queue(tp->dev, pkts_compl, bytes_compl); + netdev_tx_completed_queue(txq, pkts_compl, bytes_compl); tnapi->tx_cons = sw_idx; @@ -5373,17 +6617,29 @@ static void tg3_tx(struct tg3_napi *tnapi) } } +static void tg3_frag_free(bool is_frag, void *data) +{ + if (is_frag) + put_page(virt_to_head_page(data)); + else + kfree(data); +} + static void tg3_rx_data_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz) { + unsigned int skb_size = SKB_DATA_ALIGN(map_sz + TG3_RX_OFFSET(tp)) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + if (!ri->data) return; pci_unmap_single(tp->pdev, dma_unmap_addr(ri, mapping), map_sz, PCI_DMA_FROMDEVICE); - kfree(ri->data); + tg3_frag_free(skb_size <= PAGE_SIZE, ri->data); ri->data = NULL; } + /* Returns size of skb allocated or < 0 on error. * * We only need to fill in the address because the other members @@ -5396,7 +6652,8 @@ static void tg3_rx_data_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz) * (to fetch the error flags, vlan tag, checksum, and opaque cookie). */ static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr, - u32 opaque_key, u32 dest_idx_unmasked) + u32 opaque_key, u32 dest_idx_unmasked, + unsigned int *frag_size) { struct tg3_rx_buffer_desc *desc; struct ring_info *map; @@ -5431,7 +6688,13 @@ static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr, */ skb_size = SKB_DATA_ALIGN(data_size + TG3_RX_OFFSET(tp)) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - data = kmalloc(skb_size, GFP_ATOMIC); + if (skb_size <= PAGE_SIZE) { + data = netdev_alloc_frag(skb_size); + *frag_size = skb_size; + } else { + data = kmalloc(skb_size, GFP_ATOMIC); + *frag_size = 0; + } if (!data) return -ENOMEM; @@ -5439,8 +6702,8 @@ static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr, data + TG3_RX_OFFSET(tp), data_size, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(tp->pdev, mapping)) { - kfree(data); + if (unlikely(pci_dma_mapping_error(tp->pdev, mapping))) { + tg3_frag_free(skb_size <= PAGE_SIZE, data); return -EIO; } @@ -5555,6 +6818,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) dma_addr_t dma_addr; u32 opaque_key, desc_idx, *post_ptr; u8 *data; + u64 tstamp = 0; desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; @@ -5574,8 +6838,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) work_mask |= opaque_key; - if ((desc->err_vlan & RXD_ERR_MASK) != 0 && - (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) { + if (desc->err_vlan & RXD_ERR_MASK) { drop_it: tg3_recycle_rx(tnapi, tpr, opaque_key, desc_idx, *post_ptr); @@ -5589,23 +6852,26 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - ETH_FCS_LEN; + if ((desc->type_flags & RXD_FLAG_PTPSTAT_MASK) == + RXD_FLAG_PTPSTAT_PTPV1 || + (desc->type_flags & RXD_FLAG_PTPSTAT_MASK) == + RXD_FLAG_PTPSTAT_PTPV2) { + tstamp = tr32(TG3_RX_TSTAMP_LSB); + tstamp |= (u64)tr32(TG3_RX_TSTAMP_MSB) << 32; + } + if (len > TG3_RX_COPY_THRESH(tp)) { int skb_size; + unsigned int frag_size; skb_size = tg3_alloc_rx_data(tp, tpr, opaque_key, - *post_ptr); + *post_ptr, &frag_size); if (skb_size < 0) goto drop_it; pci_unmap_single(tp->pdev, dma_addr, skb_size, PCI_DMA_FROMDEVICE); - skb = build_skb(data); - if (!skb) { - kfree(data); - goto drop_it_no_recycle; - } - skb_reserve(skb, TG3_RX_OFFSET(tp)); /* Ensure that the update to the data happens * after the usage of the old DMA mapping. */ @@ -5613,6 +6879,12 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) ri->data = NULL; + skb = build_skb(data, frag_size); + if (!skb) { + tg3_frag_free(frag_size != 0, data); + goto drop_it_no_recycle; + } + skb_reserve(skb, TG3_RX_OFFSET(tp)); } else { tg3_recycle_rx(tnapi, tpr, opaque_key, desc_idx, *post_ptr); @@ -5631,6 +6903,10 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) } skb_put(skb, len); + if (tstamp) + tg3_hwclock_to_timestamp(tp, tstamp, + skb_hwtstamps(skb)); + if ((tp->dev->features & NETIF_F_RXCSUM) && (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) && (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK) @@ -5643,13 +6919,13 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) if (len > (tp->dev->mtu + ETH_HLEN) && skb->protocol != htons(ETH_P_8021Q)) { - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); goto drop_it_no_recycle; } if (desc->type_flags & RXD_FLAG_VLAN && !(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG)) - __vlan_hwaccel_put_tag(skb, + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), desc->err_vlan & RXD_VLAN_MASK); napi_gro_receive(&tnapi->napi, skb); @@ -5685,6 +6961,9 @@ next_pkt_nopost: /* Refill RX ring(s). */ if (!tg3_flag(tp, ENABLE_RSS)) { + /* Sync BD data before updating mailbox */ + wmb(); + if (work_mask & RXD_OPAQUE_RING_STD) { tpr->rx_std_prod_idx = std_prod_idx & tp->rx_std_ring_mask; @@ -5707,8 +6986,10 @@ next_pkt_nopost: tpr->rx_std_prod_idx = std_prod_idx & tp->rx_std_ring_mask; tpr->rx_jmb_prod_idx = jmb_prod_idx & tp->rx_jmb_ring_mask; - if (tnapi != &tp->napi[1]) + if (tnapi != &tp->napi[1]) { + tp->rx_refill = true; napi_schedule(&tp->napi[1].napi); + } } return received; @@ -5732,7 +7013,7 @@ static void tg3_poll_link(struct tg3 *tp) MAC_STATUS_LNKSTATE_CHANGED)); udelay(40); } else - tg3_setup_phy(tp, 0); + tg3_setup_phy(tp, false); spin_unlock(&tp->lock); } } @@ -5875,6 +7156,9 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) return work_done; } + if (!tnapi->rx_rcb_prod_idx) + return work_done; + /* run RX thread, within the bounds set by NAPI. * All RX "locking" is done by ensuring outside * code synchronizes with tg3->napi.poll() @@ -5888,7 +7172,8 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) u32 std_prod_idx = dpr->rx_std_prod_idx; u32 jmb_prod_idx = dpr->rx_jmb_prod_idx; - for (i = 1; i < tp->irq_cnt; i++) + tp->rx_refill = false; + for (i = 1; i <= tp->rxq_cnt; i++) err |= tg3_rx_prodring_xfer(tp, dpr, &tp->napi[i].prodring); @@ -5921,6 +7206,7 @@ static inline void tg3_reset_task_cancel(struct tg3 *tp) { cancel_work_sync(&tp->reset_task); tg3_flag_clear(tp, RESET_TASK_PENDING); + tg3_flag_clear(tp, TX_RECOVERY_PENDING); } static int tg3_poll_msix(struct napi_struct *napi, int budget) @@ -5950,9 +7236,25 @@ static int tg3_poll_msix(struct napi_struct *napi, int budget) /* check for RX/TX work to do */ if (likely(sblk->idx[0].tx_consumer == tnapi->tx_cons && *(tnapi->rx_rcb_prod_idx) == tnapi->rx_rcb_ptr)) { + + /* This test here is not race free, but will reduce + * the number of interrupts by looping again. + */ + if (tnapi == &tp->napi[1] && tp->rx_refill) + continue; + napi_complete(napi); /* Reenable interrupts. */ tw32_mailbox(tnapi->int_mbox, tnapi->last_tag << 24); + + /* This test here is synchronized by napi_schedule() + * and napi_complete() to close the race condition. + */ + if (unlikely(tnapi == &tp->napi[1] && tp->rx_refill)) { + tw32(HOSTCC_MODE, tp->coalesce_mode | + HOSTCC_MODE_ENABLE | + tnapi->coal_now); + } mmiowb(); break; } @@ -6086,17 +7388,24 @@ static inline void tg3_netif_stop(struct tg3 *tp) { tp->dev->trans_start = jiffies; /* prevent tx timeout */ tg3_napi_disable(tp); + netif_carrier_off(tp->dev); netif_tx_disable(tp->dev); } +/* tp->lock must be held */ static inline void tg3_netif_start(struct tg3 *tp) { + tg3_ptp_resume(tp); + /* NOTE: unconditional netif_tx_wake_all_queues is only * appropriate so long as all callers are assured to * have free tx slots (such as after tg3_init_hw) */ netif_tx_wake_all_queues(tp->dev); + if (tp->link_up) + netif_carrier_on(tp->dev); + tg3_napi_enable(tp); tp->napi[0].hw_status->status |= SD_STATUS_UPDATED; tg3_enable_ints(tp); @@ -6292,88 +7601,20 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id) return IRQ_RETVAL(0); } -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) - __releases(tp->lock) - __acquires(tp->lock) -{ - int err; - - err = tg3_init_hw(tp, reset_phy); - if (err) { - netdev_err(tp->dev, - "Failed to re-initialize device, aborting\n"); - tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - tg3_full_unlock(tp); - del_timer_sync(&tp->timer); - tp->irq_sync = 0; - tg3_napi_enable(tp); - 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) { int i; struct tg3 *tp = netdev_priv(dev); + if (tg3_irq_sync(tp)) + return; + for (i = 0; i < tp->irq_cnt; i++) tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); } #endif -static void tg3_reset_task(struct work_struct *work) -{ - struct tg3 *tp = container_of(work, struct tg3, reset_task); - int err; - - tg3_full_lock(tp, 0); - - if (!netif_running(tp->dev)) { - tg3_flag_clear(tp, RESET_TASK_PENDING); - tg3_full_unlock(tp); - return; - } - - tg3_full_unlock(tp); - - tg3_phy_stop(tp); - - tg3_netif_stop(tp); - - tg3_full_lock(tp, 1); - - if (tg3_flag(tp, TX_RECOVERY_PENDING)) { - tp->write32_tx_mbox = tg3_write32_tx_mbox; - tp->write32_rx_mbox = tg3_write_flush_reg32; - tg3_flag_set(tp, MBOX_WRITE_REORDER); - tg3_flag_clear(tp, TX_RECOVERY_PENDING); - } - - tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); - err = tg3_init_hw(tp, 1); - if (err) - goto out; - - tg3_netif_start(tp); - -out: - tg3_full_unlock(tp); - - if (!err) - tg3_phy_start(tp); - - tg3_flag_clear(tp, RESET_TASK_PENDING); -} - static void tg3_tx_timeout(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); @@ -6391,7 +7632,21 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) { u32 base = (u32) mapping & 0xffffffff; - return (base > 0xffffdcc0) && (base + len + 8 < base); + return base + len + 8 < base; +} + +/* Test for TSO DMA buffers that cross into regions which are within MSS bytes + * of any 4GB boundaries: 4G, 8G, etc + */ +static inline int tg3_4g_tso_overflow_test(struct tg3 *tp, dma_addr_t mapping, + u32 len, u32 mss) +{ + if (tg3_asic_rev(tp) == ASIC_REV_5762 && mss) { + u32 base = (u32) mapping & 0xffffffff; + + return ((base + len + (mss & 0x3fff)) < base); + } + return 0; } /* Test for DMA addresses > 40-bit */ @@ -6430,6 +7685,9 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget, if (tg3_4g_overflow_test(map, len)) hwbug = true; + if (tg3_4g_tso_overflow_test(tp, map, len, mss)) + hwbug = true; + if (tg3_40bit_overflow_test(tp, map, len)) hwbug = true; @@ -6526,7 +7784,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, dma_addr_t new_addr = 0; int ret = 0; - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) + if (tg3_asic_rev(tp) != ASIC_REV_5701) new_skb = skb_copy(skb, GFP_ATOMIC); else { int more_headroom = 4 - ((unsigned long)skb->data & 3); @@ -6544,7 +7802,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, PCI_DMA_TODEVICE); /* Make sure the mapping succeeded */ if (pci_dma_mapping_error(tp->pdev, new_addr)) { - dev_kfree_skb(new_skb); + dev_kfree_skb_any(new_skb); ret = -1; } else { u32 save_entry = *entry; @@ -6559,13 +7817,13 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, new_skb->len, base_flags, mss, vlan)) { tg3_tx_skb_unmap(tnapi, save_entry, -1); - dev_kfree_skb(new_skb); + dev_kfree_skb_any(new_skb); ret = -1; } } } - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); *pskb = new_skb; return ret; } @@ -6596,8 +7854,8 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) netif_wake_queue(tp->dev); } - segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO); - if (IS_ERR(segs)) + segs = skb_gso_segment(skb, tp->dev->features & ~(NETIF_F_TSO | NETIF_F_TSO6)); + if (IS_ERR(segs) || !segs) goto tg3_tso_bug_end; do { @@ -6608,14 +7866,12 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) } while (segs); tg3_tso_bug_end: - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return NETDEV_TX_OK; } -/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and - * support TG3_FLAG_HW_TSO_1 or firmware TSO only. - */ +/* hard_start_xmit for all devices */ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); @@ -6626,6 +7882,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) struct tg3_napi *tnapi; struct netdev_queue *txq; unsigned int last; + struct iphdr *iph = NULL; + struct tcphdr *tcph = NULL; + __sum16 tcp_csum = 0, ip_csum = 0; + __be16 ip_tot_len = 0; txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); tnapi = &tp->napi[skb_get_queue_mapping(skb)]; @@ -6657,11 +7917,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) mss = skb_shinfo(skb)->gso_size; if (mss) { - struct iphdr *iph; u32 tcp_opt_len, hdr_len; - if (skb_header_cloned(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + if (skb_cow_head(skb, 0)) goto drop; iph = ip_hdr(skb); @@ -6670,27 +7928,31 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN; if (!skb_is_gso_v6(skb)) { + if (unlikely((ETH_HLEN + hdr_len) > 80) && + tg3_flag(tp, TSO_BUG)) + return tg3_tso_bug(tp, skb); + + ip_csum = iph->check; + ip_tot_len = iph->tot_len; iph->check = 0; iph->tot_len = htons(mss + hdr_len); } - if (unlikely((ETH_HLEN + hdr_len) > 80) && - tg3_flag(tp, TSO_BUG)) - return tg3_tso_bug(tp, skb); - base_flags |= (TXD_FLAG_CPU_PRE_DMA | TXD_FLAG_CPU_POST_DMA); + tcph = tcp_hdr(skb); + tcp_csum = tcph->check; + if (tg3_flag(tp, HW_TSO_1) || tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3)) { - tcp_hdr(skb)->check = 0; + tcph->check = 0; base_flags &= ~TXD_FLAG_TCPUDP_CSUM; - } else - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); + } else { + tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, + 0, IPPROTO_TCP, 0); + } if (tg3_flag(tp, HW_TSO_3)) { mss |= (hdr_len & 0xc) << 12; @@ -6700,7 +7962,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) } else if (tg3_flag(tp, HW_TSO_2)) mss |= hdr_len << 9; else if (tg3_flag(tp, HW_TSO_1) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + tg3_asic_rev(tp) == ASIC_REV_5705) { if (tcp_opt_len || iph->ihl > 5) { int tsflags; @@ -6726,6 +7988,12 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) vlan = vlan_tx_tag_get(skb); } + if ((unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) && + tg3_flag(tp, TX_TSTAMP_EN)) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + base_flags |= TXD_FLAG_HWTSTAMP; + } + len = skb_headlen(skb); mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE); @@ -6745,7 +8013,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0), mss, vlan)) { would_hit_hwbug = 1; - /* Now loop through additional data fragments, and queue them. */ } else if (skb_shinfo(skb)->nr_frags > 0) { u32 tmp_mss = mss; @@ -6754,6 +8021,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) !tg3_flag(tp, HW_TSO_3)) tmp_mss = 0; + /* Now loop through additional data + * fragments, and queue them. + */ last = skb_shinfo(skb)->nr_frags - 1; for (i = 0; i <= last; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -6782,6 +8052,18 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) if (would_hit_hwbug) { tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i); + if (mss) { + /* If it's a TSO packet, do GSO instead of + * allocating and copying to a large linear SKB + */ + if (ip_tot_len) { + iph->check = ip_csum; + iph->tot_len = ip_tot_len; + } + tcph->check = tcp_csum; + return tg3_tso_bug(tp, skb); + } + /* If the workaround fails due to memory/mapping * failure, silently drop this packet. */ @@ -6793,7 +8075,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) } skb_tx_timestamp(skb); - netdev_sent_queue(tp->dev, skb->len); + netdev_tx_sent_queue(txq, skb->len); + + /* Sync BD data before updating mailbox */ + wmb(); /* Packets are ready, update Tx producer idx local and on card. */ tw32_tx_mbox(tnapi->prodmbox, entry); @@ -6819,7 +8104,7 @@ dma_error: tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, --i); tnapi->tx_buffers[tnapi->tx_prod].skb = NULL; drop: - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); drop_nofree: tp->tx_dropped++; return NETDEV_TX_OK; @@ -6845,7 +8130,7 @@ static void tg3_mac_loopback(struct tg3 *tp, bool enable) if (tg3_flag(tp, 5705_PLUS) || (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) + tg3_asic_rev(tp) == ASIC_REV_5700) tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; } @@ -6858,7 +8143,7 @@ static int tg3_phy_lpbk_set(struct tg3 *tp, u32 speed, bool extlpbk) u32 val, bmcr, mac_mode, ptest = 0; tg3_phy_toggle_apd(tp, false); - tg3_phy_toggle_automdix(tp, 0); + tg3_phy_toggle_automdix(tp, false); if (extlpbk && tg3_phy_set_extloopbk(tp)) return -EIO; @@ -6904,7 +8189,7 @@ static int tg3_phy_lpbk_set(struct tg3 *tp, u32 speed, bool extlpbk) udelay(40); if ((tp->phy_flags & TG3_PHYFLG_IS_FET) && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { + tg3_asic_rev(tp) == ASIC_REV_5785) { tg3_writephy(tp, MII_TG3_FET_PTEST, ptest | MII_TG3_FET_PTEST_FRC_TX_LINK | MII_TG3_FET_PTEST_FRC_TX_LOCK); @@ -6928,7 +8213,7 @@ static int tg3_phy_lpbk_set(struct tg3 *tp, u32 speed, bool extlpbk) else mac_mode |= MAC_MODE_PORT_MODE_MII; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { + if (tg3_asic_rev(tp) == ASIC_REV_5700) { u32 masked_phy_id = tp->phy_id & TG3_PHY_ID_MASK; if (masked_phy_id == TG3_PHY_ID_BCM5401) @@ -6966,7 +8251,7 @@ static void tg3_set_loopback(struct net_device *dev, netdev_features_t features) spin_lock_bh(&tp->lock); tg3_mac_loopback(tp, false); /* Force link status check */ - tg3_setup_phy(tp, 1); + tg3_setup_phy(tp, true); spin_unlock_bh(&tp->lock); netdev_info(dev, "Internal MAC loopback mode disabled.\n"); } @@ -6993,66 +8278,6 @@ static int tg3_set_features(struct net_device *dev, netdev_features_t features) return 0; } -static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, - int new_mtu) -{ - dev->mtu = new_mtu; - - if (new_mtu > ETH_DATA_LEN) { - if (tg3_flag(tp, 5780_CLASS)) { - netdev_update_features(dev); - tg3_flag_clear(tp, TSO_CAPABLE); - } else { - tg3_flag_set(tp, JUMBO_RING_ENABLE); - } - } else { - if (tg3_flag(tp, 5780_CLASS)) { - tg3_flag_set(tp, TSO_CAPABLE); - netdev_update_features(dev); - } - tg3_flag_clear(tp, JUMBO_RING_ENABLE); - } -} - -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; - - if (!netif_running(dev)) { - /* We'll just catch it later when the - * device is up'd. - */ - tg3_set_mtu(dev, tp, new_mtu); - return 0; - } - - tg3_phy_stop(tp); - - tg3_netif_stop(tp); - - tg3_full_lock(tp, 1); - - tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - - tg3_set_mtu(dev, tp, new_mtu); - - err = tg3_restart_hw(tp, 0); - - if (!err) - tg3_netif_start(tp); - - tg3_full_unlock(tp); - - if (!err) - tg3_phy_start(tp); - - return err; -} - static void tg3_rx_prodring_free(struct tg3 *tp, struct tg3_rx_prodring_set *tpr) { @@ -7138,7 +8363,10 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, /* Now allocate fresh SKBs for each rx ring. */ for (i = 0; i < tp->rx_pending; i++) { - if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_STD, i) < 0) { + unsigned int frag_size; + + if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_STD, i, + &frag_size) < 0) { netdev_warn(tp->dev, "Using a smaller RX standard ring. Only " "%d out of %d buffers were allocated " @@ -7170,7 +8398,10 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, } for (i = 0; i < tp->rx_jumbo_pending; i++) { - if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_JUMBO, i) < 0) { + unsigned int frag_size; + + if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_JUMBO, i, + &frag_size) < 0) { netdev_warn(tp->dev, "Using a smaller RX jumbo ring. Only %d " "out of %d buffers were allocated " @@ -7275,8 +8506,8 @@ static void tg3_free_rings(struct tg3 *tp) dev_kfree_skb_any(skb); } + netdev_tx_reset_queue(netdev_get_tx_queue(tp->dev, j)); } - netdev_reset_queue(tp->dev); } /* Initialize tx/rx rings for packet processing. @@ -7320,15 +8551,11 @@ static int tg3_init_rings(struct tg3 *tp) return 0; } -/* - * Must not be invoked with interrupt sources disabled and - * the hardware shutdown down. - */ -static void tg3_free_consistent(struct tg3 *tp) +static void tg3_mem_tx_release(struct tg3 *tp) { int i; - for (i = 0; i < tp->irq_cnt; i++) { + for (i = 0; i < tp->irq_max; i++) { struct tg3_napi *tnapi = &tp->napi[i]; if (tnapi->tx_ring) { @@ -7339,17 +8566,112 @@ static void tg3_free_consistent(struct tg3 *tp) kfree(tnapi->tx_buffers); tnapi->tx_buffers = NULL; + } +} - if (tnapi->rx_rcb) { - dma_free_coherent(&tp->pdev->dev, - TG3_RX_RCB_RING_BYTES(tp), - tnapi->rx_rcb, - tnapi->rx_rcb_mapping); - tnapi->rx_rcb = NULL; - } +static int tg3_mem_tx_acquire(struct tg3 *tp) +{ + int i; + struct tg3_napi *tnapi = &tp->napi[0]; + + /* If multivector TSS is enabled, vector 0 does not handle + * tx interrupts. Don't allocate any resources for it. + */ + if (tg3_flag(tp, ENABLE_TSS)) + tnapi++; + + for (i = 0; i < tp->txq_cnt; i++, tnapi++) { + tnapi->tx_buffers = kzalloc(sizeof(struct tg3_tx_ring_info) * + TG3_TX_RING_SIZE, GFP_KERNEL); + if (!tnapi->tx_buffers) + goto err_out; + + tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev, + TG3_TX_RING_BYTES, + &tnapi->tx_desc_mapping, + GFP_KERNEL); + if (!tnapi->tx_ring) + goto err_out; + } + + return 0; + +err_out: + tg3_mem_tx_release(tp); + return -ENOMEM; +} + +static void tg3_mem_rx_release(struct tg3 *tp) +{ + int i; + + for (i = 0; i < tp->irq_max; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; tg3_rx_prodring_fini(tp, &tnapi->prodring); + if (!tnapi->rx_rcb) + continue; + + dma_free_coherent(&tp->pdev->dev, + TG3_RX_RCB_RING_BYTES(tp), + tnapi->rx_rcb, + tnapi->rx_rcb_mapping); + tnapi->rx_rcb = NULL; + } +} + +static int tg3_mem_rx_acquire(struct tg3 *tp) +{ + unsigned int i, limit; + + limit = tp->rxq_cnt; + + /* If RSS is enabled, we need a (dummy) producer ring + * set on vector zero. This is the true hw prodring. + */ + if (tg3_flag(tp, ENABLE_RSS)) + limit++; + + for (i = 0; i < limit; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + + if (tg3_rx_prodring_init(tp, &tnapi->prodring)) + goto err_out; + + /* If multivector RSS is enabled, vector 0 + * does not handle rx or tx interrupts. + * Don't allocate any resources for it. + */ + if (!i && tg3_flag(tp, ENABLE_RSS)) + continue; + + tnapi->rx_rcb = dma_zalloc_coherent(&tp->pdev->dev, + TG3_RX_RCB_RING_BYTES(tp), + &tnapi->rx_rcb_mapping, + GFP_KERNEL); + if (!tnapi->rx_rcb) + goto err_out; + } + + return 0; + +err_out: + tg3_mem_rx_release(tp); + return -ENOMEM; +} + +/* + * Must not be invoked with interrupt sources disabled and + * the hardware shutdown down. + */ +static void tg3_free_consistent(struct tg3 *tp) +{ + int i; + + for (i = 0; i < tp->irq_cnt; i++) { + struct tg3_napi *tnapi = &tp->napi[i]; + if (tnapi->hw_status) { dma_free_coherent(&tp->pdev->dev, TG3_HW_STATUS_SIZE, tnapi->hw_status, @@ -7358,6 +8680,9 @@ static void tg3_free_consistent(struct tg3 *tp) } } + tg3_mem_rx_release(tp); + tg3_mem_tx_release(tp); + if (tp->hw_stats) { dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats), tp->hw_stats, tp->stats_mapping); @@ -7373,89 +8698,57 @@ static int tg3_alloc_consistent(struct tg3 *tp) { int i; - tp->hw_stats = dma_alloc_coherent(&tp->pdev->dev, - sizeof(struct tg3_hw_stats), - &tp->stats_mapping, - GFP_KERNEL); + tp->hw_stats = dma_zalloc_coherent(&tp->pdev->dev, + sizeof(struct tg3_hw_stats), + &tp->stats_mapping, GFP_KERNEL); if (!tp->hw_stats) goto err_out; - memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); - for (i = 0; i < tp->irq_cnt; i++) { struct tg3_napi *tnapi = &tp->napi[i]; struct tg3_hw_status *sblk; - tnapi->hw_status = dma_alloc_coherent(&tp->pdev->dev, - TG3_HW_STATUS_SIZE, - &tnapi->status_mapping, - GFP_KERNEL); + tnapi->hw_status = dma_zalloc_coherent(&tp->pdev->dev, + TG3_HW_STATUS_SIZE, + &tnapi->status_mapping, + GFP_KERNEL); if (!tnapi->hw_status) goto err_out; - memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); sblk = tnapi->hw_status; - if (tg3_rx_prodring_init(tp, &tnapi->prodring)) - goto err_out; + if (tg3_flag(tp, ENABLE_RSS)) { + u16 *prodptr = NULL; - /* If multivector TSS is enabled, vector 0 does not handle - * tx interrupts. Don't allocate any resources for it. - */ - if ((!i && !tg3_flag(tp, ENABLE_TSS)) || - (i && tg3_flag(tp, ENABLE_TSS))) { - tnapi->tx_buffers = kzalloc( - sizeof(struct tg3_tx_ring_info) * - TG3_TX_RING_SIZE, GFP_KERNEL); - if (!tnapi->tx_buffers) - goto err_out; - - tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev, - TG3_TX_RING_BYTES, - &tnapi->tx_desc_mapping, - GFP_KERNEL); - if (!tnapi->tx_ring) - goto err_out; - } - - /* - * When RSS is enabled, the status block format changes - * slightly. The "rx_jumbo_consumer", "reserved", - * and "rx_mini_consumer" members get mapped to the - * other three rx return ring producer indexes. - */ - switch (i) { - default: + /* + * When RSS is enabled, the status block format changes + * slightly. The "rx_jumbo_consumer", "reserved", + * and "rx_mini_consumer" members get mapped to the + * other three rx return ring producer indexes. + */ + switch (i) { + case 1: + prodptr = &sblk->idx[0].rx_producer; + break; + case 2: + prodptr = &sblk->rx_jumbo_consumer; + break; + case 3: + prodptr = &sblk->reserved; + break; + case 4: + prodptr = &sblk->rx_mini_consumer; + break; + } + tnapi->rx_rcb_prod_idx = prodptr; + } else { tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer; - break; - case 2: - tnapi->rx_rcb_prod_idx = &sblk->rx_jumbo_consumer; - break; - case 3: - tnapi->rx_rcb_prod_idx = &sblk->reserved; - break; - case 4: - tnapi->rx_rcb_prod_idx = &sblk->rx_mini_consumer; - break; } - - /* - * If multivector RSS is enabled, vector 0 does not handle - * rx or tx interrupts. Don't allocate any resources for it. - */ - if (!i && tg3_flag(tp, ENABLE_RSS)) - continue; - - tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev, - TG3_RX_RCB_RING_BYTES(tp), - &tnapi->rx_rcb_mapping, - GFP_KERNEL); - if (!tnapi->rx_rcb) - goto err_out; - - memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); } + if (tg3_mem_tx_acquire(tp) || tg3_mem_rx_acquire(tp)) + goto err_out; + return 0; err_out: @@ -7468,7 +8761,7 @@ err_out: /* To stop a block, clear the enable bit and poll till it * clears. tp->lock is held. */ -static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int silent) +static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, bool silent) { unsigned int i; u32 val; @@ -7495,6 +8788,14 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int tw32_f(ofs, val); for (i = 0; i < MAX_WAIT_CNT; i++) { + if (pci_channel_offline(tp->pdev)) { + dev_err(&tp->pdev->dev, + "tg3_stop_block device offline, " + "ofs=%lx enable_bit=%x\n", + ofs, enable_bit); + return -ENODEV; + } + udelay(100); val = tr32(ofs); if ((val & enable_bit) == 0) @@ -7512,12 +8813,19 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int } /* tp->lock is held. */ -static int tg3_abort_hw(struct tg3 *tp, int silent) +static int tg3_abort_hw(struct tg3 *tp, bool silent) { int i, err; tg3_disable_ints(tp); + if (pci_channel_offline(tp->pdev)) { + tp->rx_mode &= ~(RX_MODE_ENABLE | TX_MODE_ENABLE); + tp->mac_mode &= ~MAC_MODE_TDE_ENABLE; + err = -ENODEV; + goto err_no_dev; + } + tp->rx_mode &= ~RX_MODE_ENABLE; tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); @@ -7566,6 +8874,7 @@ static int tg3_abort_hw(struct tg3 *tp, int silent) err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE, silent); err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE, silent); +err_no_dev: for (i = 0; i < tp->irq_cnt; i++) { struct tg3_napi *tnapi = &tp->napi[i]; if (tnapi->hw_status) @@ -7592,7 +8901,7 @@ static void tg3_restore_pci_state(struct tg3 *tp) /* Set MAX PCI retry to zero. */ val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE); - if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5704_A0 && tg3_flag(tp, PCIX_MODE)) val |= PCISTATE_RETRY_SAME_DMA; /* Allow reads and writes to the APE register and memory space. */ @@ -7642,6 +8951,49 @@ static void tg3_restore_pci_state(struct tg3 *tp) } } +static void tg3_override_clk(struct tg3 *tp) +{ + u32 val; + + switch (tg3_asic_rev(tp)) { + case ASIC_REV_5717: + val = tr32(TG3_CPMU_CLCK_ORIDE_ENABLE); + tw32(TG3_CPMU_CLCK_ORIDE_ENABLE, val | + TG3_CPMU_MAC_ORIDE_ENABLE); + break; + + case ASIC_REV_5719: + case ASIC_REV_5720: + tw32(TG3_CPMU_CLCK_ORIDE, CPMU_CLCK_ORIDE_MAC_ORIDE_EN); + break; + + default: + return; + } +} + +static void tg3_restore_clk(struct tg3 *tp) +{ + u32 val; + + switch (tg3_asic_rev(tp)) { + case ASIC_REV_5717: + val = tr32(TG3_CPMU_CLCK_ORIDE_ENABLE); + tw32(TG3_CPMU_CLCK_ORIDE_ENABLE, + val & ~TG3_CPMU_MAC_ORIDE_ENABLE); + break; + + case ASIC_REV_5719: + case ASIC_REV_5720: + val = tr32(TG3_CPMU_CLCK_ORIDE); + tw32(TG3_CPMU_CLCK_ORIDE, val & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN); + break; + + default: + return; + } +} + /* tp->lock is held. */ static int tg3_chip_reset(struct tg3 *tp) { @@ -7649,6 +9001,9 @@ static int tg3_chip_reset(struct tg3 *tp) void (*write_op)(struct tg3 *, u32, u32); int i, err; + if (!pci_device_is_present(tp->pdev)) + return -ENODEV; + tg3_nvram_lock(tp); tg3_ape_lock(tp, TG3_APE_LOCK_GRC); @@ -7664,7 +9019,7 @@ static int tg3_chip_reset(struct tg3 *tp) */ tg3_save_pci_state(tp); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + if (tg3_asic_rev(tp) == ASIC_REV_5752 || tg3_flag(tp, 5755_PLUS)) tw32(GRC_FASTBOOT_PC, 0); @@ -7699,7 +9054,7 @@ static int tg3_chip_reset(struct tg3 *tp) for (i = 0; i < tp->irq_cnt; i++) synchronize_irq(tp->napi[i].irq_vec); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { + if (tg3_asic_rev(tp) == ASIC_REV_57780) { val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN; tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS); } @@ -7709,24 +9064,31 @@ static int tg3_chip_reset(struct tg3 *tp) if (tg3_flag(tp, PCI_EXPRESS)) { /* Force PCIe 1.0a mode */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && + if (tg3_asic_rev(tp) != ASIC_REV_5785 && !tg3_flag(tp, 57765_PLUS) && tr32(TG3_PCIE_PHY_TSTCTL) == (TG3_PCIE_PHY_TSTCTL_PCIE10 | TG3_PCIE_PHY_TSTCTL_PSCRAM)) tw32(TG3_PCIE_PHY_TSTCTL, TG3_PCIE_PHY_TSTCTL_PSCRAM); - if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) { + if (tg3_chip_rev_id(tp) != CHIPREV_ID_5750_A0) { tw32(GRC_MISC_CFG, (1 << 29)); val |= (1 << 29); } } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (tg3_asic_rev(tp) == 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); } + /* Set the clock to the highest frequency to avoid timeouts. With link + * aware mode, the clock speed could be slow and bootcode does not + * complete within the expected time. Override the clock to allow the + * bootcode to finish sooner and then restore it. + */ + tg3_override_clk(tp); + /* Manage gphy power for all CPMU absent PCIe devices. */ if (tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, CPMU_PRESENT)) val |= GRC_MISC_CFG_KEEP_GPHY_POWER; @@ -7761,15 +9123,15 @@ static int tg3_chip_reset(struct tg3 *tp) udelay(120); - if (tg3_flag(tp, PCI_EXPRESS) && pci_pcie_cap(tp->pdev)) { + if (tg3_flag(tp, PCI_EXPRESS) && pci_is_pcie(tp->pdev)) { u16 val16; - if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) { - int i; + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5750_A0) { + int j; u32 cfg_val; /* Wait for link training to complete. */ - for (i = 0; i < 5000; i++) + for (j = 0; j < 5000; j++) udelay(100); pci_read_config_dword(tp->pdev, 0xc4, &cfg_val); @@ -7778,24 +9140,17 @@ static int tg3_chip_reset(struct tg3 *tp) } /* Clear the "no snoop" and "relaxed ordering" bits. */ - pci_read_config_word(tp->pdev, - pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL, - &val16); - val16 &= ~(PCI_EXP_DEVCTL_RELAX_EN | - PCI_EXP_DEVCTL_NOSNOOP_EN); + val16 = PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN; /* * Older PCIe devices only support the 128 byte * MPS setting. Enforce the restriction. */ if (!tg3_flag(tp, CPMU_PRESENT)) - val16 &= ~PCI_EXP_DEVCTL_PAYLOAD; - pci_write_config_word(tp->pdev, - pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL, - val16); + val16 |= PCI_EXP_DEVCTL_PAYLOAD; + pcie_capability_clear_word(tp->pdev, PCI_EXP_DEVCTL, val16); /* Clear error status */ - pci_write_config_word(tp->pdev, - pci_pcie_cap(tp->pdev) + PCI_EXP_DEVSTA, + pcie_capability_write_word(tp->pdev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_CED | PCI_EXP_DEVSTA_NFED | PCI_EXP_DEVSTA_FED | @@ -7812,23 +9167,37 @@ static int tg3_chip_reset(struct tg3 *tp) val = tr32(MEMARB_MODE); tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); - if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) { + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5750_A3) { tg3_stop_fw(tp); tw32(0x5000, 0x400); } + if (tg3_flag(tp, IS_SSB_CORE)) { + /* + * BCM4785: In order to avoid repercussions from using + * potentially defective internal ROM, stop the Rx RISC CPU, + * which is not required. + */ + tg3_stop_fw(tp); + tg3_halt_cpu(tp, RX_CPU_BASE); + } + + err = tg3_poll_fw(tp); + if (err) + return err; + tw32(GRC_MODE, tp->grc_mode); - if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) { + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A0) { val = tr32(0xc4); tw32(0xc4, val | (1 << 15)); } if ((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0 && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + tg3_asic_rev(tp) == ASIC_REV_5705) { tp->pci_clock_ctrl |= CLOCK_CTRL_CLKRUN_OENABLE; - if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A0) tp->pci_clock_ctrl |= CLOCK_CTRL_FORCE_CLKRUN; tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } @@ -7847,28 +9216,24 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_ape_unlock(tp, TG3_APE_LOCK_GRC); - err = tg3_poll_fw(tp); - if (err) - return err; - tg3_mdio_start(tp); if (tg3_flag(tp, PCI_EXPRESS) && - tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && + tg3_chip_rev_id(tp) != CHIPREV_ID_5750_A0 && + tg3_asic_rev(tp) != ASIC_REV_5785 && !tg3_flag(tp, 57765_PLUS)) { val = tr32(0x7c00); tw32(0x7c00, val | (1 << 25)); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { - val = tr32(TG3_CPMU_CLCK_ORIDE); - tw32(TG3_CPMU_CLCK_ORIDE, val & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN); - } + tg3_restore_clk(tp); /* Reprobe ASF enable state. */ tg3_flag_clear(tp, ENABLE_ASF); + tp->phy_flags &= ~(TG3_PHYFLG_1G_ON_VAUX_OK | + TG3_PHYFLG_KEEP_LINK_ON_PWRDN); + tg3_flag_clear(tp, ASF_NEW_HANDSHAKE); tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { @@ -7880,19 +9245,24 @@ static int tg3_chip_reset(struct tg3 *tp) tp->last_event_jiffies = jiffies; if (tg3_flag(tp, 5750_PLUS)) tg3_flag_set(tp, ASF_NEW_HANDSHAKE); + + tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &nic_cfg); + if (nic_cfg & NIC_SRAM_1G_ON_VAUX_OK) + tp->phy_flags |= TG3_PHYFLG_1G_ON_VAUX_OK; + if (nic_cfg & NIC_SRAM_LNK_FLAP_AVOID) + tp->phy_flags |= TG3_PHYFLG_KEEP_LINK_ON_PWRDN; } } return 0; } -static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *, - struct rtnl_link_stats64 *); -static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *, - struct tg3_ethtool_stats *); +static void tg3_get_nstats(struct tg3 *, struct rtnl_link_stats64 *); +static void tg3_get_estats(struct tg3 *, struct tg3_ethtool_stats *); +static void __tg3_set_rx_mode(struct net_device *); /* tp->lock is held. */ -static int tg3_halt(struct tg3 *tp, int kind, int silent) +static int tg3_halt(struct tg3 *tp, int kind, bool silent) { int err; @@ -7903,34 +9273,32 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent) tg3_abort_hw(tp, silent); err = tg3_chip_reset(tp); - __tg3_set_mac_addr(tp, 0); + __tg3_set_mac_addr(tp, false); tg3_write_sig_legacy(tp, kind); tg3_write_sig_post_reset(tp, kind); if (tp->hw_stats) { /* Save the stats across chip resets... */ - tg3_get_stats64(tp->dev, &tp->net_stats_prev), + tg3_get_nstats(tp, &tp->net_stats_prev); tg3_get_estats(tp, &tp->estats_prev); /* And make sure the next sample is new data */ memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); } - if (err) - return err; - - return 0; + return err; } 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, skip_mac_1 = 0; + int err = 0; + bool skip_mac_1 = false; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); @@ -7948,10 +9316,11 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) /* Skip MAC addr 1 if ASF is using it. */ if ((addr0_high != addr1_high || addr0_low != addr1_low) && !(addr1_high == 0 && addr1_low == 0)) - skip_mac_1 = 1; + skip_mac_1 = true; } spin_lock_bh(&tp->lock); __tg3_set_mac_addr(tp, skip_mac_1); + __tg3_set_rx_mode(dev); spin_unlock_bh(&tp->lock); return err; @@ -7978,10 +9347,10 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, nic_addr); } -static void __tg3_set_rx_mode(struct net_device *); -static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) + +static void tg3_coal_tx_init(struct tg3 *tp, struct ethtool_coalesce *ec) { - int i; + int i = 0; if (!tg3_flag(tp, ENABLE_TSS)) { tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs); @@ -7991,31 +9360,43 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) tw32(HOSTCC_TXCOL_TICKS, 0); tw32(HOSTCC_TXMAX_FRAMES, 0); tw32(HOSTCC_TXCOAL_MAXF_INT, 0); + + for (; i < tp->txq_cnt; i++) { + u32 reg; + + reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18; + tw32(reg, ec->tx_coalesce_usecs); + reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18; + tw32(reg, ec->tx_max_coalesced_frames); + reg = HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18; + tw32(reg, ec->tx_max_coalesced_frames_irq); + } } + for (; i < tp->irq_max - 1; i++) { + tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0); + tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0); + tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); + } +} + +static void tg3_coal_rx_init(struct tg3 *tp, struct ethtool_coalesce *ec) +{ + int i = 0; + u32 limit = tp->rxq_cnt; + if (!tg3_flag(tp, ENABLE_RSS)) { tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs); tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames); tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq); + limit--; } else { tw32(HOSTCC_RXCOL_TICKS, 0); tw32(HOSTCC_RXMAX_FRAMES, 0); tw32(HOSTCC_RXCOAL_MAXF_INT, 0); } - if (!tg3_flag(tp, 5705_PLUS)) { - u32 val = ec->stats_block_coalesce_usecs; - - tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq); - tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq); - - if (!netif_carrier_ok(tp->dev)) - val = 0; - - tw32(HOSTCC_STAT_COAL_TICKS, val); - } - - for (i = 0; i < tp->irq_cnt - 1; i++) { + for (; i < limit; i++) { u32 reg; reg = HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18; @@ -8024,43 +9405,45 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) tw32(reg, ec->rx_max_coalesced_frames); reg = HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18; tw32(reg, ec->rx_max_coalesced_frames_irq); - - if (tg3_flag(tp, ENABLE_TSS)) { - reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18; - tw32(reg, ec->tx_coalesce_usecs); - reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18; - tw32(reg, ec->tx_max_coalesced_frames); - reg = HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18; - tw32(reg, ec->tx_max_coalesced_frames_irq); - } } for (; i < tp->irq_max - 1; i++) { tw32(HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18, 0); tw32(HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18, 0); tw32(HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); + } +} - if (tg3_flag(tp, ENABLE_TSS)) { - tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0); - tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0); - tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0); - } +static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) +{ + tg3_coal_tx_init(tp, ec); + tg3_coal_rx_init(tp, ec); + + if (!tg3_flag(tp, 5705_PLUS)) { + u32 val = ec->stats_block_coalesce_usecs; + + tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq); + tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq); + + if (!tp->link_up) + val = 0; + + tw32(HOSTCC_STAT_COAL_TICKS, val); } } /* tp->lock is held. */ -static void tg3_rings_reset(struct tg3 *tp) +static void tg3_tx_rcbs_disable(struct tg3 *tp) { - int i; - u32 stblk, txrcb, rxrcb, limit; - struct tg3_napi *tnapi = &tp->napi[0]; + u32 txrcb, limit; /* Disable all transmit rings but the first. */ if (!tg3_flag(tp, 5705_PLUS)) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16; else if (tg3_flag(tp, 5717_PLUS)) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4; - else if (tg3_flag(tp, 57765_CLASS)) + else if (tg3_flag(tp, 57765_CLASS) || + tg3_asic_rev(tp) == ASIC_REV_5762) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2; else limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE; @@ -8069,14 +9452,41 @@ static void tg3_rings_reset(struct tg3 *tp) txrcb < limit; txrcb += TG3_BDINFO_SIZE) tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED); +} + +/* tp->lock is held. */ +static void tg3_tx_rcbs_init(struct tg3 *tp) +{ + int i = 0; + u32 txrcb = NIC_SRAM_SEND_RCB; + + if (tg3_flag(tp, ENABLE_TSS)) + i++; + + for (; i < tp->irq_max; i++, txrcb += TG3_BDINFO_SIZE) { + struct tg3_napi *tnapi = &tp->napi[i]; + if (!tnapi->tx_ring) + continue; + + tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping, + (TG3_TX_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT), + NIC_SRAM_TX_BUFFER_DESC); + } +} + +/* tp->lock is held. */ +static void tg3_rx_ret_rcbs_disable(struct tg3 *tp) +{ + u32 rxrcb, limit; /* Disable all receive return rings but the first. */ if (tg3_flag(tp, 5717_PLUS)) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17; else if (!tg3_flag(tp, 5705_PLUS)) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16; - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + else if (tg3_asic_rev(tp) == ASIC_REV_5755 || + tg3_asic_rev(tp) == ASIC_REV_5762 || tg3_flag(tp, 57765_CLASS)) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4; else @@ -8086,6 +9496,39 @@ static void tg3_rings_reset(struct tg3 *tp) rxrcb < limit; rxrcb += TG3_BDINFO_SIZE) tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED); +} + +/* tp->lock is held. */ +static void tg3_rx_ret_rcbs_init(struct tg3 *tp) +{ + int i = 0; + u32 rxrcb = NIC_SRAM_RCV_RET_RCB; + + if (tg3_flag(tp, ENABLE_RSS)) + i++; + + for (; i < tp->irq_max; i++, rxrcb += TG3_BDINFO_SIZE) { + struct tg3_napi *tnapi = &tp->napi[i]; + + if (!tnapi->rx_rcb) + continue; + + tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping, + (tp->rx_ret_ring_mask + 1) << + BDINFO_FLAGS_MAXLEN_SHIFT, 0); + } +} + +/* tp->lock is held. */ +static void tg3_rings_reset(struct tg3 *tp) +{ + int i; + u32 stblk; + struct tg3_napi *tnapi = &tp->napi[0]; + + tg3_tx_rcbs_disable(tp); + + tg3_rx_ret_rcbs_disable(tp); /* Disable interrupts */ tw32_mailbox_f(tp->napi[0].int_mbox, 1); @@ -8122,9 +9565,6 @@ static void tg3_rings_reset(struct tg3 *tp) tw32_tx_mbox(mbox + i * 8, 0); } - txrcb = NIC_SRAM_SEND_RCB; - rxrcb = NIC_SRAM_RCV_RET_RCB; - /* Clear status block in ram. */ memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); @@ -8134,46 +9574,20 @@ static void tg3_rings_reset(struct tg3 *tp) tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tnapi->status_mapping & 0xffffffff)); - if (tnapi->tx_ring) { - tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping, - (TG3_TX_RING_SIZE << - BDINFO_FLAGS_MAXLEN_SHIFT), - NIC_SRAM_TX_BUFFER_DESC); - txrcb += TG3_BDINFO_SIZE; - } - - if (tnapi->rx_rcb) { - tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping, - (tp->rx_ret_ring_mask + 1) << - BDINFO_FLAGS_MAXLEN_SHIFT, 0); - rxrcb += TG3_BDINFO_SIZE; - } - stblk = HOSTCC_STATBLCK_RING1; for (i = 1, tnapi++; i < tp->irq_cnt; i++, tnapi++) { u64 mapping = (u64)tnapi->status_mapping; tw32(stblk + TG3_64BIT_REG_HIGH, mapping >> 32); tw32(stblk + TG3_64BIT_REG_LOW, mapping & 0xffffffff); + stblk += 8; /* Clear status block in ram. */ memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); - - if (tnapi->tx_ring) { - tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping, - (TG3_TX_RING_SIZE << - BDINFO_FLAGS_MAXLEN_SHIFT), - NIC_SRAM_TX_BUFFER_DESC); - txrcb += TG3_BDINFO_SIZE; - } - - tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping, - ((tp->rx_ret_ring_mask + 1) << - BDINFO_FLAGS_MAXLEN_SHIFT), 0); - - stblk += 8; - rxrcb += TG3_BDINFO_SIZE; } + + tg3_tx_rcbs_init(tp); + tg3_rx_ret_rcbs_init(tp); } static void tg3_setup_rxbd_thresholds(struct tg3 *tp) @@ -8182,12 +9596,12 @@ static void tg3_setup_rxbd_thresholds(struct tg3 *tp) if (!tg3_flag(tp, 5750_PLUS) || tg3_flag(tp, 5780_CLASS) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + tg3_asic_rev(tp) == ASIC_REV_5750 || + tg3_asic_rev(tp) == ASIC_REV_5752 || tg3_flag(tp, 57765_PLUS)) bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5700; - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + else if (tg3_asic_rev(tp) == ASIC_REV_5755 || + tg3_asic_rev(tp) == ASIC_REV_5787) bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5755; else bdcache_maxcnt = TG3_SRAM_RX_STD_BDCACHE_SIZE_5906; @@ -8215,13 +9629,113 @@ static void tg3_setup_rxbd_thresholds(struct tg3 *tp) tw32(JMB_REPLENISH_LWM, bdcache_maxcnt); } -static void tg3_rss_init_dflt_indir_tbl(struct tg3 *tp) +static inline u32 calc_crc(unsigned char *buf, int len) +{ + u32 reg; + u32 tmp; + int j, k; + + reg = 0xffffffff; + + for (j = 0; j < len; j++) { + reg ^= buf[j]; + + for (k = 0; k < 8; k++) { + tmp = reg & 0x01; + + reg >>= 1; + + if (tmp) + reg ^= 0xedb88320; + } + } + + return ~reg; +} + +static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all) +{ + /* accept or reject all multicast frames */ + tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0); + tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0); + tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0); + tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0); +} + +static void __tg3_set_rx_mode(struct net_device *dev) +{ + struct tg3 *tp = netdev_priv(dev); + u32 rx_mode; + + rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC | + RX_MODE_KEEP_VLAN_TAG); + +#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE) + /* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG + * flag clear. + */ + if (!tg3_flag(tp, ENABLE_ASF)) + rx_mode |= RX_MODE_KEEP_VLAN_TAG; +#endif + + if (dev->flags & IFF_PROMISC) { + /* Promiscuous mode. */ + rx_mode |= RX_MODE_PROMISC; + } else if (dev->flags & IFF_ALLMULTI) { + /* Accept all multicast. */ + tg3_set_multi(tp, 1); + } else if (netdev_mc_empty(dev)) { + /* Reject all multicast. */ + tg3_set_multi(tp, 0); + } else { + /* Accept one or more multicast(s). */ + struct netdev_hw_addr *ha; + u32 mc_filter[4] = { 0, }; + u32 regidx; + u32 bit; + u32 crc; + + netdev_for_each_mc_addr(ha, dev) { + crc = calc_crc(ha->addr, ETH_ALEN); + bit = ~crc & 0x7f; + regidx = (bit & 0x60) >> 5; + bit &= 0x1f; + mc_filter[regidx] |= (1 << bit); + } + + tw32(MAC_HASH_REG_0, mc_filter[0]); + tw32(MAC_HASH_REG_1, mc_filter[1]); + tw32(MAC_HASH_REG_2, mc_filter[2]); + tw32(MAC_HASH_REG_3, mc_filter[3]); + } + + if (netdev_uc_count(dev) > TG3_MAX_UCAST_ADDR(tp)) { + rx_mode |= RX_MODE_PROMISC; + } else if (!(dev->flags & IFF_PROMISC)) { + /* Add all entries into to the mac addr filter list */ + int i = 0; + struct netdev_hw_addr *ha; + + netdev_for_each_uc_addr(ha, dev) { + __tg3_set_one_mac_addr(tp, ha->addr, + i + TG3_UCAST_ADDR_IDX(tp)); + i++; + } + } + + if (rx_mode != tp->rx_mode) { + tp->rx_mode = rx_mode; + tw32_f(MAC_RX_MODE, rx_mode); + udelay(10); + } +} + +static void tg3_rss_init_dflt_indir_tbl(struct tg3 *tp, u32 qcnt) { int i; for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) - tp->rss_ind_tbl[i] = - ethtool_rxfh_indir_default(i, tp->irq_cnt - 1); + tp->rss_ind_tbl[i] = ethtool_rxfh_indir_default(i, qcnt); } static void tg3_rss_check_indir_tbl(struct tg3 *tp) @@ -8231,19 +9745,19 @@ static void tg3_rss_check_indir_tbl(struct tg3 *tp) if (!tg3_flag(tp, SUPPORT_MSIX)) return; - if (tp->irq_cnt <= 2) { + if (tp->rxq_cnt == 1) { memset(&tp->rss_ind_tbl[0], 0, sizeof(tp->rss_ind_tbl)); return; } /* Validate table against current IRQ count */ for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) { - if (tp->rss_ind_tbl[i] >= tp->irq_cnt - 1) + if (tp->rss_ind_tbl[i] >= tp->rxq_cnt) break; } if (i != TG3_RSS_INDIR_TBL_SIZE) - tg3_rss_init_dflt_indir_tbl(tp); + tg3_rss_init_dflt_indir_tbl(tp, tp->rxq_cnt); } static void tg3_rss_write_indir_tbl(struct tg3 *tp) @@ -8263,8 +9777,16 @@ static void tg3_rss_write_indir_tbl(struct tg3 *tp) } } +static inline u32 tg3_lso_rd_dma_workaround_bit(struct tg3 *tp) +{ + if (tg3_asic_rev(tp) == ASIC_REV_5719) + return TG3_LSO_RD_DMA_TX_LENGTH_WA_5719; + else + return TG3_LSO_RD_DMA_TX_LENGTH_WA_5720; +} + /* tp->lock is held. */ -static int tg3_reset_hw(struct tg3 *tp, int reset_phy) +static int tg3_reset_hw(struct tg3 *tp, bool reset_phy) { u32 val, rdmac_mode; int i, err, limit; @@ -8279,37 +9801,17 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tg3_flag(tp, INIT_COMPLETE)) tg3_abort_hw(tp, 1); - /* Enable MAC control of LPI */ - if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { - tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, - TG3_CPMU_EEE_LNKIDL_PCIE_NL0 | - TG3_CPMU_EEE_LNKIDL_UART_IDL); - - tw32_f(TG3_CPMU_EEE_CTRL, - TG3_CPMU_EEE_CTRL_EXIT_20_1_US); - - val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET | - TG3_CPMU_EEEMD_LPI_IN_TX | - TG3_CPMU_EEEMD_LPI_IN_RX | - TG3_CPMU_EEEMD_EEE_ENABLE; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) - val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN; - - if (tg3_flag(tp, ENABLE_APE)) - val |= TG3_CPMU_EEEMD_APE_TX_DET_EN; - - tw32_f(TG3_CPMU_EEE_MODE, val); - - tw32_f(TG3_CPMU_EEE_DBTMR1, - TG3_CPMU_DBTMR1_PCIEXIT_2047US | - TG3_CPMU_DBTMR1_LNKIDLE_2047US); - - tw32_f(TG3_CPMU_EEE_DBTMR2, - TG3_CPMU_DBTMR2_APE_TX_2047US | - TG3_CPMU_DBTMR2_TXIDXEQ_2047US); + if ((tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) && + !(tp->phy_flags & TG3_PHYFLG_USER_CONFIGURED)) { + tg3_phy_pull_config(tp); + tg3_eee_pull_config(tp, NULL); + tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED; } + /* Enable MAC control of LPI */ + if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) + tg3_setup_eee(tp); + if (reset_phy) tg3_phy_reset(tp); @@ -8319,7 +9821,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_write_sig_legacy(tp, RESET_KIND_INIT); - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) { + if (tg3_chip_rev(tp) == CHIPREV_5784_AX) { val = tr32(TG3_CPMU_CTRL); val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE); tw32(TG3_CPMU_CTRL, val); @@ -8340,7 +9842,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3_CPMU_HST_ACC, val); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { + if (tg3_asic_rev(tp) == ASIC_REV_57780) { val = tr32(PCIE_PWR_MGMT_THRESH) & ~PCIE_PWR_MGMT_L1_THRESH_MSK; val |= PCIE_PWR_MGMT_EXT_ASPM_TMR_EN | PCIE_PWR_MGMT_L1_THRESH_4MS; @@ -8370,7 +9872,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } if (tg3_flag(tp, 57765_CLASS)) { - if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) { + if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0) { u32 grc_mode = tr32(GRC_MODE); /* Access the lower 1K of PL PCIE block registers. */ @@ -8385,8 +9887,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(GRC_MODE, grc_mode); } - if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_57765_AX) { - u32 grc_mode = tr32(GRC_MODE); + if (tg3_chip_rev(tp) != CHIPREV_57765_AX) { + u32 grc_mode; + + /* Fix transmit hangs */ + val = tr32(TG3_CPMU_PADRNG_CTL); + val |= TG3_CPMU_PADRNG_CTL_RDIV2; + tw32(TG3_CPMU_PADRNG_CTL, val); + + grc_mode = tr32(GRC_MODE); /* Access the lower 1K of DL PCIE block registers. */ val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK; @@ -8418,7 +9927,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } - if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5704_A0 && tg3_flag(tp, PCIX_MODE)) { val = tr32(TG3PCI_PCISTATE); val |= PCISTATE_RETRY_SAME_DMA; @@ -8436,7 +9945,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3PCI_PCISTATE, val); } - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) { + if (tg3_chip_rev(tp) == CHIPREV_5704_BX) { /* Enable some hw fixes. */ val = tr32(TG3PCI_MSI_DATA); val |= (1 << 26) | (1 << 28) | (1 << 29); @@ -8455,14 +9964,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tg3_flag(tp, 57765_PLUS)) { val = tr32(TG3PCI_DMA_RW_CTRL) & ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT; - if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) + if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0) val &= ~DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK; if (!tg3_flag(tp, 57765_CLASS) && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) + tg3_asic_rev(tp) != ASIC_REV_5717 && + tg3_asic_rev(tp) != ASIC_REV_5762) val |= DMA_RWCTRL_TAGGED_STAT_WA; tw32(TG3PCI_DMA_RW_CTRL, val | tp->dma_rwctrl); - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) { + } else if (tg3_asic_rev(tp) != ASIC_REV_5784 && + tg3_asic_rev(tp) != ASIC_REV_5761) { /* This value is determined during the probe time DMA * engine test, tg3_test_dma. */ @@ -8483,9 +9993,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) */ tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; - tw32(GRC_MODE, - tp->grc_mode | - (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP)); + val = GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP; + if (tp->rxptpctl) + tw32(TG3_RX_PTP_CTL, + tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK); + + if (tg3_flag(tp, PTP_CAPABLE)) + val |= GRC_MODE_TIME_SYNC_ENABLE; + + tw32(GRC_MODE, tp->grc_mode | val); /* Setup the timer prescalar register. Clock is always 66Mhz. */ val = tr32(GRC_MISC_CFG); @@ -8496,9 +10012,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) /* Initialize MBUF/DESC pool. */ if (tg3_flag(tp, 5750_PLUS)) { /* Do nothing. */ - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + } else if (tg3_asic_rev(tp) != ASIC_REV_5705) { tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) + if (tg3_asic_rev(tp) == ASIC_REV_5704) tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64); else tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96); @@ -8536,11 +10052,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->bufmgr_config.dma_high_water); val = BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (tg3_asic_rev(tp) == ASIC_REV_5719) val |= BUFMGR_MODE_NO_TX_UNDERRUN; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5720_A0) + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5762 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5720_A0) val |= BUFMGR_MODE_MBLOW_ATTN_ENAB; tw32(BUFMGR_MODE, val); for (i = 0; i < 2000; i++) { @@ -8553,7 +10070,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) return -ENODEV; } - if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1) + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5906_A1) tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2); tg3_setup_rxbd_thresholds(tp); @@ -8591,7 +10108,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) /* Program the jumbo buffer descriptor ring control * blocks on those devices that have them. */ - if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 || + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 || (tg3_flag(tp, JUMBO_CAPABLE) && !tg3_flag(tp, 5780_CLASS))) { if (tg3_flag(tp, JUMBO_RING_ENABLE)) { @@ -8604,7 +10121,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, val | BDINFO_FLAGS_USE_EXT_RECV); if (!tg3_flag(tp, USE_JUMBO_BDFLAG) || - tg3_flag(tp, 57765_CLASS)) + tg3_flag(tp, 57765_CLASS) || + tg3_asic_rev(tp) == ASIC_REV_5762) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_JUMBO_BUFFER_DESC); } else { @@ -8633,7 +10151,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_rings_reset(tp); /* Initialize MAC address and backoff seed. */ - __tg3_set_mac_addr(tp, 0); + __tg3_set_mac_addr(tp, false); /* MTU + ethernet header + FCS + optional VLAN tag */ tw32(MAC_RX_MTU_SIZE, @@ -8646,7 +10164,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) (6 << TX_LENGTHS_IPG_SHIFT) | (32 << TX_LENGTHS_SLOT_TIME_SHIFT); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + if (tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_5762) val |= tr32(MAC_TX_LENGTHS) & (TX_LENGTHS_JMB_FRM_LEN_MSK | TX_LENGTHS_CNT_DWN_VAL_MSK); @@ -8666,20 +10185,20 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | RDMAC_MODE_LNGREAD_ENAB); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + if (tg3_asic_rev(tp) == ASIC_REV_5717) rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + if (tg3_asic_rev(tp) == ASIC_REV_5784 || + tg3_asic_rev(tp) == ASIC_REV_5785 || + tg3_asic_rev(tp) == ASIC_REV_57780) rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB | RDMAC_MODE_MBUF_RBD_CRPT_ENAB | RDMAC_MODE_MBUF_SBD_CRPT_ENAB; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && - tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) { + if (tg3_asic_rev(tp) == ASIC_REV_5705 && + tg3_chip_rev_id(tp) != CHIPREV_ID_5705_A0) { if (tg3_flag(tp, TSO_CAPABLE) && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + tg3_asic_rev(tp) == ASIC_REV_5705) { rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128; } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) && !tg3_flag(tp, IS_5788)) { @@ -8690,8 +10209,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tg3_flag(tp, PCI_EXPRESS)) rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) - rdmac_mode |= RDMAC_MODE_JMB_2K_MMRR; + if (tg3_asic_rev(tp) == ASIC_REV_57766) { + tp->dma_limit = 0; + if (tp->dev->mtu <= ETH_DATA_LEN) { + rdmac_mode |= RDMAC_MODE_JMB_2K_MMRR; + tp->dma_limit = TG3_TX_BD_DMA_MAX_2K; + } + } if (tg3_flag(tp, HW_TSO_1) || tg3_flag(tp, HW_TSO_2) || @@ -8699,21 +10223,29 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) rdmac_mode |= RDMAC_MODE_IPV4_LSO_EN; if (tg3_flag(tp, 57765_PLUS) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + tg3_asic_rev(tp) == ASIC_REV_5785 || + tg3_asic_rev(tp) == ASIC_REV_57780) rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + if (tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_5762) rdmac_mode |= tr32(RDMAC_MODE) & RDMAC_MODE_H2BNC_VLAN_DET; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + if (tg3_asic_rev(tp) == ASIC_REV_5761 || + tg3_asic_rev(tp) == ASIC_REV_5784 || + tg3_asic_rev(tp) == ASIC_REV_5785 || + tg3_asic_rev(tp) == ASIC_REV_57780 || tg3_flag(tp, 57765_PLUS)) { - val = tr32(TG3_RDMA_RSRVCTRL_REG); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + u32 tgtreg; + + if (tg3_asic_rev(tp) == ASIC_REV_5762) + tgtreg = TG3_RDMA_RSRVCTRL_REG2; + else + tgtreg = TG3_RDMA_RSRVCTRL_REG; + + val = tr32(tgtreg); + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 || + tg3_asic_rev(tp) == ASIC_REV_5762) { val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK | TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK | TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK); @@ -8721,14 +10253,21 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K | TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K; } - tw32(TG3_RDMA_RSRVCTRL_REG, - val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX); + tw32(tgtreg, val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { - val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL); - tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val | + if (tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_5762) { + u32 tgtreg; + + if (tg3_asic_rev(tp) == ASIC_REV_5762) + tgtreg = TG3_LSO_RD_DMA_CRPTEN_CTRL2; + else + tgtreg = TG3_LSO_RD_DMA_CRPTEN_CTRL; + + val = tr32(tgtreg); + tw32(tgtreg, val | TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K | TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K); } @@ -8805,7 +10344,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->mac_mode |= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; if (!tg3_flag(tp, 5705_PLUS) && !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) + tg3_asic_rev(tp) != ASIC_REV_5700) tp->mac_mode |= MAC_MODE_LINK_POLARITY; tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); udelay(40); @@ -8823,11 +10362,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) + if (tg3_asic_rev(tp) == ASIC_REV_5752) gpio_mask |= GRC_LCLCTRL_GPIO_OE3 | GRC_LCLCTRL_GPIO_OUTPUT3; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + if (tg3_asic_rev(tp) == ASIC_REV_5755) gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL; tp->grc_local_ctrl &= ~gpio_mask; @@ -8862,11 +10401,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB | WDMAC_MODE_LNGREAD_ENAB); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && - tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) { + if (tg3_asic_rev(tp) == ASIC_REV_5705 && + tg3_chip_rev_id(tp) != CHIPREV_ID_5705_A0) { if (tg3_flag(tp, TSO_CAPABLE) && - (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 || - tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) { + (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A1 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A2)) { /* nothing */ } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) && !tg3_flag(tp, IS_5788)) { @@ -8878,7 +10417,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tg3_flag(tp, 5755_PLUS)) val |= WDMAC_MODE_STATUS_TAG_FIX; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + if (tg3_asic_rev(tp) == ASIC_REV_5785) val |= WDMAC_MODE_BURST_ALL_DATA; tw32_f(WDMAC_MODE, val); @@ -8889,10 +10428,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD, &pcix_cmd); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) { + if (tg3_asic_rev(tp) == ASIC_REV_5703) { pcix_cmd &= ~PCI_X_CMD_MAX_READ; pcix_cmd |= PCI_X_CMD_READ_2K; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { + } else if (tg3_asic_rev(tp) == ASIC_REV_5704) { pcix_cmd &= ~(PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ); pcix_cmd |= PCI_X_CMD_READ_2K; } @@ -8903,11 +10442,25 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32_f(RDMAC_MODE, rdmac_mode); udelay(40); + if (tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720) { + for (i = 0; i < TG3_NUM_RDMA_CHANNELS; i++) { + if (tr32(TG3_RDMA_LENGTH + (i << 2)) > TG3_MAX_MTU(tp)) + break; + } + if (i < TG3_NUM_RDMA_CHANNELS) { + val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL); + val |= tg3_lso_rd_dma_workaround_bit(tp); + tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val); + tg3_flag_set(tp, 5719_5720_RDMA_BUG); + } + } + tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE); if (!tg3_flag(tp, 5705_PLUS)) tw32(MBFREE_MODE, MBFREE_MODE_ENABLE); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + if (tg3_asic_rev(tp) == ASIC_REV_5761) tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE | SNDDATAC_MODE_CDELAY); else @@ -8930,12 +10483,19 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(SNDBDI_MODE, val); tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE); - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0) { err = tg3_load_5701_a0_firmware_fix(tp); if (err) return err; } + if (tg3_asic_rev(tp) == ASIC_REV_57766) { + /* Ignore any errors for the firmware download. If download + * fails, the device will operate with EEE disabled + */ + tg3_load_57766_firmware(tp); + } + if (tg3_flag(tp, TSO_CAPABLE)) { err = tg3_load_tso_firmware(tp); if (err) @@ -8945,10 +10505,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->tx_mode = TX_MODE_ENABLE; if (tg3_flag(tp, 5755_PLUS) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tg3_asic_rev(tp) == ASIC_REV_5906) tp->tx_mode |= TX_MODE_MBUF_LOCKUP_FIX; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + if (tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_5762) { val = TX_MODE_JMB_FRM_LEN | TX_MODE_CNT_DN_MODE; tp->tx_mode &= ~val; tp->tx_mode |= tr32(MAC_TX_MODE) & val; @@ -8977,6 +10538,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tg3_flag(tp, 5755_PLUS)) tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; + if (tg3_asic_rev(tp) == ASIC_REV_5762) + tp->rx_mode |= RX_MODE_IPV4_FRAG_FIX; + if (tg3_flag(tp, ENABLE_RSS)) tp->rx_mode |= RX_MODE_RSS_ENABLE | RX_MODE_RSS_ITBL_HASH_BITS_7 | @@ -8999,8 +10563,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(10); if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) { - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) && - !(tp->phy_flags & TG3_PHYFLG_SERDES_PREEMPHASIS)) { + if ((tg3_asic_rev(tp) == ASIC_REV_5704) && + !(tp->phy_flags & TG3_PHYFLG_SERDES_PREEMPHASIS)) { /* Set drive transmission level to 1.2V */ /* only if the signal pre-emphasis bit is not set */ val = tr32(MAC_SERDES_CFG); @@ -9008,7 +10572,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) val |= 0x880; tw32(MAC_SERDES_CFG, val); } - if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1) + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5703_A1) tw32(MAC_SERDES_CFG, 0x616000); } @@ -9021,14 +10585,14 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) val = 2; tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, val); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && + if (tg3_asic_rev(tp) == ASIC_REV_5704 && (tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) { /* Use hardware link auto-negotiation */ tg3_flag_set(tp, HW_AUTONEG); } if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { + tg3_asic_rev(tp) == ASIC_REV_5714) { u32 tmp; tmp = tr32(SERDES_RX_CTRL); @@ -9039,14 +10603,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } if (!tg3_flag(tp, USE_PHYLIB)) { - if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER; - tp->link_config.speed = tp->link_config.orig_speed; - tp->link_config.duplex = tp->link_config.orig_duplex; - tp->link_config.autoneg = tp->link_config.orig_autoneg; - } - err = tg3_setup_phy(tp, 0); + err = tg3_setup_phy(tp, false); if (err) return err; @@ -9126,8 +10686,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) /* 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, int reset_phy) +static int tg3_init_hw(struct tg3 *tp, bool reset_phy) { + /* Chip may have been just powered on. If so, the boot code may still + * be running initialization. Wait for it to finish to avoid races in + * accessing the hardware. + */ + tg3_enable_register_access(tp); + tg3_poll_fw(tp); + tg3_switch_clocks(tp); tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); @@ -9135,6 +10702,90 @@ static int tg3_init_hw(struct tg3 *tp, int reset_phy) return tg3_reset_hw(tp, reset_phy); } +static void tg3_sd_scan_scratchpad(struct tg3 *tp, struct tg3_ocir *ocir) +{ + int i; + + for (i = 0; i < TG3_SD_NUM_RECS; i++, ocir++) { + u32 off = i * TG3_OCIR_LEN, len = TG3_OCIR_LEN; + + tg3_ape_scratchpad_read(tp, (u32 *) ocir, off, len); + off += len; + + if (ocir->signature != TG3_OCIR_SIG_MAGIC || + !(ocir->version_flags & TG3_OCIR_FLAG_ACTIVE)) + memset(ocir, 0, TG3_OCIR_LEN); + } +} + +/* sysfs attributes for hwmon */ +static ssize_t tg3_show_temp(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct tg3 *tp = dev_get_drvdata(dev); + u32 temperature; + + spin_lock_bh(&tp->lock); + tg3_ape_scratchpad_read(tp, &temperature, attr->index, + sizeof(temperature)); + spin_unlock_bh(&tp->lock); + return sprintf(buf, "%u\n", temperature); +} + + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tg3_show_temp, NULL, + TG3_TEMP_SENSOR_OFFSET); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, tg3_show_temp, NULL, + TG3_TEMP_CAUTION_OFFSET); +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, tg3_show_temp, NULL, + TG3_TEMP_MAX_OFFSET); + +static struct attribute *tg3_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + NULL +}; +ATTRIBUTE_GROUPS(tg3); + +static void tg3_hwmon_close(struct tg3 *tp) +{ + if (tp->hwmon_dev) { + hwmon_device_unregister(tp->hwmon_dev); + tp->hwmon_dev = NULL; + } +} + +static void tg3_hwmon_open(struct tg3 *tp) +{ + int i; + u32 size = 0; + struct pci_dev *pdev = tp->pdev; + struct tg3_ocir ocirs[TG3_SD_NUM_RECS]; + + tg3_sd_scan_scratchpad(tp, ocirs); + + for (i = 0; i < TG3_SD_NUM_RECS; i++) { + if (!ocirs[i].src_data_length) + continue; + + size += ocirs[i].src_hdr_length; + size += ocirs[i].src_data_length; + } + + if (!size) + return; + + tp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, "tg3", + tp, tg3_groups); + if (IS_ERR(tp->hwmon_dev)) { + tp->hwmon_dev = NULL; + dev_err(&pdev->dev, "Cannot register hwmon device, aborting\n"); + } +} + + #define TG3_STAT_ADD32(PSTAT, REG) \ do { u32 __val = tr32(REG); \ (PSTAT)->low += __val; \ @@ -9146,7 +10797,7 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) { struct tg3_hw_stats *sp = tp->hw_stats; - if (!netif_carrier_ok(tp->dev)) + if (!tp->link_up) return; TG3_STAT_ADD32(&sp->tx_octets, MAC_TX_STATS_OCTETS); @@ -9162,6 +10813,16 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) TG3_STAT_ADD32(&sp->tx_ucast_packets, MAC_TX_STATS_UCAST); TG3_STAT_ADD32(&sp->tx_mcast_packets, MAC_TX_STATS_MCAST); TG3_STAT_ADD32(&sp->tx_bcast_packets, MAC_TX_STATS_BCAST); + if (unlikely(tg3_flag(tp, 5719_5720_RDMA_BUG) && + (sp->tx_ucast_packets.low + sp->tx_mcast_packets.low + + sp->tx_bcast_packets.low) > TG3_NUM_RDMA_CHANNELS)) { + u32 val; + + val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL); + val &= ~tg3_lso_rd_dma_workaround_bit(tp); + tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val); + tg3_flag_clear(tp, 5719_5720_RDMA_BUG); + } TG3_STAT_ADD32(&sp->rx_octets, MAC_RX_STATS_OCTETS); TG3_STAT_ADD32(&sp->rx_fragments, MAC_RX_STATS_FRAGMENTS); @@ -9179,9 +10840,10 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE); TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && - tp->pci_chip_rev_id != CHIPREV_ID_5719_A0 && - tp->pci_chip_rev_id != CHIPREV_ID_5720_A0) { + if (tg3_asic_rev(tp) != ASIC_REV_5717 && + tg3_asic_rev(tp) != ASIC_REV_5762 && + tg3_chip_rev_id(tp) != CHIPREV_ID_5719_A0 && + tg3_chip_rev_id(tp) != CHIPREV_ID_5720_A0) { TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT); } else { u32 val = tr32(HOSTCC_FLOW_ATTN); @@ -9229,10 +10891,15 @@ static void tg3_timer(unsigned long __opaque) spin_lock(&tp->lock); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + if (tg3_asic_rev(tp) == ASIC_REV_5717 || tg3_flag(tp, 57765_CLASS)) tg3_chk_missed_msi(tp); + if (tg3_flag(tp, FLUSH_POSTED_WRITES)) { + /* BCM4785: Flush posted writes from GbE to host memory. */ + tr32(HOSTCC_MODE); + } + if (!tg3_flag(tp, TAGGED_STATUS)) { /* All of this garbage is because when using non-tagged * IRQ status the mailbox/status_block protocol the chip @@ -9275,16 +10942,16 @@ static void tg3_timer(unsigned long __opaque) phy_event = 1; if (phy_event) - tg3_setup_phy(tp, 0); + tg3_setup_phy(tp, false); } else if (tg3_flag(tp, POLL_SERDES)) { u32 mac_stat = tr32(MAC_STATUS); int need_setup = 0; - if (netif_carrier_ok(tp->dev) && + if (tp->link_up && (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)) { need_setup = 1; } - if (!netif_carrier_ok(tp->dev) && + if (!tp->link_up && (mac_stat & (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DET))) { need_setup = 1; @@ -9298,11 +10965,18 @@ static void tg3_timer(unsigned long __opaque) tw32_f(MAC_MODE, tp->mac_mode); udelay(40); } - tg3_setup_phy(tp, 0); + tg3_setup_phy(tp, false); } } else if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && tg3_flag(tp, 5780_CLASS)) { tg3_serdes_parallel_detect(tp); + } else if (tg3_flag(tp, POLL_CPMU_LINK)) { + u32 cpmu = tr32(TG3_CPMU_STATUS); + bool link_up = !((cpmu & TG3_CPMU_STATUS_LINK_MASK) == + TG3_CPMU_STATUS_LINK_MASK); + + if (link_up != tp->link_up) + tg3_setup_phy(tp, false); } tp->timer_counter = tp->timer_multiplier; @@ -9347,6 +11021,108 @@ restart_timer: add_timer(&tp->timer); } +static void tg3_timer_init(struct tg3 *tp) +{ + if (tg3_flag(tp, TAGGED_STATUS) && + tg3_asic_rev(tp) != ASIC_REV_5717 && + !tg3_flag(tp, 57765_CLASS)) + tp->timer_offset = HZ; + else + tp->timer_offset = HZ / 10; + + BUG_ON(tp->timer_offset > HZ); + + tp->timer_multiplier = (HZ / tp->timer_offset); + tp->asf_multiplier = (HZ / tp->timer_offset) * + TG3_FW_UPDATE_FREQ_SEC; + + init_timer(&tp->timer); + tp->timer.data = (unsigned long) tp; + tp->timer.function = tg3_timer; +} + +static void tg3_timer_start(struct tg3 *tp) +{ + tp->asf_counter = tp->asf_multiplier; + tp->timer_counter = tp->timer_multiplier; + + tp->timer.expires = jiffies + tp->timer_offset; + add_timer(&tp->timer); +} + +static void tg3_timer_stop(struct tg3 *tp) +{ + del_timer_sync(&tp->timer); +} + +/* Restart hardware after configuration changes, self-test, etc. + * Invoked with tp->lock held. + */ +static int tg3_restart_hw(struct tg3 *tp, bool reset_phy) + __releases(tp->lock) + __acquires(tp->lock) +{ + int err; + + err = tg3_init_hw(tp, reset_phy); + if (err) { + netdev_err(tp->dev, + "Failed to re-initialize device, aborting\n"); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); + tg3_full_unlock(tp); + tg3_timer_stop(tp); + tp->irq_sync = 0; + tg3_napi_enable(tp); + dev_close(tp->dev); + tg3_full_lock(tp, 0); + } + return err; +} + +static void tg3_reset_task(struct work_struct *work) +{ + struct tg3 *tp = container_of(work, struct tg3, reset_task); + int err; + + tg3_full_lock(tp, 0); + + if (!netif_running(tp->dev)) { + tg3_flag_clear(tp, RESET_TASK_PENDING); + tg3_full_unlock(tp); + return; + } + + tg3_full_unlock(tp); + + tg3_phy_stop(tp); + + tg3_netif_stop(tp); + + tg3_full_lock(tp, 1); + + if (tg3_flag(tp, TX_RECOVERY_PENDING)) { + tp->write32_tx_mbox = tg3_write32_tx_mbox; + tp->write32_rx_mbox = tg3_write_flush_reg32; + tg3_flag_set(tp, MBOX_WRITE_REORDER); + tg3_flag_clear(tp, TX_RECOVERY_PENDING); + } + + tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); + err = tg3_init_hw(tp, true); + if (err) + goto out; + + tg3_netif_start(tp); + +out: + tg3_full_unlock(tp); + + if (!err) + tg3_phy_start(tp); + + tg3_flag_clear(tp, RESET_TASK_PENDING); +} + static int tg3_request_irq(struct tg3 *tp, int irq_num) { irq_handler_t fn; @@ -9358,7 +11134,18 @@ static int tg3_request_irq(struct tg3 *tp, int irq_num) name = tp->dev->name; else { name = &tnapi->irq_lbl[0]; - snprintf(name, IFNAMSIZ, "%s-%d", tp->dev->name, irq_num); + if (tnapi->tx_buffers && tnapi->rx_rcb) + snprintf(name, IFNAMSIZ, + "%s-txrx-%d", tp->dev->name, irq_num); + else if (tnapi->tx_buffers) + snprintf(name, IFNAMSIZ, + "%s-tx-%d", tp->dev->name, irq_num); + else if (tnapi->rx_rcb) + snprintf(name, IFNAMSIZ, + "%s-rx-%d", tp->dev->name, irq_num); + else + snprintf(name, IFNAMSIZ, + "%s-%d", tp->dev->name, irq_num); name[IFNAMSIZ-1] = 0; } @@ -9401,7 +11188,7 @@ static int tg3_test_interrupt(struct tg3 *tp) } err = request_irq(tnapi->irq_vec, tg3_test_isr, - IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi); + IRQF_SHARED, dev->name, tnapi); if (err) return err; @@ -9502,7 +11289,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, 1); + err = tg3_init_hw(tp, true); tg3_full_unlock(tp); @@ -9514,7 +11301,7 @@ static int tg3_test_msi(struct tg3 *tp) static int tg3_request_firmware(struct tg3 *tp) { - const __be32 *fw_data; + const struct tg3_firmware_hdr *fw_hdr; if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) { netdev_err(tp->dev, "Failed to load firmware \"%s\"\n", @@ -9522,15 +11309,15 @@ static int tg3_request_firmware(struct tg3 *tp) return -ENOENT; } - fw_data = (void *)tp->fw->data; + fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data; /* Firmware blob starts with version numbers, followed by * start address and _full_ length including BSS sections * (which must be longer than the actual data, of course */ - tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */ - if (tp->fw_len < (tp->fw->size - 12)) { + tp->fw_len = be32_to_cpu(fw_hdr->len); /* includes bss */ + if (tp->fw_len < (tp->fw->size - TG3_FW_HDR_LEN)) { netdev_err(tp->dev, "bogus length %d in \"%s\"\n", tp->fw_len, tp->fw_needed); release_firmware(tp->fw); @@ -9543,56 +11330,77 @@ static int tg3_request_firmware(struct tg3 *tp) return 0; } -static bool tg3_enable_msix(struct tg3 *tp) +static u32 tg3_irq_count(struct tg3 *tp) { - int i, rc; - struct msix_entry msix_ent[tp->irq_max]; + u32 irq_cnt = max(tp->rxq_cnt, tp->txq_cnt); - tp->irq_cnt = num_online_cpus(); - if (tp->irq_cnt > 1) { + if (irq_cnt > 1) { /* We want as many rx rings enabled as there are cpus. * In multiqueue MSI-X mode, the first MSI-X vector * only deals with link interrupts, etc, so we add * one to the number of vectors we are requesting. */ - tp->irq_cnt = min_t(unsigned, tp->irq_cnt + 1, tp->irq_max); + irq_cnt = min_t(unsigned, irq_cnt + 1, tp->irq_max); } + return irq_cnt; +} + +static bool tg3_enable_msix(struct tg3 *tp) +{ + int i, rc; + struct msix_entry msix_ent[TG3_IRQ_MAX_VECS]; + + tp->txq_cnt = tp->txq_req; + tp->rxq_cnt = tp->rxq_req; + if (!tp->rxq_cnt) + tp->rxq_cnt = netif_get_num_default_rss_queues(); + if (tp->rxq_cnt > tp->rxq_max) + tp->rxq_cnt = tp->rxq_max; + + /* Disable multiple TX rings by default. Simple round-robin hardware + * scheduling of the TX rings can cause starvation of rings with + * small packets when other rings have TSO or jumbo packets. + */ + if (!tp->txq_req) + tp->txq_cnt = 1; + + tp->irq_cnt = tg3_irq_count(tp); + for (i = 0; i < tp->irq_max; i++) { msix_ent[i].entry = i; msix_ent[i].vector = 0; } - rc = pci_enable_msix(tp->pdev, msix_ent, tp->irq_cnt); + rc = pci_enable_msix_range(tp->pdev, msix_ent, 1, tp->irq_cnt); if (rc < 0) { return false; - } else if (rc != 0) { - if (pci_enable_msix(tp->pdev, msix_ent, rc)) - return false; + } else if (rc < tp->irq_cnt) { netdev_notice(tp->dev, "Requested %d MSI-X vectors, received %d\n", tp->irq_cnt, rc); tp->irq_cnt = rc; + tp->rxq_cnt = max(rc - 1, 1); + if (tp->txq_cnt) + tp->txq_cnt = min(tp->rxq_cnt, tp->txq_max); } for (i = 0; i < tp->irq_max; i++) tp->napi[i].irq_vec = msix_ent[i].vector; - netif_set_real_num_tx_queues(tp->dev, 1); - rc = tp->irq_cnt > 1 ? tp->irq_cnt - 1 : 1; - if (netif_set_real_num_rx_queues(tp->dev, rc)) { + if (netif_set_real_num_rx_queues(tp->dev, tp->rxq_cnt)) { pci_disable_msix(tp->pdev); return false; } - if (tp->irq_cnt > 1) { - tg3_flag_set(tp, ENABLE_RSS); + if (tp->irq_cnt == 1) + return true; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { - tg3_flag_set(tp, ENABLE_TSS); - netif_set_real_num_tx_queues(tp->dev, tp->irq_cnt - 1); - } - } + tg3_flag_set(tp, ENABLE_RSS); + + if (tp->txq_cnt > 1) + tg3_flag_set(tp, ENABLE_TSS); + + netif_set_real_num_tx_queues(tp->dev, tp->txq_cnt); return true; } @@ -9626,6 +11434,11 @@ defcfg: if (!tg3_flag(tp, USING_MSIX)) { tp->irq_cnt = 1; tp->napi[0].irq_vec = tp->pdev->irq; + } + + if (tp->irq_cnt == 1) { + tp->txq_cnt = 1; + tp->rxq_cnt = 1; netif_set_real_num_tx_queues(tp->dev, 1); netif_set_real_num_rx_queues(tp->dev, 1); } @@ -9643,38 +11456,12 @@ static void tg3_ints_fini(struct tg3 *tp) tg3_flag_clear(tp, ENABLE_TSS); } -static int tg3_open(struct net_device *dev) +static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq, + bool init) { - struct tg3 *tp = netdev_priv(dev); + struct net_device *dev = tp->dev; int i, err; - if (tp->fw_needed) { - err = tg3_request_firmware(tp); - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { - if (err) - return err; - } else if (err) { - netdev_warn(tp->dev, "TSO capability disabled\n"); - tg3_flag_clear(tp, TSO_CAPABLE); - } else if (!tg3_flag(tp, TSO_CAPABLE)) { - netdev_notice(tp->dev, "TSO capability restored\n"); - tg3_flag_set(tp, TSO_CAPABLE); - } - } - - netif_carrier_off(tp->dev); - - err = tg3_power_up(tp); - if (err) - return err; - - tg3_full_lock(tp, 0); - - tg3_disable_ints(tp); - tg3_flag_clear(tp, INIT_COMPLETE); - - tg3_full_unlock(tp); - /* * Setup interrupts first so we know how * many NAPI resources to allocate @@ -9688,7 +11475,7 @@ static int tg3_open(struct net_device *dev) */ err = tg3_alloc_consistent(tp); if (err) - goto err_out1; + goto out_ints_fini; tg3_napi_init(tp); @@ -9702,42 +11489,27 @@ static int tg3_open(struct net_device *dev) tnapi = &tp->napi[i]; free_irq(tnapi->irq_vec, tnapi); } - goto err_out2; + goto out_napi_fini; } } tg3_full_lock(tp, 0); - err = tg3_init_hw(tp, 1); + if (init) + tg3_ape_driver_state_change(tp, RESET_KIND_INIT); + + err = tg3_init_hw(tp, reset_phy); if (err) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); - } else { - if (tg3_flag(tp, TAGGED_STATUS) && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && - !tg3_flag(tp, 57765_CLASS)) - tp->timer_offset = HZ; - else - tp->timer_offset = HZ / 10; - - BUG_ON(tp->timer_offset > HZ); - tp->timer_counter = tp->timer_multiplier = - (HZ / tp->timer_offset); - tp->asf_counter = tp->asf_multiplier = - ((HZ / tp->timer_offset) * 2); - - init_timer(&tp->timer); - tp->timer.expires = jiffies + tp->timer_offset; - tp->timer.data = (unsigned long) tp; - tp->timer.function = tg3_timer; } tg3_full_unlock(tp); if (err) - goto err_out3; + goto out_free_irq; - if (tg3_flag(tp, USING_MSI)) { + if (test_irq && tg3_flag(tp, USING_MSI)) { err = tg3_test_msi(tp); if (err) { @@ -9746,7 +11518,7 @@ static int tg3_open(struct net_device *dev) tg3_free_rings(tp); tg3_full_unlock(tp); - goto err_out2; + goto out_napi_fini; } if (!tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) { @@ -9759,12 +11531,20 @@ static int tg3_open(struct net_device *dev) tg3_phy_start(tp); + tg3_hwmon_open(tp); + tg3_full_lock(tp, 0); - add_timer(&tp->timer); + tg3_timer_start(tp); tg3_flag_set(tp, INIT_COMPLETE); tg3_enable_ints(tp); + if (init) + tg3_ptp_init(tp); + else + tg3_ptp_resume(tp); + + tg3_full_unlock(tp); netif_tx_start_all_queues(dev); @@ -9778,35 +11558,33 @@ static int tg3_open(struct net_device *dev) return 0; -err_out3: +out_free_irq: for (i = tp->irq_cnt - 1; i >= 0; i--) { struct tg3_napi *tnapi = &tp->napi[i]; free_irq(tnapi->irq_vec, tnapi); } -err_out2: +out_napi_fini: tg3_napi_disable(tp); tg3_napi_fini(tp); tg3_free_consistent(tp); -err_out1: +out_ints_fini: tg3_ints_fini(tp); - tg3_frob_aux_power(tp, false); - pci_set_power_state(tp->pdev, PCI_D3hot); + return err; } -static int tg3_close(struct net_device *dev) +static void tg3_stop(struct tg3 *tp) { int i; - struct tg3 *tp = netdev_priv(dev); - tg3_napi_disable(tp); tg3_reset_task_cancel(tp); + tg3_netif_stop(tp); - netif_tx_stop_all_queues(dev); + tg3_timer_stop(tp); - del_timer_sync(&tp->timer); + tg3_hwmon_close(tp); tg3_phy_stop(tp); @@ -9827,18 +11605,86 @@ static int tg3_close(struct net_device *dev) tg3_ints_fini(tp); - /* Clear stats across close / open calls */ - memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev)); - memset(&tp->estats_prev, 0, sizeof(tp->estats_prev)); - tg3_napi_fini(tp); tg3_free_consistent(tp); +} - tg3_power_down(tp); +static int tg3_open(struct net_device *dev) +{ + struct tg3 *tp = netdev_priv(dev); + int err; - netif_carrier_off(tp->dev); + if (tp->fw_needed) { + err = tg3_request_firmware(tp); + if (tg3_asic_rev(tp) == ASIC_REV_57766) { + if (err) { + netdev_warn(tp->dev, "EEE capability disabled\n"); + tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP; + } else if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) { + netdev_warn(tp->dev, "EEE capability restored\n"); + tp->phy_flags |= TG3_PHYFLG_EEE_CAP; + } + } else if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0) { + if (err) + return err; + } else if (err) { + netdev_warn(tp->dev, "TSO capability disabled\n"); + tg3_flag_clear(tp, TSO_CAPABLE); + } else if (!tg3_flag(tp, TSO_CAPABLE)) { + netdev_notice(tp->dev, "TSO capability restored\n"); + tg3_flag_set(tp, TSO_CAPABLE); + } + } + + tg3_carrier_off(tp); + + err = tg3_power_up(tp); + if (err) + return err; + + tg3_full_lock(tp, 0); + + tg3_disable_ints(tp); + tg3_flag_clear(tp, INIT_COMPLETE); + + tg3_full_unlock(tp); + + err = tg3_start(tp, + !(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN), + true, true); + if (err) { + tg3_frob_aux_power(tp, false); + pci_set_power_state(tp->pdev, PCI_D3hot); + } + + if (tg3_flag(tp, PTP_CAPABLE)) { + tp->ptp_clock = ptp_clock_register(&tp->ptp_info, + &tp->pdev->dev); + if (IS_ERR(tp->ptp_clock)) + tp->ptp_clock = NULL; + } + + return err; +} + +static int tg3_close(struct net_device *dev) +{ + struct tg3 *tp = netdev_priv(dev); + + tg3_ptp_fini(tp); + + tg3_stop(tp); + /* Clear stats across close / open calls */ + memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev)); + memset(&tp->estats_prev, 0, sizeof(tp->estats_prev)); + + if (pci_device_is_present(tp->pdev)) { + tg3_power_down_prepare(tp); + + tg3_carrier_off(tp); + } return 0; } @@ -9847,23 +11693,21 @@ static inline u64 get_stat64(tg3_stat64_t *val) return ((u64)val->high << 32) | ((u64)val->low); } -static u64 calc_crc_errors(struct tg3 *tp) +static u64 tg3_calc_crc_errors(struct tg3 *tp) { struct tg3_hw_stats *hw_stats = tp->hw_stats; if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { + (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701)) { u32 val; - spin_lock_bh(&tp->lock); if (!tg3_readphy(tp, MII_TG3_TEST1, &val)) { tg3_writephy(tp, MII_TG3_TEST1, val | MII_TG3_TEST1_CRC_EN); tg3_readphy(tp, MII_TG3_RXR_COUNTERS, &val); } else val = 0; - spin_unlock_bh(&tp->lock); tp->phy_crc_errors += val; @@ -9877,15 +11721,11 @@ static u64 calc_crc_errors(struct tg3 *tp) estats->member = old_estats->member + \ get_stat64(&hw_stats->member) -static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp, - struct tg3_ethtool_stats *estats) +static void tg3_get_estats(struct tg3 *tp, struct tg3_ethtool_stats *estats) { struct tg3_ethtool_stats *old_estats = &tp->estats_prev; struct tg3_hw_stats *hw_stats = tp->hw_stats; - if (!hw_stats) - return old_estats; - ESTAT_ADD(rx_octets); ESTAT_ADD(rx_fragments); ESTAT_ADD(rx_ucast_packets); @@ -9963,20 +11803,13 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp, ESTAT_ADD(nic_tx_threshold_hit); ESTAT_ADD(mbuf_lwm_thresh_hit); - - return estats; } -static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, - struct rtnl_link_stats64 *stats) +static void tg3_get_nstats(struct tg3 *tp, struct rtnl_link_stats64 *stats) { - struct tg3 *tp = netdev_priv(dev); struct rtnl_link_stats64 *old_stats = &tp->net_stats_prev; struct tg3_hw_stats *hw_stats = tp->hw_stats; - if (!hw_stats) - return old_stats; - stats->rx_packets = old_stats->rx_packets + get_stat64(&hw_stats->rx_ucast_packets) + get_stat64(&hw_stats->rx_mcast_packets) + @@ -10009,8 +11842,6 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, get_stat64(&hw_stats->rx_frame_too_long_errors) + get_stat64(&hw_stats->rx_undersize_packets); - stats->rx_over_errors = old_stats->rx_over_errors + - get_stat64(&hw_stats->rxbds_empty); stats->rx_frame_errors = old_stats->rx_frame_errors + get_stat64(&hw_stats->rx_align_errors); stats->tx_aborted_errors = old_stats->tx_aborted_errors + @@ -10019,114 +11850,13 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, get_stat64(&hw_stats->tx_carrier_sense_errors); stats->rx_crc_errors = old_stats->rx_crc_errors + - calc_crc_errors(tp); + tg3_calc_crc_errors(tp); stats->rx_missed_errors = old_stats->rx_missed_errors + get_stat64(&hw_stats->rx_discards); stats->rx_dropped = tp->rx_dropped; stats->tx_dropped = tp->tx_dropped; - - return stats; -} - -static inline u32 calc_crc(unsigned char *buf, int len) -{ - u32 reg; - u32 tmp; - int j, k; - - reg = 0xffffffff; - - for (j = 0; j < len; j++) { - reg ^= buf[j]; - - for (k = 0; k < 8; k++) { - tmp = reg & 0x01; - - reg >>= 1; - - if (tmp) - reg ^= 0xedb88320; - } - } - - return ~reg; -} - -static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all) -{ - /* accept or reject all multicast frames */ - tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0); - tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0); - tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0); - tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0); -} - -static void __tg3_set_rx_mode(struct net_device *dev) -{ - struct tg3 *tp = netdev_priv(dev); - u32 rx_mode; - - rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC | - RX_MODE_KEEP_VLAN_TAG); - -#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE) - /* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG - * flag clear. - */ - if (!tg3_flag(tp, ENABLE_ASF)) - rx_mode |= RX_MODE_KEEP_VLAN_TAG; -#endif - - if (dev->flags & IFF_PROMISC) { - /* Promiscuous mode. */ - rx_mode |= RX_MODE_PROMISC; - } else if (dev->flags & IFF_ALLMULTI) { - /* Accept all multicast. */ - tg3_set_multi(tp, 1); - } else if (netdev_mc_empty(dev)) { - /* Reject all multicast. */ - tg3_set_multi(tp, 0); - } else { - /* Accept one or more multicast(s). */ - struct netdev_hw_addr *ha; - u32 mc_filter[4] = { 0, }; - u32 regidx; - u32 bit; - u32 crc; - - netdev_for_each_mc_addr(ha, dev) { - crc = calc_crc(ha->addr, ETH_ALEN); - bit = ~crc & 0x7f; - regidx = (bit & 0x60) >> 5; - bit &= 0x1f; - mc_filter[regidx] |= (1 << bit); - } - - tw32(MAC_HASH_REG_0, mc_filter[0]); - tw32(MAC_HASH_REG_1, mc_filter[1]); - tw32(MAC_HASH_REG_2, mc_filter[2]); - tw32(MAC_HASH_REG_3, mc_filter[3]); - } - - if (rx_mode != tp->rx_mode) { - tp->rx_mode = rx_mode; - tw32_f(MAC_RX_MODE, rx_mode); - udelay(10); - } -} - -static void tg3_set_rx_mode(struct net_device *dev) -{ - struct tg3 *tp = netdev_priv(dev); - - if (!netif_running(dev)) - return; - - tg3_full_lock(tp, 0); - __tg3_set_rx_mode(dev); - tg3_full_unlock(tp); } static int tg3_get_regs_len(struct net_device *dev) @@ -10163,23 +11893,33 @@ static int tg3_get_eeprom_len(struct net_device *dev) static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct tg3 *tp = netdev_priv(dev); - int ret; + int ret, cpmu_restore = 0; u8 *pd; - u32 i, offset, len, b_offset, b_count; + u32 i, offset, len, b_offset, b_count, cpmu_val = 0; __be32 val; if (tg3_flag(tp, NO_NVRAM)) return -EINVAL; - if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) - return -EAGAIN; - offset = eeprom->offset; len = eeprom->len; eeprom->len = 0; eeprom->magic = TG3_EEPROM_MAGIC; + /* Override clock, link aware and link idle modes */ + if (tg3_flag(tp, CPMU_PRESENT)) { + cpmu_val = tr32(TG3_CPMU_CTRL); + if (cpmu_val & (CPMU_CTRL_LINK_AWARE_MODE | + CPMU_CTRL_LINK_IDLE_MODE)) { + tw32(TG3_CPMU_CTRL, cpmu_val & + ~(CPMU_CTRL_LINK_AWARE_MODE | + CPMU_CTRL_LINK_IDLE_MODE)); + cpmu_restore = 1; + } + } + tg3_override_clk(tp); + if (offset & 3) { /* adjustments to start on required 4 byte boundary */ b_offset = offset & 3; @@ -10190,7 +11930,7 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, } ret = tg3_nvram_read_be32(tp, offset-b_offset, &val); if (ret) - return ret; + goto eeprom_done; memcpy(data, ((char *)&val) + b_offset, b_count); len -= b_count; offset += b_count; @@ -10202,10 +11942,20 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, for (i = 0; i < (len - (len & 3)); i += 4) { ret = tg3_nvram_read_be32(tp, offset + i, &val); if (ret) { + if (i) + i -= 4; eeprom->len += i; - return ret; + goto eeprom_done; } memcpy(pd + i, &val, 4); + if (need_resched()) { + if (signal_pending(current)) { + eeprom->len += i; + ret = -EINTR; + goto eeprom_done; + } + cond_resched(); + } } eeprom->len += i; @@ -10216,14 +11966,20 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, b_offset = offset + len - b_count; ret = tg3_nvram_read_be32(tp, b_offset, &val); if (ret) - return ret; + goto eeprom_done; memcpy(pd, &val, b_count); eeprom->len += b_count; } - return 0; -} + ret = 0; + +eeprom_done: + /* Restore clock, link aware and link idle modes */ + tg3_restore_clk(tp); + if (cpmu_restore) + tw32(TG3_CPMU_CTRL, cpmu_val); -static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); + return ret; +} static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { @@ -10233,9 +11989,6 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *buf; __be32 start, end; - if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) - return -EAGAIN; - if (tg3_flag(tp, NO_NVRAM) || eeprom->magic != TG3_EEPROM_MAGIC) return -EINVAL; @@ -10292,7 +12045,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) struct phy_device *phydev; if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; return phy_ethtool_gset(phydev, cmd); } @@ -10327,7 +12080,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising |= ADVERTISED_Asym_Pause; } } - if (netif_running(dev) && netif_carrier_ok(dev)) { + if (netif_running(dev) && tp->link_up) { ethtool_cmd_speed_set(cmd, tp->link_config.active_speed); cmd->duplex = tp->link_config.active_duplex; cmd->lp_advertising = tp->link_config.rmt_adv; @@ -10338,8 +12091,8 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->eth_tp_mdix = ETH_TP_MDI; } } else { - ethtool_cmd_speed_set(cmd, SPEED_INVALID); - cmd->duplex = DUPLEX_INVALID; + ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); + cmd->duplex = DUPLEX_UNKNOWN; cmd->eth_tp_mdix = ETH_TP_MDI_INVALID; } cmd->phy_address = tp->phy_addr; @@ -10359,7 +12112,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) struct phy_device *phydev; if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; return phy_ethtool_sset(phydev, cmd); } @@ -10421,20 +12174,20 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (cmd->autoneg == AUTONEG_ENABLE) { tp->link_config.advertising = (cmd->advertising | ADVERTISED_Autoneg); - tp->link_config.speed = SPEED_INVALID; - tp->link_config.duplex = DUPLEX_INVALID; + tp->link_config.speed = SPEED_UNKNOWN; + tp->link_config.duplex = DUPLEX_UNKNOWN; } else { tp->link_config.advertising = 0; tp->link_config.speed = speed; tp->link_config.duplex = cmd->duplex; } - tp->link_config.orig_speed = tp->link_config.speed; - tp->link_config.orig_duplex = tp->link_config.duplex; - tp->link_config.orig_autoneg = tp->link_config.autoneg; + tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED; + + tg3_warn_mgmt_link_flap(tp); if (netif_running(dev)) - tg3_setup_phy(tp, 1); + tg3_setup_phy(tp, true); tg3_full_unlock(tp); @@ -10478,12 +12231,10 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) device_set_wakeup_enable(dp, wol->wolopts & WAKE_MAGIC); - spin_lock_bh(&tp->lock); if (device_may_wakeup(dp)) tg3_flag_set(tp, WOL_ENABLE); else tg3_flag_clear(tp, WOL_ENABLE); - spin_unlock_bh(&tp->lock); return 0; } @@ -10511,10 +12262,12 @@ static int tg3_nway_reset(struct net_device *dev) if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) return -EINVAL; + tg3_warn_mgmt_link_flap(tp); + if (tg3_flag(tp, USE_PHYLIB)) { if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; - r = phy_start_aneg(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]); + r = phy_start_aneg(tp->mdio_bus->phy_map[tp->phy_addr]); } else { u32 bmcr; @@ -10581,14 +12334,16 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e if (tg3_flag(tp, MAX_RXPEND_64) && tp->rx_pending > 63) tp->rx_pending = 63; - tp->rx_jumbo_pending = ering->rx_jumbo_pending; + + if (tg3_flag(tp, JUMBO_RING_ENABLE)) + tp->rx_jumbo_pending = ering->rx_jumbo_pending; for (i = 0; i < tp->irq_max; i++) tp->napi[i].tx_pending = ering->tx_pending; if (netif_running(dev)) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - err = tg3_restart_hw(tp, 1); + err = tg3_restart_hw(tp, false); if (!err) tg3_netif_start(tp); } @@ -10623,11 +12378,14 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam struct tg3 *tp = netdev_priv(dev); int err = 0; + if (tp->link_config.autoneg == AUTONEG_ENABLE) + tg3_warn_mgmt_link_flap(tp); + if (tg3_flag(tp, USE_PHYLIB)) { u32 newadv; struct phy_device *phydev; - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; if (!(phydev->supported & SUPPORTED_Pause) || (!(phydev->supported & SUPPORTED_Asym_Pause) && @@ -10679,10 +12437,10 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam if (!epause->autoneg) tg3_setup_flow_control(tp, 0, 0); } else { - tp->link_config.orig_advertising &= + tp->link_config.advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); - tp->link_config.orig_advertising |= newadv; + tp->link_config.advertising |= newadv; } } else { int irq_sync = 0; @@ -10709,7 +12467,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam if (netif_running(dev)) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - err = tg3_restart_hw(tp, 1); + err = tg3_restart_hw(tp, false); if (!err) tg3_netif_start(tp); } @@ -10717,6 +12475,8 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam tg3_full_unlock(tp); } + tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED; + return err; } @@ -10743,11 +12503,11 @@ static int tg3_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, switch (info->cmd) { case ETHTOOL_GRXRINGS: if (netif_running(tp->dev)) - info->data = tp->irq_cnt; + info->data = tp->rxq_cnt; else { info->data = num_online_cpus(); - if (info->data > TG3_IRQ_MAX_VECS_RSS) - info->data = TG3_IRQ_MAX_VECS_RSS; + if (info->data > TG3_RSS_MAX_NUM_QS) + info->data = TG3_RSS_MAX_NUM_QS; } /* The first interrupt vector only @@ -10772,7 +12532,7 @@ static u32 tg3_get_rxfh_indir_size(struct net_device *dev) return size; } -static int tg3_get_rxfh_indir(struct net_device *dev, u32 *indir) +static int tg3_get_rxfh(struct net_device *dev, u32 *indir, u8 *key) { struct tg3 *tp = netdev_priv(dev); int i; @@ -10783,7 +12543,7 @@ static int tg3_get_rxfh_indir(struct net_device *dev, u32 *indir) return 0; } -static int tg3_set_rxfh_indir(struct net_device *dev, const u32 *indir) +static int tg3_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key) { struct tg3 *tp = netdev_priv(dev); size_t i; @@ -10804,6 +12564,58 @@ static int tg3_set_rxfh_indir(struct net_device *dev, const u32 *indir) return 0; } +static void tg3_get_channels(struct net_device *dev, + struct ethtool_channels *channel) +{ + struct tg3 *tp = netdev_priv(dev); + u32 deflt_qs = netif_get_num_default_rss_queues(); + + channel->max_rx = tp->rxq_max; + channel->max_tx = tp->txq_max; + + if (netif_running(dev)) { + channel->rx_count = tp->rxq_cnt; + channel->tx_count = tp->txq_cnt; + } else { + if (tp->rxq_req) + channel->rx_count = tp->rxq_req; + else + channel->rx_count = min(deflt_qs, tp->rxq_max); + + if (tp->txq_req) + channel->tx_count = tp->txq_req; + else + channel->tx_count = min(deflt_qs, tp->txq_max); + } +} + +static int tg3_set_channels(struct net_device *dev, + struct ethtool_channels *channel) +{ + struct tg3 *tp = netdev_priv(dev); + + if (!tg3_flag(tp, SUPPORT_MSIX)) + return -EOPNOTSUPP; + + if (channel->rx_count > tp->rxq_max || + channel->tx_count > tp->txq_max) + return -EINVAL; + + tp->rxq_req = channel->rx_count; + tp->txq_req = channel->tx_count; + + if (!netif_running(dev)) + return 0; + + tg3_stop(tp); + + tg3_carrier_off(tp); + + tg3_start(tp, true, false, false); + + return 0; +} + static void tg3_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { switch (stringset) { @@ -10859,7 +12671,10 @@ static void tg3_get_ethtool_stats(struct net_device *dev, { struct tg3 *tp = netdev_priv(dev); - tg3_get_estats(tp, (struct tg3_ethtool_stats *)tmp_stats); + if (tp->hw_stats) + tg3_get_estats(tp, (struct tg3_ethtool_stats *)tmp_stats); + else + memset(tmp_stats, 0, sizeof(struct tg3_ethtool_stats)); } static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen) @@ -11143,7 +12958,7 @@ static int tg3_test_link(struct tg3 *tp) max = TG3_COPPER_TIMEOUT_SEC; for (i = 0; i < max; i++) { - if (netif_carrier_ok(tp->dev)) + if (tp->link_up) return 0; if (msleep_interruptible(1000)) @@ -11442,11 +13257,12 @@ static int tg3_test_memory(struct tg3 *tp) if (tg3_flag(tp, 5717_PLUS)) mem_tbl = mem_tbl_5717; - else if (tg3_flag(tp, 57765_CLASS)) + else if (tg3_flag(tp, 57765_CLASS) || + tg3_asic_rev(tp) == ASIC_REV_5762) mem_tbl = mem_tbl_57765; else if (tg3_flag(tp, 5755_PLUS)) mem_tbl = mem_tbl_5755; - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + else if (tg3_asic_rev(tp) == ASIC_REV_5906) mem_tbl = mem_tbl_5906; else if (tg3_flag(tp, 5705_PLUS)) mem_tbl = mem_tbl_5705; @@ -11516,8 +13332,8 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) return -ENOMEM; tx_data = skb_put(skb, tx_len); - memcpy(tx_data, tp->dev->dev_addr, 6); - memset(tx_data + 6, 0x0, 8); + memcpy(tx_data, tp->dev->dev_addr, ETH_ALEN); + memset(tx_data + ETH_ALEN, 0x0, 8); tw32(MAC_RX_MTU_SIZE, tx_len + ETH_FCS_LEN); @@ -11558,7 +13374,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) } else if (tg3_flag(tp, HW_TSO_2)) mss |= hdr_len << 9; else if (tg3_flag(tp, HW_TSO_1) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + tg3_asic_rev(tp) == ASIC_REV_5705) { mss |= (TG3_TSO_TCP_OPT_LEN << 9); } else { base_flags |= (TG3_TSO_TCP_OPT_LEN << 10); @@ -11568,6 +13384,10 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) } else { num_pkts = 1; data_off = ETH_HLEN; + + if (tg3_flag(tp, USE_JUMBO_BDFLAG) && + tx_len > VLAN_ETH_FRAME_LEN) + base_flags |= TXD_FLAG_JMB_PKT; } for (i = data_off; i < tx_len; i++) @@ -11600,6 +13420,9 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) tnapi->tx_prod++; + /* Sync BD data before updating mailbox */ + wmb(); + tw32_tx_mbox(tnapi->prodmbox, tnapi->tx_prod); tr32_mailbox(tnapi->prodmbox); @@ -11698,24 +13521,28 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) { int err = -EIO; u32 eee_cap; + u32 jmb_pkt_sz = 9000; + + if (tp->dma_limit) + jmb_pkt_sz = tp->dma_limit - ETH_HLEN; eee_cap = tp->phy_flags & TG3_PHYFLG_EEE_CAP; tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP; if (!netif_running(tp->dev)) { - data[0] = TG3_LOOPBACK_FAILED; - data[1] = TG3_LOOPBACK_FAILED; + data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED; + data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED; if (do_extlpbk) - data[2] = TG3_LOOPBACK_FAILED; + data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED; goto done; } - err = tg3_reset_hw(tp, 1); + err = tg3_reset_hw(tp, true); if (err) { - data[0] = TG3_LOOPBACK_FAILED; - data[1] = TG3_LOOPBACK_FAILED; + data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED; + data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED; if (do_extlpbk) - data[2] = TG3_LOOPBACK_FAILED; + data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED; goto done; } @@ -11733,16 +13560,16 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) * errata. Also, the MAC loopback test is deprecated for * all newer ASIC revisions. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780 && + if (tg3_asic_rev(tp) != ASIC_REV_5780 && !tg3_flag(tp, CPMU_PRESENT)) { tg3_mac_loopback(tp, true); if (tg3_run_loopback(tp, ETH_FRAME_LEN, false)) - data[0] |= TG3_STD_LOOPBACK_FAILED; + data[TG3_MAC_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED; if (tg3_flag(tp, JUMBO_RING_ENABLE) && - tg3_run_loopback(tp, 9000 + ETH_HLEN, false)) - data[0] |= TG3_JMB_LOOPBACK_FAILED; + tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false)) + data[TG3_MAC_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED; tg3_mac_loopback(tp, false); } @@ -11761,13 +13588,13 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) } if (tg3_run_loopback(tp, ETH_FRAME_LEN, false)) - data[1] |= TG3_STD_LOOPBACK_FAILED; + data[TG3_PHY_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED; if (tg3_flag(tp, TSO_CAPABLE) && tg3_run_loopback(tp, ETH_FRAME_LEN, true)) - data[1] |= TG3_TSO_LOOPBACK_FAILED; + data[TG3_PHY_LOOPB_TEST] |= TG3_TSO_LOOPBACK_FAILED; if (tg3_flag(tp, JUMBO_RING_ENABLE) && - tg3_run_loopback(tp, 9000 + ETH_HLEN, false)) - data[1] |= TG3_JMB_LOOPBACK_FAILED; + tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false)) + data[TG3_PHY_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED; if (do_extlpbk) { tg3_phy_lpbk_set(tp, 0, true); @@ -11779,13 +13606,16 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) mdelay(40); if (tg3_run_loopback(tp, ETH_FRAME_LEN, false)) - data[2] |= TG3_STD_LOOPBACK_FAILED; + data[TG3_EXT_LOOPB_TEST] |= + TG3_STD_LOOPBACK_FAILED; if (tg3_flag(tp, TSO_CAPABLE) && tg3_run_loopback(tp, ETH_FRAME_LEN, true)) - data[2] |= TG3_TSO_LOOPBACK_FAILED; + data[TG3_EXT_LOOPB_TEST] |= + TG3_TSO_LOOPBACK_FAILED; if (tg3_flag(tp, JUMBO_RING_ENABLE) && - tg3_run_loopback(tp, 9000 + ETH_HLEN, false)) - data[2] |= TG3_JMB_LOOPBACK_FAILED; + tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false)) + data[TG3_EXT_LOOPB_TEST] |= + TG3_JMB_LOOPBACK_FAILED; } /* Re-enable gphy autopowerdown. */ @@ -11793,7 +13623,8 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) tg3_phy_toggle_apd(tp, true); } - err = (data[0] | data[1] | data[2]) ? -EIO : 0; + err = (data[TG3_MAC_LOOPB_TEST] | data[TG3_PHY_LOOPB_TEST] | + data[TG3_EXT_LOOPB_TEST]) ? -EIO : 0; done: tp->phy_flags |= eee_cap; @@ -11807,22 +13638,24 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, struct tg3 *tp = netdev_priv(dev); bool doextlpbk = etest->flags & ETH_TEST_FL_EXTERNAL_LB; - if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) && - tg3_power_up(tp)) { - etest->flags |= ETH_TEST_FL_FAILED; - memset(data, 1, sizeof(u64) * TG3_NUM_TEST); - return; + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { + if (tg3_power_up(tp)) { + etest->flags |= ETH_TEST_FL_FAILED; + memset(data, 1, sizeof(u64) * TG3_NUM_TEST); + return; + } + tg3_ape_driver_state_change(tp, RESET_KIND_INIT); } memset(data, 0, sizeof(u64) * TG3_NUM_TEST); if (tg3_test_nvram(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; - data[0] = 1; + data[TG3_NVRAM_TEST] = 1; } if (!doextlpbk && tg3_test_link(tp)) { etest->flags |= ETH_TEST_FL_FAILED; - data[1] = 1; + data[TG3_LINK_TEST] = 1; } if (etest->flags & ETH_TEST_FL_OFFLINE) { int err, err2 = 0, irq_sync = 0; @@ -11834,7 +13667,6 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, } tg3_full_lock(tp, irq_sync); - tg3_halt(tp, RESET_KIND_SUSPEND, 1); err = tg3_nvram_lock(tp); tg3_halt_cpu(tp, RX_CPU_BASE); @@ -11848,25 +13680,25 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, if (tg3_test_registers(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; - data[2] = 1; + data[TG3_REGISTER_TEST] = 1; } if (tg3_test_memory(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; - data[3] = 1; + data[TG3_MEMORY_TEST] = 1; } if (doextlpbk) etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE; - if (tg3_test_loopback(tp, &data[4], doextlpbk)) + if (tg3_test_loopback(tp, data, doextlpbk)) etest->flags |= ETH_TEST_FL_FAILED; tg3_full_unlock(tp); if (tg3_test_interrupt(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; - data[7] = 1; + data[TG3_INTERRUPT_TEST] = 1; } tg3_full_lock(tp, 0); @@ -11874,7 +13706,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); if (netif_running(dev)) { tg3_flag_set(tp, INIT_COMPLETE); - err2 = tg3_restart_hw(tp, 1); + err2 = tg3_restart_hw(tp, true); if (!err2) tg3_netif_start(tp); } @@ -11885,10 +13717,158 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_phy_start(tp); } if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) - tg3_power_down(tp); + tg3_power_down_prepare(tp); } +static int tg3_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) +{ + struct tg3 *tp = netdev_priv(dev); + struct hwtstamp_config stmpconf; + + if (!tg3_flag(tp, PTP_CAPABLE)) + return -EOPNOTSUPP; + + if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) + return -EFAULT; + + if (stmpconf.flags) + return -EINVAL; + + if (stmpconf.tx_type != HWTSTAMP_TX_ON && + stmpconf.tx_type != HWTSTAMP_TX_OFF) + return -ERANGE; + + switch (stmpconf.rx_filter) { + case HWTSTAMP_FILTER_NONE: + tp->rxptpctl = 0; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN | + TG3_RX_PTP_CTL_ALL_V1_EVENTS; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN | + TG3_RX_PTP_CTL_SYNC_EVNT; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN | + TG3_RX_PTP_CTL_DELAY_REQ; + break; + case HWTSTAMP_FILTER_PTP_V2_EVENT: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN | + TG3_RX_PTP_CTL_ALL_V2_EVENTS; + break; + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | + TG3_RX_PTP_CTL_ALL_V2_EVENTS; + break; + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | + TG3_RX_PTP_CTL_ALL_V2_EVENTS; + break; + case HWTSTAMP_FILTER_PTP_V2_SYNC: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN | + TG3_RX_PTP_CTL_SYNC_EVNT; + break; + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | + TG3_RX_PTP_CTL_SYNC_EVNT; + break; + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | + TG3_RX_PTP_CTL_SYNC_EVNT; + break; + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN | + TG3_RX_PTP_CTL_DELAY_REQ; + break; + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | + TG3_RX_PTP_CTL_DELAY_REQ; + break; + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | + TG3_RX_PTP_CTL_DELAY_REQ; + break; + default: + return -ERANGE; + } + + if (netif_running(dev) && tp->rxptpctl) + tw32(TG3_RX_PTP_CTL, + tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK); + + if (stmpconf.tx_type == HWTSTAMP_TX_ON) + tg3_flag_set(tp, TX_TSTAMP_EN); + else + tg3_flag_clear(tp, TX_TSTAMP_EN); + + return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? + -EFAULT : 0; +} + +static int tg3_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) +{ + struct tg3 *tp = netdev_priv(dev); + struct hwtstamp_config stmpconf; + + if (!tg3_flag(tp, PTP_CAPABLE)) + return -EOPNOTSUPP; + + stmpconf.flags = 0; + stmpconf.tx_type = (tg3_flag(tp, TX_TSTAMP_EN) ? + HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF); + + switch (tp->rxptpctl) { + case 0: + stmpconf.rx_filter = HWTSTAMP_FILTER_NONE; + break; + case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_ALL_V1_EVENTS: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; + break; + case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_SYNC_EVNT: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; + break; + case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_DELAY_REQ: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_SYNC; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_SYNC_EVNT: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_DELAY_REQ: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_DELAY_REQ: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ; + break; + case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_DELAY_REQ: + stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; + break; + default: + WARN_ON_ONCE(1); + return -ERANGE; + } + + return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? + -EFAULT : 0; +} + static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = if_mii(ifr); @@ -11899,7 +13879,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) struct phy_device *phydev; if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)) return -EAGAIN; - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; return phy_mii_ioctl(phydev, ifr, cmd); } @@ -11918,7 +13898,8 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EAGAIN; spin_lock_bh(&tp->lock); - err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval); + err = __tg3_readphy(tp, data->phy_id & 0x1f, + data->reg_num & 0x1f, &mii_regval); spin_unlock_bh(&tp->lock); data->val_out = mii_regval; @@ -11934,11 +13915,18 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EAGAIN; spin_lock_bh(&tp->lock); - err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in); + err = __tg3_writephy(tp, data->phy_id & 0x1f, + data->reg_num & 0x1f, data->val_in); spin_unlock_bh(&tp->lock); return err; + case SIOCSHWTSTAMP: + return tg3_hwtstamp_set(dev, ifr); + + case SIOCGHWTSTAMP: + return tg3_hwtstamp_get(dev, ifr); + default: /* do nothing */ break; @@ -12008,6 +13996,57 @@ static int tg3_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) return 0; } +static int tg3_set_eee(struct net_device *dev, struct ethtool_eee *edata) +{ + struct tg3 *tp = netdev_priv(dev); + + if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) { + netdev_warn(tp->dev, "Board does not support EEE!\n"); + return -EOPNOTSUPP; + } + + if (edata->advertised != tp->eee.advertised) { + netdev_warn(tp->dev, + "Direct manipulation of EEE advertisement is not supported\n"); + return -EINVAL; + } + + if (edata->tx_lpi_timer > TG3_CPMU_DBTMR1_LNKIDLE_MAX) { + netdev_warn(tp->dev, + "Maximal Tx Lpi timer supported is %#x(u)\n", + TG3_CPMU_DBTMR1_LNKIDLE_MAX); + return -EINVAL; + } + + tp->eee = *edata; + + tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED; + tg3_warn_mgmt_link_flap(tp); + + if (netif_running(tp->dev)) { + tg3_full_lock(tp, 0); + tg3_setup_eee(tp); + tg3_phy_reset(tp); + tg3_full_unlock(tp); + } + + return 0; +} + +static int tg3_get_eee(struct net_device *dev, struct ethtool_eee *edata) +{ + struct tg3 *tp = netdev_priv(dev); + + if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) { + netdev_warn(tp->dev, + "Board does not support EEE!\n"); + return -EOPNOTSUPP; + } + + *edata = tp->eee; + return 0; +} + static const struct ethtool_ops tg3_ethtool_ops = { .get_settings = tg3_get_settings, .set_settings = tg3_set_settings, @@ -12036,11 +14075,130 @@ static const struct ethtool_ops tg3_ethtool_ops = { .get_sset_count = tg3_get_sset_count, .get_rxnfc = tg3_get_rxnfc, .get_rxfh_indir_size = tg3_get_rxfh_indir_size, - .get_rxfh_indir = tg3_get_rxfh_indir, - .set_rxfh_indir = tg3_set_rxfh_indir, + .get_rxfh = tg3_get_rxfh, + .set_rxfh = tg3_set_rxfh, + .get_channels = tg3_get_channels, + .set_channels = tg3_set_channels, + .get_ts_info = tg3_get_ts_info, + .get_eee = tg3_get_eee, + .set_eee = tg3_set_eee, +}; + +static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct tg3 *tp = netdev_priv(dev); + + spin_lock_bh(&tp->lock); + if (!tp->hw_stats) { + spin_unlock_bh(&tp->lock); + return &tp->net_stats_prev; + } + + tg3_get_nstats(tp, stats); + spin_unlock_bh(&tp->lock); + + return stats; +} + +static void tg3_set_rx_mode(struct net_device *dev) +{ + struct tg3 *tp = netdev_priv(dev); + + if (!netif_running(dev)) + return; + + tg3_full_lock(tp, 0); + __tg3_set_rx_mode(dev); + tg3_full_unlock(tp); +} + +static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, + int new_mtu) +{ + dev->mtu = new_mtu; + + if (new_mtu > ETH_DATA_LEN) { + if (tg3_flag(tp, 5780_CLASS)) { + netdev_update_features(dev); + tg3_flag_clear(tp, TSO_CAPABLE); + } else { + tg3_flag_set(tp, JUMBO_RING_ENABLE); + } + } else { + if (tg3_flag(tp, 5780_CLASS)) { + tg3_flag_set(tp, TSO_CAPABLE); + netdev_update_features(dev); + } + tg3_flag_clear(tp, JUMBO_RING_ENABLE); + } +} + +static int tg3_change_mtu(struct net_device *dev, int new_mtu) +{ + struct tg3 *tp = netdev_priv(dev); + int err; + bool reset_phy = false; + + if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) + return -EINVAL; + + if (!netif_running(dev)) { + /* We'll just catch it later when the + * device is up'd. + */ + tg3_set_mtu(dev, tp, new_mtu); + return 0; + } + + tg3_phy_stop(tp); + + tg3_netif_stop(tp); + + tg3_set_mtu(dev, tp, new_mtu); + + tg3_full_lock(tp, 1); + + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); + + /* Reset PHY, otherwise the read DMA engine will be in a mode that + * breaks all requests to 256 bytes. + */ + if (tg3_asic_rev(tp) == ASIC_REV_57766) + reset_phy = true; + + err = tg3_restart_hw(tp, reset_phy); + + if (!err) + tg3_netif_start(tp); + + tg3_full_unlock(tp); + + if (!err) + tg3_phy_start(tp); + + return err; +} + +static const struct net_device_ops tg3_netdev_ops = { + .ndo_open = tg3_open, + .ndo_stop = tg3_close, + .ndo_start_xmit = tg3_start_xmit, + .ndo_get_stats64 = tg3_get_stats64, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = tg3_set_rx_mode, + .ndo_set_mac_address = tg3_set_mac_addr, + .ndo_do_ioctl = tg3_ioctl, + .ndo_tx_timeout = tg3_tx_timeout, + .ndo_change_mtu = tg3_change_mtu, + .ndo_fix_features = tg3_fix_features, + .ndo_set_features = tg3_set_features, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tg3_poll_controller, +#endif }; -static void __devinit tg3_get_eeprom_size(struct tg3 *tp) +static void tg3_get_eeprom_size(struct tg3 *tp) { u32 cursize, val, magic; @@ -12074,7 +14232,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) +static void tg3_get_nvram_size(struct tg3 *tp) { u32 val; @@ -12107,7 +14265,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp) tp->nvram_size = TG3_NVRAM_SIZE_512KB; } -static void __devinit tg3_get_nvram_info(struct tg3 *tp) +static void tg3_get_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -12119,7 +14277,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp) tw32(NVRAM_CFG1, nvcfg1); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || + if (tg3_asic_rev(tp) == ASIC_REV_5750 || tg3_flag(tp, 5780_CLASS)) { switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) { case FLASH_VENDOR_ATMEL_FLASH_BUFFERED: @@ -12158,7 +14316,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1) +static void tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1) { switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) { case FLASH_5752PAGE_SIZE_256: @@ -12185,7 +14343,7 @@ static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1) } } -static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) +static void tg3_get_5752_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -12226,7 +14384,7 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) +static void tg3_get_5755_nvram_info(struct tg3 *tp) { u32 nvcfg1, protect = 0; @@ -12282,7 +14440,7 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) +static void tg3_get_5787_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -12320,7 +14478,7 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) +static void tg3_get_5761_nvram_info(struct tg3 *tp) { u32 nvcfg1, protect = 0; @@ -12395,14 +14553,14 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp) +static void tg3_get_5906_nvram_info(struct tg3 *tp) { tp->nvram_jedecnum = JEDEC_ATMEL; tg3_flag_set(tp, NVRAM_BUFFERED); tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; } -static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) +static void tg3_get_57780_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -12475,7 +14633,7 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) } -static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) +static void tg3_get_5717_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -12553,13 +14711,35 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS); } -static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) +static void tg3_get_5720_nvram_info(struct tg3 *tp) { u32 nvcfg1, nvmpinstrp; nvcfg1 = tr32(NVRAM_CFG1); nvmpinstrp = nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK; + if (tg3_asic_rev(tp) == ASIC_REV_5762) { + if (!(nvcfg1 & NVRAM_CFG1_5762VENDOR_MASK)) { + tg3_flag_set(tp, NO_NVRAM); + return; + } + + switch (nvmpinstrp) { + case FLASH_5762_EEPROM_HD: + nvmpinstrp = FLASH_5720_EEPROM_HD; + break; + case FLASH_5762_EEPROM_LD: + nvmpinstrp = FLASH_5720_EEPROM_LD; + break; + case FLASH_5720VENDOR_M_ST_M45PE20: + /* This pinstrap supports multiple sizes, so force it + * to read the actual size from location 0xf0. + */ + nvmpinstrp = FLASH_5720VENDOR_ST_45USPT; + break; + } + } + switch (nvmpinstrp) { case FLASH_5720_EEPROM_HD: case FLASH_5720_EEPROM_LD: @@ -12605,7 +14785,8 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) tp->nvram_size = TG3_NVRAM_SIZE_1MB; break; default: - tp->nvram_size = TG3_NVRAM_SIZE_128KB; + if (tg3_asic_rev(tp) != ASIC_REV_5762) + tp->nvram_size = TG3_NVRAM_SIZE_128KB; break; } break; @@ -12651,7 +14832,8 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) tp->nvram_size = TG3_NVRAM_SIZE_1MB; break; default: - tp->nvram_size = TG3_NVRAM_SIZE_128KB; + if (tg3_asic_rev(tp) != ASIC_REV_5762) + tp->nvram_size = TG3_NVRAM_SIZE_128KB; break; } break; @@ -12663,11 +14845,30 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) tg3_nvram_get_pagesize(tp, nvcfg1); if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528) tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS); + + if (tg3_asic_rev(tp) == ASIC_REV_5762) { + u32 val; + + if (tg3_nvram_read(tp, 0, &val)) + return; + + if (val != TG3_EEPROM_MAGIC && + (val & TG3_EEPROM_MAGIC_FW_MSK) != TG3_EEPROM_MAGIC_FW) + tg3_flag_set(tp, NO_NVRAM); + } } /* Chips other than 5700/5701 use the NVRAM for fetching info. */ -static void __devinit tg3_nvram_init(struct tg3 *tp) +static void tg3_nvram_init(struct tg3 *tp) { + if (tg3_flag(tp, IS_SSB_CORE)) { + /* No NVRAM and EEPROM on the SSB Broadcom GigE core. */ + tg3_flag_clear(tp, NVRAM); + tg3_flag_clear(tp, NVRAM_BUFFERED); + tg3_flag_set(tp, NO_NVRAM); + return; + } + tw32_f(GRC_EEPROM_ADDR, (EEPROM_ADDR_FSM_RESET | (EEPROM_DEFAULT_CLOCK_PERIOD << @@ -12680,8 +14881,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM); udelay(100); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { + if (tg3_asic_rev(tp) != ASIC_REV_5700 && + tg3_asic_rev(tp) != ASIC_REV_5701) { tg3_flag_set(tp, NVRAM); if (tg3_nvram_lock(tp)) { @@ -12694,25 +14895,26 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) tp->nvram_size = 0; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) + if (tg3_asic_rev(tp) == ASIC_REV_5752) tg3_get_5752_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + else if (tg3_asic_rev(tp) == ASIC_REV_5755) tg3_get_5755_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + else if (tg3_asic_rev(tp) == ASIC_REV_5787 || + tg3_asic_rev(tp) == ASIC_REV_5784 || + tg3_asic_rev(tp) == ASIC_REV_5785) tg3_get_5787_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + else if (tg3_asic_rev(tp) == ASIC_REV_5761) tg3_get_5761_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + else if (tg3_asic_rev(tp) == ASIC_REV_5906) tg3_get_5906_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + else if (tg3_asic_rev(tp) == ASIC_REV_57780 || tg3_flag(tp, 57765_CLASS)) tg3_get_57780_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + else if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719) tg3_get_5717_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + else if (tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_5762) tg3_get_5720_nvram_info(tp); else tg3_get_nvram_info(tp); @@ -12731,260 +14933,12 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) } } -static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, - u32 offset, u32 len, u8 *buf) -{ - int i, j, rc = 0; - u32 val; - - for (i = 0; i < len; i += 4) { - u32 addr; - __be32 data; - - addr = offset + i; - - memcpy(&data, buf + i, 4); - - /* - * The SEEPROM interface expects the data to always be opposite - * the native endian format. We accomplish this by reversing - * all the operations that would have been performed on the - * data from a call to tg3_nvram_read_be32(). - */ - tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data))); - - val = tr32(GRC_EEPROM_ADDR); - tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); - - val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | - EEPROM_ADDR_READ); - tw32(GRC_EEPROM_ADDR, val | - (0 << EEPROM_ADDR_DEVID_SHIFT) | - (addr & EEPROM_ADDR_ADDR_MASK) | - EEPROM_ADDR_START | - EEPROM_ADDR_WRITE); - - for (j = 0; j < 1000; j++) { - val = tr32(GRC_EEPROM_ADDR); - - if (val & EEPROM_ADDR_COMPLETE) - break; - msleep(1); - } - if (!(val & EEPROM_ADDR_COMPLETE)) { - rc = -EBUSY; - break; - } - } - - return rc; -} - -/* offset and length are dword aligned */ -static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, - u8 *buf) -{ - int ret = 0; - u32 pagesize = tp->nvram_pagesize; - u32 pagemask = pagesize - 1; - u32 nvram_cmd; - u8 *tmp; - - tmp = kmalloc(pagesize, GFP_KERNEL); - if (tmp == NULL) - return -ENOMEM; - - while (len) { - int j; - u32 phy_addr, page_off, size; - - phy_addr = offset & ~pagemask; - - for (j = 0; j < pagesize; j += 4) { - ret = tg3_nvram_read_be32(tp, phy_addr + j, - (__be32 *) (tmp + j)); - if (ret) - break; - } - if (ret) - break; - - page_off = offset & pagemask; - size = pagesize; - if (len < size) - size = len; - - len -= size; - - memcpy(tmp + page_off, buf, size); - - offset = offset + (pagesize - page_off); - - tg3_enable_nvram_access(tp); - - /* - * Before we can erase the flash page, we need - * to issue a special "write enable" command. - */ - nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; - - if (tg3_nvram_exec_cmd(tp, nvram_cmd)) - break; - - /* Erase the target page */ - tw32(NVRAM_ADDR, phy_addr); - - nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | - NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; - - if (tg3_nvram_exec_cmd(tp, nvram_cmd)) - break; - - /* Issue another write enable to start the write. */ - nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; - - if (tg3_nvram_exec_cmd(tp, nvram_cmd)) - break; - - for (j = 0; j < pagesize; j += 4) { - __be32 data; - - data = *((__be32 *) (tmp + j)); - - tw32(NVRAM_WRDATA, be32_to_cpu(data)); - - tw32(NVRAM_ADDR, phy_addr + j); - - nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | - NVRAM_CMD_WR; - - if (j == 0) - nvram_cmd |= NVRAM_CMD_FIRST; - else if (j == (pagesize - 4)) - nvram_cmd |= NVRAM_CMD_LAST; - - if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) - break; - } - if (ret) - break; - } - - nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; - tg3_nvram_exec_cmd(tp, nvram_cmd); - - kfree(tmp); - - return ret; -} - -/* offset and length are dword aligned */ -static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, - u8 *buf) -{ - int i, ret = 0; - - for (i = 0; i < len; i += 4, offset += 4) { - u32 page_off, phy_addr, nvram_cmd; - __be32 data; - - memcpy(&data, buf + i, 4); - tw32(NVRAM_WRDATA, be32_to_cpu(data)); - - page_off = offset % tp->nvram_pagesize; - - phy_addr = tg3_nvram_phys_addr(tp, offset); - - tw32(NVRAM_ADDR, phy_addr); - - nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; - - if (page_off == 0 || i == 0) - nvram_cmd |= NVRAM_CMD_FIRST; - 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 && - !tg3_flag(tp, 5755_PLUS) && - (tp->nvram_jedecnum == JEDEC_ST) && - (nvram_cmd & NVRAM_CMD_FIRST)) { - - if ((ret = tg3_nvram_exec_cmd(tp, - NVRAM_CMD_WREN | NVRAM_CMD_GO | - NVRAM_CMD_DONE))) - - break; - } - if (!tg3_flag(tp, FLASH)) { - /* We always do complete word writes to eeprom. */ - nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); - } - - if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) - break; - } - return ret; -} - -/* offset and length are dword aligned */ -static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) -{ - int ret; - - if (tg3_flag(tp, EEPROM_WRITE_PROT)) { - tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & - ~GRC_LCLCTRL_GPIO_OUTPUT1); - udelay(40); - } - - if (!tg3_flag(tp, NVRAM)) { - ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); - } else { - u32 grc_mode; - - ret = tg3_nvram_lock(tp); - if (ret) - return ret; - - tg3_enable_nvram_access(tp); - if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) - tw32(NVRAM_WRITE1, 0x406); - - grc_mode = tr32(GRC_MODE); - tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); - - if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) { - ret = tg3_nvram_write_block_buffered(tp, offset, len, - buf); - } else { - ret = tg3_nvram_write_block_unbuffered(tp, offset, len, - buf); - } - - grc_mode = tr32(GRC_MODE); - tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); - - tg3_disable_nvram_access(tp); - tg3_nvram_unlock(tp); - } - - if (tg3_flag(tp, EEPROM_WRITE_PROT)) { - tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); - udelay(40); - } - - return ret; -} - struct subsys_tbl_ent { u16 subsys_vendor, subsys_devid; u32 phy_id; }; -static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = { +static struct subsys_tbl_ent subsys_id_to_phy_id[] = { /* Broadcom boards. */ { TG3PCI_SUBVENDOR_ID_BROADCOM, TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 }, @@ -13048,7 +15002,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = { TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 } }; -static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp) +static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp) { int i; @@ -13062,7 +15016,7 @@ static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp) return NULL; } -static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) +static void tg3_get_eeprom_hw_cfg(struct tg3 *tp) { u32 val; @@ -13073,7 +15027,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tg3_flag_set(tp, EEPROM_WRITE_PROT); tg3_flag_set(tp, WOL_CAP); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + if (tg3_asic_rev(tp) == ASIC_REV_5906) { if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) { tg3_flag_clear(tp, EEPROM_WRITE_PROT); tg3_flag_set(tp, IS_NIC); @@ -13092,7 +15046,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg, led_cfg; - u32 nic_phy_id, ver, cfg2 = 0, cfg4 = 0, eeprom_phy_id; + u32 cfg2 = 0, cfg4 = 0, cfg5 = 0; + u32 nic_phy_id, ver, eeprom_phy_id; int eeprom_phy_serdes = 0; tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); @@ -13100,15 +15055,20 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tg3_read_mem(tp, NIC_SRAM_DATA_VER, &ver); ver >>= NIC_SRAM_DATA_VER_SHIFT; - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703 && + if (tg3_asic_rev(tp) != ASIC_REV_5700 && + tg3_asic_rev(tp) != ASIC_REV_5701 && + tg3_asic_rev(tp) != ASIC_REV_5703 && (ver > 0) && (ver < 0x100)) tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + if (tg3_asic_rev(tp) == ASIC_REV_5785) tg3_read_mem(tp, NIC_SRAM_DATA_CFG_4, &cfg4); + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720) + tg3_read_mem(tp, NIC_SRAM_DATA_CFG_5, &cfg5); + if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) eeprom_phy_serdes = 1; @@ -13154,20 +15114,24 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) /* Default to PHY_1_MODE if 0 (MAC_MODE) is * read on some older 5700/5701 bootcode. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == - ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == - ASIC_REV_5701) + if (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701) tp->led_ctrl = LED_CTRL_MODE_PHY_1; break; case SHASTA_EXT_LED_SHARED: tp->led_ctrl = LED_CTRL_MODE_SHARED; - if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 && - tp->pci_chip_rev_id != CHIPREV_ID_5750_A1) + if (tg3_chip_rev_id(tp) != CHIPREV_ID_5750_A0 && + tg3_chip_rev_id(tp) != CHIPREV_ID_5750_A1) tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 | LED_CTRL_MODE_PHY_2); + + if (tg3_flag(tp, 5717_PLUS) || + tg3_asic_rev(tp) == ASIC_REV_5762) + tp->led_ctrl |= LED_CTRL_BLINK_RATE_OVERRIDE | + LED_CTRL_BLINK_RATE_MASK; + break; case SHASTA_EXT_LED_MAC: @@ -13176,19 +15140,19 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) case SHASTA_EXT_LED_COMBO: tp->led_ctrl = LED_CTRL_MODE_COMBO; - if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) + if (tg3_chip_rev_id(tp) != CHIPREV_ID_5750_A0) tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 | LED_CTRL_MODE_PHY_2); break; } - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) && + if ((tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701) && tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) tp->led_ctrl = LED_CTRL_MODE_PHY_2; - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) + if (tg3_chip_rev(tp) == CHIPREV_5784_AX) tp->led_ctrl = LED_CTRL_MODE_PHY_1; if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) { @@ -13232,19 +15196,23 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->phy_flags |= TG3_PHYFLG_SERDES_PREEMPHASIS; if ((tg3_flag(tp, 57765_PLUS) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && - GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) && + (tg3_asic_rev(tp) == ASIC_REV_5784 && + tg3_chip_rev(tp) != CHIPREV_5784_AX)) && (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN)) tp->phy_flags |= TG3_PHYFLG_ENABLE_APD; - if (tg3_flag(tp, PCI_EXPRESS) && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - !tg3_flag(tp, 57765_PLUS)) { + if (tg3_flag(tp, PCI_EXPRESS)) { u32 cfg3; tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3); - if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE) + if (tg3_asic_rev(tp) != ASIC_REV_5785 && + !tg3_flag(tp, 57765_PLUS) && + (cfg3 & NIC_SRAM_ASPM_DEBOUNCE)) tg3_flag_set(tp, ASPM_WORKAROUND); + if (cfg3 & NIC_SRAM_LNK_FLAP_AVOID) + tp->phy_flags |= TG3_PHYFLG_KEEP_LINK_ON_PWRDN; + if (cfg3 & NIC_SRAM_1G_ON_VAUX_OK) + tp->phy_flags |= TG3_PHYFLG_1G_ON_VAUX_OK; } if (cfg4 & NIC_SRAM_RGMII_INBAND_DISABLE) @@ -13253,6 +15221,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tg3_flag_set(tp, RGMII_EXT_IBND_RX_EN); if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN) tg3_flag_set(tp, RGMII_EXT_IBND_TX_EN); + + if (cfg5 & NIC_SRAM_DISABLE_1G_HALF_ADV) + tp->phy_flags |= TG3_PHYFLG_DISABLE_1G_HD_ADV; } done: if (tg3_flag(tp, WOL_CAP)) @@ -13262,7 +15233,40 @@ done: device_set_wakeup_capable(&tp->pdev->dev, false); } -static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd) +static int tg3_ape_otp_read(struct tg3 *tp, u32 offset, u32 *val) +{ + int i, err; + u32 val2, off = offset * 8; + + err = tg3_nvram_lock(tp); + if (err) + return err; + + tg3_ape_write32(tp, TG3_APE_OTP_ADDR, off | APE_OTP_ADDR_CPU_ENABLE); + tg3_ape_write32(tp, TG3_APE_OTP_CTRL, APE_OTP_CTRL_PROG_EN | + APE_OTP_CTRL_CMD_RD | APE_OTP_CTRL_START); + tg3_ape_read32(tp, TG3_APE_OTP_CTRL); + udelay(10); + + for (i = 0; i < 100; i++) { + val2 = tg3_ape_read32(tp, TG3_APE_OTP_STATUS); + if (val2 & APE_OTP_STATUS_CMD_DONE) { + *val = tg3_ape_read32(tp, TG3_APE_OTP_RD_DATA); + break; + } + udelay(10); + } + + tg3_ape_write32(tp, TG3_APE_OTP_CTRL, 0); + + tg3_nvram_unlock(tp); + if (val2 & APE_OTP_STATUS_CMD_DONE) + return 0; + + return -EBUSY; +} + +static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd) { int i; u32 val; @@ -13285,7 +15289,7 @@ static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd) * configuration is a 32-bit value that straddles the alignment boundary. * We do two 32-bit reads and then shift and merge the results. */ -static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp) +static u32 tg3_read_otp_phycfg(struct tg3 *tp) { u32 bhalf_otp, thalf_otp; @@ -13311,13 +15315,15 @@ static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp) return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16); } -static void __devinit tg3_phy_init_link_config(struct tg3 *tp) +static void tg3_phy_init_link_config(struct tg3 *tp) { u32 adv = ADVERTISED_Autoneg; - if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) - adv |= ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full; + if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { + if (!(tp->phy_flags & TG3_PHYFLG_DISABLE_1G_HD_ADV)) + adv |= ADVERTISED_1000baseT_Half; + adv |= ADVERTISED_1000baseT_Full; + } if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) adv |= ADVERTISED_100baseT_Half | @@ -13329,17 +15335,16 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp) adv |= ADVERTISED_FIBRE; tp->link_config.advertising = adv; - tp->link_config.speed = SPEED_INVALID; - tp->link_config.duplex = DUPLEX_INVALID; + tp->link_config.speed = SPEED_UNKNOWN; + tp->link_config.duplex = DUPLEX_UNKNOWN; tp->link_config.autoneg = AUTONEG_ENABLE; - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; - tp->link_config.orig_speed = SPEED_INVALID; - tp->link_config.orig_duplex = DUPLEX_INVALID; - tp->link_config.orig_autoneg = AUTONEG_INVALID; + tp->link_config.active_speed = SPEED_UNKNOWN; + tp->link_config.active_duplex = DUPLEX_UNKNOWN; + + tp->old_link = -1; } -static int __devinit tg3_phy_probe(struct tg3 *tp) +static int tg3_phy_probe(struct tg3 *tp) { u32 hw_phy_id_1, hw_phy_id_2; u32 hw_phy_id, hw_phy_id_masked; @@ -13349,6 +15354,29 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tg3_flag_set(tp, PAUSE_AUTONEG); tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX; + if (tg3_flag(tp, ENABLE_APE)) { + switch (tp->pci_fn) { + case 0: + tp->phy_ape_lock = TG3_APE_LOCK_PHY0; + break; + case 1: + tp->phy_ape_lock = TG3_APE_LOCK_PHY1; + break; + case 2: + tp->phy_ape_lock = TG3_APE_LOCK_PHY2; + break; + case 3: + tp->phy_ape_lock = TG3_APE_LOCK_PHY3; + break; + } + } + + if (!tg3_flag(tp, ENABLE_ASF) && + !(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && + !(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) + tp->phy_flags &= ~(TG3_PHYFLG_1G_ON_VAUX_OK | + TG3_PHYFLG_KEEP_LINK_ON_PWRDN); + if (tg3_flag(tp, USE_PHYLIB)) return tg3_phy_init(tp); @@ -13392,10 +15420,19 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) * subsys device table. */ p = tg3_lookup_by_subsys(tp); - if (!p) + if (p) { + tp->phy_id = p->phy_id; + } else if (!tg3_flag(tp, IS_SSB_CORE)) { + /* For now we saw the IDs 0xbc050cd0, + * 0xbc050f80 and 0xbc050c30 on devices + * connected to an BCM4785 and there are + * probably more. Just assume that the phy is + * supported when it is connected to a SSB core + * for now. + */ return -ENODEV; + } - tp->phy_id = p->phy_id; if (!tp->phy_id || tp->phy_id == TG3_PHY_ID_BCM8002) tp->phy_flags |= TG3_PHYFLG_PHY_SERDES; @@ -13403,17 +15440,29 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) } if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720 || - (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 && - tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && - tp->pci_chip_rev_id != CHIPREV_ID_57765_A0))) + (tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_57766 || + tg3_asic_rev(tp) == ASIC_REV_5762 || + (tg3_asic_rev(tp) == ASIC_REV_5717 && + tg3_chip_rev_id(tp) != CHIPREV_ID_5717_A0) || + (tg3_asic_rev(tp) == ASIC_REV_57765 && + tg3_chip_rev_id(tp) != CHIPREV_ID_57765_A0))) { tp->phy_flags |= TG3_PHYFLG_EEE_CAP; + tp->eee.supported = SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full; + tp->eee.advertised = ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full; + tp->eee.eee_enabled = 1; + tp->eee.tx_lpi_enabled = 1; + tp->eee.tx_lpi_timer = TG3_CPMU_DBTMR1_LNKIDLE_2047US; + } + tg3_phy_init_link_config(tp); - if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && + if (!(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) && + !(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && !tg3_flag(tp, ENABLE_APE) && !tg3_flag(tp, ENABLE_ASF)) { u32 bmsr, dummy; @@ -13450,7 +15499,7 @@ skip_phy_reset: return err; } -static void __devinit tg3_read_vpd(struct tg3 *tp) +static void tg3_read_vpd(struct tg3 *tp) { u8 *vpd_data; unsigned int block_end, rosize, len; @@ -13493,8 +15542,11 @@ static void __devinit tg3_read_vpd(struct tg3 *tp) if (j + len > block_end) goto partno; - memcpy(tp->fw_ver, &vpd_data[j], len); - strncat(tp->fw_ver, " bc ", vpdlen - len - 1); + if (len >= sizeof(tp->fw_ver)) + len = sizeof(tp->fw_ver) - 1; + memset(tp->fw_ver, 0, sizeof(tp->fw_ver)); + snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len, + &vpd_data[j]); } partno: @@ -13518,14 +15570,15 @@ out_not_found: return; out_no_vpd: - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { - if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717) + if (tg3_asic_rev(tp) == ASIC_REV_5717) { + if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C) strcpy(tp->board_part_number, "BCM5717"); else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718) strcpy(tp->board_part_number, "BCM5718"); else goto nomatch; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { + } else if (tg3_asic_rev(tp) == ASIC_REV_57780) { if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780) strcpy(tp->board_part_number, "BCM57780"); else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760) @@ -13536,7 +15589,7 @@ out_no_vpd: strcpy(tp->board_part_number, "BCM57788"); else goto nomatch; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + } else if (tg3_asic_rev(tp) == ASIC_REV_57765) { if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761) strcpy(tp->board_part_number, "BCM57761"); else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765) @@ -13551,7 +15604,7 @@ out_no_vpd: strcpy(tp->board_part_number, "BCM57795"); else goto nomatch; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) { + } else if (tg3_asic_rev(tp) == ASIC_REV_57766) { if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57762) strcpy(tp->board_part_number, "BCM57762"); else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57766) @@ -13562,7 +15615,7 @@ out_no_vpd: strcpy(tp->board_part_number, "BCM57786"); else goto nomatch; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + } else if (tg3_asic_rev(tp) == ASIC_REV_5906) { strcpy(tp->board_part_number, "BCM95906"); } else { nomatch: @@ -13570,7 +15623,7 @@ nomatch: } } -static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset) +static int tg3_fw_img_is_valid(struct tg3 *tp, u32 offset) { u32 val; @@ -13583,7 +15636,7 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset) return 1; } -static void __devinit tg3_read_bc_ver(struct tg3 *tp) +static void tg3_read_bc_ver(struct tg3 *tp) { u32 val, offset, start, ver_offset; int i, dst_off; @@ -13635,7 +15688,7 @@ static void __devinit tg3_read_bc_ver(struct tg3 *tp) } } -static void __devinit tg3_read_hwsb_ver(struct tg3 *tp) +static void tg3_read_hwsb_ver(struct tg3 *tp) { u32 val, major, minor; @@ -13651,7 +15704,7 @@ static void __devinit tg3_read_hwsb_ver(struct tg3 *tp) snprintf(&tp->fw_ver[0], 32, "sb v%d.%02d", major, minor); } -static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val) +static void tg3_read_sb_ver(struct tg3 *tp, u32 val) { u32 offset, major, minor, build; @@ -13706,7 +15759,7 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val) } } -static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp) +static void tg3_read_mgmtfw_ver(struct tg3 *tp) { u32 val, offset, start; int i, vlen; @@ -13758,14 +15811,9 @@ static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp) } } -static void __devinit tg3_read_dash_ver(struct tg3 *tp) +static void tg3_probe_ncsi(struct tg3 *tp) { - int vlen; u32 apedata; - char *fwtype; - - if (!tg3_flag(tp, ENABLE_APE) || !tg3_flag(tp, ENABLE_ASF)) - return; apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); if (apedata != APE_SEG_SIG_MAGIC) @@ -13775,14 +15823,24 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp) if (!(apedata & APE_FW_STATUS_READY)) return; + if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI) + tg3_flag_set(tp, APE_HAS_NCSI); +} + +static void tg3_read_dash_ver(struct tg3 *tp) +{ + int vlen; + u32 apedata; + char *fwtype; + apedata = tg3_ape_read32(tp, TG3_APE_FW_VERSION); - if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI) { - tg3_flag_set(tp, APE_HAS_NCSI); + if (tg3_flag(tp, APE_HAS_NCSI)) fwtype = "NCSI"; - } else { + else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5725) + fwtype = "SMASH"; + else fwtype = "DASH"; - } vlen = strlen(tp->fw_ver); @@ -13794,7 +15852,32 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp) (apedata & APE_FW_VERSION_BLDMSK)); } -static void __devinit tg3_read_fw_ver(struct tg3 *tp) +static void tg3_read_otp_ver(struct tg3 *tp) +{ + u32 val, val2; + + if (tg3_asic_rev(tp) != ASIC_REV_5762) + return; + + if (!tg3_ape_otp_read(tp, OTP_ADDRESS_MAGIC0, &val) && + !tg3_ape_otp_read(tp, OTP_ADDRESS_MAGIC0 + 4, &val2) && + TG3_OTP_MAGIC0_VALID(val)) { + u64 val64 = (u64) val << 32 | val2; + u32 ver = 0; + int i, vlen; + + for (i = 0; i < 7; i++) { + if ((val64 & 0xff) == 0) + break; + ver = val64 & 0xff; + val64 >>= 8; + } + vlen = strlen(tp->fw_ver); + snprintf(&tp->fw_ver[vlen], TG3_VER_SIZE - vlen, " .%02d", ver); + } +} + +static void tg3_read_fw_ver(struct tg3 *tp) { u32 val; bool vpd_vers = false; @@ -13804,6 +15887,7 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) if (tg3_flag(tp, NO_NVRAM)) { strcat(tp->fw_ver, "sb"); + tg3_read_otp_ver(tp); return; } @@ -13816,25 +15900,20 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) tg3_read_sb_ver(tp, val); else if ((val & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) tg3_read_hwsb_ver(tp); - else - return; - - if (vpd_vers) - goto done; - if (tg3_flag(tp, ENABLE_APE)) { - if (tg3_flag(tp, ENABLE_ASF)) - tg3_read_dash_ver(tp); - } else if (tg3_flag(tp, ENABLE_ASF)) { - tg3_read_mgmtfw_ver(tp); + if (tg3_flag(tp, ENABLE_ASF)) { + if (tg3_flag(tp, ENABLE_APE)) { + tg3_probe_ncsi(tp); + if (!vpd_vers) + tg3_read_dash_ver(tp); + } else if (!vpd_vers) { + tg3_read_mgmtfw_ver(tp); + } } -done: tp->fw_ver[TG3_VER_SIZE - 1] = 0; } -static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); - static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp) { if (tg3_flag(tp, LRG_PROD_RING_CAP)) @@ -13852,7 +15931,145 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = { { }, }; -static int __devinit tg3_get_invariants(struct tg3 *tp) +static struct pci_dev *tg3_find_peer(struct tg3 *tp) +{ + struct pci_dev *peer; + unsigned int func, devnr = tp->pdev->devfn & ~7; + + for (func = 0; func < 8; func++) { + peer = pci_get_slot(tp->pdev->bus, devnr | func); + if (peer && peer != tp->pdev) + break; + pci_dev_put(peer); + } + /* 5704 can be configured in single-port mode, set peer to + * tp->pdev in that case. + */ + if (!peer) { + peer = tp->pdev; + return peer; + } + + /* + * We don't need to keep the refcount elevated; there's no way + * to remove one half of this device without removing the other + */ + pci_dev_put(peer); + + return peer; +} + +static void tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg) +{ + tp->pci_chip_rev_id = misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT; + if (tg3_asic_rev(tp) == ASIC_REV_USE_PROD_ID_REG) { + u32 reg; + + /* All devices that use the alternate + * ASIC REV location have a CPMU. + */ + tg3_flag_set(tp, CPMU_PRESENT); + + if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57767 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57764 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5762 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5725 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5727 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57787) + reg = TG3PCI_GEN2_PRODID_ASICREV; + else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57762 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57766 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57782 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57786) + reg = TG3PCI_GEN15_PRODID_ASICREV; + else + reg = TG3PCI_PRODID_ASICREV; + + pci_read_config_dword(tp->pdev, reg, &tp->pci_chip_rev_id); + } + + /* Wrong chip ID in 5752 A0. This code can be removed later + * as A0 is not in production. + */ + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5752_A0_HW) + tp->pci_chip_rev_id = CHIPREV_ID_5752_A0; + + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5717_C0) + tp->pci_chip_rev_id = CHIPREV_ID_5720_A0; + + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720) + tg3_flag_set(tp, 5717_PLUS); + + if (tg3_asic_rev(tp) == ASIC_REV_57765 || + tg3_asic_rev(tp) == ASIC_REV_57766) + tg3_flag_set(tp, 57765_CLASS); + + if (tg3_flag(tp, 57765_CLASS) || tg3_flag(tp, 5717_PLUS) || + tg3_asic_rev(tp) == ASIC_REV_5762) + tg3_flag_set(tp, 57765_PLUS); + + /* Intentionally exclude ASIC_REV_5906 */ + if (tg3_asic_rev(tp) == ASIC_REV_5755 || + tg3_asic_rev(tp) == ASIC_REV_5787 || + tg3_asic_rev(tp) == ASIC_REV_5784 || + tg3_asic_rev(tp) == ASIC_REV_5761 || + tg3_asic_rev(tp) == ASIC_REV_5785 || + tg3_asic_rev(tp) == ASIC_REV_57780 || + tg3_flag(tp, 57765_PLUS)) + tg3_flag_set(tp, 5755_PLUS); + + if (tg3_asic_rev(tp) == ASIC_REV_5780 || + tg3_asic_rev(tp) == ASIC_REV_5714) + tg3_flag_set(tp, 5780_CLASS); + + if (tg3_asic_rev(tp) == ASIC_REV_5750 || + tg3_asic_rev(tp) == ASIC_REV_5752 || + tg3_asic_rev(tp) == ASIC_REV_5906 || + tg3_flag(tp, 5755_PLUS) || + tg3_flag(tp, 5780_CLASS)) + tg3_flag_set(tp, 5750_PLUS); + + if (tg3_asic_rev(tp) == ASIC_REV_5705 || + tg3_flag(tp, 5750_PLUS)) + tg3_flag_set(tp, 5705_PLUS); +} + +static bool tg3_10_100_only_device(struct tg3 *tp, + const struct pci_device_id *ent) +{ + u32 grc_misc_cfg = tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK; + + if ((tg3_asic_rev(tp) == ASIC_REV_5703 && + (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) || + (tp->phy_flags & TG3_PHYFLG_IS_FET)) + return true; + + if (ent->driver_data & TG3_DRV_DATA_FLAG_10_100_ONLY) { + if (tg3_asic_rev(tp) == ASIC_REV_5705) { + if (ent->driver_data & TG3_DRV_DATA_FLAG_5705_10_100) + return true; + } else { + return true; + } + } + + return false; +} + +static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) { u32 misc_ctrl_reg; u32 pci_state_reg, grc_misc_cfg; @@ -13883,43 +16100,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl); - tp->pci_chip_rev_id = (misc_ctrl_reg >> - MISC_HOST_CTRL_CHIPREV_SHIFT); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) { - u32 prod_id_asic_rev; - - if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) - pci_read_config_dword(tp->pdev, - TG3PCI_GEN2_PRODID_ASICREV, - &prod_id_asic_rev); - else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57762 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57766 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57782 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57786) - pci_read_config_dword(tp->pdev, - TG3PCI_GEN15_PRODID_ASICREV, - &prod_id_asic_rev); - else - pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV, - &prod_id_asic_rev); - - tp->pci_chip_rev_id = prod_id_asic_rev; - } - - /* Wrong chip ID in 5752 A0. This code can be removed later - * as A0 is not in production. - */ - if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW) - tp->pci_chip_rev_id = CHIPREV_ID_5752_A0; + tg3_detect_asic_rev(tp, misc_ctrl_reg); /* If we have 5702/03 A1 or A2 on certain ICH chipsets, * we need to disable memory and use config. cycles @@ -13938,8 +16119,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * enable this workaround if the 5703 is on the secondary * bus of these ICH bridges. */ - if ((tp->pci_chip_rev_id == CHIPREV_ID_5703_A1) || - (tp->pci_chip_rev_id == CHIPREV_ID_5703_A2)) { + if ((tg3_chip_rev_id(tp) == CHIPREV_ID_5703_A1) || + (tg3_chip_rev_id(tp) == CHIPREV_ID_5703_A2)) { static struct tg3_dev_id { u32 vendor; u32 device; @@ -13979,7 +16160,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { + if (tg3_asic_rev(tp) == ASIC_REV_5701) { static struct tg3_dev_id { u32 vendor; u32 device; @@ -14002,7 +16183,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (bridge->subordinate && (bridge->subordinate->number <= tp->pdev->bus->number) && - (bridge->subordinate->subordinate >= + (bridge->subordinate->busn_res.end >= tp->pdev->bus->number)) { tg3_flag_set(tp, 5701_DMA_BUG); pci_dev_put(bridge); @@ -14017,11 +16198,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * Any tg3 device found behind the bridge will also need the 40-bit * DMA workaround. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { - tg3_flag_set(tp, 5780_CLASS); + if (tg3_flag(tp, 5780_CLASS)) { tg3_flag_set(tp, 40BIT_DMA_BUG); - tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI); + tp->msi_cap = tp->pdev->msi_cap; } else { struct pci_dev *bridge = NULL; @@ -14032,7 +16211,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (bridge && bridge->subordinate && (bridge->subordinate->number <= tp->pdev->bus->number) && - (bridge->subordinate->subordinate >= + (bridge->subordinate->busn_res.end >= tp->pdev->bus->number)) { tg3_flag_set(tp, 40BIT_DMA_BUG); pci_dev_put(bridge); @@ -14041,62 +16220,30 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } while (bridge); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) + if (tg3_asic_rev(tp) == ASIC_REV_5704 || + tg3_asic_rev(tp) == ASIC_REV_5714) tp->pdev_peer = tg3_find_peer(tp); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) - tg3_flag_set(tp, 5717_PLUS); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) - tg3_flag_set(tp, 57765_CLASS); - - if (tg3_flag(tp, 57765_CLASS) || tg3_flag(tp, 5717_PLUS)) - tg3_flag_set(tp, 57765_PLUS); - - /* Intentionally exclude ASIC_REV_5906 */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - tg3_flag(tp, 57765_PLUS)) - tg3_flag_set(tp, 5755_PLUS); - - 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_5906 || - tg3_flag(tp, 5755_PLUS) || - tg3_flag(tp, 5780_CLASS)) - tg3_flag_set(tp, 5750_PLUS); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || - tg3_flag(tp, 5750_PLUS)) - tg3_flag_set(tp, 5705_PLUS); - /* Determine TSO capabilities */ - if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0) + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0) ; /* Do nothing. HW bug. */ else if (tg3_flag(tp, 57765_PLUS)) tg3_flag_set(tp, HW_TSO_3); else if (tg3_flag(tp, 5755_PLUS) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tg3_asic_rev(tp) == ASIC_REV_5906) tg3_flag_set(tp, HW_TSO_2); else if (tg3_flag(tp, 5750_PLUS)) { tg3_flag_set(tp, HW_TSO_1); tg3_flag_set(tp, TSO_BUG); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 && - tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2) + if (tg3_asic_rev(tp) == ASIC_REV_5750 && + tg3_chip_rev_id(tp) >= CHIPREV_ID_5750_C2) tg3_flag_clear(tp, TSO_BUG); - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && - tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) { - tg3_flag_set(tp, TSO_BUG); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) + } else if (tg3_asic_rev(tp) != ASIC_REV_5700 && + tg3_asic_rev(tp) != ASIC_REV_5701 && + tg3_chip_rev_id(tp) != CHIPREV_ID_5705_A0) { + tg3_flag_set(tp, FW_TSO); + tg3_flag_set(tp, TSO_BUG); + if (tg3_asic_rev(tp) == ASIC_REV_5705) tp->fw_needed = FIRMWARE_TG3TSO5; else tp->fw_needed = FIRMWARE_TG3TSO; @@ -14106,7 +16253,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tg3_flag(tp, HW_TSO_1) || tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3) || - tp->fw_needed) { + tg3_flag(tp, FW_TSO)) { /* For firmware TSO, assume ASF is disabled. * We'll disable TSO later if we discover ASF * is enabled in tg3_get_eeprom_hw_cfg(). @@ -14118,47 +16265,60 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->fw_needed = NULL; } - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0) tp->fw_needed = FIRMWARE_TG3; + if (tg3_asic_rev(tp) == ASIC_REV_57766) + tp->fw_needed = FIRMWARE_TG357766; + tp->irq_max = 1; if (tg3_flag(tp, 5750_PLUS)) { tg3_flag_set(tp, SUPPORT_MSI); - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX || - GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 && - tp->pci_chip_rev_id <= CHIPREV_ID_5714_A2 && + if (tg3_chip_rev(tp) == CHIPREV_5750_AX || + tg3_chip_rev(tp) == CHIPREV_5750_BX || + (tg3_asic_rev(tp) == ASIC_REV_5714 && + tg3_chip_rev_id(tp) <= CHIPREV_ID_5714_A2 && tp->pdev_peer == tp->pdev)) tg3_flag_clear(tp, SUPPORT_MSI); if (tg3_flag(tp, 5755_PLUS) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + tg3_asic_rev(tp) == ASIC_REV_5906) { tg3_flag_set(tp, 1SHOT_MSI); } if (tg3_flag(tp, 57765_PLUS)) { tg3_flag_set(tp, SUPPORT_MSIX); tp->irq_max = TG3_IRQ_MAX_VECS; - tg3_rss_init_dflt_indir_tbl(tp); } } - if (tg3_flag(tp, 5755_PLUS)) + tp->txq_max = 1; + tp->rxq_max = 1; + if (tp->irq_max > 1) { + tp->rxq_max = TG3_RSS_MAX_NUM_QS; + tg3_rss_init_dflt_indir_tbl(tp, TG3_RSS_MAX_NUM_QS); + + if (tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720) + tp->txq_max = tp->irq_max - 1; + } + + if (tg3_flag(tp, 5755_PLUS) || + tg3_asic_rev(tp) == ASIC_REV_5906) tg3_flag_set(tp, SHORT_DMA_BUG); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) + if (tg3_asic_rev(tp) == ASIC_REV_5719) tp->dma_limit = TG3_TX_BD_DMA_MAX_4K; - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) - tp->dma_limit = TG3_TX_BD_DMA_MAX_2K; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_5762) tg3_flag_set(tp, LRG_PROD_RING_CAP); if (tg3_flag(tp, 57765_PLUS) && - tp->pci_chip_rev_id != CHIPREV_ID_5719_A0) + tg3_chip_rev_id(tp) != CHIPREV_ID_5719_A0) tg3_flag_set(tp, USE_JUMBO_BDFLAG); if (!tg3_flag(tp, 5705_PLUS) || @@ -14174,30 +16334,21 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_flag_set(tp, PCI_EXPRESS); - if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0) { - int readrq = pcie_get_readrq(tp->pdev); - if (readrq > 2048) - pcie_set_readrq(tp->pdev, 2048); - } - - pci_read_config_word(tp->pdev, - pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL, - &lnkctl); + pcie_capability_read_word(tp->pdev, PCI_EXP_LNKCTL, &lnkctl); if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == - ASIC_REV_5906) { + if (tg3_asic_rev(tp) == ASIC_REV_5906) { tg3_flag_clear(tp, HW_TSO_2); tg3_flag_clear(tp, TSO_CAPABLE); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || - tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_57780_A1) + if (tg3_asic_rev(tp) == ASIC_REV_5784 || + tg3_asic_rev(tp) == ASIC_REV_5761 || + tg3_chip_rev_id(tp) == CHIPREV_ID_57780_A0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_57780_A1) tg3_flag_set(tp, CLKREQ_BUG); - } else if (tp->pci_chip_rev_id == CHIPREV_ID_5717_A0) { + } else if (tg3_chip_rev_id(tp) == CHIPREV_ID_5717_A0) { tg3_flag_set(tp, L1PLLPD_EN); } - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { + } else if (tg3_asic_rev(tp) == ASIC_REV_5785) { /* BCM5785 devices are effectively PCIe devices, and should * follow PCIe codepaths, but do not have a PCIe capabilities * section. @@ -14230,7 +16381,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) &tp->pci_cacheline_sz); pci_read_config_byte(tp->pdev, PCI_LATENCY_TIMER, &tp->pci_lat_timer); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && + if (tg3_asic_rev(tp) == ASIC_REV_5703 && tp->pci_lat_timer < 64) { tp->pci_lat_timer = 64; pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, @@ -14240,7 +16391,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Important! -- It is critical that the PCI-X hw workaround * situation is decided before the first MMIO register access. */ - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) { + if (tg3_chip_rev(tp) == CHIPREV_5700_BX) { /* 5700 BX chips need to have their TX producer index * mailboxes written twice to workaround a bug. */ @@ -14261,12 +16412,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * So explicitly force the chip into D0 here. */ pci_read_config_dword(tp->pdev, - tp->pm_cap + PCI_PM_CTRL, + tp->pdev->pm_cap + PCI_PM_CTRL, &pm_reg); pm_reg &= ~PCI_PM_CTRL_STATE_MASK; pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */; pci_write_config_dword(tp->pdev, - tp->pm_cap + PCI_PM_CTRL, + tp->pdev->pm_cap + PCI_PM_CTRL, pm_reg); /* Also, force SERR#/PERR# in PCI command. */ @@ -14282,7 +16433,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_flag_set(tp, PCI_32BIT); /* Chip-specific fixup from Broadcom driver */ - if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) && + if ((tg3_chip_rev_id(tp) == CHIPREV_ID_5704_A0) && (!(pci_state_reg & PCISTATE_RETRY_SAME_DMA))) { pci_state_reg |= PCISTATE_RETRY_SAME_DMA; pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg); @@ -14299,9 +16450,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Various workaround register access methods */ if (tg3_flag(tp, PCIX_TARGET_HWBUG)) tp->write32 = tg3_write_indirect_reg32; - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || + else if (tg3_asic_rev(tp) == ASIC_REV_5701 || (tg3_flag(tp, PCI_EXPRESS) && - tp->pci_chip_rev_id == CHIPREV_ID_5750_A0)) { + tg3_chip_rev_id(tp) == CHIPREV_ID_5750_A0)) { /* * Back to back register writes can cause problems on these * chips, the workaround is to read back all reg writes @@ -14333,7 +16484,7 @@ 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) { + if (tg3_asic_rev(tp) == 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; @@ -14342,8 +16493,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->write32 == tg3_write_indirect_reg32 || (tg3_flag(tp, PCIX_MODE) && - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701))) + (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701))) tg3_flag_set(tp, SRAM_USE_CONFIG); /* The memory arbiter has to be enabled in order for SRAM accesses @@ -14355,7 +16506,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); tp->pci_fn = PCI_FUNC(tp->pdev->devfn) & 3; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || + if (tg3_asic_rev(tp) == ASIC_REV_5704 || tg3_flag(tp, 5780_CLASS)) { if (tg3_flag(tp, PCIX_MODE)) { pci_read_config_dword(tp->pdev, @@ -14363,21 +16514,23 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) &val); tp->pci_fn = val & 0x7; } - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { - tg3_read_mem(tp, NIC_SRAM_CPMU_STATUS, &val); - if ((val & NIC_SRAM_CPMUSTAT_SIG_MSK) == - NIC_SRAM_CPMUSTAT_SIG) { - tp->pci_fn = val & TG3_CPMU_STATUS_FMSK_5717; - tp->pci_fn = tp->pci_fn ? 1 : 0; - } - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + } else if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720) { tg3_read_mem(tp, NIC_SRAM_CPMU_STATUS, &val); - if ((val & NIC_SRAM_CPMUSTAT_SIG_MSK) == - NIC_SRAM_CPMUSTAT_SIG) { + if ((val & NIC_SRAM_CPMUSTAT_SIG_MSK) != NIC_SRAM_CPMUSTAT_SIG) + val = tr32(TG3_CPMU_STATUS); + + if (tg3_asic_rev(tp) == ASIC_REV_5717) + tp->pci_fn = (val & TG3_CPMU_STATUS_FMSK_5717) ? 1 : 0; + else tp->pci_fn = (val & TG3_CPMU_STATUS_FMSK_5719) >> TG3_CPMU_STATUS_FSHFT_5719; - } + } + + if (tg3_flag(tp, FLUSH_POSTED_WRITES)) { + tp->write32_tx_mbox = tg3_write_flush_reg32; + tp->write32_rx_mbox = tg3_write_flush_reg32; } /* Get eeprom hw config before calling tg3_set_power_state(). @@ -14390,7 +16543,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ tg3_get_eeprom_hw_cfg(tp); - if (tp->fw_needed && tg3_flag(tp, ENABLE_ASF)) { + if (tg3_flag(tp, FW_TSO) && tg3_flag(tp, ENABLE_ASF)) { tg3_flag_clear(tp, TSO_CAPABLE); tg3_flag_clear(tp, TSO_BUG); tp->fw_needed = NULL; @@ -14409,31 +16562,24 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_ape_lock_init(tp); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - tg3_flag(tp, 57765_PLUS)) - tg3_flag_set(tp, CPMU_PRESENT); - /* Set up tp->grc_local_ctrl before calling * tg3_pwrsrc_switch_to_vmain(). GPIO1 driven high * will bring 5700's external PHY out of reset. * It is also used as eeprom write protect on LOMs. */ tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + if (tg3_asic_rev(tp) == ASIC_REV_5700 || tg3_flag(tp, EEPROM_WRITE_PROT)) tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1); /* Unused GPIO3 must be driven as output on 5752 because there * are no pull-up resistors on unused GPIO pins. */ - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) + else if (tg3_asic_rev(tp) == ASIC_REV_5752) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + if (tg3_asic_rev(tp) == ASIC_REV_5755 || + tg3_asic_rev(tp) == ASIC_REV_57780 || tg3_flag(tp, 57765_CLASS)) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; @@ -14447,6 +16593,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT0; } + if (tg3_asic_rev(tp) == ASIC_REV_5762) + tp->grc_local_ctrl |= + tr32(GRC_LOCAL_CTRL) & GRC_LCLCTRL_GPIO_UART_SEL; + /* Switch out of Vaux if it is a NIC */ tg3_pwrsrc_switch_to_vmain(tp); @@ -14457,42 +16607,42 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_flag_set(tp, JUMBO_RING_ENABLE); /* Determine WakeOnLan speed to use. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B2) { + if (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5701_B0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5701_B2) { tg3_flag_clear(tp, WOL_SPEED_100MB); } else { tg3_flag_set(tp, WOL_SPEED_100MB); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + if (tg3_asic_rev(tp) == ASIC_REV_5906) tp->phy_flags |= TG3_PHYFLG_IS_FET; /* A few boards don't want Ethernet@WireSpeed phy feature */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - (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)) || + if (tg3_asic_rev(tp) == ASIC_REV_5700 || + (tg3_asic_rev(tp) == ASIC_REV_5705 && + (tg3_chip_rev_id(tp) != CHIPREV_ID_5705_A0) && + (tg3_chip_rev_id(tp) != CHIPREV_ID_5705_A1)) || (tp->phy_flags & TG3_PHYFLG_IS_FET) || (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) tp->phy_flags |= TG3_PHYFLG_NO_ETH_WIRE_SPEED; - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX || - GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX) + if (tg3_chip_rev(tp) == CHIPREV_5703_AX || + tg3_chip_rev(tp) == CHIPREV_5704_AX) tp->phy_flags |= TG3_PHYFLG_ADC_BUG; - if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5704_A0) tp->phy_flags |= TG3_PHYFLG_5704_A0_BUG; if (tg3_flag(tp, 5705_PLUS) && !(tp->phy_flags & TG3_PHYFLG_IS_FET) && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 && + tg3_asic_rev(tp) != ASIC_REV_5785 && + tg3_asic_rev(tp) != ASIC_REV_57780 && !tg3_flag(tp, 57765_PLUS)) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { + if (tg3_asic_rev(tp) == ASIC_REV_5755 || + tg3_asic_rev(tp) == ASIC_REV_5787 || + tg3_asic_rev(tp) == ASIC_REV_5784 || + tg3_asic_rev(tp) == ASIC_REV_5761) { if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 && tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722) tp->phy_flags |= TG3_PHYFLG_JITTER_BUG; @@ -14502,8 +16652,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->phy_flags |= TG3_PHYFLG_BER_BUG; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && - GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) { + if (tg3_asic_rev(tp) == ASIC_REV_5784 && + tg3_chip_rev(tp) != CHIPREV_5784_AX) { tp->phy_otp = tg3_read_otp_phycfg(tp); if (tp->phy_otp == 0) tp->phy_otp = TG3_OTP_DEFAULT; @@ -14515,20 +16665,21 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->mi_mode = MAC_MI_MODE_BASE; tp->coalesce_mode = 0; - if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX && - GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX) + if (tg3_chip_rev(tp) != CHIPREV_5700_AX && + tg3_chip_rev(tp) != CHIPREV_5700_BX) tp->coalesce_mode |= HOSTCC_MODE_32BYTE; /* Set these bits to enable statistics workaround. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5720_A0) { + if (tg3_asic_rev(tp) == ASIC_REV_5717 || + tg3_asic_rev(tp) == ASIC_REV_5762 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5720_A0) { tp->coalesce_mode |= HOSTCC_MODE_ATTN; tp->grc_mode |= GRC_MODE_IRQ_ON_FLOW_ATTN; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + if (tg3_asic_rev(tp) == ASIC_REV_5785 || + tg3_asic_rev(tp) == ASIC_REV_57780) tg3_flag_set(tp, USE_PHYLIB); err = tg3_mdio_init(tp); @@ -14537,7 +16688,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Initialize data/descriptor byte/word swapping. */ val = tr32(GRC_MODE); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + if (tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_5762) val &= (GRC_MODE_BYTE_SWAP_B2HRX_DATA | GRC_MODE_WORD_SWAP_B2HRX_DATA | GRC_MODE_B2HRX_ENABLE | @@ -14553,16 +16705,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Clear this out for sanity. */ tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); + /* Clear TG3PCI_REG_BASE_ADDR to prevent hangs. */ + tw32(TG3PCI_REG_BASE_ADDR, 0); + pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg); if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 && !tg3_flag(tp, PCIX_TARGET_HWBUG)) { - u32 chiprevid = GET_CHIP_REV_ID(tp->misc_host_ctrl); - - if (chiprevid == CHIPREV_ID_5701_A0 || - chiprevid == CHIPREV_ID_5701_B0 || - chiprevid == CHIPREV_ID_5701_B2 || - chiprevid == CHIPREV_ID_5701_B5) { + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5701_A0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5701_B0 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5701_B2 || + tg3_chip_rev_id(tp) == CHIPREV_ID_5701_B5) { void __iomem *sram_base; /* Write some dummy words into the SRAM status block @@ -14582,16 +16735,21 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) udelay(50); tg3_nvram_init(tp); + /* If the device has an NVRAM, no need to load patch firmware */ + if (tg3_asic_rev(tp) == ASIC_REV_57766 && + !tg3_flag(tp, NO_NVRAM)) + tp->fw_needed = NULL; + grc_misc_cfg = tr32(GRC_MISC_CFG); grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && + if (tg3_asic_rev(tp) == ASIC_REV_5705 && (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) tg3_flag_set(tp, IS_5788); if (!tg3_flag(tp, IS_5788) && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) + tg3_asic_rev(tp) != ASIC_REV_5700) tg3_flag_set(tp, TAGGED_STATUS); if (tg3_flag(tp, TAGGED_STATUS)) { tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD | @@ -14608,22 +16766,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else tp->mac_mode = 0; - /* these are limited to 10/100 only */ - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && - (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && - tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && - (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || - (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && - (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 || - (tp->phy_flags & TG3_PHYFLG_IS_FET)) + if (tg3_10_100_only_device(tp, ent)) tp->phy_flags |= TG3_PHYFLG_10_100_ONLY; err = tg3_phy_probe(tp); @@ -14639,7 +16782,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) { tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT; } else { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) + if (tg3_asic_rev(tp) == ASIC_REV_5700) tp->phy_flags |= TG3_PHYFLG_USE_MI_INTERRUPT; else tp->phy_flags &= ~TG3_PHYFLG_USE_MI_INTERRUPT; @@ -14649,7 +16792,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * change bit implementation, so we must use the * status register in those cases. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) + if (tg3_asic_rev(tp) == ASIC_REV_5700) tg3_flag_set(tp, USE_LINKCHG_REG); else tg3_flag_clear(tp, USE_LINKCHG_REG); @@ -14659,7 +16802,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * upon subsystem IDs. */ if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && + tg3_asic_rev(tp) == ASIC_REV_5701 && !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) { tp->phy_flags |= TG3_PHYFLG_USE_MI_INTERRUPT; tg3_flag_set(tp, USE_LINKCHG_REG); @@ -14671,9 +16814,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else tg3_flag_clear(tp, POLL_SERDES); + if (tg3_flag(tp, ENABLE_APE) && tg3_flag(tp, ENABLE_ASF)) + tg3_flag_set(tp, POLL_CPMU_LINK); + tp->rx_offset = NET_SKB_PAD + NET_IP_ALIGN; tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && + if (tg3_asic_rev(tp) == ASIC_REV_5701 && tg3_flag(tp, PCIX_MODE)) { tp->rx_offset = NET_SKB_PAD; #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS @@ -14690,9 +16836,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* 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) + if (tg3_asic_rev(tp) == ASIC_REV_5750 || + tg3_asic_rev(tp) == ASIC_REV_5752 || + tg3_asic_rev(tp) == ASIC_REV_5755) tp->rx_std_max_post = 8; if (tg3_flag(tp, ASPM_WORKAROUND)) @@ -14703,7 +16849,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } #ifdef CONFIG_SPARC -static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp) +static int tg3_get_macaddr_sparc(struct tg3 *tp) { struct net_device *dev = tp->dev; struct pci_dev *pdev = tp->pdev; @@ -14712,37 +16858,42 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp) int len; addr = of_get_property(dp, "local-mac-address", &len); - if (addr && len == 6) { - memcpy(dev->dev_addr, addr, 6); - memcpy(dev->perm_addr, dev->dev_addr, 6); + if (addr && len == ETH_ALEN) { + memcpy(dev->dev_addr, addr, ETH_ALEN); return 0; } return -ENODEV; } -static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp) +static int tg3_get_default_macaddr_sparc(struct tg3 *tp) { struct net_device *dev = tp->dev; - memcpy(dev->dev_addr, idprom->id_ethaddr, 6); - memcpy(dev->perm_addr, idprom->id_ethaddr, 6); + memcpy(dev->dev_addr, idprom->id_ethaddr, ETH_ALEN); return 0; } #endif -static int __devinit tg3_get_device_address(struct tg3 *tp) +static int tg3_get_device_address(struct tg3 *tp) { struct net_device *dev = tp->dev; u32 hi, lo, mac_offset; int addr_ok = 0; + int err; #ifdef CONFIG_SPARC if (!tg3_get_macaddr_sparc(tp)) return 0; #endif + if (tg3_flag(tp, IS_SSB_CORE)) { + err = ssb_gige_get_macaddr(tp->pdev, &dev->dev_addr[0]); + if (!err && is_valid_ether_addr(&dev->dev_addr[0])) + return 0; + } + mac_offset = 0x7c; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || + if (tg3_asic_rev(tp) == ASIC_REV_5704 || tg3_flag(tp, 5780_CLASS)) { if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) mac_offset = 0xcc; @@ -14755,7 +16906,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) mac_offset = 0xcc; if (tp->pci_fn > 1) mac_offset += 0x18c; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + } else if (tg3_asic_rev(tp) == ASIC_REV_5906) mac_offset = 0x10; /* First try to get it from MAC address mailbox. */ @@ -14802,14 +16953,13 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) #endif return -EINVAL; } - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); return 0; } #define BOUNDARY_SINGLE_CACHELINE 1 #define BOUNDARY_MULTI_CACHELINE 2 -static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) +static u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val) { int cacheline_size; u8 byte; @@ -14824,8 +16974,8 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) /* On 5703 and later chips, the boundary bits have no * effect. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && + if (tg3_asic_rev(tp) != ASIC_REV_5700 && + tg3_asic_rev(tp) != ASIC_REV_5701 && !tg3_flag(tp, PCI_EXPRESS)) goto out; @@ -14950,7 +17100,8 @@ out: return val; } -static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device) +static int tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, + int size, bool to_device) { struct tg3_internal_buffer_desc test_desc; u32 sram_dma_descs; @@ -15037,7 +17188,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = { { }, }; -static int __devinit tg3_test_dma(struct tg3 *tp) +static int tg3_test_dma(struct tg3 *tp) { dma_addr_t buf_dma; u32 *buf, saved_dma_rwctrl; @@ -15062,14 +17213,14 @@ static int __devinit tg3_test_dma(struct tg3 *tp) /* DMA read watermark not used on PCIE */ tp->dma_rwctrl |= 0x00180000; } else if (!tg3_flag(tp, PCIX_MODE)) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) + if (tg3_asic_rev(tp) == ASIC_REV_5705 || + tg3_asic_rev(tp) == ASIC_REV_5750) tp->dma_rwctrl |= 0x003f0000; else tp->dma_rwctrl |= 0x003f000f; } else { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { + if (tg3_asic_rev(tp) == ASIC_REV_5703 || + tg3_asic_rev(tp) == ASIC_REV_5704) { u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f); u32 read_water = 0x7; @@ -15078,35 +17229,37 @@ static int __devinit tg3_test_dma(struct tg3 *tp) * better performance. */ if (tg3_flag(tp, 40BIT_DMA_BUG) && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) + tg3_asic_rev(tp) == ASIC_REV_5704) tp->dma_rwctrl |= 0x8000; else if (ccval == 0x6 || ccval == 0x7) tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) + if (tg3_asic_rev(tp) == ASIC_REV_5703) read_water = 4; /* Set bit 23 to enable PCIX hw bug fix */ tp->dma_rwctrl |= (read_water << DMA_RWCTRL_READ_WATER_SHIFT) | (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) | (1 << 23); - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) { + } else if (tg3_asic_rev(tp) == ASIC_REV_5780) { /* 5780 always in PCIX mode */ tp->dma_rwctrl |= 0x00144000; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { + } else if (tg3_asic_rev(tp) == ASIC_REV_5714) { /* 5714 always in PCIX mode */ tp->dma_rwctrl |= 0x00148000; } else { tp->dma_rwctrl |= 0x001b000f; } } + if (tg3_flag(tp, ONE_DMA_AT_ONCE)) + tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) + if (tg3_asic_rev(tp) == ASIC_REV_5703 || + tg3_asic_rev(tp) == ASIC_REV_5704) tp->dma_rwctrl &= 0xfffffff0; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { + if (tg3_asic_rev(tp) == ASIC_REV_5700 || + tg3_asic_rev(tp) == ASIC_REV_5701) { /* Remove this if it causes problems for some boards. */ tp->dma_rwctrl |= DMA_RWCTRL_USE_MEM_READ_MULT; @@ -15125,13 +17278,9 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); -#if 0 - /* Unneeded, already done by tg3_get_invariants. */ - tg3_switch_clocks(tp); -#endif - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) + if (tg3_asic_rev(tp) != ASIC_REV_5700 && + tg3_asic_rev(tp) != ASIC_REV_5701) goto out; /* It is best to perform DMA test with maximum write burst size @@ -15148,7 +17297,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp) p[i] = i; /* Send the buffer to the chip. */ - ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1); + ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, true); if (ret) { dev_err(&tp->pdev->dev, "%s: Buffer write failed. err = %d\n", @@ -15156,22 +17305,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) break; } -#if 0 - /* validate data reached card RAM correctly. */ - for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) { - u32 val; - tg3_read_mem(tp, 0x2100 + (i*4), &val); - if (le32_to_cpu(val) != p[i]) { - dev_err(&tp->pdev->dev, - "%s: Buffer corrupted on device! " - "(%d != %d)\n", __func__, val, i); - /* ret = -ENODEV here? */ - } - p[i] = 0; - } -#endif /* Now read it back. */ - ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0); + ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, false); if (ret) { dev_err(&tp->pdev->dev, "%s: Buffer read failed. " "err = %d\n", __func__, ret); @@ -15227,7 +17362,7 @@ out_nofree: return ret; } -static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) +static void tg3_init_bufmgr_config(struct tg3 *tp) { if (tg3_flag(tp, 57765_PLUS)) { tp->bufmgr_config.mbuf_read_dma_low_water = @@ -15250,7 +17385,7 @@ 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) { + if (tg3_asic_rev(tp) == ASIC_REV_5906) { tp->bufmgr_config.mbuf_mac_rx_low_water = DEFAULT_MB_MACRX_LOW_WATER_5906; tp->bufmgr_config.mbuf_high_water = @@ -15283,7 +17418,7 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER; } -static char * __devinit tg3_phy_string(struct tg3 *tp) +static char *tg3_phy_string(struct tg3 *tp) { switch (tp->phy_id & TG3_PHY_ID_MASK) { case TG3_PHY_ID_BCM5400: return "5400"; @@ -15308,13 +17443,14 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case TG3_PHY_ID_BCM57765: return "57765"; case TG3_PHY_ID_BCM5719C: return "5719C"; case TG3_PHY_ID_BCM5720C: return "5720C"; + case TG3_PHY_ID_BCM5762: return "5762C"; case TG3_PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; } } -static char * __devinit tg3_bus_string(struct tg3 *tp, char *str) +static char *tg3_bus_string(struct tg3 *tp, char *str) { if (tg3_flag(tp, PCI_EXPRESS)) { strcpy(str, "PCI Express"); @@ -15350,35 +17486,7 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str) return str; } -static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp) -{ - struct pci_dev *peer; - unsigned int func, devnr = tp->pdev->devfn & ~7; - - for (func = 0; func < 8; func++) { - peer = pci_get_slot(tp->pdev->bus, devnr | func); - if (peer && peer != tp->pdev) - break; - pci_dev_put(peer); - } - /* 5704 can be configured in single-port mode, set peer to - * tp->pdev in that case. - */ - if (!peer) { - peer = tp->pdev; - return peer; - } - - /* - * We don't need to keep the refcount elevated; there's no way - * to remove one half of this device without removing the other - */ - pci_dev_put(peer); - - return peer; -} - -static void __devinit tg3_init_coal(struct tg3 *tp) +static void tg3_init_coal(struct tg3 *tp) { struct ethtool_coalesce *ec = &tp->coal; @@ -15409,30 +17517,12 @@ static void __devinit tg3_init_coal(struct tg3 *tp) } } -static const struct net_device_ops tg3_netdev_ops = { - .ndo_open = tg3_open, - .ndo_stop = tg3_close, - .ndo_start_xmit = tg3_start_xmit, - .ndo_get_stats64 = tg3_get_stats64, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_rx_mode = tg3_set_rx_mode, - .ndo_set_mac_address = tg3_set_mac_addr, - .ndo_do_ioctl = tg3_ioctl, - .ndo_tx_timeout = tg3_tx_timeout, - .ndo_change_mtu = tg3_change_mtu, - .ndo_fix_features = tg3_fix_features, - .ndo_set_features = tg3_set_features, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = tg3_poll_controller, -#endif -}; - -static int __devinit tg3_init_one(struct pci_dev *pdev, +static int tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct tg3 *tp; - int i, err, pm_cap; + int i, err; u32 sndmbx, rcvmbx, intmbx; char str[40]; u64 dma_mask, persist_dma_mask; @@ -15454,26 +17544,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, pci_set_master(pdev); - /* Find power-management capability. */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap == 0) { - dev_err(&pdev->dev, - "Cannot find Power Management capability, aborting\n"); - err = -EIO; - goto err_out_free_res; - } - - err = pci_set_power_state(pdev, PCI_D0); - if (err) { - dev_err(&pdev->dev, "Transition to D0 failed, aborting\n"); - goto err_out_free_res; - } - dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS); if (!dev) { - dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n"); err = -ENOMEM; - goto err_out_power_down; + goto err_out_free_res; } SET_NETDEV_DEV(dev, &pdev->dev); @@ -15481,15 +17555,29 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp = netdev_priv(dev); tp->pdev = pdev; tp->dev = dev; - tp->pm_cap = pm_cap; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; + tp->irq_sync = 1; if (tg3_debug > 0) tp->msg_enable = tg3_debug; else tp->msg_enable = TG3_DEF_MSG_ENABLE; + if (pdev_is_ssb_gige_core(pdev)) { + tg3_flag_set(tp, IS_SSB_CORE); + if (ssb_gige_must_flush_posted_writes(pdev)) + tg3_flag_set(tp, FLUSH_POSTED_WRITES); + if (ssb_gige_one_dma_at_once(pdev)) + tg3_flag_set(tp, ONE_DMA_AT_ONCE); + if (ssb_gige_have_roboswitch(pdev)) { + tg3_flag_set(tp, USE_PHYLIB); + tg3_flag_set(tp, ROBOSWITCH); + } + if (ssb_gige_is_rgmii(pdev)) + tg3_flag_set(tp, RGMII_MODE); + } + /* The word/byte swap controls here control register access byte * swapping. DMA data byte swapping is controlled in the GRC_MODE * setting below. @@ -15527,9 +17615,16 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761SE || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) { + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57767 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57764 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5762 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5725 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5727 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57787) { tg3_flag_set(tp, ENABLE_APE); tp->aperegs = pci_ioremap_bar(pdev, BAR_2); if (!tp->aperegs) { @@ -15548,7 +17643,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, dev->netdev_ops = &tg3_netdev_ops; dev->irq = pdev->irq; - err = tg3_get_invariants(tp); + err = tg3_get_invariants(tp, ent); if (err) { dev_err(&pdev->dev, "Problem fetching invariants of chip, aborting\n"); @@ -15596,12 +17691,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_bufmgr_config(tp); - features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - /* 5700 B0 chips do not support checksumming correctly due * to hardware bugs. */ - if (tp->pci_chip_rev_id != CHIPREV_ID_5700_B0) { + if (tg3_chip_rev_id(tp) != CHIPREV_ID_5700_B0) { features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM; if (tg3_flag(tp, 5755_PLUS)) @@ -15621,15 +17714,16 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if (features & NETIF_F_IPV6_CSUM) features |= NETIF_F_TSO6; if (tg3_flag(tp, HW_TSO_3) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && - GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + tg3_asic_rev(tp) == ASIC_REV_5761 || + (tg3_asic_rev(tp) == ASIC_REV_5784 && + tg3_chip_rev(tp) != CHIPREV_5784_AX) || + tg3_asic_rev(tp) == ASIC_REV_5785 || + tg3_asic_rev(tp) == ASIC_REV_57780) features |= NETIF_F_TSO_ECN; } - dev->features |= features; + dev->features |= features | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; dev->vlan_features |= features; /* @@ -15637,14 +17731,15 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * MAC-LOOPBACK. Eventually this need to be enhanced to allow INT-PHY * loopback for the remaining devices. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780 && + if (tg3_asic_rev(tp) != ASIC_REV_5780 && !tg3_flag(tp, CPMU_PRESENT)) /* Add the loopback capability */ features |= NETIF_F_LOOPBACK; dev->hw_features |= features; + dev->priv_flags |= IFF_UNICAST_FLT; - if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && + if (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A1 && !tg3_flag(tp, TSO_CAPABLE) && !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { tg3_flag_set(tp, MAX_RXPEND_64); @@ -15723,10 +17818,14 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); - if (tg3_flag(tp, 5717_PLUS)) { - /* Resume a low-power mode */ - tg3_frob_aux_power(tp, false); - } + if (tg3_asic_rev(tp) == ASIC_REV_5719 || + tg3_asic_rev(tp) == ASIC_REV_5720 || + tg3_asic_rev(tp) == ASIC_REV_5762) + tg3_flag_set(tp, PTP_CAPABLE); + + tg3_timer_init(tp); + + tg3_carrier_off(tp); err = register_netdev(dev); if (err) { @@ -15736,13 +17835,13 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, netdev_info(dev, "Tigon3 [partno(%s) rev %04x] (%s) MAC address %pM\n", tp->board_part_number, - tp->pci_chip_rev_id, + tg3_chip_rev_id(tp), tg3_bus_string(tp, str), dev->dev_addr); if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) { struct phy_device *phydev; - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + phydev = tp->mdio_bus->phy_map[tp->phy_addr]; netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", phydev->drv->name, dev_name(&phydev->dev)); @@ -15793,27 +17892,23 @@ err_out_iounmap: err_out_free_dev: free_netdev(dev); -err_out_power_down: - pci_set_power_state(pdev, PCI_D3hot); - err_out_free_res: pci_release_regions(pdev); err_out_disable_pdev: - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); + if (pci_is_enabled(pdev)) + pci_disable_device(pdev); return err; } -static void __devexit tg3_remove_one(struct pci_dev *pdev) +static void tg3_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); if (dev) { struct tg3 *tp = netdev_priv(dev); - if (tp->fw) - release_firmware(tp->fw); + release_firmware(tp->fw); tg3_reset_task_cancel(tp); @@ -15834,7 +17929,6 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); } } @@ -15844,16 +17938,18 @@ static int tg3_suspend(struct device *device) struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); struct tg3 *tp = netdev_priv(dev); - int err; + int err = 0; + + rtnl_lock(); if (!netif_running(dev)) - return 0; + goto unlock; tg3_reset_task_cancel(tp); tg3_phy_stop(tp); tg3_netif_stop(tp); - del_timer_sync(&tp->timer); + tg3_timer_stop(tp); tg3_full_lock(tp, 1); tg3_disable_ints(tp); @@ -15873,12 +17969,11 @@ static int tg3_suspend(struct device *device) tg3_full_lock(tp, 0); tg3_flag_set(tp, INIT_COMPLETE); - err2 = tg3_restart_hw(tp, 1); + err2 = tg3_restart_hw(tp, true); if (err2) goto out; - tp->timer.expires = jiffies + tp->timer_offset; - add_timer(&tp->timer); + tg3_timer_start(tp); netif_device_attach(dev); tg3_netif_start(tp); @@ -15890,6 +17985,8 @@ out: tg3_phy_start(tp); } +unlock: + rtnl_unlock(); return err; } @@ -15898,22 +17995,26 @@ static int tg3_resume(struct device *device) struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); struct tg3 *tp = netdev_priv(dev); - int err; + int err = 0; + + rtnl_lock(); if (!netif_running(dev)) - return 0; + goto unlock; netif_device_attach(dev); tg3_full_lock(tp, 0); + tg3_ape_driver_state_change(tp, RESET_KIND_INIT); + tg3_flag_set(tp, INIT_COMPLETE); - err = tg3_restart_hw(tp, 1); + err = tg3_restart_hw(tp, + !(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN)); if (err) goto out; - tp->timer.expires = jiffies + tp->timer_offset; - add_timer(&tp->timer); + tg3_timer_start(tp); tg3_netif_start(tp); @@ -15923,17 +18024,30 @@ out: if (!err) tg3_phy_start(tp); +unlock: + rtnl_unlock(); return err; } +#endif /* CONFIG_PM_SLEEP */ static SIMPLE_DEV_PM_OPS(tg3_pm_ops, tg3_suspend, tg3_resume); -#define TG3_PM_OPS (&tg3_pm_ops) -#else +static void tg3_shutdown(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct tg3 *tp = netdev_priv(dev); -#define TG3_PM_OPS NULL + rtnl_lock(); + netif_device_detach(dev); -#endif /* CONFIG_PM_SLEEP */ + if (netif_running(dev)) + dev_close(dev); + + if (system_state == SYSTEM_POWER_OFF) + tg3_power_down(tp); + + rtnl_unlock(); +} /** * tg3_io_error_detected - called when PCI error is detected @@ -15954,18 +18068,18 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, rtnl_lock(); - if (!netif_running(netdev)) + /* We probably don't have netdev yet */ + if (!netdev || !netif_running(netdev)) goto done; tg3_phy_stop(tp); tg3_netif_stop(tp); - del_timer_sync(&tp->timer); + tg3_timer_stop(tp); /* Want to make sure that the reset task doesn't run */ tg3_reset_task_cancel(tp); - tg3_flag_clear(tp, TX_RECOVERY_PENDING); netif_device_detach(netdev); @@ -15975,10 +18089,15 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, tg3_full_unlock(tp); done: - if (state == pci_channel_io_perm_failure) + if (state == pci_channel_io_perm_failure) { + if (netdev) { + tg3_napi_enable(tp); + dev_close(netdev); + } err = PCI_ERS_RESULT_DISCONNECT; - else + } else { pci_disable_device(pdev); + } rtnl_unlock(); @@ -16004,7 +18123,8 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev) rtnl_lock(); if (pci_enable_device(pdev)) { - netdev_err(netdev, "Cannot re-enable PCI device after reset.\n"); + dev_err(&pdev->dev, + "Cannot re-enable PCI device after reset.\n"); goto done; } @@ -16012,7 +18132,7 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev) pci_restore_state(pdev); pci_save_state(pdev); - if (!netif_running(netdev)) { + if (!netdev || !netif_running(netdev)) { rc = PCI_ERS_RESULT_RECOVERED; goto done; } @@ -16024,6 +18144,10 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev) rc = PCI_ERS_RESULT_RECOVERED; done: + if (rc != PCI_ERS_RESULT_RECOVERED && netdev && netif_running(netdev)) { + tg3_napi_enable(tp); + dev_close(netdev); + } rtnl_unlock(); return rc; @@ -16048,28 +18172,30 @@ static void tg3_io_resume(struct pci_dev *pdev) goto done; tg3_full_lock(tp, 0); + tg3_ape_driver_state_change(tp, RESET_KIND_INIT); tg3_flag_set(tp, INIT_COMPLETE); - err = tg3_restart_hw(tp, 1); - tg3_full_unlock(tp); + err = tg3_restart_hw(tp, true); if (err) { + tg3_full_unlock(tp); netdev_err(netdev, "Cannot restart hardware after reset.\n"); goto done; } netif_device_attach(netdev); - tp->timer.expires = jiffies + tp->timer_offset; - add_timer(&tp->timer); + tg3_timer_start(tp); tg3_netif_start(tp); + tg3_full_unlock(tp); + tg3_phy_start(tp); done: rtnl_unlock(); } -static struct pci_error_handlers tg3_err_handler = { +static const struct pci_error_handlers tg3_err_handler = { .error_detected = tg3_io_error_detected, .slot_reset = tg3_io_slot_reset, .resume = tg3_io_resume @@ -16079,20 +18205,10 @@ static struct pci_driver tg3_driver = { .name = DRV_MODULE_NAME, .id_table = tg3_pci_tbl, .probe = tg3_init_one, - .remove = __devexit_p(tg3_remove_one), + .remove = tg3_remove_one, .err_handler = &tg3_err_handler, - .driver.pm = TG3_PM_OPS, + .driver.pm = &tg3_pm_ops, + .shutdown = tg3_shutdown, }; -static int __init tg3_init(void) -{ - return pci_register_driver(&tg3_driver); -} - -static void __exit tg3_cleanup(void) -{ - pci_unregister_driver(&tg3_driver); -} - -module_init(tg3_init); -module_exit(tg3_cleanup); +module_pci_driver(tg3_driver); |
