Commit 91ab4ed3 authored by Easwar Hariharan's avatar Easwar Hariharan Committed by Doug Ledford

staging/rdma/hfi1: Implement LED beaconing for maintenance

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: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarEaswar Hariharan <easwar.hariharan@intel.com>
Signed-off-by: default avatarMitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: default avatarJubin John <jubin.john@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 7b0b01aa
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2015 Intel Corporation. * Copyright(c) 2015, 2016 Intel Corporation.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -1172,63 +1172,64 @@ int hfi1_set_lid(struct hfi1_pportdata *ppd, u32 lid, u8 lmc) ...@@ -1172,63 +1172,64 @@ int hfi1_set_lid(struct hfi1_pportdata *ppd, u32 lid, u8 lmc)
return 0; return 0;
} }
/* void shutdown_led_override(struct hfi1_pportdata *ppd)
* Following deal with the "obviously simple" task of overriding the state {
* of the LEDs, which normally indicate link physical and logical status. struct hfi1_devdata *dd = ppd->dd;
* The complications arise in dealing with different hardware mappings
* and the board-dependent routine being called from interrupts. if (atomic_read(&ppd->led_override_timer_active)) {
* and then there's the requirement to _flash_ them. del_timer_sync(&ppd->led_override_timer);
*/ atomic_set(&ppd->led_override_timer_active, 0);
#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 */ /* Shut off LEDs after we are sure timer is not running */
#define LED_OVER_BOTH_OFF (8) setextled(dd, 0);
}
static void run_led_override(unsigned long opaque) static void run_led_override(unsigned long opaque)
{ {
struct hfi1_pportdata *ppd = (struct hfi1_pportdata *)opaque; struct hfi1_pportdata *ppd = (struct hfi1_pportdata *)opaque;
struct hfi1_devdata *dd = ppd->dd; struct hfi1_devdata *dd = ppd->dd;
int timeoff; unsigned long timeout;
int ph_idx; int phase_idx;
if (!(dd->flags & HFI1_INITTED)) if (!(dd->flags & HFI1_INITTED))
return; return;
ph_idx = ppd->led_override_phase++ & 1; phase_idx = ppd->led_override_phase & 1;
ppd->led_override = ppd->led_override_vals[ph_idx]; setextled(dd, phase_idx);
timeoff = ppd->led_override_timeoff;
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 * 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 * it fire one more time after they turn it off to simplify
*/ */
if (ppd->led_override_vals[0] || ppd->led_override_vals[1]) 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; struct hfi1_devdata *dd = ppd->dd;
int timeoff, freq;
if (!(dd->flags & HFI1_INITTED)) if (!(dd->flags & HFI1_INITTED))
return; return;
/* First check if we are blinking. If not, use 1HZ polling */ /* Convert to jiffies for direct use in timer */
timeoff = HZ; ppd->led_override_vals[0] = msecs_to_jiffies(timeoff);
freq = (val & LED_OVER_FREQ_MASK) >> LED_OVER_FREQ_SHIFT; ppd->led_override_vals[1] = msecs_to_jiffies(timeon);
ppd->led_override_phase = 1; /* Arbitrarily start from LED on phase */
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;
/* /*
* If the timer has not already been started, do so. Use a "quick" * If the timer has not already been started, do so. Use a "quick"
...@@ -1293,14 +1294,8 @@ int hfi1_reset_device(int unit) ...@@ -1293,14 +1294,8 @@ int hfi1_reset_device(int unit)
for (pidx = 0; pidx < dd->num_pports; ++pidx) { for (pidx = 0; pidx < dd->num_pports; ++pidx) {
ppd = dd->pport + 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 */ shutdown_led_override(ppd);
ppd->led_override = LED_OVER_BOTH_OFF;
} }
if (dd->flags & HFI1_HAS_SEND_DMA) if (dd->flags & HFI1_HAS_SEND_DMA)
sdma_exit(dd); sdma_exit(dd);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2015 Intel Corporation. * Copyright(c) 2015, 2016 Intel Corporation.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -669,14 +669,17 @@ struct hfi1_pportdata { ...@@ -669,14 +669,17 @@ struct hfi1_pportdata {
u8 overrun_threshold; u8 overrun_threshold;
u8 phy_error_threshold; u8 phy_error_threshold;
/* used to override LED behavior */ /* Used to override LED behavior for things like maintenance beaconing*/
u8 led_override; /* Substituted for normal value, if non-zero */ /*
u16 led_override_timeoff; /* delta to next timer event */ * Alternates per phase of blink
u8 led_override_vals[2]; /* Alternates per blink-frame */ * [0] holds LED off duration, [1] holds LED on duration
u8 led_override_phase; /* Just counts, LSB picks from vals[] */ */
unsigned long led_override_vals[2];
u8 led_override_phase; /* LSB picks from vals[] */
atomic_t led_override_timer_active; atomic_t led_override_timer_active;
/* Used to flash LEDs in override mode */ /* Used to flash LEDs in override mode */
struct timer_list led_override_timer; struct timer_list led_override_timer;
u32 sm_trap_qp; u32 sm_trap_qp;
u32 sa_qp; u32 sa_qp;
...@@ -1599,14 +1602,14 @@ void hfi1_free_devdata(struct hfi1_devdata *); ...@@ -1599,14 +1602,14 @@ void hfi1_free_devdata(struct hfi1_devdata *);
void cc_state_reclaim(struct rcu_head *rcu); void cc_state_reclaim(struct rcu_head *rcu);
struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, size_t extra); 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 * Only to be used for driver unload or device reset where we cannot allow
* any non-zero value substitutes them for the Link and LinkTrain * the timer to fire even the one extra time, else use hfi1_set_led_override
* LED states. * with timeon = timeoff = 0
*/ */
#define HFI1_LED_PHYS 1 /* Physical (linktraining) GREEN LED */ void shutdown_led_override(struct hfi1_pportdata *ppd);
#define HFI1_LED_LOG 2 /* Logical (link) YELLOW LED */
void hfi1_set_led_override(struct hfi1_pportdata *ppd, unsigned int val);
#define HFI1_CREDIT_RETURN_RATE (100) #define HFI1_CREDIT_RETURN_RATE (100)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2015 Intel Corporation. * Copyright(c) 2015, 2016 Intel Corporation.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -908,6 +908,8 @@ static void shutdown_device(struct hfi1_devdata *dd) ...@@ -908,6 +908,8 @@ static void shutdown_device(struct hfi1_devdata *dd)
/* disable the send device */ /* disable the send device */
pio_send_control(dd, PSC_GLOBAL_DISABLE); pio_send_control(dd, PSC_GLOBAL_DISABLE);
shutdown_led_override(ppd);
/* /*
* Clear SerdesEnable. * Clear SerdesEnable.
* We can't count on interrupts since we are stopping. * We can't count on interrupts since we are stopping.
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * 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 * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2015 Intel Corporation. * Copyright(c) 2015, 2016 Intel Corporation.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * 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, ...@@ -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); 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); return __subn_get_opa_led_info(smp, am, data, ibdev, port, resp_len);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment