From: Andy Gospodarek <gospo@redhat.com> Date: Thu, 28 Aug 2008 17:40:36 -0400 Subject: [net] tg3: update to upstream version 3.93 Message-id: 20080828214036.GF26620@gospo.rdu.redhat.com O-Subject: [RHEL5.3 PATCH] tg3: update to upstream version 3.93 Bugzilla: 441975 440958 436686 RH-Acked-by: David Miller <davem@redhat.com> RH-Acked-by: John W. Linville <linville@redhat.com> This is an update to the tg3 driver that moves us forward to upstream version 3.93. In the process I dropped this patch: commit 49b6e95ff6d05722bcf7a52b00454566ce0c44eb Author: David S. Miller <davem@sunset.davemloft.net> Date: Thu Mar 29 01:38:42 2007 -0700 [TG3]: Use pci_device_to_OF_node() on sparc. And use CONFIG_SPARC instead of CONFIG_SPARC64 as the test. as a favor to our friends who compile RHEL kernels on SPARC, so they can still use our SRPMs. I have lightly tested it and Broadcom has promised to have someone test it as well. I will post updates if needed, but I do not expect it will be. This will resolve BZ 441975, 440958, and 436686. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2363497..44955c0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2241,6 +2241,7 @@ config VIA_VELOCITY config TIGON3 tristate "Broadcom Tigon3 support" depends on PCI + select PHYLIB help This driver supports Broadcom Tigon3 based gigabit Ethernet cards. diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index f5aad77..e44abea 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -283,6 +283,7 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd) return 0; } +EXPORT_SYMBOL(phy_ethtool_sset); int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) { @@ -299,7 +300,7 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) return 0; } - +EXPORT_SYMBOL(phy_ethtool_gset); /* Note that this function is currently incompatible with the * PHYCONTROL layer. It changes registers without regard to @@ -354,6 +355,7 @@ int phy_mii_ioctl(struct phy_device *phydev, return 0; } +EXPORT_SYMBOL(phy_mii_ioctl); /* phy_start_aneg * diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 81f1575..bb63e81 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -32,6 +32,7 @@ #include <linux/skbuff.h> #include <linux/ethtool.h> #include <linux/mii.h> +#include <linux/phy.h> #include <linux/if_vlan.h> #include <linux/ip.h> #include <linux/tcp.h> @@ -66,8 +67,8 @@ #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.93" +#define DRV_MODULE_RELDATE "May 22, 2008" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -205,6 +206,7 @@ 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_5785)}, {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)}, @@ -806,6 +808,506 @@ 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; +} + +static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg) +{ + struct tg3 *tp = (struct tg3 *)bp->priv; + u32 val; + + if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) + return -EAGAIN; + + if (tg3_readphy(tp, reg, &val)) + return -EIO; + + return val; +} + +static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val) +{ + struct tg3 *tp = (struct tg3 *)bp->priv; + + if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) + return -EAGAIN; + + if (tg3_writephy(tp, reg, val)) + return -EIO; + + return 0; +} + +static int tg3_mdio_reset(struct mii_bus *bp) +{ + return 0; +} + +static void tg3_mdio_start(struct tg3 *tp) +{ + if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { + spin_lock(&tp->mdio_bus.mdio_lock); + tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED; + spin_unlock(&tp->mdio_bus.mdio_lock); + } + + tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL; + tw32_f(MAC_MI_MODE, tp->mi_mode); + udelay(80); +} + +static void tg3_mdio_stop(struct tg3 *tp) +{ + if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { + spin_lock(&tp->mdio_bus.mdio_lock); + tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_PAUSED; + spin_unlock(&tp->mdio_bus.mdio_lock); + } +} + +static int tg3_mdio_init(struct tg3 *tp) +{ + int i; + u32 reg; + struct mii_bus *mdio_bus = &tp->mdio_bus; + + spin_lock_init(&mdio_bus->mdio_lock); + tg3_mdio_start(tp); + + if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) || + (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED)) + return 0; + + memset(mdio_bus, 0, sizeof(*mdio_bus)); + + mdio_bus->name = "tg3 mdio bus"; + mdio_bus->id = (tp->pdev->bus->number << 8) | + tp->pdev->devfn; + mdio_bus->priv = tp; + mdio_bus->dev = &tp->pdev->dev; + mdio_bus->read = &tg3_mdio_read; + mdio_bus->write = &tg3_mdio_write; + mdio_bus->reset = &tg3_mdio_reset; + mdio_bus->phy_mask = ~(1 << PHY_ADDR); + mdio_bus->irq = &tp->mdio_irq[0]; + + for (i = 0; i < PHY_MAX_ADDR; i++) + mdio_bus->irq[i] = PHY_POLL; + + /* The bus registration will look for all the PHYs on the mdio bus. + * Unfortunately, it does not ensure the PHY is powered up before + * accessing the PHY ID registers. A chip reset is the + * quickest way to bring the device back to an operational state.. + */ + if (tg3_readphy(tp, MII_BMCR, ®) || (reg & BMCR_PDOWN)) + tg3_bmcr_reset(tp); + + i = mdiobus_register(mdio_bus); + if (!i) + tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED; + else + printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n", + tp->dev->name, i); + + return i; +} + +static void tg3_mdio_fini(struct tg3 *tp) +{ + if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { + tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_INITED; + mdiobus_unregister(&tp->mdio_bus); + tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED; + } +} + +/* tp->lock is held. */ +static void tg3_wait_for_event_ack(struct tg3 *tp) +{ + int i; + + /* Wait for up to 2.5 milliseconds */ + for (i = 0; i < 250000; i++) { + if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT)) + break; + udelay(10); + } +} + +/* 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); + + val = tr32(GRC_RX_CPU_EVENT); + val |= GRC_RX_CPU_DRIVER_EVENT; + tw32_f(GRC_RX_CPU_EVENT, val); +} + +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; + + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) + autoneg = tp->mdio_bus.phy_map[PHY_ADDR]->autoneg; + else + 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_adjust_link(struct net_device *dev) +{ + u8 oldflowctrl, linkmesg = 0; + u32 mac_mode, lcl_adv, rmt_adv; + struct tg3 *tp = netdev_priv(dev); + struct phy_device *phydev = tp->mdio_bus.phy_map[PHY_ADDR]; + + spin_lock(&tp->lock); + + mac_mode = tp->mac_mode & ~(MAC_MODE_PORT_MODE_MASK | + MAC_MODE_HALF_DUPLEX); + + oldflowctrl = tp->link_config.active_flowctrl; + + if (phydev->link) { + lcl_adv = 0; + rmt_adv = 0; + + if (phydev->speed == SPEED_100 || phydev->speed == SPEED_10) + mac_mode |= MAC_MODE_PORT_MODE_MII; + else + mac_mode |= MAC_MODE_PORT_MODE_GMII; + + if (phydev->duplex == DUPLEX_HALF) + mac_mode |= MAC_MODE_HALF_DUPLEX; + else { + lcl_adv = tg3_advert_flowctrl_1000T( + tp->link_config.flowctrl); + + if (phydev->pause) + rmt_adv = LPA_PAUSE_CAP; + if (phydev->asym_pause) + rmt_adv |= LPA_PAUSE_ASYM; + } + + tg3_setup_flow_control(tp, lcl_adv, rmt_adv); + } else + mac_mode |= MAC_MODE_PORT_MODE_GMII; + + if (mac_mode != tp->mac_mode) { + tp->mac_mode = mac_mode; + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); + } + + if (phydev->speed == SPEED_1000 && phydev->duplex == DUPLEX_HALF) + tw32(MAC_TX_LENGTHS, + ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | + (6 << TX_LENGTHS_IPG_SHIFT) | + (0xff << TX_LENGTHS_SLOT_TIME_SHIFT))); + else + tw32(MAC_TX_LENGTHS, + ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | + (6 << TX_LENGTHS_IPG_SHIFT) | + (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); + + if ((phydev->link && tp->link_config.active_speed == SPEED_INVALID) || + (!phydev->link && tp->link_config.active_speed != SPEED_INVALID) || + phydev->speed != tp->link_config.active_speed || + phydev->duplex != tp->link_config.active_duplex || + oldflowctrl != tp->link_config.active_flowctrl) + linkmesg = 1; + + tp->link_config.active_speed = phydev->speed; + tp->link_config.active_duplex = phydev->duplex; + + spin_unlock(&tp->lock); + + if (linkmesg) + tg3_link_report(tp); +} + +static int tg3_phy_init(struct tg3 *tp) +{ + struct phy_device *phydev; + + if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) + return 0; + + /* Bring the PHY back to a known state. */ + tg3_bmcr_reset(tp); + + phydev = tp->mdio_bus.phy_map[PHY_ADDR]; + + /* Attach the MAC to the PHY. */ + phydev = phy_connect(tp->dev, phydev->dev.bus_id, + tg3_adjust_link, 0); + if (IS_ERR(phydev)) { + printk(KERN_ERR "%s: Could not attach to PHY\n", tp->dev->name); + return PTR_ERR(phydev); + } + + tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED; + + /* Mask with MAC supported features. */ + phydev->supported &= (PHY_GBIT_FEATURES | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause); + + phydev->advertising = phydev->supported; + + printk(KERN_INFO + "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", + tp->dev->name, phydev->drv->name, phydev->dev.bus_id); + + return 0; +} + +static void tg3_phy_start(struct tg3 *tp) +{ + struct phy_device *phydev; + + if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + return; + + phydev = tp->mdio_bus.phy_map[PHY_ADDR]; + + if (tp->link_config.phy_is_low_power) { + tp->link_config.phy_is_low_power = 0; + phydev->speed = tp->link_config.orig_speed; + phydev->duplex = tp->link_config.orig_duplex; + phydev->autoneg = tp->link_config.orig_autoneg; + phydev->advertising = tp->link_config.orig_advertising; + } + + phy_start(phydev); + + phy_start_aneg(phydev); +} + +static void tg3_phy_stop(struct tg3 *tp) +{ + if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + return; + + phy_stop(tp->mdio_bus.phy_map[PHY_ADDR]); +} + +static void tg3_phy_fini(struct tg3 *tp) +{ + if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { + phy_disconnect(tp->mdio_bus.phy_map[PHY_ADDR]); + tp->tg3_flags3 &= ~TG3_FLG3_PHY_CONNECTED; + } +} + +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_automdix(struct tg3 *tp, int enable) { u32 phy; @@ -857,35 +1359,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) @@ -1075,6 +1589,7 @@ static void tg3_link_report(struct tg3 *); */ static int tg3_phy_reset(struct tg3 *tp) { + u32 cpmuctrl; u32 phy_status; int err; @@ -1104,10 +1619,28 @@ 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 (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 (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { u32 val; @@ -1126,6 +1659,8 @@ static int tg3_phy_reset(struct tg3 *tp) MII_TG3_MISC_SHDW_APD_WKTM_84MS); } + tg3_phy_apply_otp(tp); + out: if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); @@ -1227,6 +1762,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; @@ -1338,7 +1888,7 @@ static void tg3_power_down_phy(struct tg3 *tp) tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); udelay(40); return; - } else { + } else if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); @@ -1412,7 +1962,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) "requested.\n", tp->dev->name, state); return -EINVAL; - }; + } power_control |= PCI_PM_CTRL_PME_ENABLE; @@ -1420,18 +1970,55 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) tw32(TG3PCI_MISC_HOST_CTRL, misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT); - if (tp->link_config.phy_is_low_power == 0) { - tp->link_config.phy_is_low_power = 1; - tp->link_config.orig_speed = tp->link_config.speed; - tp->link_config.orig_duplex = tp->link_config.duplex; - tp->link_config.orig_autoneg = tp->link_config.autoneg; - } + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if ((tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) && + !tp->link_config.phy_is_low_power) { + struct phy_device *phydev; + u32 advertising; + + phydev = tp->mdio_bus.phy_map[PHY_ADDR]; + + tp->link_config.phy_is_low_power = 1; + + tp->link_config.orig_speed = phydev->speed; + tp->link_config.orig_duplex = phydev->duplex; + tp->link_config.orig_autoneg = phydev->autoneg; + tp->link_config.orig_advertising = phydev->advertising; + + advertising = ADVERTISED_TP | + ADVERTISED_Pause | + ADVERTISED_Autoneg | + ADVERTISED_10baseT_Half; + + if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || + (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) { + if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) + advertising |= + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_10baseT_Full; + else + advertising |= ADVERTISED_10baseT_Full; + } - if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) { - tp->link_config.speed = SPEED_10; - tp->link_config.duplex = DUPLEX_HALF; - tp->link_config.autoneg = AUTONEG_ENABLE; - tg3_setup_phy(tp, 0); + phydev->advertising = advertising; + + phy_start_aneg(phydev); + } + } else { + if (tp->link_config.phy_is_low_power == 0) { + tp->link_config.phy_is_low_power = 1; + tp->link_config.orig_speed = tp->link_config.speed; + tp->link_config.orig_duplex = tp->link_config.duplex; + tp->link_config.orig_autoneg = tp->link_config.autoneg; + } + + if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) { + tp->link_config.speed = SPEED_10; + tp->link_config.duplex = DUPLEX_HALF; + tp->link_config.autoneg = AUTONEG_ENABLE; + tg3_setup_phy(tp, 0); + } } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { @@ -1462,8 +2049,10 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) u32 mac_mode; if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); - udelay(40); + if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); + udelay(40); + } if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) mac_mode = MAC_MODE_PORT_MODE_GMII; @@ -1588,102 +2177,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 +2221,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 +2247,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 +2256,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 +2278,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 +2293,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 +2306,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 +2333,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 +2426,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 +2477,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 +2608,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; @@ -2272,6 +2785,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 +2885,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 +3031,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 +3070,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 +3133,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 +3159,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 +3169,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 +3180,13 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) } /* Want auto-negotiation. */ - expected_sg_dig_ctrl = 0x81388400; + expected_sg_dig_ctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_COMMON_SETUP; - /* Pause capability */ - expected_sg_dig_ctrl |= (1 << 11); - - /* 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 +3201,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 +3212,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 +3245,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 +3281,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 +3319,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 +3344,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 +3433,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 +3449,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 +3494,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 +3565,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 +3580,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; @@ -3343,7 +3872,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. @@ -3403,7 +3932,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, @@ -3615,7 +4144,15 @@ static int tg3_poll(struct net_device *netdev, int *budget) sblk->status = SD_STATUS_UPDATED | (sblk->status & ~SD_STATUS_LINK_CHG); spin_lock(&tp->lock); - tg3_setup_phy(tp, 0); + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + tw32_f(MAC_STATUS, + (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED | + MAC_STATUS_MI_COMPLETION | + MAC_STATUS_LNKSTATE_CHANGED)); + udelay(40); + } else + tg3_setup_phy(tp, 0); spin_unlock(&tp->lock); } } @@ -3857,6 +4394,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; @@ -3887,6 +4426,7 @@ static void tg3_poll_controller(struct net_device *dev) static void tg3_reset_task(void *_data) { struct tg3 *tp = _data; + int err; unsigned int restart_timer; tg3_full_lock(tp, 0); @@ -3900,6 +4440,8 @@ static void tg3_reset_task(void *_data) tg3_full_unlock(tp); + tg3_phy_stop(tp); + tg3_netif_stop(tp); tg3_full_lock(tp, 1); @@ -3915,7 +4457,8 @@ static void tg3_reset_task(void *_data) } tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); - if (tg3_init_hw(tp, 1)) + err = tg3_init_hw(tp, 1); + if (err) goto out; tg3_netif_start(tp); @@ -3927,6 +4470,9 @@ out: tp->tg3_dist_flags &= ~TG3_DIST_FLAG_IN_RESET_TASK; tg3_full_unlock(tp); + + if (!err) + tg3_phy_start(tp); } static void tg3_dump_short_state(struct tg3 *tp) @@ -3979,11 +4525,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 { @@ -4193,7 +4749,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 { @@ -4306,7 +4862,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, @@ -4418,6 +4976,8 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) return 0; } + tg3_phy_stop(tp); + tg3_netif_stop(tp); tg3_full_lock(tp, 1); @@ -4433,6 +4993,9 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) tg3_full_unlock(tp); + if (!err) + tg3_phy_start(tp); + return err; } @@ -4724,7 +5287,7 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int default: break; - }; + } } val = tr32(ofs); @@ -4966,7 +5529,7 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) default: break; - }; + } } if (kind == RESET_KIND_INIT || @@ -4992,7 +5555,7 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind) default: break; - }; + } } if (kind == RESET_KIND_SHUTDOWN) @@ -5021,7 +5584,7 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind) default: break; - }; + } } } @@ -5143,6 +5706,8 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_nvram_lock(tp); + tg3_mdio_stop(tp); + /* No matching tg3_nvram_unlock() after this because * chip reset below will undo the nvram lock. */ @@ -5158,7 +5723,8 @@ static int tg3_chip_reset(struct tg3 *tp) 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_5761 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) tw32(GRC_FASTBOOT_PC, 0); /* @@ -5294,6 +5860,8 @@ static int tg3_chip_reset(struct tg3 *tp) tw32_f(MAC_MODE, 0); udelay(40); + tg3_mdio_start(tp); + err = tg3_poll_fw(tp); if (err) return err; @@ -5329,19 +5897,17 @@ 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); + val |= GRC_RX_CPU_DRIVER_EVENT; 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); - } + /* Wait for RX cpu to ACK this event. */ + tg3_wait_for_event_ack(tp); } } @@ -6375,7 +6941,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_abort_hw(tp, 1); } - if (reset_phy) + if (reset_phy && + !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) tg3_phy_reset(tp); err = tg3_chip_reset(tp); @@ -6451,7 +7018,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) return err; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) { + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) { /* This value is determined during the probe time DMA * engine test, tg3_test_dma. */ @@ -6690,7 +7258,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | RDMAC_MODE_LNGREAD_ENAB); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB | RDMAC_MODE_MBUF_RBD_CRPT_ENAB | RDMAC_MODE_MBUF_SBD_CRPT_ENAB; @@ -6858,8 +7427,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) 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)) - val |= (1 << 29); + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)) + val |= WDMAC_MODE_STATUS_TAG_FIX; tw32_f(WDMAC_MODE, val); udelay(40); @@ -6920,23 +7490,14 @@ 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_5761) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); - if (tp->link_config.phy_is_low_power) { - tp->link_config.phy_is_low_power = 0; - tp->link_config.speed = tp->link_config.orig_speed; - tp->link_config.duplex = tp->link_config.orig_duplex; - tp->link_config.autoneg = tp->link_config.orig_autoneg; - } - - tp->mi_mode = MAC_MI_MODE_BASE; - tw32_f(MAC_MI_MODE, tp->mi_mode); - udelay(80); - tw32(MAC_LED_CTRL, tp->led_ctrl); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); @@ -6983,19 +7544,28 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); } - err = tg3_setup_phy(tp, 0); - if (err) - return err; + if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { + if (tp->link_config.phy_is_low_power) { + tp->link_config.phy_is_low_power = 0; + tp->link_config.speed = tp->link_config.orig_speed; + tp->link_config.duplex = tp->link_config.orig_duplex; + tp->link_config.autoneg = tp->link_config.orig_autoneg; + } - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) { - u32 tmp; + err = tg3_setup_phy(tp, 0); + if (err) + return err; - /* Clear CRC stats. */ - if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) { - tg3_writephy(tp, MII_TG3_TEST1, - tmp | MII_TG3_TEST1_CRC_EN); - tg3_readphy(tp, 0x14, &tmp); + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) { + u32 tmp; + + /* Clear CRC stats. */ + if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) { + tg3_writephy(tp, MII_TG3_TEST1, + tmp | MII_TG3_TEST1_CRC_EN); + tg3_readphy(tp, 0x14, &tmp); + } } } @@ -7048,7 +7618,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. */ @@ -7065,21 +7635,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) */ static int tg3_init_hw(struct tg3 *tp, int reset_phy) { - int err; - - /* Force the chip into D0. */ - err = tg3_set_power_state(tp, PCI_D0); - if (err) - goto out; - tg3_switch_clocks(tp); tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); - err = tg3_reset_hw(tp, reset_phy); - -out: - return err; + return tg3_reset_hw(tp, reset_phy); } #define TG3_STAT_ADD32(PSTAT, REG) \ @@ -7231,14 +7791,16 @@ static void tg3_timer(unsigned long __opaque) if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { u32 val; + 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); + val |= GRC_RX_CPU_DRIVER_EVENT; + tw32_f(GRC_RX_CPU_EVENT, val); } tp->asf_counter = tp->asf_multiplier; } @@ -7392,13 +7954,11 @@ static int tg3_open(struct net_device *dev) netif_carrier_off(tp->dev); - tg3_full_lock(tp, 0); - err = tg3_set_power_state(tp, PCI_D0); - if (err) { - tg3_full_unlock(tp); + if (err) return err; - } + + tg3_full_lock(tp, 0); tg3_disable_ints(tp); tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; @@ -7507,6 +8067,8 @@ static int tg3_open(struct net_device *dev) } } + tg3_phy_start(tp); + tg3_full_lock(tp, 0); add_timer(&tp->timer); @@ -8187,6 +8749,7 @@ static int tg3_get_eeprom_len(struct net_device *dev) } 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); static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) @@ -8194,7 +8757,8 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, 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 +8777,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 +8789,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,11 +8803,10 @@ 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; @@ -8257,8 +8818,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, { 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 +8833,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 +8847,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; @@ -8314,7 +8874,13 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct tg3 *tp = netdev_priv(dev); + struct tg3 *tp = netdev_priv(dev); + + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + return -EAGAIN; + return phy_ethtool_gset(tp->mdio_bus.phy_map[PHY_ADDR], cmd); + } cmd->supported = (SUPPORTED_Autoneg); @@ -8351,6 +8917,12 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct tg3 *tp = netdev_priv(dev); + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + return -EAGAIN; + return phy_ethtool_sset(tp->mdio_bus.phy_map[PHY_ADDR], cmd); + } + if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) { /* These are the only valid advertisement bits allowed. */ if (cmd->autoneg == AUTONEG_ENABLE && @@ -8368,7 +8940,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 +8955,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; @@ -8466,7 +9038,10 @@ 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) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) dev->features |= NETIF_F_TSO_ECN; } else dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN); @@ -8477,7 +9052,6 @@ static int tg3_set_tso(struct net_device *dev, u32 value) static int tg3_nway_reset(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); - u32 bmcr; int r; if (!netif_running(dev)) @@ -8486,17 +9060,25 @@ static int tg3_nway_reset(struct net_device *dev) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) return -EINVAL; - spin_lock_bh(&tp->lock); - r = -EINVAL; - tg3_readphy(tp, MII_BMCR, &bmcr); - if (!tg3_readphy(tp, MII_BMCR, &bmcr) && - ((bmcr & BMCR_ANENABLE) || - (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) { - tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART | - BMCR_ANENABLE); - r = 0; + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + return -EAGAIN; + r = phy_start_aneg(tp->mdio_bus.phy_map[PHY_ADDR]); + } else { + u32 bmcr; + + spin_lock_bh(&tp->lock); + r = -EINVAL; + tg3_readphy(tp, MII_BMCR, &bmcr); + if (!tg3_readphy(tp, MII_BMCR, &bmcr) && + ((bmcr & BMCR_ANENABLE) || + (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) { + tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART | + BMCR_ANENABLE); + r = 0; + } + spin_unlock_bh(&tp->lock); } - spin_unlock_bh(&tp->lock); return r; } @@ -8538,6 +9120,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e return -EINVAL; if (netif_running(dev)) { + tg3_phy_stop(tp); tg3_netif_stop(tp); irq_sync = 1; } @@ -8561,6 +9144,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e tg3_full_unlock(tp); + if (irq_sync && !err) + tg3_phy_start(tp); + return err; } @@ -8569,43 +9155,107 @@ 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) { struct tg3 *tp = netdev_priv(dev); - int irq_sync = 0, err = 0; + int err = 0; - if (netif_running(dev)) { - tg3_netif_stop(tp); - irq_sync = 1; - } + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + return -EAGAIN; - tg3_full_lock(tp, irq_sync); + if (epause->autoneg) { + u32 newadv; + struct phy_device *phydev; - if (epause->autoneg) - tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; - else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; - if (epause->rx_pause) - tp->tg3_flags |= TG3_FLAG_RX_PAUSE; - else - tp->tg3_flags &= ~TG3_FLAG_RX_PAUSE; - if (epause->tx_pause) - tp->tg3_flags |= TG3_FLAG_TX_PAUSE; - else - tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE; + phydev = tp->mdio_bus.phy_map[PHY_ADDR]; - if (netif_running(dev)) { - tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - err = tg3_restart_hw(tp, 1); - if (!err) - tg3_netif_start(tp); - } + if (epause->rx_pause) { + if (epause->tx_pause) + newadv = ADVERTISED_Pause; + else + newadv = ADVERTISED_Pause | + ADVERTISED_Asym_Pause; + } else if (epause->tx_pause) { + newadv = ADVERTISED_Asym_Pause; + } else + newadv = 0; + + if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { + u32 oldadv = phydev->advertising & + (ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + if (oldadv != newadv) { + phydev->advertising &= + ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + phydev->advertising |= newadv; + err = phy_start_aneg(phydev); + } + } else { + tp->link_config.advertising &= + ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + tp->link_config.advertising |= newadv; + } + } else { + if (epause->rx_pause) + tp->link_config.flowctrl |= TG3_FLOW_CTRL_RX; + else + tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_RX; - tg3_full_unlock(tp); + if (epause->tx_pause) + tp->link_config.flowctrl |= TG3_FLOW_CTRL_TX; + else + tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_TX; + + if (netif_running(dev)) + tg3_setup_flow_control(tp, 0, 0); + } + } else { + int irq_sync = 0; + + if (netif_running(dev)) { + tg3_netif_stop(tp); + irq_sync = 1; + } + + tg3_full_lock(tp, irq_sync); + + if (epause->autoneg) + tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; + else + tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; + if (epause->rx_pause) + tp->link_config.flowctrl |= TG3_FLOW_CTRL_RX; + else + tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_RX; + if (epause->tx_pause) + tp->link_config.flowctrl |= TG3_FLOW_CTRL_TX; + else + tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_TX; + + if (netif_running(dev)) { + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); + err = tg3_restart_hw(tp, 1); + if (!err) + tg3_netif_start(tp); + } + + tg3_full_unlock(tp); + } return err; } @@ -8649,7 +9299,8 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) ethtool_op_set_tx_hw_csum(dev, data); else ethtool_op_set_tx_csum(dev, data); @@ -8691,7 +9342,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) @@ -8730,7 +9381,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 +9419,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 +9452,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 +9498,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; @@ -9169,7 +9819,8 @@ static int tg3_test_memory(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) mem_tbl = mem_tbl_5755; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) mem_tbl = mem_tbl_5906; @@ -9375,7 +10026,9 @@ static int tg3_test_loopback(struct tg3 *tp) if (err) return TG3_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 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { int i; u32 status; @@ -9392,7 +10045,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,14 +10055,17 @@ 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 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { tw32(TG3_CPMU_CTRL, cpmuctrl); /* Release the mutex */ tw32(TG3_CPMU_MUTEX_GNT, CPMU_MUTEX_GNT_DRIVER); } - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK)) err |= TG3_PHY_LOOPBACK_FAILED; } @@ -9436,9 +10092,10 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, data[1] = 1; } if (etest->flags & ETH_TEST_FL_OFFLINE) { - int err, irq_sync = 0; + int err, err2 = 0, irq_sync = 0; if (netif_running(dev)) { + tg3_phy_stop(tp); tg3_netif_stop(tp); irq_sync = 1; } @@ -9479,11 +10136,15 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); if (netif_running(dev)) { tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - if (!tg3_restart_hw(tp, 1)) + err2 = tg3_restart_hw(tp, 1); + if (!err2) tg3_netif_start(tp); } tg3_full_unlock(tp); + + if (irq_sync && !err2) + tg3_phy_start(tp); } if (tp->link_config.phy_is_low_power) tg3_set_power_state(tp, PCI_D3hot); @@ -9496,6 +10157,12 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) struct tg3 *tp = netdev_priv(dev); int err; + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) + return -EAGAIN; + return phy_mii_ioctl(tp->mdio_bus.phy_map[PHY_ADDR], data, cmd); + } + switch(cmd) { case SIOCGMIIPHY: data->phy_id = PHY_ADDR; @@ -9733,7 +10400,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 +10541,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 +10558,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 +10662,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; } } @@ -10050,7 +10726,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) tg3_get_5755_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) tg3_get_5787_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) tg3_get_5761_nvram_info(tp); @@ -10188,6 +10865,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 +10891,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); @@ -10261,8 +10948,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 +10993,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 +11031,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; @@ -10369,6 +11058,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { @@ -10637,16 +11327,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; @@ -10693,12 +11382,64 @@ 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; u32 hw_phy_id, hw_phy_id_masked; int err; + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) + return tg3_phy_init(tp); + /* Reading the PHY ID register can conflict with ASF * firwmare access to the PHY hardware. */ @@ -10848,6 +11589,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, @@ -10864,8 +11606,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp) 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); } } @@ -10958,11 +11700,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 +11742,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; @@ -11137,6 +11879,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. @@ -11192,6 +11966,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; @@ -11213,6 +11988,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; @@ -11225,14 +12001,8 @@ 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_5705_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); @@ -11421,7 +12191,8 @@ 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 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || @@ -11449,6 +12220,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) { @@ -11505,18 +12285,41 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG; if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M) tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) 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 (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) tp->coalesce_mode |= HOSTCC_MODE_32BYTE; - /* Initialize MAC MI mode, polling disabled. */ - tw32_f(MAC_MI_MODE, tp->mi_mode); - udelay(80); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB; + + err = tg3_mdio_init(tp); + if (err) + return err; /* Initialize data/descriptor byte/word swapping. */ val = tr32(GRC_MODE); @@ -11597,6 +12400,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) printk(KERN_ERR PFX "(%s) phy probe failed, err %d\n", pci_name(tp->pdev), err); /* ... but do not return immediately ... */ + tg3_mdio_fini(tp); } tg3_read_partno(tp); @@ -11644,6 +12448,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->dev->hard_start_xmit = tg3_start_xmit; else @@ -11676,15 +12481,19 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp) { struct net_device *dev = tp->dev; struct pci_dev *pdev = tp->pdev; - struct device_node *dp = pci_device_to_OF_node(pdev); - const unsigned char *addr; - int len; - - addr = of_get_property(dp, "local-mac-address", &len); - if (addr && len == 6) { - memcpy(dev->dev_addr, addr, 6); - memcpy(dev->perm_addr, dev->dev_addr, 6); - return 0; + struct pcidev_cookie *pcp = pdev->sysdata; + + if (pcp != NULL) { + const unsigned char *addr; + int len; + + addr = of_get_property(pcp->prom_node, "local-mac-address", + &len); + if (addr && len == 6) { + memcpy(dev->dev_addr, addr, 6); + memcpy(dev->perm_addr, dev->dev_addr, 6); + return 0; + } } return -ENODEV; } @@ -11764,7 +12573,7 @@ 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 @@ -11846,7 +12655,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 +12672,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 +12716,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: @@ -12267,7 +13076,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,7 +13178,8 @@ 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; + resource_size_t tg3reg_base; + unsigned long tg3reg_len; struct net_device *dev; struct tg3 *tp; int i, err, pm_cap; @@ -12437,7 +13247,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, 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 @@ -12569,7 +13379,10 @@ 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) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) dev->features |= NETIF_F_TSO_ECN; } @@ -12600,7 +13413,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; @@ -12634,7 +13447,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) dev->features |= NETIF_F_HW_CSUM; else dev->features |= NETIF_F_IP_CSUM; @@ -12645,6 +13459,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, /* 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); @@ -12719,6 +13534,12 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) struct tg3 *tp = netdev_priv(dev); flush_scheduled_work(); + + if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { + tg3_phy_fini(tp); + tg3_mdio_fini(tp); + } + unregister_netdev(dev); if (tp->aperegs) { iounmap(tp->aperegs); @@ -12751,6 +13572,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) return 0; flush_scheduled_work(); + tg3_phy_stop(tp); tg3_netif_stop(tp); del_timer_sync(&tp->timer); @@ -12768,10 +13590,13 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) err = tg3_set_power_state(tp, pci_choose_state(pdev, state)); if (err) { + int err2; + tg3_full_lock(tp, 0); tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - if (tg3_restart_hw(tp, 1)) + err2 = tg3_restart_hw(tp, 1); + if (err2) goto out; tp->timer.expires = jiffies + tp->timer_offset; @@ -12782,6 +13607,9 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) out: tg3_full_unlock(tp); + + if (!err2) + tg3_phy_start(tp); } return err; @@ -12824,6 +13652,9 @@ static int tg3_resume(struct pci_dev *pdev) out: tg3_full_unlock(tp); + if (!err) + tg3_phy_start(tp); + return err; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c654142..e621e07 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -128,6 +128,7 @@ #define ASIC_REV_USE_PROD_ID_REG 0x0f #define ASIC_REV_5784 0x5784 #define ASIC_REV_5761 0x5761 +#define ASIC_REV_5785 0x5785 #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -138,6 +139,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 @@ -413,7 +416,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 +548,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 +561,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 +869,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 @@ -1099,6 +1110,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 @@ -1419,6 +1431,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 +1565,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 +1591,50 @@ #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 + + + +/* 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 @@ -1627,6 +1701,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 @@ -1698,15 +1773,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 @@ -1736,6 +1827,34 @@ #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_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 @@ -2103,13 +2222,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. @@ -2118,6 +2242,7 @@ struct tg3_link_config { u16 orig_speed; u8 orig_duplex; u8 orig_autoneg; + u32 orig_advertising; }; struct tg3_bufmgr_config { @@ -2338,8 +2463,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 @@ -2396,6 +2519,11 @@ struct tg3 { #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_5701_DMA_BUG 0x00000008 +#define TG3_FLG3_USE_PHYLIB 0x00000010 +#define TG3_FLG3_MDIOBUS_INITED 0x00000020 +#define TG3_FLG3_MDIOBUS_PAUSED 0x00000040 +#define TG3_FLG3_PHY_CONNECTED 0x00000080 struct timer_list timer; u16 timer_counter; @@ -2436,6 +2564,9 @@ struct tg3 { int msi_cap; int pcix_cap; + struct mii_bus mdio_bus; + int mdio_irq[PHY_MAX_ADDR]; + /* PHY info */ u32 phy_id; #define PHY_ID_MASK 0xfffffff0 @@ -2465,6 +2596,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 +2626,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 +2641,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/include/linux/pci_ids.h b/include/linux/pci_ids.h index 4c8934c..f20d3f6 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1964,6 +1964,7 @@ #define PCI_DEVICE_ID_TIGON3_5787M 0x1693 #define PCI_DEVICE_ID_TIGON3_5782 0x1696 #define PCI_DEVICE_ID_TIGON3_5784 0x1698 +#define PCI_DEVICE_ID_TIGON3_5785 0x1699 #define PCI_DEVICE_ID_TIGON3_5786 0x169a #define PCI_DEVICE_ID_TIGON3_5787 0x169b #define PCI_DEVICE_ID_TIGON3_5788 0x169c