summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica
diff options
context:
space:
mode:
authorsilby <silby@FreeBSD.org>2008-12-13 06:04:34 +0000
committersilby <silby@FreeBSD.org>2008-12-13 06:04:34 +0000
commit87d51087469197c8178c6ac4f4b0ba96f7ce41dc (patch)
treeb655bc3dbf1893db64ed01ddacbd2a6209faf693 /sys/dev/acpica
parent477666d0ad0d8897c20b61df3484a084fccd3840 (diff)
downloadFreeBSD-src-87d51087469197c8178c6ac4f4b0ba96f7ce41dc.zip
FreeBSD-src-87d51087469197c8178c6ac4f4b0ba96f7ce41dc.tar.gz
Add the sysctl debug.acpi.batt.batt_sleep_ms.
On some laptops with smart batteries, enabling battery monitoring software causes keystrokes from atkbd to be lost. This has also been reported on Linux, and is apparently due to the keyboard and I2C line for the battery being routed through the same chip. Whether that's accurate or not, adding extra sleeps to the status checking code causes the problem to go away. I've been running this for nearly six months now on my laptop, it works like a charm. Reviewed by: Nate Lawson (in a previous revision) MFC after: 2 weeks
Diffstat (limited to 'sys/dev/acpica')
-rw-r--r--sys/dev/acpica/acpi_smbat.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/sys/dev/acpica/acpi_smbat.c b/sys/dev/acpica/acpi_smbat.c
index 5e1c66e..d358ffd 100644
--- a/sys/dev/acpica/acpi_smbat.c
+++ b/sys/dev/acpica/acpi_smbat.c
@@ -61,6 +61,23 @@ static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst);
ACPI_SERIAL_DECL(smbat, "ACPI Smart Battery");
+SYSCTL_DECL(_debug_acpi);
+SYSCTL_NODE(_debug_acpi, OID_AUTO, batt, CTLFLAG_RD, NULL, "Battery debugging");
+
+/* On some laptops with smart batteries, enabling battery monitoring
+ * software causes keystrokes from atkbd to be lost. This has also been
+ * reported on Linux, and is apparently due to the keyboard and I2C line
+ * for the battery being routed through the same chip. Whether that's
+ * accurate or not, adding extra sleeps to the status checking code
+ * causes the problem to go away.
+ *
+ * If you experience that problem, try a value of 10ms and move up
+ * from there.
+ */
+static int batt_sleep_ms;
+SYSCTL_INT(_debug_acpi_batt, OID_AUTO, batt_sleep_ms, CTLFLAG_RW, &batt_sleep_ms, 0,
+ "Sleep during battery status updates to prevent keystroke loss.");
+
static device_method_t acpi_smbat_methods[] = {
/* device interface */
DEVMETHOD(device_probe, acpi_smbat_probe),
@@ -176,6 +193,9 @@ acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
ACPI_SERIAL_ASSERT(smbat);
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
val = addr;
error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR,
val, 1);
@@ -194,6 +214,9 @@ acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
if (error)
goto out;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
for (to = SMBUS_TIMEOUT; to != 0; to--) {
error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
&val, 1);
@@ -239,6 +262,9 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
ACPI_SERIAL_ASSERT(smbat);
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
val = addr;
error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR,
val, 1);
@@ -257,6 +283,9 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
if (error)
goto out;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
for (to = SMBUS_TIMEOUT; to != 0; to--) {
error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
&val, 1);
@@ -292,6 +321,9 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
if (len > val)
len = val;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
while (len--) {
error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_DATA
+ len, &val, 1);
@@ -299,6 +331,8 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
goto out;
ptr[len] = val;
+ if (batt_sleep_ms)
+ AcpiOsSleep(1);
}
out:
OpenPOWER on IntegriCloud