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);
        }