summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2017-01-05 11:41:01 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-01-06 22:41:01 +0000
commit6aaee50cda1fceab93b5743c219d90efa99c93ac (patch)
tree55aa92e3f7a3126c99371198b4b4fd6d74e5d62d
parentd657179c75b125e94b198f07b2aaafdc5a7a118e (diff)
downloadchrome-ec-6aaee50cda1fceab93b5743c219d90efa99c93ac.tar.gz
npcx: shi: Optimize OBUF copy / fill
We have hard timing requirements once we begin to output our host command response, and most of the time is spent copying our response to OBUF. Optimize our copy loops to remove needless increments and to avoid needless struct dereference. BUG=chrome-os-partner:61304 BRANCH=gru TEST=Manual on kevin, verify the following performance metrics: Time spent in shi_fill_out_status(): Was 40us, now 28us Time spent in shi_write_half_obuf(): Was 60us, now 31us Time spent in shi_write_first_pkg_outbuf: Was 90us, now 37us (bad case) Was 26us, now 16us (better case / less data copied) Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Change-Id: I04075c92744eeefe8f2be009e6598718c45143c4 Reviewed-on: https://chromium-review.googlesource.com/425331
-rw-r--r--chip/npcx/shi.c75
1 files changed, 53 insertions, 22 deletions
diff --git a/chip/npcx/shi.c b/chip/npcx/shi.c
index 449d932ba7..317cdb63c8 100644
--- a/chip/npcx/shi.c
+++ b/chip/npcx/shi.c
@@ -340,17 +340,25 @@ static void shi_parse_header(void)
/* This routine fills out all SHI output buffer with status byte */
static void shi_fill_out_status(uint8_t status)
{
- uint16_t i;
- uint16_t offset = SHI_OBUF_VALID_OFFSET;
+ uint8_t offset;
+ uint8_t *obuf_ptr;
+ uint8_t *obuf_end;
/* Disable interrupts in case the interfere by the other interrupts */
interrupt_disable();
+ offset = SHI_OBUF_VALID_OFFSET;
+
/* Fill out all output buffer with status byte */
- for (i = offset; i < SHI_OBUF_FULL_SIZE; i++)
- NPCX_OBUF(i) = status;
- for (i = 0; i < offset; i++)
- NPCX_OBUF(i) = status;
+ obuf_ptr = (uint8_t *)SHI_OBUF_START_ADDR + offset;
+ obuf_end = (uint8_t *)SHI_OBUF_START_ADDR + SHI_OBUF_FULL_SIZE;
+ while (obuf_ptr != obuf_end)
+ *(obuf_ptr++) = status;
+
+ obuf_ptr = (uint8_t *)SHI_OBUF_START_ADDR;
+ obuf_end = (uint8_t *)SHI_OBUF_START_ADDR + offset;
+ while (obuf_ptr != obuf_end)
+ *(obuf_ptr++) = status;
/* End of critical section */
interrupt_enable();
@@ -380,12 +388,20 @@ static int shi_is_cs_glitch(void)
*/
static void shi_write_half_outbuf(void)
{
- uint16_t i;
- uint16_t size = MIN(SHI_OBUF_HALF_SIZE,
- shi_params.sz_response - shi_params.sz_sending);
+ const uint8_t size = MIN(SHI_OBUF_HALF_SIZE,
+ shi_params.sz_response -
+ shi_params.sz_sending);
+ uint8_t *obuf_ptr = (uint8_t *)shi_params.tx_buf;
+ const uint8_t *obuf_end = obuf_ptr + size;
+ uint8_t *msg_ptr = shi_params.tx_msg;
+
/* Fill half output buffer */
- for (i = 0; i < size; i++, shi_params.sz_sending++)
- *(shi_params.tx_buf++) = *(shi_params.tx_msg++);
+ while (obuf_ptr != obuf_end)
+ *(obuf_ptr++) = *(msg_ptr++);
+
+ shi_params.sz_sending += size;
+ shi_params.tx_buf = obuf_ptr;
+ shi_params.tx_msg = msg_ptr;
}
/*
@@ -394,8 +410,10 @@ static void shi_write_half_outbuf(void)
*/
static void shi_write_first_pkg_outbuf(uint16_t szbytes)
{
- uint16_t i;
- uint16_t offset, size;
+ uint8_t size, offset;
+ uint8_t *obuf_ptr;
+ uint8_t *obuf_end;
+ uint8_t *msg_ptr;
#ifdef NPCX_SHI_BYPASS_OVER_256B
/*
@@ -412,22 +430,35 @@ static void shi_write_first_pkg_outbuf(uint16_t szbytes)
}
#endif
+ /* Start writing at our current OBUF position */
offset = SHI_OBUF_VALID_OFFSET;
- shi_params.tx_buf = SHI_OBUF_START_ADDR + offset;
- /* Fill half output buffer */
+ obuf_ptr = (uint8_t *)SHI_OBUF_START_ADDR + offset;
+ msg_ptr = shi_params.tx_msg;
+
+ /* Fill up to OBUF mid point, or OBUF end */
size = MIN(SHI_OBUF_HALF_SIZE - (offset % SHI_OBUF_HALF_SIZE),
szbytes - shi_params.sz_sending);
- for (i = 0; i < size; i++, shi_params.sz_sending++)
- *(shi_params.tx_buf++) = *(shi_params.tx_msg++);
+ obuf_end = obuf_ptr + size;
+ while (obuf_ptr != obuf_end)
+ *(obuf_ptr++) = *(msg_ptr++);
- /* Write data from bottom address again */
- if (shi_params.tx_buf == SHI_OBUF_FULL_ADDR)
- shi_params.tx_buf = SHI_OBUF_START_ADDR;
+ /* Track bytes sent for later accounting */
+ shi_params.sz_sending += size;
+
+ /* Write data to beginning of OBUF if we've reached the end */
+ if (obuf_ptr == SHI_OBUF_FULL_ADDR)
+ obuf_ptr = (uint8_t *)SHI_OBUF_START_ADDR;
/* Fill next half output buffer */
size = MIN(SHI_OBUF_HALF_SIZE, szbytes - shi_params.sz_sending);
- for (i = 0; i < size; i++, shi_params.sz_sending++)
- *(shi_params.tx_buf++) = *(shi_params.tx_msg++);
+ obuf_end = obuf_ptr + size;
+ while (obuf_ptr != obuf_end)
+ *(obuf_ptr++) = *(msg_ptr++);
+
+ /* Track bytes sent / last OBUF position written for later accounting */
+ shi_params.sz_sending += size;
+ shi_params.tx_buf = obuf_ptr;
+ shi_params.tx_msg = msg_ptr;
}
/* This routine copies SHI half input buffer data to msg buffer */