diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/sky2.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index e5679965501..2c9118125b5 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -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; @@ -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); |