Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=da4c1ff475d82585e3206f0270cb1ba55bcf3c74
Commit:     da4c1ff475d82585e3206f0270cb1ba55bcf3c74
Parent:     7a7b5181517752005fd0dc822176a6975218ec0f
Author:     Stephen Hemminger <[EMAIL PROTECTED]>
AuthorDate: Thu Feb 15 16:40:32 2007 -0800
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Sat Feb 17 15:30:47 2007 -0500

    sky2: flow control negotiation for Yukon-FE
    
    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 <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 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 e567996..2c91181 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);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to