From 5bc3dc3bbe8f062b39065678638b820de330dee2 Mon Sep 17 00:00:00 2001 From: Alec Berg Date: Wed, 10 Sep 2014 03:49:34 -0700 Subject: samus: add automatic retries for host commands from EC to PD Add three retries for EC to PD host commands. With this change, removed retry mechanism in host_command_pd.c which was a retry only for the specific EC_CMD_PD_EXCHANGE_STATUS host command. BUG=chrome-os-partner:32006 BRANCH=none TEST=Loaded EC code onto samus. Added the following code for testing failed host commands to samus_pd common/host_command.c host_command_task(): if ((evt & TASK_EVENT_CMD_PENDING) && pending_args) { if (i++ != 4) pending_args->result = host_command_process(pending_args); else { pending_args->result = -7; i = 0; } host_send_response(pending_args); } This test code on samus_pd drops one in every five host commands. With this code, from the EC, I send "pdcmd 0 0", and verified that 1 out of 5 times the EC prints a host command failed code, but then retries successfully. Change-Id: Ibf43feefbfc7d791c45c6689b82c66f5d71046ab Signed-off-by: Alec Berg Reviewed-on: https://chromium-review.googlesource.com/217461 Reviewed-by: Todd Broch --- common/host_command_master.c | 36 +++++++++++++++++++++++------------- common/host_command_pd.c | 10 ++-------- include/ec_commands.h | 3 ++- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/common/host_command_master.c b/common/host_command_master.c index 38acd9a560..11d0dbca06 100644 --- a/common/host_command_master.c +++ b/common/host_command_master.c @@ -20,6 +20,9 @@ /* Host command timeout */ #define HOST_COMMAND_TIMEOUT_US SECOND +/* Number of attempts for each PD host command */ +#define PD_HOST_COMMAND_ATTEMPTS 3 + static struct mutex pd_mutex; /** @@ -86,7 +89,7 @@ static int pd_host_command_internal(int command, int version, if (ret) { i2c_lock(I2C_PORT_PD_MCU, 0); CPRINTF("[%T i2c transaction 1 failed: %d]\n", ret); - return -ret; + return -EC_RES_BUS_ERROR; } resp_len = resp_buf[1]; @@ -107,7 +110,7 @@ static int pd_host_command_internal(int command, int version, i2c_lock(I2C_PORT_PD_MCU, 0); if (ret) { CPRINTF("[%T i2c transaction 2 failed: %d]\n", ret); - return -ret; + return -EC_RES_BUS_ERROR; } /* Check for host command error code */ @@ -151,7 +154,7 @@ static int pd_host_command_internal(int command, int version, if ((uint8_t)sum) { CPRINTF("[%T command 0x%02x bad checksum returned: " "%d]\n", command, sum); - return -EC_RES_ERROR; + return -EC_RES_INVALID_CHECKSUM; } /* Return output buffer size */ @@ -163,16 +166,23 @@ int pd_host_command(int command, int version, void *indata, int insize) { int rv; - - /* Acquire mutex */ - mutex_lock(&pd_mutex); - - /* Call internal version of host command */ - rv = pd_host_command_internal(command, version, outdata, outsize, - indata, insize); - - /* Release mutex */ - mutex_unlock(&pd_mutex); + int tries = 0; + + /* Try multiple times to send host command. */ + for (tries = 0; tries < PD_HOST_COMMAND_ATTEMPTS; tries++) { + /* Acquire mutex */ + mutex_lock(&pd_mutex); + /* Call internal version of host command */ + rv = pd_host_command_internal(command, version, outdata, + outsize, indata, insize); + /* Release mutex */ + mutex_unlock(&pd_mutex); + + /* If host command error due to i2c bus error, try again. */ + if (rv != -EC_RES_BUS_ERROR) + break; + task_wait_event(50*MSEC); + } return rv; } diff --git a/common/host_command_pd.c b/common/host_command_pd.c index ecd5e07cf5..444e9e3288 100644 --- a/common/host_command_pd.c +++ b/common/host_command_pd.c @@ -26,7 +26,7 @@ static void pd_exchange_status(void) { struct ec_params_pd_status ec_status; struct ec_response_pd_status pd_status; - int rv = 0, tries = 0; + int rv = 0; /* Send battery state of charge */ if (charge_get_flags() & CHARGE_FLAG_BATT_RESPONSIVE) @@ -34,15 +34,9 @@ static void pd_exchange_status(void) else ec_status.batt_soc = -1; - /* Try 3 times to get the PD MCU status. */ - while (tries++ < 3) { - rv = pd_host_command(EC_CMD_PD_EXCHANGE_STATUS, 0, &ec_status, + rv = pd_host_command(EC_CMD_PD_EXCHANGE_STATUS, 0, &ec_status, sizeof(struct ec_params_pd_status), &pd_status, sizeof(struct ec_response_pd_status)); - if (rv >= 0) - break; - task_wait_event(500*MSEC); - } if (rv < 0) { CPRINTS("Host command to PD MCU failed"); diff --git a/include/ec_commands.h b/include/ec_commands.h index 4428648511..951551769b 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -224,7 +224,8 @@ enum ec_status { EC_RES_OVERFLOW = 11, /* Table / data overflow */ EC_RES_INVALID_HEADER = 12, /* Header contains invalid data */ EC_RES_REQUEST_TRUNCATED = 13, /* Didn't get the entire request */ - EC_RES_RESPONSE_TOO_BIG = 14 /* Response was too big to handle */ + EC_RES_RESPONSE_TOO_BIG = 14, /* Response was too big to handle */ + EC_RES_BUS_ERROR = 15 /* Communications bus error */ }; /* -- cgit v1.2.1