diff options
-rw-r--r-- | hw/fsp/fsp-leds.c | 127 | ||||
-rw-r--r-- | include/fsp.h | 4 |
2 files changed, 62 insertions, 69 deletions
diff --git a/hw/fsp/fsp-leds.c b/hw/fsp/fsp-leds.c index 327adb2..07785b7 100644 --- a/hw/fsp/fsp-leds.c +++ b/hw/fsp/fsp-leds.c @@ -244,9 +244,29 @@ enclosure: encl_led->excl_bit = encl_cec_led->excl_bit; } +static int fsp_set_led_response(uint32_t cmd) +{ + struct fsp_msg *msg; + int rc = -1; + + msg = fsp_mkmsg(cmd, 0); + if (!msg) { + prerror(PREFIX + "Failed to allocate FSP_RSP_SET_LED_STATE [cmd=%x])\n", + cmd); + } else { + rc = fsp_queue_msg(msg, fsp_freemsg); + if (rc != OPAL_SUCCESS) { + fsp_freemsg(msg); + prerror(PREFIX "Failed to queue " + "FSP_RSP_SET_LED_STATE [cmd=%x]\n", cmd); + } + } + return rc; +} + static void fsp_spcn_set_led_completion(struct fsp_msg *msg) { - struct fsp_msg *smsg = NULL; struct fsp_msg *resp = msg->resp; u32 cmd = FSP_RSP_SET_LED_STATE; u8 status = resp->word1 & 0xff00; @@ -272,19 +292,8 @@ static void fsp_spcn_set_led_completion(struct fsp_msg *msg) } /* FSP initiated SPCN command */ - if (spcn_cmd->cmd_src == SPCN_SRC_FSP) { - smsg = fsp_mkmsg(cmd, 0); - if (!smsg) { - prerror(PREFIX - "Failed to allocate FSP_RSP_SET_LED_STATE\n"); - } else { - if (fsp_queue_msg(smsg, fsp_freemsg)) { - fsp_freemsg(smsg); - prerror(PREFIX "Failed to queue " - "FSP_RSP_SET_LED_STATE\n"); - } - } - } + if (spcn_cmd->cmd_src == SPCN_SRC_FSP) + fsp_set_led_response(cmd); unlock(&led_lock); @@ -318,6 +327,7 @@ static int fsp_msg_set_led_state(struct led_set_cmd *spcn_cmd) void *buf = led_buffer; u16 data_len = 0; u32 cmd_hdr = 0; + u32 cmd = FSP_RSP_SET_LED_STATE; int rc = -1; sled.lc_len = strlen(spcn_cmd->loc_code); @@ -335,22 +345,9 @@ static int fsp_msg_set_led_state(struct led_set_cmd *spcn_cmd) /* LED not present */ if (led == NULL) { - u32 cmd = 0; - struct fsp_msg *msg = NULL; - - cmd = FSP_RSP_SET_LED_STATE | FSP_STATUS_INVALID_LC; - msg = fsp_mkmsg(cmd, 0); - if (!msg) { - prerror(PREFIX "Could not allocate " - "FSP_RSP_SET_LED_STATE | " - "FSP_STATUS_INVALID_LC\n"); - } else { - if (fsp_queue_msg(msg, fsp_freemsg)) { - fsp_freemsg(msg); - prerror(PREFIX "Couldn't queue " - "FSP_RSP_SET_LED_STATE" - "|FSP_STATUS_INVALID_LC\n"); - } + if (spcn_cmd->cmd_src == SPCN_SRC_FSP) { + cmd |= FSP_STATUS_INVALID_LC; + fsp_set_led_response(cmd); } unlock(&led_lock); @@ -407,9 +404,10 @@ static int fsp_msg_set_led_state(struct led_set_cmd *spcn_cmd) msg = fsp_mkmsg(FSP_CMD_SPCN_PASSTHRU, 4, SPCN_ADDR_MODE_CEC_NODE, cmd_hdr, 0, PSI_DMA_LED_BUF); if (!msg) { - unlock(&led_lock); free(spcn_cmd); - return rc; + cmd |= FSP_STATUS_GENERIC_ERROR; + rc = -1; + goto update_fail; } /* @@ -421,12 +419,23 @@ static int fsp_msg_set_led_state(struct led_set_cmd *spcn_cmd) rc = fsp_queue_msg(msg, fsp_spcn_set_led_completion); if (rc != OPAL_SUCCESS) { + cmd |= FSP_STATUS_GENERIC_ERROR; fsp_freemsg(msg); free(spcn_cmd); /* Revert LED state update */ update_led_list(spcn_cmd->loc_code, spcn_cmd->ckpt_status); } +update_fail: + if (rc) { + log_simple_error(&e_info(OPAL_RC_LED_STATE), + PREFIX "Set led state failed at LC=%s\n", + spcn_cmd->loc_code); + + if (spcn_cmd->cmd_src == SPCN_SRC_FSP) + fsp_set_led_response(cmd); + } + unlock(&led_lock); return rc; } @@ -458,12 +467,7 @@ static int process_led_state_change(void) spcn_cmd = list_pop(&spcn_cmdq, struct led_set_cmd, link); unlock(&spcn_cmd_lock); - rc = fsp_msg_set_led_state(spcn_cmd); - if (rc) - log_simple_error(&e_info(OPAL_RC_LED_STATE), - PREFIX "Set led state failed at LC=%s\n", - spcn_cmd->loc_code); - + fsp_msg_set_led_state(spcn_cmd); return rc; } @@ -869,25 +873,13 @@ static void fsp_set_led_state(struct fsp_msg *msg) u32 tce_token = msg->data.words[1]; bool command, state; void *buf; - struct fsp_msg *resp; + int rc; /* Parse the inbound buffer */ buf = fsp_inbound_buf_from_tce(tce_token); if (!buf) { - struct fsp_msg *msg; - msg = fsp_mkmsg(FSP_RSP_SET_LED_STATE | - FSP_STATUS_INVALID_DATA, - 0); - if (!msg) { - prerror(PREFIX "Couldn't allocate FSP_RSP_SET_LED_STATE |" - " FSP_STATUS_INVALID_DATA\n"); - return; - } - if (fsp_queue_msg(msg, fsp_freemsg)) { - fsp_freemsg(msg); - prerror(PREFIX "Couldn't queue FSP_RSP_SET_LED_STATE |" - " FSP_STATUS_INVALID_DATA\n"); - } + fsp_set_led_response(FSP_RSP_SET_LED_STATE | + FSP_STATUS_INVALID_DATA); return; } memcpy(&req, buf, sizeof(req)); @@ -927,28 +919,25 @@ static void fsp_set_led_state(struct fsp_msg *msg) if (!strcmp(led->loc_code, req.loc_code)) continue; - queue_led_state_change(led->loc_code, - command, state, SPCN_SRC_FSP); + rc = queue_led_state_change(led->loc_code, command, + state, SPCN_SRC_FSP); + if (rc != 0) + fsp_set_led_response(FSP_RSP_SET_LED_STATE | + FSP_STATUS_GENERIC_ERROR); } break; case SET_IND_SINGLE_LOC_CODE: /* Set led state for single descendent led */ - queue_led_state_change(req.loc_code, - command, state, SPCN_SRC_FSP); + rc = queue_led_state_change(req.loc_code, + command, state, SPCN_SRC_FSP); + if (rc != 0) + fsp_set_led_response(FSP_RSP_SET_LED_STATE | + FSP_STATUS_GENERIC_ERROR); break; default: - resp = fsp_mkmsg(FSP_RSP_SET_LED_STATE | - FSP_STATUS_NOT_SUPPORTED, 0); - if (!resp) { - prerror(PREFIX "Unable to alloc FSP_RSP_SET_LED_STATE |" - " FSP_STATUS_NOT_SUPPORTED\n"); - break; - } - if (fsp_queue_msg(resp, fsp_freemsg)) { - fsp_freemsg(resp); - prerror(PREFIX "Failed to queue FSP_RSP_SET_LED_STATE |" - " FSP_STATUS_NOT_SUPPORTED\n"); - } + fsp_set_led_response(FSP_RSP_SET_LED_STATE | + FSP_STATUS_NOT_SUPPORTED); + break; } } diff --git a/include/fsp.h b/include/fsp.h index c960469..66fadb1 100644 --- a/include/fsp.h +++ b/include/fsp.h @@ -69,8 +69,12 @@ #define FSP_STAUS_INVALID_HMC_ID 0x51 #define FSP_STATUS_SPCN_ERROR 0xA8 /* SPCN error */ #define FSP_STATUS_INVALID_LC 0xC0 /* Invalid location code */ +#define FSP_STATUS_ENCL_IND_RESET 0xC2 /* Enclosure Indicator cannot be reset */ #define FSP_STATUS_TOD_RESET 0xA9 /* TOD reset due to invalid state at POR */ #define FSP_STATUS_TOD_PERMANENT_ERROR 0xAF /* Permanent error in TOD */ +#define FSP_STATUS_I2C_TRANS_ERROR 0xE4 /* I2C device / transmission error */ +#define FSP_STATUS_IND_PARTIAL_SUCCESS 0xE5 /* Indicator partial success */ +#define FSP_STATUS_GENERIC_FAILURE 0xEF /* Generic Failure in execution */ /* * FSP registers |