Signed-off-by: Harrison Metzger <harrisonmetz@xxxxxxxxx> On Mon, Jul 13, 2009 at 9:45 AM, Oliver Neukum<oliver@xxxxxxxxxx> wrote:> This patch adds to the usbsevseg driver:>> - suspend/resume support> - reset_resume support> - autosuspend using the display's power state to determine idleness>> Signed-off-by: Oliver Neukum <oliver@xxxxxxxxxx>>> Hi,>> Harrison and I have added pm support to the usbsevseg driver.>> Regards> Oliver> -->> commit e57549bbabb8462ed30474d5590cd70aff49a75c> Author: Oliver Neukum <oliver@xxxxxxxxxx>> Date: Mon Jul 13 16:30:37 2009 +0200>> usb: full power management support for usbsevseg>> diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c> index 28a6a3a..3db2555 100644> --- a/drivers/usb/misc/usbsevseg.c> +++ b/drivers/usb/misc/usbsevseg.c> @@ -38,6 +38,7 @@ static char *display_textmodes[] = {"raw", "hex", "ascii", NULL};>> struct usb_sevsegdev {> struct usb_device *udev;> + struct usb_interface *intf;>> u8 powered;> u8 mode_msb;> @@ -46,6 +47,8 @@ struct usb_sevsegdev {> u8 textmode;> u8 text[MAXLEN];> u16 textlength;> +> + u8 shadow_power; /* for PM */> };>> /* sysfs_streq can't replace this completely> @@ -65,6 +68,12 @@ static void update_display_powered(struct usb_sevsegdev *mydev)> {> int rc;>> + if (!mydev->shadow_power && mydev->powered) {> + rc = usb_autopm_get_interface(mydev->intf);> + if (rc < 0)> + return;> + }> +> rc = usb_control_msg(mydev->udev,> usb_sndctrlpipe(mydev->udev, 0),> 0x12,> @@ -76,12 +85,18 @@ static void update_display_powered(struct usb_sevsegdev *mydev)> 2000);> if (rc < 0)> dev_dbg(&mydev->udev->dev, "power retval = %d\n", rc);> +> + if (mydev->shadow_power && !mydev->powered)> + usb_autopm_put_interface(mydev->intf);> }>> static void update_display_mode(struct usb_sevsegdev *mydev)> {> int rc;>> + if(mydev->shadow_power != 1)> + return;> +> rc = usb_control_msg(mydev->udev,> usb_sndctrlpipe(mydev->udev, 0),> 0x12,> @@ -96,14 +111,17 @@ static void update_display_mode(struct usb_sevsegdev *mydev)> dev_dbg(&mydev->udev->dev, "mode retval = %d\n", rc);> }>> -static void update_display_visual(struct usb_sevsegdev *mydev)> +static void update_display_visual(struct usb_sevsegdev *mydev, gfp_t mf)> {> int rc;> int i;> unsigned char *buffer;> u8 decimals = 0;>> - buffer = kzalloc(MAXLEN, GFP_KERNEL);> + if(mydev->shadow_power != 1)> + return;> +> + buffer = kzalloc(MAXLEN, mf);> if (!buffer) {> dev_err(&mydev->udev->dev, "out of memory\n");> return;> @@ -163,7 +181,7 @@ static ssize_t set_attr_##name(struct device *dev, \> struct usb_sevsegdev *mydev = usb_get_intfdata(intf); \> \> mydev->name = simple_strtoul(buf, NULL, 10); \> - update_fcn(mydev); \> + update_fcn(mydev); \> \> return count; \> } \> @@ -194,7 +212,7 @@ static ssize_t set_attr_text(struct device *dev,> if (end > 0)> memcpy(mydev->text, buf, end);>> - update_display_visual(mydev);> + update_display_visual(mydev, GFP_KERNEL);> return count;> }>> @@ -242,7 +260,7 @@ static ssize_t set_attr_decimals(struct device *dev,> if (buf[i] == '1')> mydev->decimals[end-1-i] = 1;>> - update_display_visual(mydev);> + update_display_visual(mydev, GFP_KERNEL);>> return count;> }> @@ -286,7 +304,7 @@ static ssize_t set_attr_textmode(struct device *dev,> for (i = 0; display_textmodes[i]; i++) {> if (sysfs_streq(display_textmodes[i], buf)) {> mydev->textmode = i;> - update_display_visual(mydev);> + update_display_visual(mydev, GFP_KERNEL);> return count;> }> }> @@ -330,6 +348,7 @@ static int sevseg_probe(struct usb_interface *interface,> }>> mydev->udev = usb_get_dev(udev);> + mydev->intf = interface;> usb_set_intfdata(interface, mydev);>> /*set defaults */> @@ -364,11 +383,49 @@ static void sevseg_disconnect(struct usb_interface *interface)> dev_info(&interface->dev, "USB 7 Segment now disconnected\n");> }>> +static int sevseg_suspend(struct usb_interface *intf, pm_message_t message)> +{> + struct usb_sevsegdev *mydev;> +> + mydev = usb_get_intfdata(intf);> + mydev->shadow_power = 0;> +> + return 0;> +}> +> +static int sevseg_resume(struct usb_interface *intf)> +{> + struct usb_sevsegdev *mydev;> +> + mydev = usb_get_intfdata(intf);> + mydev->shadow_power = 1;> + update_display_mode(mydev);> + update_display_visual(mydev, GFP_NOIO);> +> + return 0;> +}> +> +static int sevseg_reset_resume(struct usb_interface *intf)> +{> + struct usb_sevsegdev *mydev;> +> + mydev = usb_get_intfdata(intf);> + mydev->shadow_power = 1;> + update_display_mode(mydev);> + update_display_visual(mydev, GFP_NOIO);> +> + return 0;> +}> +> static struct usb_driver sevseg_driver = {> .name = "usbsevseg",> .probe = sevseg_probe,> .disconnect = sevseg_disconnect,> + .suspend = sevseg_suspend,> + .resume = sevseg_resume,> + .reset_resume = sevseg_reset_resume,> .id_table = id_table,> + .supports_autosuspend = 1,> };>> static int __init usb_sevseg_init(void)>>��.n��������+%������w��{.n�����{���)��jg��������ݢj����G�������j:+v���w�m������w�������h�����٥