[BNX2]: Add 5708S parallel detection.

Add code to parallel detect 1Gbps and 2.5Gbps link speeds.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Michael Chan 2006-11-19 14:08:29 -08:00 committed by David S. Miller
parent 48b01e2d7c
commit f8dd064ee1
2 changed files with 57 additions and 21 deletions

View file

@ -1067,19 +1067,17 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
bnx2_write_phy(bp, MII_ADVERTISE, new_adv); bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
BMCR_ANENABLE); BMCR_ANENABLE);
if (CHIP_NUM(bp) == CHIP_NUM_5706) { /* Speed up link-up time when the link partner
/* Speed up link-up time when the link partner * does not autonegotiate which is very common
* does not autonegotiate which is very common * in blade servers. Some blade servers use
* in blade servers. Some blade servers use * IPMI for kerboard input and it's important
* IPMI for kerboard input and it's important * to minimize link disruptions. Autoneg. involves
* to minimize link disruptions. Autoneg. involves * exchanging base pages plus 3 next pages and
* exchanging base pages plus 3 next pages and * normally completes in about 120 msec.
* normally completes in about 120 msec. */
*/ bp->current_interval = SERDES_AN_TIMEOUT;
bp->current_interval = SERDES_AN_TIMEOUT; bp->serdes_an_pending = 1;
bp->serdes_an_pending = 1; mod_timer(&bp->timer, jiffies + bp->current_interval);
mod_timer(&bp->timer, jiffies + bp->current_interval);
}
} }
return 0; return 0;
@ -4227,6 +4225,41 @@ bnx2_5706_serdes_timer(struct bnx2 *bp)
spin_unlock(&bp->phy_lock); spin_unlock(&bp->phy_lock);
} }
static void
bnx2_5708_serdes_timer(struct bnx2 *bp)
{
if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) {
bp->serdes_an_pending = 0;
return;
}
spin_lock(&bp->phy_lock);
if (bp->serdes_an_pending)
bp->serdes_an_pending--;
else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
u32 bmcr;
bnx2_read_phy(bp, MII_BMCR, &bmcr);
if (bmcr & BMCR_ANENABLE) {
bmcr &= ~BMCR_ANENABLE;
bmcr |= BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500;
bnx2_write_phy(bp, MII_BMCR, bmcr);
bp->current_interval = SERDES_FORCED_TIMEOUT;
} else {
bmcr &= ~(BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500);
bmcr |= BMCR_ANENABLE;
bnx2_write_phy(bp, MII_BMCR, bmcr);
bp->serdes_an_pending = 2;
bp->current_interval = bp->timer_interval;
}
} else
bp->current_interval = bp->timer_interval;
spin_unlock(&bp->phy_lock);
}
static void static void
bnx2_timer(unsigned long data) bnx2_timer(unsigned long data)
{ {
@ -4244,9 +4277,12 @@ bnx2_timer(unsigned long data)
bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
if ((bp->phy_flags & PHY_SERDES_FLAG) && if (bp->phy_flags & PHY_SERDES_FLAG) {
(CHIP_NUM(bp) == CHIP_NUM_5706)) if (CHIP_NUM(bp) == CHIP_NUM_5706)
bnx2_5706_serdes_timer(bp); bnx2_5706_serdes_timer(bp);
else if (CHIP_NUM(bp) == CHIP_NUM_5708)
bnx2_5708_serdes_timer(bp);
}
bnx2_restart_timer: bnx2_restart_timer:
mod_timer(&bp->timer, jiffies + bp->current_interval); mod_timer(&bp->timer, jiffies + bp->current_interval);
@ -4917,11 +4953,10 @@ bnx2_nway_reset(struct net_device *dev)
msleep(20); msleep(20);
spin_lock_bh(&bp->phy_lock); spin_lock_bh(&bp->phy_lock);
if (CHIP_NUM(bp) == CHIP_NUM_5706) {
bp->current_interval = SERDES_AN_TIMEOUT; bp->current_interval = SERDES_AN_TIMEOUT;
bp->serdes_an_pending = 1; bp->serdes_an_pending = 1;
mod_timer(&bp->timer, jiffies + bp->current_interval); mod_timer(&bp->timer, jiffies + bp->current_interval);
}
} }
bnx2_read_phy(bp, MII_BMCR, &bmcr); bnx2_read_phy(bp, MII_BMCR, &bmcr);

View file

@ -4040,6 +4040,7 @@ struct bnx2 {
u8 serdes_an_pending; u8 serdes_an_pending;
#define SERDES_AN_TIMEOUT (HZ / 3) #define SERDES_AN_TIMEOUT (HZ / 3)
#define SERDES_FORCED_TIMEOUT (HZ / 10)
u8 mac_addr[8]; u8 mac_addr[8];