fep->dirty_tx = bdp;
}
-/* This function is called to start or restart the FEC during a link
- * change. This only happens when switching between half and full
- * duplex.
+/*
+ * This function is called to start or restart the FEC during a link
+ * change, transmit timeout, or to reconfigure the FEC. The network
+ * packet processing for this device must be stopped before this call.
*/
static void
fec_restart(struct net_device *ndev, int duplex)
u32 rcntl = OPT_FRAME_SIZE | 0x04;
u32 ecntl = 0x2; /* ETHEREN */
- if (netif_running(ndev)) {
- netif_device_detach(ndev);
- napi_disable(&fep->napi);
- netif_tx_disable(ndev);
- netif_tx_lock_bh(ndev);
- }
-
/* Whack a reset. We should wait for this. */
writel(1, fep->hwp + FEC_ECNTRL);
udelay(10);
/* Enable interrupts we wish to service */
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-
- if (netif_running(ndev)) {
- netif_tx_unlock_bh(ndev);
- netif_wake_queue(ndev);
- napi_enable(&fep->napi);
- netif_device_attach(ndev);
- }
}
static void
fep->delay_work.timeout = false;
rtnl_lock();
if (netif_device_present(ndev) || netif_running(ndev)) {
+ netif_device_detach(ndev);
+ napi_disable(&fep->napi);
+ netif_tx_disable(ndev);
+ netif_tx_lock_bh(ndev);
fec_restart(ndev, fep->full_duplex);
+ netif_tx_unlock_bh(ndev);
netif_wake_queue(ndev);
+ napi_enable(&fep->napi);
+ netif_device_attach(ndev);
}
rtnl_unlock();
}
}
/* if any of the above changed restart the FEC */
- if (status_change)
+ if (status_change) {
+ netif_device_detach(ndev);
+ napi_disable(&fep->napi);
+ netif_tx_disable(ndev);
+ netif_tx_lock_bh(ndev);
fec_restart(ndev, phy_dev->duplex);
+ netif_tx_unlock_bh(ndev);
+ netif_wake_queue(ndev);
+ napi_enable(&fep->napi);
+ netif_device_attach(ndev);
+ }
} else {
if (fep->link) {
fec_stop(ndev);
fec_stop(ndev);
phy_start_aneg(fep->phy_dev);
}
- if (netif_running(ndev))
+ if (netif_running(ndev)) {
+ netif_device_detach(ndev);
+ napi_disable(&fep->napi);
+ netif_tx_disable(ndev);
+ netif_tx_lock_bh(ndev);
fec_restart(ndev, fep->full_duplex);
+ netif_tx_unlock_bh(ndev);
+ netif_wake_queue(ndev);
+ napi_enable(&fep->napi);
+ netif_device_attach(ndev);
+ }
return 0;
}
if (netif_running(netdev)) {
fec_stop(netdev);
+ netif_device_detach(netdev);
+ napi_disable(&fep->napi);
+ netif_tx_disable(netdev);
+ netif_tx_lock_bh(netdev);
fec_restart(netdev, fep->phy_dev->duplex);
+ netif_tx_unlock_bh(netdev);
netif_wake_queue(netdev);
+ napi_enable(&fep->napi);
+ netif_device_attach(netdev);
}
}
rtnl_lock();
if (netif_running(ndev)) {
+ netif_device_detach(ndev);
+ napi_disable(&fep->napi);
+ netif_tx_disable(ndev);
+ netif_tx_lock_bh(ndev);
fec_restart(ndev, fep->full_duplex);
+ netif_tx_unlock_bh(ndev);
+ netif_wake_queue(ndev);
+ napi_enable(&fep->napi);
netif_device_attach(ndev);
phy_start(fep->phy_dev);
}