Skip to content

Commit

Permalink
sky2: flow control negotiation for Yukon-FE
Browse files Browse the repository at this point in the history
The Yukon-FE chip doesn't do gigabit and has a differen PHY internally.
On this chip, phy status register doesn't properly reflect the result
of flow control negotiation. To workaround the problem and avoid having
to have so much chip dependent code; compute the result of flow control
by looking at the local and remote advertised bits.

Signed-off-by: Stephen Hemmminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Stephen Hemminger authored and Jeff Garzik committed Feb 17, 2007
1 parent 7a7b518 commit da4c1ff
Showing 1 changed file with 31 additions and 11 deletions.
42 changes: 31 additions & 11 deletions drivers/net/sky2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1766,10 +1766,10 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
{
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
u16 lpa;
u16 advert, lpa;

advert = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP);

if (lpa & PHY_M_AN_RF) {
printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name);
return -1;
Expand All @@ -1784,20 +1784,40 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
sky2->speed = sky2_phy_speed(hw, aux);
sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;

/* Pause bits are offset (9..8) */
if (hw->chip_id == CHIP_ID_YUKON_XL
|| hw->chip_id == CHIP_ID_YUKON_EC_U
|| hw->chip_id == CHIP_ID_YUKON_EX)
aux >>= 6;

sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN,
aux & PHY_M_PS_TX_P_EN);
/* Since the pause result bits seem to in different positions on
* different chips. look at registers.
*/
if (!sky2_is_copper(hw)) {
/* Shift for bits in fiber PHY */
advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);

if (advert & ADVERTISE_1000XPAUSE)
advert |= ADVERTISE_PAUSE_CAP;
if (advert & ADVERTISE_1000XPSE_ASYM)
advert |= ADVERTISE_PAUSE_ASYM;
if (lpa & LPA_1000XPAUSE)
lpa |= LPA_PAUSE_CAP;
if (lpa & LPA_1000XPAUSE_ASYM)
lpa |= LPA_PAUSE_ASYM;
}

sky2->flow_status = FC_NONE;
if (advert & ADVERTISE_PAUSE_CAP) {
if (lpa & LPA_PAUSE_CAP)
sky2->flow_status = FC_BOTH;
else if (advert & ADVERTISE_PAUSE_ASYM)
sky2->flow_status = FC_RX;
} else if (advert & ADVERTISE_PAUSE_ASYM) {
if ((lpa & LPA_PAUSE_CAP) && (lpa & LPA_PAUSE_ASYM))
sky2->flow_status = FC_TX;
}

if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000
&& !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX))
sky2->flow_status = FC_NONE;

if (aux & PHY_M_PS_RX_P_EN)
if (sky2->flow_status & FC_TX)
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
else
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
Expand Down

0 comments on commit da4c1ff

Please sign in to comment.