Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7bbe990c989ee16f2c1be3e4ae28f8004bec788c
Commit:     7bbe990c989ee16f2c1be3e4ae28f8004bec788c
Parent:     55b3fd41b0846929f68b5fb1058ad8077289f584
Author:     Oliver Neukum <[EMAIL PROTECTED]>
AuthorDate: Wed Jun 13 17:13:31 2007 +0200
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Thu Jul 12 16:34:38 2007 -0700

    USB: autosuspend for usblcd
    
    this patch implements autosuspend for the usblcd driver. It uses
    the new usb_anchor infrastructure. Many thanks to Georges for testing.
    
    Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
    Cc: Georges Toth <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/misc/usblcd.c |   46 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 6e093c2..504f722 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -45,6 +45,7 @@ struct usb_lcd {
        struct kref             kref;
        struct semaphore        limit_sem;              /* to stop writes at 
full throttle from
                                                         * using up all RAM */
+       struct usb_anchor       submitted;              /* URBs to wait for 
before suspend */
 };
 #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
 
@@ -67,7 +68,7 @@ static int lcd_open(struct inode *inode, struct file *file)
 {
        struct usb_lcd *dev;
        struct usb_interface *interface;
-       int subminor;
+       int subminor, r;
 
        subminor = iminor(inode);
 
@@ -85,6 +86,13 @@ static int lcd_open(struct inode *inode, struct file *file)
        /* increment our usage count for the device */
        kref_get(&dev->kref);
 
+       /* grab a power reference */
+       r = usb_autopm_get_interface(interface);
+       if (r < 0) {
+               kref_put(&dev->kref, lcd_delete);
+               return r;
+       }
+
        /* save our object in the file's private structure */
        file->private_data = dev;
 
@@ -100,6 +108,7 @@ static int lcd_release(struct inode *inode, struct file 
*file)
                return -ENODEV;
 
        /* decrement the count on our device */
+       usb_autopm_put_interface(dev->interface);
        kref_put(&dev->kref, lcd_delete);
        return 0;
 }
@@ -225,12 +234,14 @@ static ssize_t lcd_write(struct file *file, const char 
__user * user_buffer, siz
                          usb_sndbulkpipe(dev->udev, 
dev->bulk_out_endpointAddr),
                          buf, count, lcd_write_bulk_callback, dev);
        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       usb_anchor_urb(urb, &dev->submitted);
        
        /* send the data out the bulk port */
        retval = usb_submit_urb(urb, GFP_KERNEL);
        if (retval) {
                err("USBLCD: %s - failed submitting write urb, error %d", 
__FUNCTION__, retval);
-               goto error;
+               goto error_unanchor;
        }
        
        /* release our reference to this urb, the USB core will eventually free 
it entirely */
@@ -238,7 +249,8 @@ static ssize_t lcd_write(struct file *file, const char 
__user * user_buffer, siz
 
 exit:
        return count;
-
+error_unanchor:
+       usb_unanchor_urb(urb);
 error:
        usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
        usb_free_urb(urb);
@@ -283,6 +295,7 @@ static int lcd_probe(struct usb_interface *interface, const 
struct usb_device_id
        }
        kref_init(&dev->kref);
        sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES);
+       init_usb_anchor(&dev->submitted);
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
@@ -350,6 +363,30 @@ error:
        return retval;
 }
 
+static void lcd_draw_down(struct usb_lcd *dev)
+{
+       int time;
+
+       time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+       if (!time)
+               usb_kill_anchored_urbs(&dev->submitted);
+}
+
+static int lcd_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct usb_lcd *dev = usb_get_intfdata(intf);
+
+       if (!dev)
+               return 0;
+       lcd_draw_down(dev);
+       return 0;
+}
+
+static int lcd_resume (struct usb_interface *intf)
+{
+       return 0;
+}
+
 static void lcd_disconnect(struct usb_interface *interface)
 {
        struct usb_lcd *dev;
@@ -371,7 +408,10 @@ static struct usb_driver lcd_driver = {
        .name =         "usblcd",
        .probe =        lcd_probe,
        .disconnect =   lcd_disconnect,
+       .suspend =      lcd_suspend,
+       .resume =       lcd_resume,
        .id_table =     id_table,
+       .supports_autosuspend = 1,
 };
 
 static int __init usb_lcd_init(void)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to