X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Ftg3.c;h=b5931a0c766420c5efc97212abf349004fcedc97;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=1a26b11fb39a53f9f6b095d5ff4e4886acf880b6;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 1a26b11fb..b5931a0c7 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12,7 +12,7 @@ #include #include - +#include #include #include #include @@ -60,8 +60,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.10" -#define DRV_MODULE_RELDATE "September 14, 2004" +#define DRV_MODULE_VERSION "3.23" +#define DRV_MODULE_RELDATE "February 15, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -141,10 +141,11 @@ static char version[] __devinitdata = MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)"); MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(tg3_debug, "i"); -MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); +MODULE_VERSION(DRV_MODULE_VERSION); static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ +module_param(tg3_debug, int, 0); +MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); static struct pci_device_id tg3_pci_tbl[] = { { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700, @@ -205,6 +206,14 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, @@ -224,8 +233,8 @@ static struct pci_device_id tg3_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, tg3_pci_tbl); -struct { - char string[ETH_GSTRING_LEN]; +static struct { + const char string[ETH_GSTRING_LEN]; } ethtool_stats_keys[TG3_NUM_STATS] = { { "rx_octets" }, { "rx_fragments" }, @@ -417,6 +426,20 @@ static void tg3_enable_ints(struct tg3 *tp) tg3_cond_int(tp); } +/* tg3_restart_ints + * similar to tg3_enable_ints, but it can return without flushing the + * PIO write which reenables interrupts + */ +static void tg3_restart_ints(struct tg3 *tp) +{ + tw32(TG3PCI_MISC_HOST_CTRL, + (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000); + mmiowb(); + + tg3_cond_int(tp); +} + static inline void tg3_netif_stop(struct tg3 *tp) { netif_poll_disable(tp->dev); @@ -470,7 +493,8 @@ static void tg3_switch_clocks(struct tg3 *tp) static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) { u32 frame_val; - int loops, ret; + unsigned int loops; + int ret; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, @@ -478,7 +502,7 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) udelay(80); } - *val = 0xffffffff; + *val = 0x0; frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & MI_COM_PHY_ADDR_MASK); @@ -489,7 +513,7 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; - while (loops-- > 0) { + while (loops != 0) { udelay(10); frame_val = tr32(MAC_MI_COM); @@ -498,10 +522,11 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) frame_val = tr32(MAC_MI_COM); break; } + loops -= 1; } ret = -EBUSY; - if (loops > 0) { + if (loops != 0) { *val = frame_val & MI_COM_DATA_MASK; ret = 0; } @@ -517,7 +542,8 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val) static int tg3_writephy(struct tg3 *tp, int reg, u32 val) { u32 frame_val; - int loops, ret; + unsigned int loops; + int ret; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { tw32_f(MAC_MI_MODE, @@ -535,7 +561,7 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; - while (loops-- > 0) { + while (loops != 0) { udelay(10); frame_val = tr32(MAC_MI_COM); if ((frame_val & MI_COM_BUSY) == 0) { @@ -543,10 +569,11 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) frame_val = tr32(MAC_MI_COM); break; } + loops -= 1; } ret = -EBUSY; - if (loops > 0) + if (loops != 0) ret = 0; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { @@ -564,9 +591,10 @@ static void tg3_phy_set_wirespeed(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) return; - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007); - tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); - tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); + if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007) && + !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val)) + tg3_writephy(tp, MII_TG3_AUX_CTRL, + (val | (1 << 15) | (1 << 4))); } static int tg3_bmcr_reset(struct tg3 *tp) @@ -607,9 +635,10 @@ static int tg3_wait_macro_done(struct tg3 *tp) while (limit--) { u32 tmp32; - tg3_readphy(tp, 0x16, &tmp32); - if ((tmp32 & 0x1000) == 0) - break; + if (!tg3_readphy(tp, 0x16, &tmp32)) { + if ((tmp32 & 0x1000) == 0) + break; + } } if (limit <= 0) return -EBUSY; @@ -661,9 +690,9 @@ static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp) for (i = 0; i < 6; i += 2) { u32 low, high; - tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low); - tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high); - if (tg3_wait_macro_done(tp)) { + if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) || + tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) || + tg3_wait_macro_done(tp)) { *resetp = 1; return -EBUSY; } @@ -719,7 +748,9 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) } /* Disable transmitter and interrupt. */ - tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); + if (tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) + continue; + reg32 |= 0x3000; tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); @@ -728,7 +759,9 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) BMCR_FULLDPLX | TG3_BMCR_SPEED1000); /* Set to master mode. */ - tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig); + if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig)) + continue; + tg3_writephy(tp, MII_TG3_CTRL, (MII_TG3_CTRL_AS_MASTER | MII_TG3_CTRL_ENABLE_AS_MASTER)); @@ -766,9 +799,11 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); - tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); - reg32 &= ~0x3000; - tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); + if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) { + reg32 &= ~0x3000; + tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); + } else if (!err) + err = -EBUSY; return err; } @@ -832,9 +867,9 @@ out: u32 phy_reg; /* Set bit 14 with read-modify-write to preserve other bits */ - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007); - tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg); - tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000); + if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007) && + !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg)) + tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000); } tg3_phy_set_wirespeed(tp); return 0; @@ -866,34 +901,42 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT1)); udelay(100); } else { + u32 no_gpio2; + u32 grc_local_ctrl; + if (tp_peer != tp && (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) return; + /* On 5753 and variants, GPIO2 cannot be used. */ + no_gpio2 = tp->nic_sram_data_cfg & + NIC_SRAM_DATA_CFG_NO_GPIO2; + + grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + GRC_LCLCTRL_GPIO_OUTPUT2; + if (no_gpio2) { + grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT2); + } tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); + grc_local_ctrl); udelay(100); - tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); - udelay(100); + grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0; tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1)); + grc_local_ctrl); udelay(100); + + if (!no_gpio2) { + grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2; + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + grc_local_ctrl); + udelay(100); + } } } else { if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && @@ -1209,7 +1252,7 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 }; } -static int tg3_phy_copper_begin(struct tg3 *tp) +static void tg3_phy_copper_begin(struct tg3 *tp) { u32 new_adv; int i; @@ -1324,15 +1367,16 @@ static int tg3_phy_copper_begin(struct tg3 *tp) if (tp->link_config.duplex == DUPLEX_FULL) bmcr |= BMCR_FULLDPLX; - tg3_readphy(tp, MII_BMCR, &orig_bmcr); - if (bmcr != orig_bmcr) { + if (!tg3_readphy(tp, MII_BMCR, &orig_bmcr) && + (bmcr != orig_bmcr)) { tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK); for (i = 0; i < 1500; i++) { u32 tmp; udelay(10); - tg3_readphy(tp, MII_BMSR, &tmp); - tg3_readphy(tp, MII_BMSR, &tmp); + if (tg3_readphy(tp, MII_BMSR, &tmp) || + tg3_readphy(tp, MII_BMSR, &tmp)) + continue; if (!(tmp & BMSR_LSTATUS)) { udelay(40); break; @@ -1345,8 +1389,6 @@ static int tg3_phy_copper_begin(struct tg3 *tp) tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); } - - return 0; } static int tg3_init_5401phy_dsp(struct tg3 *tp) @@ -1381,7 +1423,9 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp) { u32 adv_reg, all_mask; - tg3_readphy(tp, MII_ADVERTISE, &adv_reg); + if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg)) + return 0; + all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL); if ((adv_reg & all_mask) != all_mask) @@ -1389,7 +1433,9 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp) if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) { u32 tg3_ctrl; - tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl); + if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl)) + return 0; + all_mask = (MII_TG3_CTRL_ADV_1000_HALF | MII_TG3_CTRL_ADV_1000_FULL); if ((tg3_ctrl & all_mask) != all_mask) @@ -1429,8 +1475,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && netif_carrier_ok(tp->dev)) { tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - if (!(bmsr & BMSR_LSTATUS)) + if (!tg3_readphy(tp, MII_BMSR, &bmsr) && + !(bmsr & BMSR_LSTATUS)) force_reset = 1; } if (force_reset) @@ -1438,9 +1484,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) + if (tg3_readphy(tp, MII_BMSR, &bmsr) || + !(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) bmsr = 0; if (!(bmsr & BMSR_LSTATUS)) { @@ -1451,8 +1496,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) tg3_readphy(tp, MII_BMSR, &bmsr); for (i = 0; i < 1000; i++) { udelay(10); - tg3_readphy(tp, MII_BMSR, &bmsr); - if (bmsr & BMSR_LSTATUS) { + if (!tg3_readphy(tp, MII_BMSR, &bmsr) && + (bmsr & BMSR_LSTATUS)) { udelay(40); break; } @@ -1514,8 +1559,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) bmsr = 0; for (i = 0; i < 100; i++) { tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - if (bmsr & BMSR_LSTATUS) + if (!tg3_readphy(tp, MII_BMSR, &bmsr) && + (bmsr & BMSR_LSTATUS)) break; udelay(40); } @@ -1526,8 +1571,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); for (i = 0; i < 2000; i++) { udelay(10); - tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); - if (aux_stat) + if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) && + aux_stat) break; } @@ -1538,7 +1583,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) bmcr = 0; for (i = 0; i < 200; i++) { tg3_readphy(tp, MII_BMCR, &bmcr); - tg3_readphy(tp, MII_BMCR, &bmcr); + if (tg3_readphy(tp, MII_BMCR, &bmcr)) + continue; if (bmcr && bmcr != 0x7fff) break; udelay(10); @@ -1575,10 +1621,13 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) (tp->link_config.autoneg == AUTONEG_ENABLE)) { u32 local_adv, remote_adv; - tg3_readphy(tp, MII_ADVERTISE, &local_adv); + if (tg3_readphy(tp, MII_ADVERTISE, &local_adv)) + local_adv = 0; local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - tg3_readphy(tp, MII_LPA, &remote_adv); + 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, @@ -1597,8 +1646,8 @@ relink: tg3_phy_copper_begin(tp); tg3_readphy(tp, MII_BMSR, &tmp); - tg3_readphy(tp, MII_BMSR, &tmp); - if (tmp & BMSR_LSTATUS) + if (!tg3_readphy(tp, MII_BMSR, &tmp) && + (tmp & BMSR_LSTATUS)) current_link_up = 1; } @@ -2099,8 +2148,9 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) port_a = 0; - serdes_cfg = tr32(MAC_SERDES_CFG) & - ((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20)); + /* preserve bits 0-11,13,14 for signal pre-emphasis */ + /* preserve bits 20-23 for voltage regulator */ + serdes_cfg = tr32(MAC_SERDES_CFG) & 0x00f06fff; } sg_dig_ctrl = tr32(SG_DIG_CTRL); @@ -2111,9 +2161,9 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) u32 val = serdes_cfg; if (port_a) - val |= 0xc010880; + val |= 0xc010000; else - val |= 0x4010880; + val |= 0x4010000; tw32_f(MAC_SERDES_CFG, val); } tw32_f(SG_DIG_CTRL, 0x01388400); @@ -2136,7 +2186,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) if (sg_dig_ctrl != expected_sg_dig_ctrl) { if (workaround) - tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011880); + tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000); tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30)); udelay(5); tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl); @@ -2144,7 +2194,16 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; } else if (mac_status & (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DET)) { - sg_dig_status = tr32(SG_DIG_STATUS); + int i; + + /* Giver time to negotiate (~200ms) */ + for (i = 0; i < 40000; i++) { + sg_dig_status = tr32(SG_DIG_STATUS); + if (sg_dig_status & (0x3)) + break; + udelay(5); + } + mac_status = tr32(MAC_STATUS); if ((sg_dig_status & (1 << 1)) && (mac_status & MAC_STATUS_PCS_SYNCED)) { @@ -2168,9 +2227,9 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) u32 val = serdes_cfg; if (port_a) - val |= 0xc010880; + val |= 0xc010000; else - val |= 0x4010880; + val |= 0x4010000; tw32_f(MAC_SERDES_CFG, val); } @@ -2178,8 +2237,12 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) tw32_f(SG_DIG_CTRL, 0x01388400); udelay(40); + /* Link parallel detection - link is up */ + /* only if we have PCS_SYNC and not */ + /* receiving config code words */ mac_status = tr32(MAC_STATUS); - if (mac_status & MAC_STATUS_PCS_SYNCED) { + if ((mac_status & MAC_STATUS_PCS_SYNCED) && + !(mac_status & MAC_STATUS_RCVD_CFG)) { tg3_setup_flow_control(tp, 0, 0); current_link_up = 1; } @@ -2650,7 +2713,11 @@ static int tg3_rx(struct tg3 *tp, int budget) len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */ - if (len > RX_COPY_THRESHOLD) { + if (len > RX_COPY_THRESHOLD + && tp->rx_offset == 2 + /* rx_offset != 2 iff this is a 5701 card running + * in PCI-X mode [see tg3_get_invariants()] */ + ) { int skb_size; skb_size = tg3_alloc_rx_skb(tp, opaque_key, @@ -2729,6 +2796,7 @@ next_pkt_nopost: tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, sw_idx); } + mmiowb(); return received; } @@ -2787,7 +2855,7 @@ static int tg3_poll(struct net_device *netdev, int *budget) if (done) { spin_lock_irqsave(&tp->lock, flags); __netif_rx_complete(netdev); - tg3_enable_ints(tp); + tg3_restart_ints(tp); spin_unlock_irqrestore(&tp->lock, flags); } @@ -3050,11 +3118,19 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->nh.iph->check = 0; skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len); - skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, - skb->nh.iph->daddr, - 0, IPPROTO_TCP, 0); + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { + skb->h.th->check = 0; + base_flags &= ~TXD_FLAG_TCPUDP_CSUM; + } + else { + skb->h.th->check = + ~csum_tcpudp_magic(skb->nh.iph->saddr, + skb->nh.iph->daddr, + 0, IPPROTO_TCP, 0); + } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) { if (tcp_opt_len || skb->nh.iph->ihl > 5) { int tsflags; @@ -3121,7 +3197,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) would_hit_hwbug = entry + 1; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) tg3_set_txd(tp, entry, mapping, len, base_flags, (i == last)|(mss << 1)); else @@ -3176,6 +3252,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); out_unlock: + mmiowb(); spin_unlock_irqrestore(&tp->tx_lock, flags); dev->trans_start = jiffies; @@ -3788,7 +3865,7 @@ static int tg3_chip_reset(struct tg3 *tp) val |= PCISTATE_RETRY_SAME_DMA; pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); - pci_restore_state(tp->pdev, tp->pci_cfg_state); + pci_restore_state(tp->pdev); /* Make sure PCI-X relaxed ordering bit is clear. */ pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); @@ -4504,7 +4581,7 @@ static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000, }; -u32 tg3TsoFwRodata[] = { +static u32 tg3TsoFwRodata[] = { 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f, 0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, @@ -4512,7 +4589,7 @@ u32 tg3TsoFwRodata[] = { 0x00000000, }; -u32 tg3TsoFwData[] = { +static u32 tg3TsoFwData[] = { 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -4693,14 +4770,14 @@ static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { 0x00000000, 0x00000000, 0x00000000, }; -u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { +static u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000, 0x00000000, }; -u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { +static u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }; @@ -4712,7 +4789,7 @@ static int tg3_load_tso_firmware(struct tg3 *tp) unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; int err, i; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) return 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { @@ -4796,9 +4873,8 @@ static void __tg3_set_mac_addr(struct tg3 *tp) tw32(MAC_ADDR_0_LOW + (i * 8), addr_low); } - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { for (i = 0; i < 12; i++) { tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high); tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low); @@ -4844,7 +4920,8 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS), maxlen_flags); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) + if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)) tg3_write_mem(tp, (bdinfo_addr + TG3_BDINFO_NIC_ADDR), nic_addr); @@ -5146,7 +5223,7 @@ static int tg3_reset_hw(struct tg3 *tp) } #if TG3_TSO_SUPPORT != 0 - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) rdmac_mode |= (1 << 27); #endif @@ -5296,7 +5373,7 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ); tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); #if TG3_TSO_SUPPORT != 0 - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) + 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); @@ -5346,8 +5423,10 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(10); if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) && + !(tp->tg3_flags2 & TG3_FLG2_SERDES_PREEMPHASIS)) { /* Set drive transmission level to 1.2V */ + /* only if the signal pre-emphasis bit is not set */ val = tr32(MAC_SERDES_CFG); val &= 0xfffff000; val |= 0x880; @@ -5376,9 +5455,10 @@ static int tg3_reset_hw(struct tg3 *tp) u32 tmp; /* Clear CRC stats. */ - tg3_readphy(tp, 0x1e, &tmp); - tg3_writephy(tp, 0x1e, tmp | 0x8000); - tg3_readphy(tp, 0x14, &tmp); + if (!tg3_readphy(tp, 0x1e, &tmp)) { + tg3_writephy(tp, 0x1e, tmp | 0x8000); + tg3_readphy(tp, 0x14, &tmp); + } } __tg3_set_rx_mode(tp->dev); @@ -5968,9 +6048,11 @@ static unsigned long calc_crc_errors(struct tg3 *tp) u32 val; spin_lock_irqsave(&tp->lock, flags); - tg3_readphy(tp, 0x1e, &val); - tg3_writephy(tp, 0x1e, val | 0x8000); - tg3_readphy(tp, 0x14, &val); + if (!tg3_readphy(tp, 0x1e, &val)) { + tg3_writephy(tp, 0x1e, val | 0x8000); + tg3_readphy(tp, 0x14, &val); + } else + val = 0; spin_unlock_irqrestore(&tp->lock, flags); tp->phy_crc_errors += val; @@ -6316,14 +6398,16 @@ do { p = (u32 *)(orig_p + (reg)); \ static int tg3_get_eeprom_len(struct net_device *dev) { - return EEPROM_CHIP_SIZE; + struct tg3 *tp = netdev_priv(dev); + + return tp->nvram_size; } -static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp, - u32 offset, u32 *val); +static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val); + static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); int ret; u8 *pd; u32 i, offset, len, val, b_offset, b_count; @@ -6332,10 +6416,7 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, len = eeprom->len; eeprom->len = 0; - ret = tg3_nvram_read_using_eeprom(tp, 0, &eeprom->magic); - if (ret) - return ret; - eeprom->magic = swab32(eeprom->magic); + eeprom->magic = TG3_EEPROM_MAGIC; if (offset & 3) { /* adjustments to start on required 4 byte boundary */ @@ -6345,9 +6426,10 @@ 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_using_eeprom(tp, offset-b_offset, &val); + ret = tg3_nvram_read(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; @@ -6357,12 +6439,13 @@ 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_using_eeprom(tp, offset + i, - (u32*)(pd + i)); + ret = tg3_nvram_read(tp, offset + i, &val); if (ret) { eeprom->len += i; return ret; } + val = cpu_to_le32(val); + memcpy(pd + i, &val, 4); } eeprom->len += i; @@ -6371,15 +6454,72 @@ 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_using_eeprom(tp, b_offset, &val); + ret = tg3_nvram_read(tp, b_offset, &val); if (ret) return ret; + val = cpu_to_le32(val); memcpy(pd, ((char*)&val), b_count); eeprom->len += b_count; } return 0; } +static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); + +static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) +{ + struct tg3 *tp = netdev_priv(dev); + int ret; + u32 offset, len, b_offset, odd_len, start, end; + u8 *buf; + + if (eeprom->magic != TG3_EEPROM_MAGIC) + return -EINVAL; + + offset = eeprom->offset; + len = eeprom->len; + + if ((b_offset = (offset & 3))) { + /* adjustments to start on required 4 byte boundary */ + ret = tg3_nvram_read(tp, offset-b_offset, &start); + if (ret) + return ret; + start = cpu_to_le32(start); + len += b_offset; + offset &= ~3; + } + + odd_len = 0; + if ((len & 3) && ((len > 4) || (b_offset == 0))) { + /* adjustments to end on required 4 byte boundary */ + odd_len = 1; + len = (len + 3) & ~3; + ret = tg3_nvram_read(tp, offset+len-4, &end); + if (ret) + return ret; + end = cpu_to_le32(end); + } + + buf = data; + if (b_offset || odd_len) { + buf = kmalloc(len, GFP_KERNEL); + if (buf == 0) + return -ENOMEM; + if (b_offset) + memcpy(buf, &start, 4); + if (odd_len) + memcpy(buf+len-4, &end, 4); + memcpy(buf + b_offset, data, eeprom->len); + } + + ret = tg3_nvram_write_block(tp, offset, len, buf); + + if (buf != data) + kfree(buf); + + return ret; +} + static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct tg3 *tp = netdev_priv(dev); @@ -6528,10 +6668,10 @@ static int tg3_nway_reset(struct net_device *dev) int r; spin_lock_irq(&tp->lock); - tg3_readphy(tp, MII_BMCR, &bmcr); - tg3_readphy(tp, MII_BMCR, &bmcr); r = -EINVAL; - if (bmcr & BMCR_ANENABLE) { + tg3_readphy(tp, MII_BMCR, &bmcr); + if (!tg3_readphy(tp, MII_BMCR, &bmcr) && + (bmcr & BMCR_ANENABLE)) { tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); r = 0; } @@ -6685,7 +6825,7 @@ static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf) static void tg3_get_ethtool_stats (struct net_device *dev, struct ethtool_stats *estats, u64 *tmp_stats) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); } @@ -6779,6 +6919,7 @@ static struct ethtool_ops tg3_ethtool_ops = { .get_link = ethtool_op_get_link, .get_eeprom_len = tg3_get_eeprom_len, .get_eeprom = tg3_get_eeprom, + .set_eeprom = tg3_set_eeprom, .get_ringparam = tg3_get_ringparam, .set_ringparam = tg3_set_ringparam, .get_pauseparam = tg3_get_pauseparam, @@ -6798,6 +6939,103 @@ static struct ethtool_ops tg3_ethtool_ops = { .get_ethtool_stats = tg3_get_ethtool_stats, }; +static void __devinit tg3_get_eeprom_size(struct tg3 *tp) +{ + u32 cursize, val; + + tp->nvram_size = EEPROM_CHIP_SIZE; + + if (tg3_nvram_read(tp, 0, &val) != 0) + return; + + if (swab32(val) != TG3_EEPROM_MAGIC) + return; + + /* + * Size the chip by reading offsets at increasing powers of two. + * When we encounter our validation signature, we know the addressing + * has wrapped around, and thus have our chip size. + */ + cursize = 0x800; + + while (cursize < tp->nvram_size) { + if (tg3_nvram_read(tp, cursize, &val) != 0) + return; + + if (swab32(val) == TG3_EEPROM_MAGIC) + break; + + cursize <<= 1; + } + + tp->nvram_size = cursize; +} + +static void __devinit tg3_get_nvram_size(struct tg3 *tp) +{ + u32 val; + + if (tg3_nvram_read(tp, 0xf0, &val) == 0) { + if (val != 0) { + tp->nvram_size = (val >> 16) * 1024; + return; + } + } + tp->nvram_size = 0x20000; +} + +static void __devinit tg3_get_nvram_info(struct tg3 *tp) +{ + u32 nvcfg1; + + nvcfg1 = tr32(NVRAM_CFG1); + if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { + tp->tg3_flags2 |= TG3_FLG2_FLASH; + } + else { + nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; + tw32(NVRAM_CFG1, nvcfg1); + } + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { + switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) { + case FLASH_VENDOR_ATMEL_FLASH_BUFFERED: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + break; + case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->nvram_pagesize = ATMEL_AT25F512_PAGE_SIZE; + break; + case FLASH_VENDOR_ATMEL_EEPROM: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + break; + case FLASH_VENDOR_ST: + tp->nvram_jedecnum = JEDEC_ST; + tp->nvram_pagesize = ST_M45PEX0_PAGE_SIZE; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + break; + case FLASH_VENDOR_SAIFUN: + tp->nvram_jedecnum = JEDEC_SAIFUN; + tp->nvram_pagesize = SAIFUN_SA25F0XX_PAGE_SIZE; + break; + case FLASH_VENDOR_SST_SMALL: + case FLASH_VENDOR_SST_LARGE: + tp->nvram_jedecnum = JEDEC_SST; + tp->nvram_pagesize = SST_25VF0X0_PAGE_SIZE; + break; + } + } + else { + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + } +} + /* Chips other than 5700/5701 use the NVRAM for fetching info. */ static void __devinit tg3_nvram_init(struct tg3 *tp) { @@ -6822,37 +7060,32 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { - u32 nvcfg1; + tp->tg3_flags |= TG3_FLAG_NVRAM; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { u32 nvaccess = tr32(NVRAM_ACCESS); - tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); + tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); } - nvcfg1 = tr32(NVRAM_CFG1); - - tp->tg3_flags |= TG3_FLAG_NVRAM; - if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { - if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE) - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - } else { - nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; - tw32(NVRAM_CFG1, nvcfg1); - } + tg3_get_nvram_info(tp); + tg3_get_nvram_size(tp); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { u32 nvaccess = tr32(NVRAM_ACCESS); - tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); + tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); } + } else { tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED); + + tg3_get_eeprom_size(tp); } } -static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp, - u32 offset, u32 *val) +static int tg3_nvram_read_using_eeprom(struct tg3 *tp, + u32 offset, u32 *val) { u32 tmp; int i; @@ -6885,11 +7118,30 @@ static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp, return 0; } -static int __devinit tg3_nvram_read(struct tg3 *tp, - u32 offset, u32 *val) +#define NVRAM_CMD_TIMEOUT 10000 + +static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd) { int i; + tw32(NVRAM_CMD, nvram_cmd); + for (i = 0; i < NVRAM_CMD_TIMEOUT; i++) { + udelay(10); + if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) { + udelay(10); + break; + } + } + if (i == NVRAM_CMD_TIMEOUT) { + return -EBUSY; + } + return 0; +} + +static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) +{ + int ret; + if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n"); return -EINVAL; @@ -6898,10 +7150,14 @@ static int __devinit tg3_nvram_read(struct tg3 *tp, if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) return tg3_nvram_read_using_eeprom(tp, offset, val); - if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) - offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) << - NVRAM_BUFFERED_PAGE_POS) + - (offset % NVRAM_BUFFERED_PAGE_SIZE); + if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && + (tp->tg3_flags2 & TG3_FLG2_FLASH) && + (tp->nvram_jedecnum == JEDEC_ATMEL)) { + + offset = ((offset / tp->nvram_pagesize) << + ATMEL_AT45DB0X1B_PAGE_POS) + + (offset % tp->nvram_pagesize); + } if (offset > NVRAM_ADDR_MSK) return -EINVAL; @@ -6915,19 +7171,11 @@ static int __devinit tg3_nvram_read(struct tg3 *tp, } tw32(NVRAM_ADDR, offset); - tw32(NVRAM_CMD, - NVRAM_CMD_RD | NVRAM_CMD_GO | - NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); + ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_RD | NVRAM_CMD_GO | + NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); - /* Wait for done bit to clear. */ - for (i = 0; i < 1000; i++) { - udelay(10); - if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) { - udelay(10); - *val = swab32(tr32(NVRAM_RDDATA)); - break; - } - } + if (ret == 0) + *val = swab32(tr32(NVRAM_RDDATA)); tg3_nvram_unlock(tp); @@ -6937,10 +7185,268 @@ static int __devinit tg3_nvram_read(struct tg3 *tp, tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); } - if (i >= 1000) - return -EBUSY; + return ret; +} - return 0; +static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, + u32 offset, u32 len, u8 *buf) +{ + int i, j, rc = 0; + u32 val; + + for (i = 0; i < len; i += 4) { + u32 addr, data; + + addr = offset + i; + + memcpy(&data, buf + i, 4); + + tw32(GRC_EEPROM_DATA, cpu_to_le32(data)); + + val = tr32(GRC_EEPROM_ADDR); + tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); + + val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | + EEPROM_ADDR_READ); + tw32(GRC_EEPROM_ADDR, val | + (0 << EEPROM_ADDR_DEVID_SHIFT) | + (addr & EEPROM_ADDR_ADDR_MASK) | + EEPROM_ADDR_START | + EEPROM_ADDR_WRITE); + + for (j = 0; j < 10000; j++) { + val = tr32(GRC_EEPROM_ADDR); + + if (val & EEPROM_ADDR_COMPLETE) + break; + udelay(100); + } + if (!(val & EEPROM_ADDR_COMPLETE)) { + rc = -EBUSY; + break; + } + } + + return rc; +} + +/* offset and length are dword aligned */ +static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, + u8 *buf) +{ + int ret = 0; + u32 pagesize = tp->nvram_pagesize; + u32 pagemask = pagesize - 1; + u32 nvram_cmd; + u8 *tmp; + + tmp = kmalloc(pagesize, GFP_KERNEL); + if (tmp == NULL) + return -ENOMEM; + + while (len) { + int j; + u32 phy_addr, page_off, size, nvaccess; + + phy_addr = offset & ~pagemask; + + for (j = 0; j < pagesize; j += 4) { + if ((ret = tg3_nvram_read(tp, phy_addr + j, + (u32 *) (tmp + j)))) + break; + } + if (ret) + break; + + page_off = offset & pagemask; + size = pagesize; + if (len < size) + size = len; + + len -= size; + + memcpy(tmp + page_off, buf, size); + + offset = offset + (pagesize - page_off); + + nvaccess = tr32(NVRAM_ACCESS); + tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); + + /* + * Before we can erase the flash page, we need + * to issue a special "write enable" command. + */ + nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; + + if (tg3_nvram_exec_cmd(tp, nvram_cmd)) + break; + + /* Erase the target page */ + tw32(NVRAM_ADDR, phy_addr); + + nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | + NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; + + if (tg3_nvram_exec_cmd(tp, nvram_cmd)) + break; + + /* Issue another write enable to start the write. */ + nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; + + if (tg3_nvram_exec_cmd(tp, nvram_cmd)) + break; + + for (j = 0; j < pagesize; j += 4) { + u32 data; + + data = *((u32 *) (tmp + j)); + tw32(NVRAM_WRDATA, cpu_to_be32(data)); + + tw32(NVRAM_ADDR, phy_addr + j); + + nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | + NVRAM_CMD_WR; + + if (j == 0) + nvram_cmd |= NVRAM_CMD_FIRST; + else if (j == (pagesize - 4)) + nvram_cmd |= NVRAM_CMD_LAST; + + if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) + break; + } + if (ret) + break; + } + + nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; + tg3_nvram_exec_cmd(tp, nvram_cmd); + + kfree(tmp); + + return ret; +} + +/* offset and length are dword aligned */ +static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, + u8 *buf) +{ + int i, ret = 0; + + for (i = 0; i < len; i += 4, offset += 4) { + u32 data, page_off, phy_addr, nvram_cmd; + + memcpy(&data, buf + i, 4); + tw32(NVRAM_WRDATA, cpu_to_be32(data)); + + page_off = offset % tp->nvram_pagesize; + + if ((tp->tg3_flags2 & TG3_FLG2_FLASH) && + (tp->nvram_jedecnum == JEDEC_ATMEL)) { + + phy_addr = ((offset / tp->nvram_pagesize) << + ATMEL_AT45DB0X1B_PAGE_POS) + page_off; + } + else { + phy_addr = offset; + } + + tw32(NVRAM_ADDR, phy_addr); + + nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; + + if ((page_off == 0) || (i == 0)) + nvram_cmd |= NVRAM_CMD_FIRST; + else if (page_off == (tp->nvram_pagesize - 4)) + nvram_cmd |= NVRAM_CMD_LAST; + + if (i == (len - 4)) + nvram_cmd |= NVRAM_CMD_LAST; + + if ((tp->nvram_jedecnum == JEDEC_ST) && + (nvram_cmd & NVRAM_CMD_FIRST)) { + + if ((ret = tg3_nvram_exec_cmd(tp, + NVRAM_CMD_WREN | NVRAM_CMD_GO | + NVRAM_CMD_DONE))) + + break; + } + if (!(tp->tg3_flags2 & TG3_FLG2_FLASH)) { + /* We always do complete word writes to eeprom. */ + nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); + } + + if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) + break; + } + return ret; +} + +/* offset and length are dword aligned */ +static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) +{ + int ret; + + if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { + printk(KERN_ERR PFX "Attempt to do nvram_write on Sun 570X\n"); + return -EINVAL; + } + + if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + GRC_LCLCTRL_GPIO_OE1); + udelay(40); + } + + if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) { + ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); + } + else { + u32 grc_mode; + + tg3_nvram_lock(tp); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { + u32 nvaccess = tr32(NVRAM_ACCESS); + + tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); + + tw32(NVRAM_WRITE1, 0x406); + } + + grc_mode = tr32(GRC_MODE); + tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); + + if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) || + !(tp->tg3_flags2 & TG3_FLG2_FLASH)) { + + ret = tg3_nvram_write_block_buffered(tp, offset, len, + buf); + } + else { + ret = tg3_nvram_write_block_unbuffered(tp, offset, len, + buf); + } + + grc_mode = tr32(GRC_MODE); + tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { + u32 nvaccess = tr32(NVRAM_ACCESS); + + tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); + } + tg3_nvram_unlock(tp); + } + + if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1); + udelay(40); + } + + return ret; } struct subsys_tbl_ent { @@ -7014,11 +7520,19 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg, led_cfg; - u32 nic_phy_id, cfg2; + u32 nic_phy_id, ver, cfg2 = 0; tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); tp->nic_sram_data_cfg = nic_cfg; + tg3_read_mem(tp, NIC_SRAM_DATA_VER, &ver); + ver >>= NIC_SRAM_DATA_VER_SHIFT; + if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703) && + (ver > 0) && (ver < 0x100)) + tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2); + eeprom_signature_found = 1; if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == @@ -7037,8 +7551,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) eeprom_phy_id = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { - tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg); - led_cfg &= (NIC_SRAM_DATA_CFG_LED_MODE_MASK | + led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK | SHASTA_EXT_LED_MODE_MASK); } else led_cfg = nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK; @@ -7083,9 +7596,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) tp->led_ctrl = LED_CTRL_MODE_PHY_2; - if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) && + if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; @@ -7097,9 +7609,13 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL) tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP; - tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2); if (cfg2 & (1 << 17)) tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING; + + /* serdes signal pre-emphasis in register 0x590 set by */ + /* bootcode if bit 18 is set */ + if (cfg2 & (1 << 18)) + tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS; } /* Reading the PHY ID register can conflict with ASF @@ -7155,9 +7671,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) u32 bmsr, adv_reg, tg3_ctrl; tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - - if (bmsr & BMSR_LSTATUS) + if (!tg3_readphy(tp, MII_BMSR, &bmsr) && + (bmsr & BMSR_LSTATUS)) goto skip_phy_reset; err = tg3_phy_reset(tp); @@ -7381,6 +7896,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pci_hdr_type = (cacheline_sz_reg >> 16) & 0xff; tp->pci_bist = (cacheline_sz_reg >> 24) & 0xff; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) + tp->tg3_flags2 |= TG3_FLG2_HW_TSO; + if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; @@ -7593,7 +8111,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 || tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F)) + (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F || + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F))) tp->tg3_flags |= TG3_FLAG_10_100_ONLY; err = tg3_phy_probe(tp); @@ -7900,7 +8419,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) #endif if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { - tp->dma_rwctrl |= 0x001f0000; + /* DMA read watermark not used on PCIE */ + tp->dma_rwctrl |= 0x00180000; } else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) @@ -8223,7 +8743,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, spin_lock_init(&tp->indirect_lock); INIT_WORK(&tp->reset_task, tg3_reset_task, tp); - tp->regs = ioremap(tg3reg_base, tg3reg_len); + tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len); if (tp->regs == 0UL) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); @@ -8274,11 +8794,13 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, } #if TG3_TSO_SUPPORT != 0 - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { + tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; + } + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || tp->pci_chip_rev_id == CHIPREV_ID_5705_A0 || - ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)) { + (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) { tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; } else { tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; @@ -8316,7 +8838,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, */ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { - pci_save_state(tp->pdev, tp->pci_cfg_state); + pci_save_state(tp->pdev); tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); tg3_halt(tp); } @@ -8355,7 +8877,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * of the PCI config space. We need to restore this after * GRC_MISC_CFG core clock resets and some resume events. */ - pci_save_state(tp->pdev, tp->pci_cfg_state); + pci_save_state(tp->pdev); printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", dev->name, @@ -8474,7 +8996,7 @@ static int tg3_resume(struct pci_dev *pdev) if (!netif_running(dev)) return 0; - pci_restore_state(tp->pdev, tp->pci_cfg_state); + pci_restore_state(tp->pdev); err = tg3_set_power_state(tp, 0); if (err)