summaryrefslogtreecommitdiffstats
path: root/hw/fsp/fsp-leds.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/fsp/fsp-leds.c')
-rw-r--r--hw/fsp/fsp-leds.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/hw/fsp/fsp-leds.c b/hw/fsp/fsp-leds.c
index bc0c663a..fde3cff7 100644
--- a/hw/fsp/fsp-leds.c
+++ b/hw/fsp/fsp-leds.c
@@ -201,25 +201,11 @@ static inline void opal_led_update_complete(u64 async_token, u64 result)
* occured with the recent SPCN command. Subsequent LED requests will
* be served with these updates changed to the list.
*/
-static void update_led_list(char *loc_code, u32 led_state)
+static void update_led_list(char *loc_code, u32 led_state, u32 excl_bit)
{
struct fsp_led_data *led = NULL, *encl_led = NULL, *encl_cec_led = NULL;
bool is_encl_led = is_enclosure_led(loc_code);
- if (is_encl_led)
- goto enclosure;
-
- /* Descendant LED in CEC list */
- led = fsp_find_cec_led(loc_code);
- if (!led) {
- log_simple_error(&e_info(OPAL_RC_LED_LC),
- PREFIX "Could not find descendent LED in CEC LC=%s\n",
- loc_code);
- return;
- }
- led->status = led_state;
-
-enclosure:
/* Enclosure LED in CEC list */
encl_cec_led = fsp_find_encl_cec_led(loc_code);
if (!encl_cec_led) {
@@ -229,6 +215,21 @@ enclosure:
return;
}
+ /* Update state */
+ if (is_encl_led) {
+ /* Enclosure exclusive bit */
+ encl_cec_led->excl_bit = excl_bit;
+ } else { /* Descendant LED in CEC list */
+ led = fsp_find_cec_led(loc_code);
+ if (!led) {
+ log_simple_error(&e_info(OPAL_RC_LED_LC), PREFIX
+ "Could not find descendent LED in \
+ CEC LC=%s\n", loc_code);
+ return;
+ }
+ led->status = led_state;
+ }
+
/* Enclosure LED in ENCL list */
encl_led = fsp_find_encl_encl_led(loc_code);
if (!encl_led) {
@@ -296,7 +297,8 @@ static void fsp_spcn_set_led_completion(struct fsp_msg *msg)
cmd |= FSP_STATUS_GENERIC_ERROR;
/* Rollback the changes */
- update_led_list(spcn_cmd->loc_code, spcn_cmd->ckpt_status);
+ update_led_list(spcn_cmd->loc_code,
+ spcn_cmd->ckpt_status, spcn_cmd->ckpt_excl_bit);
}
/* FSP initiated SPCN command */
@@ -382,6 +384,7 @@ static int fsp_msg_set_led_state(struct led_set_cmd *spcn_cmd)
* command eventually fails.
*/
spcn_cmd->ckpt_status = led->status;
+ spcn_cmd->ckpt_excl_bit = led->excl_bit;
sled.state = led->status;
/* Update the exclussive LED bits */
@@ -436,7 +439,7 @@ static int fsp_msg_set_led_state(struct led_set_cmd *spcn_cmd)
* Update the local lists based on the attempted SPCN command to
* set/reset an individual led (CEC or ENCL).
*/
- update_led_list(spcn_cmd->loc_code, sled.state);
+ update_led_list(spcn_cmd->loc_code, sled.state, led->excl_bit);
msg->user_data = spcn_cmd;
rc = fsp_queue_msg(msg, fsp_spcn_set_led_completion);
@@ -445,7 +448,8 @@ static int fsp_msg_set_led_state(struct led_set_cmd *spcn_cmd)
fsp_freemsg(msg);
free(spcn_cmd);
/* Revert LED state update */
- update_led_list(spcn_cmd->loc_code, spcn_cmd->ckpt_status);
+ update_led_list(spcn_cmd->loc_code, spcn_cmd->ckpt_status,
+ spcn_cmd->ckpt_excl_bit);
}
update_fail:
OpenPOWER on IntegriCloud