Kumar,

> I've got a BCM5461 that requires this fix to be able to force the speeds 
> on the PHY.  Not sure if its needed on the other variants or not.  The 
> problem is the genphy_config_aneg resets the PHY when forcing the speed 
> and once we reset the BCM5461 it doesn't remember any of its settings.

 I recall seeing a similar problem before and having checked with the IEEE 
spec I believe it's the generic code that is incorrect.  Following is my 
fix to address this problem.  Please try and see if it works for you.

 I am waiting for 2.6.20 to happen before I recheck my list of patches 
related to the BCM1250 MAC and the PHY library and (re)submit whatever is 
still relevant.  This patch is one of candidates.

  Maciej

patch-mips-2.6.18-20060920-phy-forcing-1
diff -up --recursive --new-file 
linux-mips-2.6.18-20060920.macro/drivers/net/phy/phy.c 
linux-mips-2.6.18-20060920/drivers/net/phy/phy.c
--- linux-mips-2.6.18-20060920.macro/drivers/net/phy/phy.c      2006-08-05 
04:58:46.000000000 +0000
+++ linux-mips-2.6.18-20060920/drivers/net/phy/phy.c    2006-09-25 
03:03:45.000000000 +0000
@@ -713,6 +713,8 @@ static void phy_timer(unsigned long data
                                } else {
                                        phydev->state = PHY_NOLINK;
                                        netif_carrier_off(phydev->attached_dev);
+                                       phydev->link_timeout =
+                                               PHY_NOLINK_TIMEOUT;
                                }
 
                                phydev->adjust_link(phydev->attached_dev);
@@ -759,6 +761,9 @@ static void phy_timer(unsigned long data
                                phydev->state = PHY_RUNNING;
                                netif_carrier_on(phydev->attached_dev);
                                phydev->adjust_link(phydev->attached_dev);
+                       } else if (0 == phydev->link_timeout--) {
+                               phydev->autoneg = AUTONEG_ENABLE;
+                               needs_aneg = 1;
                        }
                        break;
                case PHY_FORCING:
@@ -797,6 +802,7 @@ static void phy_timer(unsigned long data
                        } else {
                                phydev->state = PHY_NOLINK;
                                netif_carrier_off(phydev->attached_dev);
+                               phydev->link_timeout = PHY_NOLINK_TIMEOUT;
                        }
 
                        phydev->adjust_link(phydev->attached_dev);
diff -up --recursive --new-file 
linux-mips-2.6.18-20060920.macro/drivers/net/phy/phy_device.c 
linux-mips-2.6.18-20060920/drivers/net/phy/phy_device.c
--- linux-mips-2.6.18-20060920.macro/drivers/net/phy/phy_device.c       
2006-09-20 20:50:26.000000000 +0000
+++ linux-mips-2.6.18-20060920/drivers/net/phy/phy_device.c     2006-09-25 
01:51:34.000000000 +0000
@@ -325,10 +325,18 @@ EXPORT_SYMBOL(genphy_config_advert);
  *   Please see phy_sanitize_settings() */
 int genphy_setup_forced(struct phy_device *phydev)
 {
-       int ctl = BMCR_RESET;
+       int ctl;
 
        phydev->pause = phydev->asym_pause = 0;
 
+       ctl = phy_read(phydev, MII_BMCR);
+
+       ctl &= ~(BMCR_ANENABLE | BMCR_ANRESTART);
+
+       ctl &= ~(BMCR_ISOLATE);
+
+       ctl &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX);
+
        if (SPEED_1000 == phydev->speed)
                ctl |= BMCR_SPEED1000;
        else if (SPEED_100 == phydev->speed)
@@ -336,16 +344,8 @@ int genphy_setup_forced(struct phy_devic
 
        if (DUPLEX_FULL == phydev->duplex)
                ctl |= BMCR_FULLDPLX;
-       
-       ctl = phy_write(phydev, MII_BMCR, ctl);
-
-       if (ctl < 0)
-               return ctl;
 
-       /* We just reset the device, so we'd better configure any
-        * settings the PHY requires to operate */
-       if (phydev->drv->config_init)
-               ctl = phydev->drv->config_init(phydev);
+       ctl = phy_write(phydev, MII_BMCR, ctl);
 
        return ctl;
 }
diff -up --recursive --new-file 
linux-mips-2.6.18-20060920.macro/include/linux/phy.h 
linux-mips-2.6.18-20060920/include/linux/phy.h
--- linux-mips-2.6.18-20060920.macro/include/linux/phy.h        2006-08-29 
04:58:59.000000000 +0000
+++ linux-mips-2.6.18-20060920/include/linux/phy.h      2006-09-29 
14:19:10.000000000 +0000
@@ -50,6 +50,7 @@
 #define PHY_STATE_TIME         1
 #define PHY_FORCE_TIMEOUT      10
 #define PHY_AN_TIMEOUT         10
+#define PHY_NOLINK_TIMEOUT     3
 
 #define PHY_MAX_ADDR 32
 
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to