|
@@ -624,6 +624,9 @@ union ring_type {
|
|
|
#define NV_MSI_X_VECTOR_TX 0x1
|
|
|
#define NV_MSI_X_VECTOR_OTHER 0x2
|
|
|
|
|
|
+#define NV_RESTART_TX 0x1
|
|
|
+#define NV_RESTART_RX 0x2
|
|
|
+
|
|
|
/* statistics */
|
|
|
struct nv_ethtool_str {
|
|
|
char name[ETH_GSTRING_LEN];
|
|
@@ -2767,6 +2770,7 @@ static int nv_update_linkspeed(struct net_device *dev)
|
|
|
int mii_status;
|
|
|
int retval = 0;
|
|
|
u32 control_1000, status_1000, phyreg, pause_flags, txreg;
|
|
|
+ u32 txrxFlags = 0;
|
|
|
|
|
|
/* BMSR_LSTATUS is latched, read it twice:
|
|
|
* we want the current value.
|
|
@@ -2862,6 +2866,16 @@ set_speed:
|
|
|
np->duplex = newdup;
|
|
|
np->linkspeed = newls;
|
|
|
|
|
|
+ /* The transmitter and receiver must be restarted for safe update */
|
|
|
+ if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START) {
|
|
|
+ txrxFlags |= NV_RESTART_TX;
|
|
|
+ nv_stop_tx(dev);
|
|
|
+ }
|
|
|
+ if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
|
|
|
+ txrxFlags |= NV_RESTART_RX;
|
|
|
+ nv_stop_rx(dev);
|
|
|
+ }
|
|
|
+
|
|
|
if (np->gigabit == PHY_GIGABIT) {
|
|
|
phyreg = readl(base + NvRegRandomSeed);
|
|
|
phyreg &= ~(0x3FF00);
|
|
@@ -2950,6 +2964,11 @@ set_speed:
|
|
|
}
|
|
|
nv_update_pause(dev, pause_flags);
|
|
|
|
|
|
+ if (txrxFlags & NV_RESTART_TX)
|
|
|
+ nv_start_tx(dev);
|
|
|
+ if (txrxFlags & NV_RESTART_RX)
|
|
|
+ nv_start_rx(dev);
|
|
|
+
|
|
|
return retval;
|
|
|
}
|
|
|
|