diff options
author | david decotigny <decot@googlers.com> | 2012-08-24 13:22:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-08-30 13:04:57 -0400 |
commit | 3f0a1b58ae1fb72dee348564d03f42cca2338ab8 (patch) | |
tree | f79ac3ef59e592afa25b0a66bc0a287015555d0e /drivers/net/ethernet/nvidia/forcedeth.c | |
parent | 1ff39eb66b6ba456995fa19185463d7753cd8798 (diff) |
forcedeth: prevent TX timeouts after reboot
This complements patch "net-forcedeth: fix TX timeout caused by TX
pause on down link" which ensures that a lock-up sequence is not sent
to the NIC. Present patch ensures that if a NIC is already locked-up,
the driver will recover from it when initializing the device.
It does the equivalent of the following recovery sequence:
- write NVREG_TX_PAUSEFRAME_ENABLE_V1 to eth1's register
NvRegTxPauseFrame
- write NVREG_XMITCTL_START to eth1's register
NvRegTransmitterControl
- write 0 to eth1's register NvRegTransmitterControl
(this is at the heart of the "unbricking" sequence mentioned in patch
"net-forcedeth: fix TX timeout caused by TX pause on down link")
Tested:
- hardware is MCP55 device id 10de:0373 (rev a3), dual-port
- reboot a kernel without any of patches mentioned
- freeze the NIC (details on description for commit "net-forcedeth:
fix TX timeout caused by TX pause on down link")
- wait 5mn until ping hangs & TX timeout in dmesg
- reboot on kernel with present patch
- host is immediatly operational, no TX timeout
Signed-off-by: David Decotigny <decot@googlers.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/nvidia/forcedeth.c')
-rw-r--r-- | drivers/net/ethernet/nvidia/forcedeth.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 8b82457c1682..876beceaf2d7 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c | |||
@@ -5905,11 +5905,19 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
5905 | goto out_error; | 5905 | goto out_error; |
5906 | } | 5906 | } |
5907 | 5907 | ||
5908 | netif_carrier_off(dev); | ||
5909 | |||
5910 | /* Some NICs freeze when TX pause is enabled while NIC is | ||
5911 | * down, and this stays across warm reboots. The sequence | ||
5912 | * below should be enough to recover from that state. | ||
5913 | */ | ||
5914 | nv_update_pause(dev, 0); | ||
5915 | nv_start_tx(dev); | ||
5916 | nv_stop_tx(dev); | ||
5917 | |||
5908 | if (id->driver_data & DEV_HAS_VLAN) | 5918 | if (id->driver_data & DEV_HAS_VLAN) |
5909 | nv_vlan_mode(dev, dev->features); | 5919 | nv_vlan_mode(dev, dev->features); |
5910 | 5920 | ||
5911 | netif_carrier_off(dev); | ||
5912 | |||
5913 | dev_info(&pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, addr %pM\n", | 5921 | dev_info(&pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, addr %pM\n", |
5914 | dev->name, np->phy_oui, np->phyaddr, dev->dev_addr); | 5922 | dev->name, np->phy_oui, np->phyaddr, dev->dev_addr); |
5915 | 5923 | ||