Commit d3fe5891 authored by Scott Feldman's avatar Scott Feldman Committed by Jeff Garzik

[E100] forced speed/duplex link recover

On Thu, 20 Mar 2003, Scott Feldman wrote:


* Bug fix when changing to non-autoneg, device may lose
  link with some switches, so try to recover link by
  forcing PHY.
parent 3e961093
...@@ -87,6 +87,8 @@ ...@@ -87,6 +87,8 @@
#include "e100_config.h" #include "e100_config.h"
#include "e100_phy.h" #include "e100_phy.h"
extern void e100_force_speed_duplex_to_phy(struct e100_private *bdp);
static char e100_gstrings_stats[][ETH_GSTRING_LEN] = { static char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
...@@ -1707,6 +1709,11 @@ e100_watchdog(struct net_device *dev) ...@@ -1707,6 +1709,11 @@ e100_watchdog(struct net_device *dev)
} else { } else {
if (netif_running(dev)) if (netif_running(dev))
netif_stop_queue(dev); netif_stop_queue(dev);
/* When changing to non-autoneg, device may lose */
/* link with some switches. e100 will try to */
/* revover link by sending command to PHY layer */
if (bdp->params.e100_speed_duplex != E100_AUTONEG)
e100_force_speed_duplex_to_phy(bdp);
} }
rmb(); rmb();
...@@ -3023,12 +3030,17 @@ e100_isolate_driver(struct e100_private *bdp) ...@@ -3023,12 +3030,17 @@ e100_isolate_driver(struct e100_private *bdp)
void void
e100_set_speed_duplex(struct e100_private *bdp) e100_set_speed_duplex(struct e100_private *bdp)
{ {
if (netif_carrier_ok(bdp->device)) int carrier_ok;
/* Device may lose link with some siwtches when */
/* changing speed/duplex to non-autoneg. e100 */
/* needs to remember carrier state in order to */
/* start watchdog timer for recovering link */
if ((carrier_ok = netif_carrier_ok(bdp->device)))
e100_isolate_driver(bdp); e100_isolate_driver(bdp);
e100_phy_set_speed_duplex(bdp, true); e100_phy_set_speed_duplex(bdp, true);
e100_config_fc(bdp); /* re-config flow-control if necessary */ e100_config_fc(bdp); /* re-config flow-control if necessary */
e100_config(bdp); e100_config(bdp);
if (netif_carrier_ok(bdp->device)) if (carrier_ok)
e100_deisolate_driver(bdp, false); e100_deisolate_driver(bdp, false);
} }
......
...@@ -636,7 +636,6 @@ e100_force_speed_duplex(struct e100_private *bdp) ...@@ -636,7 +636,6 @@ e100_force_speed_duplex(struct e100_private *bdp)
control &= ~BMCR_ANENABLE; control &= ~BMCR_ANENABLE;
control &= ~BMCR_LOOPBACK; control &= ~BMCR_LOOPBACK;
/* Check e100.c values */
switch (bdp->params.e100_speed_duplex) { switch (bdp->params.e100_speed_duplex) {
case E100_SPEED_10_HALF: case E100_SPEED_10_HALF:
control &= ~BMCR_SPEED100; control &= ~BMCR_SPEED100;
...@@ -682,6 +681,41 @@ e100_force_speed_duplex(struct e100_private *bdp) ...@@ -682,6 +681,41 @@ e100_force_speed_duplex(struct e100_private *bdp)
} while (true); } while (true);
} }
void
e100_force_speed_duplex_to_phy(struct e100_private *bdp)
{
u16 control;
e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);
control &= ~BMCR_ANENABLE;
control &= ~BMCR_LOOPBACK;
switch (bdp->params.e100_speed_duplex) {
case E100_SPEED_10_HALF:
control &= ~BMCR_SPEED100;
control &= ~BMCR_FULLDPLX;
break;
case E100_SPEED_10_FULL:
control &= ~BMCR_SPEED100;
control |= BMCR_FULLDPLX;
break;
case E100_SPEED_100_HALF:
control |= BMCR_SPEED100;
control &= ~BMCR_FULLDPLX;
break;
case E100_SPEED_100_FULL:
control |= BMCR_SPEED100;
control |= BMCR_FULLDPLX;
break;
}
/* Send speed/duplex command to PHY layer. */
e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);
}
/* /*
* Procedure: e100_set_fc * Procedure: e100_set_fc
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment