> It seems to me that you must not use GFP_KERNEL in resume()
> You may be resumed before paging devices, thus you cannot do io,
> hence you should use GFP_NOIO.

Interesting point.  Well, I forgot Greg's favorite line ("Signed...") too,
so here's an updated version ...

- Dave

Basic HID driver support for USB suspend/resume.  At least one keyboard
works OK as a remote wakeup source ... unless you write the sysfs
power/state attribute using that USB keyboard, in which case the input
subsystem reports an endless stream of newlines!  :)

Someone still needs to implement some configurable timer to support the
"suspend idle mice/keyboards/..." policy for devices that can issue
wakeup events.  In conjunction with autosuspend policies in hub and
HCD (UHCI) code, that could allegedly save 2W of power by enabling the
C3 state on Centrino laptops that use USB mice.

Signed-off-by: David Brownell <[EMAIL PROTECTED]>

--- 1.95/drivers/usb/input/hid-core.c	Mon Sep 20 10:31:27 2004
+++ edited/drivers/usb/input/hid-core.c	Fri Oct  1 19:12:41 2004
@@ -925,6 +925,7 @@
 		case -ECONNRESET:	/* unlink */
 		case -ENOENT:
 		case -ESHUTDOWN:
+		case -EPERM:
 			return;
 		default:		/* error */
 			warn("input irq status %d received", urb->status);
@@ -1823,6 +1824,30 @@
 	return 0;
 }
 
+static int hid_suspend(struct usb_interface *intf, u32 state)
+{
+	struct hid_device *hid = usb_get_intfdata (intf);
+
+	usb_kill_urb(hid->urbin);
+	intf->dev.power.power_state = state;
+	dev_dbg(&intf->dev, "suspend\n");
+	return 0;
+}
+
+static int hid_resume(struct usb_interface *intf)
+{
+	struct hid_device *hid = usb_get_intfdata (intf);
+	int status;
+
+	intf->dev.power.power_state = PM_SUSPEND_ON;
+	if (hid->open)
+		status = usb_submit_urb(hid->urbin, GFP_NOIO);
+	else
+		status = 0;
+	dev_dbg(&intf->dev, "resume status %d\n", status);
+	return status;
+}
+
 static struct usb_device_id hid_usb_ids [] = {
 	{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
 	    .bInterfaceClass = USB_INTERFACE_CLASS_HID },
@@ -1836,6 +1861,8 @@
 	.name =		"usbhid",
 	.probe =	hid_probe,
 	.disconnect =	hid_disconnect,
+	.suspend =	hid_suspend,
+	.resume =	hid_resume,
 	.id_table =	hid_usb_ids,
 };
 

Reply via email to