summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Schilder <mschilder@google.com>2018-01-03 22:34:27 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-02-01 00:48:08 +0000
commit4baa9343b7624807bb8676b681720c7329fa0af1 (patch)
tree12b0f72eab1c7bc9b2d362a6454e85afcdca6619
parent25f9804269152c564ca593c51405b2574bd7fe35 (diff)
downloadchrome-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.c6
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;
}