ethtool: allow custom interval for physical identification
authorAllan, Bruce W <bruce.w.allan@intel.com>
Wed, 13 Apr 2011 13:09:10 +0000 (13:09 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 Apr 2011 04:15:49 +0000 (21:15 -0700)
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>
14 files changed:
drivers/net/benet/be_ethtool.c
drivers/net/bnx2.c
drivers/net/bnx2x/bnx2x_ethtool.c
drivers/net/cxgb3/cxgb3_main.c
drivers/net/ewrk3.c
drivers/net/niu.c
drivers/net/pcnet32.c
drivers/net/s2io.c
drivers/net/sfc/ethtool.c
drivers/net/skge.c
drivers/net/sky2.c
drivers/net/tg3.c
include/linux/ethtool.h
net/core/ethtool.c

index 96f5502e0ef7707e17909e0212d5ebc62e5334d9..80226e4801f34bf6eb31f49f6784d7dda4212f66 100644 (file)
@@ -516,7 +516,7 @@ be_set_phys_id(struct net_device *netdev,
        case ETHTOOL_ID_ACTIVE:
                be_cmd_get_beacon_state(adapter, adapter->hba_port_num,
                                        &adapter->beacon_state);
-               return -EINVAL;
+               return 1;       /* cycle on/off once per second */
 
        case ETHTOOL_ID_ON:
                be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
index 0a52079bafef9e8c74bd7b2d93c93341bc0d02b9..bf729ee6acbdc7fc227668eaba2af71214e091c0 100644 (file)
@@ -7473,7 +7473,7 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
 
                bp->leds_save = REG_RD(bp, BNX2_MISC_CFG);
                REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
-               return -EINVAL;
+               return 1;       /* cycle on/off once per second */
 
        case ETHTOOL_ID_ON:
                REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
index ad7d91e499f4522eba9b6c1467e14cc0d1d61f27..0a5e88d6ba2c14ea9f31cf99d84f8c3495dbc922 100644 (file)
@@ -2025,7 +2025,7 @@ static int bnx2x_set_phys_id(struct net_device *dev,
 
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
-               return -EINVAL;
+               return 1;       /* cycle on/off once per second */
 
        case ETHTOOL_ID_ON:
                bnx2x_set_led(&bp->link_params, &bp->link_vars,
index 802c7a7c3b255662be0fc5017df092ed52526b8b..a087e0691dcedce2ab550a85c82c9ab996c3432f 100644 (file)
@@ -1757,7 +1757,7 @@ static int set_phys_id(struct net_device *dev,
 
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
-               return -EINVAL;
+               return 1;       /* cycle on/off once per second */
 
        case ETHTOOL_ID_OFF:
                t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, 0);
index c7ce4438e9238d817f78a5b21383214443ef43b2..17b6027d8be8a8231bbb6366040cbb8205c49d8b 100644 (file)
@@ -1618,7 +1618,7 @@ static int ewrk3_set_phys_id(struct net_device *dev,
                /* Prevent ISR from twiddling the LED */
                lp->led_mask = 0;
                spin_unlock_irq(&lp->hw_lock);
-               return -EINVAL;
+               return 2;       /* cycle on/off twice per second */
 
        case ETHTOOL_ID_ON:
                cr = inb(EWRK3_CR);
index 3fa1e9cdb4a85fbd9e219287d140bc75fd2596dc..ea2272f0f37ea4efb2904d82d635e8114b1ec92a 100644 (file)
@@ -7896,7 +7896,7 @@ static int niu_set_phys_id(struct net_device *dev,
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
                np->orig_led_state = niu_led_state_save(np);
-               return -EINVAL;
+               return 1;       /* cycle on/off once per second */
 
        case ETHTOOL_ID_ON:
                niu_force_led(np, 1);
index e89afb929740b2b0c287a8fb1951d54ef875ec44..0a1efbae1bc0577c9774d3fe577d46ad3244e5cb 100644 (file)
@@ -1038,7 +1038,7 @@ static int pcnet32_set_phys_id(struct net_device *dev,
                for (i = 4; i < 8; i++)
                        lp->save_regs[i - 4] = a->read_bcr(ioaddr, i);
                spin_unlock_irqrestore(&lp->lock, flags);
-               return -EINVAL;
+               return 2;       /* cycle on/off twice per second */
 
        case ETHTOOL_ID_ON:
        case ETHTOOL_ID_OFF:
index 2d5cc6142c044ae3a2ad11d472403b7a0f961b7e..2302d9743744124f95424e6547033a5c3f4207e3 100644 (file)
@@ -5541,7 +5541,7 @@ static int s2io_ethtool_set_led(struct net_device *dev,
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
                sp->adapt_ctrl_org = readq(&bar0->gpio_control);
-               return -EINVAL;
+               return 1;       /* cycle on/off once per second */
 
        case ETHTOOL_ID_ON:
                s2io_set_led(sp, true);
index 644f7c1d6e7b30934b575950febe7feedcadb538..5d8468fc58042c2434e480160f346ce5e61986bd 100644 (file)
@@ -182,7 +182,7 @@ static int efx_ethtool_phys_id(struct net_device *net_dev,
                               enum ethtool_phys_id_state state)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
-       enum efx_led_mode mode;
+       enum efx_led_mode mode = EFX_LED_DEFAULT;
 
        switch (state) {
        case ETHTOOL_ID_ON:
@@ -194,8 +194,8 @@ static int efx_ethtool_phys_id(struct net_device *net_dev,
        case ETHTOOL_ID_INACTIVE:
                mode = EFX_LED_DEFAULT;
                break;
-       default:
-               return -EINVAL;
+       case ETHTOOL_ID_ACTIVE:
+               return 1;       /* cycle on/off once per second */
        }
 
        efx->type->set_id_led(efx, mode);
index 310dcbce2519349e975ee70703734e0cc52fecd9..176d784cbb542bdf5a64d3dad1f9195cf3c07659 100644 (file)
@@ -753,7 +753,7 @@ static int skge_set_phys_id(struct net_device *dev,
 
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
-               return -EINVAL;
+               return 2;       /* cycle on/off twice per second */
 
        case ETHTOOL_ID_ON:
                skge_led(skge, LED_MODE_TST);
index a4b8fe564eb05e02ba367171637136f6c75cda40..c8d045114c66902abbea9054503d816aad6229f2 100644 (file)
@@ -3813,7 +3813,7 @@ static int sky2_set_phys_id(struct net_device *dev,
 
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
-               return -EINVAL;
+               return 1;       /* cycle on/off once per second */
        case ETHTOOL_ID_INACTIVE:
                sky2_led(sky2, MO_LED_NORM);
                break;
index 10fa476fede3240fbf24a0dd011a910277278c19..9915734ac3e9e64a1682680ffd9f3fe8a98a4f11 100644 (file)
@@ -10384,7 +10384,7 @@ static int tg3_set_phys_id(struct net_device *dev,
 
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
-               return -EINVAL;
+               return 1;       /* cycle on/off once per second */
 
        case ETHTOOL_ID_ON:
                tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
index ad22a68c2e5d9a1f843cb767141e7961aba48745..9de31274341d9929629fe999d31b7a304c5a14fc 100644 (file)
@@ -798,8 +798,10 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
  *     attached to it.  The implementation may update the indicator
  *     asynchronously or synchronously, but in either case it must return
  *     quickly.  It is initially called with the argument %ETHTOOL_ID_ACTIVE,
- *     and must either activate asynchronous updates or return -%EINVAL.
- *     If it returns -%EINVAL then it will be called again at intervals with
+ *     and must either activate asynchronous updates and return zero, return
+ *     a negative error or return a positive frequency for synchronous
+ *     indication (e.g. 1 for one on/off cycle per second).  If it returns
+ *     a frequency then it will be called again at intervals with the
  *     argument %ETHTOOL_ID_ON or %ETHTOOL_ID_OFF and should set the state of
  *     the indicator accordingly.  Finally, it is called with the argument
  *     %ETHTOOL_ID_INACTIVE and must deactivate the indicator.  Returns a
index 41dee2de13adc9a31b27bb48835daf90e73f31bb..13d79f5a86e56cd3812ebbc655fe0244cb646030 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));
        }