From patchwork Mon Jun 7 20:50:20 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Stern X-Patchwork-Id: 104831 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o57KoMrw020958 for ; Mon, 7 Jun 2010 20:50:22 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753413Ab0FGUuV (ORCPT ); Mon, 7 Jun 2010 16:50:21 -0400 Received: from iolanthe.rowland.org ([192.131.102.54]:41186 "HELO iolanthe.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1753368Ab0FGUuU (ORCPT ); Mon, 7 Jun 2010 16:50:20 -0400 Received: (qmail 18892 invoked by uid 2102); 7 Jun 2010 16:50:20 -0400 Received: from localhost (sendmail-bs@127.0.0.1) by localhost with SMTP; 7 Jun 2010 16:50:20 -0400 Date: Mon, 7 Jun 2010 16:50:20 -0400 (EDT) From: Alan Stern X-X-Sender: stern@iolanthe.rowland.org To: Len Brown cc: Bjorn Helgaas , "Rafael J. Wysocki" , Subject: [PATCH] PNPACPI: add support for remote wakeup Message-ID: MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 07 Jun 2010 20:50:22 +0000 (UTC) Index: usb-2.6/include/linux/pnp.h =================================================================== --- usb-2.6.orig/include/linux/pnp.h +++ usb-2.6/include/linux/pnp.h @@ -414,6 +414,7 @@ struct pnp_protocol { int (*disable) (struct pnp_dev *dev); /* protocol specific suspend/resume */ + bool (*can_wakeup) (struct pnp_dev *dev); int (*suspend) (struct pnp_dev * dev, pm_message_t state); int (*resume) (struct pnp_dev * dev); Index: usb-2.6/drivers/pnp/core.c =================================================================== --- usb-2.6.orig/drivers/pnp/core.c +++ usb-2.6/drivers/pnp/core.c @@ -164,6 +164,9 @@ int __pnp_add_device(struct pnp_dev *dev list_add_tail(&dev->global_list, &pnp_global); list_add_tail(&dev->protocol_list, &dev->protocol->devices); spin_unlock(&pnp_lock); + if (dev->protocol->can_wakeup) + device_set_wakeup_capable(&dev->dev, + dev->protocol->can_wakeup(dev)); return device_register(&dev->dev); } Index: usb-2.6/drivers/pnp/pnpacpi/core.c =================================================================== --- usb-2.6.orig/drivers/pnp/pnpacpi/core.c +++ usb-2.6/drivers/pnp/pnpacpi/core.c @@ -121,17 +121,37 @@ static int pnpacpi_disable_resources(str } #ifdef CONFIG_ACPI_SLEEP +static bool pnpacpi_can_wakeup(struct pnp_dev *dev) +{ + struct acpi_device *acpi_dev = dev->data; + acpi_handle handle = acpi_dev->handle; + + return acpi_bus_can_wakeup(handle); +} + static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) { struct acpi_device *acpi_dev = dev->data; acpi_handle handle = acpi_dev->handle; int power_state; + if (device_can_wakeup(&dev->dev)) { + int rc = acpi_pm_device_sleep_wake(&dev->dev, + device_may_wakeup(&dev->dev)); + + if (rc) + return rc; + } power_state = acpi_pm_device_sleep_state(&dev->dev, NULL); if (power_state < 0) power_state = (state.event == PM_EVENT_ON) ? ACPI_STATE_D0 : ACPI_STATE_D3; + /* acpi_bus_set_power() often fails (keyboard port can't be + * powered-down?), and in any case, our return value is ignored + * by pnp_bus_suspend(). Hence we don't revert the wakeup + * setting if the set_power fails. + */ return acpi_bus_set_power(handle, power_state); } @@ -140,6 +160,8 @@ static int pnpacpi_resume(struct pnp_dev struct acpi_device *acpi_dev = dev->data; acpi_handle handle = acpi_dev->handle; + if (device_may_wakeup(&dev->dev)) + acpi_pm_device_sleep_wake(&dev->dev, false); return acpi_bus_set_power(handle, ACPI_STATE_D0); } #endif @@ -150,6 +172,7 @@ struct pnp_protocol pnpacpi_protocol = { .set = pnpacpi_set_resources, .disable = pnpacpi_disable_resources, #ifdef CONFIG_ACPI_SLEEP + .can_wakeup = pnpacpi_can_wakeup, .suspend = pnpacpi_suspend, .resume = pnpacpi_resume, #endif