On Wed, 2006-02-01 at 00:54 -0800, [EMAIL PROTECTED] wrote:
> From: Benjamin Herrenschmidt <[EMAIL PROTECTED]>

Andrew, please drop it for now. It has issues on sparc64 that I need to
have a look at.

Ben.

> On my latest laptop, I've had occasional PHY dead on wakeup from sleep... 
> the PHY would be totally unresponsive even to toggling the hard reset line
> until the machine is powered down...  Looking closely at the code, I found
> some possible issues in the way we setup the MDIO lines during suspend
> along with slight divergences from what Darwin does when resetting it that
> may explain the problem.  That patch change these and the problem appear to
> be gone for me at least...  I also fixed an mdelay -> msleep while I was at
> it to the pmac feature code that is called when toggling the PHY reset line
> since sungem doesn't call it in an atomic context anymore.
> 
> Signed-off-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]>
> Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
> ---
> 
>  arch/powerpc/platforms/powermac/feature.c |    6 +-
>  drivers/net/sungem.c                      |   55 ++++++++++----------
>  2 files changed, 34 insertions(+), 27 deletions(-)
> 
> diff -puN 
> arch/powerpc/platforms/powermac/feature.c~sungem-make-pm-of-phys-more-reliable-2
>  arch/powerpc/platforms/powermac/feature.c
> --- 
> devel/arch/powerpc/platforms/powermac/feature.c~sungem-make-pm-of-phys-more-reliable-2
>     2006-01-31 21:07:28.000000000 -0800
> +++ devel-akpm/arch/powerpc/platforms/powermac/feature.c      2006-01-31 
> 21:07:28.000000000 -0800
> @@ -910,16 +910,18 @@ core99_gmac_phy_reset(struct device_node
>           macio->type != macio_intrepid)
>               return -ENODEV;
>  
> +     printk(KERN_DEBUG "Hard reset of PHY chip ...\n");
> +
>       LOCK(flags);
>       MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
>       (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET);
>       UNLOCK(flags);
> -     mdelay(10);
> +     msleep(10);
>       LOCK(flags);
>       MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */
>               KEYLARGO_GPIO_OUTOUT_DATA);
>       UNLOCK(flags);
> -     mdelay(10);
> +     msleep(10);
>  
>       return 0;
>  }
> diff -puN drivers/net/sungem.c~sungem-make-pm-of-phys-more-reliable-2 
> drivers/net/sungem.c
> --- devel/drivers/net/sungem.c~sungem-make-pm-of-phys-more-reliable-2 
> 2006-01-31 21:07:28.000000000 -0800
> +++ devel-akpm/drivers/net/sungem.c   2006-01-31 21:07:28.000000000 -0800
> @@ -1654,36 +1654,40 @@ static void gem_init_rings(struct gem *g
>  /* Init PHY interface and start link poll state machine */
>  static void gem_init_phy(struct gem *gp)
>  {
> -     u32 mifcfg;
> +     u32 mif_cfg;
>  
>       /* Revert MIF CFG setting done on stop_phy */
> -     mifcfg = readl(gp->regs + MIF_CFG);
> -     mifcfg &= ~MIF_CFG_BBMODE;
> -     writel(mifcfg, gp->regs + MIF_CFG);
> +     mif_cfg = readl(gp->regs + MIF_CFG);
> +     mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1);
> +     mif_cfg |= MIF_CFG_MDI0;
> +     writel(mif_cfg, gp->regs + MIF_CFG);
> +     writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE);
> +     writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG);
>       
>       if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
>               int i;
> +             u16 ctrl;
>  
> -             /* Those delay sucks, the HW seem to love them though, I'll
> -              * serisouly consider breaking some locks here to be able
> -              * to schedule instead
> -              */
> -             for (i = 0; i < 3; i++) {
>  #ifdef CONFIG_PPC_PMAC
> -                     pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 
> 0, 0);
> -                     msleep(20);
> +             pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0);
>  #endif
> -                     /* Some PHYs used by apple have problem getting back to 
> us,
> -                      * we do an additional reset here
> -                      */
> -                     phy_write(gp, MII_BMCR, BMCR_RESET);
> -                     msleep(20);
> -                     if (phy_read(gp, MII_BMCR) != 0xffff)
> +
> +             /* Some PHYs used by apple have problem getting back
> +              * to us, we do an additional reset here
> +              */
> +             phy_write(gp, MII_BMCR, BMCR_RESET);
> +             for (i = 0; i < 50; i++) {
> +                     if ((phy_read(gp, MII_BMCR) & BMCR_RESET) == 0)
>                               break;
> -                     if (i == 2)
> -                             printk(KERN_WARNING "%s: GMAC PHY not 
> responding !\n",
> -                                    gp->dev->name);
> +                     msleep(10);
>               }
> +             if (i == 50)
> +                     printk(KERN_WARNING "%s: GMAC PHY not responding !\n",
> +                            gp->dev->name);
> +             /* Make sure isolate is off */
> +             ctrl = phy_read(gp, MII_BMCR);
> +             if (ctrl & BMCR_ISOLATE)
> +                     phy_write(gp, MII_BMCR, ctrl & ~BMCR_ISOLATE);
>       }
>  
>       if (gp->pdev->vendor == PCI_VENDOR_ID_SUN &&
> @@ -2120,7 +2124,7 @@ static void gem_reinit_chip(struct gem *
>  /* Must be invoked with no lock held. */
>  static void gem_stop_phy(struct gem *gp, int wol)
>  {
> -     u32 mifcfg;
> +     u32 mif_cfg;
>       unsigned long flags;
>  
>       /* Let the chip settle down a bit, it seems that helps
> @@ -2131,9 +2135,9 @@ static void gem_stop_phy(struct gem *gp,
>       /* Make sure we aren't polling PHY status change. We
>        * don't currently use that feature though
>        */
> -     mifcfg = readl(gp->regs + MIF_CFG);
> -     mifcfg &= ~MIF_CFG_POLL;
> -     writel(mifcfg, gp->regs + MIF_CFG);
> +     mif_cfg = readl(gp->regs + MIF_CFG);
> +     mif_cfg &= ~MIF_CFG_POLL;
> +     writel(mif_cfg, gp->regs + MIF_CFG);
>  
>       if (wol && gp->has_wol) {
>               unsigned char *e = &gp->dev->dev_addr[0];
> @@ -2183,7 +2187,8 @@ static void gem_stop_phy(struct gem *gp,
>               /* According to Apple, we must set the MDIO pins to this begnign
>                * state or we may 1) eat more current, 2) damage some PHYs
>                */
> -             writel(mifcfg | MIF_CFG_BBMODE, gp->regs + MIF_CFG);
> +             mif_cfg = 0;
> +             writel(mif_cfg | MIF_CFG_BBMODE, gp->regs + MIF_CFG);
>               writel(0, gp->regs + MIF_BBCLK);
>               writel(0, gp->regs + MIF_BBDATA);
>               writel(0, gp->regs + MIF_BBOENAB);
> _

-
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