summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Rawling <mwr@google.com>2021-09-29 21:23:21 -0700
committerAndrew Evans <andrewevans@google.com>2022-04-19 10:16:03 -0700
commit52fae86c0c3a6339847d610db904573eb611d36c (patch)
tree29051953efbe7886e12445f9d7c3ca1ef0e63e1a
parent832cf00114a3210be383afb18662f600069a2a3b (diff)
downloadnanohub-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.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/comms.c b/comms.c
index 3f9d29e..21530dd 100644
--- a/comms.c
+++ b/comms.c
@@ -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));