i40e: update led set args
authorJesse Brandeburg <jesse.brandeburg@intel.com>
Thu, 28 Nov 2013 06:39:33 +0000 (06:39 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sat, 4 Jan 2014 05:21:42 +0000 (21:21 -0800)
Add an argument to led function and refactor code to flash LED lights
correctly.

Change-Id: I00b21607ced53aaa057159503875708871946259
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Kavindya Deegala <kavindya.s.deegala@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_prototype.h

index e9aab1c..d84fca1 100644 (file)
@@ -401,6 +401,38 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw)
 }
 
 /**
+ * i40e_led_is_mine - helper to find matching led
+ * @hw: pointer to the hw struct
+ * @idx: index into GPIO registers
+ *
+ * returns: 0 if no match, otherwise the value of the GPIO_CTL register
+ */
+static u32 i40e_led_is_mine(struct i40e_hw *hw, int idx)
+{
+       u32 gpio_val = 0;
+       u32 port;
+
+       if (!hw->func_caps.led[idx])
+               return 0;
+
+       gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx));
+       port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >>
+               I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
+
+       /* if PRT_NUM_NA is 1 then this LED is not port specific, OR
+        * if it is not our port then ignore
+        */
+       if ((gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK) ||
+           (port != hw->port))
+               return 0;
+
+       return gpio_val;
+}
+
+#define I40E_LED0 22
+#define I40E_LINK_ACTIVITY 0xC
+
+/**
  * i40e_led_get - return current on/off mode
  * @hw: pointer to the hw struct
  *
@@ -411,24 +443,20 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw)
  **/
 u32 i40e_led_get(struct i40e_hw *hw)
 {
-       u32 gpio_val = 0;
        u32 mode = 0;
-       u32 port;
        int i;
 
-       for (i = 0; i < I40E_HW_CAP_MAX_GPIO; i++) {
-               if (!hw->func_caps.led[i])
-                       continue;
-
-               gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(i));
-               port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK)
-                       >> I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
+       /* as per the documentation GPIO 22-29 are the LED
+        * GPIO pins named LED0..LED7
+        */
+       for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) {
+               u32 gpio_val = i40e_led_is_mine(hw, i);
 
-               if (port != hw->port)
+               if (!gpio_val)
                        continue;
 
-               mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK)
-                               >> I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT;
+               mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) >>
+                       I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT;
                break;
        }
 
@@ -438,31 +466,41 @@ u32 i40e_led_get(struct i40e_hw *hw)
 /**
  * i40e_led_set - set new on/off mode
  * @hw: pointer to the hw struct
- * @mode: 0=off, else on (see EAS for mode details)
+ * @mode: 0=off, 0xf=on (else see manual for mode details)
+ * @blink: true if the LED should blink when on, false if steady
+ *
+ * if this function is used to turn on the blink it should
+ * be used to disable the blink when restoring the original state.
  **/
-void i40e_led_set(struct i40e_hw *hw, u32 mode)
+void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink)
 {
-       u32 gpio_val = 0;
-       u32 led_mode = 0;
-       u32 port;
        int i;
 
-       for (i = 0; i < I40E_HW_CAP_MAX_GPIO; i++) {
-               if (!hw->func_caps.led[i])
-                       continue;
+       if (mode & 0xfffffff0)
+               hw_dbg(hw, "invalid mode passed in %X\n", mode);
 
-               gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(i));
-               port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK)
-                       >> I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
+       /* as per the documentation GPIO 22-29 are the LED
+        * GPIO pins named LED0..LED7
+        */
+       for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) {
+               u32 gpio_val = i40e_led_is_mine(hw, i);
 
-               if (port != hw->port)
+               if (!gpio_val)
                        continue;
 
-               led_mode = (mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) &
-                           I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;
                gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;
-               gpio_val |= led_mode;
+               /* this & is a bit of paranoia, but serves as a range check */
+               gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) &
+                            I40E_GLGEN_GPIO_CTL_LED_MODE_MASK);
+
+               if (mode == I40E_LINK_ACTIVITY)
+                       blink = false;
+
+               gpio_val |= (blink ? 1 : 0) <<
+                           I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT;
+
                wr32(hw, I40E_GLGEN_GPIO_CTL(i), gpio_val);
+               break;
        }
 }
 
index 255a138..0359c36 100644 (file)
@@ -916,13 +916,13 @@ static int i40e_set_phys_id(struct net_device *netdev,
                pf->led_status = i40e_led_get(hw);
                return blink_freq;
        case ETHTOOL_ID_ON:
-               i40e_led_set(hw, 0xF);
+               i40e_led_set(hw, 0xF, false);
                break;
        case ETHTOOL_ID_OFF:
-               i40e_led_set(hw, 0x0);
+               i40e_led_set(hw, 0x0, false);
                break;
        case ETHTOOL_ID_INACTIVE:
-               i40e_led_set(hw, pf->led_status);
+               i40e_led_set(hw, pf->led_status, false);
                break;
        }
 
index 5c458bb..0b6e9fc 100644 (file)
@@ -61,7 +61,7 @@ void i40e_debug_aq(struct i40e_hw *hw,
 void i40e_idle_aq(struct i40e_hw *hw);
 
 u32 i40e_led_get(struct i40e_hw *hw);
-void i40e_led_set(struct i40e_hw *hw, u32 mode);
+void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink);
 
 /* admin send queue commands */