summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/common/block/cse/cse_eop.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/src/soc/intel/common/block/cse/cse_eop.c b/src/soc/intel/common/block/cse/cse_eop.c
index bc6d83764ea4..c6b527778f50 100644
--- a/src/soc/intel/common/block/cse/cse_eop.c
+++ b/src/soc/intel/common/block/cse/cse_eop.c
@@ -11,13 +11,29 @@
#include <timestamp.h>
#include <types.h>
+#define CSE_MAX_RETRY_CMD 3
+
enum cse_cmd_result {
CSE_CMD_RESULT_GLOBAL_RESET_REQUESTED,
CSE_CMD_RESULT_SUCCESS,
CSE_CMD_RESULT_ERROR,
CSE_CMD_RESULT_DISABLED,
+ CSE_CMD_RESULT_RETRY,
};
+static enum cse_cmd_result decode_heci_send_receive_error(enum cse_tx_rx_status ret)
+{
+ switch (ret) {
+ case CSE_TX_ERR_CSE_NOT_READY:
+ case CSE_RX_ERR_CSE_NOT_READY:
+ case CSE_RX_ERR_RESP_LEN_MISMATCH:
+ case CSE_RX_ERR_TIMEOUT:
+ return CSE_CMD_RESULT_RETRY;
+ default:
+ return CSE_CMD_RESULT_ERROR;
+ }
+}
+
static bool cse_disable_mei_bus(void)
{
struct bus_disable_message {
@@ -49,6 +65,7 @@ static bool cse_disable_mei_bus(void)
static enum cse_cmd_result cse_send_eop(void)
{
+ enum cse_tx_rx_status ret;
enum {
EOP_REQUESTED_ACTION_CONTINUE = 0,
EOP_REQUESTED_ACTION_GLOBAL_RESET = 1,
@@ -98,10 +115,9 @@ static enum cse_cmd_result cse_send_eop(void)
printk(BIOS_INFO, "HECI: Sending End-of-Post\n");
- if (heci_send_receive(&msg, sizeof(msg), &resp, &resp_size, HECI_MKHI_ADDR)) {
- printk(BIOS_ERR, "HECI: EOP send/receive fail\n");
- return CSE_CMD_RESULT_ERROR;
- }
+ ret = heci_send_receive(&msg, sizeof(msg), &resp, &resp_size, HECI_MKHI_ADDR);
+ if (ret)
+ return decode_heci_send_receive_error(ret);
if (resp.hdr.result) {
printk(BIOS_ERR, "HECI: EOP Resp Failed: %u\n", resp.hdr.result);
@@ -123,6 +139,18 @@ static enum cse_cmd_result cse_send_eop(void)
}
}
+static enum cse_cmd_result cse_send_cmd_retries(enum cse_cmd_result (*cse_send_command)(void))
+{
+ size_t retry;
+ enum cse_cmd_result ret;
+ for (retry = 0; retry < CSE_MAX_RETRY_CMD; retry++) {
+ ret = cse_send_command();
+ if (ret != CSE_CMD_RESULT_RETRY)
+ break;
+ }
+ return ret;
+}
+
/*
* On EOP error, the BIOS is required to send an MEI bus disable message to the
* CSE, followed by disabling all MEI devices. After successfully completing
@@ -193,7 +221,7 @@ static void do_send_end_of_post(void)
set_cse_device_state(PCH_DEVFN_CSE, DEV_ACTIVE);
timestamp_add_now(TS_ME_END_OF_POST_START);
- handle_cse_eop_result(cse_send_eop());
+ handle_cse_eop_result(cse_send_cmd_retries(cse_send_eop));
timestamp_add_now(TS_ME_END_OF_POST_END);
set_cse_device_state(PCH_DEVFN_CSE, DEV_IDLE);