From 22c76a4fd536ba53f563d72d2b3402c45f925f85 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 29 Jul 2021 18:38:20 +0200 Subject: [PATCH] stlink: dequeue CSW write only if it doesn't change csw_default The stlink commands for buffer read/write carry the associated CSW value that has to be used. We can dequeue any CSW write request and add the CSW in the following buffer read/write. In preparation to next patch that uses stlink commands misc-rw (commands that don't handle CSW value), let's dequeue only those CSW write that don't change csw_default. Keep a local cache of last csw_default. Tag the queued CSW writes that change csw_default. Dequeue only the un-tagged CSW writes. On buffer read/write commands, limiting the dequeued CSW write surely adds a performance penalty. But csw_default is not changed often so the penalty is not significant. Change-Id: I538d257fe3c434fc97587846d759951384327f02 Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6606 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI --- src/jtag/drivers/stlink_usb.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index e6fc7b624a..92ce1e8015 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -227,6 +227,7 @@ struct dap_queue { unsigned int reg; struct adiv5_ap *ap; uint32_t data; + bool changes_csw_default; } ap_w; struct mem_ap { uint32_t addr; @@ -3960,6 +3961,7 @@ struct hl_layout_api_s stlink_usb_layout_api = { static struct stlink_usb_handle_s *stlink_dap_handle; static struct hl_interface_param_s stlink_dap_param; static DECLARE_BITMAP(opened_ap, DP_APSEL_MAX + 1); +static uint32_t last_csw_default[DP_APSEL_MAX + 1]; static int stlink_dap_error = ERROR_OK; /** */ @@ -4004,6 +4006,7 @@ static int stlink_usb_open_ap(void *handle, unsigned short apsel) LOG_DEBUG("AP %d enabled", apsel); set_bit(apsel, opened_ap); + last_csw_default[apsel] = 0; return ERROR_OK; } @@ -4087,6 +4090,8 @@ static int stlink_dap_op_connect(struct adiv5_dap *dap) dap->do_reconnect = false; dap_invalidate_cache(dap); + for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) + last_csw_default[i] = 0; retval = dap_dp_init(dap); if (retval != ERROR_OK) { @@ -4504,8 +4509,9 @@ static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, q = prev_q; prev_q--; } - /* de-queue previous write-CSW */ - if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW) { + /* de-queue previous write-CSW if it didn't changed ap->csw_default */ + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW && + !prev_q->ap_w.changes_csw_default) { stlink_dap_handle->queue_index = i; q = prev_q; } @@ -4568,8 +4574,9 @@ static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, q = prev_q; prev_q--; } - /* de-queue previous write-CSW */ - if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW) { + /* de-queue previous write-CSW if it didn't changed ap->csw_default */ + if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW && + !prev_q->ap_w.changes_csw_default) { stlink_dap_handle->queue_index = i; q = prev_q; } @@ -4603,6 +4610,12 @@ static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, q->ap_w.reg = reg; q->ap_w.ap = ap; q->ap_w.data = data; + if (reg == MEM_AP_REG_CSW && ap->csw_default != last_csw_default[ap->ap_num]) { + q->ap_w.changes_csw_default = true; + last_csw_default[ap->ap_num] = ap->csw_default; + } else { + q->ap_w.changes_csw_default = false; + } } if (i == MAX_QUEUE_DEPTH - 1) -- 2.30.2