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 @@
* Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
* Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
* Copyright (C) 2004 Sun Microsystems Inc.
*
* Firmware is:
* Copyright (C) 2000-2003 Broadcom Corporation.
*/
#include <linux/config.h>
......@@ -57,8 +60,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.8"
#define DRV_MODULE_RELDATE "July 14, 2004"
#define DRV_MODULE_VERSION "3.9"
#define DRV_MODULE_RELDATE "August 30, 2004"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
......@@ -442,9 +445,14 @@ static void tg3_switch_clocks(struct tg3 *tp)
0x1f);
tp->pci_clock_ctrl = clock_ctrl;
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
(orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
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,
clock_ctrl |
(CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
......@@ -980,7 +988,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
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.duplex = DUPLEX_HALF;
tp->link_config.autoneg = AUTONEG_ENABLE;
......@@ -992,7 +1000,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
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);
udelay(40);
......@@ -1487,6 +1495,18 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
current_speed = SPEED_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;
for (i = 0; i < 100; i++) {
tg3_readphy(tp, MII_BMSR, &bmsr);
......@@ -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);
}
}
relink:
if (current_link_up == 0) {
u32 tmp;
......@@ -1616,7 +1636,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
tw32_f(MAC_MODE, tp->mac_mode);
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. */
tw32_f(MAC_EVENT, 0);
} else {
......@@ -1965,22 +1985,6 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
static int fiber_autoneg(struct tg3 *tp, u32 *flags)
{
int res = 0;
if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
u32 dig_status;
dig_status = tr32(SG_DIG_STATUS);
*flags = 0;
if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
*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) &&
!(dig_status & (SG_DIG_AUTONEG_ERROR |
SG_DIG_PARTNER_FAULT_MASK)))
res = 1;
} else {
struct tg3_fiber_aneginfo aninfo;
int status = ANEG_FAILED;
unsigned int tick;
......@@ -2018,47 +2022,20 @@ static int fiber_autoneg(struct tg3 *tp, u32 *flags)
(aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
MR_LP_ADV_FULL_DUPLEX)))
res = 1;
}
return res;
}
static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
static void tg3_init_bcm8002(struct tg3 *tp)
{
u32 orig_pause_cfg;
u16 orig_active_speed;
u8 orig_active_duplex;
int current_link_up;
u32 mac_status = tr32(MAC_STATUS);
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;
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->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
/* Allow time for the hardware to auto-negotiate (195ms) */
unsigned int tick = 0;
while (++tick < 195000) {
if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE)
break;
udelay(1);
}
if (tick >= 195000)
printk(KERN_INFO PFX "%s: HW autoneg failed !\n",
tp->dev->name);
}
/* Reset when initting first time or we have a link. */
if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
(tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) &&
!(mac_status & MAC_STATUS_PCS_SYNCED))
return;
/* Set PLL lock range. */
tg3_writephy(tp, 0x16, 0x8007);
......@@ -2097,19 +2074,131 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
* later.
*/
tg3_writephy(tp, 0x10, 0x8011);
}
static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
{
u32 sg_dig_ctrl, sg_dig_status;
u32 serdes_cfg, expected_sg_dig_ctrl;
int workaround, port_a;
int current_link_up;
serdes_cfg = 0;
expected_sg_dig_ctrl = 0;
workaround = 0;
port_a = 1;
current_link_up = 0;
if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 &&
tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) {
workaround = 1;
if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
port_a = 0;
serdes_cfg = tr32(MAC_SERDES_CFG) &
((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20));
}
/* Enable link change interrupt unless serdes polling. */
if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES))
tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
sg_dig_ctrl = tr32(SG_DIG_CTRL);
if (tp->link_config.autoneg != AUTONEG_ENABLE) {
if (sg_dig_ctrl & (1 << 31)) {
if (workaround) {
u32 val = serdes_cfg;
if (port_a)
val |= 0xc010880;
else
tw32_f(MAC_EVENT, 0);
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;
}
goto out;
}
/* Want auto-negotiation. */
expected_sg_dig_ctrl = 0x81388400;
/* Pause capability */
expected_sg_dig_ctrl |= (1 << 11);
/* Asymettric pause */
expected_sg_dig_ctrl |= (1 << 12);
if (sg_dig_ctrl != expected_sg_dig_ctrl) {
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);
tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
} else if (mac_status & (MAC_STATUS_PCS_SYNCED |
MAC_STATUS_SIGNAL_DET)) {
sg_dig_status = tr32(SG_DIG_STATUS);
if ((sg_dig_status & (1 << 1)) &&
(mac_status & MAC_STATUS_PCS_SYNCED)) {
u32 local_adv, remote_adv;
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;
tg3_setup_flow_control(tp, local_adv, remote_adv);
current_link_up = 1;
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);
}
tw32_f(SG_DIG_CTRL, 0x01388400);
udelay(40);
current_link_up = 0;
if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
mac_status = tr32(MAC_STATUS);
if (mac_status & MAC_STATUS_PCS_SYNCED) {
tg3_setup_flow_control(tp, 0, 0);
current_link_up = 1;
}
}
}
}
out:
return current_link_up;
}
static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
{
int current_link_up = 0;
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)) {
u32 local_adv, remote_adv;
......@@ -2123,11 +2212,10 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
tg3_setup_flow_control(tp, local_adv, remote_adv);
tp->tg3_flags |=
TG3_FLAG_GOT_SERDES_FLOWCTL;
tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
current_link_up = 1;
}
for (i = 0; i < 60; i++) {
for (i = 0; i < 30; i++) {
udelay(20);
tw32_f(MAC_STATUS,
(MAC_STATUS_SYNC_CHANGED |
......@@ -2138,17 +2226,77 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
MAC_STATUS_CFG_CHANGED)) == 0)
break;
}
mac_status = tr32(MAC_STATUS);
if (current_link_up == 0 &&
(tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
(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);
}
} else
tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
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;
tw32_f(MAC_MODE, tp->mac_mode);
......@@ -2159,19 +2307,24 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
(tp->hw_status->status & ~SD_STATUS_LINK_CHG));
for (i = 0; i < 100; i++) {
udelay(20);
tw32_f(MAC_STATUS,
(MAC_STATUS_SYNC_CHANGED |
tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED));
udelay(40);
if ((tr32(MAC_STATUS) &
(MAC_STATUS_SYNC_CHANGED |
udelay(5);
if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
MAC_STATUS_CFG_CHANGED)) == 0)
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;
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) {
tp->link_config.active_speed = SPEED_1000;
......@@ -2203,15 +2356,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
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;
}
......@@ -2219,7 +2363,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
{
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);
} else {
err = tg3_setup_copper_phy(tp, force_reset);
......@@ -2738,11 +2882,11 @@ static void tg3_reset_task(void *_data)
tg3_halt(tp);
tg3_init_hw(tp);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
if (restart_timer)
mod_timer(&tp->timer, jiffies + 1);
}
......@@ -3102,9 +3246,10 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
tg3_init_hw(tp);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0;
}
......@@ -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. */
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);
if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
tg3_stop_fw(tp);
tw32(0x5000, 0x400);
}
tw32(GRC_MODE, tp->grc_mode);
if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
......@@ -3713,7 +3865,7 @@ static int tg3_chip_reset(struct tg3 *tp)
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;
tw32_f(MAC_MODE, tp->mac_mode);
} else
......@@ -5243,14 +5395,14 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(MAC_LED_CTRL, tp->led_ctrl);
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);
udelay(10);
}
tw32_f(MAC_RX_MODE, tp->rx_mode);
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) {
/* Set drive transmission level to 1.2V */
val = tr32(MAC_SERDES_CFG);
......@@ -5268,22 +5420,8 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
tp->phy_id == PHY_ID_SERDES) {
/* Enable 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_PHY_SERDES)) {
/* Use hardware link auto-negotiation */
tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
}
......@@ -5291,7 +5429,7 @@ static int tg3_reset_hw(struct tg3 *tp)
if (err)
return err;
if (tp->phy_id != PHY_ID_SERDES) {
if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
u32 tmp;
/* Clear CRC stats. */
......@@ -5483,7 +5621,8 @@ static void tg3_timer(unsigned long __opaque)
need_setup = 1;
}
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;
}
if (need_setup) {
......@@ -5879,7 +6018,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
{
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_5701)) {
unsigned long flags;
......@@ -6310,7 +6449,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->supported |= (SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
if (tp->phy_id != PHY_ID_SERDES)
if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES))
cmd->supported |= (SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_10baseT_Half |
......@@ -6339,7 +6478,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
tp->link_config.phy_is_low_power)
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. */
if (cmd->autoneg == AUTONEG_ENABLE &&
(cmd->advertising & ~(ADVERTISED_1000baseT_Half |
......@@ -6397,7 +6536,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
if (wol->wolopts & ~WAKE_MAGIC)
return -EINVAL;
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))
return -EINVAL;
......@@ -6493,10 +6632,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
tg3_halt(tp);
tg3_init_hw(tp);
netif_wake_queue(tp->dev);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0;
}
......@@ -6531,9 +6669,9 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX;
tg3_halt(tp);
tg3_init_hw(tp);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0;
}
......@@ -6620,7 +6758,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCGMIIREG: {
u32 mii_regval;
if (tp->phy_id == PHY_ID_SERDES)
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
break; /* We have no PHY */
spin_lock_irq(&tp->lock);
......@@ -6633,7 +6771,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
case SIOCSMIIREG:
if (tp->phy_id == PHY_ID_SERDES)
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
break; /* We have no PHY */
if (!capable(CAP_NET_ADMIN))
......@@ -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, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
{ 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, 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, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
{ PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */
......@@ -6882,7 +7020,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
/* 3com boards. */
{ PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
{ 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, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
......@@ -6895,37 +7033,43 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
/* Compaq boards. */
{ PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
{ 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, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */
/* 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;
u32 hw_phy_id, hw_phy_id_masked;
u32 val;
int i, eeprom_signature_found, err;
int i;
tp->phy_id = PHY_ID_INVALID;
for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) {
if ((subsys_id_to_phy_id[i].subsys_vendor ==
tp->pdev->subsystem_vendor) &&
(subsys_id_to_phy_id[i].subsys_devid ==
tp->pdev->subsystem_device)) {
tp->phy_id = subsys_id_to_phy_id[i].phy_id;
break;
}
tp->pdev->subsystem_device))
return &subsys_id_to_phy_id[i];
}
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_serdes = 0;
eeprom_signature_found = 0;
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
if (val == NIC_SRAM_DATA_SIG_MAGIC) {
u32 nic_cfg, led_cfg;
u32 nic_phy_id, cfg2;
tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
tp->nic_sram_data_cfg = nic_cfg;
......@@ -6933,10 +7077,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
eeprom_signature_found = 1;
if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) {
eeprom_phy_id = PHY_ID_SERDES;
} else {
u32 nic_phy_id;
NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
eeprom_phy_serdes = 1;
tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
if (nic_phy_id != 0) {
......@@ -6946,8 +7088,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
eeprom_phy_id = (id1 >> 16) << 10;
eeprom_phy_id |= (id2 & 0xfc00) << 16;
eeprom_phy_id |= (id2 & 0x03ff) << 0;
}
}
} else
eeprom_phy_id = 0;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg);
......@@ -7009,6 +7151,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
}
if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2);
if (cfg2 & (1 << 17))
tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
}
/* Reading the PHY ID register can conflict with ASF
......@@ -7035,20 +7181,31 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
tp->phy_id = hw_phy_id;
if (hw_phy_id_masked == PHY_ID_BCM8002)
tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
} else {
/* phy_id currently holds the value found in the
* subsys_id_to_phy_id[] table or PHY_ID_INVALID
* if a match was not found there.
if (eeprom_signature_found) {
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.
*/
if (tp->phy_id == PHY_ID_INVALID) {
if (!eeprom_signature_found ||
!KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
p = lookup_by_subsys(tp);
if (!p)
return -ENODEV;
tp->phy_id = eeprom_phy_id;
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)) {
u32 bmsr, adv_reg, tg3_ctrl;
......@@ -7105,7 +7262,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
if (!eeprom_signature_found)
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 =
(ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full |
......@@ -7492,12 +7649,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
grc_misc_cfg = tr32(GRC_MISC_CFG);
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 &&
grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
}
#endif
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_5788M))
......@@ -7524,7 +7683,7 @@ static int __devinit tg3_get_invariants(struct tg3 *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;
} else {
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)
* upon subsystem IDs.
*/
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 |
TG3_FLAG_USE_LINKCHG_REG);
}
/* 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;
else
tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
......@@ -7988,8 +8147,8 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
case PHY_ID_BCM5704: return "5704";
case PHY_ID_BCM5705: return "5705";
case PHY_ID_BCM5750: return "5750";
case PHY_ID_BCM8002: return "8002";
case PHY_ID_SERDES: return "serdes";
case PHY_ID_BCM8002: return "8002/serdes";
case 0: return "serdes";
default: return "unknown";
};
}
......@@ -8371,11 +8530,11 @@ static int tg3_suspend(struct pci_dev *pdev, u32 state)
tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
netif_device_attach(dev);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
}
return err;
......@@ -8408,11 +8567,11 @@ static int tg3_resume(struct pci_dev *pdev)
tg3_enable_ints(tp);
tg3_netif_start(tp);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0;
}
......
......@@ -124,6 +124,7 @@
#define CHIPREV_ID_5705_A3 0x3003
#define CHIPREV_ID_5750_A0 0x4000
#define CHIPREV_ID_5750_A1 0x4001
#define CHIPREV_ID_5750_A3 0x4003
#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
#define ASIC_REV_5700 0x07
#define ASIC_REV_5701 0x00
......@@ -2089,6 +2090,9 @@ struct tg3 {
#define TG3_FLG2_PCI_EXPRESS 0x00000200
#define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400
#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;
#define SPLIT_MODE_5704_MAX_REQ 3
......@@ -2136,7 +2140,6 @@ struct tg3 {
#define PHY_ID_BCM5705 0x600081a0
#define PHY_ID_BCM5750 0x60008180
#define PHY_ID_BCM8002 0x60010140
#define PHY_ID_SERDES 0xfeedbee0
#define PHY_ID_INVALID 0xffffffff
#define PHY_ID_REV_MASK 0x0000000f
#define PHY_REV_BCM5401_B0 0x1
......@@ -2159,7 +2162,7 @@ struct tg3 {
(X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
(X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
(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;
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