aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2014-07-08 07:40:07 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-08 23:02:58 -0400
commit8ce5624f5bbb991ae3aea2fcdae86d808351e173 (patch)
treef1fa4fca6e1b256be169541d8f24bd5642488f0b
parent8bbbd3c19c469a1c6b8e97e9f5a083d029657be5 (diff)
net: fec: only restart or stop the device if it is present and running
Avoid calling fec_restart() or fec_stop() while the device is down or not present (iow suspended.) Although the ndo_timeout method will only be called if the device is present and running, we defer this to a work queue. The work queue can run independently, and so needs to repeat these checks to ensure that a restart doesn't occur after the device has been taken down or detached for suspend. In this case, we call fec_restart() in the resume path, so nothing is lost. For fec_set_features, we add a call to fec_restart() in fec_enet_open() to ensure that the hardware is appropriate programmed when the interface is opened. fec_set_features() call should not occur while we're suspended, so we don't have to worry about that case. The adjust_link needs similar treatment - this also is called from a work queue, which may be run independently after we have taken the device down and detached it. In this case, we just mark the link down and take no further action. We will reset things appropriately once the device is up and running again, at which point we will receive another adjust_link callback. Acked-by: Fugang Duan <B38611@freescale.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 03785cd14b7c..bfb2bb00c493 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1065,12 +1065,15 @@ static void fec_enet_work(struct work_struct *work)
1065 container_of(work, 1065 container_of(work,
1066 struct fec_enet_private, 1066 struct fec_enet_private,
1067 delay_work.delay_work.work); 1067 delay_work.delay_work.work);
1068 struct net_device *ndev = fep->netdev;
1068 1069
1069 if (fep->delay_work.timeout) { 1070 if (fep->delay_work.timeout) {
1070 fep->delay_work.timeout = false; 1071 fep->delay_work.timeout = false;
1071 rtnl_lock(); 1072 rtnl_lock();
1072 fec_restart(fep->netdev, fep->full_duplex); 1073 if (netif_device_present(ndev) || netif_running(ndev)) {
1073 netif_wake_queue(fep->netdev); 1074 fec_restart(ndev, fep->full_duplex);
1075 netif_wake_queue(ndev);
1076 }
1074 rtnl_unlock(); 1077 rtnl_unlock();
1075 } 1078 }
1076 1079
@@ -1504,7 +1507,14 @@ static void fec_enet_adjust_link(struct net_device *ndev)
1504 return; 1507 return;
1505 } 1508 }
1506 1509
1507 if (phy_dev->link) { 1510 /*
1511 * If the netdev is down, or is going down, we're not interested
1512 * in link state events, so just mark our idea of the link as down
1513 * and ignore the event.
1514 */
1515 if (!netif_running(ndev) || !netif_device_present(ndev)) {
1516 fep->link = 0;
1517 } else if (phy_dev->link) {
1508 if (!fep->link) { 1518 if (!fep->link) {
1509 fep->link = phy_dev->link; 1519 fep->link = phy_dev->link;
1510 status_change = 1; 1520 status_change = 1;
@@ -2184,6 +2194,7 @@ fec_enet_open(struct net_device *ndev)
2184 return ret; 2194 return ret;
2185 } 2195 }
2186 2196
2197 fec_restart(ndev, fep->full_duplex);
2187 napi_enable(&fep->napi); 2198 napi_enable(&fep->napi);
2188 phy_start(fep->phy_dev); 2199 phy_start(fep->phy_dev);
2189 netif_start_queue(ndev); 2200 netif_start_queue(ndev);
@@ -2350,8 +2361,6 @@ static int fec_set_features(struct net_device *netdev,
2350 fec_stop(netdev); 2361 fec_stop(netdev);
2351 fec_restart(netdev, fep->phy_dev->duplex); 2362 fec_restart(netdev, fep->phy_dev->duplex);
2352 netif_wake_queue(netdev); 2363 netif_wake_queue(netdev);
2353 } else {
2354 fec_restart(netdev, fep->phy_dev->duplex);
2355 } 2364 }
2356 } 2365 }
2357 2366