Module Name: src Committed By: riastradh Date: Tue Jul 18 10:03:47 UTC 2023
Modified Files: src/sys/dev/acpi: acpi_ec.c Log Message: acpiec(4): Sprinkle comments. Note where this code is abusing cv_wait and needs a loop to handle spurious wakeups. No functional change intended. To generate a diff of this commit: cvs rdiff -u -r1.89 -r1.90 src/sys/dev/acpi/acpi_ec.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/acpi/acpi_ec.c diff -u src/sys/dev/acpi/acpi_ec.c:1.89 src/sys/dev/acpi/acpi_ec.c:1.90 --- src/sys/dev/acpi/acpi_ec.c:1.89 Tue Jul 18 10:03:35 2023 +++ src/sys/dev/acpi/acpi_ec.c Tue Jul 18 10:03:46 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_ec.c,v 1.89 2023/07/18 10:03:35 riastradh Exp $ */ +/* $NetBSD: acpi_ec.c,v 1.90 2023/07/18 10:03:46 riastradh Exp $ */ /*- * Copyright (c) 2007 Joerg Sonnenberger <jo...@netbsd.org>. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.89 2023/07/18 10:03:35 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.90 2023/07/18 10:03:46 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_acpi_ec.h" @@ -694,6 +694,11 @@ acpiec_read(device_t dv, uint8_t addr, u return AE_ERROR; } } else if (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, EC_CMD_TIMEOUT * hz)) { + /* + * XXX while (sc->sc_state != EC_STATE_FREE) + * cv_timedwait(...), + * plus deadline + */ mutex_exit(&sc->sc_mtx); acpiec_unlock(dv); aprint_error_dev(dv, @@ -756,6 +761,11 @@ acpiec_write(device_t dv, uint8_t addr, return AE_ERROR; } } else if (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, EC_CMD_TIMEOUT * hz)) { + /* + * XXX while (sc->sc_state != EC_STATE_FREE) + * cv_timedwait(...), + * plus deadline + */ mutex_exit(&sc->sc_mtx); acpiec_unlock(dv); aprint_error_dev(dv, @@ -869,13 +879,21 @@ acpiec_gpe_query(void *arg) int i; loop: + /* + * Wait until the EC sends an SCI requesting a query. + * + * XXX This needs to be `while', not `if'. + */ mutex_enter(&sc->sc_mtx); - if (sc->sc_got_sci == false) cv_wait(&sc->sc_cv_sci, &sc->sc_mtx); DPRINTF(ACPIEC_DEBUG_QUERY, sc, "SCI query requested\n"); mutex_exit(&sc->sc_mtx); + /* + * EC wants to submit a query to us. Exclude concurrent reads + * and writes while we handle it. + */ acpiec_lock(dv); mutex_enter(&sc->sc_mtx); @@ -893,6 +911,7 @@ loop: } DPRINTF(ACPIEC_DEBUG_QUERY, sc, "SCI polling timeout\n"); + /* XXX while (sc->sc_state != EC_STATE_FREE) cv_wait(...) */ cv_wait(&sc->sc_cv, &sc->sc_mtx); done: @@ -951,17 +970,14 @@ acpiec_gpe_state_machine(device_t dv) case EC_STATE_QUERY_VAL: if ((reg & EC_STATUS_OBF) == 0) break; /* Nothing of interest here. */ - sc->sc_cur_val = acpiec_read_data(sc); sc->sc_state = EC_STATE_FREE; - cv_signal(&sc->sc_cv); break; case EC_STATE_READ: if ((reg & EC_STATUS_IBF) != 0) break; /* Nothing of interest here. */ - acpiec_write_command(sc, EC_COMMAND_READ); sc->sc_state = EC_STATE_READ_ADDR; break; @@ -969,7 +985,6 @@ acpiec_gpe_state_machine(device_t dv) case EC_STATE_READ_ADDR: if ((reg & EC_STATUS_IBF) != 0) break; /* Nothing of interest here. */ - acpiec_write_data(sc, sc->sc_cur_addr); sc->sc_state = EC_STATE_READ_VAL; break; @@ -979,14 +994,12 @@ acpiec_gpe_state_machine(device_t dv) break; /* Nothing of interest here. */ sc->sc_cur_val = acpiec_read_data(sc); sc->sc_state = EC_STATE_FREE; - cv_signal(&sc->sc_cv); break; case EC_STATE_WRITE: if ((reg & EC_STATUS_IBF) != 0) break; /* Nothing of interest here. */ - acpiec_write_command(sc, EC_COMMAND_WRITE); sc->sc_state = EC_STATE_WRITE_ADDR; break; @@ -1003,7 +1016,6 @@ acpiec_gpe_state_machine(device_t dv) break; /* Nothing of interest here. */ sc->sc_state = EC_STATE_FREE; cv_signal(&sc->sc_cv); - acpiec_write_data(sc, sc->sc_cur_val); break; @@ -1014,10 +1026,15 @@ acpiec_gpe_state_machine(device_t dv) cv_signal(&sc->sc_cv_sci); } break; + default: panic("invalid state"); } + /* + * In case GPE interrupts are broken, poll once per tick for EC + * status updates while a transaction is still pending. + */ if (sc->sc_state != EC_STATE_FREE) { DPRINTF(ACPIEC_DEBUG_INTR, sc, "schedule callout\n"); callout_schedule(&sc->sc_pseudo_intr, 1);