From 946415f3a731d731cb1378d60b28f8ffab8d16cb Mon Sep 17 00:00:00 2001 From: Tim Crawford Date: Tue, 10 Oct 2023 12:12:41 -0600 Subject: [PATCH] peci: Add timeouts to infinitely blocking waits Add timeouts to the legacy PECI implementation to prevent the EC locking up when PECI stops working, such as during S0ix opportunistic suspend. This is not the optimal solution, as PECI should not be available at all to cause the lock up in the first place, but it at least prevents the issue. Signed-off-by: Tim Crawford --- src/board/system76/common/peci.c | 40 ++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/board/system76/common/peci.c b/src/board/system76/common/peci.c index 9cdf1a9..5a15031 100644 --- a/src/board/system76/common/peci.c +++ b/src/board/system76/common/peci.c @@ -33,6 +33,9 @@ int16_t peci_temp = 0; #define PECI_TEMP(X) ((int16_t)(X)) +// Maximum OOB channel response time in ms +#define PECI_ESPI_TIMEOUT 10 + // clang-format off #define FAN_POINT(T, D) { .temp = PECI_TEMP(T), .duty = PWM_DUTY(D) } // clang-format on @@ -90,9 +93,6 @@ bool peci_available(void) { #if CONFIG_PECI_OVER_ESPI -// Maximum OOB channel response time in ms -#define PECI_ESPI_TIMEOUT 10 - void peci_init(void) {} // Returns true on success, false on error @@ -291,7 +291,14 @@ void peci_init(void) { // Returns true on success, false on error bool peci_get_temp(int16_t *data) { // Wait for any in-progress transaction to complete - while (HOSTAR & BIT(0)) {} + uint32_t start = time_get(); + while (HOSTAR & BIT(0)) { + if ((time_get() - start) >= PECI_ESPI_TIMEOUT) { + DEBUG("%s: host timeout\n", __func__); + return false; + } + } + // Clear status HOSTAR = HOSTAR; @@ -309,7 +316,13 @@ bool peci_get_temp(int16_t *data) { HOCTLR |= 1; // Wait for command completion - while (!(HOSTAR & BIT(1))) {} + start = time_get(); + while (!(HOSTAR & BIT(1))) { + if ((time_get() - start) >= PECI_ESPI_TIMEOUT) { + DEBUG("%s: command timeout\n", __func__); + return false; + } + } uint8_t status = HOSTAR; if (status & 0xEC) { @@ -333,7 +346,14 @@ bool peci_get_temp(int16_t *data) { // negative (0x1000 | status register) on PECI hardware error int16_t peci_wr_pkg_config(uint8_t index, uint16_t param, uint32_t data) { // Wait for any in-progress transaction to complete - while (HOSTAR & BIT(0)) {} + uint32_t start = time_get(); + while (HOSTAR & BIT(0)) { + if ((time_get() - start) >= PECI_ESPI_TIMEOUT) { + DEBUG("%s: host timeout\n", __func__); + return false; + } + } + // Clear status HOSTAR = HOSTAR; @@ -365,7 +385,13 @@ int16_t peci_wr_pkg_config(uint8_t index, uint16_t param, uint32_t data) { HOCTLR |= 1; // Wait for command completion - while (!(HOSTAR & BIT(1))) {} + start = time_get(); + while (!(HOSTAR & BIT(1))) { + if ((time_get() - start) >= PECI_ESPI_TIMEOUT) { + DEBUG("%s: command timeout\n", __func__); + return false; + } + } uint8_t status = HOSTAR; if (status & 0xEC) {