Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=911b237d7d327db5371a762f4d8d8cd9ea763662
Commit:     911b237d7d327db5371a762f4d8d8cd9ea763662
Parent:     968530643a0685caced9dfd6f72f20d5e7bc8fbb
Author:     Benjamin Herrenschmidt <[EMAIL PROTECTED]>
AuthorDate: Wed Dec 5 11:14:27 2007 +1100
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Fri Dec 7 15:09:05 2007 -0500

    ibm_newemac: Workaround reset timeout when no link
    
    With some PHYs, when the link goes away, the EMAC reset fails due
    to the loss of the RX clock I believe.
    
    The old EMAC driver worked around that using some internal chip-specific
    clock force bits that are different on various 44x implementations.
    
    This is an attempt at doing it differently, by avoiding the reset when
    there is no link, but forcing loopback mode instead. It seems to work
    on my Taishan 440GX based board so far.
    
    Signed-off-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]>
    Acked-by: Stefan Roese <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/net/ibm_newemac/core.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index eb0718b..e0eae09 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -464,26 +464,34 @@ static int emac_configure(struct emac_instance *dev)
 {
        struct emac_regs __iomem *p = dev->emacp;
        struct net_device *ndev = dev->ndev;
-       int tx_size, rx_size;
+       int tx_size, rx_size, link = netif_carrier_ok(dev->ndev);
        u32 r, mr1 = 0;
 
        DBG(dev, "configure" NL);
 
-       if (emac_reset(dev) < 0)
+       if (!link) {
+               out_be32(&p->mr1, in_be32(&p->mr1)
+                        | EMAC_MR1_FDE | EMAC_MR1_ILE);
+               udelay(100);
+       } else if (emac_reset(dev) < 0)
                return -ETIMEDOUT;
 
        if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
                tah_reset(dev->tah_dev);
 
-       DBG(dev, " duplex = %d, pause = %d, asym_pause = %d\n",
-           dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause);
+       DBG(dev, " link = %d duplex = %d, pause = %d, asym_pause = %d\n",
+           link, dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause);
 
        /* Default fifo sizes */
        tx_size = dev->tx_fifo_size;
        rx_size = dev->rx_fifo_size;
 
+       /* No link, force loopback */
+       if (!link)
+               mr1 = EMAC_MR1_FDE | EMAC_MR1_ILE;
+
        /* Check for full duplex */
-       if (dev->phy.duplex == DUPLEX_FULL)
+       else if (dev->phy.duplex == DUPLEX_FULL)
                mr1 |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001;
 
        /* Adjust fifo sizes, mr1 and timeouts based on link speed */
@@ -1165,9 +1173,9 @@ static void emac_link_timer(struct work_struct *work)
                link_poll_interval = PHY_POLL_LINK_ON;
        } else {
                if (netif_carrier_ok(dev->ndev)) {
-                       emac_reinitialize(dev);
                        netif_carrier_off(dev->ndev);
                        netif_tx_disable(dev->ndev);
+                       emac_reinitialize(dev);
                        emac_print_link_status(dev);
                }
                link_poll_interval = PHY_POLL_LINK_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