ethtool: allow custom interval for physical identification
When physical identification of an adapter is done by toggling the
mechanism on and off through software utilizing the set_phys_id operation,
it is done with a fixed duration for both on and off states. Some drivers
may want to set a custom duration for the on/off intervals. This patch
changes the API so the return code from the driver's entry point when it
is called with ETHTOOL_ID_ACTIVE can specify the frequency at which to
cycle the on/off states, and updates the drivers that have already been
converted to use the new set_phys_id and use the synchronous method for
identifying an adapter.
The physical identification frequency set in the updated drivers is based
on how it was done prior to the introduction of set_phys_id.
Compile tested only. Also fixes a compiler warning in sfc.
v2: drivers do not return -EINVAL for ETHOOL_ID_ACTIVE
v3: fold patchset into single patch and cleanup per Ben's feedback
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Sathya Perla <sathya.perla@emulex.com>
Cc: Subbu Seetharaman <subbu.seetharaman@emulex.com>
Cc: Ajit Khaparde <ajit.khaparde@emulex.com>
Cc: Michael Chan <mchan@broadcom.com>
Cc: Eilon Greenstein <eilong@broadcom.com>
Cc: Divy Le Ray <divy@chelsio.com>
Cc: Don Fry <pcnet32@frontier.com>
Cc: Jon Mason <jdmason@kudzu.us>
Cc: Solarflare linux maintainers <linux-net-drivers@solarflare.com>
Cc: Steve Hodgson <shodgson@solarflare.com>
Cc: Stephen Hemminger <shemminger@linux-foundation.org>
Cc: Matt Carlson <mcarlson@broadcom.com>
Acked-by: Jon Mason <jdmason@kudzu.us>
Acked-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 41dee2d..13d79f5 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1669,7 +1669,7 @@
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 @@
schedule_timeout_interruptible(
id.data ? (id.data * HZ) : MAX_SCHEDULE_TIMEOUT);
} else {
- /* Driver expects to be called periodically */
- do {
- rtnl_lock();
- rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ON);
- rtnl_unlock();
- if (rc)
- break;
- schedule_timeout_interruptible(HZ / 2);
+ /* Driver expects to be called at twice the frequency in rc */
+ int n = rc * 2, i, interval = HZ / n;
- 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 seconds */
+ do {
+ /* 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));
}