summaryrefslogtreecommitdiff
path: root/common/usbc/usbc_task.c
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-04-30 10:07:25 -0600
committerCommit Bot <commit-bot@chromium.org>2020-05-01 22:21:44 +0000
commit5517aa585a2b0a6529cd1e2d5506dfe41d794343 (patch)
treef7f36ccd8eab966e5a671d7b67806b40ec7e5471 /common/usbc/usbc_task.c
parente71c333908978fdbce67441060aa7467b83b2bc3 (diff)
downloadchrome-ec-5517aa585a2b0a6529cd1e2d5506dfe41d794343.tar.gz
TCPMv2: Port over interrupt storm tracker from v1
Moves the storm tracker from v1 into the v2 interrupt task, to protect against poorly behaving TCPCs crashing the EC. Also lowered threshold to 400, based on empirical testing on waddledee with a single interrupt storming TCPC on the system. BRANCH=None BUG=b:153989733 TEST=on waddledee, plugging a charger into C1 results in the port periodically disabling instead of watchdog boot loops Signed-off-by: Diana Z <dzigterman@chromium.org> Change-Id: I807b411d755de3232b3b4a953cd631a34d8d9223 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2174751 Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'common/usbc/usbc_task.c')
-rw-r--r--common/usbc/usbc_task.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/common/usbc/usbc_task.c b/common/usbc/usbc_task.c
index 3ba7a81642..8f9ab0445e 100644
--- a/common/usbc/usbc_task.c
+++ b/common/usbc/usbc_task.c
@@ -34,6 +34,9 @@
#define USBC_EVENT_TIMEOUT (5 * MSEC)
+#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
+
static uint8_t paused[CONFIG_USB_PD_PORT_MAX_COUNT];
int tc_restart_tcpc(int port)
@@ -76,6 +79,14 @@ void schedule_deferred_pd_interrupt(const int port)
}
/*
+ * Theoretically, we may need to support up to 400 USB-PD packets per second for
+ * intensive operations such as FW update over PD. This value has tested well
+ * preventing watchdog resets with a single bad port partner plugged in.
+ */
+#define ALERT_STORM_MAX_COUNT 400
+#define ALERT_STORM_INTERVAL SECOND
+
+/*
* Main task entry point that handles PD interrupts for a single port
*
* @param p The PD port number for which to handle interrupts (pointer is
@@ -85,6 +96,10 @@ void pd_interrupt_handler_task(void *p)
{
const int port = (int) p;
const int port_mask = (PD_STATUS_TCPC_ALERT_0 << port);
+ struct {
+ int count;
+ timestamp_t time;
+ } storm_tracker[CONFIG_USB_PD_PORT_MAX_COUNT] = {};
ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
@@ -106,8 +121,33 @@ void pd_interrupt_handler_task(void *p)
* PD_PROCESS_INTERRUPT to check if we missed anything.
*/
while ((tcpc_get_alert_status() & port_mask) &&
- pd_is_port_enabled(port))
+ pd_is_port_enabled(port)) {
+ timestamp_t now;
+
tcpc_alert(port);
+
+ now = get_time();
+ if (timestamp_expired(storm_tracker[port].time,
+ &now)) {
+ /* Reset timer into future */
+ storm_tracker[port].time.val =
+ now.val + ALERT_STORM_INTERVAL;
+
+ /*
+ * Start at 1 since we are processing an
+ * interrupt right now
+ */
+ storm_tracker[port].count = 1;
+ } else if (++storm_tracker[port].count >
+ ALERT_STORM_MAX_COUNT) {
+ CPRINTS("C%d: Interrupt storm detected."
+ " Disabling port temporarily",
+ port);
+
+ pd_set_suspend(port, 1);
+ pd_deferred_resume(port);
+ }
+ }
}
}
}