svn commit: r186026 - head/sys/dev/acpica

Mike Silbersack silby at FreeBSD.org
Sat Dec 13 06:04:35 UTC 2008


Author: silby
Date: Sat Dec 13 06:04:34 2008
New Revision: 186026
URL: http://svn.freebsd.org/changeset/base/186026

Log:
  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

Modified:
  head/sys/dev/acpica/acpi_smbat.c

Modified: head/sys/dev/acpica/acpi_smbat.c
==============================================================================
--- head/sys/dev/acpica/acpi_smbat.c	Sat Dec 13 06:01:54 2008	(r186025)
+++ head/sys/dev/acpica/acpi_smbat.c	Sat Dec 13 06:04:34 2008	(r186026)
@@ -61,6 +61,23 @@ static int	acpi_smbat_get_bst(device_t d
 
 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_soft
 
 	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_soft
 	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_smba
 
 	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_smba
 	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_smba
 	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_smba
 			goto out;
 
 		ptr[len] = val;
+		if (batt_sleep_ms)
+		    AcpiOsSleep(1);
 	}
 
 out:


More information about the svn-src-all mailing list