From 919ebca8cc38d23b3a6b27a1b5bde6de1778d4f9 Mon Sep 17 00:00:00 2001 From: Sheng-Liang Song Date: Fri, 22 May 2015 17:44:23 -0700 Subject: sb_firmware: fixed the last write delays BUG=chrome-os-partner:40569 BUG=chromium:497809 BRANCH=none TEST=Begin 1. Install noraml linux images 2. Connected Battery which is having old firmware(100) 3. power on DUT and goto crosh (In normal mode) 4. run "battery_firmware update " 5. Remove AC to interrupt the update 6. Power OFF and power on the DUT again 7. Now seen critical firmware update screen. 8. Reboot around 4 min. 9. See login window. End Signed-off-by: Sheng-liang Song Reviewed-on: https://chromium-review.googlesource.com/273660 Reviewed-by: Shawn N (cherry picked from commit 7a54beba504af6177720e52f9c1ff7e35ec17d2e) Change-Id: I2090cfa9200a7402a5fba2e111073dd1d7e7b422 Reviewed-on: https://chromium-review.googlesource.com/277540 Reviewed-by: Sheng-liang Song Commit-Queue: Sheng-liang Song Tested-by: Sheng-liang Song --- util/ec_sb_firmware_update.c | 47 ++++++++++++++++++++++++++++++-------------- util/ec_sb_firmware_update.h | 2 +- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/util/ec_sb_firmware_update.c b/util/ec_sb_firmware_update.c index ee6e4a8393..9db44c165f 100644 --- a/util/ec_sb_firmware_update.c +++ b/util/ec_sb_firmware_update.c @@ -33,20 +33,22 @@ struct delay_value { uint32_t value; }; -/* A default retry counter on errors */ +/* Default retry counter on errors */ #define SB_FW_UPDATE_DEFAULT_RETRY_CNT 3 +/* Default delay value */ +#define SB_FW_UPDATE_DEFAULT_DELAY 1000 -#define DELAY_VALUE_BEGIN 500000 -#define DELAY_VALUE_END 1000000 -#define DELAY_VALUE_BUSY 1000000 +#define DELAY_US_BEGIN 500000 +#define DELAY_US_END 1000000 +#define DELAY_US_BUSY 1000000 +#define DELAY_US_WRITE_END 50000 static struct delay_value sb_delays[] = { {1, 100000}, {2, 9000000}, - {3, 100000}, - {10, 25000}, - {770, 25000}, - {2680, 25000}, + {4, 100000}, + {771, 30000}, + {2200, 10000}, {0xFFFFFF, 50000}, }; @@ -283,7 +285,7 @@ static int get_status(struct sb_fw_update_status *status) param->hdr.subcmd = EC_SB_FW_UPDATE_STATUS; do { - usleep(1000); + usleep(SB_FW_UPDATE_DEFAULT_DELAY); rv = ec_command(EC_CMD_SB_FW_UPDATE, 0, param, sizeof(struct ec_sb_fw_update_header), resp, SB_FW_UPDATE_CMD_STATUS_SIZE); @@ -311,7 +313,7 @@ static int get_info(struct sb_fw_update_info *info) param->hdr.subcmd = EC_SB_FW_UPDATE_INFO; do { - usleep(1000); + usleep(SB_FW_UPDATE_DEFAULT_DELAY); rv = ec_command(EC_CMD_SB_FW_UPDATE, 0, param, sizeof(struct ec_sb_fw_update_header), resp, SB_FW_UPDATE_CMD_INFO_SIZE); @@ -400,7 +402,7 @@ static enum fw_update_state s0_read_status(struct fw_update_ctrl *fw_update) } if (fw_update->status.busy) { - usleep(DELAY_VALUE_BUSY); + usleep(DELAY_US_BUSY); return S0_READ_STATUS; } else return S1_READ_INFO; @@ -522,7 +524,7 @@ static enum fw_update_state s4_write_update(struct fw_update_ctrl *fw_update) log_msg(fw_update, S4_WRITE_UPDATE, "Interface Error"); return S10_TERMINAL; } - usleep(DELAY_VALUE_BEGIN); + usleep(DELAY_US_BEGIN); return S5_READ_STATUS; } @@ -574,6 +576,13 @@ static enum fw_update_state s6_write_block(struct fw_update_ctrl *fw_update) return S10_TERMINAL; } + /* + * Add more delays after the last a few block (3) writes. + * 3 is chosen based on current test results. + */ + if ((offset + 3 * fw_update->step_size) >= fw_update->size) + usleep(DELAY_US_WRITE_END); + usleep(get_delay_value(offset, fw_update->step_size)); return S7_READ_STATUS; @@ -588,7 +597,7 @@ static enum fw_update_state s7_read_status(struct fw_update_ctrl *fw_update) bsize = fw_update->step_size; do { - usleep(1000); + usleep(SB_FW_UPDATE_DEFAULT_DELAY); rv = get_status(&fw_update->status); if (rv) { dump_data(fw_update->ptr+offset, offset, bsize); @@ -647,7 +656,8 @@ static enum fw_update_state s8_write_end(struct fw_update_ctrl *fw_update) if (fw_update->rv) return S10_TERMINAL; - usleep(DELAY_VALUE_END); + usleep(DELAY_US_END); + fw_update->busy_retry_cnt = SB_FW_UPDATE_BUSY_ERROR_RETRY_CNT; return S9_READ_STATUS; } @@ -655,7 +665,12 @@ static enum fw_update_state s9_read_status(struct fw_update_ctrl *fw_update) { int rv; - /* Poll for completion */ + if (fw_update->busy_retry_cnt == 0) { + fw_update->rv = -1; + log_msg(fw_update, S9_READ_STATUS, "Busy"); + return S10_TERMINAL; + } + rv = get_status(&fw_update->status); if (rv) { fw_update->rv = -1; @@ -664,6 +679,8 @@ static enum fw_update_state s9_read_status(struct fw_update_ctrl *fw_update) } if ((fw_update->status.fw_update_mode == 1) || (fw_update->status.busy == 1)) { + usleep(SB_FW_UPDATE_DEFAULT_DELAY); + fw_update->busy_retry_cnt--; return S9_READ_STATUS; } log_msg(fw_update, S9_READ_STATUS, "Complete"); diff --git a/util/ec_sb_firmware_update.h b/util/ec_sb_firmware_update.h index 7dcd6802fa..6673ba99cf 100644 --- a/util/ec_sb_firmware_update.h +++ b/util/ec_sb_firmware_update.h @@ -121,6 +121,6 @@ enum sb_maker_id { */ #define SB_FW_UPDATE_ERROR_RETRY_CNT 2 #define SB_FW_UPDATE_FEC_ERROR_RETRY_CNT 2 -#define SB_FW_UPDATE_BUSY_ERROR_RETRY_CNT 9 +#define SB_FW_UPDATE_BUSY_ERROR_RETRY_CNT 4 #endif -- cgit v1.2.1