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