diff options
| author | Ayaz Abdulla <aabdulla@nvidia.com> | 2008-02-04 15:13:59 -0500 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2008-02-06 06:41:14 -0500 |
| commit | b2976d23a15aac11e8e77a496108b9f4040fac4d (patch) | |
| tree | f5ac3f3007795411969047233591f0b364db65cd | |
| parent | 47eaa267a5db1729d238f977364e297b8963e115 (diff) | |
forcedeth: restart tx/rx
This patch fixes the issue where the transmitter and receiver must be
restarted when applying new changes to certain registers.
Signed-off-by: Ayaz Abdulla <aabdulla@nvidia.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/net/forcedeth.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 36342230a6de..6e47b1103cd2 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
| @@ -624,6 +624,9 @@ union ring_type { | |||
| 624 | #define NV_MSI_X_VECTOR_TX 0x1 | 624 | #define NV_MSI_X_VECTOR_TX 0x1 |
| 625 | #define NV_MSI_X_VECTOR_OTHER 0x2 | 625 | #define NV_MSI_X_VECTOR_OTHER 0x2 |
| 626 | 626 | ||
| 627 | #define NV_RESTART_TX 0x1 | ||
| 628 | #define NV_RESTART_RX 0x2 | ||
| 629 | |||
| 627 | /* statistics */ | 630 | /* statistics */ |
| 628 | struct nv_ethtool_str { | 631 | struct nv_ethtool_str { |
| 629 | char name[ETH_GSTRING_LEN]; | 632 | char name[ETH_GSTRING_LEN]; |
| @@ -2767,6 +2770,7 @@ static int nv_update_linkspeed(struct net_device *dev) | |||
| 2767 | int mii_status; | 2770 | int mii_status; |
| 2768 | int retval = 0; | 2771 | int retval = 0; |
| 2769 | u32 control_1000, status_1000, phyreg, pause_flags, txreg; | 2772 | u32 control_1000, status_1000, phyreg, pause_flags, txreg; |
| 2773 | u32 txrxFlags = 0; | ||
| 2770 | 2774 | ||
| 2771 | /* BMSR_LSTATUS is latched, read it twice: | 2775 | /* BMSR_LSTATUS is latched, read it twice: |
| 2772 | * we want the current value. | 2776 | * we want the current value. |
| @@ -2862,6 +2866,16 @@ set_speed: | |||
| 2862 | np->duplex = newdup; | 2866 | np->duplex = newdup; |
| 2863 | np->linkspeed = newls; | 2867 | np->linkspeed = newls; |
| 2864 | 2868 | ||
| 2869 | /* The transmitter and receiver must be restarted for safe update */ | ||
| 2870 | if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START) { | ||
| 2871 | txrxFlags |= NV_RESTART_TX; | ||
| 2872 | nv_stop_tx(dev); | ||
| 2873 | } | ||
| 2874 | if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) { | ||
| 2875 | txrxFlags |= NV_RESTART_RX; | ||
| 2876 | nv_stop_rx(dev); | ||
| 2877 | } | ||
| 2878 | |||
| 2865 | if (np->gigabit == PHY_GIGABIT) { | 2879 | if (np->gigabit == PHY_GIGABIT) { |
| 2866 | phyreg = readl(base + NvRegRandomSeed); | 2880 | phyreg = readl(base + NvRegRandomSeed); |
| 2867 | phyreg &= ~(0x3FF00); | 2881 | phyreg &= ~(0x3FF00); |
| @@ -2950,6 +2964,11 @@ set_speed: | |||
| 2950 | } | 2964 | } |
| 2951 | nv_update_pause(dev, pause_flags); | 2965 | nv_update_pause(dev, pause_flags); |
| 2952 | 2966 | ||
| 2967 | if (txrxFlags & NV_RESTART_TX) | ||
| 2968 | nv_start_tx(dev); | ||
| 2969 | if (txrxFlags & NV_RESTART_RX) | ||
| 2970 | nv_start_rx(dev); | ||
| 2971 | |||
| 2953 | return retval; | 2972 | return retval; |
| 2954 | } | 2973 | } |
| 2955 | 2974 | ||
