staging/rdma/hfi1: Implement LED beaconing for maintenance
authorEaswar Hariharan <easwar.hariharan@intel.com>
Wed, 3 Feb 2016 22:35:57 +0000 (14:35 -0800)
committerDoug Ledford <dledford@redhat.com>
Fri, 11 Mar 2016 01:37:57 +0000 (20:37 -0500)
This patch implements LED beaconing for maintenance. A MAD packet with
the LEDInfo attribute set to 1 will enable LED beaconing with a duty
cycle of 2s on and 1.5s off. A MAD packet with the LEDInfo attribute
set to 0 will disable beaconing and return the LED to normal operation.

Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Easwar Hariharan <easwar.hariharan@intel.com>
Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: Jubin John <jubin.john@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/staging/rdma/hfi1/driver.c
drivers/staging/rdma/hfi1/hfi.h
drivers/staging/rdma/hfi1/init.c
drivers/staging/rdma/hfi1/mad.c

index 59ce85f8d155b42c1c0f3dd220451f09c367019a..5d012feaa4d413bc54b923d59e4dce0f3f47dbd0 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2015 Intel Corporation.
+ * Copyright(c) 2015, 2016 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -18,7 +18,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2015 Intel Corporation.
+ * Copyright(c) 2015, 2016 Intel Corporation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1172,63 +1172,64 @@ int hfi1_set_lid(struct hfi1_pportdata *ppd, u32 lid, u8 lmc)
        return 0;
 }
 
-/*
- * Following deal with the "obviously simple" task of overriding the state
- * of the LEDs, which normally indicate link physical and logical status.
- * The complications arise in dealing with different hardware mappings
- * and the board-dependent routine being called from interrupts.
- * and then there's the requirement to _flash_ them.
- */
-#define LED_OVER_FREQ_SHIFT 8
-#define LED_OVER_FREQ_MASK (0xFF<<LED_OVER_FREQ_SHIFT)
-/* Below is "non-zero" to force override, but both actual LEDs are off */
-#define LED_OVER_BOTH_OFF (8)
+void shutdown_led_override(struct hfi1_pportdata *ppd)
+{
+       struct hfi1_devdata *dd = ppd->dd;
+
+       if (atomic_read(&ppd->led_override_timer_active)) {
+               del_timer_sync(&ppd->led_override_timer);
+               atomic_set(&ppd->led_override_timer_active, 0);
+       }
+
+       /* Shut off LEDs after we are sure timer is not running */
+       setextled(dd, 0);
+}
 
 static void run_led_override(unsigned long opaque)
 {
        struct hfi1_pportdata *ppd = (struct hfi1_pportdata *)opaque;
        struct hfi1_devdata *dd = ppd->dd;
-       int timeoff;
-       int ph_idx;
+       unsigned long timeout;
+       int phase_idx;
 
        if (!(dd->flags & HFI1_INITTED))
                return;
 
-       ph_idx = ppd->led_override_phase++ & 1;
-       ppd->led_override = ppd->led_override_vals[ph_idx];
-       timeoff = ppd->led_override_timeoff;
+       phase_idx = ppd->led_override_phase & 1;
+       setextled(dd, phase_idx);
+
+       timeout = ppd->led_override_vals[phase_idx];
+       /* Set up for next phase */
+       ppd->led_override_phase = !ppd->led_override_phase;
 
        /*
         * don't re-fire the timer if user asked for it to be off; we let
         * it fire one more time after they turn it off to simplify
         */
        if (ppd->led_override_vals[0] || ppd->led_override_vals[1])
-               mod_timer(&ppd->led_override_timer, jiffies + timeoff);
+               mod_timer(&ppd->led_override_timer, jiffies + timeout);
+       else
+               /* Hand control of the LED to the DC for normal operation */
+               write_csr(dd, DCC_CFG_LED_CNTRL, 0);
 }
 
-void hfi1_set_led_override(struct hfi1_pportdata *ppd, unsigned int val)
+/*
+ * To have the LED blink in a particular pattern, provide timeon and timeoff
+ * in milliseconds. To turn off custom blinking and return to normal operation,
+ * provide timeon = timeoff = 0.
+ */
+void hfi1_set_led_override(struct hfi1_pportdata *ppd, unsigned int timeon,
+                          unsigned int timeoff)
 {
        struct hfi1_devdata *dd = ppd->dd;
-       int timeoff, freq;
 
        if (!(dd->flags & HFI1_INITTED))
                return;
 
-       /* First check if we are blinking. If not, use 1HZ polling */
-       timeoff = HZ;
-       freq = (val & LED_OVER_FREQ_MASK) >> LED_OVER_FREQ_SHIFT;
-
-       if (freq) {
-               /* For blink, set each phase from one nybble of val */
-               ppd->led_override_vals[0] = val & 0xF;
-               ppd->led_override_vals[1] = (val >> 4) & 0xF;
-               timeoff = (HZ << 4)/freq;
-       } else {
-               /* Non-blink set both phases the same. */
-               ppd->led_override_vals[0] = val & 0xF;
-               ppd->led_override_vals[1] = val & 0xF;
-       }
-       ppd->led_override_timeoff = timeoff;
+       /* Convert to jiffies for direct use in timer */
+       ppd->led_override_vals[0] = msecs_to_jiffies(timeoff);
+       ppd->led_override_vals[1] = msecs_to_jiffies(timeon);
+       ppd->led_override_phase = 1; /* Arbitrarily start from LED on phase */
 
        /*
         * If the timer has not already been started, do so. Use a "quick"
@@ -1293,14 +1294,8 @@ int hfi1_reset_device(int unit)
 
        for (pidx = 0; pidx < dd->num_pports; ++pidx) {
                ppd = dd->pport + pidx;
-               if (atomic_read(&ppd->led_override_timer_active)) {
-                       /* Need to stop LED timer, _then_ shut off LEDs */
-                       del_timer_sync(&ppd->led_override_timer);
-                       atomic_set(&ppd->led_override_timer_active, 0);
-               }
 
-               /* Shut off LEDs after we are sure timer is not running */
-               ppd->led_override = LED_OVER_BOTH_OFF;
+               shutdown_led_override(ppd);
        }
        if (dd->flags & HFI1_HAS_SEND_DMA)
                sdma_exit(dd);
index da429915e5dbc0a4c21c882b8d3bbea86a890941..18508c9423a9bf8807e28df01baa3de78e552fcb 100644 (file)
@@ -7,7 +7,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2015 Intel Corporation.
+ * Copyright(c) 2015, 2016 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -20,7 +20,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2015 Intel Corporation.
+ * Copyright(c) 2015, 2016 Intel Corporation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -669,14 +669,17 @@ struct hfi1_pportdata {
        u8 overrun_threshold;
        u8 phy_error_threshold;
 
-       /* used to override LED behavior */
-       u8 led_override;  /* Substituted for normal value, if non-zero */
-       u16 led_override_timeoff; /* delta to next timer event */
-       u8 led_override_vals[2]; /* Alternates per blink-frame */
-       u8 led_override_phase; /* Just counts, LSB picks from vals[] */
+       /* Used to override LED behavior for things like maintenance beaconing*/
+       /*
+        * Alternates per phase of blink
+        * [0] holds LED off duration, [1] holds LED on duration
+        */
+       unsigned long led_override_vals[2];
+       u8 led_override_phase; /* LSB picks from vals[] */
        atomic_t led_override_timer_active;
        /* Used to flash LEDs in override mode */
        struct timer_list led_override_timer;
+
        u32 sm_trap_qp;
        u32 sa_qp;
 
@@ -1599,14 +1602,14 @@ void hfi1_free_devdata(struct hfi1_devdata *);
 void cc_state_reclaim(struct rcu_head *rcu);
 struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, size_t extra);
 
+void hfi1_set_led_override(struct hfi1_pportdata *ppd, unsigned int timeon,
+                          unsigned int timeoff);
 /*
- * Set LED override, only the two LSBs have "public" meaning, but
- * any non-zero value substitutes them for the Link and LinkTrain
- * LED states.
+ * Only to be used for driver unload or device reset where we cannot allow
+ * the timer to fire even the one extra time, else use hfi1_set_led_override
+ * with timeon = timeoff = 0
  */
-#define HFI1_LED_PHYS 1 /* Physical (linktraining) GREEN LED */
-#define HFI1_LED_LOG 2  /* Logical (link) YELLOW LED */
-void hfi1_set_led_override(struct hfi1_pportdata *ppd, unsigned int val);
+void shutdown_led_override(struct hfi1_pportdata *ppd);
 
 #define HFI1_CREDIT_RETURN_RATE (100)
 
index eec91305516a8d735fcbb8ae7dfc4d2b6e2c4d1a..fe5e1e57307b69c8e8eb28cb92785eff67e5f192 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2015 Intel Corporation.
+ * Copyright(c) 2015, 2016 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -18,7 +18,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2015 Intel Corporation.
+ * Copyright(c) 2015, 2016 Intel Corporation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -908,6 +908,8 @@ static void shutdown_device(struct hfi1_devdata *dd)
                /* disable the send device */
                pio_send_control(dd, PSC_GLOBAL_DISABLE);
 
+               shutdown_led_override(ppd);
+
                /*
                 * Clear SerdesEnable.
                 * We can't count on interrupts since we are stopping.
index 5146f5df7a10be249034f4f9d8a720a2551e803d..6976f93bd36f16de62dc88428d5763eb98b559b9 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2015 Intel Corporation.
+ * Copyright(c) 2015, 2016 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -18,7 +18,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2015 Intel Corporation.
+ * Copyright(c) 2015, 2016 Intel Corporation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -3449,7 +3449,10 @@ static int __subn_set_opa_led_info(struct opa_smp *smp, u32 am, u8 *data,
                return reply((struct ib_mad_hdr *)smp);
        }
 
-       setextled(dd, on);
+       if (on)
+               hfi1_set_led_override(dd->pport, 2000, 1500);
+       else
+               hfi1_set_led_override(dd->pport, 0, 0);
 
        return __subn_get_opa_led_info(smp, am, data, ibdev, port, resp_len);
 }