From: t_jeang Date: Tue, 6 Jan 2009 12:05:57 +0000 (+0000) Subject: imported patch tg3-3.92l X-Git-Tag: drivers-net-atl1-backport X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=536103298b0fc30f30678142d7c64024e4022043;p=xenclient%2Fkernel.git imported patch tg3-3.92l --- diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 81f15752..c937fe9a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -15,9 +15,22 @@ * notice is accompanying it. */ +#include +#if (LINUX_VERSION_CODE < 0x020612) +#include +#endif + +#if (LINUX_VERSION_CODE < 0x020500) +#if defined(CONFIG_MODVERSIONS) && defined(MODULE) && ! defined(MODVERSIONS) +#define MODVERSIONS +#include +#endif +#endif #include +#if (LINUX_VERSION_CODE >= 0x20600) #include +#endif #include #include #include @@ -35,9 +48,14 @@ #include #include #include +#if (LINUX_VERSION_CODE >= 0x20600) #include +#endif #include +#if (LINUX_VERSION_CODE >= 0x020600) #include +#endif +#include #include #include @@ -47,8 +65,6 @@ #include #include -#include "tg3_compat.h" - #ifdef CONFIG_SPARC #include #include @@ -60,14 +76,31 @@ #define TG3_VLAN_TAG_USED 0 #endif +#ifdef NETIF_F_TSO #define TG3_TSO_SUPPORT 1 +#else +#define TG3_TSO_SUPPORT 0 +#endif #include "tg3.h" #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.86" -#define DRV_MODULE_RELDATE "November 9, 2007" +#define DRV_MODULE_VERSION "3.92l" +#define DRV_MODULE_RELDATE "September 26, 2008" + +/* The driver optimizes the hot rx code path by merging a mandatory rx double + * copy check with the normal double copy rx threshold check. On those + * architectures where the mandatory double copy is not needed, we can optimize + * further by saving a device structure dereference and hardcoding the double + * copy threshold in place. + */ +#if NET_IP_ALIGN == 0 || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + #define TG3_RX_COPY_THRESH(tp) RX_COPY_THRESHOLD +#else + #define TG3_RX_COPY_THRESH(tp) ((tp)->rx_copy_thresh) +#endif + #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -123,12 +156,14 @@ TG3_TX_RING_SIZE) #define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) -#define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64) -#define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64) +#define RX_PKT_BUF_SZ (1536 + 64) +#define RX_JUMBO_PKT_BUF_SZ (9046 + 64) /* minimum number of free TX descriptors required to wake up TX process */ #define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4) +#define TG3_RAW_IP_ALIGN 2 + /* number of ETHTOOL_GSTATS u64's */ #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) @@ -143,8 +178,10 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ +#if (LINUX_VERSION_CODE >= 0x20600) module_param(tg3_debug, int, 0); MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); +#endif static struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)}, @@ -205,6 +242,8 @@ static struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761S)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761SE)}, {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)}, @@ -535,6 +574,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) return 0; switch (locknum) { + case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: break; default: @@ -572,6 +612,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) return; switch (locknum) { + case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: break; default: @@ -658,7 +699,11 @@ static void tg3_restart_ints(struct tg3 *tp) static inline void tg3_netif_stop(struct tg3 *tp) { tp->dev->trans_start = jiffies; /* prevent tx timeout */ +#ifdef TG3_NAPI + napi_disable(&tp->napi); +#else netif_poll_disable(tp->dev); +#endif netif_tx_disable(tp->dev); } @@ -669,7 +714,11 @@ static inline void tg3_netif_start(struct tg3 *tp) * so long as all callers are assured to have free tx slots * (such as after tg3_init_hw) */ +#ifdef TG3_NAPI + napi_enable(&tp->napi); +#else netif_poll_enable(tp->dev); +#endif tp->hw_status->status |= SD_STATUS_UPDATED; tg3_enable_ints(tp); } @@ -806,6 +855,301 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) return ret; } +static int tg3_bmcr_reset(struct tg3 *tp) +{ + u32 phy_control; + int limit, err; + + /* OK, reset it, and poll the BMCR_RESET bit until it + * clears or we time out. + */ + phy_control = BMCR_RESET; + err = tg3_writephy(tp, MII_BMCR, phy_control); + if (err != 0) + return -EBUSY; + + limit = 5000; + while (limit--) { + err = tg3_readphy(tp, MII_BMCR, &phy_control); + if (err != 0) + return -EBUSY; + + if ((phy_control & BMCR_RESET) == 0) { + udelay(40); + break; + } + udelay(10); + } + if (limit <= 0) + return -EBUSY; + + return 0; +} + +/* tp->lock is held. */ +static inline void tg3_generate_fw_event(struct tg3 *tp) +{ + u32 val; + + val = tr32(GRC_RX_CPU_EVENT); + val |= GRC_RX_CPU_DRIVER_EVENT; + tw32_f(GRC_RX_CPU_EVENT, val); + + tp->last_event_jiffies = jiffies; +} + +#define TG3_FW_EVENT_TIMEOUT_USEC 2500 + +/* tp->lock is held. */ +static void tg3_wait_for_event_ack(struct tg3 *tp) +{ + int i; + unsigned int delay_cnt; + long time_remain; + + /* If enough time has passed, no wait is necessary. */ + time_remain = (long)(tp->last_event_jiffies + 1 + + usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) - + (long)jiffies; + if (time_remain < 0) + return; + + /* Check if we can shorten the wait time. */ + delay_cnt = jiffies_to_usecs(time_remain); + if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC) + delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC; + delay_cnt = (delay_cnt >> 3) + 1; + + for (i = 0; i < delay_cnt; i++) { + if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT)) + break; + udelay(8); + } +} + +/* tp->lock is held. */ +static void tg3_ump_link_report(struct tg3 *tp) +{ + u32 reg; + u32 val; + + if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || + !(tp->tg3_flags & TG3_FLAG_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); + + 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); + + 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); + + val = 0; + if (!(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) { + if (!tg3_readphy(tp, MII_CTRL1000, ®)) + val = reg << 16; + if (!tg3_readphy(tp, MII_STAT1000, ®)) + val |= (reg & 0xffff); + } + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, 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); + + tg3_generate_fw_event(tp); +} + +static void tg3_link_report(struct tg3 *tp) +{ + if (!netif_carrier_ok(tp->dev)) { + if (netif_msg_link(tp)) + printk(KERN_INFO PFX "%s: Link is down.\n", + tp->dev->name); + tg3_ump_link_report(tp); + } else if (netif_msg_link(tp)) { + printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n", + tp->dev->name, + (tp->link_config.active_speed == SPEED_1000 ? + 1000 : + (tp->link_config.active_speed == SPEED_100 ? + 100 : 10)), + (tp->link_config.active_duplex == DUPLEX_FULL ? + "full" : "half")); + + printk(KERN_INFO PFX + "%s: Flow control is %s for TX and %s for RX.\n", + tp->dev->name, + (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) ? + "on" : "off", + (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) ? + "on" : "off"); + tg3_ump_link_report(tp); + } +} + +static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl) +{ + u16 miireg; + + if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX)) + miireg = ADVERTISE_PAUSE_CAP; + else if (flow_ctrl & TG3_FLOW_CTRL_TX) + miireg = ADVERTISE_PAUSE_ASYM; + else if (flow_ctrl & TG3_FLOW_CTRL_RX) + miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + else + miireg = 0; + + return miireg; +} + +static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) +{ + u16 miireg; + + if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX)) + miireg = ADVERTISE_1000XPAUSE; + else if (flow_ctrl & TG3_FLOW_CTRL_TX) + miireg = ADVERTISE_1000XPSE_ASYM; + else if (flow_ctrl & TG3_FLOW_CTRL_RX) + miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM; + else + miireg = 0; + + return miireg; +} + +static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv) +{ + u8 cap = 0; + + if (lcladv & ADVERTISE_PAUSE_CAP) { + if (lcladv & ADVERTISE_PAUSE_ASYM) { + if (rmtadv & LPA_PAUSE_CAP) + cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; + else if (rmtadv & LPA_PAUSE_ASYM) + cap = TG3_FLOW_CTRL_RX; + } else { + if (rmtadv & LPA_PAUSE_CAP) + cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; + } + } else if (lcladv & ADVERTISE_PAUSE_ASYM) { + if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) + cap = TG3_FLOW_CTRL_TX; + } + + return cap; +} + +static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv) +{ + u8 cap = 0; + + if (lcladv & ADVERTISE_1000XPAUSE) { + if (lcladv & ADVERTISE_1000XPSE_ASYM) { + if (rmtadv & LPA_1000XPAUSE) + cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; + else if (rmtadv & LPA_1000XPAUSE_ASYM) + cap = TG3_FLOW_CTRL_RX; + } else { + if (rmtadv & LPA_1000XPAUSE) + cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; + } + } else if (lcladv & ADVERTISE_1000XPSE_ASYM) { + if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM)) + cap = TG3_FLOW_CTRL_TX; + } + + return cap; +} + +static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv) +{ + u8 autoneg; + u8 flowctrl = 0; + u32 old_rx_mode = tp->rx_mode; + u32 old_tx_mode = tp->tx_mode; + + autoneg = tp->link_config.autoneg; + + if (autoneg == AUTONEG_ENABLE && + (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) { + if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) + flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv); + else + flowctrl = tg3_resolve_flowctrl_1000T(lcladv, rmtadv); + } else + flowctrl = tp->link_config.flowctrl; + + tp->link_config.active_flowctrl = flowctrl; + + if (flowctrl & TG3_FLOW_CTRL_RX) + tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; + else + tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE; + + if (old_rx_mode != tp->rx_mode) + tw32_f(MAC_RX_MODE, tp->rx_mode); + + if (flowctrl & TG3_FLOW_CTRL_TX) + tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; + else + tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE; + + if (old_tx_mode != tp->tx_mode) + tw32_f(MAC_TX_MODE, tp->tx_mode); +} + +static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) +{ + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val); +} + +static void tg3_phy_toggle_apd(struct tg3 *tp, int enable) +{ + u32 reg; + + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + return; + + reg = MII_TG3_MISC_SHDW_WREN | + MII_TG3_MISC_SHDW_SCR5_SEL | + 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) + reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD; + + tg3_writephy(tp, MII_TG3_MISC_SHDW, reg); + + + reg = MII_TG3_MISC_SHDW_WREN | + MII_TG3_MISC_SHDW_APD_SEL | + MII_TG3_MISC_SHDW_APD_WKTM_84MS; + if (enable) + reg |= MII_TG3_MISC_SHDW_APD_ENABLE; + + tg3_writephy(tp, MII_TG3_MISC_SHDW, reg); +} + static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) { u32 phy; @@ -857,35 +1201,47 @@ static void tg3_phy_set_wirespeed(struct tg3 *tp) (val | (1 << 15) | (1 << 4))); } -static int tg3_bmcr_reset(struct tg3 *tp) +static void tg3_phy_apply_otp(struct tg3 *tp) { - u32 phy_control; - int limit, err; + u32 otp, phy; - /* OK, reset it, and poll the BMCR_RESET bit until it - * clears or we time out. - */ - phy_control = BMCR_RESET; - err = tg3_writephy(tp, MII_BMCR, phy_control); - if (err != 0) - return -EBUSY; + if (!tp->phy_otp) + return; - limit = 5000; - while (limit--) { - err = tg3_readphy(tp, MII_BMCR, &phy_control); - if (err != 0) - return -EBUSY; + otp = tp->phy_otp; - if ((phy_control & BMCR_RESET) == 0) { - udelay(40); - break; - } - udelay(10); - } - if (limit <= 0) - return -EBUSY; + /* Enable SM_DSP clock and tx 6dB coding. */ + phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | + MII_TG3_AUXCTL_ACTL_SMDSP_ENA | + MII_TG3_AUXCTL_ACTL_TX_6DB; + tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); - return 0; + phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); + phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT; + tg3_phydsp_write(tp, MII_TG3_DSP_TAP1, phy); + + phy = ((otp & TG3_OTP_HPFFLTR_MASK) >> TG3_OTP_HPFFLTR_SHIFT) | + ((otp & TG3_OTP_HPFOVER_MASK) >> TG3_OTP_HPFOVER_SHIFT); + tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH0, phy); + + phy = ((otp & TG3_OTP_LPFDIS_MASK) >> TG3_OTP_LPFDIS_SHIFT); + phy |= MII_TG3_DSP_AADJ1CH3_ADCCKADJ; + tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH3, phy); + + phy = ((otp & TG3_OTP_VDAC_MASK) >> TG3_OTP_VDAC_SHIFT); + tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, phy); + + phy = ((otp & TG3_OTP_10BTAMP_MASK) >> TG3_OTP_10BTAMP_SHIFT); + tg3_phydsp_write(tp, MII_TG3_DSP_EXP96, phy); + + phy = ((otp & TG3_OTP_ROFF_MASK) >> TG3_OTP_ROFF_SHIFT) | + ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); + tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); + + /* Turn off SM_DSP clock. */ + phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | + MII_TG3_AUXCTL_ACTL_TX_6DB; + tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); } static int tg3_wait_macro_done(struct tg3 *tp) @@ -1068,13 +1424,12 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) return err; } -static void tg3_link_report(struct tg3 *); - /* This will reset the tigon3 PHY if there is no valid * link unless the FORCE argument is non-zero. */ static int tg3_phy_reset(struct tg3 *tp) { + u32 cpmuctrl; u32 phy_status; int err; @@ -1104,11 +1459,30 @@ static int tg3_phy_reset(struct tg3 *tp) goto out; } + 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) { + cpmuctrl = tr32(TG3_CPMU_CTRL); + if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) + tw32(TG3_CPMU_CTRL, + cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY); + } + err = tg3_bmcr_reset(tp); if (err) return err; - if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) { + u32 phy; + + phy = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz; + tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, phy); + + 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) { u32 val; val = tr32(TG3_CPMU_LSPD_1000MB_CLK); @@ -1118,14 +1492,15 @@ static int tg3_phy_reset(struct tg3 *tp) udelay(40); tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val); } - - /* Disable GPHY autopowerdown. */ - tg3_writephy(tp, MII_TG3_MISC_SHDW, - MII_TG3_MISC_SHDW_WREN | - MII_TG3_MISC_SHDW_APD_SEL | - MII_TG3_MISC_SHDW_APD_WKTM_84MS); } + tg3_phy_apply_otp(tp); + + if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) + tg3_phy_toggle_apd(tp, 1); + else + tg3_phy_toggle_apd(tp, 0); + out: if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); @@ -1227,6 +1602,21 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); + } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */ + u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + tp->grc_local_ctrl; + tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); + + grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2; + tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); + + grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0; + tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); } else { u32 no_gpio2; u32 grc_local_ctrl = 0; @@ -1353,7 +1743,8 @@ static void tg3_power_down_phy(struct tg3 *tp) (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) return; - if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX || + GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) { val = tr32(TG3_CPMU_LSPD_1000MB_CLK); val &= ~CPMU_LSPD_1000MB_MACCLK_MASK; val |= CPMU_LSPD_1000MB_MACCLK_12_5; @@ -1412,7 +1803,20 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) "requested.\n", tp->dev->name, state); return -EINVAL; - }; + } + + /* Restore the CLKREQ setting. */ + if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) { + u16 lnkctl; + + pci_read_config_word(tp->pdev, + tp->pcie_cap + PCI_EXP_LNKCTL, + &lnkctl); + lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN; + pci_write_config_word(tp->pdev, + tp->pcie_cap + PCI_EXP_LNKCTL, + lnkctl); + } power_control |= PCI_PM_CTRL_PME_ENABLE; @@ -1447,7 +1851,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) tg3_read_mem(tp, NIC_SRAM_FW_ASF_STATUS_MBOX, &val); if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) break; +#if (LINUX_VERSION_CODE < 0x20607) + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 1000); +#else msleep(1); +#endif } } if (tp->tg3_flags & TG3_FLAG_WOL_CAP) @@ -1489,8 +1898,21 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) tw32(MAC_LED_CTRL, tp->led_ctrl); if (((power_caps & PCI_PM_CAP_PME_D3cold) && - (tp->tg3_flags & TG3_FLAG_WOL_ENABLE))) + (tp->tg3_flags & TG3_FLAG_WOL_ENABLE))) { mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE; + if (((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) && + ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || + (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))) + mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL; + } + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { + mac_mode |= tp->mac_mode & + (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN); + if (mac_mode & MAC_MODE_APE_TX_EN) + mac_mode |= MAC_MODE_TDE_ENABLE; + } tw32_f(MAC_MODE, mac_mode); udelay(100); @@ -1588,102 +2010,6 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) return 0; } -static void tg3_link_report(struct tg3 *tp) -{ - if (!netif_carrier_ok(tp->dev)) { - if (netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: Link is down.\n", - tp->dev->name); - } else if (netif_msg_link(tp)) { - printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n", - tp->dev->name, - (tp->link_config.active_speed == SPEED_1000 ? - 1000 : - (tp->link_config.active_speed == SPEED_100 ? - 100 : 10)), - (tp->link_config.active_duplex == DUPLEX_FULL ? - "full" : "half")); - - printk(KERN_INFO PFX "%s: Flow control is %s for TX and " - "%s for RX.\n", - tp->dev->name, - (tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "on" : "off", - (tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "on" : "off"); - } -} - -static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv) -{ - u32 new_tg3_flags = 0; - u32 old_rx_mode = tp->rx_mode; - u32 old_tx_mode = tp->tx_mode; - - if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { - - /* Convert 1000BaseX flow control bits to 1000BaseT - * bits before resolving flow control. - */ - if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { - local_adv &= ~(ADVERTISE_PAUSE_CAP | - ADVERTISE_PAUSE_ASYM); - remote_adv &= ~(LPA_PAUSE_CAP | LPA_PAUSE_ASYM); - - if (local_adv & ADVERTISE_1000XPAUSE) - local_adv |= ADVERTISE_PAUSE_CAP; - if (local_adv & ADVERTISE_1000XPSE_ASYM) - local_adv |= ADVERTISE_PAUSE_ASYM; - if (remote_adv & LPA_1000XPAUSE) - remote_adv |= LPA_PAUSE_CAP; - if (remote_adv & LPA_1000XPAUSE_ASYM) - remote_adv |= LPA_PAUSE_ASYM; - } - - if (local_adv & ADVERTISE_PAUSE_CAP) { - if (local_adv & ADVERTISE_PAUSE_ASYM) { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); - else if (remote_adv & LPA_PAUSE_ASYM) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE); - } else { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); - } - } else if (local_adv & ADVERTISE_PAUSE_ASYM) { - if ((remote_adv & LPA_PAUSE_CAP) && - (remote_adv & LPA_PAUSE_ASYM)) - new_tg3_flags |= TG3_FLAG_TX_PAUSE; - } - - tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE); - tp->tg3_flags |= new_tg3_flags; - } else { - new_tg3_flags = tp->tg3_flags; - } - - if (new_tg3_flags & TG3_FLAG_RX_PAUSE) - tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; - else - tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE; - - if (old_rx_mode != tp->rx_mode) { - tw32_f(MAC_RX_MODE, tp->rx_mode); - } - - if (new_tg3_flags & TG3_FLAG_TX_PAUSE) - tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; - else - tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE; - - if (old_tx_mode != tp->tx_mode) { - tw32_f(MAC_TX_MODE, tp->tx_mode); - } -} - static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex) { switch (val & MII_TG3_AUX_STAT_SPDMASK) { @@ -1728,7 +2054,7 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *speed = SPEED_INVALID; *duplex = DUPLEX_INVALID; break; - }; + } } static void tg3_phy_copper_begin(struct tg3 *tp) @@ -1754,7 +2080,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) ~(ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); - new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); + new_adv = ADVERTISE_CSMA; if (tp->link_config.advertising & ADVERTISED_10baseT_Half) new_adv |= ADVERTISE_10HALF; if (tp->link_config.advertising & ADVERTISED_10baseT_Full) @@ -1763,6 +2089,9 @@ static void tg3_phy_copper_begin(struct tg3 *tp) new_adv |= ADVERTISE_100HALF; if (tp->link_config.advertising & ADVERTISED_100baseT_Full) new_adv |= ADVERTISE_100FULL; + + new_adv |= tg3_advert_flowctrl_1000T(tp->link_config.flowctrl); + tg3_writephy(tp, MII_ADVERTISE, new_adv); if (tp->link_config.advertising & @@ -1782,9 +2111,11 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tg3_writephy(tp, MII_TG3_CTRL, 0); } } else { + new_adv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl); + new_adv |= ADVERTISE_CSMA; + /* Asking for a specific link mode. */ if (tp->link_config.speed == SPEED_1000) { - new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP; tg3_writephy(tp, MII_ADVERTISE, new_adv); if (tp->link_config.duplex == DUPLEX_FULL) @@ -1795,11 +2126,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) new_adv |= (MII_TG3_CTRL_AS_MASTER | MII_TG3_CTRL_ENABLE_AS_MASTER); - tg3_writephy(tp, MII_TG3_CTRL, new_adv); } else { - tg3_writephy(tp, MII_TG3_CTRL, 0); - - new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP; if (tp->link_config.speed == SPEED_100) { if (tp->link_config.duplex == DUPLEX_FULL) new_adv |= ADVERTISE_100FULL; @@ -1812,7 +2139,11 @@ static void tg3_phy_copper_begin(struct tg3 *tp) new_adv |= ADVERTISE_10HALF; } tg3_writephy(tp, MII_ADVERTISE, new_adv); + + new_adv = 0; } + + tg3_writephy(tp, MII_TG3_CTRL, new_adv); } if (tp->link_config.autoneg == AUTONEG_DISABLE && @@ -1835,7 +2166,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) case SPEED_1000: bmcr |= TG3_BMCR_SPEED1000; break; - }; + } if (tp->link_config.duplex == DUPLEX_FULL) bmcr |= BMCR_FULLDPLX; @@ -1928,10 +2259,44 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask) return 1; } +static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv) +{ + u32 curadv, reqadv; + + if (tg3_readphy(tp, MII_ADVERTISE, lcladv)) + return 1; + + curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl); + + if (tp->link_config.active_duplex == DUPLEX_FULL) { + if (curadv != reqadv) + return 0; + + if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) + tg3_readphy(tp, MII_LPA, rmtadv); + } else { + /* Reprogram the advertisement register, even if it + * does not affect the current link. If the link + * gets renegotiated in the future, we can save an + * additional renegotiation cycle by advertising + * it correctly in the first place. + */ + if (curadv != reqadv) { + *lcladv &= ~(ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv); + } + } + + return 1; +} + static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) { int current_link_up; u32 bmsr, dummy; + u32 lcl_adv, rmt_adv; u16 current_speed; u8 current_duplex; int i, err; @@ -1945,9 +2310,11 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) MAC_STATUS_LNKSTATE_CHANGED)); udelay(40); - tp->mi_mode = MAC_MI_MODE_BASE; - tw32_f(MAC_MI_MODE, tp->mi_mode); - udelay(80); + if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { + tw32_f(MAC_MI_MODE, + (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); + udelay(80); + } tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02); @@ -2074,56 +2441,35 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) udelay(10); } - if (tp->link_config.autoneg == AUTONEG_ENABLE) { - if (bmcr & BMCR_ANENABLE) { - current_link_up = 1; + lcl_adv = 0; + rmt_adv = 0; - /* Force autoneg restart if we are exiting - * low power mode. - */ - if (!tg3_copper_is_advertising_all(tp, - tp->link_config.advertising)) - current_link_up = 0; - } else { - current_link_up = 0; + tp->link_config.active_speed = current_speed; + tp->link_config.active_duplex = current_duplex; + + if (tp->link_config.autoneg == AUTONEG_ENABLE) { + if ((bmcr & BMCR_ANENABLE) && + tg3_copper_is_advertising_all(tp, + tp->link_config.advertising)) { + if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv, + &rmt_adv)) + current_link_up = 1; } } else { if (!(bmcr & BMCR_ANENABLE) && tp->link_config.speed == current_speed && - tp->link_config.duplex == current_duplex) { + tp->link_config.duplex == current_duplex && + tp->link_config.flowctrl == + tp->link_config.active_flowctrl) { current_link_up = 1; - } else { - current_link_up = 0; } } - tp->link_config.active_speed = current_speed; - tp->link_config.active_duplex = current_duplex; + if (current_link_up == 1 && + tp->link_config.active_duplex == DUPLEX_FULL) + tg3_setup_flow_control(tp, lcl_adv, rmt_adv); } - if (current_link_up == 1 && - (tp->link_config.active_duplex == DUPLEX_FULL) && - (tp->link_config.autoneg == AUTONEG_ENABLE)) { - u32 local_adv, remote_adv; - - if (tg3_readphy(tp, MII_ADVERTISE, &local_adv)) - local_adv = 0; - local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - - if (tg3_readphy(tp, MII_LPA, &remote_adv)) - remote_adv = 0; - - remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM); - - /* If we are not advertising full pause capability, - * something is wrong. Bring the link down and reconfigure. - */ - if (local_adv != ADVERTISE_PAUSE_CAP) { - current_link_up = 0; - } else { - tg3_setup_flow_control(tp, local_adv, remote_adv); - } - } relink: if (current_link_up == 0 || tp->link_config.phy_is_low_power) { u32 tmp; @@ -2194,6 +2540,24 @@ relink: NIC_SRAM_FIRMWARE_MBOX_MAGIC2); } + /* Prevent send BD corruption. */ + if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) { + u16 oldlnkctl, newlnkctl; + + pci_read_config_word(tp->pdev, + tp->pcie_cap + 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; + else + newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN; + if (newlnkctl != oldlnkctl) + pci_write_config_word(tp->pdev, + tp->pcie_cap + PCI_EXP_LNKCTL, + newlnkctl); + } + if (current_link_up != netif_carrier_ok(tp->dev)) { if (current_link_up) netif_carrier_on(tp->dev); @@ -2272,6 +2636,7 @@ struct tg3_fiber_aneginfo { static int tg3_fiber_aneg_smachine(struct tg3 *tp, struct tg3_fiber_aneginfo *ap) { + u16 flowctrl; unsigned long delta; u32 rx_cfg_reg; int ret; @@ -2371,7 +2736,12 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp, case ANEG_STATE_ABILITY_DETECT_INIT: ap->flags &= ~(MR_TOGGLE_TX); - ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1); + ap->txconfig = ANEG_CFG_FD; + flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl); + if (flowctrl & ADVERTISE_1000XPAUSE) + ap->txconfig |= ANEG_CFG_PS1; + if (flowctrl & ADVERTISE_1000XPSE_ASYM) + ap->txconfig |= ANEG_CFG_PS2; tw32(MAC_TX_AUTO_NEG, ap->txconfig); tp->mac_mode |= MAC_MODE_SEND_CONFIGS; tw32_f(MAC_MODE, tp->mac_mode); @@ -2512,12 +2882,12 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp, default: ret = ANEG_FAILED; break; - }; + } return ret; } -static int fiber_autoneg(struct tg3 *tp, u32 *flags) +static int fiber_autoneg(struct tg3 *tp, u32 *txflags, u32 *rxflags) { int res = 0; struct tg3_fiber_aneginfo aninfo; @@ -2551,7 +2921,8 @@ static int fiber_autoneg(struct tg3 *tp, u32 *flags) tw32_f(MAC_MODE, tp->mac_mode); udelay(40); - *flags = aninfo.flags; + *txflags = aninfo.txconfig; + *rxflags = aninfo.flags; if (status == ANEG_DONE && (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | @@ -2613,6 +2984,7 @@ static void tg3_init_bcm8002(struct tg3 *tp) static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) { + u16 flowctrl; u32 sg_dig_ctrl, sg_dig_status; u32 serdes_cfg, expected_sg_dig_ctrl; int workaround, port_a; @@ -2638,7 +3010,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) sg_dig_ctrl = tr32(SG_DIG_CTRL); if (tp->link_config.autoneg != AUTONEG_ENABLE) { - if (sg_dig_ctrl & (1 << 31)) { + if (sg_dig_ctrl & SG_DIG_USING_HW_AUTONEG) { if (workaround) { u32 val = serdes_cfg; @@ -2648,7 +3020,8 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) val |= 0x4010000; tw32_f(MAC_SERDES_CFG, val); } - tw32_f(SG_DIG_CTRL, 0x01388400); + + tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP); } if (mac_status & MAC_STATUS_PCS_SYNCED) { tg3_setup_flow_control(tp, 0, 0); @@ -2658,13 +3031,13 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) } /* Want auto-negotiation. */ - expected_sg_dig_ctrl = 0x81388400; - - /* Pause capability */ - expected_sg_dig_ctrl |= (1 << 11); + expected_sg_dig_ctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_COMMON_SETUP; - /* Asymettric pause */ - expected_sg_dig_ctrl |= (1 << 12); + flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl); + if (flowctrl & ADVERTISE_1000XPAUSE) + expected_sg_dig_ctrl |= SG_DIG_PAUSE_CAP; + if (flowctrl & ADVERTISE_1000XPSE_ASYM) + expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE; if (sg_dig_ctrl != expected_sg_dig_ctrl) { if ((tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) && @@ -2679,7 +3052,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) restart_autoneg: if (workaround) tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000); - tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30)); + tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | SG_DIG_SOFT_RESET); udelay(5); tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl); @@ -2690,22 +3063,25 @@ restart_autoneg: sg_dig_status = tr32(SG_DIG_STATUS); mac_status = tr32(MAC_STATUS); - if ((sg_dig_status & (1 << 1)) && + if ((sg_dig_status & SG_DIG_AUTONEG_COMPLETE) && (mac_status & MAC_STATUS_PCS_SYNCED)) { - u32 local_adv, remote_adv; + u32 local_adv = 0, remote_adv = 0; + + if (sg_dig_ctrl & SG_DIG_PAUSE_CAP) + local_adv |= ADVERTISE_1000XPAUSE; + if (sg_dig_ctrl & SG_DIG_ASYM_PAUSE) + local_adv |= ADVERTISE_1000XPSE_ASYM; - local_adv = ADVERTISE_PAUSE_CAP; - remote_adv = 0; - if (sg_dig_status & (1 << 19)) - remote_adv |= LPA_PAUSE_CAP; - if (sg_dig_status & (1 << 20)) - remote_adv |= LPA_PAUSE_ASYM; + if (sg_dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE) + remote_adv |= LPA_1000XPAUSE; + if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE) + remote_adv |= LPA_1000XPAUSE_ASYM; tg3_setup_flow_control(tp, local_adv, remote_adv); current_link_up = 1; tp->serdes_counter = 0; tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; - } else if (!(sg_dig_status & (1 << 1))) { + } else if (!(sg_dig_status & SG_DIG_AUTONEG_COMPLETE)) { if (tp->serdes_counter) tp->serdes_counter--; else { @@ -2720,7 +3096,7 @@ restart_autoneg: tw32_f(MAC_SERDES_CFG, val); } - tw32_f(SG_DIG_CTRL, 0x01388400); + tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP); udelay(40); /* Link parallel detection - link is up */ @@ -2756,18 +3132,21 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) goto out; if (tp->link_config.autoneg == AUTONEG_ENABLE) { - u32 flags; + u32 txflags, rxflags; int i; - if (fiber_autoneg(tp, &flags)) { - u32 local_adv, remote_adv; + if (fiber_autoneg(tp, &txflags, &rxflags)) { + u32 local_adv = 0, remote_adv = 0; - local_adv = ADVERTISE_PAUSE_CAP; - remote_adv = 0; - if (flags & MR_LP_ADV_SYM_PAUSE) - remote_adv |= LPA_PAUSE_CAP; - if (flags & MR_LP_ADV_ASYM_PAUSE) - remote_adv |= LPA_PAUSE_ASYM; + if (txflags & ANEG_CFG_PS1) + local_adv |= ADVERTISE_1000XPAUSE; + if (txflags & ANEG_CFG_PS2) + local_adv |= ADVERTISE_1000XPSE_ASYM; + + if (rxflags & MR_LP_ADV_SYM_PAUSE) + remote_adv |= LPA_1000XPAUSE; + if (rxflags & MR_LP_ADV_ASYM_PAUSE) + remote_adv |= LPA_1000XPAUSE_ASYM; tg3_setup_flow_control(tp, local_adv, remote_adv); @@ -2791,6 +3170,8 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) !(mac_status & MAC_STATUS_RCVD_CFG)) current_link_up = 1; } else { + tg3_setup_flow_control(tp, 0, 0); + /* Forcing 1000FD link up. */ current_link_up = 1; @@ -2814,9 +3195,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) int current_link_up; int i; - orig_pause_cfg = - (tp->tg3_flags & (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE)); + orig_pause_cfg = tp->link_config.active_flowctrl; orig_active_speed = tp->link_config.active_speed; orig_active_duplex = tp->link_config.active_duplex; @@ -2905,9 +3284,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) netif_carrier_off(tp->dev); tg3_link_report(tp); } else { - u32 now_pause_cfg = - tp->tg3_flags & (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); + u32 now_pause_cfg = tp->link_config.active_flowctrl; if (orig_pause_cfg != now_pause_cfg || orig_active_speed != tp->link_config.active_speed || orig_active_duplex != tp->link_config.active_duplex) @@ -2923,6 +3300,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) u32 bmsr, bmcr; u16 current_speed; u8 current_duplex; + u32 local_adv, remote_adv; tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; tw32_f(MAC_MODE, tp->mac_mode); @@ -2967,8 +3345,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) ADVERTISE_1000XPSE_ASYM | ADVERTISE_SLCT); - /* Always advertise symmetric PAUSE just like copper */ - new_adv |= ADVERTISE_1000XPAUSE; + new_adv |= tg3_advert_flowctrl_1000X(tp->link_config.flowctrl); if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) new_adv |= ADVERTISE_1000XHALF; @@ -3039,8 +3416,11 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) else current_duplex = DUPLEX_HALF; + local_adv = 0; + remote_adv = 0; + if (bmcr & BMCR_ANENABLE) { - u32 local_adv, remote_adv, common; + u32 common; err |= tg3_readphy(tp, MII_ADVERTISE, &local_adv); err |= tg3_readphy(tp, MII_LPA, &remote_adv); @@ -3051,15 +3431,15 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) current_duplex = DUPLEX_FULL; else current_duplex = DUPLEX_HALF; - - tg3_setup_flow_control(tp, local_adv, - remote_adv); } else current_link_up = 0; } } + if (current_link_up == 1 && current_duplex == DUPLEX_FULL) + tg3_setup_flow_control(tp, local_adv, remote_adv); + tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX; if (tp->link_config.active_duplex == DUPLEX_HALF) tp->mac_mode |= MAC_MODE_HALF_DUPLEX; @@ -3154,8 +3534,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) err = tg3_setup_copper_phy(tp, force_reset); } - if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) { + if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) { u32 val, scale; val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK; @@ -3343,7 +3722,7 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, default: return -EINVAL; - }; + } /* Do not overwrite any of the map or rp information * until we are sure we can commit to a new buffer. @@ -3351,14 +3730,14 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, * Callers depend upon this behavior and assume that * we leave everything unchanged if we fail. */ - skb = netdev_alloc_skb(tp->dev, skb_size); + skb = netdev_alloc_skb(tp->dev, skb_size + tp->rx_offset); if (skb == NULL) return -ENOMEM; skb_reserve(skb, tp->rx_offset); mapping = pci_map_single(tp->pdev, skb->data, - skb_size - tp->rx_offset, + skb_size, PCI_DMA_FROMDEVICE); map->skb = skb; @@ -3403,7 +3782,7 @@ static void tg3_recycle_rx(struct tg3 *tp, u32 opaque_key, default: return; - }; + } dest_map->skb = src_map->skb; pci_unmap_addr_set(dest_map, mapping, @@ -3414,13 +3793,6 @@ static void tg3_recycle_rx(struct tg3 *tp, u32 opaque_key, src_map->skb = NULL; } -#if TG3_VLAN_TAG_USED -static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag) -{ - return vlan_hwaccel_receive_skb(skb, tp->vlgrp, vlan_tag); -} -#endif - /* The RX ring scheme is composed of multiple rings which post fresh * buffers to the chip, and one special ring the chip uses to report * status back to the host. @@ -3466,6 +3838,8 @@ static int tg3_rx(struct tg3 *tp, int budget) struct sk_buff *skb; dma_addr_t dma_addr; u32 opaque_key, desc_idx, *post_ptr; + bool hw_vlan __maybe_unused = false; + u16 vtag __maybe_unused = 0; desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; @@ -3500,11 +3874,7 @@ static int tg3_rx(struct tg3 *tp, int budget) len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */ - if (len > RX_COPY_THRESHOLD - && tp->rx_offset == 2 - /* rx_offset != 2 iff this is a 5701 card running - * in PCI-X mode [see tg3_get_invariants()] */ - ) { + if (len > TG3_RX_COPY_THRESH(tp)) { int skb_size; skb_size = tg3_alloc_rx_skb(tp, opaque_key, @@ -3513,7 +3883,7 @@ static int tg3_rx(struct tg3 *tp, int budget) goto drop_it; pci_unmap_single(tp->pdev, dma_addr, - skb_size - tp->rx_offset, + skb_size, PCI_DMA_FROMDEVICE); skb_put(skb, len); @@ -3523,11 +3893,11 @@ static int tg3_rx(struct tg3 *tp, int budget) tg3_recycle_rx(tp, opaque_key, desc_idx, *post_ptr); - copy_skb = netdev_alloc_skb(tp->dev, len + 2); + copy_skb = netdev_alloc_skb(tp->dev, len + TG3_RAW_IP_ALIGN + VLAN_HLEN); if (copy_skb == NULL) goto drop_it_no_recycle; - skb_reserve(copy_skb, 2); + skb_reserve(copy_skb, TG3_RAW_IP_ALIGN + VLAN_HLEN); skb_put(copy_skb, len); pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); skb_copy_from_linear_data(skb, copy_skb->data, len); @@ -3546,13 +3916,34 @@ static int tg3_rx(struct tg3 *tp, int budget) skb->ip_summed = CHECKSUM_NONE; skb->protocol = eth_type_trans(skb, tp->dev); + + if ((len > (tp->dev->mtu + ETH_HLEN)) && + (ntohs(skb->protocol) != ETH_P_8021Q)) { + dev_kfree_skb(skb); + goto next_pkt; + } + + if (desc->type_flags & RXD_FLAG_VLAN && + !(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG)) { + vtag = desc->err_vlan & RXD_VLAN_MASK; #if TG3_VLAN_TAG_USED - if (tp->vlgrp != NULL && - desc->type_flags & RXD_FLAG_VLAN) { - tg3_vlan_rx(tp, skb, - desc->err_vlan & RXD_VLAN_MASK); - } else + if (tp->vlgrp) + hw_vlan = true; + else #endif + { + struct vlan_ethhdr *ve = (struct vlan_ethhdr *) + __skb_push(skb, VLAN_HLEN); + + memmove(ve, skb->data + VLAN_HLEN, ETH_ALEN * 2); + ve->h_vlan_proto = htons(ETH_P_8021Q); + ve->h_vlan_TCI = htons(vtag); + } + } + + if (hw_vlan) + vlan_hwaccel_receive_skb(skb, tp->vlgrp, vtag); + else netif_receive_skb(skb); tp->dev->last_rx = jiffies; @@ -3585,6 +3976,9 @@ next_pkt_nopost: tp->rx_rcb_ptr = sw_idx; tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, sw_idx); + /* Some platforms need to sync memory here */ + wmb(); + /* Refill RX ring(s). */ if (work_mask & RXD_OPAQUE_RING_STD) { sw_idx = tp->rx_std_ptr % TG3_RX_RING_SIZE; @@ -3601,6 +3995,85 @@ next_pkt_nopost: return received; } +#ifdef TG3_NAPI + +static int tg3_poll_work(struct tg3 *tp, int work_done, int budget) +{ + struct tg3_hw_status *sblk = tp->hw_status; + + /* handle link change and other phy events */ + if (!(tp->tg3_flags & + (TG3_FLAG_USE_LINKCHG_REG | + TG3_FLAG_POLL_SERDES))) { + if (sblk->status & SD_STATUS_LINK_CHG) { + sblk->status = SD_STATUS_UPDATED | + (sblk->status & ~SD_STATUS_LINK_CHG); + spin_lock(&tp->lock); + tg3_setup_phy(tp, 0); + spin_unlock(&tp->lock); + } + } + + /* run TX completion thread */ + if (sblk->idx[0].tx_consumer != tp->tx_cons) { + tg3_tx(tp); + if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) + 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() + */ + if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) + work_done += tg3_rx(tp, budget - work_done); + + return work_done; +} + +static int tg3_poll(struct napi_struct *napi, int budget) +{ + struct tg3 *tp = container_of(napi, struct tg3, napi); + int work_done = 0; + struct tg3_hw_status *sblk = tp->hw_status; + + while (1) { + work_done = tg3_poll_work(tp, work_done, budget); + + if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) + goto tx_recovery; + + if (unlikely(work_done >= budget)) + break; + + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { + /* tp->last_tag is used in tg3_restart_ints() below + * to tell the hw how much work has been processed, + * so we must read it before checking for more work. + */ + tp->last_tag = sblk->status_tag; + rmb(); + } else + sblk->status &= ~SD_STATUS_UPDATED; + + if (likely(!tg3_has_work(tp))) { + netif_rx_complete(tp->dev, napi); + tg3_restart_ints(tp); + break; + } + } + + return work_done; + +tx_recovery: + /* work_done is guaranteed to be less than budget. */ + netif_rx_complete(tp->dev, napi); + schedule_work(&tp->reset_task); + return work_done; +} + +#else + static int tg3_poll(struct net_device *netdev, int *budget) { struct tg3 *tp = netdev_priv(netdev); @@ -3663,6 +4136,8 @@ static int tg3_poll(struct net_device *netdev, int *budget) return (done ? 0 : 1); } +#endif /* TG3_NAPI */ + static void tg3_irq_quiesce(struct tg3 *tp) { BUG_ON(tp->irq_sync); @@ -3670,7 +4145,11 @@ static void tg3_irq_quiesce(struct tg3 *tp) tp->irq_sync = 1; smp_mb(); +#if (LINUX_VERSION_CODE >= 0x2051c) synchronize_irq(tp->pdev->irq); +#else + synchronize_irq(); +#endif } static inline int tg3_irq_sync(struct tg3 *tp) @@ -3698,7 +4177,11 @@ static inline void tg3_full_unlock(struct tg3 *tp) /* One-shot MSI handler - Chip automatically disables interrupt * after sending MSI so driver doesn't have to do it. */ +#if (LINUX_VERSION_CODE < 0x20613) static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t tg3_msi_1shot(int irq, void *dev_id) +#endif { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3707,7 +4190,11 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs) prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); if (likely(!tg3_irq_sync(tp))) +#ifdef TG3_NAPI + netif_rx_schedule(dev, &tp->napi); +#else netif_rx_schedule(dev); /* schedule NAPI poll */ +#endif return IRQ_HANDLED; } @@ -3716,7 +4203,11 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs) * flush status block and interrupt mailbox. PCI ordering rules * guarantee that MSI will arrive after the status block. */ +#if (LINUX_VERSION_CODE < 0x20613) static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t tg3_msi(int irq, void *dev_id) +#endif { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3732,12 +4223,20 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) */ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); if (likely(!tg3_irq_sync(tp))) +#ifdef TG3_NAPI + netif_rx_schedule(dev, &tp->napi); +#else netif_rx_schedule(dev); /* schedule NAPI poll */ +#endif return IRQ_RETVAL(1); } +#if (LINUX_VERSION_CODE < 0x20613) static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t tg3_interrupt(int irq, void *dev_id) +#endif { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3774,7 +4273,11 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) sblk->status &= ~SD_STATUS_UPDATED; if (likely(tg3_has_work(tp))) { prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); +#ifdef TG3_NAPI + netif_rx_schedule(dev, &tp->napi); +#else netif_rx_schedule(dev); /* schedule NAPI poll */ +#endif } else { /* No work, shared interrupt perhaps? re-enable * interrupts, and flush that PCI write @@ -3786,7 +4289,11 @@ out: return IRQ_RETVAL(handled); } +#if (LINUX_VERSION_CODE < 0x20613) static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) +#endif { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3820,6 +4327,18 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); if (tg3_irq_sync(tp)) goto out; +#ifdef TG3_NAPI + if (netif_rx_schedule_prep(dev, &tp->napi)) { + prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + /* Update last_tag to mark that this status has been + * seen. Because interrupt may be shared, we may be + * racing with tg3_poll(), so only update last_tag + * if tg3_poll() is not scheduled. + */ + tp->last_tag = sblk->status_tag; + __netif_rx_schedule(dev, &tp->napi); + } +#else if (netif_rx_schedule_prep(dev)) { prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); /* Update last_tag to mark that this status has been @@ -3830,13 +4349,17 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r tp->last_tag = sblk->status_tag; __netif_rx_schedule(dev); } +#endif out: return IRQ_RETVAL(handled); } /* ISR for interrupt test */ -static irqreturn_t tg3_test_isr(int irq, void *dev_id, - struct pt_regs *regs) +#if (LINUX_VERSION_CODE < 0x020613) +static irqreturn_t tg3_test_isr(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t tg3_test_isr(int irq, void *dev_id) +#endif { struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); @@ -3857,6 +4380,8 @@ static int tg3_halt(struct tg3 *, int, int); * Invoked with tp->lock held. */ static int tg3_restart_hw(struct tg3 *tp, int reset_phy) + __releases(tp->lock) + __acquires(tp->lock) { int err; @@ -3868,32 +4393,57 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy) tg3_full_unlock(tp); del_timer_sync(&tp->timer); tp->irq_sync = 0; +#ifdef TG3_NAPI + napi_enable(&tp->napi); +#else netif_poll_enable(tp->dev); +#endif dev_close(tp->dev); tg3_full_lock(tp, 0); } return err; } -#ifdef CONFIG_NET_POLL_CONTROLLER +#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) static void tg3_poll_controller(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); +#if defined(RED_HAT_LINUX_KERNEL) && (LINUX_VERSION_CODE < 0x20600) + if (netdump_mode) { + tg3_interrupt(tp->pdev->irq, dev, NULL); + if (dev->poll_list.prev) { + int budget = 64; + + tg3_poll(dev, &budget); + } + } + else +#endif +#if (LINUX_VERSION_CODE < 0x020613) tg3_interrupt(tp->pdev->irq, dev, NULL); +#else + tg3_interrupt(tp->pdev->irq, dev); +#endif } #endif +#if defined(INIT_DELAYED_WORK_DEFERRABLE) || defined(INIT_WORK_NAR) +static void tg3_reset_task(struct work_struct *work) +#else static void tg3_reset_task(void *_data) +#endif { +#if defined(INIT_DELAYED_WORK_DEFERRABLE) || defined(INIT_WORK_NAR) + struct tg3 *tp = container_of(work, struct tg3, reset_task); +#else struct tg3 *tp = _data; +#endif unsigned int restart_timer; tg3_full_lock(tp, 0); - tp->tg3_dist_flags |= TG3_DIST_FLAG_IN_RESET_TASK; if (!netif_running(tp->dev)) { - tp->tg3_dist_flags &= ~TG3_DIST_FLAG_IN_RESET_TASK; tg3_full_unlock(tp); return; } @@ -3924,8 +4474,6 @@ static void tg3_reset_task(void *_data) mod_timer(&tp->timer, jiffies + 1); out: - tp->tg3_dist_flags &= ~TG3_DIST_FLAG_IN_RESET_TASK; - tg3_full_unlock(tp); } @@ -3979,11 +4527,21 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, u32 last_plus_one, u32 *start, u32 base_flags, u32 mss) { - struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); + struct sk_buff *new_skb; dma_addr_t new_addr = 0; u32 entry = *start; int i, ret = 0; + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) + new_skb = skb_copy(skb, GFP_ATOMIC); + else { + int more_headroom = 4 - ((unsigned long)skb->data & 3); + + new_skb = skb_copy_expand(skb, + skb_headroom(skb) + more_headroom, + skb_tailroom(skb), GFP_ATOMIC); + } + if (!new_skb) { ret = -1; } else { @@ -4067,7 +4625,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); /* We are running in BH disabled context with netif_tx_lock - * and TX reclaim runs via tp->poll inside of a software + * and TX reclaim runs via tp->napi.poll inside of a software * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ @@ -4084,6 +4642,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) entry = tp->tx_prod; base_flags = 0; +#if TG3_TSO_SUPPORT != 0 mss = 0; if ((mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; @@ -4094,9 +4653,12 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) goto out_unlock; } +#ifndef BCM_NO_TSO6 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) mss |= (skb_headlen(skb) - ETH_HLEN) << 9; - else { + else +#endif + { struct iphdr *iph = ip_hdr(skb); tcp_opt_len = tcp_optlen(skb); @@ -4113,8 +4675,13 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) tcp_hdr(skb)->check = 0; } - else if (skb->ip_summed == CHECKSUM_HW) + else if (skb->ip_summed == CHECKSUM_PARTIAL) + base_flags |= TXD_FLAG_TCPUDP_CSUM; +#else + mss = 0; + if (skb->ip_summed == CHECKSUM_PARTIAL) base_flags |= TXD_FLAG_TCPUDP_CSUM; +#endif #if TG3_VLAN_TAG_USED if (tp->vlgrp != NULL && vlan_tx_tag_present(skb)) base_flags |= (TXD_FLAG_VLAN | @@ -4156,6 +4723,9 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) } } + /* Some platforms need to sync memory here */ + wmb(); + /* Packets are ready, update Tx producer idx local and on card. */ tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); @@ -4166,7 +4736,9 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_wake_queue(tp->dev); } +#if TG3_TSO_SUPPORT != 0 out_unlock: +#endif mmiowb(); dev->trans_start = jiffies; @@ -4174,6 +4746,228 @@ out_unlock: return NETDEV_TX_OK; } +#if TG3_TSO_SUPPORT != 0 +#ifndef NETIF_F_GSO + +struct sk_buff *skb_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = NULL; + struct sk_buff *tail = NULL; + unsigned int mss = skb_shinfo(skb)->gso_size; + unsigned int doffset = skb->data - skb->mac.raw; + unsigned int offset = doffset; + unsigned int headroom; + unsigned int len; + int nfrags = skb_shinfo(skb)->nr_frags; + int err = -ENOMEM; + int i = 0; + int pos; + + __skb_push(skb, doffset); + headroom = skb_headroom(skb); + pos = skb_headlen(skb); + + do { + struct sk_buff *nskb; + skb_frag_t *frag; + int hsize; + int k; + int size; + + len = skb->len - offset; + if (len > mss) + len = mss; + + hsize = skb_headlen(skb) - offset; + if (hsize < 0) + hsize = 0; + if (hsize > len) + hsize = len; + + nskb = alloc_skb(hsize + doffset + headroom, GFP_ATOMIC); + if (unlikely(!nskb)) + goto err; + + if (segs) + tail->next = nskb; + else + segs = nskb; + tail = nskb; + + nskb->dev = skb->dev; + nskb->priority = skb->priority; + nskb->protocol = skb->protocol; + nskb->dst = dst_clone(skb->dst); + memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); + nskb->pkt_type = skb->pkt_type; + nskb->mac_len = skb->mac_len; + + skb_reserve(nskb, headroom); + nskb->mac.raw = nskb->data; + nskb->nh.raw = nskb->data + skb->mac_len; + nskb->h.raw = nskb->nh.raw + (skb->h.raw - skb->nh.raw); + memcpy(skb_put(nskb, doffset), skb->data, doffset); + + frag = skb_shinfo(nskb)->frags; + k = 0; + + nskb->ip_summed = CHECKSUM_PARTIAL; + nskb->csum = skb->csum; + memcpy(skb_put(nskb, hsize), skb->data + offset, hsize); + + while (pos < offset + len) { + BUG_ON(i >= nfrags); + + *frag = skb_shinfo(skb)->frags[i]; + get_page(frag->page); + size = frag->size; + + if (pos < offset) { + frag->page_offset += offset - pos; + frag->size -= offset - pos; + } + + k++; + + if (pos + size <= offset + len) { + i++; + pos += size; + } else { + frag->size -= pos + size - (offset + len); + break; + } + + frag++; + } + + skb_shinfo(nskb)->nr_frags = k; + nskb->data_len = len - hsize; + nskb->len += nskb->data_len; + nskb->truesize += nskb->data_len; + } while ((offset += len) < skb->len); + + return segs; + +err: + while ((skb = segs)) { + segs = skb->next; + kfree(skb); + } + return ERR_PTR(err); +} + +static struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + struct tcphdr *th; + unsigned thlen; + unsigned int seq; + u32 delta; + unsigned int oldlen; + unsigned int len; + + if (!pskb_may_pull(skb, sizeof(*th))) + goto out; + + th = skb->h.th; + thlen = th->doff * 4; + if (thlen < sizeof(*th)) + goto out; + + if (!pskb_may_pull(skb, thlen)) + goto out; + + oldlen = (u16)~skb->len; + __skb_pull(skb, thlen); + + segs = skb_segment(skb, features); + if (IS_ERR(segs)) + goto out; + + len = skb_shinfo(skb)->gso_size; + delta = htonl(oldlen + (thlen + len)); + + skb = segs; + th = skb->h.th; + seq = ntohl(th->seq); + + do { + th->fin = th->psh = 0; + + th->check = ~csum_fold((u32)((u32)th->check + + (u32)delta)); + seq += len; + skb = skb->next; + th = skb->h.th; + + th->seq = htonl(seq); + th->cwr = 0; + } while (skb->next); + + delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len); + th->check = ~csum_fold((u32)((u32)th->check + + (u32)delta)); +out: + return segs; +} + +static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + struct iphdr *iph; + int ihl; + int id; + + if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) + goto out; + + iph = skb->nh.iph; + ihl = iph->ihl * 4; + if (ihl < sizeof(*iph)) + goto out; + + if (unlikely(!pskb_may_pull(skb, ihl))) + goto out; + + skb->h.raw = __skb_pull(skb, ihl); + iph = skb->nh.iph; + id = ntohs(iph->id); + segs = ERR_PTR(-EPROTONOSUPPORT); + + segs = tcp_tso_segment(skb, features); + + if (!segs || IS_ERR(segs)) + goto out; + + skb = segs; + do { + iph = skb->nh.iph; + iph->id = htons(id++); + iph->tot_len = htons(skb->len - skb->mac_len); + iph->check = 0; + iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); + } while ((skb = skb->next)); + +out: + return segs; +} + +static struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) +{ + struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); + + skb->mac.raw = skb->data; + skb->mac_len = skb->nh.raw - skb->data; + __skb_pull(skb, skb->mac_len); + + segs = inet_gso_segment(skb, features); + + __skb_push(skb, skb->data - skb->mac.raw); + return segs; +} + +#endif + static int tg3_start_xmit_dma_bug(struct sk_buff *, struct net_device *); /* Use GSO to workaround a rare TSO bug that may be triggered when the @@ -4193,7 +4987,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) } segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO); - if (unlikely(IS_ERR(segs))) + if (IS_ERR(segs)) goto tg3_tso_bug_end; do { @@ -4209,6 +5003,8 @@ tg3_tso_bug_end: return NETDEV_TX_OK; } +#endif + /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and * support TG3_FLG2_HW_TSO_1 or firmware TSO only. */ @@ -4222,7 +5018,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); /* We are running in BH disabled context with netif_tx_lock - * and TX reclaim runs via tp->poll inside of a software + * and TX reclaim runs via tp->napi.poll inside of a software * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ @@ -4239,10 +5035,12 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) entry = tp->tx_prod; base_flags = 0; - if (skb->ip_summed == CHECKSUM_HW) + if (skb->ip_summed == CHECKSUM_PARTIAL) base_flags |= TXD_FLAG_TCPUDP_CSUM; +#if TG3_TSO_SUPPORT != 0 mss = 0; - if ((mss = skb_shinfo(skb)->gso_size) != 0) { + if (((mss = skb_shinfo(skb)->gso_size) != 0) && + (skb_shinfo(skb)->gso_segs > 1)) { struct iphdr *iph; int tcp_opt_len, ip_tcp_len, hdr_len; @@ -4292,6 +5090,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) } } } +#else + mss = 0; +#endif #if TG3_VLAN_TAG_USED if (tp->vlgrp != NULL && vlan_tx_tag_present(skb)) base_flags |= (TXD_FLAG_VLAN | @@ -4306,7 +5107,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) would_hit_hwbug = 0; - if (tg3_4g_overflow_test(mapping, len)) + if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG) + would_hit_hwbug = 1; + else if (tg3_4g_overflow_test(mapping, len)) would_hit_hwbug = 1; tg3_set_txd(tp, entry, mapping, len, base_flags, @@ -4365,6 +5168,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) entry = start; } + /* Some platforms need to sync memory here */ + wmb(); + /* Packets are ready, update Tx producer idx local and on card. */ tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); @@ -4391,7 +5197,9 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, if (new_mtu > ETH_DATA_LEN) { if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; +#if TG3_TSO_SUPPORT != 0 ethtool_op_set_tso(dev, 0); +#endif } else tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE; @@ -4455,7 +5263,7 @@ static void tg3_free_rings(struct tg3 *tp) continue; pci_unmap_single(tp->pdev, pci_unmap_addr(rxp, mapping), - tp->rx_pkt_buf_sz - tp->rx_offset, + tp->rx_pkt_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb_any(rxp->skb); rxp->skb = NULL; @@ -4468,7 +5276,7 @@ static void tg3_free_rings(struct tg3 *tp) continue; pci_unmap_single(tp->pdev, pci_unmap_addr(rxp, mapping), - RX_JUMBO_PKT_BUF_SZ - tp->rx_offset, + RX_JUMBO_PKT_BUF_SZ, PCI_DMA_FROMDEVICE); dev_kfree_skb_any(rxp->skb); rxp->skb = NULL; @@ -4541,7 +5349,7 @@ static int tg3_init_rings(struct tg3 *tp) struct tg3_rx_buffer_desc *rxd; rxd = &tp->rx_std[i]; - rxd->idx_len = (tp->rx_pkt_buf_sz - tp->rx_offset - 64) + rxd->idx_len = (tp->rx_pkt_buf_sz - 64) << RXD_LEN_SHIFT; rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT); rxd->opaque = (RXD_OPAQUE_RING_STD | @@ -4553,7 +5361,7 @@ static int tg3_init_rings(struct tg3 *tp) struct tg3_rx_buffer_desc *rxd; rxd = &tp->rx_jumbo[i]; - rxd->idx_len = (RX_JUMBO_PKT_BUF_SZ - tp->rx_offset - 64) + rxd->idx_len = (RX_JUMBO_PKT_BUF_SZ - 64) << RXD_LEN_SHIFT; rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT) | RXD_FLAG_JUMBO; @@ -4724,7 +5532,7 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int default: break; - }; + } } val = tr32(ofs); @@ -4877,7 +5685,7 @@ static void tg3_ape_send_event(struct tg3 *tp, u32 event) return; apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); - if (apedata != APE_FW_STATUS_READY) + if (!(apedata & APE_FW_STATUS_READY)) return; /* Wait for up to 1 millisecond for APE to service previous event. */ @@ -4927,6 +5735,13 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) event = APE_EVENT_STATUS_STATE_START; break; case RESET_KIND_SHUTDOWN: + /* With the interface we are currently using, + * APE does not track driver state. Wiping + * out the HOST SEGMENT SIGNATURE forces + * the APE to assume OS absent status. + */ + tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0); + event = APE_EVENT_STATUS_STATE_UNLOAD; break; case RESET_KIND_SUSPEND: @@ -4966,13 +5781,12 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) default: break; - }; + } } if (kind == RESET_KIND_INIT || kind == RESET_KIND_SUSPEND) tg3_ape_driver_state_change(tp, kind); - } /* tp->lock is held. */ @@ -4992,7 +5806,7 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind) default: break; - }; + } } if (kind == RESET_KIND_SHUTDOWN) @@ -5021,7 +5835,7 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind) default: break; - }; + } } } @@ -5102,7 +5916,7 @@ static void tg3_restore_pci_state(struct tg3 *tp) } /* Make sure PCI-X relaxed ordering bit is clear. */ - if (tp->pcix_cap) { + if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { u16 pcix_cmd; pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD, @@ -5143,6 +5957,8 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_nvram_lock(tp); + tg3_ape_lock(tp, TG3_APE_LOCK_GRC); + /* No matching tg3_nvram_unlock() after this because * chip reset below will undo the nvram lock. */ @@ -5184,7 +6000,11 @@ static int tg3_chip_reset(struct tg3 *tp) } tp->last_tag = 0; smp_mb(); +#if (LINUX_VERSION_CODE >= 0x2051c) synchronize_irq(tp->pdev->irq); +#else + synchronize_irq(); +#endif /* do the reset */ val = GRC_MISC_CFG_CORECLK_RESET; @@ -5290,10 +6110,17 @@ static int tg3_chip_reset(struct tg3 *tp) } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_GMII; tw32_f(MAC_MODE, tp->mac_mode); + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { + tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN); + if (tp->mac_mode & MAC_MODE_APE_TX_EN) + tp->mac_mode |= MAC_MODE_TDE_ENABLE; + tw32_f(MAC_MODE, tp->mac_mode); } else tw32_f(MAC_MODE, 0); udelay(40); + tg3_ape_unlock(tp, TG3_APE_LOCK_GRC); + err = tg3_poll_fw(tp); if (err) return err; @@ -5315,6 +6142,7 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; + tp->last_event_jiffies = jiffies; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; } @@ -5328,20 +6156,15 @@ static void tg3_stop_fw(struct tg3 *tp) { if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { - u32 val; - int i; + /* Wait for RX cpu to ACK the previous event. */ + tg3_wait_for_event_ack(tp); tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW); - val = tr32(GRC_RX_CPU_EVENT); - val |= (1 << 14); - tw32(GRC_RX_CPU_EVENT, val); - /* Wait for RX cpu to ACK the event. */ - for (i = 0; i < 100; i++) { - if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14))) - break; - udelay(1); - } + tg3_generate_fw_event(tp); + + /* Wait for RX cpu to ACK this event. */ + tg3_wait_for_event_ack(tp); } } @@ -5667,6 +6490,7 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) return 0; } +#if TG3_TSO_SUPPORT != 0 #define TG3_TSO_FW_RELEASE_MAJOR 0x1 #define TG3_TSO_FW_RELASE_MINOR 0x6 @@ -6243,6 +7067,7 @@ static int tg3_load_tso_firmware(struct tg3 *tp) return 0; } +#endif /* TG3_TSO_SUPPORT != 0 */ /* tp->lock is held. */ static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1) @@ -6384,8 +7209,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_write_sig_legacy(tp, RESET_KIND_INIT); - if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) { + if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) { val = tr32(TG3_CPMU_CTRL); val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE); tw32(TG3_CPMU_CTRL, val); @@ -6494,6 +7318,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE); tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE); } +#if TG3_TSO_SUPPORT != 0 else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { int fw_len; @@ -6508,6 +7333,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE5705 - fw_len - 0xa00); } +#endif if (tp->dev->mtu <= ETH_DATA_LEN) { tw32(BUFMGR_MB_RDMA_LOW_WATER, @@ -6667,7 +7493,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) __tg3_set_mac_addr(tp, 0); /* MTU + ethernet header + FCS + optional VLAN tag */ - tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + 8); + tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); /* The slot time is changed by tg3_setup_phy if we * run at gigabit with half duplex. @@ -6711,8 +7537,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; +#if TG3_TSO_SUPPORT != 0 if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) rdmac_mode |= (1 << 27); +#endif /* Receive/send statistics. */ if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { @@ -6785,7 +7613,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(10); } - tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; + else + tp->mac_mode = 0; + tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && @@ -6859,7 +7691,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) (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)) - val |= (1 << 29); + val |= WDMAC_MODE_STATUS_TAG_FIX; tw32_f(WDMAC_MODE, val); udelay(40); @@ -6897,8 +7729,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB); tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ); tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); +#if TG3_TSO_SUPPORT != 0 if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8); +#endif tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE); tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE); @@ -6908,11 +7742,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) return err; } +#if TG3_TSO_SUPPORT != 0 if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { err = tg3_load_tso_firmware(tp); if (err) return err; } +#endif tp->tx_mode = TX_MODE_ENABLE; tw32_f(MAC_TX_MODE, tp->tx_mode); @@ -6920,6 +7756,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->rx_mode = RX_MODE_ENABLE; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; @@ -6933,7 +7770,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->link_config.autoneg = tp->link_config.orig_autoneg; } - tp->mi_mode = MAC_MI_MODE_BASE; + tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL; tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); @@ -7048,7 +7885,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) default: break; - }; + } if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) /* Write our heartbeat update interval to APE. */ @@ -7228,17 +8065,17 @@ static void tg3_timer(unsigned long __opaque) * resets. */ if (!--tp->asf_counter) { - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { - u32 val; + if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && + !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { + tg3_wait_for_event_ack(tp); tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_ALIVE3); tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); /* 5 seconds timeout */ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); - val = tr32(GRC_RX_CPU_EVENT); - val |= (1 << 14); - tw32(GRC_RX_CPU_EVENT, val); + + tg3_generate_fw_event(tp); } tp->asf_counter = tp->asf_multiplier; } @@ -7252,7 +8089,11 @@ restart_timer: static int tg3_request_irq(struct tg3 *tp) { +#if (LINUX_VERSION_CODE < 0x020613) irqreturn_t (*fn)(int, void *, struct pt_regs *); +#else + irq_handler_t fn; +#endif unsigned long flags; struct net_device *dev = tp->dev; @@ -7306,7 +8147,12 @@ static int tg3_test_interrupt(struct tg3 *tp) break; } +#if (LINUX_VERSION_CODE < 0x20607) + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(10); +#else msleep(10); +#endif } tg3_disable_ints(tp); @@ -7361,7 +8207,9 @@ static int tg3_test_msi(struct tg3 *tp) tp->dev->name); free_irq(tp->pdev->irq, dev); +#ifdef CONFIG_PCI_MSI pci_disable_msi(tp->pdev); +#endif tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; @@ -7412,6 +8260,7 @@ static int tg3_open(struct net_device *dev) if (err) return err; +#ifdef CONFIG_PCI_MSI if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) { /* All MSI supporting chips should support tagged * status. Assert that this is the case. @@ -7422,26 +8271,39 @@ static int tg3_open(struct net_device *dev) } else if (pci_enable_msi(tp->pdev) == 0) { u32 msi_mode; +#ifndef BCM_HAS_INTX_MSI_WORKAROUND /* Hardware bug - MSI won't work if INTX disabled. */ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) +#if (LINUX_VERSION_CODE < 0x2060e) + tg3_enable_intx(tp->pdev); +#else pci_intx(tp->pdev, 1); +#endif +#endif msi_mode = tr32(MSGINT_MODE); tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); tp->tg3_flags2 |= TG3_FLG2_USING_MSI; } } +#endif err = tg3_request_irq(tp); if (err) { if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { +#ifdef CONFIG_PCI_MSI pci_disable_msi(tp->pdev); +#endif tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; } tg3_free_consistent(tp); return err; } +#ifdef TG3_NAPI + napi_enable(&tp->napi); +#endif + tg3_full_lock(tp, 0); err = tg3_init_hw(tp, 1); @@ -7469,9 +8331,14 @@ static int tg3_open(struct net_device *dev) tg3_full_unlock(tp); if (err) { +#ifdef TG3_NAPI + napi_disable(&tp->napi); +#endif free_irq(tp->pdev->irq, dev); if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { +#ifdef CONFIG_PCI_MSI pci_disable_msi(tp->pdev); +#endif tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; } tg3_free_consistent(tp); @@ -7485,7 +8352,9 @@ static int tg3_open(struct net_device *dev) tg3_full_lock(tp, 0); if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { +#ifdef CONFIG_PCI_MSI pci_disable_msi(tp->pdev); +#endif tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; } tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); @@ -7494,6 +8363,10 @@ static int tg3_open(struct net_device *dev) tg3_full_unlock(tp); +#ifdef TG3_NAPI + napi_disable(&tp->napi); +#endif + return err; } @@ -7755,12 +8628,16 @@ static int tg3_close(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); - /* Calling flush_scheduled_work() may deadlock because - * linkwatch_event() may be on the workqueue and it will try to get - * the rtnl_lock which we are holding. - */ - while (tp->tg3_dist_flags & TG3_DIST_FLAG_IN_RESET_TASK) - msleep(1); +#ifdef TG3_NAPI + napi_disable(&tp->napi); +#endif + +#if (LINUX_VERSION_CODE >= 0x20616) + cancel_work_sync(&tp->reset_task); +#else + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); +#endif netif_stop_queue(dev); @@ -7781,7 +8658,9 @@ static int tg3_close(struct net_device *dev) free_irq(tp->pdev->irq, dev); if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { +#ifdef CONFIG_PCI_MSI pci_disable_msi(tp->pdev); +#endif tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; } @@ -8179,22 +9058,27 @@ do { p = (u32 *)(orig_p + (reg)); \ tg3_full_unlock(tp); } +#if (LINUX_VERSION_CODE >= 0x20418) static int tg3_get_eeprom_len(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); return tp->nvram_size; } +#endif static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val); +static int tg3_nvram_read_le(struct tg3 *tp, u32 offset, __le32 *val); static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val); +#ifdef ETHTOOL_GEEPROM static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct tg3 *tp = netdev_priv(dev); int ret; u8 *pd; - u32 i, offset, len, val, b_offset, b_count; + u32 i, offset, len, b_offset, b_count; + __le32 val; if (tp->link_config.phy_is_low_power) return -EAGAIN; @@ -8213,10 +9097,9 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, /* i.e. offset=1 len=2 */ b_count = len; } - ret = tg3_nvram_read(tp, offset-b_offset, &val); + ret = tg3_nvram_read_le(tp, offset-b_offset, &val); if (ret) return ret; - val = cpu_to_le32(val); memcpy(data, ((char*)&val) + b_offset, b_count); len -= b_count; offset += b_count; @@ -8226,12 +9109,11 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, /* read bytes upto the last 4 byte boundary */ pd = &data[eeprom->len]; for (i = 0; i < (len - (len & 3)); i += 4) { - ret = tg3_nvram_read(tp, offset + i, &val); + ret = tg3_nvram_read_le(tp, offset + i, &val); if (ret) { eeprom->len += i; return ret; } - val = cpu_to_le32(val); memcpy(pd + i, &val, 4); } eeprom->len += i; @@ -8241,24 +9123,26 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, pd = &data[eeprom->len]; b_count = len & 3; b_offset = offset + len - b_count; - ret = tg3_nvram_read(tp, b_offset, &val); + ret = tg3_nvram_read_le(tp, b_offset, &val); if (ret) return ret; - val = cpu_to_le32(val); - memcpy(pd, ((char*)&val), b_count); + memcpy(pd, &val, b_count); eeprom->len += b_count; } return 0; } +#endif static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); +#ifdef ETHTOOL_SEEPROM static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct tg3 *tp = netdev_priv(dev); int ret; - u32 offset, len, b_offset, odd_len, start, end; + u32 offset, len, b_offset, odd_len; u8 *buf; + __le32 start, end; if (tp->link_config.phy_is_low_power) return -EAGAIN; @@ -8271,10 +9155,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, if ((b_offset = (offset & 3))) { /* adjustments to start on required 4 byte boundary */ - ret = tg3_nvram_read(tp, offset-b_offset, &start); + ret = tg3_nvram_read_le(tp, offset-b_offset, &start); if (ret) return ret; - start = cpu_to_le32(start); len += b_offset; offset &= ~3; if (len < 4) @@ -8286,10 +9169,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, /* adjustments to end on required 4 byte boundary */ odd_len = 1; len = (len + 3) & ~3; - ret = tg3_nvram_read(tp, offset+len-4, &end); + ret = tg3_nvram_read_le(tp, offset+len-4, &end); if (ret) return ret; - end = cpu_to_le32(end); } buf = data; @@ -8311,10 +9193,11 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, return ret; } +#endif static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct tg3 *tp = netdev_priv(dev); + struct tg3 *tp = netdev_priv(dev); cmd->supported = (SUPPORTED_Autoneg); @@ -8368,7 +9251,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) (cmd->speed == SPEED_1000)) return -EINVAL; else if ((cmd->speed == SPEED_1000) && - (tp->tg3_flags2 & TG3_FLAG_10_100_ONLY)) + (tp->tg3_flags & TG3_FLAG_10_100_ONLY)) return -EINVAL; tg3_full_lock(tp, 0); @@ -8383,7 +9266,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) tp->link_config.advertising = 0; tp->link_config.speed = cmd->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; @@ -8453,6 +9336,7 @@ static void tg3_set_msglevel(struct net_device *dev, u32 value) tp->msg_enable = value; } +#if TG3_TSO_SUPPORT != 0 static int tg3_set_tso(struct net_device *dev, u32 value) { struct tg3 *tp = netdev_priv(dev); @@ -8466,13 +9350,16 @@ static int tg3_set_tso(struct net_device *dev, u32 value) (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) { if (value) { dev->features |= NETIF_F_TSO6; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + if (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)) dev->features |= NETIF_F_TSO_ECN; } else dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN); } return ethtool_op_set_tso(dev, value); } +#endif static int tg3_nway_reset(struct net_device *dev) { @@ -8569,8 +9456,16 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam struct tg3 *tp = netdev_priv(dev); epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0; - epause->rx_pause = (tp->tg3_flags & TG3_FLAG_RX_PAUSE) != 0; - epause->tx_pause = (tp->tg3_flags & TG3_FLAG_TX_PAUSE) != 0; + + if (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) + epause->rx_pause = 1; + else + epause->rx_pause = 0; + + if (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) + epause->tx_pause = 1; + else + epause->tx_pause = 0; } static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) @@ -8590,13 +9485,13 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam else tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; if (epause->rx_pause) - tp->tg3_flags |= TG3_FLAG_RX_PAUSE; + tp->link_config.flowctrl |= TG3_FLOW_CTRL_RX; else - tp->tg3_flags &= ~TG3_FLAG_RX_PAUSE; + tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_RX; if (epause->tx_pause) - tp->tg3_flags |= TG3_FLAG_TX_PAUSE; + tp->link_config.flowctrl |= TG3_FLOW_CTRL_TX; else - tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE; + tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_TX; if (netif_running(dev)) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); @@ -8636,6 +9531,7 @@ static int tg3_set_rx_csum(struct net_device *dev, u32 data) return 0; } +#ifdef BCM_HAS_SET_TX_CSUM static int tg3_set_tx_csum(struct net_device *dev, u32 data) { struct tg3 *tp = netdev_priv(dev); @@ -8650,22 +9546,43 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) 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 defined(BCM_HAS_ETHTOOL_OP_SET_TX_IPV6_CSUM) + ethtool_op_set_tx_ipv6_csum(dev, data); +#elif defined(BCM_HAS_ETHTOOL_OP_SET_TX_HW_CSUM) ethtool_op_set_tx_hw_csum(dev, data); +#else + tg3_set_tx_hw_csum(dev, data); +#endif else ethtool_op_set_tx_csum(dev, data); return 0; } +#endif + +static int tg3_get_sset_count (struct net_device *dev, int sset) +{ + switch (sset) { + case ETH_SS_TEST: + return TG3_NUM_TEST; + case ETH_SS_STATS: + return TG3_NUM_STATS; + default: + return -EOPNOTSUPP; + } +} +#if (LINUX_VERSION_CODE < 0x020618) static int tg3_get_stats_count (struct net_device *dev) { - return TG3_NUM_STATS; + return tg3_get_sset_count(dev, ETH_SS_STATS); } static int tg3_get_test_count (struct net_device *dev) { - return TG3_NUM_TEST; + return tg3_get_sset_count(dev, ETH_SS_TEST); } +#endif static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf) { @@ -8691,7 +9608,7 @@ static int tg3_phys_id(struct net_device *dev, u32 data) return -EAGAIN; if (data == 0) - data = 2; + data = UINT_MAX / 2; for (i = 0; i < (data * 2); i++) { if ((i % 2) == 0) @@ -8707,7 +9624,12 @@ static int tg3_phys_id(struct net_device *dev, u32 data) tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE | LED_CTRL_TRAFFIC_OVERRIDE); +#if (LINUX_VERSION_CODE < 0x20607) + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout(HZ / 2)) +#else if (msleep_interruptible(500)) +#endif break; } tw32(MAC_LED_CTRL, tp->led_ctrl); @@ -8730,7 +9652,8 @@ static void tg3_get_ethtool_stats (struct net_device *dev, static int tg3_test_nvram(struct tg3 *tp) { - u32 *buf, csum, magic; + u32 csum, magic; + __le32 *buf; int i, j, k, err = 0, size; if (tg3_nvram_read_swab(tp, 0, &magic) != 0) @@ -8767,21 +9690,19 @@ static int tg3_test_nvram(struct tg3 *tp) err = -EIO; for (i = 0, j = 0; i < size; i += 4, j++) { - u32 val; - - if ((err = tg3_nvram_read(tp, i, &val)) != 0) + if ((err = tg3_nvram_read_le(tp, i, &buf[j])) != 0) break; - buf[j] = cpu_to_le32(val); } if (i < size) goto out; /* Selfboot format */ - if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) == + magic = swab32(le32_to_cpu(buf[0])); + if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) { u8 *buf8 = (u8 *) buf, csum8 = 0; - if ((cpu_to_be32(buf[0]) & TG3_EEPROM_SB_REVISION_MASK) == + if ((magic & TG3_EEPROM_SB_REVISION_MASK) == TG3_EEPROM_SB_REVISION_2) { /* For rev 2, the csum doesn't include the MBA. */ for (i = 0; i < TG3_EEPROM_SB_F1R2_MBA_OFF; i++) @@ -8802,7 +9723,7 @@ static int tg3_test_nvram(struct tg3 *tp) goto out; } - if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) == + if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) { u8 data[NVRAM_SELFBOOT_DATA_SIZE]; u8 parity[NVRAM_SELFBOOT_DATA_SIZE]; @@ -8848,12 +9769,12 @@ static int tg3_test_nvram(struct tg3 *tp) /* Bootstrap checksum at offset 0x10 */ csum = calc_crc((unsigned char *) buf, 0x10); - if(csum != cpu_to_le32(buf[0x10/4])) + if(csum != le32_to_cpu(buf[0x10/4])) goto out; /* Manufacturing block starts at offset 0x74, checksum at 0xfc */ csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88); - if (csum != cpu_to_le32(buf[0xfc/4])) + if (csum != le32_to_cpu(buf[0xfc/4])) goto out; err = 0; @@ -8864,7 +9785,7 @@ out: } #define TG3_SERDES_TIMEOUT_SEC 2 -#define TG3_COPPER_TIMEOUT_SEC 6 +#define TG3_COPPER_TIMEOUT_SEC 7 static int tg3_test_link(struct tg3 *tp) { @@ -8882,7 +9803,12 @@ static int tg3_test_link(struct tg3 *tp) if (netif_carrier_ok(tp->dev)) return 0; +#if (LINUX_VERSION_CODE < 0x20607) + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout(HZ)) +#else if (msleep_interruptible(1000)) +#endif break; } @@ -9299,6 +10225,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) tp->tx_prod++; num_pkts++; + /* Some platforms need to sync memory here */ + wmb(); + tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, tp->tx_prod); tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW); @@ -9375,7 +10304,12 @@ static int tg3_test_loopback(struct tg3 *tp) if (err) return TG3_LOOPBACK_FAILED; - if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + /* Turn off gphy autopowerdown. */ + if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) + tg3_phy_toggle_apd(tp, 0); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { int i; u32 status; @@ -9392,7 +10326,7 @@ static int tg3_test_loopback(struct tg3 *tp) if (status != CPMU_MUTEX_GNT_DRIVER) return TG3_LOOPBACK_FAILED; - /* Turn off power management based on link speed. */ + /* Turn off link-based power management. */ cpmuctrl = tr32(TG3_CPMU_CTRL); tw32(TG3_CPMU_CTRL, cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE | @@ -9402,7 +10336,8 @@ static int tg3_test_loopback(struct tg3 *tp) if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) err |= TG3_MAC_LOOPBACK_FAILED; - if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { tw32(TG3_CPMU_CTRL, cpmuctrl); /* Release the mutex */ @@ -9414,6 +10349,10 @@ static int tg3_test_loopback(struct tg3 *tp) err |= TG3_PHY_LOOPBACK_FAILED; } + /* Re-enable gphy autopowerdown. */ + if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) + tg3_phy_toggle_apd(tp, 1); + return err; } @@ -9492,7 +10431,11 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { +#if (LINUX_VERSION_CODE >= 0x020607) struct mii_ioctl_data *data = if_mii(ifr); +#else + struct mii_ioctl_data *data = (struct mii_ioctl_data *) &ifr->ifr_ifru; +#endif struct tg3 *tp = netdev_priv(dev); int err; @@ -9571,8 +10514,7 @@ static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) tg3_netif_stop(tp); tg3_full_lock(tp, 0); - if (tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; + vlan_group_set_device(tp->vlgrp, vid, NULL); tg3_full_unlock(tp); if (netif_running(dev)) @@ -9654,9 +10596,15 @@ static struct ethtool_ops tg3_ethtool_ops = { .set_msglevel = tg3_set_msglevel, .nway_reset = tg3_nway_reset, .get_link = ethtool_op_get_link, +#if (LINUX_VERSION_CODE >= 0x20418) .get_eeprom_len = tg3_get_eeprom_len, +#endif +#ifdef ETHTOOL_GEEPROM .get_eeprom = tg3_get_eeprom, +#endif +#ifdef ETHTOOL_SEEPROM .set_eeprom = tg3_set_eeprom, +#endif .get_ringparam = tg3_get_ringparam, .set_ringparam = tg3_set_ringparam, .get_pauseparam = tg3_get_pauseparam, @@ -9664,20 +10612,33 @@ static struct ethtool_ops tg3_ethtool_ops = { .get_rx_csum = tg3_get_rx_csum, .set_rx_csum = tg3_set_rx_csum, .get_tx_csum = ethtool_op_get_tx_csum, +#ifdef BCM_HAS_SET_TX_CSUM .set_tx_csum = tg3_set_tx_csum, +#endif .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, +#if TG3_TSO_SUPPORT != 0 .get_tso = ethtool_op_get_tso, .set_tso = tg3_set_tso, +#endif +#if (LINUX_VERSION_CODE < 0x20618) .self_test_count = tg3_get_test_count, +#endif .self_test = tg3_self_test, .get_strings = tg3_get_strings, .phys_id = tg3_phys_id, +#if (LINUX_VERSION_CODE < 0x20618) .get_stats_count = tg3_get_stats_count, +#endif .get_ethtool_stats = tg3_get_ethtool_stats, .get_coalesce = tg3_get_coalesce, .set_coalesce = tg3_set_coalesce, +#if (LINUX_VERSION_CODE >= 0x20618) + .get_sset_count = tg3_get_sset_count, +#endif +#if defined(ETHTOOL_GPERMADDR) && (LINUX_VERSION_CODE < 0x020617) .get_perm_addr = ethtool_op_get_perm_addr, +#endif }; static void __devinit tg3_get_eeprom_size(struct tg3 *tp) @@ -9733,7 +10694,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp) return; } } - tp->nvram_size = 0x80000; + tp->nvram_size = TG3_NVRAM_SIZE_512KB; } static void __devinit tg3_get_nvram_info(struct tg3 *tp) @@ -9874,11 +10835,14 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) tp->nvram_pagesize = 264; if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 || nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5) - tp->nvram_size = (protect ? 0x3e200 : 0x80000); + tp->nvram_size = (protect ? 0x3e200 : + TG3_NVRAM_SIZE_512KB); else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2) - tp->nvram_size = (protect ? 0x1f200 : 0x40000); + tp->nvram_size = (protect ? 0x1f200 : + TG3_NVRAM_SIZE_256KB); else - tp->nvram_size = (protect ? 0x1f200 : 0x20000); + tp->nvram_size = (protect ? 0x1f200 : + TG3_NVRAM_SIZE_128KB); break; case FLASH_5752VENDOR_ST_M45PE10: case FLASH_5752VENDOR_ST_M45PE20: @@ -9888,11 +10852,17 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_FLASH; tp->nvram_pagesize = 256; if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10) - tp->nvram_size = (protect ? 0x10000 : 0x20000); + tp->nvram_size = (protect ? + TG3_NVRAM_SIZE_64KB : + TG3_NVRAM_SIZE_128KB); else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20) - tp->nvram_size = (protect ? 0x10000 : 0x40000); + tp->nvram_size = (protect ? + TG3_NVRAM_SIZE_64KB : + TG3_NVRAM_SIZE_256KB); else - tp->nvram_size = (protect ? 0x20000 : 0x80000); + tp->nvram_size = (protect ? + TG3_NVRAM_SIZE_128KB : + TG3_NVRAM_SIZE_512KB); break; } } @@ -9986,25 +10956,25 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) case FLASH_5761VENDOR_ATMEL_MDB161D: case FLASH_5761VENDOR_ST_A_M45PE16: case FLASH_5761VENDOR_ST_M_M45PE16: - tp->nvram_size = 0x100000; + tp->nvram_size = TG3_NVRAM_SIZE_2MB; break; case FLASH_5761VENDOR_ATMEL_ADB081D: case FLASH_5761VENDOR_ATMEL_MDB081D: case FLASH_5761VENDOR_ST_A_M45PE80: case FLASH_5761VENDOR_ST_M_M45PE80: - tp->nvram_size = 0x80000; + tp->nvram_size = TG3_NVRAM_SIZE_1MB; break; case FLASH_5761VENDOR_ATMEL_ADB041D: case FLASH_5761VENDOR_ATMEL_MDB041D: case FLASH_5761VENDOR_ST_A_M45PE40: case FLASH_5761VENDOR_ST_M_M45PE40: - tp->nvram_size = 0x40000; + tp->nvram_size = TG3_NVRAM_SIZE_512KB; break; case FLASH_5761VENDOR_ATMEL_ADB021D: case FLASH_5761VENDOR_ATMEL_MDB021D: case FLASH_5761VENDOR_ST_A_M45PE20: case FLASH_5761VENDOR_ST_M_M45PE20: - tp->nvram_size = 0x20000; + tp->nvram_size = TG3_NVRAM_SIZE_256KB; break; } } @@ -10025,7 +10995,12 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) (EEPROM_DEFAULT_CLOCK_PERIOD << EEPROM_ADDR_CLKPERD_SHIFT))); +#if (LINUX_VERSION_CODE < 0x20607) + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 1000); +#else msleep(1); +#endif /* Enable seeprom accesses. */ tw32_f(GRC_LOCAL_CTRL, @@ -10097,7 +11072,12 @@ static int tg3_nvram_read_using_eeprom(struct tg3 *tp, if (tmp & EEPROM_ADDR_COMPLETE) break; +#if (LINUX_VERSION_CODE < 0x20607) + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 1000); +#else msleep(1); +#endif } if (!(tmp & EEPROM_ADDR_COMPLETE)) return -EBUSY; @@ -10188,6 +11168,15 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) return ret; } +static int tg3_nvram_read_le(struct tg3 *tp, u32 offset, __le32 *val) +{ + u32 v; + int res = tg3_nvram_read(tp, offset, &v); + if (!res) + *val = cpu_to_le32(v); + return res; +} + static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val) { int err; @@ -10205,13 +11194,14 @@ static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, u32 val; for (i = 0; i < len; i += 4) { - u32 addr, data; + u32 addr; + __le32 data; addr = offset + i; memcpy(&data, buf + i, 4); - tw32(GRC_EEPROM_DATA, cpu_to_le32(data)); + tw32(GRC_EEPROM_DATA, le32_to_cpu(data)); val = tr32(GRC_EEPROM_ADDR); tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); @@ -10229,7 +11219,12 @@ static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, if (val & EEPROM_ADDR_COMPLETE) break; +#if (LINUX_VERSION_CODE < 0x20607) + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 1000); +#else msleep(1); +#endif } if (!(val & EEPROM_ADDR_COMPLETE)) { rc = -EBUSY; @@ -10261,8 +11256,8 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, phy_addr = offset & ~pagemask; for (j = 0; j < pagesize; j += 4) { - if ((ret = tg3_nvram_read(tp, phy_addr + j, - (u32 *) (tmp + j)))) + if ((ret = tg3_nvram_read_le(tp, phy_addr + j, + (__le32 *) (tmp + j)))) break; } if (ret) @@ -10306,10 +11301,11 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, break; for (j = 0; j < pagesize; j += 4) { - u32 data; + __be32 data; - data = *((u32 *) (tmp + j)); - tw32(NVRAM_WRDATA, cpu_to_be32(data)); + data = *((__be32 *) (tmp + j)); + /* swab32(le32_to_cpu(data)), actually */ + tw32(NVRAM_WRDATA, be32_to_cpu(data)); tw32(NVRAM_ADDR, phy_addr + j); @@ -10343,10 +11339,11 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, int i, ret = 0; for (i = 0; i < len; i += 4, offset += 4) { - u32 data, page_off, phy_addr, nvram_cmd; + u32 page_off, phy_addr, nvram_cmd; + __be32 data; memcpy(&data, buf + i, 4); - tw32(NVRAM_WRDATA, cpu_to_be32(data)); + tw32(NVRAM_WRDATA, be32_to_cpu(data)); page_off = offset % tp->nvram_pagesize; @@ -10512,7 +11509,12 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr); pmcsr &= ~PCI_PM_CTRL_STATE_MASK; pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr); +#if (LINUX_VERSION_CODE < 0x20607) + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 1000); +#else msleep(1); +#endif /* Make sure register accesses (indirect or otherwise) * will function correctly. @@ -10637,16 +11639,15 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) 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) && tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) tp->led_ctrl = LED_CTRL_MODE_PHY_2; - if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) - tp->led_ctrl = LED_CTRL_MODE_MAC; + if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) + tp->led_ctrl = LED_CTRL_MODE_PHY_1; if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) { tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; @@ -10683,6 +11684,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) if (cfg2 & (1 << 18)) tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && + GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX && + (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN)) + tp->tg3_flags3 |= TG3_FLG3_PHY_ENABLE_APD; + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { u32 cfg3; @@ -10693,6 +11699,55 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) } } +static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd) +{ + int i; + u32 val; + + tw32(OTP_CTRL, cmd | OTP_CTRL_OTP_CMD_START); + tw32(OTP_CTRL, cmd); + + /* Wait for up to 1 ms for command to execute. */ + for (i = 0; i < 100; i++) { + val = tr32(OTP_STATUS); + if (val & OTP_STATUS_CMD_DONE) + break; + udelay(10); + } + + return (val & OTP_STATUS_CMD_DONE) ? 0 : -EBUSY; +} + +/* Read the gphy configuration from the OTP region of the chip. The gphy + * 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) +{ + u32 bhalf_otp, thalf_otp; + + tw32(OTP_MODE, OTP_MODE_OTP_THRU_GRC); + + if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_INIT)) + return 0; + + tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC1); + + if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ)) + return 0; + + thalf_otp = tr32(OTP_READ_DATA); + + tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC2); + + if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ)) + return 0; + + bhalf_otp = tr32(OTP_READ_DATA); + + return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16); +} + static int __devinit tg3_phy_probe(struct tg3 *tp) { u32 hw_phy_id_1, hw_phy_id_2; @@ -10848,6 +11903,7 @@ static void __devinit tg3_read_partno(struct tg3 *tp) vpd_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_VPD); for (i = 0; i < 256; i += 4) { u32 tmp, j = 0; + __le32 v; u16 tmp16; pci_write_config_word(tp->pdev, vpd_cap + PCI_VPD_ADDR, @@ -10857,15 +11913,20 @@ static void __devinit tg3_read_partno(struct tg3 *tp) PCI_VPD_ADDR, &tmp16); if (tmp16 & 0x8000) break; +#if (LINUX_VERSION_CODE < 0x20607) + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); +#else msleep(1); +#endif } if (!(tmp16 & 0x8000)) goto out_not_found; pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA, &tmp); - tmp = cpu_to_le32(tmp); - memcpy(&vpd_data[i], &tmp, 4); + v = cpu_to_le32(tmp); + memcpy(&vpd_data[i], &v, 4); } } @@ -10934,6 +11995,51 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset) return 1; } +static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val) +{ + u32 offset, major, minor, build; + + tp->fw_ver[0] = 's'; + tp->fw_ver[1] = 'b'; + tp->fw_ver[2] = '\0'; + + if ((val & TG3_EEPROM_SB_FORMAT_MASK) != TG3_EEPROM_SB_FORMAT_1) + return; + + switch (val & TG3_EEPROM_SB_REVISION_MASK) { + case TG3_EEPROM_SB_REVISION_0: + offset = TG3_EEPROM_SB_F1R0_EDH_OFF; + break; + case TG3_EEPROM_SB_REVISION_2: + offset = TG3_EEPROM_SB_F1R2_EDH_OFF; + break; + case TG3_EEPROM_SB_REVISION_3: + offset = TG3_EEPROM_SB_F1R3_EDH_OFF; + break; + default: + return; + } + + if (tg3_nvram_read_swab(tp, offset, &val)) + return; + + build = (val & TG3_EEPROM_SB_EDH_BLD_MASK) >> + TG3_EEPROM_SB_EDH_BLD_SHFT; + major = (val & TG3_EEPROM_SB_EDH_MAJ_MASK) >> + TG3_EEPROM_SB_EDH_MAJ_SHFT; + minor = val & TG3_EEPROM_SB_EDH_MIN_MASK; + + if (minor > 99 || build > 26) + return; + + snprintf(&tp->fw_ver[2], 30, " v%d.%02d", major, minor); + + if (build > 0) { + tp->fw_ver[8] = 'a' + build - 1; + tp->fw_ver[9] = '\0'; + } +} + static void __devinit tg3_read_fw_ver(struct tg3 *tp) { u32 val, offset, start; @@ -10943,8 +12049,12 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) if (tg3_nvram_read_swab(tp, 0, &val)) return; - if (val != TG3_EEPROM_MAGIC) + if (val != TG3_EEPROM_MAGIC) { + if ((val & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) + tg3_read_sb_ver(tp, val); + return; + } if (tg3_nvram_read_swab(tp, 0xc, &offset) || tg3_nvram_read_swab(tp, 0x4, &start)) @@ -10958,11 +12068,11 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) offset = offset + ver_offset - start; for (i = 0; i < 16; i += 4) { - if (tg3_nvram_read(tp, offset + i, &val)) + __le32 v; + if (tg3_nvram_read_le(tp, offset + i, &v)) return; - val = le32_to_cpu(val); - memcpy(tp->fw_ver + i, &val, 4); + memcpy(tp->fw_ver + i, &v, 4); } if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || @@ -11000,19 +12110,19 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) tp->fw_ver[bcnt++] = ' '; for (i = 0; i < 4; i++) { - if (tg3_nvram_read(tp, offset, &val)) + __le32 v; + if (tg3_nvram_read_le(tp, offset, &v)) return; - val = le32_to_cpu(val); - offset += sizeof(val); + offset += sizeof(v); - if (bcnt > TG3_VER_SIZE - sizeof(val)) { - memcpy(&tp->fw_ver[bcnt], &val, TG3_VER_SIZE - bcnt); + if (bcnt > TG3_VER_SIZE - sizeof(v)) { + memcpy(&tp->fw_ver[bcnt], &v, TG3_VER_SIZE - bcnt); break; } - memcpy(&tp->fw_ver[bcnt], &val, sizeof(val)); - bcnt += sizeof(val); + memcpy(&tp->fw_ver[bcnt], &v, sizeof(v)); + bcnt += sizeof(v); } tp->fw_ver[TG3_VER_SIZE - 1] = 0; @@ -11022,6 +12132,7 @@ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); static int __devinit tg3_get_invariants(struct tg3 *tp) { +#if (LINUX_VERSION_CODE >= 0x2060a) static struct pci_device_id write_reorder_chipsets[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) }, @@ -11031,12 +12142,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) PCI_DEVICE_ID_VIA_8385_0) }, { }, }; +#endif u32 misc_ctrl_reg; u32 cacheline_sz_reg; u32 pci_state_reg, grc_misc_cfg; u32 val; u16 pci_cmd; - int err, pcie_cap; + int err; /* Force memory write invalidate off. If we leave it on, * then on 5700_BX chips we have to enable a workaround. @@ -11137,6 +12249,38 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { + static struct tg3_dev_id { + u32 vendor; + u32 device; + } bridge_chipsets[] = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0 }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1 }, + { }, + }; + struct tg3_dev_id *pci_id = &bridge_chipsets[0]; + struct pci_dev *bridge = NULL; + + while (pci_id->vendor != 0) { + bridge = pci_get_device(pci_id->vendor, + pci_id->device, + bridge); + if (!bridge) { + pci_id++; + continue; + } + if (bridge->subordinate && + (bridge->subordinate->number <= + tp->pdev->bus->number) && + (bridge->subordinate->subordinate >= + tp->pdev->bus->number)) { + tp->tg3_flags3 |= TG3_FLG3_5701_DMA_BUG; + pci_dev_put(bridge); + break; + } + } + } + /* The EPB bridge inside 5714, 5715, and 5780 cannot support * DMA addresses > 40-bit. This bridge may have other additional * 57xx devices behind it in some 4-port NIC designs for example. @@ -11225,31 +12369,42 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) + if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS) || + (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; - pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP); - if (pcie_cap != 0) { + pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, + &pci_state_reg); + + tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP); + if (tp->pcie_cap != 0) { + u16 lnkctl; + tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; pcie_set_readrq(tp->pdev, 4096); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - u16 lnkctl; - - pci_read_config_word(tp->pdev, - pcie_cap + PCI_EXP_LNKCTL, - &lnkctl); - if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) + pci_read_config_word(tp->pdev, + tp->pcie_cap + PCI_EXP_LNKCTL, + &lnkctl); + if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG; + } + } else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || + (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX); + if (!tp->pcix_cap) { + printk(KERN_ERR PFX "Cannot find PCI-X " + "capability, aborting.\n"); + return -EIO; } + + if (!(pci_state_reg & PCISTATE_CONV_PCI_MODE)) + tp->tg3_flags |= TG3_FLAG_PCIX_MODE; } /* If we have an AMD 762 or VIA K8T800 chipset, write @@ -11258,7 +12413,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * every mailbox register write to force the writes to be * posted to the chip in order. */ +#if (LINUX_VERSION_CODE < 0x2060a) + if ((pci_find_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_FE_GATE_700C, NULL) || + pci_find_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_8131_BRIDGE, NULL) || + pci_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_8385_0, NULL)) && +#else if (pci_dev_present(write_reorder_chipsets) && +#endif !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; @@ -11275,29 +12439,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) cacheline_sz_reg); } - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || - (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { - tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX); - if (!tp->pcix_cap) { - printk(KERN_ERR PFX "Cannot find PCI-X " - "capability, aborting.\n"); - return -EIO; - } - } - - pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, - &pci_state_reg); - - if (tp->pcix_cap && (pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) { - tp->tg3_flags |= TG3_FLAG_PCIX_MODE; + if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) { + /* 5700 BX chips need to have their TX producer index + * mailboxes written twice to workaround a bug. + */ + tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG; - /* If this is a 5700 BX chipset, and we are in PCI-X - * mode, enable register write workaround. + /* If we are in PCI-X mode, enable register write workaround. * * The workaround is to use indirect register accesses * for all chip writes not to mailbox registers. */ - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) { + if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { u32 pm_reg; tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; @@ -11322,12 +12475,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - /* 5700 BX chips need to have their TX producer index mailboxes - * written twice to workaround a bug. - */ - if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) - tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG; - if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0) tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED; if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0) @@ -11421,16 +12568,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; - if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 || - tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5761_A1) - tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES; - } - /* Set up tp->grc_local_ctrl before calling tg3_set_power_state(). * GPIO1 driven high will bring 5700's external PHY out of reset. * It is also used as eeprom write protect on LOMs. @@ -11449,6 +12589,15 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + /* Turn off the debug UART. */ + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + if (tp->tg3_flags2 & TG3_FLG2_IS_NIC) + /* Keep VMain power. */ + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OUTPUT0; + } + /* Force the chip into D0. */ err = tg3_set_power_state(tp, PCI_D0); if (err) { @@ -11509,6 +12658,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_PHY_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) { + tp->phy_otp = tg3_read_otp_phycfg(tp); + if (tp->phy_otp == 0) + tp->phy_otp = TG3_OTP_DEFAULT; + } + + if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) + tp->mi_mode = MAC_MI_MODE_500KHZ_CONST; + else + 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) @@ -11577,6 +12738,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->misc_host_ctrl); } + /* Preserve the APE MAC_MODE bits */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + tp->mac_mode = tr32(MAC_MODE) | + MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; + else + tp->mac_mode = TG3_DEF_MAC_MODE; + /* 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)) || @@ -11649,10 +12817,15 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug; - tp->rx_offset = 2; + tp->rx_offset = NET_IP_ALIGN + VLAN_HLEN; + tp->rx_copy_thresh = RX_COPY_THRESHOLD; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) - tp->rx_offset = 0; + (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) { + tp->rx_offset -= NET_IP_ALIGN; +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + tp->rx_copy_thresh = ~(u16)0; +#endif + } tp->rx_std_max_post = TG3_RX_RING_SIZE; @@ -11764,13 +12937,15 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) } if (!is_valid_ether_addr(&dev->dev_addr[0])) { -#ifdef CONFIG_SPARC64 +#ifdef CONFIG_SPARC if (!tg3_get_default_macaddr_sparc(tp)) return 0; #endif return -EINVAL; } +#ifdef ETHTOOL_GPERMADDR memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); +#endif return 0; } @@ -11846,7 +13021,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX | DMA_RWCTRL_WRITE_BNDRY_384_PCIX); break; - }; + } } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { switch (cacheline_size) { case 16: @@ -11863,7 +13038,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE; val |= DMA_RWCTRL_WRITE_BNDRY_128_PCIE; break; - }; + } } else { switch (cacheline_size) { case 16: @@ -11907,7 +13082,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) val |= (DMA_RWCTRL_READ_BNDRY_1024 | DMA_RWCTRL_WRITE_BNDRY_1024); break; - }; + } } out: @@ -12157,17 +13332,25 @@ static int __devinit tg3_test_dma(struct tg3 *tp) } if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) != DMA_RWCTRL_WRITE_BNDRY_16) { +#if (LINUX_VERSION_CODE >= 0x2060a) static struct pci_device_id dma_wait_state_chipsets[] = { { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_PCI15) }, { }, }; +#endif /* DMA test passed without adjusting DMA boundary, * now look for chipsets that are known to expose the * DMA bug without failing the test. */ - if (pci_dev_present(dma_wait_state_chipsets)) { +#if (LINUX_VERSION_CODE < 0x2060a) + if (pci_find_device(PCI_VENDOR_ID_APPLE, + PCI_DEVICE_ID_APPLE_UNI_N_PCI15, NULL)) +#else + if (pci_dev_present(dma_wait_state_chipsets)) +#endif + { tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK; tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16; } @@ -12267,7 +13450,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; - }; + } } static char * __devinit tg3_bus_string(struct tg3 *tp, char *str) @@ -12369,12 +13552,13 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int tg3_version_printed = 0; - unsigned long tg3reg_base, tg3reg_len; + unsigned long tg3reg_len; struct net_device *dev; struct tg3 *tp; - int i, err, pm_cap; + int err, pm_cap; char str[40]; u64 dma_mask, persist_dma_mask; + DECLARE_MAC_BUF(mac); if (tg3_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -12411,9 +13595,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_free_res; } - tg3reg_base = pci_resource_start(pdev, 0); - tg3reg_len = pci_resource_len(pdev, 0); - dev = alloc_etherdev(sizeof(*tp)); if (!dev) { printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); @@ -12422,7 +13603,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, } SET_MODULE_OWNER(dev); +#if (LINUX_VERSION_CODE >= 0x20419) SET_NETDEV_DEV(dev, &pdev->dev); +#endif #if TG3_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; @@ -12434,10 +13617,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->pdev = pdev; tp->dev = dev; tp->pm_cap = pm_cap; - tp->mac_mode = TG3_DEF_MAC_MODE; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; - tp->mi_mode = MAC_MI_MODE_BASE; + if (tg3_debug > 0) tp->msg_enable = tg3_debug; else @@ -12466,9 +13648,17 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, #endif spin_lock_init(&tp->lock); spin_lock_init(&tp->indirect_lock); +#if defined(INIT_DELAYED_WORK_DEFERRABLE) || defined(INIT_WORK_NAR) + INIT_WORK(&tp->reset_task, tg3_reset_task); +#else INIT_WORK(&tp->reset_task, tg3_reset_task, tp); +#endif + + dev->mem_start = pci_resource_start(pdev, 0); + tg3reg_len = pci_resource_len(pdev, 0); + dev->mem_end = dev->mem_start + tg3reg_len; - tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len); + tp->regs = ioremap_nocache(dev->mem_start, tg3reg_len); if (!tp->regs) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); @@ -12489,13 +13679,17 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, dev->set_mac_address = tg3_set_mac_addr; dev->do_ioctl = tg3_ioctl; dev->tx_timeout = tg3_tx_timeout; +#ifdef TG3_NAPI + netif_napi_add(dev, &tp->napi, tg3_poll, 64); +#else dev->poll = tg3_poll; - dev->ethtool_ops = &tg3_ethtool_ops; dev->weight = 64; +#endif + dev->ethtool_ops = &tg3_ethtool_ops; dev->watchdog_timeo = TG3_TX_TIMEOUT; dev->change_mtu = tg3_change_mtu; dev->irq = pdev->irq; -#ifdef CONFIG_NET_POLL_CONTROLLER +#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) dev->poll_controller = tg3_poll_controller; #endif @@ -12547,6 +13741,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_bufmgr_config(tp); +#if TG3_TSO_SUPPORT != 0 if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; } @@ -12569,10 +13764,13 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) dev->features |= NETIF_F_TSO6; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + if (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)) dev->features |= NETIF_F_TSO_ECN; } +#endif if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && @@ -12589,6 +13787,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, } if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + resource_size_t tg3reg_base; + if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { printk(KERN_ERR PFX "Cannot find proper PCI device " "base address for APE, aborting.\n"); @@ -12600,7 +13800,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3reg_len = pci_resource_len(pdev, 2); tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len); - if (tp->aperegs == 0UL) { + if (!tp->aperegs) { printk(KERN_ERR PFX "Cannot map APE registers, " "aborting.\n"); err = -ENOMEM; @@ -12631,6 +13831,14 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * checksumming. */ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { +#ifdef NETIF_F_IPV6_CSUM + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + dev->features |= NETIF_F_IPV6_CSUM; +#else 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 || @@ -12639,12 +13847,14 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, else dev->features |= NETIF_F_IP_CSUM; dev->features |= NETIF_F_SG; +#endif tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; } else tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; /* flow control autonegotiation is default behavior */ tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; + tp->link_config.flowctrl = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; tg3_init_coal(tp); @@ -12657,7 +13867,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_apeunmap; } - printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ", + printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] " + "(%s) %s Ethernet %s\n", dev->name, tp->board_part_number, tp->pci_chip_rev_id, @@ -12665,11 +13876,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_bus_string(tp, str), ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" : ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" : - "10/100/1000Base-T"))); - - for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i], - i == 5 ? '\n' : ':'); + "10/100/1000Base-T")), + print_mac(mac, dev->dev_addr)); printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] " "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n", @@ -12700,7 +13908,11 @@ err_out_iounmap: } err_out_free_dev: +#if (LINUX_VERSION_CODE >= 0x20418) free_netdev(dev); +#else + kfree(dev); +#endif err_out_free_res: pci_release_regions(pdev); @@ -12718,7 +13930,9 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) if (dev) { struct tg3 *tp = netdev_priv(dev); +#if (LINUX_VERSION_CODE >= 0x20600) flush_scheduled_work(); +#endif unregister_netdev(dev); if (tp->aperegs) { iounmap(tp->aperegs); @@ -12728,14 +13942,22 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) iounmap(tp->regs); tp->regs = NULL; } +#if (LINUX_VERSION_CODE >= 0x20418) free_netdev(dev); +#else + kfree(dev); +#endif pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } } +#if (LINUX_VERSION_CODE < 0x2060b) +static int tg3_suspend(struct pci_dev *pdev, u32 state) +#else static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) +#endif { struct net_device *dev = pci_get_drvdata(pdev); struct tg3 *tp = netdev_priv(dev); @@ -12745,12 +13967,18 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) * MSI address and data need to be saved if using MSI and * netif_running(). */ +#if (LINUX_VERSION_CODE < 0x2060a) + pci_save_state(pdev, tp->pci_cfg_state); +#else pci_save_state(pdev); +#endif if (!netif_running(dev)) return 0; +#if (LINUX_VERSION_CODE >= 0x20600) flush_scheduled_work(); +#endif tg3_netif_stop(tp); del_timer_sync(&tp->timer); @@ -12766,7 +13994,11 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; tg3_full_unlock(tp); +#if (LINUX_VERSION_CODE < 0x2060b) + err = tg3_set_power_state(tp, state); +#else err = tg3_set_power_state(tp, pci_choose_state(pdev, state)); +#endif if (err) { tg3_full_lock(tp, 0); @@ -12793,7 +14025,11 @@ static int tg3_resume(struct pci_dev *pdev) struct tg3 *tp = netdev_priv(dev); int err; +#if (LINUX_VERSION_CODE < 0x2060a) + pci_restore_state(tp->pdev, tp->pci_cfg_state); +#else pci_restore_state(tp->pdev); +#endif if (!netif_running(dev)) return 0; @@ -12802,10 +14038,16 @@ static int tg3_resume(struct pci_dev *pdev) if (err) return err; +#ifndef BCM_HAS_INTX_MSI_WORKAROUND /* Hardware bug - MSI won't work if INTX disabled. */ if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) && (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) +#if (LINUX_VERSION_CODE < 0x2060e) + tg3_enable_intx(tp->pdev); +#else pci_intx(tp->pdev, 1); +#endif +#endif netif_device_attach(dev); @@ -12838,7 +14080,11 @@ static struct pci_driver tg3_driver = { static int __init tg3_init(void) { +#if (LINUX_VERSION_CODE < 0x020613) return pci_module_init(&tg3_driver); +#else + return pci_register_driver(&tg3_driver); +#endif } static void __exit tg3_cleanup(void) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c654142a..26232cba 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -9,6 +9,423 @@ #ifndef _T3_H #define _T3_H +#if !defined(PCI_DEVICE_ID_TIGON3_5704S_2) +#define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5705F) +#define PCI_DEVICE_ID_TIGON3_5705F 0x166e +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5720) +#define PCI_DEVICE_ID_TIGON3_5720 0x1658 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5721) +#define PCI_DEVICE_ID_TIGON3_5721 0x1659 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5750) +#define PCI_DEVICE_ID_TIGON3_5750 0x1676 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5751) +#define PCI_DEVICE_ID_TIGON3_5751 0x1677 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5750M) +#define PCI_DEVICE_ID_TIGON3_5750M 0x167c +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5751M) +#define PCI_DEVICE_ID_TIGON3_5751M 0x167d +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5751F) +#define PCI_DEVICE_ID_TIGON3_5751F 0x167e +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5789) +#define PCI_DEVICE_ID_TIGON3_5789 0x169d +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5753) +#define PCI_DEVICE_ID_TIGON3_5753 0x16f7 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5753M) +#define PCI_DEVICE_ID_TIGON3_5753M 0x16fd +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5753F) +#define PCI_DEVICE_ID_TIGON3_5753F 0x16fe +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5781) +#define PCI_DEVICE_ID_TIGON3_5781 0x16dd +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5752) +#define PCI_DEVICE_ID_TIGON3_5752 0x1600 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5752M) +#define PCI_DEVICE_ID_TIGON3_5752M 0x1601 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5714) +#define PCI_DEVICE_ID_TIGON3_5714 0x1668 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5714S) +#define PCI_DEVICE_ID_TIGON3_5714S 0x1669 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5780) +#define PCI_DEVICE_ID_TIGON3_5780 0x166a +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5780S) +#define PCI_DEVICE_ID_TIGON3_5780S 0x166b +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5715) +#define PCI_DEVICE_ID_TIGON3_5715 0x1678 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5715S) +#define PCI_DEVICE_ID_TIGON3_5715S 0x1679 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5756) +#define PCI_DEVICE_ID_TIGON3_5756 0x1674 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5754) +#define PCI_DEVICE_ID_TIGON3_5754 0x167a +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5754M) +#define PCI_DEVICE_ID_TIGON3_5754M 0x1672 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5755) +#define PCI_DEVICE_ID_TIGON3_5755 0x167b +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5755M) +#define PCI_DEVICE_ID_TIGON3_5755M 0x1673 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5722) +#define PCI_DEVICE_ID_TIGON3_5722 0x165a +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5786) +#define PCI_DEVICE_ID_TIGON3_5786 0x169a +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5787M) +#define PCI_DEVICE_ID_TIGON3_5787M 0x1693 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5787) +#define PCI_DEVICE_ID_TIGON3_5787 0x169b +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5787F) +#define PCI_DEVICE_ID_TIGON3_5787F 0x167f +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5906) +#define PCI_DEVICE_ID_TIGON3_5906 0x1712 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5906M) +#define PCI_DEVICE_ID_TIGON3_5906M 0x1713 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5784) +#define PCI_DEVICE_ID_TIGON3_5784 0x1698 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5764) +#define PCI_DEVICE_ID_TIGON3_5764 0x1684 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5723) +#define PCI_DEVICE_ID_TIGON3_5723 0x165b +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5761) +#define PCI_DEVICE_ID_TIGON3_5761 0x1681 +#endif + +#if !defined(PCI_DEVICE_ID_TIGON3_5761E) +#define PCI_DEVICE_ID_TIGON3_5761E 0x1680 +#endif + +#define PCI_DEVICE_ID_TIGON3_5761S 0x1688 +#define PCI_DEVICE_ID_TIGON3_5761SE 0x1689 + +#if !defined(PCI_DEVICE_ID_APPLE_TIGON3) +#define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 +#endif + +#if !defined(PCI_DEVICE_ID_APPLE_UNI_N_PCI15) +#define PCI_DEVICE_ID_APPLE_UNI_N_PCI15 0x002e +#endif + +#if !defined(PCI_DEVICE_ID_VIA_8385_0) +#define PCI_DEVICE_ID_VIA_8385_0 0x3188 +#endif + +#if !defined(PCI_DEVICE_ID_AMD_8131_BRIDGE) +#define PCI_DEVICE_ID_AMD_8131_BRIDGE 0x7450 +#endif + +#if !defined(PCI_DEVICE_ID_SERVERWORKS_EPB) +#define PCI_DEVICE_ID_SERVERWORKS_EPB 0x0103 +#endif + +#if !defined(PCI_VENDOR_ID_ARIMA) +#define PCI_VENDOR_ID_ARIMA 0x161f +#endif + +#ifndef PCI_DEVICE +#define PCI_DEVICE(vend,dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID +#endif + +#if !defined(PCI_VPD_ADDR) +#define PCI_VPD_ADDR 2 +#define PCI_VPD_DATA 4 +#endif + +#ifndef NETDEV_TX_OK +#define NETDEV_TX_OK 0 +#endif + +#ifndef NETDEV_TX_BUSY +#define NETDEV_TX_BUSY 1 +#endif + +#ifndef NETDEV_TX_LOCKED +#define NETDEV_TX_LOCKED -1 +#endif + +#include "tg3_compat.h" + +#ifndef CHECKSUM_PARTIAL +#define CHECKSUM_PARTIAL CHECKSUM_HW +#endif + +#ifndef DMA_64BIT_MASK +#define DMA_64BIT_MASK ((u64) 0xffffffffffffffffULL) +#define DMA_32BIT_MASK ((u64) 0x00000000ffffffffULL) +#endif + +#ifndef DMA_40BIT_MASK +#define DMA_40BIT_MASK ((u64) 0x000000ffffffffffULL) +#endif + +#ifndef mmiowb +#define mmiowb() +#endif + +#ifndef PCI_D0 +typedef u32 pm_message_t; +typedef u32 pci_power_t; +#define PCI_D0 0 +#define PCI_D1 1 +#define PCI_D2 2 +#define PCI_D3hot 3 +#endif + +#ifndef WARN_ON +#define WARN_ON(x) +#endif + +#ifndef IRQ_RETVAL +typedef void irqreturn_t; +#define IRQ_RETVAL(x) +#define IRQ_HANDLED +#define IRQ_NONE +#endif + +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif + +#ifndef IRQF_SAMPLE_RANDOM +#define IRQF_SAMPLE_RANDOM SA_SAMPLE_RANDOM +#endif + +#if (LINUX_VERSION_CODE < 0x020604) +#define MODULE_VERSION(version) +#endif + +#if (LINUX_VERSION_CODE <= 0x020600) +#define schedule_work(x) schedule_task(x) +#define work_struct tq_struct +#define INIT_WORK(x, y, z) INIT_TQUEUE(x, y, z) +#endif + +#ifndef ADVERTISE_PAUSE +#define ADVERTISE_PAUSE_CAP 0x0400 +#endif +#ifndef ADVERTISE_PAUSE_ASYM +#define ADVERTISE_PAUSE_ASYM 0x0800 +#endif +#ifndef LPA_PAUSE +#define LPA_PAUSE_CAP 0x0400 +#endif +#ifndef LPA_PAUSE_ASYM +#define LPA_PAUSE_ASYM 0x0800 +#endif +#ifndef MII_CTRL1000 +#define MII_CTRL1000 0x9 +#endif +#ifndef MII_STAT1000 +#define MII_STAT1000 0xa +#endif +#ifndef BMCR_SPEED1000 +#define BMCR_SPEED1000 0x40 +#endif +#ifndef ADVERTISE_1000FULL +#define ADVERTISE_1000FULL 0x0200 +#define ADVERTISE_1000HALF 0x0100 +#endif +#ifndef ADVERTISE_1000XFULL +#define ADVERTISE_1000XFULL 0x20 +#define ADVERTISE_1000XHALF 0x40 +#define ADVERTISE_1000XPAUSE 0x80 +#define ADVERTISE_1000XPSE_ASYM 0x100 +#define LPA_1000XFULL 0x20 +#define LPA_1000XHALF 0x40 +#define LPA_1000XPAUSE 0x80 +#define LPA_1000XPAUSE_ASYM 0x100 +#endif + +#if (LINUX_VERSION_CODE >= 0x020618) +#define TG3_NAPI +#endif + +#if (LINUX_VERSION_CODE < 0x020420) +#define ETH_SS_TEST 0 +#define ETH_SS_STATS 1 +#endif + +#if (LINUX_VERSION_CODE < 0x020605) +#define pci_dma_sync_single_for_cpu(pdev, map, len, dir) \ + pci_dma_sync_single(pdev, map, len, dir) + +#define pci_dma_sync_single_for_device(pdev, map, len, dir) +#endif + +#if (LINUX_VERSION_CODE < 0x020600) +#define pci_get_device(x, y, z) pci_find_device(x, y, z) +#define pci_get_slot(x, y) pci_find_slot((x)->number, y) +#define pci_dev_put(x) +#endif + +#if (LINUX_VERSION_CODE < 0x020547) +#define pci_set_consistent_dma_mask(pdev, mask) (0) +#endif + +#if (LINUX_VERSION_CODE < 0x020612) +static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev, + unsigned int length) +{ + struct sk_buff *skb = dev_alloc_skb(length); + if (skb) + skb->dev = dev; + return skb; +} +#endif + +#ifndef NETIF_F_GSO +static inline void netif_tx_lock(struct net_device *dev) +{ + spin_lock(&dev->xmit_lock); + dev->xmit_lock_owner = smp_processor_id(); +} + +static inline void netif_tx_unlock(struct net_device *dev) +{ + dev->xmit_lock_owner = -1; + spin_unlock(&dev->xmit_lock); +} +#endif + +#if !defined(HAVE_NETDEV_PRIV) && (LINUX_VERSION_CODE != 0x020603) && (LINUX_VERSION_CODE != 0x020604) && (LINUX_VERSION_CODE != 0x20605) +static inline void *netdev_priv(struct net_device *dev) +{ + return dev->priv; +} +#endif + +#ifdef OLD_NETIF +static inline void netif_poll_disable(struct net_device *dev) +{ + while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) { + /* No hurry. */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } +} + +static inline void netif_poll_enable(struct net_device *dev) +{ + clear_bit(__LINK_STATE_RX_SCHED, &dev->state); +} + +static inline void netif_tx_disable(struct net_device *dev) +{ + spin_lock_bh(&dev->xmit_lock); + netif_stop_queue(dev); + spin_unlock_bh(&dev->xmit_lock); +} + +#endif + +#if (LINUX_VERSION_CODE < 0x2060c) +static inline int skb_header_cloned(struct sk_buff *skb) { return 0; } +#endif + +#ifndef VLAN_GROUP_ARRAY_SPLIT_PARTS +static inline void vlan_group_set_device(struct vlan_group *vg, int vlan_id, + struct net_device *dev) +{ + if (vg) + vg->vlan_devices[vlan_id] = dev; +} +#endif +#if (LINUX_VERSION_CODE < 0x2060e) +static inline void tg3_enable_intx(struct pci_dev *pdev) +{ + u16 pci_command; + + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + if (pci_command & PCI_COMMAND_INTX_DISABLE) + pci_write_config_word(pdev, PCI_COMMAND, + pci_command & ~PCI_COMMAND_INTX_DISABLE); +} +#endif + +#ifndef SET_MODULE_OWNER +#define SET_MODULE_OWNER(dev) do { } while (0) +#endif + +#ifndef NETIF_F_LLTX +#define NETIF_F_LLTX 0 +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + #define TG3_64BIT_REG_HIGH 0x00UL #define TG3_64BIT_REG_LOW 0x04UL @@ -22,7 +439,7 @@ #define TG3_BDINFO_NIC_ADDR 0xcUL /* 32-bit */ #define TG3_BDINFO_SIZE 0x10UL -#define RX_COPY_THRESHOLD 256 +#define RX_COPY_THRESHOLD 256 #define TG3_RX_INTERNAL_RING_SZ_5906 32 @@ -57,6 +474,9 @@ #define TG3PCI_IRQ_PIN 0x0000003d #define TG3PCI_MIN_GNT 0x0000003e #define TG3PCI_MAX_LAT 0x0000003f +#ifndef PCI_X_CMD_READ_2K +#define PCI_X_CMD_READ_2K 0x0008 +#endif /* 0x40 --> 0x64 unused */ #define TG3PCI_MSI_DATA 0x00000064 /* 0x66 --> 0x68 unused */ @@ -108,10 +528,6 @@ #define CHIPREV_ID_5752_A1 0x6001 #define CHIPREV_ID_5714_A2 0x9002 #define CHIPREV_ID_5906_A1 0xc001 -#define CHIPREV_ID_5784_A0 0x5784000 -#define CHIPREV_ID_5784_A1 0x5784001 -#define CHIPREV_ID_5761_A0 0x5761000 -#define CHIPREV_ID_5761_A1 0x5761001 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 @@ -138,6 +554,8 @@ #define CHIPREV_5704_BX 0x21 #define CHIPREV_5750_AX 0x40 #define CHIPREV_5750_BX 0x41 +#define CHIPREV_5784_AX 0x57840 +#define CHIPREV_5761_AX 0x57610 #define GET_METAL_REV(CHIP_REV_ID) ((CHIP_REV_ID) & 0xff) #define METAL_REV_A0 0x00 #define METAL_REV_A1 0x01 @@ -322,6 +740,9 @@ #define MAC_MODE_TDE_ENABLE 0x00200000 #define MAC_MODE_RDE_ENABLE 0x00400000 #define MAC_MODE_FHDE_ENABLE 0x00800000 +#define MAC_MODE_KEEP_FRAME_IN_WOL 0x01000000 +#define MAC_MODE_APE_RX_EN 0x08000000 +#define MAC_MODE_APE_TX_EN 0x10000000 #define MAC_STATUS 0x00000404 #define MAC_STATUS_PCS_SYNCED 0x00000001 #define MAC_STATUS_SIGNAL_DET 0x00000002 @@ -413,7 +834,7 @@ #define MAC_MI_MODE_CLK_10MHZ 0x00000001 #define MAC_MI_MODE_SHORT_PREAMBLE 0x00000002 #define MAC_MI_MODE_AUTO_POLL 0x00000010 -#define MAC_MI_MODE_CORE_CLK_62MHZ 0x00008000 +#define MAC_MI_MODE_500KHZ_CONST 0x00008000 #define MAC_MI_MODE_BASE 0x000c0000 /* XXX magic values XXX */ #define MAC_AUTO_POLL_STATUS 0x00000458 #define MAC_AUTO_POLL_ERROR 0x00000001 @@ -545,6 +966,8 @@ #define SG_DIG_FIBER_MODE 0x00008000 #define SG_DIG_REMOTE_FAULT_MASK 0x00006000 #define SG_DIG_PAUSE_MASK 0x00001800 +#define SG_DIG_PAUSE_CAP 0x00000800 +#define SG_DIG_ASYM_PAUSE 0x00001000 #define SG_DIG_GBIC_ENABLE 0x00000400 #define SG_DIG_CHECK_END_ENABLE 0x00000200 #define SG_DIG_SGMII_AUTONEG_TIMER 0x00000100 @@ -556,6 +979,11 @@ #define SG_DIG_AUTONEG_LOW_ENABLE 0x00000004 #define SG_DIG_REMOTE_LOOPBACK 0x00000002 #define SG_DIG_LOOPBACK 0x00000001 +#define SG_DIG_COMMON_SETUP (SG_DIG_CRC16_CLEAR_N | \ + SG_DIG_LOCAL_DUPLEX_STATUS | \ + SG_DIG_LOCAL_LINK_STATUS | \ + (0x2 << SG_DIG_SPEED_STATUS_SHIFT) | \ + SG_DIG_FIBER_MODE | SG_DIG_GBIC_ENABLE) #define SG_DIG_STATUS 0x000005b4 #define SG_DIG_CRC16_BUS_MASK 0xffff0000 #define SG_DIG_PARTNER_FAULT_MASK 0x00600000 /* If !MRADV_CRC16_SELECT */ @@ -859,6 +1287,7 @@ #define CPMU_CTRL_LINK_IDLE_MODE 0x00000200 #define CPMU_CTRL_LINK_AWARE_MODE 0x00000400 #define CPMU_CTRL_LINK_SPEED_MODE 0x00004000 +#define CPMU_CTRL_GPHY_10MB_RXONLY 0x00010000 #define TG3_CPMU_LSPD_10MB_CLK 0x00003604 #define CPMU_LSPD_10MB_MACCLK_MASK 0x001f0000 #define CPMU_LSPD_10MB_MACCLK_6_25 0x00130000 @@ -866,6 +1295,7 @@ #define TG3_CPMU_LSPD_1000MB_CLK 0x0000360c #define CPMU_LSPD_1000MB_MACCLK_62_5 0x00000000 +#define CPMU_LSPD_1000MB_MACCLK_30_0 0x00030000 #define CPMU_LSPD_1000MB_MACCLK_12_5 0x00110000 #define CPMU_LSPD_1000MB_MACCLK_MASK 0x001f0000 #define TG3_CPMU_LNK_AWARE_PWRMD 0x00003610 @@ -1099,6 +1529,7 @@ #define WDMAC_MODE_FIFOOREAD_ENAB 0x00000100 #define WDMAC_MODE_LNGREAD_ENAB 0x00000200 #define WDMAC_MODE_RX_ACCEL 0x00000400 +#define WDMAC_MODE_STATUS_TAG_FIX 0x20000000 #define WDMAC_STATUS 0x00004c04 #define WDMAC_STATUS_TGTABORT 0x00000004 #define WDMAC_STATUS_MSTABORT 0x00000008 @@ -1383,6 +1814,8 @@ #define GRC_MISC_CFG_BOARD_ID_5788 0x00010000 #define GRC_MISC_CFG_BOARD_ID_5788M 0x00018000 #define GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000 +#define GRC_MISC_CFG_BOARD_ID_5754 0x00008000 +#define GRC_MISC_CFG_BOARD_ID_5754M 0x0000c000 #define GRC_MISC_CFG_EPHY_IDDQ 0x00200000 #define GRC_MISC_CFG_KEEP_GPHY_POWER 0x04000000 #define GRC_LOCAL_CTRL 0x00006808 @@ -1419,6 +1852,7 @@ #define GRC_LCLCTRL_AUTO_SEEPROM 0x01000000 #define GRC_TIMER 0x0000680c #define GRC_RX_CPU_EVENT 0x00006810 +#define GRC_RX_CPU_DRIVER_EVENT 0x00004000 #define GRC_RX_TIMER_REF 0x00006814 #define GRC_RX_CPU_SEM 0x00006818 #define GRC_REMOTE_RX_CPU_ATTN 0x0000681c @@ -1552,7 +1986,24 @@ /* 0x702c unused */ #define NVRAM_ADDR_LOCKOUT 0x00007030 -/* 0x7034 --> 0x7c00 unused */ +/* 0x7034 --> 0x7500 unused */ + +#define OTP_MODE 0x00007500 +#define OTP_MODE_OTP_THRU_GRC 0x00000001 +#define OTP_CTRL 0x00007504 +#define OTP_CTRL_OTP_PROG_ENABLE 0x00200000 +#define OTP_CTRL_OTP_CMD_READ 0x00000000 +#define OTP_CTRL_OTP_CMD_INIT 0x00000008 +#define OTP_CTRL_OTP_CMD_START 0x00000001 +#define OTP_STATUS 0x00007508 +#define OTP_STATUS_CMD_DONE 0x00000001 +#define OTP_ADDRESS 0x0000750c +#define OTP_ADDRESS_MAGIC1 0x000000a0 +#define OTP_ADDRESS_MAGIC2 0x00000080 +/* 0x7510 unused */ + +#define OTP_READ_DATA 0x00007514 +/* 0x7518 --> 0x7c04 unused */ #define PCIE_TRANSACTION_CFG 0x00007c04 #define PCIE_TRANS_CFG_1SHOT_MSI 0x20000000 @@ -1561,6 +2012,28 @@ #define PCIE_PWR_MGMT_THRESH 0x00007d28 #define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00 + +/* OTP bit definitions */ +#define TG3_OTP_AGCTGT_MASK 0x000000e0 +#define TG3_OTP_AGCTGT_SHIFT 1 +#define TG3_OTP_HPFFLTR_MASK 0x00000300 +#define TG3_OTP_HPFFLTR_SHIFT 1 +#define TG3_OTP_HPFOVER_MASK 0x00000400 +#define TG3_OTP_HPFOVER_SHIFT 1 +#define TG3_OTP_LPFDIS_MASK 0x00000800 +#define TG3_OTP_LPFDIS_SHIFT 11 +#define TG3_OTP_VDAC_MASK 0xff000000 +#define TG3_OTP_VDAC_SHIFT 24 +#define TG3_OTP_10BTAMP_MASK 0x0000f000 +#define TG3_OTP_10BTAMP_SHIFT 8 +#define TG3_OTP_ROFF_MASK 0x00e00000 +#define TG3_OTP_ROFF_SHIFT 11 +#define TG3_OTP_RCOFF_MASK 0x001c0000 +#define TG3_OTP_RCOFF_SHIFT 16 + +#define TG3_OTP_DEFAULT 0x286c1640 + + #define TG3_EEPROM_MAGIC 0x669955aa #define TG3_EEPROM_MAGIC_FW 0xa5000000 #define TG3_EEPROM_MAGIC_FW_MSK 0xff000000 @@ -1579,6 +2052,17 @@ #define TG3_NVM_DIRTYPE_SHIFT 24 #define TG3_NVM_DIRTYPE_ASFINI 1 +#define TG3_EEPROM_SB_F1R0_EDH_OFF 0x10 +#define TG3_EEPROM_SB_F1R2_EDH_OFF 0x14 +#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10 +#define TG3_EEPROM_SB_F1R3_EDH_OFF 0x18 +#define TG3_EEPROM_SB_EDH_MAJ_MASK 0x00000700 +#define TG3_EEPROM_SB_EDH_MAJ_SHFT 8 +#define TG3_EEPROM_SB_EDH_MIN_MASK 0x000000ff +#define TG3_EEPROM_SB_EDH_BLD_MASK 0x0000f800 +#define TG3_EEPROM_SB_EDH_BLD_SHFT 11 + + /* 32K Window into NIC internal memory */ #define NIC_SRAM_WIN_BASE 0x00008000 @@ -1627,6 +2111,7 @@ #define FWCMD_NICDRV_IPV6ADDR_CHG 0x00000004 #define FWCMD_NICDRV_FIX_DMAR 0x00000005 #define FWCMD_NICDRV_FIX_DMAW 0x00000006 +#define FWCMD_NICDRV_LINK_UPDATE 0x0000000c #define FWCMD_NICDRV_ALIVE2 0x0000000d #define FWCMD_NICDRV_ALIVE3 0x0000000e #define NIC_SRAM_FW_CMD_LEN_MBOX 0x00000b7c @@ -1653,6 +2138,7 @@ #define NIC_SRAM_DATA_CFG_2 0x00000d38 +#define NIC_SRAM_DATA_CFG_2_APD_EN 0x00000400 #define SHASTA_EXT_LED_MODE_MASK 0x00018000 #define SHASTA_EXT_LED_LEGACY 0x00000000 #define SHASTA_EXT_LED_SHARED 0x00008000 @@ -1698,15 +2184,31 @@ #define MII_TG3_DSP_RW_PORT 0x15 /* DSP coefficient read/write port */ -#define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */ #define MII_TG3_EPHY_PTEST 0x17 /* 5906 PHY register */ +#define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */ + +#define MII_TG3_DSP_TAP1 0x0001 +#define MII_TG3_DSP_TAP1_AGCTGT_DFLT 0x0007 +#define MII_TG3_DSP_AADJ1CH0 0x001f +#define MII_TG3_DSP_AADJ1CH3 0x601f +#define MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002 +#define MII_TG3_DSP_EXP8 0x0708 +#define MII_TG3_DSP_EXP8_REJ2MHz 0x0001 +#define MII_TG3_DSP_EXP8_AEDW 0x0200 +#define MII_TG3_DSP_EXP75 0x0f75 +#define MII_TG3_DSP_EXP96 0x0f96 +#define MII_TG3_DSP_EXP97 0x0f97 #define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */ #define MII_TG3_AUXCTL_MISC_WREN 0x8000 #define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200 #define MII_TG3_AUXCTL_MISC_RDSEL_MISC 0x7000 -#define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007 +#define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007 + +#define MII_TG3_AUXCTL_ACTL_SMDSP_ENA 0x0800 +#define MII_TG3_AUXCTL_ACTL_TX_6DB 0x0400 +#define MII_TG3_AUXCTL_SHDWSEL_AUXCTL 0x0000 #define MII_TG3_AUX_STAT 0x19 /* auxilliary status register */ #define MII_TG3_AUX_STAT_LPASS 0x0004 @@ -1724,18 +2226,26 @@ #define MII_TG3_ISTAT 0x1a /* IRQ status register */ #define MII_TG3_IMASK 0x1b /* IRQ mask register */ -#define MII_TG3_MISC_SHDW 0x1c -#define MII_TG3_MISC_SHDW_WREN 0x8000 -#define MII_TG3_MISC_SHDW_APD_SEL 0x2800 - -#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001 - /* ISTAT/IMASK event bits */ #define MII_TG3_INT_LINKCHG 0x0002 #define MII_TG3_INT_SPEEDCHG 0x0004 #define MII_TG3_INT_DUPLEXCHG 0x0008 #define MII_TG3_INT_ANEG_PAGE_RX 0x0400 +#define MII_TG3_MISC_SHDW 0x1c +#define MII_TG3_MISC_SHDW_WREN 0x8000 +#define MII_TG3_MISC_SHDW_SCR5_SEL 0x1400 +#define MII_TG3_MISC_SHDW_APD_SEL 0x2800 + +#define MII_TG3_MISC_SHDW_SCR5_C125OE 0x0001 +#define MII_TG3_MISC_SHDW_SCR5_DLLAPD 0x0002 +#define MII_TG3_MISC_SHDW_SCR5_SDTL 0x0004 +#define MII_TG3_MISC_SHDW_SCR5_DLPTLM 0x0008 +#define MII_TG3_MISC_SHDW_SCR5_LPED 0x0010 + +#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001 +#define MII_TG3_MISC_SHDW_APD_ENABLE 0x0020 + #define MII_TG3_EPHY_TEST 0x1f /* 5906 PHY register */ #define MII_TG3_EPHY_SHADOW_EN 0x80 @@ -1784,9 +2294,9 @@ #define APE_EVENT_STATUS_EVENT_PENDING 0x80000000 /* APE convenience enumerations. */ +#define TG3_APE_LOCK_GRC 1 #define TG3_APE_LOCK_MEM 4 -#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10 /* There are two ways to manage the TX descriptors on the tigon3. @@ -1942,35 +2452,35 @@ struct tg3_internal_buffer_desc { #define TG3_HW_STATUS_SIZE 0x50 struct tg3_hw_status { - u32 status; + volatile u32 status; #define SD_STATUS_UPDATED 0x00000001 #define SD_STATUS_LINK_CHG 0x00000002 #define SD_STATUS_ERROR 0x00000004 - u32 status_tag; + volatile u32 status_tag; #ifdef __BIG_ENDIAN - u16 rx_consumer; - u16 rx_jumbo_consumer; + volatile u16 rx_consumer; + volatile u16 rx_jumbo_consumer; #else - u16 rx_jumbo_consumer; - u16 rx_consumer; + volatile u16 rx_jumbo_consumer; + volatile u16 rx_consumer; #endif #ifdef __BIG_ENDIAN - u16 reserved; - u16 rx_mini_consumer; + volatile u16 reserved; + volatile u16 rx_mini_consumer; #else - u16 rx_mini_consumer; - u16 reserved; + volatile u16 rx_mini_consumer; + volatile u16 reserved; #endif struct { #ifdef __BIG_ENDIAN - u16 tx_consumer; - u16 rx_producer; + volatile u16 tx_consumer; + volatile u16 rx_producer; #else - u16 rx_producer; - u16 tx_consumer; + volatile u16 rx_producer; + volatile u16 tx_consumer; #endif } idx[16]; }; @@ -2103,13 +2613,18 @@ struct tg3_link_config { u16 speed; u8 duplex; u8 autoneg; + u8 flowctrl; +#define TG3_FLOW_CTRL_TX 0x01 +#define TG3_FLOW_CTRL_RX 0x02 /* Describes what we actually have. */ - u16 active_speed; + u8 active_flowctrl; + u8 active_duplex; #define SPEED_INVALID 0xffff #define DUPLEX_INVALID 0xff #define AUTONEG_INVALID 0xff + u16 active_speed; /* When we go in and out of low power mode we need * to swap with this state. @@ -2286,6 +2801,9 @@ struct tg3 { dma_addr_t tx_desc_mapping; /* begin "rx thread" cacheline section */ +#ifdef TG3_NAPI + struct napi_struct napi; +#endif void (*write32_rx_mbox) (struct tg3 *, u32, u32); u32 rx_rcb_ptr; @@ -2317,11 +2835,13 @@ struct tg3 { struct tg3_ethtool_stats estats; struct tg3_ethtool_stats estats_prev; + union { unsigned long phy_crc_errors; + unsigned long last_event_jiffies; + }; - u32 rx_offset; - /* RHEL5 only */ - u32 tg3_dist_flags; + u16 rx_offset; + u16 rx_copy_thresh; u32 tg3_flags; #define TG3_FLAG_TAGGED_STATUS 0x00000001 #define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 @@ -2338,8 +2858,6 @@ struct tg3 { #define TG3_FLAG_EEPROM_WRITE_PROT 0x00001000 #define TG3_FLAG_NVRAM 0x00002000 #define TG3_FLAG_NVRAM_BUFFERED 0x00004000 -#define TG3_FLAG_RX_PAUSE 0x00008000 -#define TG3_FLAG_TX_PAUSE 0x00010000 #define TG3_FLAG_PCIX_MODE 0x00020000 #define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 #define TG3_FLAG_PCI_32BIT 0x00080000 @@ -2350,7 +2868,6 @@ struct tg3 { #define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 #define TG3_FLAG_CPMU_PRESENT 0x04000000 -#define TG3_FLAG_IN_RESET_TASK 0x04000000 #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_SUPPORT_MSI 0x20000000 @@ -2395,7 +2912,9 @@ struct tg3 { u32 tg3_flags3; #define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001 #define TG3_FLG3_ENABLE_APE 0x00000002 -#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004 +#define TG3_FLG3_PHY_ENABLE_APD 0x00000004 +#define TG3_FLG3_5701_DMA_BUG 0x00000008 +#define TG3_FLG3_CLKREQ_BUG 0x00000010 struct timer_list timer; u16 timer_counter; @@ -2431,10 +2950,16 @@ struct tg3 { u8 pci_lat_timer; u8 pci_hdr_type; u8 pci_bist; +#if (LINUX_VERSION_CODE < 0x2060a) + u32 pci_cfg_state[64 / sizeof(u32)]; +#endif int pm_cap; int msi_cap; + union { int pcix_cap; + int pcie_cap; + }; /* PHY info */ u32 phy_id; @@ -2465,6 +2990,7 @@ struct tg3 { #define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */ u32 led_ctrl; + u32 phy_otp; u16 pci_cmd; char board_part_number[24]; @@ -2494,6 +3020,13 @@ struct tg3 { int nvram_lock_cnt; u32 nvram_size; +#define TG3_NVRAM_SIZE_64KB 0x00010000 +#define TG3_NVRAM_SIZE_128KB 0x00020000 +#define TG3_NVRAM_SIZE_256KB 0x00040000 +#define TG3_NVRAM_SIZE_512KB 0x00080000 +#define TG3_NVRAM_SIZE_1MB 0x00100000 +#define TG3_NVRAM_SIZE_2MB 0x00200000 + u32 nvram_pagesize; u32 nvram_jedecnum; @@ -2502,10 +3035,10 @@ struct tg3 { #define JEDEC_SAIFUN 0x4f #define JEDEC_SST 0xbf -#define ATMEL_AT24C64_CHIP_SIZE (64 * 1024) +#define ATMEL_AT24C64_CHIP_SIZE TG3_NVRAM_SIZE_64KB #define ATMEL_AT24C64_PAGE_SIZE (32) -#define ATMEL_AT24C512_CHIP_SIZE (512 * 1024) +#define ATMEL_AT24C512_CHIP_SIZE TG3_NVRAM_SIZE_512KB #define ATMEL_AT24C512_PAGE_SIZE (128) #define ATMEL_AT45DB0X1B_PAGE_POS 9 diff --git a/drivers/net/tg3_compat.h b/drivers/net/tg3_compat.h index 8070e6cf..78f4c7f9 100644 --- a/drivers/net/tg3_compat.h +++ b/drivers/net/tg3_compat.h @@ -1,12 +1,204 @@ -#ifndef __TG3_COMPAT_H__ -#define __TG3_COMPAT_H__ +#include "tg3_flags.h" + +#if !defined(__maybe_unused) +#define __maybe_unused /* unimplemented */ +#endif + +#if !defined(__iomem) +#define __iomem +#endif + +#ifndef __acquires +#define __acquires(x) +#endif + +#ifndef __releases +#define __releases(x) +#endif + +#ifndef PCI_DEVICE_ID_INTEL_PXH_0 +#define PCI_DEVICE_ID_INTEL_PXH_0 0x0329 +#endif + +#ifndef PCI_DEVICE_ID_INTEL_PXH_1 +#define PCI_DEVICE_ID_INTEL_PXH_1 0x032A +#endif + +#ifndef BCM_HAS_BOOL +typedef int bool; +#define false 0 +#define true 1 +#endif + +#ifndef BCM_HAS_LE32 +typedef u32 __le32; +typedef u32 __be32; +#endif + +#ifndef BCM_HAS_RESOURCE_SIZE_T +typedef unsigned long resource_size_t; +#endif + +#ifndef BCM_HAS_KZALLOC +static inline void *kzalloc(size_t size, int flags) +{ + void * memptr = kmalloc(size, flags); + if (memptr) + memset(memptr, 0, size); + + return memptr; +} +#endif + +#ifndef BCM_HAS_USECS_TO_JIFFIES +unsigned long usecs_to_jiffies(const unsigned int u) +{ + if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET)) + return MAX_JIFFY_OFFSET; +#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) + return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ); +#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC) + return u * (HZ / USEC_PER_SEC); +#else + return (USEC_TO_HZ_MUL32 * u + USEC_TO_HZ_ADJ32) + >> USEC_TO_HZ_SHR32; +#endif +} +#endif + +#ifndef BCM_HAS_SKB_COPY_FROM_LINEAR_DATA +static inline void skb_copy_from_linear_data(const struct sk_buff *skb, + void *to, + const unsigned int len) +{ + memcpy(to, skb->data, len); +} +#endif + +#ifndef PCI_CAP_ID_EXP +#define PCI_CAP_ID_EXP 0x10 +#endif +#ifndef PCI_EXP_LNKCTL +#define PCI_EXP_LNKCTL 16 +#endif +#ifndef PCI_EXP_LNKCTL_CLKREQ_EN +#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 +#endif + +#ifndef BCM_HAS_PCIE_SET_READRQ +#ifndef PCI_EXP_DEVCTL +#define PCI_EXP_DEVCTL 8 +#endif +#ifndef PCI_EXP_DEVCTL_READRQ +#define PCI_EXP_DEVCTL_READRQ 0x7000 +#endif +static inline int pcie_set_readrq(struct pci_dev *dev, int rq) +{ + int cap, err = -EINVAL; + u16 ctl, v; + + if (rq < 128 || rq > 4096 || (rq & (rq-1))) + goto out; + + v = (ffs(rq) - 8) << 12; + + cap = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!cap) + goto out; + + err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); + if (err) + goto out; + + if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) { + ctl &= ~PCI_EXP_DEVCTL_READRQ; + ctl |= v; + err = pci_write_config_dword(dev, cap + PCI_EXP_DEVCTL, ctl); + } + +out: + return err; +} +#endif /* BCM_HAS_PCIE_SET_READRQ */ + +#ifndef ETH_FCS_LEN +#define ETH_FCS_LEN 4 +#endif + +#ifndef BCM_HAS_PRINT_MAC +#define DECLARE_MAC_BUF(_mac) char _mac[18] + +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" + +static char *print_mac(char * buf, const u8 *addr) +{ + sprintf(buf, MAC_FMT, + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + return buf; +} +#endif -#define PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */ -#define TG3_DIST_FLAG_IN_RESET_TASK 0x00000001 +#if !defined(BCM_HAS_ETHTOOL_OP_SET_TX_IPV6_CSUM) && \ + !defined(BCM_HAS_ETHTOOL_OP_SET_TX_HW_CSUM) && \ + defined(BCM_HAS_SET_TX_CSUM) +static int tg3_set_tx_hw_csum(struct net_device *dev, u32 data) +{ + if (data) + dev->features |= NETIF_F_HW_CSUM; + else + dev->features &= ~NETIF_F_HW_CSUM; -#define PCI_DEVICE(vend,dev) \ - .vendor = (vend), .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID + return 0; +} +#endif + + +#ifdef NETIF_F_TSO +#ifndef NETIF_F_GSO +#define gso_size tso_size +#define gso_segs tso_segs +#endif +#ifndef NETIF_F_TSO6 +#define NETIF_F_TSO6 0 +#define BCM_NO_TSO6 1 +#endif +#ifndef NETIF_F_TSO_ECN +#define NETIF_F_TSO_ECN 0 +#endif + +#ifndef BCM_HAS_SKB_TRANSPORT_OFFSET +static inline int skb_transport_offset(const struct sk_buff *skb) +{ + return (int) (skb->h.raw - skb->data); +} +#endif +#ifndef BCM_HAS_IP_HDR +static inline struct iphdr *ip_hdr(const struct sk_buff *skb) +{ + return skb->nh.iph; +} +#endif + +#ifndef BCM_HAS_IP_HDRLEN +static inline unsigned int ip_hdrlen(const struct sk_buff *skb) +{ + return ip_hdr(skb)->ihl * 4; +} +#endif + +#ifndef BCM_HAS_TCP_HDR +static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb) +{ + return skb->h.th; +} +#endif + +#ifndef BCM_HAS_TCP_OPTLEN +static inline unsigned int tcp_optlen(const struct sk_buff *skb) +{ + return (tcp_hdr(skb)->doff - 5) * 4; +} +#endif #endif diff --git a/drivers/net/tg3_flags.h b/drivers/net/tg3_flags.h new file mode 100644 index 00000000..349e0dae --- /dev/null +++ b/drivers/net/tg3_flags.h @@ -0,0 +1,14 @@ +#define BCM_HAS_BOOL +#define BCM_HAS_LE32 +#define BCM_HAS_RESOURCE_SIZE_T +#define BCM_HAS_KZALLOC +#define BCM_HAS_USECS_TO_JIFFIES +#define BCM_HAS_SKB_COPY_FROM_LINEAR_DATA +#define BCM_HAS_PCIE_SET_READRQ +#define BCM_HAS_ETHTOOL_OP_SET_TX_HW_CSUM +#define BCM_HAS_SET_TX_CSUM +#define BCM_HAS_SKB_TRANSPORT_OFFSET +#define BCM_HAS_IP_HDR +#define BCM_HAS_IP_HDRLEN +#define BCM_HAS_TCP_HDR +#define BCM_HAS_TCP_OPTLEN