X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Ftg3.c;h=633c128a622868ac91b9cde33b41baf6c4e8e219;hb=e308a5d806c852f56590ffdd3834d0df0cbed8d7;hp=5ee14764fd74e0ed5dc56296022588e03577e113;hpb=6460d948f3ebf7d5040328a60a0ab7221f69945b;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5ee1476..633c128 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -64,8 +66,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.78" -#define DRV_MODULE_RELDATE "July 11, 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 @@ -198,6 +200,12 @@ static struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)}, + {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)}, @@ -312,6 +320,16 @@ static u32 tg3_read32(struct tg3 *tp, u32 off) return (readl(tp->regs + off)); } +static void tg3_ape_write32(struct tg3 *tp, u32 off, u32 val) +{ + writel(val, tp->aperegs + off); +} + +static u32 tg3_ape_read32(struct tg3 *tp, u32 off) +{ + return (readl(tp->aperegs + off)); +} + static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; @@ -498,6 +516,73 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) spin_unlock_irqrestore(&tp->indirect_lock, flags); } +static void tg3_ape_lock_init(struct tg3 *tp) +{ + int i; + + /* Make sure the driver hasn't any stale locks. */ + for (i = 0; i < 8; i++) + tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + 4 * i, + APE_LOCK_GRANT_DRIVER); +} + +static int tg3_ape_lock(struct tg3 *tp, int locknum) +{ + int i, off; + int ret = 0; + u32 status; + + if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) + return 0; + + switch (locknum) { + case TG3_APE_LOCK_MEM: + break; + default: + return -EINVAL; + } + + off = 4 * locknum; + + tg3_ape_write32(tp, TG3_APE_LOCK_REQ + off, APE_LOCK_REQ_DRIVER); + + /* Wait for up to 1 millisecond to acquire lock. */ + for (i = 0; i < 100; i++) { + status = tg3_ape_read32(tp, TG3_APE_LOCK_GRANT + off); + if (status == APE_LOCK_GRANT_DRIVER) + break; + udelay(10); + } + + if (status != APE_LOCK_GRANT_DRIVER) { + /* Revoke the lock request. */ + tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, + APE_LOCK_GRANT_DRIVER); + + ret = -EBUSY; + } + + return ret; +} + +static void tg3_ape_unlock(struct tg3 *tp, int locknum) +{ + int off; + + if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) + return; + + switch (locknum) { + case TG3_APE_LOCK_MEM: + break; + default: + return; + } + + off = 4 * locknum; + tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, APE_LOCK_GRANT_DRIVER); +} + static void tg3_disable_ints(struct tg3 *tp) { tw32(TG3PCI_MISC_HOST_CTRL, @@ -574,7 +659,7 @@ static void tg3_restart_ints(struct tg3 *tp) static inline void tg3_netif_stop(struct tg3 *tp) { tp->dev->trans_start = jiffies; /* prevent tx timeout */ - netif_poll_disable(tp->dev); + napi_disable(&tp->napi); netif_tx_disable(tp->dev); } @@ -585,7 +670,7 @@ static inline void tg3_netif_start(struct tg3 *tp) * so long as all callers are assured to have free tx slots * (such as after tg3_init_hw) */ - netif_poll_enable(tp->dev); + napi_enable(&tp->napi); tp->hw_status->status |= SD_STATUS_UPDATED; tg3_enable_ints(tp); } @@ -595,7 +680,8 @@ static void tg3_switch_clocks(struct tg3 *tp) u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL); u32 orig_clock_ctrl; - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + if ((tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) || + (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) return; orig_clock_ctrl = clock_ctrl; @@ -709,16 +795,585 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) loops -= 1; } - ret = -EBUSY; - if (loops != 0) - ret = 0; + ret = -EBUSY; + if (loops != 0) + ret = 0; + + if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { + tw32_f(MAC_MI_MODE, tp->mi_mode); + udelay(80); + } + + 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_config(struct tg3 *tp) +{ + u32 val; + + if (tp->mdio_bus.phy_map[PHY_ADDR]->interface != + PHY_INTERFACE_MODE_RGMII) + return; + + val = tr32(MAC_PHYCFG1) & ~(MAC_PHYCFG1_RGMII_EXT_RX_DEC | + MAC_PHYCFG1_RGMII_SND_STAT_EN); + if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) { + if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) + val |= MAC_PHYCFG1_RGMII_EXT_RX_DEC; + if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) + val |= MAC_PHYCFG1_RGMII_SND_STAT_EN; + } + tw32(MAC_PHYCFG1, val | MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_TXC_DRV); + + val = tr32(MAC_PHYCFG2) & ~(MAC_PHYCFG2_INBAND_ENABLE); + if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)) + val |= MAC_PHYCFG2_INBAND_ENABLE; + tw32(MAC_PHYCFG2, val); + + val = tr32(MAC_EXT_RGMII_MODE); + val &= ~(MAC_RGMII_MODE_RX_INT_B | + MAC_RGMII_MODE_RX_QUALITY | + MAC_RGMII_MODE_RX_ACTIVITY | + MAC_RGMII_MODE_RX_ENG_DET | + MAC_RGMII_MODE_TX_ENABLE | + MAC_RGMII_MODE_TX_LOWPWR | + MAC_RGMII_MODE_TX_RESET); + if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) { + if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) + val |= MAC_RGMII_MODE_RX_INT_B | + MAC_RGMII_MODE_RX_QUALITY | + MAC_RGMII_MODE_RX_ACTIVITY | + MAC_RGMII_MODE_RX_ENG_DET; + if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) + val |= MAC_RGMII_MODE_TX_ENABLE | + MAC_RGMII_MODE_TX_LOWPWR | + MAC_RGMII_MODE_TX_RESET; + } + tw32(MAC_EXT_RGMII_MODE, val); +} + +static void tg3_mdio_start(struct tg3 *tp) +{ + if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { + mutex_lock(&tp->mdio_bus.mdio_lock); + tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED; + mutex_unlock(&tp->mdio_bus.mdio_lock); + } + + tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL; + tw32_f(MAC_MI_MODE, tp->mi_mode); + udelay(80); + + if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) + tg3_mdio_config(tp); +} + +static void tg3_mdio_stop(struct tg3 *tp) +{ + if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { + mutex_lock(&tp->mdio_bus.mdio_lock); + tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_PAUSED; + mutex_unlock(&tp->mdio_bus.mdio_lock); + } +} + +static int tg3_mdio_init(struct tg3 *tp) +{ + int i; + u32 reg; + struct phy_device *phydev; + struct mii_bus *mdio_bus = &tp->mdio_bus; + + 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"; + snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%x", + (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) { + printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n", + tp->dev->name, i); + return i; + } + + tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED; + + phydev = tp->mdio_bus.phy_map[PHY_ADDR]; + + switch (phydev->phy_id) { + case TG3_PHY_ID_BCM50610: + phydev->interface = PHY_INTERFACE_MODE_RGMII; + if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) + phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE; + if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) + phydev->dev_flags |= PHY_BRCM_EXT_IBND_RX_ENABLE; + if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) + phydev->dev_flags |= PHY_BRCM_EXT_IBND_TX_ENABLE; + break; + case TG3_PHY_ID_BCMAC131: + phydev->interface = PHY_INTERFACE_MODE_MII; + break; + } + + tg3_mdio_config(tp); + + return 0; +} + +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, + phydev->dev_flags, phydev->interface); + 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); - if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { - tw32_f(MAC_MI_MODE, tp->mi_mode); - udelay(80); + 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; } +} - return ret; +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) @@ -772,35 +1427,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) @@ -983,13 +1650,12 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) return err; } -static void tg3_link_report(struct tg3 *); - /* This will reset the tigon3 PHY if there is no valid * link unless the FORCE argument is non-zero. */ static int tg3_phy_reset(struct tg3 *tp) { + u32 cpmuctrl; u32 phy_status; int err; @@ -1019,10 +1685,48 @@ 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; + + val = tr32(TG3_CPMU_LSPD_1000MB_CLK); + if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) == + CPMU_LSPD_1000MB_MACCLK_12_5) { + val &= ~CPMU_LSPD_1000MB_MACCLK_MASK; + udelay(40); + tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val); + } + + /* Disable GPHY autopowerdown. */ + tg3_writephy(tp, MII_TG3_MISC_SHDW, + MII_TG3_MISC_SHDW_WREN | + MII_TG3_MISC_SHDW_APD_SEL | + MII_TG3_MISC_SHDW_APD_WKTM_84MS); + } + + tg3_phy_apply_otp(tp); + out: if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); @@ -1124,6 +1828,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; @@ -1214,6 +1933,8 @@ static void tg3_nvram_unlock(struct tg3 *); static void tg3_power_down_phy(struct tg3 *tp) { + u32 val; + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { u32 sg_dig_ctrl = tr32(SG_DIG_CTRL); @@ -1228,14 +1949,12 @@ static void tg3_power_down_phy(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - u32 val; - tg3_bmcr_reset(tp); val = tr32(GRC_MISC_CFG); 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); @@ -1249,6 +1968,14 @@ static void tg3_power_down_phy(struct tg3 *tp) (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 && (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) return; + + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + val = tr32(TG3_CPMU_LSPD_1000MB_CLK); + val &= ~CPMU_LSPD_1000MB_MACCLK_MASK; + val |= CPMU_LSPD_1000MB_MACCLK_12_5; + tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val); + } + tg3_writephy(tp, MII_BMCR, BMCR_PDOWN); } @@ -1301,7 +2028,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; @@ -1309,18 +2036,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) { @@ -1351,8 +2115,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; @@ -1400,6 +2166,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK | CLOCK_CTRL_PWRDOWN_PLL133, 40); } else if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || + (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) { /* do nothing */ } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && @@ -1444,7 +2211,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) && - !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) + !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && + !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) tg3_power_down_phy(tp); tg3_frob_aux_power(tp); @@ -1475,102 +2243,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) { @@ -1615,7 +2287,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) @@ -1641,7 +2313,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) @@ -1650,6 +2322,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 & @@ -1669,9 +2344,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) @@ -1682,11 +2359,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; @@ -1699,7 +2372,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 && @@ -1722,7 +2399,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; @@ -1815,10 +2492,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; @@ -1832,9 +2543,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); @@ -1961,56 +2674,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; @@ -2159,6 +2851,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; @@ -2258,7 +2951,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); @@ -2399,12 +3097,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; @@ -2438,7 +3136,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 | @@ -2500,6 +3199,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; @@ -2525,7 +3225,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; @@ -2535,7 +3235,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); @@ -2545,13 +3246,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) && @@ -2566,7 +3267,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); @@ -2577,22 +3278,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 { @@ -2607,7 +3311,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 */ @@ -2643,18 +3347,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); @@ -2678,6 +3385,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; @@ -2701,9 +3410,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; @@ -2792,9 +3499,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) @@ -2810,6 +3515,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); @@ -2854,8 +3560,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; @@ -2926,8 +3631,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); @@ -2938,15 +3646,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; @@ -3041,6 +3749,23 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) err = tg3_setup_copper_phy(tp, force_reset); } + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) { + u32 val, scale; + + val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK; + if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5) + scale = 65; + else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25) + scale = 6; + else + scale = 12; + + val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK; + val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT); + tw32(GRC_MISC_CFG, val); + } + if (tp->link_config.active_speed == SPEED_1000 && tp->link_config.active_duplex == DUPLEX_HALF) tw32(MAC_TX_LENGTHS, @@ -3213,7 +3938,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. @@ -3273,7 +3998,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, @@ -3471,11 +4196,9 @@ next_pkt_nopost: return received; } -static int tg3_poll(struct net_device *netdev, int *budget) +static int tg3_poll_work(struct tg3 *tp, int work_done, int budget) { - struct tg3 *tp = netdev_priv(netdev); struct tg3_hw_status *sblk = tp->hw_status; - int done; /* handle link change and other phy events */ if (!(tp->tg3_flags & @@ -3485,7 +4208,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); } } @@ -3493,44 +4224,59 @@ static int tg3_poll(struct net_device *netdev, int *budget) /* run TX completion thread */ if (sblk->idx[0].tx_consumer != tp->tx_cons) { tg3_tx(tp); - if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) { - netif_rx_complete(netdev); - schedule_work(&tp->reset_task); - return 0; - } + if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) + return work_done; } /* run RX thread, within the bounds set by NAPI. * All RX "locking" is done by ensuring outside - * code synchronizes with dev->poll() + * code synchronizes with tg3->napi.poll() */ - if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) { - int orig_budget = *budget; - int work_done; + if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) + work_done += tg3_rx(tp, budget - work_done); - if (orig_budget > netdev->quota) - orig_budget = netdev->quota; + return work_done; +} - work_done = tg3_rx(tp, orig_budget); +static int tg3_poll(struct napi_struct *napi, int budget) +{ + struct tg3 *tp = container_of(napi, struct tg3, napi); + int work_done = 0; + struct tg3_hw_status *sblk = tp->hw_status; - *budget -= work_done; - netdev->quota -= work_done; - } + while (1) { + work_done = tg3_poll_work(tp, work_done, budget); - if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { - tp->last_tag = sblk->status_tag; - rmb(); - } else - sblk->status &= ~SD_STATUS_UPDATED; + if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) + goto tx_recovery; - /* if no more work, tell net stack and NIC we're done */ - done = !tg3_has_work(tp); - if (done) { - netif_rx_complete(netdev); - tg3_restart_ints(tp); + if (unlikely(work_done >= budget)) + break; + + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { + /* tp->last_tag is used in tg3_restart_ints() below + * to tell the hw how much work has been processed, + * so we must read it before checking for more work. + */ + tp->last_tag = sblk->status_tag; + rmb(); + } else + sblk->status &= ~SD_STATUS_UPDATED; + + if (likely(!tg3_has_work(tp))) { + netif_rx_complete(tp->dev, napi); + tg3_restart_ints(tp); + break; + } } - return (done ? 0 : 1); + return work_done; + +tx_recovery: + /* work_done is guaranteed to be less than budget. */ + netif_rx_complete(tp->dev, napi); + schedule_work(&tp->reset_task); + return work_done; } static void tg3_irq_quiesce(struct tg3 *tp) @@ -3577,7 +4323,7 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id) prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); if (likely(!tg3_irq_sync(tp))) - netif_rx_schedule(dev); /* schedule NAPI poll */ + netif_rx_schedule(dev, &tp->napi); return IRQ_HANDLED; } @@ -3602,7 +4348,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id) */ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); if (likely(!tg3_irq_sync(tp))) - netif_rx_schedule(dev); /* schedule NAPI poll */ + netif_rx_schedule(dev, &tp->napi); return IRQ_RETVAL(1); } @@ -3644,7 +4390,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id) sblk->status &= ~SD_STATUS_UPDATED; if (likely(tg3_has_work(tp))) { prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); - netif_rx_schedule(dev); /* schedule NAPI poll */ + netif_rx_schedule(dev, &tp->napi); } else { /* No work, shared interrupt perhaps? re-enable * interrupts, and flush that PCI write @@ -3690,7 +4436,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); if (tg3_irq_sync(tp)) goto out; - if (netif_rx_schedule_prep(dev)) { + if (netif_rx_schedule_prep(dev, &tp->napi)) { prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); /* Update last_tag to mark that this status has been * seen. Because interrupt may be shared, we may be @@ -3698,7 +4444,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * if tg3_poll() is not scheduled. */ tp->last_tag = sblk->status_tag; - __netif_rx_schedule(dev); + __netif_rx_schedule(dev, &tp->napi); } out: return IRQ_RETVAL(handled); @@ -3726,6 +4472,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; @@ -3737,7 +4485,7 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy) tg3_full_unlock(tp); del_timer_sync(&tp->timer); tp->irq_sync = 0; - netif_poll_enable(tp->dev); + napi_enable(&tp->napi); dev_close(tp->dev); tg3_full_lock(tp, 0); } @@ -3756,6 +4504,7 @@ static void tg3_poll_controller(struct net_device *dev) static void tg3_reset_task(struct work_struct *work) { struct tg3 *tp = container_of(work, struct tg3, reset_task); + int err; unsigned int restart_timer; tg3_full_lock(tp, 0); @@ -3767,6 +4516,8 @@ static void tg3_reset_task(struct work_struct *work) tg3_full_unlock(tp); + tg3_phy_stop(tp); + tg3_netif_stop(tp); tg3_full_lock(tp, 1); @@ -3782,7 +4533,8 @@ static void tg3_reset_task(struct work_struct *work) } 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); @@ -3792,6 +4544,9 @@ static void tg3_reset_task(struct work_struct *work) out: tg3_full_unlock(tp); + + if (!err) + tg3_phy_start(tp); } static void tg3_dump_short_state(struct tg3 *tp) @@ -3844,11 +4599,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 { @@ -3932,7 +4697,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); /* We are running in BH disabled context with netif_tx_lock - * and TX reclaim runs via tp->poll inside of a software + * and TX reclaim runs via tp->napi.poll inside of a software * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ @@ -4058,7 +4823,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 { @@ -4087,7 +4852,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); /* We are running in BH disabled context with netif_tx_lock - * and TX reclaim runs via tp->poll inside of a software + * and TX reclaim runs via tp->napi.poll inside of a software * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ @@ -4171,7 +4936,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, @@ -4283,6 +5050,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); @@ -4298,6 +5067,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; } @@ -4589,7 +5361,7 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int default: break; - }; + } } val = tr32(ofs); @@ -4732,6 +5504,80 @@ static void tg3_disable_nvram_access(struct tg3 *tp) } } +static void tg3_ape_send_event(struct tg3 *tp, u32 event) +{ + int i; + u32 apedata; + + apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); + if (apedata != APE_SEG_SIG_MAGIC) + return; + + apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); + if (apedata != APE_FW_STATUS_READY) + return; + + /* Wait for up to 1 millisecond for APE to service previous event. */ + for (i = 0; i < 10; i++) { + if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM)) + return; + + apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); + + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, + event | APE_EVENT_STATUS_EVENT_PENDING); + + tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); + + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + break; + + udelay(100); + } + + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); +} + +static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) +{ + u32 event; + u32 apedata; + + if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) + return; + + switch (kind) { + case RESET_KIND_INIT: + tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, + APE_HOST_SEG_SIG_MAGIC); + tg3_ape_write32(tp, TG3_APE_HOST_SEG_LEN, + APE_HOST_SEG_LEN_MAGIC); + apedata = tg3_ape_read32(tp, TG3_APE_HOST_INIT_COUNT); + tg3_ape_write32(tp, TG3_APE_HOST_INIT_COUNT, ++apedata); + tg3_ape_write32(tp, TG3_APE_HOST_DRIVER_ID, + APE_HOST_DRIVER_ID_MAGIC); + tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR, + APE_HOST_BEHAV_NO_PHYLOCK); + + event = APE_EVENT_STATUS_STATE_START; + break; + case RESET_KIND_SHUTDOWN: + event = APE_EVENT_STATUS_STATE_UNLOAD; + break; + case RESET_KIND_SUSPEND: + event = APE_EVENT_STATUS_STATE_SUSPEND; + break; + default: + return; + } + + event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE; + + tg3_ape_send_event(tp, event); +} + /* tp->lock is held. */ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) { @@ -4757,8 +5603,12 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) default: break; - }; + } } + + if (kind == RESET_KIND_INIT || + kind == RESET_KIND_SUSPEND) + tg3_ape_driver_state_change(tp, kind); } /* tp->lock is held. */ @@ -4778,8 +5628,11 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind) default: break; - }; + } } + + if (kind == RESET_KIND_SHUTDOWN) + tg3_ape_driver_state_change(tp, kind); } /* tp->lock is held. */ @@ -4804,7 +5657,7 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind) default: break; - }; + } } } @@ -4847,6 +5700,74 @@ static int tg3_poll_fw(struct tg3 *tp) return 0; } +/* Save PCI command register before chip reset */ +static void tg3_save_pci_state(struct tg3 *tp) +{ + pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd); +} + +/* Restore PCI state after chip reset */ +static void tg3_restore_pci_state(struct tg3 *tp) +{ + u32 val; + + /* Re-enable indirect register accesses. */ + pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, + tp->misc_host_ctrl); + + /* Set MAX PCI retry to zero. */ + val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE); + if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && + (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) + val |= PCISTATE_RETRY_SAME_DMA; + /* Allow reads and writes to the APE register and memory space. */ + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + val |= PCISTATE_ALLOW_APE_CTLSPC_WR | + PCISTATE_ALLOW_APE_SHMEM_WR; + pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); + + pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd); + + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) + pcie_set_readrq(tp->pdev, 4096); + else { + pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, + tp->pci_cacheline_sz); + pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, + tp->pci_lat_timer); + } + + /* Make sure PCI-X relaxed ordering bit is clear. */ + if (tp->pcix_cap) { + u16 pcix_cmd; + + pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD, + &pcix_cmd); + pcix_cmd &= ~PCI_X_CMD_ERO; + pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD, + pcix_cmd); + } + + if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { + + /* Chip reset on 5780 will reset MSI enable bit, + * so need to restore it. + */ + if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { + u16 ctrl; + + pci_read_config_word(tp->pdev, + tp->msi_cap + PCI_MSI_FLAGS, + &ctrl); + pci_write_config_word(tp->pdev, + tp->msi_cap + PCI_MSI_FLAGS, + ctrl | PCI_MSI_FLAGS_ENABLE); + val = tr32(MSGINT_MODE); + tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE); + } + } +} + static void tg3_stop_fw(struct tg3 *); /* tp->lock is held. */ @@ -4858,14 +5779,25 @@ 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. */ tp->nvram_lock_cnt = 0; + /* GRC_MISC_CFG core clock reset will clear the memory + * enable bit in PCI register 4 and the MSI enable bit + * on some chips, so we save relevant registers here. + */ + tg3_save_pci_state(tp); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + 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) tw32(GRC_FASTBOOT_PC, 0); /* @@ -4961,50 +5893,14 @@ static int tg3_chip_reset(struct tg3 *tp) pci_write_config_dword(tp->pdev, 0xd8, 0xf5000); } - /* Re-enable indirect register accesses. */ - pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, - tp->misc_host_ctrl); - - /* Set MAX PCI retry to zero. */ - val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE); - if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) - val |= PCISTATE_RETRY_SAME_DMA; - pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); - - pci_restore_state(tp->pdev); + tg3_restore_pci_state(tp); tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING; - /* Make sure PCI-X relaxed ordering bit is clear. */ - pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); - val &= ~PCIX_CAPS_RELAXED_ORDERING; - pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val); - - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { - u32 val; - - /* Chip reset on 5780 will reset MSI enable bit, - * so need to restore it. - */ - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { - u16 ctrl; - - pci_read_config_word(tp->pdev, - tp->msi_cap + PCI_MSI_FLAGS, - &ctrl); - pci_write_config_word(tp->pdev, - tp->msi_cap + PCI_MSI_FLAGS, - ctrl | PCI_MSI_FLAGS_ENABLE); - val = tr32(MSGINT_MODE); - tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE); - } - + val = 0; + if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) val = tr32(MEMARB_MODE); - tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); - - } else - tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); + tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) { tg3_stop_fw(tp); @@ -5014,7 +5910,7 @@ static int tg3_chip_reset(struct tg3 *tp) tw32(GRC_MODE, tp->grc_mode); if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) { - u32 val = tr32(0xc4); + val = tr32(0xc4); tw32(0xc4, val | (1 << 15)); } @@ -5037,13 +5933,15 @@ 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; if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) { - u32 val = tr32(0x7c00); + val = tr32(0x7c00); tw32(0x7c00, val | (1 << 25)); } @@ -5069,21 +5967,20 @@ static int tg3_chip_reset(struct tg3 *tp) /* tp->lock is held. */ static void tg3_stop_fw(struct tg3 *tp) { - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { + 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); } } @@ -6117,7 +7014,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); @@ -6126,14 +7024,38 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_write_sig_legacy(tp, RESET_KIND_INIT); + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) { + val = tr32(TG3_CPMU_CTRL); + val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE); + tw32(TG3_CPMU_CTRL, val); + + val = tr32(TG3_CPMU_LSPD_10MB_CLK); + val &= ~CPMU_LSPD_10MB_MACCLK_MASK; + val |= CPMU_LSPD_10MB_MACCLK_6_25; + tw32(TG3_CPMU_LSPD_10MB_CLK, val); + + val = tr32(TG3_CPMU_LNK_AWARE_PWRMD); + val &= ~CPMU_LNK_AWARE_MACCLK_MASK; + val |= CPMU_LNK_AWARE_MACCLK_6_25; + tw32(TG3_CPMU_LNK_AWARE_PWRMD, val); + + val = tr32(TG3_CPMU_HST_ACC); + val &= ~CPMU_HST_ACC_MACCLK_MASK; + val |= CPMU_HST_ACC_MACCLK_6_25; + tw32(TG3_CPMU_HST_ACC, val); + } + /* This works around an issue with Athlon chipsets on * B3 tigon3 silicon. This bit has no effect on any * other revision. But do not set this on PCI Express - * chips. + * chips and don't even touch the clocks if the CPMU is present. */ - if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) - tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT; - tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); + if (!(tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)) { + if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) + tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT; + tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); + } if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { @@ -6142,6 +7064,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3PCI_PCISTATE, val); } + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + /* Allow reads and writes to the + * APE register and memory space. + */ + val = tr32(TG3PCI_PCISTATE); + val |= PCISTATE_ALLOW_APE_CTLSPC_WR | + PCISTATE_ALLOW_APE_SHMEM_WR; + tw32(TG3PCI_PCISTATE, val); + } + if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) { /* Enable some hw fixes. */ val = tr32(TG3PCI_MSI_DATA); @@ -6158,10 +7090,14 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (err) return err; - /* This value is determined during the probe time DMA - * engine test, tg3_test_dma. - */ - tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); + 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) { + /* This value is determined during the probe time DMA + * engine test, tg3_test_dma. + */ + tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); + } tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS | GRC_MODE_4X_NIC_SEND_RINGS | @@ -6395,6 +7331,12 @@ 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 || + 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; + /* If statement applies to 5705 and 5750 PCI devices only */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) || @@ -6556,22 +7498,29 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) /* Enable host coalescing bug fix */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) - val |= (1 << 29); + (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)) + val |= WDMAC_MODE_STATUS_TAG_FIX; tw32_f(WDMAC_MODE, val); udelay(40); - if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) { - val = tr32(TG3PCI_X_CAPS); + if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { + u16 pcix_cmd; + + pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD, + &pcix_cmd); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) { - val &= ~PCIX_CAPS_BURST_MASK; - val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); + pcix_cmd &= ~PCI_X_CMD_MAX_READ; + pcix_cmd |= PCI_X_CMD_READ_2K; } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { - val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK); - val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); + pcix_cmd &= ~(PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ); + pcix_cmd |= PCI_X_CMD_READ_2K; } - tw32(TG3PCI_X_CAPS, val); + pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD, + pcix_cmd); } tw32_f(RDMAC_MODE, rdmac_mode); @@ -6580,7 +7529,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE); if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) tw32(MBFREE_MODE, MBFREE_MODE_ENABLE); - tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + tw32(SNDDATAC_MODE, + SNDDATAC_MODE_ENABLE | SNDDATAC_MODE_CDELAY); + else + tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE); + tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE); tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB); tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ); @@ -6607,23 +7562,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(100); tp->rx_mode = RX_MODE_ENABLE; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || + 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); @@ -6670,19 +7617,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); + } } } @@ -6735,7 +7691,12 @@ 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. */ + tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS, + APE_HOST_HEARTBEAT_INT_DISABLE); tg3_write_sig_post_reset(tp, RESET_KIND_INIT); @@ -6913,14 +7874,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; } @@ -7120,6 +8083,8 @@ static int tg3_open(struct net_device *dev) return err; } + napi_enable(&tp->napi); + tg3_full_lock(tp, 0); err = tg3_init_hw(tp, 1); @@ -7147,6 +8112,7 @@ static int tg3_open(struct net_device *dev) tg3_full_unlock(tp); if (err) { + napi_disable(&tp->napi); free_irq(tp->pdev->irq, dev); if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { pci_disable_msi(tp->pdev); @@ -7172,6 +8138,8 @@ static int tg3_open(struct net_device *dev) tg3_full_unlock(tp); + napi_disable(&tp->napi); + return err; } @@ -7185,6 +8153,8 @@ static int tg3_open(struct net_device *dev) } } + tg3_phy_start(tp); + tg3_full_lock(tp, 0); add_timer(&tp->timer); @@ -7433,6 +8403,7 @@ static int tg3_close(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); + napi_disable(&tp->napi); cancel_work_sync(&tp->reset_task); netif_stop_queue(dev); @@ -7860,6 +8831,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) @@ -7867,7 +8839,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; @@ -7886,10 +8859,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; @@ -7899,12 +8871,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; @@ -7914,11 +8885,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; @@ -7930,8 +8900,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; @@ -7944,10 +8915,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) @@ -7959,16 +8929,15 @@ 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; if (b_offset || odd_len) { buf = kmalloc(len, GFP_KERNEL); - if (buf == 0) + if (!buf) return -ENOMEM; if (b_offset) memcpy(buf, &start, 4); @@ -7987,7 +8956,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); @@ -8000,7 +8975,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) SUPPORTED_100baseT_Full | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_MII); + SUPPORTED_TP); cmd->port = PORT_TP; } else { cmd->supported |= SUPPORTED_FIBRE; @@ -8024,6 +8999,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 && @@ -8041,21 +9022,22 @@ 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); tp->link_config.autoneg = cmd->autoneg; if (cmd->autoneg == AUTONEG_ENABLE) { - tp->link_config.advertising = cmd->advertising; + tp->link_config.advertising = (cmd->advertising | + ADVERTISED_Autoneg); tp->link_config.speed = SPEED_INVALID; tp->link_config.duplex = DUPLEX_INVALID; } else { 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; @@ -8136,10 +9118,15 @@ static int tg3_set_tso(struct net_device *dev, u32 value) } if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) { - if (value) + if (value) { dev->features |= NETIF_F_TSO6; - else - dev->features &= ~NETIF_F_TSO6; + 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); } return ethtool_op_set_tso(dev, value); } @@ -8147,7 +9134,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)) @@ -8156,17 +9142,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; } @@ -8208,6 +9202,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; } @@ -8231,6 +9226,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; } @@ -8239,44 +9237,108 @@ 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 (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; + + 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); + } - 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); } - tg3_full_unlock(tp); - return err; } @@ -8317,7 +9379,10 @@ 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_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) ethtool_op_set_tx_ipv6_csum(dev, data); else ethtool_op_set_tx_csum(dev, data); @@ -8325,14 +9390,16 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) return 0; } -static int tg3_get_stats_count (struct net_device *dev) -{ - return TG3_NUM_STATS; -} - -static int tg3_get_test_count (struct net_device *dev) +static int tg3_get_sset_count (struct net_device *dev, int sset) { - return TG3_NUM_TEST; + switch (sset) { + case ETH_SS_TEST: + return TG3_NUM_TEST; + case ETH_SS_STATS: + return TG3_NUM_STATS; + default: + return -EOPNOTSUPP; + } } static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf) @@ -8359,7 +9426,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) @@ -8390,14 +9457,17 @@ static void tg3_get_ethtool_stats (struct net_device *dev, } #define NVRAM_TEST_SIZE 0x100 -#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14 +#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14 +#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18 +#define NVRAM_SELFBOOT_FORMAT1_3_SIZE 0x1c #define NVRAM_SELFBOOT_HW_SIZE 0x20 #define NVRAM_SELFBOOT_DATA_SIZE 0x1c static int tg3_test_nvram(struct tg3 *tp) { - u32 *buf, csum, magic; - int i, j, err = 0, size; + u32 csum, magic; + __le32 *buf; + int i, j, k, err = 0, size; if (tg3_nvram_read_swab(tp, 0, &magic) != 0) return -EIO; @@ -8405,9 +9475,22 @@ static int tg3_test_nvram(struct tg3 *tp) if (magic == TG3_EEPROM_MAGIC) size = NVRAM_TEST_SIZE; else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) { - if ((magic & 0xe00000) == 0x200000) - size = NVRAM_SELFBOOT_FORMAT1_SIZE; - else + if ((magic & TG3_EEPROM_SB_FORMAT_MASK) == + TG3_EEPROM_SB_FORMAT_1) { + switch (magic & TG3_EEPROM_SB_REVISION_MASK) { + case TG3_EEPROM_SB_REVISION_0: + size = NVRAM_SELFBOOT_FORMAT1_0_SIZE; + break; + case TG3_EEPROM_SB_REVISION_2: + size = NVRAM_SELFBOOT_FORMAT1_2_SIZE; + break; + case TG3_EEPROM_SB_REVISION_3: + size = NVRAM_SELFBOOT_FORMAT1_3_SIZE; + break; + default: + return 0; + } + } else return 0; } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) size = NVRAM_SELFBOOT_HW_SIZE; @@ -8420,22 +9503,29 @@ 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; - for (i = 0; i < size; i++) - csum8 += buf8[i]; + 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++) + csum8 += buf8[i]; + for (i = TG3_EEPROM_SB_F1R2_MBA_OFF + 4; i < size; i++) + csum8 += buf8[i]; + } else { + for (i = 0; i < size; i++) + csum8 += buf8[i]; + } if (csum8 == 0) { err = 0; @@ -8446,12 +9536,11 @@ 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]; u8 *buf8 = (u8 *) buf; - int j, k; /* Separate the parity bits and the data bytes. */ for (i = 0, j = 0, k = 0; i < NVRAM_SELFBOOT_HW_SIZE; i++) { @@ -8493,12 +9582,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; @@ -8761,7 +9850,7 @@ static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len) int i; u32 j; - for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) { + for (i = 0; i < ARRAY_SIZE(test_pattern); i++) { for (j = 0; j < len; j += 4) { u32 val; @@ -8812,7 +9901,10 @@ static int tg3_test_memory(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + 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) mem_tbl = mem_tbl_5755; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) mem_tbl = mem_tbl_5906; @@ -9009,6 +10101,7 @@ out: static int tg3_test_loopback(struct tg3 *tp) { int err = 0; + u32 cpmuctrl = 0; if (!netif_running(tp->dev)) return TG3_LOOPBACK_FAILED; @@ -9017,9 +10110,46 @@ static int tg3_test_loopback(struct tg3 *tp) if (err) return TG3_LOOPBACK_FAILED; + 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; + + tw32(TG3_CPMU_MUTEX_REQ, CPMU_MUTEX_REQ_DRIVER); + + /* Wait for up to 40 microseconds to acquire lock. */ + for (i = 0; i < 4; i++) { + status = tr32(TG3_CPMU_MUTEX_GNT); + if (status == CPMU_MUTEX_GNT_DRIVER) + break; + udelay(10); + } + + if (status != CPMU_MUTEX_GNT_DRIVER) + return TG3_LOOPBACK_FAILED; + + /* Turn off link-based power management. */ + cpmuctrl = tr32(TG3_CPMU_CTRL); + tw32(TG3_CPMU_CTRL, + cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE | + CPMU_CTRL_LINK_AWARE_MODE)); + } + if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) err |= TG3_MAC_LOOPBACK_FAILED; - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + + 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) && + !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) { if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK)) err |= TG3_PHY_LOOPBACK_FAILED; } @@ -9046,9 +10176,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; } @@ -9089,11 +10220,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); @@ -9106,6 +10241,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; @@ -9257,21 +10398,16 @@ static const struct ethtool_ops tg3_ethtool_ops = { .set_pauseparam = tg3_set_pauseparam, .get_rx_csum = tg3_get_rx_csum, .set_rx_csum = tg3_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, .set_tx_csum = tg3_set_tx_csum, - .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, .set_tso = tg3_set_tso, - .self_test_count = tg3_get_test_count, .self_test = tg3_self_test, .get_strings = tg3_get_strings, .phys_id = tg3_phys_id, - .get_stats_count = tg3_get_stats_count, .get_ethtool_stats = tg3_get_ethtool_stats, .get_coalesce = tg3_get_coalesce, .set_coalesce = tg3_set_coalesce, - .get_perm_addr = ethtool_op_get_perm_addr, + .get_sset_count = tg3_get_sset_count, }; static void __devinit tg3_get_eeprom_size(struct tg3 *tp) @@ -9327,7 +10463,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) @@ -9468,11 +10604,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: @@ -9482,11 +10621,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; } } @@ -9529,6 +10674,81 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) } } +static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) +{ + u32 nvcfg1, protect = 0; + + nvcfg1 = tr32(NVRAM_CFG1); + + /* NVRAM protection for TPM */ + if (nvcfg1 & (1 << 27)) { + tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; + protect = 1; + } + + nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK; + switch (nvcfg1) { + case FLASH_5761VENDOR_ATMEL_ADB021D: + case FLASH_5761VENDOR_ATMEL_ADB041D: + case FLASH_5761VENDOR_ATMEL_ADB081D: + case FLASH_5761VENDOR_ATMEL_ADB161D: + case FLASH_5761VENDOR_ATMEL_MDB021D: + case FLASH_5761VENDOR_ATMEL_MDB041D: + case FLASH_5761VENDOR_ATMEL_MDB081D: + case FLASH_5761VENDOR_ATMEL_MDB161D: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS; + tp->nvram_pagesize = 256; + break; + case FLASH_5761VENDOR_ST_A_M45PE20: + case FLASH_5761VENDOR_ST_A_M45PE40: + case FLASH_5761VENDOR_ST_A_M45PE80: + case FLASH_5761VENDOR_ST_A_M45PE16: + case FLASH_5761VENDOR_ST_M_M45PE20: + case FLASH_5761VENDOR_ST_M_M45PE40: + case FLASH_5761VENDOR_ST_M_M45PE80: + case FLASH_5761VENDOR_ST_M_M45PE16: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 256; + break; + } + + if (protect) { + tp->nvram_size = tr32(NVRAM_ADDR_LOCKOUT); + } else { + switch (nvcfg1) { + case FLASH_5761VENDOR_ATMEL_ADB161D: + case FLASH_5761VENDOR_ATMEL_MDB161D: + case FLASH_5761VENDOR_ST_A_M45PE16: + case FLASH_5761VENDOR_ST_M_M45PE16: + 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 = 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 = 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 = TG3_NVRAM_SIZE_256KB; + break; + } + } +} + static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp) { tp->nvram_jedecnum = JEDEC_ATMEL; @@ -9568,8 +10788,12 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) tg3_get_5752_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) tg3_get_5755_nvram_info(tp); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) 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); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tg3_get_5906_nvram_info(tp); else @@ -9647,6 +10871,7 @@ static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr) if ((tp->tg3_flags & TG3_FLAG_NVRAM) && (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && (tp->tg3_flags2 & TG3_FLG2_FLASH) && + !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) && (tp->nvram_jedecnum == JEDEC_ATMEL)) addr = ((addr / tp->nvram_pagesize) << @@ -9661,6 +10886,7 @@ static u32 tg3_nvram_logical_addr(struct tg3 *tp, u32 addr) if ((tp->tg3_flags & TG3_FLAG_NVRAM) && (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && (tp->tg3_flags2 & TG3_FLG2_FLASH) && + !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) && (tp->nvram_jedecnum == JEDEC_ATMEL)) addr = ((addr >> ATMEL_AT45DB0X1B_PAGE_POS) * @@ -9702,6 +10928,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; @@ -9719,13 +10954,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); @@ -9775,8 +11011,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) @@ -9820,10 +11056,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); @@ -9857,10 +11094,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; @@ -9881,6 +11119,9 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) && + (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)) { @@ -10051,15 +11292,19 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; tp->tg3_flags2 |= TG3_FLG2_IS_NIC; } - if (tr32(VCPU_CFGSHDW) & VCPU_CFGSHDW_ASPM_DBNC) + val = tr32(VCPU_CFGSHDW); + if (val & VCPU_CFGSHDW_ASPM_DBNC) tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND; + if ((val & VCPU_CFGSHDW_WOL_ENABLE) && + (val & VCPU_CFGSHDW_WOL_MAGPKT)) + tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; return; } tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg, led_cfg; - u32 nic_phy_id, ver, cfg2 = 0, eeprom_phy_id; + u32 nic_phy_id, ver, cfg2 = 0, cfg4 = 0, eeprom_phy_id; int eeprom_phy_serdes = 0; tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); @@ -10073,6 +11318,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) (ver > 0) && (ver < 0x100)) tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + tg3_read_mem(tp, NIC_SRAM_DATA_CFG_4, &cfg4); + if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) eeprom_phy_serdes = 1; @@ -10145,13 +11393,16 @@ 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 (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; if ((tp->pdev->subsystem_vendor == @@ -10169,10 +11420,16 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; } + if (nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) + tp->tg3_flags3 |= TG3_FLG3_ENABLE_APE; if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES && !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)) tp->tg3_flags &= ~TG3_FLAG_WOL_CAP; + if (tp->tg3_flags & TG3_FLAG_WOL_CAP && + nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE) + tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; + if (cfg2 & (1 << 17)) tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING; @@ -10188,7 +11445,63 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE) tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND; } + + if (cfg4 & NIC_SRAM_RGMII_STD_IBND_DISABLE) + tp->tg3_flags3 |= TG3_FLG3_RGMII_STD_IBND_DISABLE; + if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_RX_EN) + tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_RX_EN; + if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN) + tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_TX_EN; + } +} + +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) @@ -10197,11 +11510,15 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) 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. */ err = 0; - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { + if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || + (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { hw_phy_id = hw_phy_id_masked = PHY_ID_INVALID; } else { /* Now read the physical PHY_ID from the chip and verify @@ -10248,6 +11565,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) } if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) && + !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) && !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { u32 bmsr, adv_reg, tg3_ctrl, mask; @@ -10344,6 +11662,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, @@ -10360,8 +11679,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); } } @@ -10417,9 +11736,24 @@ out_not_found: strcpy(tp->board_part_number, "none"); } +static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset) +{ + u32 val; + + if (tg3_nvram_read_swab(tp, offset, &val) || + (val & 0xfc000000) != 0x0c000000 || + tg3_nvram_read_swab(tp, offset + 4, &val) || + val != 0) + return 0; + + return 1; +} + static void __devinit tg3_read_fw_ver(struct tg3 *tp) { u32 val, offset, start; + u32 ver_offset; + int i, bcnt; if (tg3_nvram_read_swab(tp, 0, &val)) return; @@ -10432,29 +11766,71 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) return; offset = tg3_nvram_logical_addr(tp, offset); - if (tg3_nvram_read_swab(tp, offset, &val)) + + if (!tg3_fw_img_is_valid(tp, offset) || + tg3_nvram_read_swab(tp, offset + 8, &ver_offset)) return; - if ((val & 0xfc000000) == 0x0c000000) { - u32 ver_offset, addr; - int i; + offset = offset + ver_offset - start; + for (i = 0; i < 16; i += 4) { + __le32 v; + if (tg3_nvram_read_le(tp, offset + i, &v)) + return; + + memcpy(tp->fw_ver + i, &v, 4); + } + + if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || + (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) + return; - if (tg3_nvram_read_swab(tp, offset + 4, &val) || - tg3_nvram_read_swab(tp, offset + 8, &ver_offset)) + for (offset = TG3_NVM_DIR_START; + offset < TG3_NVM_DIR_END; + offset += TG3_NVM_DIRENT_SIZE) { + if (tg3_nvram_read_swab(tp, offset, &val)) return; - if (val != 0) + if ((val >> TG3_NVM_DIRTYPE_SHIFT) == TG3_NVM_DIRTYPE_ASFINI) + break; + } + + if (offset == TG3_NVM_DIR_END) + return; + + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + start = 0x08000000; + else if (tg3_nvram_read_swab(tp, offset - 4, &start)) + return; + + if (tg3_nvram_read_swab(tp, offset + 4, &offset) || + !tg3_fw_img_is_valid(tp, offset) || + tg3_nvram_read_swab(tp, offset + 8, &val)) + return; + + offset += val - start; + + bcnt = strlen(tp->fw_ver); + + tp->fw_ver[bcnt++] = ','; + tp->fw_ver[bcnt++] = ' '; + + for (i = 0; i < 4; i++) { + __le32 v; + if (tg3_nvram_read_le(tp, offset, &v)) return; - addr = offset + ver_offset - start; - for (i = 0; i < 16; i += 4) { - if (tg3_nvram_read(tp, addr + i, &val)) - return; + offset += sizeof(v); - val = cpu_to_le32(val); - memcpy(tp->fw_ver + i, &val, 4); + if (bcnt > TG3_VER_SIZE - sizeof(v)) { + memcpy(&tp->fw_ver[bcnt], &v, TG3_VER_SIZE - bcnt); + break; } + + memcpy(&tp->fw_ver[bcnt], &v, sizeof(v)); + bcnt += sizeof(v); } + + tp->fw_ver[TG3_VER_SIZE - 1] = 0; } static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); @@ -10499,6 +11875,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pci_chip_rev_id = (misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) { + u32 prod_id_asic_rev; + + pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV, + &prod_id_asic_rev); + tp->pci_chip_rev_id = prod_id_asic_rev & PROD_ID_ASIC_REV_MASK; + } /* Wrong chip ID in 5752 A0. This code can be removed later * as A0 is not in production. @@ -10565,6 +11948,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. @@ -10618,6 +12033,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) 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_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; @@ -10637,6 +12055,9 @@ static int __devinit tg3_get_invariants(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_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; @@ -10649,17 +12070,16 @@ 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_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); if (pcie_cap != 0) { tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; + + pcie_set_readrq(tp->pdev, 4096); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { u16 lnkctl; @@ -10694,10 +12114,20 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) cacheline_sz_reg); } + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || + (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { + tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX); + if (!tp->pcix_cap) { + printk(KERN_ERR PFX "Cannot find PCI-X " + "capability, aborting.\n"); + return -EIO; + } + } + pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg); - if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) { + if (tp->pcix_cap && (pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) { tp->tg3_flags |= TG3_FLAG_PCIX_MODE; /* If this is a 5700 BX chipset, and we are in PCI-X @@ -10708,7 +12138,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) { u32 pm_reg; - u16 pci_cmd; tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; @@ -10716,11 +12145,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * space registers clobbered due to this bug. * So explicitly force the chip into D0 here. */ - pci_read_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT, + pci_read_config_dword(tp->pdev, + tp->pm_cap + PCI_PM_CTRL, &pm_reg); pm_reg &= ~PCI_PM_CTRL_STATE_MASK; pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */; - pci_write_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT, + pci_write_config_dword(tp->pdev, + tp->pm_cap + PCI_PM_CTRL, pm_reg); /* Also, force SERR#/PERR# in PCI command. */ @@ -10818,6 +12249,28 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ tg3_get_eeprom_hw_cfg(tp); + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + /* Allow reads and writes to the + * APE register and memory space. + */ + pci_state_reg |= PCISTATE_ALLOW_APE_CTLSPC_WR | + PCISTATE_ALLOW_APE_SHMEM_WR; + pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, + pci_state_reg); + } + + 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) { + tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; + + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 || + tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5761_A1) + tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES; + } + /* Set up tp->grc_local_ctrl before calling tg3_set_power_state(). * GPIO1 driven high will bring 5700's external PHY out of reset. * It is also used as eeprom write protect on LOMs. @@ -10836,6 +12289,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) { @@ -10884,24 +12346,42 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 && tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722) 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 (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); @@ -10982,6 +12462,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); @@ -11027,6 +12508,9 @@ static int __devinit tg3_get_invariants(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_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->dev->hard_start_xmit = tg3_start_xmit; else @@ -11047,11 +12531,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) tp->rx_std_max_post = 8; - /* By default, disable wake-on-lan. User can change this - * using ETHTOOL_SWOL. - */ - tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; - if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) tp->pwrmgmt_thresh = tr32(PCIE_PWR_MGMT_THRESH) & PCIE_PWR_MGMT_L1_THRESH_MSK; @@ -11152,7 +12631,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 @@ -11234,7 +12713,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: @@ -11251,7 +12730,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: @@ -11295,7 +12774,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: @@ -11648,12 +13127,14 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5780: return "5780"; case PHY_ID_BCM5755: return "5755"; case PHY_ID_BCM5787: return "5787"; + case PHY_ID_BCM5784: return "5784"; case PHY_ID_BCM5756: return "5722/5756"; case PHY_ID_BCM5906: return "5906"; + case PHY_ID_BCM5761: return "5761"; 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) @@ -11755,12 +13236,14 @@ 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; + int err, pm_cap; char str[40]; u64 dma_mask, persist_dma_mask; + DECLARE_MAC_BUF(mac); if (tg3_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -11807,7 +13290,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_free_res; } - SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); #if TG3_VLAN_TAG_USED @@ -11822,7 +13304,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 @@ -11854,7 +13336,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, INIT_WORK(&tp->reset_task, tg3_reset_task); tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len); - if (tp->regs == 0UL) { + if (!tp->regs) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); err = -ENOMEM; @@ -11874,9 +13356,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, dev->set_mac_address = tg3_set_mac_addr; dev->do_ioctl = tg3_ioctl; dev->tx_timeout = tg3_tx_timeout; - dev->poll = tg3_poll; + netif_napi_add(dev, &tp->napi, tg3_poll, 64); dev->ethtool_ops = &tg3_ethtool_ops; - dev->weight = 64; dev->watchdog_timeo = TG3_TX_TIMEOUT; dev->change_mtu = tg3_change_mtu; dev->irq = pdev->irq; @@ -11954,6 +13435,11 @@ 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 || + (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; } @@ -11971,6 +13457,28 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { + printk(KERN_ERR PFX "Cannot find proper PCI device " + "base address for APE, aborting.\n"); + err = -ENODEV; + goto err_out_iounmap; + } + + tg3reg_base = pci_resource_start(pdev, 2); + tg3reg_len = pci_resource_len(pdev, 2); + + tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len); + if (!tp->aperegs) { + printk(KERN_ERR PFX "Cannot map APE registers, " + "aborting.\n"); + err = -ENOMEM; + goto err_out_iounmap; + } + + tg3_ape_lock_init(tp); + } + /* * Reset chip in case UNDI or EFI driver did not shutdown * DMA self test will enable WDMAC and we'll see (spurious) @@ -11978,7 +13486,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, */ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { - pci_save_state(tp->pdev); tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); } @@ -11986,7 +13493,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err = tg3_test_dma(tp); if (err) { printk(KERN_ERR PFX "DMA engine test failed, aborting.\n"); - goto err_out_iounmap; + goto err_out_apeunmap; } /* Tigon3 can do ipv4 only... and some chips have buggy @@ -11995,7 +13502,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_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) dev->features |= NETIF_F_IPV6_CSUM; tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; @@ -12004,25 +13514,21 @@ 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); - /* Now that we have fully setup the chip, save away a snapshot - * of the PCI config space. We need to restore this after - * GRC_MISC_CFG core clock resets and some resume events. - */ - pci_save_state(tp->pdev); - pci_set_drvdata(pdev, dev); err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "Cannot register net device, " "aborting.\n"); - goto err_out_iounmap; + goto err_out_apeunmap; } - printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ", + printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] " + "(%s) %s Ethernet %s\n", dev->name, tp->board_part_number, tp->pci_chip_rev_id, @@ -12030,11 +13536,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_bus_string(tp, str), ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" : ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" : - "10/100/1000Base-T"))); - - for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i], - i == 5 ? '\n' : ':'); + "10/100/1000Base-T")), + print_mac(mac, dev->dev_addr)); printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] " "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n", @@ -12052,6 +13555,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, return 0; +err_out_apeunmap: + if (tp->aperegs) { + iounmap(tp->aperegs); + tp->aperegs = NULL; + } + err_out_iounmap: if (tp->regs) { iounmap(tp->regs); @@ -12078,7 +13587,17 @@ 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); + tp->aperegs = NULL; + } if (tp->regs) { iounmap(tp->regs); tp->regs = NULL; @@ -12096,10 +13615,17 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) struct tg3 *tp = netdev_priv(dev); int err; + /* PCI register 4 needs to be saved whether netif_running() or not. + * MSI address and data need to be saved if using MSI and + * netif_running(). + */ + pci_save_state(pdev); + if (!netif_running(dev)) return 0; flush_scheduled_work(); + tg3_phy_stop(tp); tg3_netif_stop(tp); del_timer_sync(&tp->timer); @@ -12115,15 +13641,15 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; tg3_full_unlock(tp); - /* Save MSI address and data for resume. */ - pci_save_state(pdev); - 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; @@ -12134,6 +13660,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; @@ -12145,11 +13674,11 @@ static int tg3_resume(struct pci_dev *pdev) struct tg3 *tp = netdev_priv(dev); int err; + pci_restore_state(tp->pdev); + if (!netif_running(dev)) return 0; - pci_restore_state(tp->pdev); - err = tg3_set_power_state(tp, PCI_D0); if (err) return err; @@ -12171,6 +13700,9 @@ static int tg3_resume(struct pci_dev *pdev) out: tg3_full_unlock(tp); + if (!err) + tg3_phy_start(tp); + return err; }