#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/brcmphy.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <asm/prom.h>
#endif
+#define BAR_0 0
+#define BAR_2 2
+
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define TG3_VLAN_TAG_USED 1
#else
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.84"
-#define DRV_MODULE_RELDATE "October 12, 2007"
+#define DRV_MODULE_VERSION "3.95"
+#define DRV_MODULE_RELDATE "November 3, 2008"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
/* minimum number of free TX descriptors required to wake up TX process */
#define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4)
+#define TG3_RAW_IP_ALIGN 2
+
/* number of ETHTOOL_GSTATS u64's */
#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
{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, TG3PCI_DEVICE_TIGON3_5761S)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
+ {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)},
return 0;
switch (locknum) {
+ case TG3_APE_LOCK_GRC:
case TG3_APE_LOCK_MEM:
break;
default:
return;
switch (locknum) {
+ case TG3_APE_LOCK_GRC:
case TG3_APE_LOCK_MEM:
break;
default:
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_5785(struct tg3 *tp)
+{
+ u32 val;
+ struct phy_device *phydev;
+
+ phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+ switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
+ case TG3_PHY_ID_BCM50610:
+ val = MAC_PHYCFG2_50610_LED_MODES;
+ break;
+ case TG3_PHY_ID_BCMAC131:
+ val = MAC_PHYCFG2_AC131_LED_MODES;
+ break;
+ case TG3_PHY_ID_RTL8211C:
+ val = MAC_PHYCFG2_RTL8211C_LED_MODES;
+ break;
+ case TG3_PHY_ID_RTL8201E:
+ val = MAC_PHYCFG2_RTL8201E_LED_MODES;
+ break;
+ default:
+ return;
+ }
+
+ if (phydev->interface != PHY_INTERFACE_MODE_RGMII) {
+ tw32(MAC_PHYCFG2, val);
+
+ val = tr32(MAC_PHYCFG1);
+ val &= ~MAC_PHYCFG1_RGMII_INT;
+ tw32(MAC_PHYCFG1, val);
+
+ return;
+ }
+
+ if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE))
+ val |= MAC_PHYCFG2_EMODE_MASK_MASK |
+ MAC_PHYCFG2_FMODE_MASK_MASK |
+ MAC_PHYCFG2_GMODE_MASK_MASK |
+ MAC_PHYCFG2_ACT_MASK_MASK |
+ MAC_PHYCFG2_QUAL_MASK_MASK |
+ MAC_PHYCFG2_INBAND_ENABLE;
+
+ tw32(MAC_PHYCFG2, val);
+
+ 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_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) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ tg3_mdio_config_5785(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;
+
+ tg3_mdio_start(tp);
+
+ if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) ||
+ (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED))
+ return 0;
+
+ tp->mdio_bus = mdiobus_alloc();
+ if (tp->mdio_bus == NULL)
+ return -ENOMEM;
+
+ tp->mdio_bus->name = "tg3 mdio bus";
+ snprintf(tp->mdio_bus->id, MII_BUS_ID_SIZE, "%x",
+ (tp->pdev->bus->number << 8) | tp->pdev->devfn);
+ tp->mdio_bus->priv = tp;
+ tp->mdio_bus->parent = &tp->pdev->dev;
+ tp->mdio_bus->read = &tg3_mdio_read;
+ tp->mdio_bus->write = &tg3_mdio_write;
+ tp->mdio_bus->reset = &tg3_mdio_reset;
+ tp->mdio_bus->phy_mask = ~(1 << PHY_ADDR);
+ tp->mdio_bus->irq = &tp->mdio_irq[0];
+
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ tp->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(tp->mdio_bus);
+ if (i) {
+ printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n",
+ tp->dev->name, i);
+ mdiobus_free(tp->mdio_bus);
+ return i;
+ }
+
+ phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+
+ if (!phydev || !phydev->drv) {
+ printk(KERN_WARNING "%s: No PHY devices\n", tp->dev->name);
+ mdiobus_unregister(tp->mdio_bus);
+ mdiobus_free(tp->mdio_bus);
+ return -ENODEV;
+ }
+
+ switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
+ case TG3_PHY_ID_BCM50610:
+ 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;
+ /* fallthru */
+ case TG3_PHY_ID_RTL8211C:
+ phydev->interface = PHY_INTERFACE_MODE_RGMII;
+ break;
+ case TG3_PHY_ID_RTL8201E:
+ case TG3_PHY_ID_BCMAC131:
+ phydev->interface = PHY_INTERFACE_MODE_MII;
+ break;
+ }
+
+ tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ tg3_mdio_config_5785(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);
+ mdiobus_free(tp->mdio_bus);
+ tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED;
+ }
+}
+
+/* tp->lock is held. */
+static inline void tg3_generate_fw_event(struct tg3 *tp)
+{
+ u32 val;
+
+ val = tr32(GRC_RX_CPU_EVENT);
+ val |= GRC_RX_CPU_DRIVER_EVENT;
+ tw32_f(GRC_RX_CPU_EVENT, val);
+
+ tp->last_event_jiffies = jiffies;
+}
+
+#define TG3_FW_EVENT_TIMEOUT_USEC 2500
+
+/* tp->lock is held. */
+static void tg3_wait_for_event_ack(struct tg3 *tp)
+{
+ int i;
+ unsigned int delay_cnt;
+ long time_remain;
+
+ /* If enough time has passed, no wait is necessary. */
+ time_remain = (long)(tp->last_event_jiffies + 1 +
+ usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) -
+ (long)jiffies;
+ if (time_remain < 0)
+ return;
+
+ /* Check if we can shorten the wait time. */
+ delay_cnt = jiffies_to_usecs(time_remain);
+ if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC)
+ delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC;
+ delay_cnt = (delay_cnt >> 3) + 1;
+
+ for (i = 0; i < delay_cnt; i++) {
+ if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
+ break;
+ udelay(8);
+ }
+}
+
+/* tp->lock is held. */
+static void tg3_ump_link_report(struct tg3 *tp)
+{
+ u32 reg;
+ u32 val;
+
+ if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
+ !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+ return;
+
+ tg3_wait_for_event_ack(tp);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
+
+ val = 0;
+ if (!tg3_readphy(tp, MII_BMCR, ®))
+ val = reg << 16;
+ if (!tg3_readphy(tp, MII_BMSR, ®))
+ val |= (reg & 0xffff);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
+
+ val = 0;
+ if (!tg3_readphy(tp, MII_ADVERTISE, ®))
+ val = reg << 16;
+ if (!tg3_readphy(tp, MII_LPA, ®))
+ val |= (reg & 0xffff);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
+
+ val = 0;
+ if (!(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) {
+ if (!tg3_readphy(tp, MII_CTRL1000, ®))
+ val = reg << 16;
+ if (!tg3_readphy(tp, MII_STAT1000, ®))
+ val |= (reg & 0xffff);
+ }
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
+
+ if (!tg3_readphy(tp, MII_PHYADDR, ®))
+ val = reg << 16;
+ else
+ val = 0;
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
+
+ tg3_generate_fw_event(tp);
+}
+
+static void tg3_link_report(struct tg3 *tp)
+{
+ if (!netif_carrier_ok(tp->dev)) {
+ if (netif_msg_link(tp))
+ printk(KERN_INFO PFX "%s: Link is down.\n",
+ tp->dev->name);
+ tg3_ump_link_report(tp);
+ } else if (netif_msg_link(tp)) {
+ printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n",
+ tp->dev->name,
+ (tp->link_config.active_speed == SPEED_1000 ?
+ 1000 :
+ (tp->link_config.active_speed == SPEED_100 ?
+ 100 : 10)),
+ (tp->link_config.active_duplex == DUPLEX_FULL ?
+ "full" : "half"));
+
+ printk(KERN_INFO PFX
+ "%s: Flow control is %s for TX and %s for RX.\n",
+ tp->dev->name,
+ (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) ?
+ "on" : "off",
+ (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) ?
+ "on" : "off");
+ tg3_ump_link_report(tp);
+ }
+}
+
+static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
+{
+ u16 miireg;
+
+ if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
+ miireg = ADVERTISE_PAUSE_CAP;
+ else if (flow_ctrl & TG3_FLOW_CTRL_TX)
+ miireg = ADVERTISE_PAUSE_ASYM;
+ else if (flow_ctrl & TG3_FLOW_CTRL_RX)
+ miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ else
+ miireg = 0;
+
+ return miireg;
+}
+
+static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
+{
+ u16 miireg;
+
+ if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
+ miireg = ADVERTISE_1000XPAUSE;
+ else if (flow_ctrl & TG3_FLOW_CTRL_TX)
+ miireg = ADVERTISE_1000XPSE_ASYM;
+ else if (flow_ctrl & TG3_FLOW_CTRL_RX)
+ miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+ else
+ miireg = 0;
+
+ return miireg;
+}
+
+static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv)
+{
+ u8 cap = 0;
+
+ if (lcladv & ADVERTISE_PAUSE_CAP) {
+ if (lcladv & ADVERTISE_PAUSE_ASYM) {
+ if (rmtadv & LPA_PAUSE_CAP)
+ cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+ else if (rmtadv & LPA_PAUSE_ASYM)
+ cap = TG3_FLOW_CTRL_RX;
+ } else {
+ if (rmtadv & LPA_PAUSE_CAP)
+ cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+ }
+ } else if (lcladv & ADVERTISE_PAUSE_ASYM) {
+ if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
+ cap = TG3_FLOW_CTRL_TX;
+ }
+
+ return cap;
+}
+
+static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
+{
+ u8 cap = 0;
+
+ if (lcladv & ADVERTISE_1000XPAUSE) {
+ if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+ if (rmtadv & LPA_1000XPAUSE)
+ cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+ else if (rmtadv & LPA_1000XPAUSE_ASYM)
+ cap = TG3_FLOW_CTRL_RX;
+ } else {
+ if (rmtadv & LPA_1000XPAUSE)
+ cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+ }
+ } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+ if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
+ cap = TG3_FLOW_CTRL_TX;
+ }
+
+ return cap;
+}
+
+static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
+{
+ u8 autoneg;
+ u8 flowctrl = 0;
+ u32 old_rx_mode = tp->rx_mode;
+ u32 old_tx_mode = tp->tx_mode;
+
+ 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 (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ if (phydev->speed == SPEED_10)
+ tw32(MAC_MI_STAT,
+ MAC_MI_STAT_10MBPS_MODE |
+ MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+ else
+ tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+ }
+
+ 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, dev_name(&phydev->dev), 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);
+ }
+
+ /* Mask with MAC supported features. */
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_GMII:
+ case PHY_INTERFACE_MODE_RGMII:
+ phydev->supported &= (PHY_GBIT_FEATURES |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ case PHY_INTERFACE_MODE_MII:
+ phydev->supported &= (PHY_BASIC_FEATURES |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ default:
+ phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]);
+ return -EINVAL;
+ }
+
+ tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED;
+
+ phydev->advertising = phydev->supported;
+
+ return 0;
+}
+
+static void tg3_phy_start(struct tg3 *tp)
+{
+ struct phy_device *phydev;
+
+ if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
+ return;
+
+ phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+
+ if (tp->link_config.phy_is_low_power) {
+ tp->link_config.phy_is_low_power = 0;
+ phydev->speed = tp->link_config.orig_speed;
+ phydev->duplex = tp->link_config.orig_duplex;
+ phydev->autoneg = tp->link_config.orig_autoneg;
+ phydev->advertising = tp->link_config.orig_advertising;
+ }
+
+ phy_start(phydev);
+
+ phy_start_aneg(phydev);
+}
+
+static void tg3_phy_stop(struct tg3 *tp)
+{
+ if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
+ return;
+
+ phy_stop(tp->mdio_bus->phy_map[PHY_ADDR]);
+}
+
+static void tg3_phy_fini(struct tg3 *tp)
+{
+ if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) {
+ phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]);
+ tp->tg3_flags3 &= ~TG3_FLG3_PHY_CONNECTED;
+ }
+}
+
+static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
+{
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
+}
+
+static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable)
+{
+ u32 reg;
- if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
- tw32_f(MAC_MI_MODE, tp->mi_mode);
- udelay(80);
- }
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+ return;
- return ret;
+ reg = MII_TG3_MISC_SHDW_WREN |
+ MII_TG3_MISC_SHDW_SCR5_SEL |
+ MII_TG3_MISC_SHDW_SCR5_LPED |
+ MII_TG3_MISC_SHDW_SCR5_DLPTLM |
+ MII_TG3_MISC_SHDW_SCR5_SDTL |
+ MII_TG3_MISC_SHDW_SCR5_C125OE;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 || !enable)
+ reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD;
+
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+
+
+ reg = MII_TG3_MISC_SHDW_WREN |
+ MII_TG3_MISC_SHDW_APD_SEL |
+ MII_TG3_MISC_SHDW_APD_WKTM_84MS;
+ if (enable)
+ reg |= MII_TG3_MISC_SHDW_APD_ENABLE;
+
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
}
static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
(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)
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;
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 (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+ GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
+ u32 val;
+
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ 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);
+ }
+ }
+
+ tg3_phy_apply_otp(tp);
+
+ if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
+ tg3_phy_toggle_apd(tp, true);
+ else
+ tg3_phy_toggle_apd(tp, false);
+
out:
if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
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;
static int tg3_nvram_lock(struct tg3 *);
static void tg3_nvram_unlock(struct tg3 *);
-static void tg3_power_down_phy(struct tg3 *tp)
+static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
{
+ 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);
}
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 (do_low_power) {
tg3_writephy(tp, MII_TG3_EXT_CTRL,
MII_TG3_EXT_CTRL_FORCE_LED_OFF);
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
+
+ tg3_writephy(tp, MII_TG3_AUX_CTRL,
+ MII_TG3_AUXCTL_SHDWSEL_PWRCTL |
+ MII_TG3_AUXCTL_PCTL_100TX_LPWR |
+ MII_TG3_AUXCTL_PCTL_SPR_ISOLATE |
+ MII_TG3_AUXCTL_PCTL_VREG_11V);
}
/* The PHY should not be powered down on some chips because
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
return;
+
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+ GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ val |= CPMU_LSPD_1000MB_MACCLK_12_5;
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
}
+/* tp->lock is held. */
+static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
+{
+ u32 addr_high, addr_low;
+ int i;
+
+ addr_high = ((tp->dev->dev_addr[0] << 8) |
+ tp->dev->dev_addr[1]);
+ addr_low = ((tp->dev->dev_addr[2] << 24) |
+ (tp->dev->dev_addr[3] << 16) |
+ (tp->dev->dev_addr[4] << 8) |
+ (tp->dev->dev_addr[5] << 0));
+ for (i = 0; i < 4; i++) {
+ if (i == 1 && skip_mac_1)
+ continue;
+ tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
+ tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ for (i = 0; i < 12; i++) {
+ tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
+ tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
+ }
+ }
+
+ addr_high = (tp->dev->dev_addr[0] +
+ tp->dev->dev_addr[1] +
+ tp->dev->dev_addr[2] +
+ tp->dev->dev_addr[3] +
+ tp->dev->dev_addr[4] +
+ tp->dev->dev_addr[5]) &
+ TX_BACKOFF_SEED_MASK;
+ tw32(MAC_TX_BACKOFF_SEED, addr_high);
+}
+
static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
{
u32 misc_host_ctrl;
- u16 power_control, power_caps;
- int pm = tp->pm_cap;
+ bool device_should_wake, do_low_power;
/* Make sure register accesses (indirect or otherwise)
* will function correctly.
TG3PCI_MISC_HOST_CTRL,
tp->misc_host_ctrl);
- pci_read_config_word(tp->pdev,
- pm + PCI_PM_CTRL,
- &power_control);
- power_control |= PCI_PM_CTRL_PME_STATUS;
- power_control &= ~(PCI_PM_CTRL_STATE_MASK);
switch (state) {
case PCI_D0:
- power_control |= 0;
- pci_write_config_word(tp->pdev,
- pm + PCI_PM_CTRL,
- power_control);
- udelay(100); /* Delay after power state change */
+ pci_enable_wake(tp->pdev, state, false);
+ pci_set_power_state(tp->pdev, PCI_D0);
/* Switch out of Vaux if it is a NIC */
if (tp->tg3_flags2 & TG3_FLG2_IS_NIC)
return 0;
case PCI_D1:
- power_control |= 1;
- break;
-
case PCI_D2:
- power_control |= 2;
- break;
-
case PCI_D3hot:
- power_control |= 3;
break;
default:
- printk(KERN_WARNING PFX "%s: Invalid power state (%d) "
- "requested.\n",
- tp->dev->name, state);
+ printk(KERN_ERR PFX "%s: Invalid power state (D%d) requested\n",
+ tp->dev->name, state);
return -EINVAL;
- };
+ }
+
+ /* Restore the CLKREQ setting. */
+ if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
+ u16 lnkctl;
- power_control |= PCI_PM_CTRL_PME_ENABLE;
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &lnkctl);
+ lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ lnkctl);
+ }
misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
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;
- }
+ device_should_wake = pci_pme_capable(tp->pdev, state) &&
+ device_may_wakeup(&tp->pdev->dev) &&
+ (tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
+
+ if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+ do_low_power = false;
+ if ((tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) &&
+ !tp->link_config.phy_is_low_power) {
+ struct phy_device *phydev;
+ u32 phyid, 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) ||
+ device_should_wake) {
+ 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);
+
+ phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
+ if (phyid != TG3_PHY_ID_BCMAC131) {
+ phyid &= TG3_PHY_OUI_MASK;
+ if (phyid == TG3_PHY_OUI_1 &&
+ phyid == TG3_PHY_OUI_2 &&
+ phyid == TG3_PHY_OUI_3)
+ do_low_power = true;
+ }
+ }
+ } else {
+ do_low_power = false;
+
+ 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);
+ }
}
+ __tg3_set_mac_addr(tp, 0);
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
u32 val;
WOL_DRV_WOL |
WOL_SET_MAGIC_PKT);
- pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
-
- if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
+ if (device_should_wake) {
u32 mac_mode;
if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
- udelay(40);
+ if (do_low_power) {
+ 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;
if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
tw32(MAC_LED_CTRL, tp->led_ctrl);
- if (((power_caps & PCI_PM_CAP_PME_D3cold) &&
- (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)))
- mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
+ mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
+ if (((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+ !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) &&
+ ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+ (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)))
+ mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL;
+
+ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+ mac_mode |= tp->mac_mode &
+ (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
+ if (mac_mode & MAC_MODE_APE_TX_EN)
+ mac_mode |= MAC_MODE_TDE_ENABLE;
+ }
tw32_f(MAC_MODE, mac_mode);
udelay(100);
}
}
- if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
+ if (!(device_should_wake) &&
!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
- tg3_power_down_phy(tp);
+ tg3_power_down_phy(tp, do_low_power);
tg3_frob_aux_power(tp);
tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+ if (device_should_wake)
+ pci_enable_wake(tp->pdev, state, true);
+
/* Finally, set the new power state. */
- pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
- udelay(100); /* Delay after power state change */
+ pci_set_power_state(tp->pdev, 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) {
*speed = SPEED_INVALID;
*duplex = DUPLEX_INVALID;
break;
- };
+ }
}
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)
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 &
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)
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;
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 &&
case SPEED_1000:
bmcr |= TG3_BMCR_SPEED1000;
break;
- };
+ }
if (tp->link_config.duplex == DUPLEX_FULL)
bmcr |= BMCR_FULLDPLX;
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;
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);
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) &&
- (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);
+ }
}
+
+ if (current_link_up == 1 &&
+ tp->link_config.active_duplex == DUPLEX_FULL)
+ tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
}
+
relink:
if (current_link_up == 0 || tp->link_config.phy_is_low_power) {
u32 tmp;
NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
}
+ /* Prevent send BD corruption. */
+ if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
+ u16 oldlnkctl, newlnkctl;
+
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &oldlnkctl);
+ if (tp->link_config.active_speed == SPEED_100 ||
+ tp->link_config.active_speed == SPEED_10)
+ newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
+ else
+ newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
+ if (newlnkctl != oldlnkctl)
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ newlnkctl);
+ }
+
if (current_link_up != netif_carrier_ok(tp->dev)) {
if (current_link_up)
netif_carrier_on(tp->dev);
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;
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);
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;
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 |
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;
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;
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);
}
/* 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) &&
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);
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 {
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 */
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);
!(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;
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;
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)
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);
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;
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);
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;
err = tg3_setup_copper_phy(tp, force_reset);
}
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) {
+ u32 val, scale;
+
+ val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
+ 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,
return;
}
- pci_unmap_single(tp->pdev,
- pci_unmap_addr(ri, mapping),
- skb_headlen(skb),
- PCI_DMA_TODEVICE);
+ skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
ri->skb = NULL;
ri = &tp->tx_buffers[sw_idx];
if (unlikely(ri->skb != NULL || sw_idx == hw_idx))
tx_bug = 1;
-
- pci_unmap_page(tp->pdev,
- pci_unmap_addr(ri, mapping),
- skb_shinfo(skb)->frags[i].size,
- PCI_DMA_TODEVICE);
-
sw_idx = NEXT_TX(sw_idx);
}
default:
return -EINVAL;
- };
+ }
/* Do not overwrite any of the map or rp information
* until we are sure we can commit to a new buffer.
default:
return;
- };
+ }
dest_map->skb = src_map->skb;
pci_unmap_addr_set(dest_map, mapping,
goto next_pkt;
}
- len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */
+ len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) -
+ ETH_FCS_LEN;
if (len > RX_COPY_THRESHOLD
- && tp->rx_offset == 2
- /* rx_offset != 2 iff this is a 5701 card running
- * in PCI-X mode [see tg3_get_invariants()] */
+ && tp->rx_offset == NET_IP_ALIGN
+ /* rx_offset will likely not equal NET_IP_ALIGN
+ * if this is a 5701 card running in PCI-X mode
+ * [see tg3_get_invariants()]
+ */
) {
int skb_size;
tg3_recycle_rx(tp, opaque_key,
desc_idx, *post_ptr);
- copy_skb = netdev_alloc_skb(tp->dev, len + 2);
+ copy_skb = netdev_alloc_skb(tp->dev,
+ len + TG3_RAW_IP_ALIGN);
if (copy_skb == NULL)
goto drop_it_no_recycle;
- skb_reserve(copy_skb, 2);
+ skb_reserve(copy_skb, TG3_RAW_IP_ALIGN);
skb_put(copy_skb, len);
pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
skb_copy_from_linear_data(skb, copy_skb->data, len);
#endif
netif_receive_skb(skb);
- tp->dev->last_rx = jiffies;
received++;
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);
}
}
* Invoked with tp->lock held.
*/
static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
+ __releases(tp->lock)
+ __acquires(tp->lock)
{
int err;
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);
tg3_full_unlock(tp);
+ tg3_phy_stop(tp);
+
tg3_netif_stop(tp);
tg3_full_lock(tp, 1);
}
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);
out:
tg3_full_unlock(tp);
+
+ if (!err)
+ tg3_phy_start(tp);
}
static void tg3_dump_short_state(struct tg3 *tp)
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 {
/* New SKB is guaranteed to be linear. */
entry = *start;
- new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
- PCI_DMA_TODEVICE);
+ ret = skb_dma_map(&tp->pdev->dev, new_skb, DMA_TO_DEVICE);
+ new_addr = skb_shinfo(new_skb)->dma_maps[0];
+
/* Make sure new skb does not cross any 4G boundaries.
* Drop the packet if it does.
*/
- if (tg3_4g_overflow_test(new_addr, new_skb->len)) {
+ if (ret || tg3_4g_overflow_test(new_addr, new_skb->len)) {
+ if (!ret)
+ skb_dma_unmap(&tp->pdev->dev, new_skb,
+ DMA_TO_DEVICE);
ret = -1;
dev_kfree_skb(new_skb);
new_skb = NULL;
/* Now clean up the sw ring entries. */
i = 0;
while (entry != last_plus_one) {
- int len;
-
- if (i == 0)
- len = skb_headlen(skb);
- else
- len = skb_shinfo(skb)->frags[i-1].size;
- pci_unmap_single(tp->pdev,
- pci_unmap_addr(&tp->tx_buffers[entry], mapping),
- len, PCI_DMA_TODEVICE);
if (i == 0) {
tp->tx_buffers[entry].skb = new_skb;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, new_addr);
} else {
tp->tx_buffers[entry].skb = NULL;
}
i++;
}
+ skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
dev_kfree_skb(skb);
return ret;
static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
- dma_addr_t mapping;
u32 len, entry, base_flags, mss;
+ struct skb_shared_info *sp;
+ dma_addr_t mapping;
len = skb_headlen(skb);
(vlan_tx_tag_get(skb) << 16));
#endif
- /* Queue skb data, a.k.a. the main skb fragment. */
- mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (skb_dma_map(&tp->pdev->dev, skb, DMA_TO_DEVICE)) {
+ dev_kfree_skb(skb);
+ goto out_unlock;
+ }
+
+ sp = skb_shinfo(skb);
+
+ mapping = sp->dma_maps[0];
tp->tx_buffers[entry].skb = skb;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
tg3_set_txd(tp, entry, mapping, len, base_flags,
(skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
len = frag->size;
- mapping = pci_map_page(tp->pdev,
- frag->page,
- frag->page_offset,
- len, PCI_DMA_TODEVICE);
-
+ mapping = sp->dma_maps[i + 1];
tp->tx_buffers[entry].skb = NULL;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
tg3_set_txd(tp, entry, mapping, len,
base_flags, (i == last) | (mss << 1));
}
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 {
static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
- dma_addr_t mapping;
u32 len, entry, base_flags, mss;
+ struct skb_shared_info *sp;
int would_hit_hwbug;
+ dma_addr_t mapping;
len = skb_headlen(skb);
(vlan_tx_tag_get(skb) << 16));
#endif
- /* Queue skb data, a.k.a. the main skb fragment. */
- mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (skb_dma_map(&tp->pdev->dev, skb, DMA_TO_DEVICE)) {
+ dev_kfree_skb(skb);
+ goto out_unlock;
+ }
+
+ sp = skb_shinfo(skb);
+
+ mapping = sp->dma_maps[0];
tp->tx_buffers[entry].skb = skb;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
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,
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
len = frag->size;
- mapping = pci_map_page(tp->pdev,
- frag->page,
- frag->page_offset,
- len, PCI_DMA_TODEVICE);
+ mapping = sp->dma_maps[i + 1];
tp->tx_buffers[entry].skb = NULL;
- pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
if (tg3_4g_overflow_test(mapping, len))
would_hit_hwbug = 1;
return 0;
}
+ tg3_phy_stop(tp);
+
tg3_netif_stop(tp);
tg3_full_lock(tp, 1);
tg3_full_unlock(tp);
+ if (!err)
+ tg3_phy_start(tp);
+
return err;
}
for (i = 0; i < TG3_TX_RING_SIZE; ) {
struct tx_ring_info *txp;
struct sk_buff *skb;
- int j;
txp = &tp->tx_buffers[i];
skb = txp->skb;
continue;
}
- pci_unmap_single(tp->pdev,
- pci_unmap_addr(txp, mapping),
- skb_headlen(skb),
- PCI_DMA_TODEVICE);
- txp->skb = NULL;
+ skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
- i++;
+ txp->skb = NULL;
- for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) {
- txp = &tp->tx_buffers[i & (TG3_TX_RING_SIZE - 1)];
- pci_unmap_page(tp->pdev,
- pci_unmap_addr(txp, mapping),
- skb_shinfo(skb)->frags[j].size,
- PCI_DMA_TODEVICE);
- i++;
- }
+ i += skb_shinfo(skb)->nr_frags + 1;
dev_kfree_skb_any(skb);
}
default:
break;
- };
+ }
}
val = tr32(ofs);
return;
apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
- if (apedata != APE_FW_STATUS_READY)
+ if (!(apedata & APE_FW_STATUS_READY))
return;
/* Wait for up to 1 millisecond for APE to service previous event. */
event = APE_EVENT_STATUS_STATE_START;
break;
case RESET_KIND_SHUTDOWN:
+ /* With the interface we are currently using,
+ * APE does not track driver state. Wiping
+ * out the HOST SEGMENT SIGNATURE forces
+ * the APE to assume OS absent status.
+ */
+ tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);
+
event = APE_EVENT_STATUS_STATE_UNLOAD;
break;
case RESET_KIND_SUSPEND:
default:
break;
- };
+ }
}
if (kind == RESET_KIND_INIT ||
default:
break;
- };
+ }
}
if (kind == RESET_KIND_SHUTDOWN)
default:
break;
- };
+ }
}
}
/* Save PCI command register before chip reset */
static void tg3_save_pci_state(struct tg3 *tp)
{
- u32 val;
-
- pci_read_config_dword(tp->pdev, TG3PCI_COMMAND, &val);
- tp->pci_cmd = val;
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
}
/* Restore PCI state after chip reset */
PCISTATE_ALLOW_APE_SHMEM_WR;
pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
- pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
+ pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
- if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
- 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);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
+ 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) {
+ if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
u16 pcix_cmd;
pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
tg3_nvram_lock(tp);
+ tg3_mdio_stop(tp);
+
+ tg3_ape_lock(tp, TG3_APE_LOCK_GRC);
+
/* No matching tg3_nvram_unlock() after this because
* chip reset below will undo the nvram lock.
*/
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
tw32(GRC_FASTBOOT_PC, 0);
/*
udelay(120);
- if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+ if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pcie_cap) {
if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
int i;
u32 cfg_val;
pci_write_config_dword(tp->pdev, 0xc4,
cfg_val | (1 << 15));
}
- /* Set PCIE max payload size and clear error status. */
- pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
+
+ /* Set PCIE max payload size to 128 bytes and
+ * clear the "no snoop" and "relaxed ordering" bits.
+ */
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVCTL,
+ 0);
+
+ pcie_set_readrq(tp->pdev, 4096);
+
+ /* Clear error status */
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVSTA,
+ PCI_EXP_DEVSTA_CED |
+ PCI_EXP_DEVSTA_NFED |
+ PCI_EXP_DEVSTA_FED |
+ PCI_EXP_DEVSTA_URD);
}
tg3_restore_pci_state(tp);
} else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
tw32_f(MAC_MODE, tp->mac_mode);
+ } else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+ tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
+ if (tp->mac_mode & MAC_MODE_APE_TX_EN)
+ tp->mac_mode |= MAC_MODE_TDE_ENABLE;
+ tw32_f(MAC_MODE, tp->mac_mode);
} else
tw32_f(MAC_MODE, 0);
udelay(40);
+ tg3_mdio_start(tp);
+
+ tg3_ape_unlock(tp, TG3_APE_LOCK_GRC);
+
err = tg3_poll_fw(tp);
if (err)
return err;
tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
+ tp->last_event_jiffies = jiffies;
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
}
{
if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
- u32 val;
- int i;
+ /* Wait for RX cpu to ACK the previous event. */
+ tg3_wait_for_event_ack(tp);
tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
- val = tr32(GRC_RX_CPU_EVENT);
- val |= (1 << 14);
- tw32(GRC_RX_CPU_EVENT, val);
- /* Wait for RX cpu to ACK the event. */
- for (i = 0; i < 100; i++) {
- if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14)))
- break;
- udelay(1);
- }
+ tg3_generate_fw_event(tp);
+
+ /* Wait for RX cpu to ACK this event. */
+ tg3_wait_for_event_ack(tp);
}
}
}
-/* tp->lock is held. */
-static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
-{
- u32 addr_high, addr_low;
- int i;
-
- addr_high = ((tp->dev->dev_addr[0] << 8) |
- tp->dev->dev_addr[1]);
- addr_low = ((tp->dev->dev_addr[2] << 24) |
- (tp->dev->dev_addr[3] << 16) |
- (tp->dev->dev_addr[4] << 8) |
- (tp->dev->dev_addr[5] << 0));
- for (i = 0; i < 4; i++) {
- if (i == 1 && skip_mac_1)
- continue;
- tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
- tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
- }
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
- for (i = 0; i < 12; i++) {
- tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
- tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
- }
- }
-
- addr_high = (tp->dev->dev_addr[0] +
- tp->dev->dev_addr[1] +
- tp->dev->dev_addr[2] +
- tp->dev->dev_addr[3] +
- tp->dev->dev_addr[4] +
- tp->dev->dev_addr[5]) &
- TX_BACKOFF_SEED_MASK;
- tw32(MAC_TX_BACKOFF_SEED, addr_high);
-}
-
static int tg3_set_mac_addr(struct net_device *dev, void *p)
{
struct tg3 *tp = netdev_priv(dev);
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);
tg3_write_sig_legacy(tp, RESET_KIND_INIT);
- if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) {
val = tr32(TG3_CPMU_CTRL);
val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
tw32(TG3_CPMU_CTRL, val);
+
+ 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
RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
RDMAC_MODE_LNGREAD_ENAB);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB |
RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
RDMAC_MODE_MBUF_SBD_CRPT_ENAB;
udelay(10);
}
- tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
+ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+ tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+ else
+ tp->mac_mode = 0;
+ tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761))
- val |= (1 << 29);
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785))
+ val |= WDMAC_MODE_STATUS_TAG_FIX;
tw32_f(WDMAC_MODE, val);
udelay(40);
tp->rx_mode = RX_MODE_ENABLE;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
tw32_f(MAC_RX_MODE, tp->rx_mode);
udelay(10);
- if (tp->link_config.phy_is_low_power) {
- tp->link_config.phy_is_low_power = 0;
- tp->link_config.speed = tp->link_config.orig_speed;
- tp->link_config.duplex = tp->link_config.orig_duplex;
- tp->link_config.autoneg = tp->link_config.orig_autoneg;
- }
-
- tp->mi_mode = MAC_MI_MODE_BASE;
- tw32_f(MAC_MI_MODE, tp->mi_mode);
- udelay(80);
-
tw32(MAC_LED_CTRL, tp->led_ctrl);
tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
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);
+ }
}
}
default:
break;
- };
+ }
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
/* Write our heartbeat update interval to APE. */
*/
static int tg3_init_hw(struct tg3 *tp, int reset_phy)
{
- int err;
-
- /* Force the chip into D0. */
- err = tg3_set_power_state(tp, PCI_D0);
- if (err)
- goto out;
-
tg3_switch_clocks(tp);
tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
- err = tg3_reset_hw(tp, reset_phy);
-
-out:
- return err;
+ return tg3_reset_hw(tp, reset_phy);
}
#define TG3_STAT_ADD32(PSTAT, REG) \
* resets.
*/
if (!--tp->asf_counter) {
- if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
- u32 val;
+ if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
+ !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
+ tg3_wait_for_event_ack(tp);
tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
FWCMD_NICDRV_ALIVE3);
tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
/* 5 seconds timeout */
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
- val = tr32(GRC_RX_CPU_EVENT);
- val |= (1 << 14);
- tw32(GRC_RX_CPU_EVENT, val);
+
+ tg3_generate_fw_event(tp);
}
tp->asf_counter = tp->asf_multiplier;
}
netif_carrier_off(tp->dev);
- tg3_full_lock(tp, 0);
-
err = tg3_set_power_state(tp, PCI_D0);
- if (err) {
- tg3_full_unlock(tp);
+ if (err)
return err;
- }
+
+ tg3_full_lock(tp, 0);
tg3_disable_ints(tp);
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
} else if (pci_enable_msi(tp->pdev) == 0) {
u32 msi_mode;
- /* Hardware bug - MSI won't work if INTX disabled. */
- if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
- pci_intx(tp->pdev, 1);
-
msi_mode = tr32(MSGINT_MODE);
tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
}
}
+ tg3_phy_start(tp);
+
tg3_full_lock(tp, 0);
add_timer(&tp->timer);
return ret;
}
+static inline u64 get_estat64(tg3_stat64_t *val)
+{
+ return ((u64)val->high << 32) | ((u64)val->low);
+}
+
static unsigned long calc_crc_errors(struct tg3 *tp)
{
struct tg3_hw_stats *hw_stats = tp->hw_stats;
#define ESTAT_ADD(member) \
estats->member = old_estats->member + \
- get_stat64(&hw_stats->member)
+ get_estat64(&hw_stats->member)
static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
{
}
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)
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;
/* 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;
/* 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;
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;
{
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;
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)
/* 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;
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);
SUPPORTED_100baseT_Full |
SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
- SUPPORTED_MII);
+ SUPPORTED_TP);
cmd->port = PORT_TP;
} else {
cmd->supported |= SUPPORTED_FIBRE;
{
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 &&
(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.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;
{
struct tg3 *tp = netdev_priv(dev);
- if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+ if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) &&
+ device_can_wakeup(&tp->pdev->dev))
wol->supported = WAKE_MAGIC;
else
wol->supported = 0;
wol->wolopts = 0;
- if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
+ if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
+ device_can_wakeup(&tp->pdev->dev))
wol->wolopts = WAKE_MAGIC;
memset(&wol->sopass, 0, sizeof(wol->sopass));
}
static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct tg3 *tp = netdev_priv(dev);
+ struct device *dp = &tp->pdev->dev;
if (wol->wolopts & ~WAKE_MAGIC)
return -EINVAL;
if ((wol->wolopts & WAKE_MAGIC) &&
- !(tp->tg3_flags & TG3_FLAG_WOL_CAP))
+ !((tp->tg3_flags & TG3_FLAG_WOL_CAP) && device_can_wakeup(dp)))
return -EINVAL;
spin_lock_bh(&tp->lock);
- if (wol->wolopts & WAKE_MAGIC)
+ if (wol->wolopts & WAKE_MAGIC) {
tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
- else
+ device_set_wakeup_enable(dp, true);
+ } else {
tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
+ device_set_wakeup_enable(dp, false);
+ }
spin_unlock_bh(&tp->lock);
return 0;
(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) {
if (value) {
dev->features |= NETIF_F_TSO6;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
dev->features |= NETIF_F_TSO_ECN;
} else
dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
static int tg3_nway_reset(struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
- u32 bmcr;
int r;
if (!netif_running(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;
}
return -EINVAL;
if (netif_running(dev)) {
+ tg3_phy_stop(tp);
tg3_netif_stop(tp);
irq_sync = 1;
}
tg3_full_unlock(tp);
+ if (irq_sync && !err)
+ tg3_phy_start(tp);
+
return err;
}
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;
+
+ if (epause->autoneg) {
+ u32 newadv;
+ struct phy_device *phydev;
+
+ 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);
- 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 (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;
+ 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;
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
ethtool_op_set_tx_ipv6_csum(dev, data);
else
ethtool_op_set_tx_csum(dev, data);
return -EAGAIN;
if (data == 0)
- data = 2;
+ data = UINT_MAX / 2;
for (i = 0; i < (data * 2); i++) {
if ((i % 2) == 0)
}
#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;
+ u32 csum, magic;
+ __le32 *buf;
int i, j, k, err = 0, size;
if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
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;
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;
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];
/* 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;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
mem_tbl = mem_tbl_5755;
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
mem_tbl = mem_tbl_5906;
if (err)
return TG3_LOOPBACK_FAILED;
- if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+ /* Turn off gphy autopowerdown. */
+ if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
+ tg3_phy_toggle_apd(tp, false);
+
+ 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;
if (status != CPMU_MUTEX_GNT_DRIVER)
return TG3_LOOPBACK_FAILED;
+ /* Turn off link-based power management. */
cpmuctrl = tr32(TG3_CPMU_CTRL);
-
- /* Turn off power management based on link speed. */
tw32(TG3_CPMU_CTRL,
- cpmuctrl & ~CPMU_CTRL_LINK_SPEED_MODE);
+ 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_flags & TG3_FLAG_CPMU_PRESENT) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
tw32(TG3_CPMU_CTRL, cpmuctrl);
/* Release the mutex */
tw32(TG3_CPMU_MUTEX_GNT, CPMU_MUTEX_GNT_DRIVER);
}
- if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+ !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) {
if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK))
err |= TG3_PHY_LOOPBACK_FAILED;
}
+ /* Re-enable gphy autopowerdown. */
+ if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
+ tg3_phy_toggle_apd(tp, true);
+
return err;
}
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;
}
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);
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;
return;
}
}
- tp->nvram_size = 0x80000;
+ tp->nvram_size = TG3_NVRAM_SIZE_512KB;
}
static void __devinit tg3_get_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:
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;
}
}
case FLASH_5761VENDOR_ATMEL_MDB161D:
case FLASH_5761VENDOR_ST_A_M45PE16:
case FLASH_5761VENDOR_ST_M_M45PE16:
- tp->nvram_size = 0x100000;
+ tp->nvram_size = TG3_NVRAM_SIZE_2MB;
break;
case FLASH_5761VENDOR_ATMEL_ADB081D:
case FLASH_5761VENDOR_ATMEL_MDB081D:
case FLASH_5761VENDOR_ST_A_M45PE80:
case FLASH_5761VENDOR_ST_M_M45PE80:
- tp->nvram_size = 0x80000;
+ tp->nvram_size = TG3_NVRAM_SIZE_1MB;
break;
case FLASH_5761VENDOR_ATMEL_ADB041D:
case FLASH_5761VENDOR_ATMEL_MDB041D:
case FLASH_5761VENDOR_ST_A_M45PE40:
case FLASH_5761VENDOR_ST_M_M45PE40:
- tp->nvram_size = 0x40000;
+ tp->nvram_size = TG3_NVRAM_SIZE_512KB;
break;
case FLASH_5761VENDOR_ATMEL_ADB021D:
case FLASH_5761VENDOR_ATMEL_MDB021D:
case FLASH_5761VENDOR_ST_A_M45PE20:
case FLASH_5761VENDOR_ST_M_M45PE20:
- tp->nvram_size = 0x20000;
+ tp->nvram_size = TG3_NVRAM_SIZE_256KB;
break;
}
}
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
tg3_get_5755_nvram_info(tp);
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
tg3_get_5787_nvram_info(tp);
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
tg3_get_5761_nvram_info(tp);
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;
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);
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)
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);
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;
(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)) {
if (val & VCPU_CFGSHDW_ASPM_DBNC)
tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
if ((val & VCPU_CFGSHDW_WOL_ENABLE) &&
- (val & VCPU_CFGSHDW_WOL_MAGPKT))
+ (val & VCPU_CFGSHDW_WOL_MAGPKT) &&
+ device_may_wakeup(&tp->pdev->dev))
tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
- return;
+ goto done;
}
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);
(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;
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 ==
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)
+
+ if ((nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) &&
+ (tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
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)
+ 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))
if (cfg2 & (1 << 18))
tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX &&
+ (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN))
+ tp->tg3_flags3 |= TG3_FLG3_PHY_ENABLE_APD;
+
if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
u32 cfg3;
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;
+ }
+done:
+ device_init_wakeup(&tp->pdev->dev, tp->tg3_flags & TG3_FLAG_WOL_CAP);
+ device_set_wakeup_enable(&tp->pdev->dev,
+ tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
+}
+
+static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+{
+ int i;
+ u32 val;
+
+ tw32(OTP_CTRL, cmd | OTP_CTRL_OTP_CMD_START);
+ tw32(OTP_CTRL, cmd);
+
+ /* Wait for up to 1 ms for command to execute. */
+ for (i = 0; i < 100; i++) {
+ val = tr32(OTP_STATUS);
+ if (val & OTP_STATUS_CMD_DONE)
+ break;
+ udelay(10);
}
+
+ return (val & OTP_STATUS_CMD_DONE) ? 0 : -EBUSY;
+}
+
+/* Read the gphy configuration from the OTP region of the chip. The gphy
+ * configuration is a 32-bit value that straddles the alignment boundary.
+ * We do two 32-bit reads and then shift and merge the results.
+ */
+static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
+{
+ u32 bhalf_otp, thalf_otp;
+
+ tw32(OTP_MODE, OTP_MODE_OTP_THRU_GRC);
+
+ if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_INIT))
+ return 0;
+
+ tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC1);
+
+ if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+ return 0;
+
+ thalf_otp = tr32(OTP_READ_DATA);
+
+ tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC2);
+
+ if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+ return 0;
+
+ bhalf_otp = tr32(OTP_READ_DATA);
+
+ return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
}
static int __devinit tg3_phy_probe(struct tg3 *tp)
u32 hw_phy_id, 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.
*/
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,
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);
}
}
offset = offset + ver_offset - start;
for (i = 0; i < 16; i += 4) {
- if (tg3_nvram_read(tp, offset + i, &val))
+ __le32 v;
+ if (tg3_nvram_read_le(tp, offset + i, &v))
return;
- val = le32_to_cpu(val);
- memcpy(tp->fw_ver + i, &val, 4);
+ memcpy(tp->fw_ver + i, &v, 4);
}
if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
- (tp->tg3_flags & TG3_FLG3_ENABLE_APE))
+ (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
return;
for (offset = TG3_NVM_DIR_START;
tp->fw_ver[bcnt++] = ' ';
for (i = 0; i < 4; i++) {
- if (tg3_nvram_read(tp, offset, &val))
+ __le32 v;
+ if (tg3_nvram_read_le(tp, offset, &v))
return;
- val = le32_to_cpu(val);
- offset += sizeof(val);
+ offset += sizeof(v);
- if (bcnt > TG3_VER_SIZE - sizeof(val)) {
- memcpy(&tp->fw_ver[bcnt], &val, TG3_VER_SIZE - bcnt);
+ if (bcnt > TG3_VER_SIZE - sizeof(v)) {
+ memcpy(&tp->fw_ver[bcnt], &v, TG3_VER_SIZE - bcnt);
break;
}
- memcpy(&tp->fw_ver[bcnt], &val, sizeof(val));
- bcnt += sizeof(val);
+ memcpy(&tp->fw_ver[bcnt], &v, sizeof(v));
+ bcnt += sizeof(v);
}
tp->fw_ver[TG3_VER_SIZE - 1] = 0;
u32 pci_state_reg, grc_misc_cfg;
u32 val;
u16 pci_cmd;
- int err, pcie_cap;
+ int err;
/* Force memory write invalidate off. If we leave it on,
* then on 5700_BX chips we have to enable a workaround.
}
}
+ 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.
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;
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;
}
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+ (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
- pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
- if (pcie_cap != 0) {
+ pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
+ &pci_state_reg);
+
+ tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
+ if (tp->pcie_cap != 0) {
+ u16 lnkctl;
+
tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- u16 lnkctl;
- pci_read_config_word(tp->pdev,
- pcie_cap + PCI_EXP_LNKCTL,
- &lnkctl);
- if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN)
+ pcie_set_readrq(tp->pdev, 4096);
+
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &lnkctl);
+ if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG;
+ }
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+ } else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+ (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+ tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
+ if (!tp->pcix_cap) {
+ printk(KERN_ERR PFX "Cannot find PCI-X "
+ "capability, aborting.\n");
+ return -EIO;
}
+
+ if (!(pci_state_reg & PCISTATE_CONV_PCI_MODE))
+ tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
}
/* If we have an AMD 762 or VIA K8T800 chipset, write
cacheline_sz_reg);
}
- if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
- (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
- tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
- if (!tp->pcix_cap) {
- printk(KERN_ERR PFX "Cannot find PCI-X "
- "capability, aborting.\n");
- return -EIO;
- }
- }
-
- pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
- &pci_state_reg);
-
- if (tp->pcix_cap && (pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
- tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
+ /* 5700 BX chips need to have their TX producer index
+ * mailboxes written twice to workaround a bug.
+ */
+ tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
- /* If this is a 5700 BX chipset, and we are in PCI-X
- * mode, enable register write workaround.
+ /* If we are in PCI-X mode, enable register write workaround.
*
* The workaround is to use indirect register accesses
* for all chip writes not to mailbox registers.
*/
- if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
+ if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
u32 pm_reg;
tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
}
}
- /* 5700 BX chips need to have their TX producer index mailboxes
- * written twice to workaround a bug.
- */
- if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
- tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
-
if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
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) {
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);
tp->misc_host_ctrl);
}
+ /* Preserve the APE MAC_MODE bits */
+ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+ tp->mac_mode = tr32(MAC_MODE) |
+ MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+ else
+ tp->mac_mode = TG3_DEF_MAC_MODE;
+
/* these are limited to 10/100 only */
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
(grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
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);
else
tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
- /* All chips before 5787 can get confused if TX buffers
- * straddle the 4GB address boundary in some cases.
- */
- 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_5906)
- tp->dev->hard_start_xmit = tg3_start_xmit;
- else
- tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug;
-
- tp->rx_offset = 2;
+ tp->rx_offset = NET_IP_ALIGN;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
(tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
tp->rx_offset = 0;
}
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
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:
val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
val |= DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
break;
- };
+ }
} else {
switch (cacheline_size) {
case 16:
val |= (DMA_RWCTRL_READ_BNDRY_1024 |
DMA_RWCTRL_WRITE_BNDRY_1024);
break;
- };
+ }
}
out:
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)
}
}
+static const struct net_device_ops tg3_netdev_ops = {
+ .ndo_open = tg3_open,
+ .ndo_stop = tg3_close,
+ .ndo_start_xmit = tg3_start_xmit,
+ .ndo_get_stats = tg3_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = tg3_set_rx_mode,
+ .ndo_set_mac_address = tg3_set_mac_addr,
+ .ndo_do_ioctl = tg3_ioctl,
+ .ndo_tx_timeout = tg3_tx_timeout,
+ .ndo_change_mtu = tg3_change_mtu,
+#if TG3_VLAN_TAG_USED
+ .ndo_vlan_rx_register = tg3_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = tg3_poll_controller,
+#endif
+};
+
+static const struct net_device_ops tg3_netdev_ops_dma_bug = {
+ .ndo_open = tg3_open,
+ .ndo_stop = tg3_close,
+ .ndo_start_xmit = tg3_start_xmit_dma_bug,
+ .ndo_get_stats = tg3_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = tg3_set_rx_mode,
+ .ndo_set_mac_address = tg3_set_mac_addr,
+ .ndo_do_ioctl = tg3_ioctl,
+ .ndo_tx_timeout = tg3_tx_timeout,
+ .ndo_change_mtu = tg3_change_mtu,
+#if TG3_VLAN_TAG_USED
+ .ndo_vlan_rx_register = tg3_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = tg3_poll_controller,
+#endif
+};
+
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_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;
return err;
}
- if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ if (!(pci_resource_flags(pdev, BAR_0) & IORESOURCE_MEM)) {
printk(KERN_ERR PFX "Cannot find proper PCI device "
"base address, aborting.\n");
err = -ENODEV;
goto err_out_free_res;
}
- tg3reg_base = pci_resource_start(pdev, 0);
- tg3reg_len = pci_resource_len(pdev, 0);
-
dev = alloc_etherdev(sizeof(*tp));
if (!dev) {
printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
#if TG3_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->vlan_rx_register = tg3_vlan_rx_register;
#endif
tp = netdev_priv(dev);
tp->pdev = pdev;
tp->dev = dev;
tp->pm_cap = pm_cap;
- tp->mac_mode = TG3_DEF_MAC_MODE;
tp->rx_mode = TG3_DEF_RX_MODE;
tp->tx_mode = TG3_DEF_TX_MODE;
- tp->mi_mode = MAC_MI_MODE_BASE;
+
if (tg3_debug > 0)
tp->msg_enable = tg3_debug;
else
spin_lock_init(&tp->indirect_lock);
INIT_WORK(&tp->reset_task, tg3_reset_task);
- tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len);
+ dev->mem_start = pci_resource_start(pdev, BAR_0);
+ tg3reg_len = pci_resource_len(pdev, BAR_0);
+ dev->mem_end = dev->mem_start + tg3reg_len;
+
+ tp->regs = ioremap_nocache(dev->mem_start, tg3reg_len);
if (!tp->regs) {
printk(KERN_ERR PFX "Cannot map device registers, "
"aborting.\n");
tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
tp->tx_pending = TG3_DEF_TX_RING_PENDING;
- dev->open = tg3_open;
- dev->stop = tg3_close;
- dev->get_stats = tg3_get_stats;
- dev->set_multicast_list = tg3_set_rx_mode;
- dev->set_mac_address = tg3_set_mac_addr;
- dev->do_ioctl = tg3_ioctl;
- dev->tx_timeout = tg3_tx_timeout;
netif_napi_add(dev, &tp->napi, tg3_poll, 64);
dev->ethtool_ops = &tg3_ethtool_ops;
dev->watchdog_timeo = TG3_TX_TIMEOUT;
- dev->change_mtu = tg3_change_mtu;
dev->irq = pdev->irq;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = tg3_poll_controller;
-#endif
err = tg3_get_invariants(tp);
if (err) {
goto err_out_iounmap;
}
+ 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)
+ dev->netdev_ops = &tg3_netdev_ops;
+ else
+ dev->netdev_ops = &tg3_netdev_ops_dma_bug;
+
+
/* The EPB bridge inside 5714, 5715, and 5780 and any
* device behind the EPB cannot support DMA addresses > 40-bit.
* On 64-bit systems with IOMMU, use 40-bit dma_mask.
if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906))
dev->features |= NETIF_F_TSO6;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
dev->features |= NETIF_F_TSO_ECN;
}
goto err_out_iounmap;
}
+ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+ if (!(pci_resource_flags(pdev, BAR_2) & IORESOURCE_MEM)) {
+ printk(KERN_ERR PFX "Cannot find proper PCI device "
+ "base address for APE, aborting.\n");
+ err = -ENODEV;
+ goto err_out_iounmap;
+ }
+
+ tp->aperegs = pci_ioremap_bar(pdev, BAR_2);
+ 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)
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
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
dev->features |= NETIF_F_IPV6_CSUM;
tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
/* flow control autonegotiation is default behavior */
tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+ tp->link_config.flowctrl = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
tg3_init_coal(tp);
- 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 == 0UL) {
- printk(KERN_ERR PFX "Cannot map APE registers, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_out_iounmap;
- }
-
- tg3_ape_lock_init(tp);
- }
-
pci_set_drvdata(pdev, dev);
err = register_netdev(dev);
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] (%s) MAC address %pM\n",
dev->name,
tp->board_part_number,
tp->pci_chip_rev_id,
- tg3_phy_string(tp),
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' : ':');
+ dev->dev_addr);
- printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
- "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n",
+ if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)
+ printk(KERN_INFO
+ "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
+ tp->dev->name,
+ tp->mdio_bus->phy_map[PHY_ADDR]->drv->name,
+ dev_name(&tp->mdio_bus->phy_map[PHY_ADDR]->dev));
+ else
+ printk(KERN_INFO
+ "%s: attached PHY is %s (%s Ethernet) (WireSpeed[%d])\n",
+ tp->dev->name, tg3_phy_string(tp),
+ ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
+ ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
+ "10/100/1000Base-T")),
+ (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0);
+
+ printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n",
dev->name,
(tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
(tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
(tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
- (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
dev->name, tp->dma_rwctrl,
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);
{
struct net_device *dev = pci_get_drvdata(pdev);
struct tg3 *tp = netdev_priv(dev);
+ pci_power_t target_state;
int err;
/* PCI register 4 needs to be saved whether netif_running() or not.
return 0;
flush_scheduled_work();
+ tg3_phy_stop(tp);
tg3_netif_stop(tp);
del_timer_sync(&tp->timer);
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
tg3_full_unlock(tp);
- err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
+ target_state = pdev->pm_cap ? pci_target_state(pdev) : PCI_D3hot;
+
+ err = tg3_set_power_state(tp, target_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;
out:
tg3_full_unlock(tp);
+
+ if (!err2)
+ tg3_phy_start(tp);
}
return err;
if (err)
return err;
- /* Hardware bug - MSI won't work if INTX disabled. */
- if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
- (tp->tg3_flags2 & TG3_FLG2_USING_MSI))
- pci_intx(tp->pdev, 1);
-
netif_device_attach(dev);
tg3_full_lock(tp, 0);
out:
tg3_full_unlock(tp);
+ if (!err)
+ tg3_phy_start(tp);
+
return err;
}