summaryrefslogtreecommitdiffstats
path: root/hw/fsp/fsp-leds.c
diff options
context:
space:
mode:
authorVasant Hegde <hegdevasant@linux.vnet.ibm.com>2015-03-08 16:29:01 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-03-20 04:40:01 +1100
commit361ca244010ae0230d385850f06bb68e03b40c84 (patch)
tree03aea5d24d47cef616e21045533ebc23b575db7a /hw/fsp/fsp-leds.c
parent2a824b4c3935b3ba9d99c8bc00f4dd747f60dbea (diff)
downloadtalos-skiboot-361ca244010ae0230d385850f06bb68e03b40c84.tar.gz
talos-skiboot-361ca244010ae0230d385850f06bb68e03b40c84.zip
FSP/LEDS: Roll back exclusive bit in case FSP command queuing fails
Presently we update enclosure exclusive bit before making LED update SPCN passthrough command and not reverting if this command fails. So we endup having wrong state if SPCN passthrough command fails. This patch fixes above described issue. Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
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