From 07bf28b77c7890f134e147baac0823a5c7a322f2 Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Tue, 24 Nov 2015 16:04:25 -0800 Subject: [PATCH] mec1322: i2c: Add hard-timeout for status wait Add a hard timeout to wait_for_interrupt() so that we won't wait forever, even if we get into a state where interrupts fire yet our status is not as expected. BUG=chromium:561143 TEST=Verify "ectool i2cxfer 1 0x25 1 2" doesn't watchdog on glados BRANCH=None Signed-off-by: Shawn Nematbakhsh Change-Id: I39773370bb7e45a8f0c0cdb4a463904643f72587 Reviewed-on: https://chromium-review.googlesource.com/314253 Commit-Ready: Shawn N Tested-by: Shawn N Reviewed-by: Alec Berg --- chip/mec1322/i2c.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/chip/mec1322/i2c.c b/chip/mec1322/i2c.c index 8cf92cb860..cc8649cd10 100644 --- a/chip/mec1322/i2c.c +++ b/chip/mec1322/i2c.c @@ -122,16 +122,18 @@ static void reset_controller(int controller) } } -static int wait_for_interrupt(int controller) +static int wait_for_interrupt(int controller, int timeout) { int event; + if (timeout <= 0) + return EC_ERROR_TIMEOUT; + cdata[controller].task_waiting = task_get_current(); task_enable_irq(MEC1322_IRQ_I2C_0 + controller); /* Wait until I2C interrupt or timeout. */ - event = task_wait_event_mask(TASK_EVENT_I2C_IDLE, - cdata[controller].timeout_us); + event = task_wait_event_mask(TASK_EVENT_I2C_IDLE, timeout); task_disable_irq(MEC1322_IRQ_I2C_0 + controller); cdata[controller].task_waiting = TASK_ID_INVALID; @@ -143,14 +145,15 @@ static int wait_idle(int controller) { uint8_t sts = MEC1322_I2C_STATUS(controller); uint64_t block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; - int rv; + uint64_t task_timeout = block_timeout + cdata[controller].timeout_us; + int rv = 0; while (!(sts & STS_NBB)) { - if (get_time().val > block_timeout) { - rv = wait_for_interrupt(controller); - if (rv) - return rv; - } + if (rv) + return rv; + if (get_time().val > block_timeout) + rv = wait_for_interrupt(controller, + task_timeout - get_time().val); sts = MEC1322_I2C_STATUS(controller); } @@ -163,14 +166,15 @@ static int wait_byte_done(int controller) { uint8_t sts = MEC1322_I2C_STATUS(controller); uint64_t block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; - int rv; + uint64_t task_timeout = block_timeout + cdata[controller].timeout_us; + int rv = 0; while (sts & STS_PIN) { - if (get_time().val > block_timeout) { - rv = wait_for_interrupt(controller); - if (rv) - return rv; - } + if (rv) + return rv; + if (get_time().val > block_timeout) + rv = wait_for_interrupt(controller, + task_timeout - get_time().val); sts = MEC1322_I2C_STATUS(controller); }