Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Jun 2014 21:21:55 +0200
From:      Edward Tomasz =?utf-8?Q?Napiera=C5=82a?= <trasz@FreeBSD.org>
To:        freebsd-current@FreeBSD.org
Subject:   [patch] USB after second suspend/resume on ThinkPads.
Message-ID:  <20140616192155.GE13481@brick.home>

next in thread | raw e-mail | index | archive | help
Hi.  Patch below should fix a problem where USB stops working after
_second_ suspend/resume, which happens on various ThinkPad models.
Please test, and report both success stories and failures.  If nothing
comes up, I'll commit it in a week or so.

(Btw, has anyone encountered the problem on hardware other than ThinkPads?)


Index: sys/dev/acpi_support/acpi_ibm.c
===================================================================
--- sys/dev/acpi_support/acpi_ibm.c	(revision 267417)
+++ sys/dev/acpi_support/acpi_ibm.c	(working copy)
@@ -169,6 +169,9 @@ struct acpi_ibm_softc {
 	int		light_get_supported;
 	int		light_set_supported;
 
+	/* USB power workaround */
+	ACPI_HANDLE	power_handle;
+
 	/* led(4) interface */
 	struct cdev	*led_dev;
 	int		led_busy;
@@ -365,6 +368,7 @@ acpi_ibm_attach(device_t dev)
 {
 	struct acpi_ibm_softc	*sc;
 	devclass_t		ec_devclass;
+	ACPI_STATUS		status;
 
 	ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
 
@@ -448,6 +452,17 @@ acpi_ibm_attach(device_t dev)
 	if (sc->light_set_supported)
 		sc->led_dev = led_create_state(ibm_led, sc, "thinklight", sc->light_val);
 
+	/*
+	 * Obtain a handle to the power resource available on many models.
+	 * This must be turned on manually upon resume. Otherwise the system
+	 * may, for instance, resume from S3 with usb(4) powered down.
+	 */
+	status = AcpiGetHandle(sc->handle, "\\_SB.PCI0.LPC.EC.PUBS", &sc->power_handle);
+	if (ACPI_FAILURE(status)) {
+		device_printf(dev, "Failed to get power handle\n");
+		return (status);
+	}
+
 	return (0);
 }
 
@@ -476,6 +491,7 @@ static int
 acpi_ibm_resume(device_t dev)
 {
 	struct acpi_ibm_softc *sc = device_get_softc(dev);
+	ACPI_STATUS status;
 
 	ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
 
@@ -495,6 +511,15 @@ acpi_ibm_resume(device_t dev)
 
 		acpi_ibm_sysctl_set(sc, i, val);
 	}
+	if (sc->power_handle != NULL) {
+		status = AcpiEvaluateObject(sc->power_handle,
+		    "_ON", NULL, NULL);
+		if (ACPI_FAILURE(status)) {
+			device_printf(dev, "failed to switch %s on - %s\n",
+			    acpi_name(sc->power_handle),
+			    AcpiFormatException(status));
+		}
+	}
 	ACPI_SERIAL_END(ibm);
 
 	return (0);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140616192155.GE13481>