g: recover from usb_upgrade interruptions

The usb upgrade protocol is very fragile, any error while transferring
data causes the state machine on the target to lock up, and the only
way to resume the upgrade is to power cycle the device.

With this patch USB callbacks which happen more than 5 seconds since
the previous callback would be considered a start of new transfer,
thus allowing to attempt a new upgrade without the power cycle.

BRANCH=none
BUG=chrome-os-partner:52856
TEST=the following script allows to upgrade successfully:
    $ while not  ./extra/usb_updater/usb_updater build/cr50/ec.bin; do sleep 6; done

Change-Id: Ibe1078cf62073ce89a31416522b0d6917bc923b9
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/341572
Reviewed-by: Marius Schilder <mschilder@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
This commit is contained in:
Vadim Bendebury
2016-04-29 16:11:28 -07:00
committed by chrome-bot
parent c8e38a9314
commit 42662f2214

View File

@@ -91,12 +91,37 @@ static uint8_t *block_buffer;
static uint32_t block_size;
static uint32_t block_index;
/*
* When was last time a USB callback was called, in microseconds, free running
* timer.
*/
static uint64_t prev_activity_timestamp;
/* Called to deal with data from the host */
static void upgrade_out_handler(struct consumer const *consumer, size_t count)
{
struct update_pdu_header updu;
size_t resp_size;
uint32_t resp_value;
uint64_t delta_time;
/* How much time since the previous USB callback? */
delta_time = get_time().val - prev_activity_timestamp;
prev_activity_timestamp += delta_time;
/* If timeout exceeds 5 seconds - let's start over. */
if ((delta_time > 5000000) && (rx_state_ != rx_idle)) {
if (block_buffer) {
/*
* Previous transfer could have been aborted mid
* block.
*/
shared_mem_release(block_buffer);
block_buffer = NULL;
}
rx_state_ = rx_idle;
CPRINTS("FW update: recovering after timeout\n");
}
if (rx_state_ == rx_idle) {
/* This better be the first block, of zero size. */
@@ -210,10 +235,11 @@ static void upgrade_out_handler(struct consumer const *consumer, size_t count)
*/
fw_upgrade_command_handler(block_buffer, block_index, &resp_size);
shared_mem_release(block_buffer);
resp_value = block_buffer[0];
QUEUE_ADD_UNITS(&upgrade_to_usb, &resp_value, sizeof(resp_value));
rx_state_ = rx_outside_block;
shared_mem_release(block_buffer);
block_buffer = NULL;
}
static void upgrade_flush(struct consumer const *consumer)