diff options
author | Mark Rawling <mwr@google.com> | 2021-09-29 21:23:21 -0700 |
---|---|---|
committer | Andrew Evans <andrewevans@google.com> | 2022-04-19 10:16:03 -0700 |
commit | 52fae86c0c3a6339847d610db904573eb611d36c (patch) | |
tree | 29051953efbe7886e12445f9d7c3ca1ef0e63e1a | |
parent | 832cf00114a3210be383afb18662f600069a2a3b (diff) | |
download | nanohub-52fae86c0c3a6339847d610db904573eb611d36c.tar.gz |
Nanohub flow control with exponential backoff
This CL modifies the Nanohub busy mechanism to make it suitable for use
in a general flow control scheme. This form of flow control will be
used with a new MCU traffic strategy, which generally guarantees fast,
fixed transaction timing, with backoff for overruns and other extremes.
The MCU will be configured with sufficient capacity to trigger flow
control rarely, but when it does the performance will degrade smoothly.
The exponential backoff uses sleep instead of udelay for less CPU load.
This is shown to behave just as well as udelay for the traffic patterns
of interest.
This change is important to enable SPI DMA on the AP because it can
cope with the wider range of timing that results when using DMA.
Specific use cases include:
- write overruns during MCU startup (implicated in sensor flakiness)
- abnornmal timing, eg, during display offload where heavy graphics
initialisation can occur
See go/rh-nanohub-mcu-architecture
Bug: 200859803
Bug: 200616501
Test: prolonged stress testing with and without induced retries
Change-Id: Ic37ea88b058955f7ca5bb57ec0d18d6903da8ac7
-rw-r--r-- | comms.c | 18 |
1 files changed, 14 insertions, 4 deletions
@@ -29,6 +29,10 @@ #define RESEND_SHORT_DELAY_US 500 /* 500us - 1ms */ #define RESEND_LONG_DELAY_US 100000 /* 100ms - 200ms */ +#define BUSY_DELAY_MIN_US 50 +#define BUSY_DELAY_MAX_US 100000 +#define BUSY_BACKOFF_RATE 2 + static const uint32_t crc_table[] = { 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, @@ -350,6 +354,7 @@ int nanohub_comms_rx_retrans_boottime(struct nanohub_data *data, uint32_t cmd, int packet_size = 0; struct nanohub_packet_pad *pad = packet_alloc(GFP_KERNEL); int delay = 0; + int busy_delay = BUSY_DELAY_MIN_US; int ret; uint32_t seq; struct timespec ts; @@ -386,8 +391,10 @@ int nanohub_comms_rx_retrans_boottime(struct nanohub_data *data, uint32_t cmd, if (retrans_cnt >= 0) udelay(retrans_delay); } else if (ret == ERROR_BUSY) { - usleep_range(RESEND_LONG_DELAY_US, - RESEND_LONG_DELAY_US * 2); + usleep_range(busy_delay, busy_delay * 2); + if (busy_delay < BUSY_DELAY_MAX_US) { + busy_delay = min(busy_delay * BUSY_BACKOFF_RATE, BUSY_DELAY_MAX_US); + } } } while ((ret == ERROR_BUSY) || (ret == ERROR_NACK && retrans_cnt >= 0)); @@ -406,6 +413,7 @@ int nanohub_comms_tx_rx_retrans(struct nanohub_data *data, uint32_t cmd, int packet_size = 0; struct nanohub_packet_pad *pad = packet_alloc(GFP_KERNEL); int delay = 0; + int busy_delay = BUSY_DELAY_MIN_US; int ret; uint32_t seq; @@ -437,8 +445,10 @@ int nanohub_comms_tx_rx_retrans(struct nanohub_data *data, uint32_t cmd, if (retrans_cnt >= 0) udelay(retrans_delay); } else if (ret == ERROR_BUSY) { - usleep_range(RESEND_LONG_DELAY_US, - RESEND_LONG_DELAY_US * 2); + usleep_range(busy_delay, busy_delay * 2); + if (busy_delay < BUSY_DELAY_MAX_US) { + busy_delay = min(busy_delay * BUSY_BACKOFF_RATE, BUSY_DELAY_MAX_US); + } } } while ((ret == ERROR_BUSY) || (ret == ERROR_NACK && retrans_cnt >= 0)); |