ethtool: allow custom interval for physical identification
[pandora-kernel.git] / net / core / ethtool.c
index 41dee2d..13d79f5 100644 (file)
@@ -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));
        }