[RFC] Wakeup for PNP

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 23 Feb 2010, Dmitry Torokhov wrote:

> Yes, I agree, we need a genric mechanism for PNP to emable wakups. It
> was discussed a bit here:
> 
> 	http://bugzilla.kernel.org/show_bug.cgi?id=8286
> 
> but David was too hung up on the fact that number of devices in ACPI
> does not map directly onto number of serio ports when i8042 is in active
> multiplexing mode that it id not go anywhere.

Does this look reasonable?  I don't know anything about PNPBIOS or 
ISAPNP, so it handles only PNPACPI.  But at least it's a starting 
point -- and it does enable my system to wake up in response to 
hitting a key.

(This combines changes to the PNP core with changes to the i8042 
drivers.  For submission they can be broken out into separate patches.)

Alan Stern


Index: usb-2.6/drivers/input/serio/i8042-x86ia64io.h
===================================================================
--- usb-2.6.orig/drivers/input/serio/i8042-x86ia64io.h
+++ usb-2.6/drivers/input/serio/i8042-x86ia64io.h
@@ -625,6 +625,7 @@ static int i8042_pnp_kbd_probe(struct pn
 	}
 
 	i8042_pnp_kbd_devices++;
+	device_set_wakeup_enable(&dev->dev, true);
 	return 0;
 }
 
@@ -646,6 +647,7 @@ static int i8042_pnp_aux_probe(struct pn
 	}
 
 	i8042_pnp_aux_devices++;
+	device_set_wakeup_enable(&dev->dev, true);
 	return 0;
 }
 
@@ -656,7 +658,7 @@ static struct pnp_device_id pnp_kbd_devi
 };
 
 static struct pnp_driver i8042_pnp_kbd_driver = {
-	.name           = "i8042 kbd",
+	.name           = "i8042-kbd",
 	.id_table       = pnp_kbd_devids,
 	.probe          = i8042_pnp_kbd_probe,
 };
@@ -676,7 +678,7 @@ static struct pnp_device_id pnp_aux_devi
 };
 
 static struct pnp_driver i8042_pnp_aux_driver = {
-	.name           = "i8042 aux",
+	.name           = "i8042-aux",
 	.id_table       = pnp_aux_devids,
 	.probe          = i8042_pnp_aux_probe,
 };
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);
+	device_set_wakeup_capable(&dev->dev,
+			dev->protocol->can_wakeup &&
+			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,12 +121,27 @@ static int pnpacpi_disable_resources(str
 }
 
 #ifdef CONFIG_ACPI_SLEEP
+static bool pnpacpi_can_wakeup(struct pnp_dev *dev)
+{
+	acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
+
+	return handle && 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 ret;
+
+		ret = acpi_pm_device_sleep_wake(&dev->dev,
+				device_may_wakeup(&dev->dev));
+		if (ret)
+			return ret;
+	}
 	power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
 	if (power_state < 0)
 		power_state = (state.event == PM_EVENT_ON) ?
@@ -140,6 +155,8 @@ static int pnpacpi_resume(struct pnp_dev
 	struct acpi_device *acpi_dev = dev->data;
 	acpi_handle handle = acpi_dev->handle;
 
+	if (device_can_wakeup(&dev->dev))
+		acpi_pm_device_sleep_wake(&dev->dev, false);
 	return acpi_bus_set_power(handle, ACPI_STATE_D0);
 }
 #endif
@@ -150,6 +167,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
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);
 

_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux