diff options
author | Marius Schilder <mschilder@google.com> | 2018-01-03 22:34:27 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2018-02-01 00:48:08 +0000 |
commit | 4baa9343b7624807bb8676b681720c7329fa0af1 (patch) | |
tree | 12b0f72eab1c7bc9b2d362a6454e85afcdca6619 | |
parent | 25f9804269152c564ca593c51405b2574bd7fe35 (diff) | |
download | chrome-ec-4baa9343b7624807bb8676b681720c7329fa0af1.tar.gz |
g: fix flaky timeout check for spi transfer.
Typically this routine runs on low priority hook task.
A pre-emption by a higher priority task might be mistaken for timeout.
Double check the transfer done status after the timeout time has passed.
Also clear the TXDONE status before starting a fresh transaction to make sure
we wait for the current transaction to complete; an errand TXDONE status
at start of the transaction will pre-empt waiting for the current transaction
and return stale data.
BRANCH=none
TEST=mn50 stress test fails within minutes vs. now stable.
Main test component is higher priority console task
that does intermittent compute during usb-spi transfers.
Change-Id: Ide4390e42d3957bc45eea8160617a52dd31ed866
Reviewed-on: https://chromium-review.googlesource.com/849662
Commit-Ready: Marius Schilder <mschilder@chromium.org>
Tested-by: Marius Schilder <mschilder@chromium.org>
Reviewed-by: Marius Schilder <mschilder@chromium.org>
Reviewed-by: Nagendra Modadugu <ngm@google.com>
Reviewed-by: Nick Sanders <nsanders@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
(cherry picked from commit 1c1af98e405d291606a4a862459d3acb134c9ca3)
Reviewed-on: https://chromium-review.googlesource.com/896752
Tested-by: Vadim Bendebury <vbendeb@chromium.org>
Commit-Queue: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r-- | chip/g/spi_master.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/chip/g/spi_master.c b/chip/g/spi_master.c index 13d8e15b75..e3547d0d97 100644 --- a/chip/g/spi_master.c +++ b/chip/g/spi_master.c @@ -79,6 +79,7 @@ int spi_transaction(const struct spi_device_t *spi_device, #endif /* CONFIG_SPI_MASTER_NO_CS_GPIOS */ /* Initiate the transaction. */ + GWRITE_FIELD_I(SPI, port, ISTATE_CLR, TXDONE, 1); GWRITE_FIELD_I(SPI, port, XACT, SIZE, transaction_size - 1); GWRITE_FIELD_I(SPI, port, XACT, START, 1); @@ -87,6 +88,11 @@ int spi_transaction(const struct spi_device_t *spi_device, while (!GREAD_FIELD_I(SPI, port, ISTATE, TXDONE)) { /* Give up if the deadline has been exceeded. */ if (get_time().val > timeout.val) { + /* Might have been pre-empted by other task. + * Check ISTATE.TXDONE again for legit timeout. + */ + if (GREAD_FIELD_I(SPI, port, ISTATE, TXDONE)) + break; rv = EC_ERROR_TIMEOUT; goto err_cs_high; } |