diff options
-rw-r--r-- | src/target/riscv/batch.c | 16 | ||||
-rw-r--r-- | src/target/riscv/batch.h | 71 | ||||
-rw-r--r-- | src/target/riscv/riscv-013.c | 190 |
3 files changed, 167 insertions, 110 deletions
diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index 4115a37..bb1070a 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -29,7 +29,7 @@ struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans) out->allocated_scans = scans; out->last_scan = RISCV_SCAN_TYPE_INVALID; out->was_run = false; - out->used_delay = 0; + out->last_scan_delay = 0; out->data_out = NULL; out->data_in = NULL; @@ -109,7 +109,7 @@ static bool riscv_batch_was_scan_busy(const struct riscv_batch *batch, } static void add_idle_before_batch(const struct riscv_batch *batch, size_t start_idx, - struct riscv_scan_delays delays) + const struct riscv_scan_delays *delays) { if (!batch->was_run) return; @@ -121,9 +121,9 @@ static void add_idle_before_batch(const struct riscv_batch *batch, size_t start_ ? batch->delay_classes[start_idx - 1] : RISCV_DELAY_BASE; const unsigned int new_delay = riscv_scan_get_delay(delays, delay_class); - if (new_delay <= batch->used_delay) + if (new_delay <= batch->last_scan_delay) return; - const unsigned int idle_change = new_delay - batch->used_delay; + const unsigned int idle_change = new_delay - batch->last_scan_delay; LOG_TARGET_DEBUG(batch->target, "Adding %u idle cycles before the batch.", idle_change); assert(idle_change <= INT_MAX); @@ -131,19 +131,19 @@ static void add_idle_before_batch(const struct riscv_batch *batch, size_t start_ } static int get_delay(const struct riscv_batch *batch, size_t scan_idx, - struct riscv_scan_delays delays) + const struct riscv_scan_delays *delays) { assert(batch); assert(scan_idx < batch->used_scans); const enum riscv_scan_delay_class delay_class = batch->delay_classes[scan_idx]; - const unsigned int delay = riscv_scan_get_delay(delays, delay_class); + const unsigned int delay = riscv_scan_get_delay(delays, delay_class); assert(delay <= INT_MAX); return delay; } int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx, - struct riscv_scan_delays delays, bool resets_delays, + const struct riscv_scan_delays *delays, bool resets_delays, size_t reset_delays_after) { assert(batch->used_scans); @@ -195,7 +195,7 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx, } batch->was_run = true; - batch->used_delay = get_delay(batch, batch->used_scans - 1, delays); + batch->last_scan_delay = get_delay(batch, batch->used_scans - 1, delays); return ERROR_OK; } diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h index 03947aa..327406c 100644 --- a/src/target/riscv/batch.h +++ b/src/target/riscv/batch.h @@ -25,40 +25,66 @@ enum riscv_scan_delay_class { /* Delay for System Bus read operation: */ RISCV_DELAY_SYSBUS_READ, /* Delay for System Bus write operation: */ - RISCV_DELAY_SYSBUS_WRITE, + RISCV_DELAY_SYSBUS_WRITE }; +static inline const char * +riscv_scan_delay_class_name(enum riscv_scan_delay_class delay_class) +{ + switch (delay_class) { + case RISCV_DELAY_BASE: + return "DM access"; + case RISCV_DELAY_ABSTRACT_COMMAND: + return "Abstract Command"; + case RISCV_DELAY_SYSBUS_READ: + return "System Bus read"; + case RISCV_DELAY_SYSBUS_WRITE: + return "System Bus write"; + } + assert(0); + return NULL; +} + +/* The scan delay values are passed to "jtag_add_runtest()", which accepts an + * "int". Therefore, the passed value should be no greater than "INT_MAX". + * + * Since the resulting delay value can be a sum of two individual delays, + * individual delays are limited to "INT_MAX / 2" to prevent overflow of the + * final sum. + */ +#define RISCV_SCAN_DELAY_MAX (INT_MAX / 2) + struct riscv_scan_delays { - /* The purpose of these delays is to be passed to "jtag_add_runtest()", - * which accepts an "int". - * Therefore, they should be no greater then "INT_MAX". - */ unsigned int base_delay; unsigned int ac_delay; unsigned int sb_read_delay; unsigned int sb_write_delay; }; -static inline unsigned int riscv_scan_get_delay(struct riscv_scan_delays delays, +static inline unsigned int +riscv_scan_get_delay(const struct riscv_scan_delays *delays, enum riscv_scan_delay_class delay_class) { switch (delay_class) { case RISCV_DELAY_BASE: - return delays.base_delay; + return delays->base_delay; case RISCV_DELAY_ABSTRACT_COMMAND: - return delays.ac_delay; + return delays->base_delay + delays->ac_delay; case RISCV_DELAY_SYSBUS_READ: - return delays.sb_read_delay; + return delays->base_delay + delays->sb_read_delay; case RISCV_DELAY_SYSBUS_WRITE: - return delays.sb_write_delay; + return delays->base_delay + delays->sb_write_delay; } + assert(0); return 0; } static inline void riscv_scan_set_delay(struct riscv_scan_delays *delays, enum riscv_scan_delay_class delay_class, unsigned int delay) { - assert(delay <= INT_MAX); + assert(delay <= RISCV_SCAN_DELAY_MAX); + LOG_DEBUG("%s delay is set to %u.", + riscv_scan_delay_class_name(delay_class), delay); switch (delay_class) { case RISCV_DELAY_BASE: delays->base_delay = delay; @@ -73,6 +99,25 @@ static inline void riscv_scan_set_delay(struct riscv_scan_delays *delays, delays->sb_write_delay = delay; return; } + assert(0); +} + +static inline int riscv_scan_increase_delay(struct riscv_scan_delays *delays, + enum riscv_scan_delay_class delay_class) +{ + const unsigned int delay = riscv_scan_get_delay(delays, delay_class); + const unsigned int delay_step = delay / 10 + 1; + if (delay > RISCV_SCAN_DELAY_MAX - delay_step) { + /* It's not clear if this issue actually occurs in real + * use-cases, so stick with a simple solution until the + * first bug report. + */ + LOG_ERROR("Delay for %s (%d) is not increased anymore (maximum was reached).", + riscv_scan_delay_class_name(delay_class), delay); + return ERROR_FAIL; + } + riscv_scan_set_delay(delays, delay_class, delay + delay_step); + return ERROR_OK; } /* A batch of multiple JTAG scans, which are grouped together to avoid the @@ -113,7 +158,7 @@ struct riscv_batch { /* Number of RTI cycles used by the last scan on the last run. * Only valid when `was_run` is set. */ - unsigned int used_delay; + unsigned int last_scan_delay; }; /* Allocates (or frees) a new scan set. "scans" is the maximum number of JTAG @@ -138,7 +183,7 @@ bool riscv_batch_full(struct riscv_batch *batch); * OpenOCD that are based on batches. */ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx, - struct riscv_scan_delays delays, bool resets_delays, + const struct riscv_scan_delays *delays, bool resets_delays, size_t reset_delays_after); /* Get the number of scans successfully executed form this batch. */ diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 8d46a86..49c328e 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -169,21 +169,12 @@ typedef struct { * access. */ unsigned int dtmcs_idle; - /* This value is incremented every time a dbus access comes back as "busy". - * It's used to determine how many run-test/idle cycles to feed the target - * in between accesses. */ - unsigned int dmi_busy_delay; - - /* Number of run-test/idle cycles to add between consecutive bus master - * reads/writes respectively. */ - unsigned int bus_master_write_delay, bus_master_read_delay; - - /* This value is increased every time we tried to execute two commands - * consecutively, and the second one failed because the previous hadn't - * completed yet. It's used to add extra run-test/idle cycles after - * starting a command, so we don't have to waste time checking for busy to - * go low. */ - unsigned int ac_busy_delay; + /* This structure is used to determine how many run-test/idle to use after + * an access of corresponding "riscv_scan_delay_class". + * Values are incremented every time an access results in a busy + * response. + */ + struct riscv_scan_delays learned_delays; bool abstract_read_csr_supported; bool abstract_write_csr_supported; @@ -478,15 +469,25 @@ static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr return ERROR_OK; } -static void increase_dmi_busy_delay(struct target *target) +static int increase_dmi_busy_delay(struct target *target) { - riscv013_info_t *info = get_info(target); - info->dmi_busy_delay += info->dmi_busy_delay / 10 + 1; - LOG_TARGET_DEBUG(target, "dtmcs_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d", - info->dtmcs_idle, info->dmi_busy_delay, - info->ac_busy_delay); + RISCV013_INFO(info); + + int res = dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, + NULL /* discard result */); + if (res != ERROR_OK) + return res; - dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */); + res = riscv_scan_increase_delay(&info->learned_delays, + RISCV_DELAY_BASE); + return res; +} + +static void reset_learned_delays(struct target *target) +{ + RISCV013_INFO(info); + assert(info); + memset(&info->learned_delays, 0, sizeof(info->learned_delays)); } static void decrement_reset_delays_counter(struct target *target, size_t finished_scans) @@ -503,9 +504,7 @@ static void decrement_reset_delays_counter(struct target *target, size_t finishe r->reset_delays_wait = -1; LOG_TARGET_DEBUG(target, "resetting learned delays (reset_delays_wait counter expired)"); - RISCV013_INFO(info); - info->dmi_busy_delay = 0; - info->ac_busy_delay = 0; + reset_learned_delays(target); } /** * exec: If this is set, assume the scan results in an execution, so more @@ -554,9 +553,9 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in, jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE); } - int idle_count = info->dmi_busy_delay; - if (exec) - idle_count += info->ac_busy_delay; + int idle_count = exec + ? riscv_scan_get_delay(&info->learned_delays, RISCV_DELAY_ABSTRACT_COMMAND) + : riscv_scan_get_delay(&info->learned_delays, RISCV_DELAY_BASE); if (idle_count) jtag_add_runtest(idle_count, TAP_IDLE); @@ -635,7 +634,9 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, status = dmi_scan(target, NULL, NULL, op, address, data_out, exec); if (status == DMI_STATUS_BUSY) { - increase_dmi_busy_delay(target); + int result = increase_dmi_busy_delay(target); + if (result != ERROR_OK) + return result; if (dmi_busy_encountered) *dmi_busy_encountered = true; } else if (status == DMI_STATUS_SUCCESS) { @@ -661,7 +662,9 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, status = dmi_scan(target, NULL, data_in, DMI_OP_NOP, address, 0, false); if (status == DMI_STATUS_BUSY) { - increase_dmi_busy_delay(target); + int result = increase_dmi_busy_delay(target); + if (result != ERROR_OK) + return result; if (dmi_busy_encountered) *dmi_busy_encountered = true; } else if (status == DMI_STATUS_SUCCESS) { @@ -837,13 +840,11 @@ static int dmstatus_read(struct target *target, uint32_t *dmstatus, return result; } -static void increase_ac_busy_delay(struct target *target) +static int increase_ac_busy_delay(struct target *target) { riscv013_info_t *info = get_info(target); - info->ac_busy_delay += info->ac_busy_delay / 10 + 1; - LOG_TARGET_DEBUG(target, "dtmcs_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d", - info->dtmcs_idle, info->dmi_busy_delay, - info->ac_busy_delay); + return riscv_scan_increase_delay(&info->learned_delays, + RISCV_DELAY_ABSTRACT_COMMAND); } static uint32_t __attribute__((unused)) abstract_register_size(unsigned width) @@ -911,13 +912,13 @@ static int dm013_select_target(struct target *target) return dm013_select_hart(target, info->index); } -#define EXECUTE_ABSTRACT_COMMAND_BATCH_SIZE 2 +#define ABSTRACT_COMMAND_BATCH_SIZE 2 static size_t abstract_cmd_fill_batch(struct riscv_batch *batch, uint32_t command) { assert(riscv_batch_available_scans(batch) - >= EXECUTE_ABSTRACT_COMMAND_BATCH_SIZE); + >= ABSTRACT_COMMAND_BATCH_SIZE); riscv_batch_add_dm_write(batch, DM_COMMAND, command, /* read_back */ true, RISCV_DELAY_ABSTRACT_COMMAND); return riscv_batch_add_dm_read(batch, DM_ABSTRACTCS, RISCV_DELAY_BASE); @@ -935,7 +936,9 @@ static int abstract_cmd_batch_check_and_clear_cmderr(struct target *target, res = wait_for_idle(target, &abstractcs); if (res != ERROR_OK) goto clear_cmderr; - increase_ac_busy_delay(target); + res = increase_ac_busy_delay(target); + if (res != ERROR_OK) + goto clear_cmderr; } *cmderr = get_field32(abstractcs, DM_ABSTRACTCS_CMDERR); if (*cmderr == CMDERR_NONE) @@ -975,7 +978,7 @@ static int execute_abstract_command(struct target *target, uint32_t command, return ERROR_FAIL; struct riscv_batch *batch = riscv_batch_alloc(target, - EXECUTE_ABSTRACT_COMMAND_BATCH_SIZE); + ABSTRACT_COMMAND_BATCH_SIZE); const size_t abstractcs_read_key = abstract_cmd_fill_batch(batch, command); /* Abstract commands are executed while running the batch. */ @@ -1203,7 +1206,7 @@ static int register_write_abstract(struct target *target, enum gdb_regno number, assert(size_bits % 32 == 0); const unsigned int size_in_words = size_bits / 32; const unsigned int batch_size = size_in_words - + EXECUTE_ABSTRACT_COMMAND_BATCH_SIZE; + + ABSTRACT_COMMAND_BATCH_SIZE; struct riscv_batch * const batch = riscv_batch_alloc(target, batch_size); abstract_data_write_fill_batch(batch, value, /*index*/ 0, size_bits); @@ -2757,29 +2760,13 @@ static int sb_write_address(struct target *target, target_addr_t address, (uint32_t)address, false, ensure_success); } -/* TODO: store delays in "struct riscv_scan_delays" and remove this function. */ -struct riscv_scan_delays get_scan_delays(struct target *target) -{ - RISCV013_INFO(info); - assert(info); - struct riscv_scan_delays delays; - riscv_scan_set_delay(&delays, RISCV_DELAY_BASE, info->dmi_busy_delay); - riscv_scan_set_delay(&delays, RISCV_DELAY_ABSTRACT_COMMAND, info->dmi_busy_delay + - info->ac_busy_delay); - riscv_scan_set_delay(&delays, RISCV_DELAY_SYSBUS_READ, info->dmi_busy_delay + - info->bus_master_read_delay); - riscv_scan_set_delay(&delays, RISCV_DELAY_SYSBUS_WRITE, info->dmi_busy_delay + - info->bus_master_write_delay); - return delays; -} - static int batch_run(struct target *target, struct riscv_batch *batch) { RISCV_INFO(r); + RISCV013_INFO(info); select_dmi(target); riscv_batch_add_nop(batch); - const int result = riscv_batch_run_from(batch, 0, - get_scan_delays(target), + const int result = riscv_batch_run_from(batch, 0, &info->learned_delays, /*resets_delays*/ r->reset_delays_wait >= 0, r->reset_delays_wait); /* TODO: To use `riscv_batch_finished_scans()` here, it is needed for @@ -2796,18 +2783,18 @@ static int batch_run(struct target *target, struct riscv_batch *batch) static int batch_run_timeout(struct target *target, struct riscv_batch *batch) { RISCV013_INFO(info); - select_dmi(target); riscv_batch_add_nop(batch); size_t finished_scans = 0; const time_t start = time(NULL); - const unsigned int old_dmi_busy_delay = info->dmi_busy_delay; + const unsigned int old_base_delay = riscv_scan_get_delay(&info->learned_delays, + RISCV_DELAY_BASE); int result; do { RISCV_INFO(r); result = riscv_batch_run_from(batch, finished_scans, - get_scan_delays(target), + &info->learned_delays, /*resets_delays*/ r->reset_delays_wait >= 0, r->reset_delays_wait); const size_t new_finished_scans = riscv_batch_finished_scans(batch); @@ -2820,16 +2807,20 @@ static int batch_run_timeout(struct target *target, struct riscv_batch *batch) assert(finished_scans == batch->used_scans); return ERROR_OK; } - increase_dmi_busy_delay(target); + result = increase_dmi_busy_delay(target); + if (result != ERROR_OK) + return result; } while (time(NULL) - start < riscv_command_timeout_sec); assert(result == ERROR_OK); assert(riscv_batch_was_batch_busy(batch)); /* Reset dmi_busy_delay, so the value doesn't get too big. */ - LOG_TARGET_DEBUG(target, "dmi_busy_delay is restored to %u.", - old_dmi_busy_delay); - info->dmi_busy_delay = old_dmi_busy_delay; + LOG_TARGET_DEBUG(target, "%s delay is restored to %u.", + riscv_scan_delay_class_name(RISCV_DELAY_BASE), + old_base_delay); + riscv_scan_set_delay(&info->learned_delays, RISCV_DELAY_BASE, + old_base_delay); LOG_TARGET_ERROR(target, "DMI operation didn't complete in %d seconds. " "The target is either really slow or broken. You could increase " @@ -2968,7 +2959,11 @@ static int sample_memory_bus_v1(struct target *target, * with a larger DMI delay. */ unsigned int sbcs_read_op = riscv_batch_get_dmi_read_op(batch, sbcs_read_index); if (sbcs_read_op == DTM_DMI_OP_BUSY) { - increase_dmi_busy_delay(target); + result = increase_dmi_busy_delay(target); + if (result != ERROR_OK) { + riscv_batch_free(batch); + return result; + } continue; } @@ -2976,9 +2971,12 @@ static int sample_memory_bus_v1(struct target *target, if (get_field(sbcs_read, DM_SBCS_SBBUSYERROR)) { /* Discard this batch when we encounter "busy error" state on the System Bus level. * We'll try next time with a larger System Bus read delay. */ - info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1; dm_write(target, DM_SBCS, sbcs_read | DM_SBCS_SBBUSYERROR | DM_SBCS_SBERROR); + int res = riscv_scan_increase_delay(&info->learned_delays, + RISCV_DELAY_SYSBUS_READ); riscv_batch_free(batch); + if (res != ERROR_OK) + return res; continue; } if (get_field(sbcs_read, DM_SBCS_SBERROR)) { @@ -3135,11 +3133,7 @@ static int init_target(struct command_context *cmd_ctx, riscv013_info_t *info = get_info(target); info->progbufsize = -1; - - info->dmi_busy_delay = 0; - info->bus_master_read_delay = 0; - info->bus_master_write_delay = 0; - info->ac_busy_delay = 0; + reset_learned_delays(target); /* Assume all these abstract commands are supported until we learn * otherwise. @@ -3226,7 +3220,8 @@ static int deassert_reset(struct target *target) return result; uint32_t dmstatus; - const int orig_dmi_busy_delay = info->dmi_busy_delay; + const unsigned int orig_base_delay = riscv_scan_get_delay(&info->learned_delays, + RISCV_DELAY_BASE); time_t start = time(NULL); LOG_TARGET_DEBUG(target, "Waiting for hart to come out of reset."); do { @@ -3259,7 +3254,8 @@ static int deassert_reset(struct target *target) } while (get_field(dmstatus, DM_DMSTATUS_ALLUNAVAIL) && !get_field(dmstatus, DM_DMSTATUS_ALLHAVERESET)); - info->dmi_busy_delay = orig_dmi_busy_delay; + riscv_scan_set_delay(&info->learned_delays, RISCV_DELAY_BASE, + orig_base_delay); if (target->reset_halt) { target->state = TARGET_HALTED; @@ -3588,10 +3584,12 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, if (sb_write_address(target, next_address, true) != ERROR_OK) return ERROR_FAIL; - if (info->bus_master_read_delay) { + unsigned int bus_master_read_delay = riscv_scan_get_delay(&info->learned_delays, + RISCV_DELAY_SYSBUS_READ); + if (bus_master_read_delay) { LOG_TARGET_DEBUG(target, "Waiting %d cycles for bus master read delay", - info->bus_master_read_delay); - jtag_add_runtest(info->bus_master_read_delay, TAP_IDLE); + bus_master_read_delay); + jtag_add_runtest(bus_master_read_delay, TAP_IDLE); if (jtag_execute_queue() != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed to scan idle sequence"); return ERROR_FAIL; @@ -3621,10 +3619,12 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, DMI_OP_READ, sbdata[j] + dm->base, 0, false); /* By reading from sbdata0, we have just initiated another system bus read. * If necessary add a delay so the read can finish. */ - if (j == 0 && info->bus_master_read_delay) { + bus_master_read_delay = riscv_scan_get_delay(&info->learned_delays, + RISCV_DELAY_SYSBUS_READ); + if (j == 0 && bus_master_read_delay) { LOG_TARGET_DEBUG(target, "Waiting %d cycles for bus master read delay", - info->bus_master_read_delay); - jtag_add_runtest(info->bus_master_read_delay, TAP_IDLE); + bus_master_read_delay); + jtag_add_runtest(bus_master_read_delay, TAP_IDLE); if (jtag_execute_queue() != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed to scan idle sequence"); return ERROR_FAIL; @@ -3711,9 +3711,10 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, return ERROR_FAIL; } - info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1; - LOG_TARGET_DEBUG(target, "Increasing bus_master_read_delay to %d.", - info->bus_master_read_delay); + int res = riscv_scan_increase_delay(&info->learned_delays, + RISCV_DELAY_SYSBUS_READ); + if (res != ERROR_OK) + return res; continue; } @@ -4129,8 +4130,12 @@ static int read_memory_progbuf_inner_on_ac_busy(struct target *target, uint32_t start_index, uint32_t *elements_read, struct memory_access_info access) { - increase_ac_busy_delay(target); - riscv013_clear_abstract_error(target); + int res = riscv013_clear_abstract_error(target); + if (res != ERROR_OK) + return res; + res = increase_ac_busy_delay(target); + if (res != ERROR_OK) + return res; if (dm_write(target, DM_ABSTRACTAUTO, 0) != ERROR_OK) return ERROR_FAIL; @@ -4828,8 +4833,11 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, LOG_TARGET_DEBUG(target, "Sbbusyerror encountered during system bus write."); /* Clear the sticky error flag. */ dm_write(target, DM_SBCS, sbcs | DM_SBCS_SBBUSYERROR); - /* Slow down before trying again. */ - info->bus_master_write_delay += info->bus_master_write_delay / 10 + 1; + /* Slow down before trying again. + * FIXME: Possible overflow is ignored here. + */ + riscv_scan_increase_delay(&info->learned_delays, + RISCV_DELAY_SYSBUS_WRITE); } if (get_field(sbcs, DM_SBCS_SBBUSYERROR) || dmi_busy_encountered) { @@ -4940,8 +4948,12 @@ static int write_memory_progbuf_teardown(struct target *target) static int write_memory_progbuf_handle_busy(struct target *target, target_addr_t *address_p, uint32_t size, const uint8_t *buffer) { - riscv013_clear_abstract_error(target); - increase_ac_busy_delay(target); + int res = riscv013_clear_abstract_error(target); + if (res != ERROR_OK) + return res; + res = increase_ac_busy_delay(target); + if (res != ERROR_OK) + return res; if (write_memory_progbuf_teardown(target) != ERROR_OK) return ERROR_FAIL; |