summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavid decotigny <decot@googlers.com>2012-08-24 21:22:53 +0400
committerDavid S. Miller <davem@davemloft.net>2012-08-30 21:04:57 +0400
commit3f0a1b58ae1fb72dee348564d03f42cca2338ab8 (patch)
treef79ac3ef59e592afa25b0a66bc0a287015555d0e
parent1ff39eb66b6ba456995fa19185463d7753cd8798 (diff)
downloadlinux-3f0a1b58ae1fb72dee348564d03f42cca2338ab8.tar.xz
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>
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c12
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
goto out_error;
}
+ netif_carrier_off(dev);
+
+ /* Some NICs freeze when TX pause is enabled while NIC is
+ * down, and this stays across warm reboots. The sequence
+ * below should be enough to recover from that state.
+ */
+ nv_update_pause(dev, 0);
+ nv_start_tx(dev);
+ nv_stop_tx(dev);
+
if (id->driver_data & DEV_HAS_VLAN)
nv_vlan_mode(dev, dev->features);
- netif_carrier_off(dev);
-
dev_info(&pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, addr %pM\n",
dev->name, np->phy_oui, np->phyaddr, dev->dev_addr);