summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Broch <tbroch@chromium.org>2015-01-02 20:30:21 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-07 08:45:38 +0000
commit5ef45ad19e839006a17668d792770021e022f3c8 (patch)
treec7c1a37cba02756ce2c012559c7500f30b7666d7
parentc0f64b13e981fd0c2901e1c33d7f6e52287ca0df (diff)
downloadchrome-ec-5ef45ad19e839006a17668d792770021e022f3c8.tar.gz
pd: Add timeout for HC flash commands.
For flash commands add timeout so if VDM doesn't return properly host can receive error message. Note, for flash erase its performed by page at a cost of 20-40ms according to datasheet. For hoho/dingdong that leaves maximum erase time at 40ms * 32 =< 1280ms which is above the host command timeout. Increasing the host command delay (i2c bus pending) is not an option and since the erase will complete and subsequent erases will be much faster do to early out in physical_flash_erase this solution should be acceptable. Future CLs could alternatively push the burden of command latency to host altogether and return EC_RES_SUCCESS in similar fashion to reboot command. Signed-off-by: Todd Broch <tbroch@chromium.org> BRANCH=samus BUG=chrome-os-partner:33947 TEST=manual, if VDM doesn't return by timeout HC command is properly returned EC_RES_TIMEOUT error code. Change-Id: I33c515200c2999dd97fdd690a7e900c5548b2d47 Reviewed-on: https://chromium-review.googlesource.com/238290 Reviewed-by: Alec Berg <alecaberg@chromium.org> Tested-by: Todd Broch <tbroch@chromium.org> Commit-Queue: Todd Broch <tbroch@chromium.org>
-rw-r--r--common/host_command_master.c6
-rw-r--r--common/usb_pd_protocol.c39
-rw-r--r--include/usb_pd.h3
3 files changed, 31 insertions, 17 deletions
diff --git a/common/host_command_master.c b/common/host_command_master.c
index 11d0dbca06..39bbf37df5 100644
--- a/common/host_command_master.c
+++ b/common/host_command_master.c
@@ -11,15 +11,13 @@
#include "i2c.h"
#include "task.h"
#include "timer.h"
+#include "usb_pd.h"
#include "util.h"
/* Console output macros */
#define CPUTS(outstr) cputs(CC_HOSTCMD, outstr)
#define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ## args)
-/* Host command timeout */
-#define HOST_COMMAND_TIMEOUT_US SECOND
-
/* Number of attempts for each PD host command */
#define PD_HOST_COMMAND_ATTEMPTS 3
@@ -81,7 +79,7 @@ static int pd_host_command_internal(int command, int version,
* length.
*/
i2c_lock(I2C_PORT_PD_MCU, 1);
- i2c_set_timeout(I2C_PORT_PD_MCU, HOST_COMMAND_TIMEOUT_US);
+ i2c_set_timeout(I2C_PORT_PD_MCU, PD_HOST_COMMAND_TIMEOUT_US);
ret = i2c_xfer(I2C_PORT_PD_MCU, CONFIG_USB_PD_I2C_SLAVE_ADDR,
&req_buf[0], outsize + sizeof(rq) + 1, &resp_buf[0],
2, I2C_XFER_START);
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 98b14a2736..9d9c9d2178 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -3053,6 +3053,7 @@ static int hc_remote_flash(struct host_cmd_handler_args *args)
int port = p->port;
const uint32_t *data = &(p->size) + 1;
int i, size;
+ timestamp_t timeout;
if (p->size + sizeof(*p) > args->params_size)
return EC_RES_INVALID_PARAM;
@@ -3073,23 +3074,24 @@ static int hc_remote_flash(struct host_cmd_handler_args *args)
pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0);
/* Delay to give time for device to reboot */
- usleep(900 * MSEC);
+ usleep(PD_HOST_COMMAND_TIMEOUT_US - 100*MSEC);
return EC_RES_SUCCESS;
case USB_PD_FW_FLASH_ERASE:
pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0);
-
- /* Wait until VDM is done */
- while (pd[port].vdm_state > 0)
- task_wait_event(100*MSEC);
+ /*
+ * TODO: Note, page erase for 2K is 20-40msec while host command
+ * timeout is 1sec so this can't be longer. In practice,
+ * for 32 pages, its passed. Better way to implement may be to
+ * push burden to HOST to manage latency.
+ */
+ timeout.val = get_time().val +
+ PD_HOST_COMMAND_TIMEOUT_US - 100*MSEC;
break;
case USB_PD_FW_ERASE_SIG:
pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0);
-
- /* Wait until VDM is done */
- while (pd[port].vdm_state > 0)
- task_wait_event(100*MSEC);
+ timeout.val = get_time().val + 500*MSEC;
break;
case USB_PD_FW_FLASH_WRITE:
@@ -3101,22 +3103,33 @@ static int hc_remote_flash(struct host_cmd_handler_args *args)
for (i = 0; i < size; i += VDO_MAX_SIZE - 1) {
pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE,
data + i, MIN(size - i, VDO_MAX_SIZE - 1));
+ timeout.val = get_time().val + 500*MSEC;
/* Wait until VDM is done */
- while (pd[port].vdm_state > 0)
+ while ((pd[port].vdm_state > 0) &&
+ (get_time().val < timeout.val))
task_wait_event(10*MSEC);
+
+ if (pd[port].vdm_state > 0)
+ return EC_RES_TIMEOUT;
}
- break;
+ return EC_RES_SUCCESS;
default:
return EC_RES_INVALID_PARAM;
break;
}
+ /* Wait until VDM is done or timeout */
+ while ((pd[port].vdm_state > 0) && (get_time().val < timeout.val))
+ task_wait_event(50*MSEC);
+
if (pd[port].vdm_state < 0)
return EC_RES_ERROR;
- else
- return EC_RES_SUCCESS;
+ if (pd[port].vdm_state > 0)
+ return EC_RES_TIMEOUT;
+
+ return EC_RES_SUCCESS;
}
DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE,
hc_remote_flash,
diff --git a/include/usb_pd.h b/include/usb_pd.h
index b1d72d1402..0f080c24e0 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -10,6 +10,9 @@
#include "common.h"
+/* PD Host command timeout */
+#define PD_HOST_COMMAND_TIMEOUT_US SECOND
+
enum pd_errors {
PD_ERR_INVAL = -1, /* Invalid packet */
PD_ERR_HARD_RESET = -2, /* Got a Hard-Reset packet */