aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ibm_newemac
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-12-04 19:14:27 -0500
committerJeff Garzik <jeff@garzik.org>2007-12-07 15:09:05 -0500
commit911b237d7d327db5371a762f4d8d8cd9ea763662 (patch)
tree10ec6fe5d727439b112d8c1d52c7124f462b2aa1 /drivers/net/ibm_newemac
parent968530643a0685caced9dfd6f72f20d5e7bc8fbb (diff)
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 <benh@kernel.crashing.org> Acked-by: Stefan Roese <sr@denx.de> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/ibm_newemac')
-rw-r--r--drivers/net/ibm_newemac/core.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index eb0718b441bb..e0eae09febfa 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)
464{ 464{
465 struct emac_regs __iomem *p = dev->emacp; 465 struct emac_regs __iomem *p = dev->emacp;
466 struct net_device *ndev = dev->ndev; 466 struct net_device *ndev = dev->ndev;
467 int tx_size, rx_size; 467 int tx_size, rx_size, link = netif_carrier_ok(dev->ndev);
468 u32 r, mr1 = 0; 468 u32 r, mr1 = 0;
469 469
470 DBG(dev, "configure" NL); 470 DBG(dev, "configure" NL);
471 471
472 if (emac_reset(dev) < 0) 472 if (!link) {
473 out_be32(&p->mr1, in_be32(&p->mr1)
474 | EMAC_MR1_FDE | EMAC_MR1_ILE);
475 udelay(100);
476 } else if (emac_reset(dev) < 0)
473 return -ETIMEDOUT; 477 return -ETIMEDOUT;
474 478
475 if (emac_has_feature(dev, EMAC_FTR_HAS_TAH)) 479 if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
476 tah_reset(dev->tah_dev); 480 tah_reset(dev->tah_dev);
477 481
478 DBG(dev, " duplex = %d, pause = %d, asym_pause = %d\n", 482 DBG(dev, " link = %d duplex = %d, pause = %d, asym_pause = %d\n",
479 dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause); 483 link, dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause);
480 484
481 /* Default fifo sizes */ 485 /* Default fifo sizes */
482 tx_size = dev->tx_fifo_size; 486 tx_size = dev->tx_fifo_size;
483 rx_size = dev->rx_fifo_size; 487 rx_size = dev->rx_fifo_size;
484 488
489 /* No link, force loopback */
490 if (!link)
491 mr1 = EMAC_MR1_FDE | EMAC_MR1_ILE;
492
485 /* Check for full duplex */ 493 /* Check for full duplex */
486 if (dev->phy.duplex == DUPLEX_FULL) 494 else if (dev->phy.duplex == DUPLEX_FULL)
487 mr1 |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001; 495 mr1 |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001;
488 496
489 /* Adjust fifo sizes, mr1 and timeouts based on link speed */ 497 /* Adjust fifo sizes, mr1 and timeouts based on link speed */
@@ -1165,9 +1173,9 @@ static void emac_link_timer(struct work_struct *work)
1165 link_poll_interval = PHY_POLL_LINK_ON; 1173 link_poll_interval = PHY_POLL_LINK_ON;
1166 } else { 1174 } else {
1167 if (netif_carrier_ok(dev->ndev)) { 1175 if (netif_carrier_ok(dev->ndev)) {
1168 emac_reinitialize(dev);
1169 netif_carrier_off(dev->ndev); 1176 netif_carrier_off(dev->ndev);
1170 netif_tx_disable(dev->ndev); 1177 netif_tx_disable(dev->ndev);
1178 emac_reinitialize(dev);
1171 emac_print_link_status(dev); 1179 emac_print_link_status(dev);
1172 } 1180 }
1173 link_poll_interval = PHY_POLL_LINK_OFF; 1181 link_poll_interval = PHY_POLL_LINK_OFF;