Commit 96cf2a82 authored by David S. Miller's avatar David S. Miller

Merge davem@nuts.davemloft.net:/disk1/BK/tg3-2.6

into kernel.bkbits.net:/home/davem/tg3-2.6
parents f9464393 f966e9fa
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
* Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
* Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
* Copyright (C) 2004 Sun Microsystems Inc. * Copyright (C) 2004 Sun Microsystems Inc.
*
* Firmware is:
* Copyright (C) 2000-2003 Broadcom Corporation.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -57,8 +60,8 @@ ...@@ -57,8 +60,8 @@
#define DRV_MODULE_NAME "tg3" #define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.8" #define DRV_MODULE_VERSION "3.9"
#define DRV_MODULE_RELDATE "July 14, 2004" #define DRV_MODULE_RELDATE "August 30, 2004"
#define TG3_DEF_MAC_MODE 0 #define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0 #define TG3_DEF_RX_MODE 0
...@@ -442,9 +445,14 @@ static void tg3_switch_clocks(struct tg3 *tp) ...@@ -442,9 +445,14 @@ static void tg3_switch_clocks(struct tg3 *tp)
0x1f); 0x1f);
tp->pci_clock_ctrl = clock_ctrl; tp->pci_clock_ctrl = clock_ctrl;
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
(orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
tw32_f(TG3PCI_CLOCK_CTRL,
clock_ctrl | CLOCK_CTRL_625_CORE);
udelay(40);
}
} else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
tw32_f(TG3PCI_CLOCK_CTRL, tw32_f(TG3PCI_CLOCK_CTRL,
clock_ctrl | clock_ctrl |
(CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK)); (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
...@@ -980,7 +988,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state) ...@@ -980,7 +988,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
tp->link_config.orig_autoneg = tp->link_config.autoneg; tp->link_config.orig_autoneg = tp->link_config.autoneg;
} }
if (tp->phy_id != PHY_ID_SERDES) { if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
tp->link_config.speed = SPEED_10; tp->link_config.speed = SPEED_10;
tp->link_config.duplex = DUPLEX_HALF; tp->link_config.duplex = DUPLEX_HALF;
tp->link_config.autoneg = AUTONEG_ENABLE; tp->link_config.autoneg = AUTONEG_ENABLE;
...@@ -992,7 +1000,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state) ...@@ -992,7 +1000,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) { if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
u32 mac_mode; u32 mac_mode;
if (tp->phy_id != PHY_ID_SERDES) { if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
udelay(40); udelay(40);
...@@ -1487,6 +1495,18 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1487,6 +1495,18 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
current_speed = SPEED_INVALID; current_speed = SPEED_INVALID;
current_duplex = DUPLEX_INVALID; current_duplex = DUPLEX_INVALID;
if (tp->tg3_flags2 & TG3_FLG2_CAPACITIVE_COUPLING) {
u32 val;
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007);
tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
if (!(val & (1 << 10))) {
val |= (1 << 10);
tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
goto relink;
}
}
bmsr = 0; bmsr = 0;
for (i = 0; i < 100; i++) { for (i = 0; i < 100; i++) {
tg3_readphy(tp, MII_BMSR, &bmsr); tg3_readphy(tp, MII_BMSR, &bmsr);
...@@ -1566,7 +1586,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1566,7 +1586,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
tg3_setup_flow_control(tp, local_adv, remote_adv); tg3_setup_flow_control(tp, local_adv, remote_adv);
} }
} }
relink:
if (current_link_up == 0) { if (current_link_up == 0) {
u32 tmp; u32 tmp;
...@@ -1616,7 +1636,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1616,7 +1636,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
tw32_f(MAC_MODE, tp->mac_mode); tw32_f(MAC_MODE, tp->mac_mode);
udelay(40); udelay(40);
if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) { if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
/* Polled via timer. */ /* Polled via timer. */
tw32_f(MAC_EVENT, 0); tw32_f(MAC_EVENT, 0);
} else { } else {
...@@ -1965,190 +1985,318 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp, ...@@ -1965,190 +1985,318 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
static int fiber_autoneg(struct tg3 *tp, u32 *flags) static int fiber_autoneg(struct tg3 *tp, u32 *flags)
{ {
int res = 0; int res = 0;
struct tg3_fiber_aneginfo aninfo;
int status = ANEG_FAILED;
unsigned int tick;
u32 tmp;
if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) { tw32_f(MAC_TX_AUTO_NEG, 0);
u32 dig_status;
dig_status = tr32(SG_DIG_STATUS); tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
*flags = 0; tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE) udelay(40);
*flags |= MR_LP_ADV_ASYM_PAUSE;
if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
*flags |= MR_LP_ADV_SYM_PAUSE;
if ((dig_status & SG_DIG_AUTONEG_COMPLETE) && tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
!(dig_status & (SG_DIG_AUTONEG_ERROR | udelay(40);
SG_DIG_PARTNER_FAULT_MASK)))
res = 1;
} else {
struct tg3_fiber_aneginfo aninfo;
int status = ANEG_FAILED;
unsigned int tick;
u32 tmp;
tw32_f(MAC_TX_AUTO_NEG, 0); memset(&aninfo, 0, sizeof(aninfo));
aninfo.flags |= MR_AN_ENABLE;
aninfo.state = ANEG_STATE_UNKNOWN;
aninfo.cur_time = 0;
tick = 0;
while (++tick < 195000) {
status = tg3_fiber_aneg_smachine(tp, &aninfo);
if (status == ANEG_DONE || status == ANEG_FAILED)
break;
tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; udelay(1);
tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); }
udelay(40);
tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
udelay(40); tw32_f(MAC_MODE, tp->mac_mode);
udelay(40);
memset(&aninfo, 0, sizeof(aninfo)); *flags = aninfo.flags;
aninfo.flags |= MR_AN_ENABLE;
aninfo.state = ANEG_STATE_UNKNOWN;
aninfo.cur_time = 0;
tick = 0;
while (++tick < 195000) {
status = tg3_fiber_aneg_smachine(tp, &aninfo);
if (status == ANEG_DONE || status == ANEG_FAILED)
break;
udelay(1); if (status == ANEG_DONE &&
} (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
MR_LP_ADV_FULL_DUPLEX)))
res = 1;
tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; return res;
tw32_f(MAC_MODE, tp->mac_mode); }
udelay(40);
*flags = aninfo.flags; static void tg3_init_bcm8002(struct tg3 *tp)
{
u32 mac_status = tr32(MAC_STATUS);
int i;
if (status == ANEG_DONE && /* Reset when initting first time or we have a link. */
(aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) &&
MR_LP_ADV_FULL_DUPLEX))) !(mac_status & MAC_STATUS_PCS_SYNCED))
res = 1; return;
}
return res; /* Set PLL lock range. */
tg3_writephy(tp, 0x16, 0x8007);
/* SW reset */
tg3_writephy(tp, MII_BMCR, BMCR_RESET);
/* Wait for reset to complete. */
/* XXX schedule_timeout() ... */
for (i = 0; i < 500; i++)
udelay(10);
/* Config mode; select PMA/Ch 1 regs. */
tg3_writephy(tp, 0x10, 0x8411);
/* Enable auto-lock and comdet, select txclk for tx. */
tg3_writephy(tp, 0x11, 0x0a10);
tg3_writephy(tp, 0x18, 0x00a0);
tg3_writephy(tp, 0x16, 0x41ff);
/* Assert and deassert POR. */
tg3_writephy(tp, 0x13, 0x0400);
udelay(40);
tg3_writephy(tp, 0x13, 0x0000);
tg3_writephy(tp, 0x11, 0x0a50);
udelay(40);
tg3_writephy(tp, 0x11, 0x0a10);
/* Wait for signal to stabilize */
/* XXX schedule_timeout() ... */
for (i = 0; i < 15000; i++)
udelay(10);
/* Deselect the channel register so we can read the PHYID
* later.
*/
tg3_writephy(tp, 0x10, 0x8011);
} }
static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
{ {
u32 orig_pause_cfg; u32 sg_dig_ctrl, sg_dig_status;
u16 orig_active_speed; u32 serdes_cfg, expected_sg_dig_ctrl;
u8 orig_active_duplex; int workaround, port_a;
int current_link_up; int current_link_up;
int i;
orig_pause_cfg = serdes_cfg = 0;
(tp->tg3_flags & (TG3_FLAG_RX_PAUSE | expected_sg_dig_ctrl = 0;
TG3_FLAG_TX_PAUSE)); workaround = 0;
orig_active_speed = tp->link_config.active_speed; port_a = 1;
orig_active_duplex = tp->link_config.active_duplex; current_link_up = 0;
tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 &&
tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) {
tw32_f(MAC_MODE, tp->mac_mode); workaround = 1;
udelay(40); if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
port_a = 0;
if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) { serdes_cfg = tr32(MAC_SERDES_CFG) &
/* Allow time for the hardware to auto-negotiate (195ms) */ ((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20));
unsigned int tick = 0; }
while (++tick < 195000) { sg_dig_ctrl = tr32(SG_DIG_CTRL);
if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE)
break; if (tp->link_config.autoneg != AUTONEG_ENABLE) {
udelay(1); if (sg_dig_ctrl & (1 << 31)) {
if (workaround) {
u32 val = serdes_cfg;
if (port_a)
val |= 0xc010880;
else
val |= 0x4010880;
tw32_f(MAC_SERDES_CFG, val);
}
tw32_f(SG_DIG_CTRL, 0x01388400);
}
if (mac_status & MAC_STATUS_PCS_SYNCED) {
tg3_setup_flow_control(tp, 0, 0);
current_link_up = 1;
} }
if (tick >= 195000) goto out;
printk(KERN_INFO PFX "%s: HW autoneg failed !\n",
tp->dev->name);
} }
/* Reset when initting first time or we have a link. */ /* Want auto-negotiation. */
if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || expected_sg_dig_ctrl = 0x81388400;
(tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
/* Set PLL lock range. */
tg3_writephy(tp, 0x16, 0x8007);
/* SW reset */ /* Pause capability */
tg3_writephy(tp, MII_BMCR, BMCR_RESET); expected_sg_dig_ctrl |= (1 << 11);
/* Wait for reset to complete. */ /* Asymettric pause */
/* XXX schedule_timeout() ... */ expected_sg_dig_ctrl |= (1 << 12);
for (i = 0; i < 500; i++)
udelay(10);
/* Config mode; select PMA/Ch 1 regs. */ if (sg_dig_ctrl != expected_sg_dig_ctrl) {
tg3_writephy(tp, 0x10, 0x8411); if (workaround)
tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011880);
tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30));
udelay(5);
tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
/* Enable auto-lock and comdet, select txclk for tx. */ tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
tg3_writephy(tp, 0x11, 0x0a10); } else if (mac_status & (MAC_STATUS_PCS_SYNCED |
MAC_STATUS_SIGNAL_DET)) {
sg_dig_status = tr32(SG_DIG_STATUS);
tg3_writephy(tp, 0x18, 0x00a0); if ((sg_dig_status & (1 << 1)) &&
tg3_writephy(tp, 0x16, 0x41ff); (mac_status & MAC_STATUS_PCS_SYNCED)) {
u32 local_adv, remote_adv;
/* Assert and deassert POR. */ local_adv = ADVERTISE_PAUSE_CAP;
tg3_writephy(tp, 0x13, 0x0400); remote_adv = 0;
udelay(40); if (sg_dig_status & (1 << 19))
tg3_writephy(tp, 0x13, 0x0000); remote_adv |= LPA_PAUSE_CAP;
if (sg_dig_status & (1 << 20))
remote_adv |= LPA_PAUSE_ASYM;
tg3_writephy(tp, 0x11, 0x0a50); tg3_setup_flow_control(tp, local_adv, remote_adv);
udelay(40); current_link_up = 1;
tg3_writephy(tp, 0x11, 0x0a10); tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
} else if (!(sg_dig_status & (1 << 1))) {
if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED)
tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
else {
if (workaround) {
u32 val = serdes_cfg;
if (port_a)
val |= 0xc010880;
else
val |= 0x4010880;
tw32_f(MAC_SERDES_CFG, serdes_cfg);
}
/* Wait for signal to stabilize */ tw32_f(SG_DIG_CTRL, 0x01388400);
/* XXX schedule_timeout() ... */ udelay(40);
for (i = 0; i < 15000; i++)
udelay(10);
/* Deselect the channel register so we can read the PHYID mac_status = tr32(MAC_STATUS);
* later. if (mac_status & MAC_STATUS_PCS_SYNCED) {
*/ tg3_setup_flow_control(tp, 0, 0);
tg3_writephy(tp, 0x10, 0x8011); current_link_up = 1;
}
}
}
} }
/* Enable link change interrupt unless serdes polling. */ out:
if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES)) return current_link_up;
tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); }
else
tw32_f(MAC_EVENT, 0);
udelay(40);
current_link_up = 0; static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) { {
if (tp->link_config.autoneg == AUTONEG_ENABLE) { int current_link_up = 0;
u32 flags;
if (!(mac_status & MAC_STATUS_PCS_SYNCED)) {
tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
goto out;
}
if (tp->link_config.autoneg == AUTONEG_ENABLE) {
u32 flags;
int i;
if (fiber_autoneg(tp, &flags)) { if (fiber_autoneg(tp, &flags)) {
u32 local_adv, remote_adv; u32 local_adv, remote_adv;
local_adv = ADVERTISE_PAUSE_CAP; local_adv = ADVERTISE_PAUSE_CAP;
remote_adv = 0; remote_adv = 0;
if (flags & MR_LP_ADV_SYM_PAUSE) if (flags & MR_LP_ADV_SYM_PAUSE)
remote_adv |= LPA_PAUSE_CAP; remote_adv |= LPA_PAUSE_CAP;
if (flags & MR_LP_ADV_ASYM_PAUSE) if (flags & MR_LP_ADV_ASYM_PAUSE)
remote_adv |= LPA_PAUSE_ASYM; remote_adv |= LPA_PAUSE_ASYM;
tg3_setup_flow_control(tp, local_adv, remote_adv); tg3_setup_flow_control(tp, local_adv, remote_adv);
tp->tg3_flags |=
TG3_FLAG_GOT_SERDES_FLOWCTL;
current_link_up = 1;
}
for (i = 0; i < 60; i++) {
udelay(20);
tw32_f(MAC_STATUS,
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED));
udelay(40);
if ((tr32(MAC_STATUS) &
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED)) == 0)
break;
}
if (current_link_up == 0 &&
(tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
current_link_up = 1;
}
} else {
/* Forcing 1000FD link up. */
current_link_up = 1;
tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
current_link_up = 1;
} }
} else for (i = 0; i < 30; i++) {
tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL; udelay(20);
tw32_f(MAC_STATUS,
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED));
udelay(40);
if ((tr32(MAC_STATUS) &
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED)) == 0)
break;
}
mac_status = tr32(MAC_STATUS);
if (current_link_up == 0 &&
(mac_status & MAC_STATUS_PCS_SYNCED) &&
!(mac_status & MAC_STATUS_RCVD_CFG))
current_link_up = 1;
} else {
/* Forcing 1000FD link up. */
current_link_up = 1;
tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
udelay(40);
}
out:
return current_link_up;
}
static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
{
u32 orig_pause_cfg;
u16 orig_active_speed;
u8 orig_active_duplex;
u32 mac_status;
int current_link_up;
int i;
orig_pause_cfg =
(tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
TG3_FLAG_TX_PAUSE));
orig_active_speed = tp->link_config.active_speed;
orig_active_duplex = tp->link_config.active_duplex;
if (!(tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) &&
netif_carrier_ok(tp->dev) &&
(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) {
mac_status = tr32(MAC_STATUS);
mac_status &= (MAC_STATUS_PCS_SYNCED |
MAC_STATUS_SIGNAL_DET |
MAC_STATUS_CFG_CHANGED |
MAC_STATUS_RCVD_CFG);
if (mac_status == (MAC_STATUS_PCS_SYNCED |
MAC_STATUS_SIGNAL_DET)) {
tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED));
return 0;
}
}
tw32_f(MAC_TX_AUTO_NEG, 0);
tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
tw32_f(MAC_MODE, tp->mac_mode);
udelay(40);
if (tp->phy_id == PHY_ID_BCM8002)
tg3_init_bcm8002(tp);
/* Enable link change event even when serdes polling. */
tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
udelay(40);
current_link_up = 0;
mac_status = tr32(MAC_STATUS);
if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG)
current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status);
else
current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
tw32_f(MAC_MODE, tp->mac_mode); tw32_f(MAC_MODE, tp->mac_mode);
...@@ -2159,19 +2307,24 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) ...@@ -2159,19 +2307,24 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
(tp->hw_status->status & ~SD_STATUS_LINK_CHG)); (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
for (i = 0; i < 100; i++) { for (i = 0; i < 100; i++) {
udelay(20); tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
tw32_f(MAC_STATUS, MAC_STATUS_CFG_CHANGED));
(MAC_STATUS_SYNC_CHANGED | udelay(5);
MAC_STATUS_CFG_CHANGED)); if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
udelay(40); MAC_STATUS_CFG_CHANGED)) == 0)
if ((tr32(MAC_STATUS) &
(MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED)) == 0)
break; break;
} }
if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) mac_status = tr32(MAC_STATUS);
if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
current_link_up = 0; current_link_up = 0;
if (tp->link_config.autoneg == AUTONEG_ENABLE) {
tw32_f(MAC_MODE, (tp->mac_mode |
MAC_MODE_SEND_CONFIGS));
udelay(1);
tw32_f(MAC_MODE, tp->mac_mode);
}
}
if (current_link_up == 1) { if (current_link_up == 1) {
tp->link_config.active_speed = SPEED_1000; tp->link_config.active_speed = SPEED_1000;
...@@ -2203,15 +2356,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) ...@@ -2203,15 +2356,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
tg3_link_report(tp); tg3_link_report(tp);
} }
if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
udelay(40);
if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
tw32_f(MAC_MODE, tp->mac_mode);
udelay(40);
}
}
return 0; return 0;
} }
...@@ -2219,7 +2363,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) ...@@ -2219,7 +2363,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
{ {
int err; int err;
if (tp->phy_id == PHY_ID_SERDES) { if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
err = tg3_setup_fiber_phy(tp, force_reset); err = tg3_setup_fiber_phy(tp, force_reset);
} else { } else {
err = tg3_setup_copper_phy(tp, force_reset); err = tg3_setup_copper_phy(tp, force_reset);
...@@ -2738,11 +2882,11 @@ static void tg3_reset_task(void *_data) ...@@ -2738,11 +2882,11 @@ static void tg3_reset_task(void *_data)
tg3_halt(tp); tg3_halt(tp);
tg3_init_hw(tp); tg3_init_hw(tp);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock); spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock); spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
if (restart_timer) if (restart_timer)
mod_timer(&tp->timer, jiffies + 1); mod_timer(&tp->timer, jiffies + 1);
} }
...@@ -3102,9 +3246,10 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) ...@@ -3102,9 +3246,10 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
tg3_init_hw(tp); tg3_init_hw(tp);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock); spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock); spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0; return 0;
} }
...@@ -3595,6 +3740,8 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind) ...@@ -3595,6 +3740,8 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind)
} }
} }
static void tg3_stop_fw(struct tg3 *);
/* tp->lock is held. */ /* tp->lock is held. */
static int tg3_chip_reset(struct tg3 *tp) static int tg3_chip_reset(struct tg3 *tp)
{ {
...@@ -3697,6 +3844,11 @@ static int tg3_chip_reset(struct tg3 *tp) ...@@ -3697,6 +3844,11 @@ static int tg3_chip_reset(struct tg3 *tp)
tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
tg3_stop_fw(tp);
tw32(0x5000, 0x400);
}
tw32(GRC_MODE, tp->grc_mode); tw32(GRC_MODE, tp->grc_mode);
if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) { if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
...@@ -3713,7 +3865,7 @@ static int tg3_chip_reset(struct tg3 *tp) ...@@ -3713,7 +3865,7 @@ static int tg3_chip_reset(struct tg3 *tp)
tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
} }
if (tp->phy_id == PHY_ID_SERDES) { if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
tp->mac_mode = MAC_MODE_PORT_MODE_TBI; tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
tw32_f(MAC_MODE, tp->mac_mode); tw32_f(MAC_MODE, tp->mac_mode);
} else } else
...@@ -5243,14 +5395,14 @@ static int tg3_reset_hw(struct tg3 *tp) ...@@ -5243,14 +5395,14 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(MAC_LED_CTRL, tp->led_ctrl); tw32(MAC_LED_CTRL, tp->led_ctrl);
tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
if (tp->phy_id == PHY_ID_SERDES) { if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
tw32_f(MAC_RX_MODE, RX_MODE_RESET); tw32_f(MAC_RX_MODE, RX_MODE_RESET);
udelay(10); udelay(10);
} }
tw32_f(MAC_RX_MODE, tp->rx_mode); tw32_f(MAC_RX_MODE, tp->rx_mode);
udelay(10); udelay(10);
if (tp->phy_id == PHY_ID_SERDES) { if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
/* Set drive transmission level to 1.2V */ /* Set drive transmission level to 1.2V */
val = tr32(MAC_SERDES_CFG); val = tr32(MAC_SERDES_CFG);
...@@ -5268,22 +5420,8 @@ static int tg3_reset_hw(struct tg3 *tp) ...@@ -5268,22 +5420,8 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2); tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
tp->phy_id == PHY_ID_SERDES) { (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
/* Enable hardware link auto-negotiation */ /* Use hardware link auto-negotiation */
u32 digctrl, txctrl;
digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N |
SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS |
(2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE |
SG_DIG_GBIC_ENABLE;
txctrl = tr32(MAC_SERDES_CFG);
tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT);
tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET);
tr32(SG_DIG_CTRL);
udelay(5);
tw32_f(SG_DIG_CTRL, digctrl);
tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG; tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
} }
...@@ -5291,7 +5429,7 @@ static int tg3_reset_hw(struct tg3 *tp) ...@@ -5291,7 +5429,7 @@ static int tg3_reset_hw(struct tg3 *tp)
if (err) if (err)
return err; return err;
if (tp->phy_id != PHY_ID_SERDES) { if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
u32 tmp; u32 tmp;
/* Clear CRC stats. */ /* Clear CRC stats. */
...@@ -5483,7 +5621,8 @@ static void tg3_timer(unsigned long __opaque) ...@@ -5483,7 +5621,8 @@ static void tg3_timer(unsigned long __opaque)
need_setup = 1; need_setup = 1;
} }
if (! netif_carrier_ok(tp->dev) && if (! netif_carrier_ok(tp->dev) &&
(mac_stat & MAC_STATUS_PCS_SYNCED)) { (mac_stat & (MAC_STATUS_PCS_SYNCED |
MAC_STATUS_SIGNAL_DET))) {
need_setup = 1; need_setup = 1;
} }
if (need_setup) { if (need_setup) {
...@@ -5879,7 +6018,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp) ...@@ -5879,7 +6018,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
{ {
struct tg3_hw_stats *hw_stats = tp->hw_stats; struct tg3_hw_stats *hw_stats = tp->hw_stats;
if (tp->phy_id != PHY_ID_SERDES && if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
unsigned long flags; unsigned long flags;
...@@ -6310,7 +6449,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -6310,7 +6449,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->supported |= (SUPPORTED_1000baseT_Half | cmd->supported |= (SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full); SUPPORTED_1000baseT_Full);
if (tp->phy_id != PHY_ID_SERDES) if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES))
cmd->supported |= (SUPPORTED_100baseT_Half | cmd->supported |= (SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Full |
SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Half |
...@@ -6339,7 +6478,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -6339,7 +6478,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
tp->link_config.phy_is_low_power) tp->link_config.phy_is_low_power)
return -EAGAIN; return -EAGAIN;
if (tp->phy_id == PHY_ID_SERDES) { if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
/* These are the only valid advertisement bits allowed. */ /* These are the only valid advertisement bits allowed. */
if (cmd->autoneg == AUTONEG_ENABLE && if (cmd->autoneg == AUTONEG_ENABLE &&
(cmd->advertising & ~(ADVERTISED_1000baseT_Half | (cmd->advertising & ~(ADVERTISED_1000baseT_Half |
...@@ -6397,7 +6536,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) ...@@ -6397,7 +6536,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
if (wol->wolopts & ~WAKE_MAGIC) if (wol->wolopts & ~WAKE_MAGIC)
return -EINVAL; return -EINVAL;
if ((wol->wolopts & WAKE_MAGIC) && if ((wol->wolopts & WAKE_MAGIC) &&
tp->phy_id == PHY_ID_SERDES && tp->tg3_flags2 & TG3_FLG2_PHY_SERDES &&
!(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
return -EINVAL; return -EINVAL;
...@@ -6493,10 +6632,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e ...@@ -6493,10 +6632,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
tg3_halt(tp); tg3_halt(tp);
tg3_init_hw(tp); tg3_init_hw(tp);
netif_wake_queue(tp->dev); tg3_netif_start(tp);
spin_unlock(&tp->tx_lock); spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock); spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0; return 0;
} }
...@@ -6531,9 +6669,9 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam ...@@ -6531,9 +6669,9 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX; tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX;
tg3_halt(tp); tg3_halt(tp);
tg3_init_hw(tp); tg3_init_hw(tp);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock); spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock); spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0; return 0;
} }
...@@ -6620,7 +6758,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -6620,7 +6758,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCGMIIREG: { case SIOCGMIIREG: {
u32 mii_regval; u32 mii_regval;
if (tp->phy_id == PHY_ID_SERDES) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
break; /* We have no PHY */ break; /* We have no PHY */
spin_lock_irq(&tp->lock); spin_lock_irq(&tp->lock);
...@@ -6633,7 +6771,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -6633,7 +6771,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
} }
case SIOCSMIIREG: case SIOCSMIIREG:
if (tp->phy_id == PHY_ID_SERDES) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
break; /* We have no PHY */ break; /* We have no PHY */
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
...@@ -6870,10 +7008,10 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = { ...@@ -6870,10 +7008,10 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
{ PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */ { PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */
{ PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */ { PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
{ PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */ { PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */
{ PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES }, /* BCM95700A9 */ { PCI_VENDOR_ID_BROADCOM, 0x0003, 0 }, /* BCM95700A9 */
{ PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */ { PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */
{ PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */ { PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */
{ PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES }, /* BCM95701A7 */ { PCI_VENDOR_ID_BROADCOM, 0x0007, 0 }, /* BCM95701A7 */
{ PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */ { PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
{ PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */ { PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
{ PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */ { PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */
...@@ -6882,7 +7020,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = { ...@@ -6882,7 +7020,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
/* 3com boards. */ /* 3com boards. */
{ PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */ { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
{ PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */ { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */
{ PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES }, /* 3C996SX */ { PCI_VENDOR_ID_3COM, 0x1004, 0 }, /* 3C996SX */
{ PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */ { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */
{ PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */ { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
...@@ -6895,37 +7033,43 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = { ...@@ -6895,37 +7033,43 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
/* Compaq boards. */ /* Compaq boards. */
{ PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */ { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
{ PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */ { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */
{ PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES }, /* CHANGELING */ { PCI_VENDOR_ID_COMPAQ, 0x007d, 0 }, /* CHANGELING */
{ PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */ { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */
{ PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */ { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */
/* IBM boards. */ /* IBM boards. */
{ PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */ { PCI_VENDOR_ID_IBM, 0x0281, 0 } /* IBM??? */
}; };
static int __devinit tg3_phy_probe(struct tg3 *tp) static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp)
{ {
u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2; int i;
u32 hw_phy_id, hw_phy_id_masked;
u32 val;
int i, eeprom_signature_found, err;
tp->phy_id = PHY_ID_INVALID;
for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) { for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) {
if ((subsys_id_to_phy_id[i].subsys_vendor == if ((subsys_id_to_phy_id[i].subsys_vendor ==
tp->pdev->subsystem_vendor) && tp->pdev->subsystem_vendor) &&
(subsys_id_to_phy_id[i].subsys_devid == (subsys_id_to_phy_id[i].subsys_devid ==
tp->pdev->subsystem_device)) { tp->pdev->subsystem_device))
tp->phy_id = subsys_id_to_phy_id[i].phy_id; return &subsys_id_to_phy_id[i];
break;
}
} }
return NULL;
}
static int __devinit tg3_phy_probe(struct tg3 *tp)
{
u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
u32 hw_phy_id, hw_phy_id_masked;
u32 val;
int eeprom_signature_found, eeprom_phy_serdes, err;
tp->phy_id = PHY_ID_INVALID;
eeprom_phy_id = PHY_ID_INVALID; eeprom_phy_id = PHY_ID_INVALID;
eeprom_phy_serdes = 0;
eeprom_signature_found = 0; eeprom_signature_found = 0;
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
if (val == NIC_SRAM_DATA_SIG_MAGIC) { if (val == NIC_SRAM_DATA_SIG_MAGIC) {
u32 nic_cfg, led_cfg; u32 nic_cfg, led_cfg;
u32 nic_phy_id, cfg2;
tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
tp->nic_sram_data_cfg = nic_cfg; tp->nic_sram_data_cfg = nic_cfg;
...@@ -6933,21 +7077,19 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) ...@@ -6933,21 +7077,19 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
eeprom_signature_found = 1; eeprom_signature_found = 1;
if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) { NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
eeprom_phy_id = PHY_ID_SERDES; eeprom_phy_serdes = 1;
} else {
u32 nic_phy_id;
tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id); tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
if (nic_phy_id != 0) { if (nic_phy_id != 0) {
u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK; u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK; u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
eeprom_phy_id = (id1 >> 16) << 10; eeprom_phy_id = (id1 >> 16) << 10;
eeprom_phy_id |= (id2 & 0xfc00) << 16; eeprom_phy_id |= (id2 & 0xfc00) << 16;
eeprom_phy_id |= (id2 & 0x03ff) << 0; eeprom_phy_id |= (id2 & 0x03ff) << 0;
} } else
} eeprom_phy_id = 0;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg); tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg);
...@@ -7009,6 +7151,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) ...@@ -7009,6 +7151,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
} }
if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL) if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP; tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2);
if (cfg2 & (1 << 17))
tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
} }
/* Reading the PHY ID register can conflict with ASF /* Reading the PHY ID register can conflict with ASF
...@@ -7035,20 +7181,31 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) ...@@ -7035,20 +7181,31 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) { if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
tp->phy_id = hw_phy_id; tp->phy_id = hw_phy_id;
if (hw_phy_id_masked == PHY_ID_BCM8002)
tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
} else { } else {
/* phy_id currently holds the value found in the if (eeprom_signature_found) {
* subsys_id_to_phy_id[] table or PHY_ID_INVALID
* if a match was not found there.
*/
if (tp->phy_id == PHY_ID_INVALID) {
if (!eeprom_signature_found ||
!KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
return -ENODEV;
tp->phy_id = eeprom_phy_id; tp->phy_id = eeprom_phy_id;
if (eeprom_phy_serdes)
tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
} else {
struct subsys_tbl_ent *p;
/* No eeprom signature? Try the hardcoded
* subsys device table.
*/
p = lookup_by_subsys(tp);
if (!p)
return -ENODEV;
tp->phy_id = p->phy_id;
if (!tp->phy_id ||
tp->phy_id == PHY_ID_BCM8002)
tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
} }
} }
if (tp->phy_id != PHY_ID_SERDES && if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
u32 bmsr, adv_reg, tg3_ctrl; u32 bmsr, adv_reg, tg3_ctrl;
...@@ -7105,7 +7262,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) ...@@ -7105,7 +7262,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
if (!eeprom_signature_found) if (!eeprom_signature_found)
tp->led_ctrl = LED_CTRL_MODE_PHY_1; tp->led_ctrl = LED_CTRL_MODE_PHY_1;
if (tp->phy_id == PHY_ID_SERDES) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
tp->link_config.advertising = tp->link_config.advertising =
(ADVERTISED_1000baseT_Half | (ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full | ADVERTISED_1000baseT_Full |
...@@ -7492,12 +7649,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -7492,12 +7649,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
grc_misc_cfg = tr32(GRC_MISC_CFG); grc_misc_cfg = tr32(GRC_MISC_CFG);
grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK; grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
/* Broadcom's driver says that CIOBE multisplit has a bug */
#if 0
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) { grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
tp->tg3_flags |= TG3_FLAG_SPLIT_MODE; tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ; tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
} }
#endif
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
(grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
...@@ -7524,7 +7683,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -7524,7 +7683,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tg3_read_partno(tp); tg3_read_partno(tp);
if (tp->phy_id == PHY_ID_SERDES) { if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
} else { } else {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
...@@ -7547,13 +7706,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -7547,13 +7706,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
* upon subsystem IDs. * upon subsystem IDs.
*/ */
if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
tp->phy_id != PHY_ID_SERDES) { !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT | tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
TG3_FLAG_USE_LINKCHG_REG); TG3_FLAG_USE_LINKCHG_REG);
} }
/* For all SERDES we poll the MAC status register. */ /* For all SERDES we poll the MAC status register. */
if (tp->phy_id == PHY_ID_SERDES) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
tp->tg3_flags |= TG3_FLAG_POLL_SERDES; tp->tg3_flags |= TG3_FLAG_POLL_SERDES;
else else
tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
...@@ -7988,8 +8147,8 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) ...@@ -7988,8 +8147,8 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
case PHY_ID_BCM5704: return "5704"; case PHY_ID_BCM5704: return "5704";
case PHY_ID_BCM5705: return "5705"; case PHY_ID_BCM5705: return "5705";
case PHY_ID_BCM5750: return "5750"; case PHY_ID_BCM5750: return "5750";
case PHY_ID_BCM8002: return "8002"; case PHY_ID_BCM8002: return "8002/serdes";
case PHY_ID_SERDES: return "serdes"; case 0: return "serdes";
default: return "unknown"; default: return "unknown";
}; };
} }
...@@ -8371,11 +8530,11 @@ static int tg3_suspend(struct pci_dev *pdev, u32 state) ...@@ -8371,11 +8530,11 @@ static int tg3_suspend(struct pci_dev *pdev, u32 state)
tp->timer.expires = jiffies + tp->timer_offset; tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer); add_timer(&tp->timer);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
netif_device_attach(dev); netif_device_attach(dev);
tg3_netif_start(tp); tg3_netif_start(tp);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
} }
return err; return err;
...@@ -8408,11 +8567,11 @@ static int tg3_resume(struct pci_dev *pdev) ...@@ -8408,11 +8567,11 @@ static int tg3_resume(struct pci_dev *pdev)
tg3_enable_ints(tp); tg3_enable_ints(tp);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock); spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock); spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0; return 0;
} }
......
...@@ -124,6 +124,7 @@ ...@@ -124,6 +124,7 @@
#define CHIPREV_ID_5705_A3 0x3003 #define CHIPREV_ID_5705_A3 0x3003
#define CHIPREV_ID_5750_A0 0x4000 #define CHIPREV_ID_5750_A0 0x4000
#define CHIPREV_ID_5750_A1 0x4001 #define CHIPREV_ID_5750_A1 0x4001
#define CHIPREV_ID_5750_A3 0x4003
#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
#define ASIC_REV_5700 0x07 #define ASIC_REV_5700 0x07
#define ASIC_REV_5701 0x00 #define ASIC_REV_5701 0x00
...@@ -2089,6 +2090,9 @@ struct tg3 { ...@@ -2089,6 +2090,9 @@ struct tg3 {
#define TG3_FLG2_PCI_EXPRESS 0x00000200 #define TG3_FLG2_PCI_EXPRESS 0x00000200
#define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400 #define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400
#define TG3_FLG2_HW_AUTONEG 0x00000800 #define TG3_FLG2_HW_AUTONEG 0x00000800
#define TG3_FLG2_PHY_JUST_INITTED 0x00001000
#define TG3_FLG2_PHY_SERDES 0x00002000
#define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000
u32 split_mode_max_reqs; u32 split_mode_max_reqs;
#define SPLIT_MODE_5704_MAX_REQ 3 #define SPLIT_MODE_5704_MAX_REQ 3
...@@ -2136,7 +2140,6 @@ struct tg3 { ...@@ -2136,7 +2140,6 @@ struct tg3 {
#define PHY_ID_BCM5705 0x600081a0 #define PHY_ID_BCM5705 0x600081a0
#define PHY_ID_BCM5750 0x60008180 #define PHY_ID_BCM5750 0x60008180
#define PHY_ID_BCM8002 0x60010140 #define PHY_ID_BCM8002 0x60010140
#define PHY_ID_SERDES 0xfeedbee0
#define PHY_ID_INVALID 0xffffffff #define PHY_ID_INVALID 0xffffffff
#define PHY_ID_REV_MASK 0x0000000f #define PHY_ID_REV_MASK 0x0000000f
#define PHY_REV_BCM5401_B0 0x1 #define PHY_REV_BCM5401_B0 0x1
...@@ -2159,7 +2162,7 @@ struct tg3 { ...@@ -2159,7 +2162,7 @@ struct tg3 {
(X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
(X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
(X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
(X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES) (X) == PHY_ID_BCM8002)
struct tg3_hw_stats *hw_stats; struct tg3_hw_stats *hw_stats;
dma_addr_t stats_mapping; dma_addr_t stats_mapping;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment