summaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/ethtool.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 41dee2de13ad..13d79f5a86e5 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1669,7 +1669,7 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
return dev->ethtool_ops->phys_id(dev, id.data);
rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE);
- if (rc && rc != -EINVAL)
+ if (rc < 0)
return rc;
/* Drop the RTNL lock while waiting, but prevent reentry or
@@ -1684,21 +1684,22 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
schedule_timeout_interruptible(
id.data ? (id.data * HZ) : MAX_SCHEDULE_TIMEOUT);
} else {
- /* Driver expects to be called periodically */
+ /* Driver expects to be called at twice the frequency in rc */
+ int n = rc * 2, i, interval = HZ / n;
+
+ /* Count down seconds */
do {
- rtnl_lock();
- rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ON);
- rtnl_unlock();
- if (rc)
- break;
- schedule_timeout_interruptible(HZ / 2);
-
- rtnl_lock();
- rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_OFF);
- rtnl_unlock();
- if (rc)
- break;
- schedule_timeout_interruptible(HZ / 2);
+ /* Count down iterations per second */
+ i = n;
+ do {
+ rtnl_lock();
+ rc = dev->ethtool_ops->set_phys_id(dev,
+ (i & 1) ? ETHTOOL_ID_OFF : ETHTOOL_ID_ON);
+ rtnl_unlock();
+ if (rc)
+ break;
+ schedule_timeout_interruptible(interval);
+ } while (!signal_pending(current) && --i != 0);
} while (!signal_pending(current) &&
(id.data == 0 || --id.data != 0));
}