On Thu, Oct 05, 2006 at 09:04:11AM +0200, Oliver Neukum wrote:
> Hi,
> 
> this implements suspend support for usblp. According to the CUPS people
> ENODEV will make CUPS retry the job. Thus it is returned in the runtime
> case. My printer survives suspend/resume cycles with it.
> 
>       Regards
>               Oliver

It looks very good, thanks Oliver! I hope it works as well, too. :)

> Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
Signed-off-by: Vojtech Pavlik <[EMAIL PROTECTED]>

Greg, can you add this to your tree?

Vojtech

> --- current/drivers/usb/class/usblp.c 2006-09-20 05:42:06.000000000 +0200
> +++ linux-2.6.18/drivers/usb/class/usblp.c    2006-10-05 08:50:57.000000000 
> +0200
> @@ -154,6 +154,7 @@
>       unsigned char           used;                   /* True if open */
>       unsigned char           present;                /* True if not 
> disconnected */
>       unsigned char           bidir;                  /* interface is 
> bidirectional */
> +     unsigned char           sleeping;               /* interface is 
> suspended */
>       unsigned char           *device_id_string;      /* IEEE 1284 DEVICE ID 
> string (ptr) */
>                                                       /* first 2 bytes are 
> (big-endian) length */
>  };
> @@ -183,6 +184,7 @@
>       dbg("quirks=%d", usblp->quirks);
>       dbg("used=%d", usblp->used);
>       dbg("bidir=%d", usblp->bidir);
> +     dbg("sleeping=%d", usblp->sleeping);
>       dbg("device_id_string=\"%s\"",
>               usblp->device_id_string ?
>                       usblp->device_id_string + 2 :
> @@ -338,6 +340,20 @@
>       return newerr;
>  }
>  
> +static int handle_bidir (struct usblp *usblp)
> +{
> +     if (usblp->bidir && usblp->used && !usblp->sleeping) {
> +             usblp->readcount = 0;
> +             usblp->readurb->dev = usblp->dev;
> +             if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
> +                     usblp->used = 0;
> +                     return -EIO;
> +             }
> +     }
> +
> +     return 0;
> +}
> +
>  /*
>   * File op functions.
>   */
> @@ -390,14 +406,9 @@
>       usblp->writeurb->status = 0;
>       usblp->readurb->status = 0;
>  
> -     if (usblp->bidir) {
> -             usblp->readcount = 0;
> -             usblp->readurb->dev = usblp->dev;
> -             if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
> -                     retval = -EIO;
> -                     usblp->used = 0;
> -                     file->private_data = NULL;
> -             }
> +     if (handle_bidir(usblp) < 0) {
> +             file->private_data = NULL;
> +             retval = -EIO;
>       }
>  out:
>       mutex_unlock (&usblp_mutex);
> @@ -460,6 +471,11 @@
>               goto done;
>       }
>  
> +     if (usblp->sleeping) {
> +             retval = -ENODEV;
> +             goto done;
> +     }
> +
>       dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, 
> _IOC_TYPE(cmd),
>               _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) );
>  
> @@ -658,6 +674,11 @@
>                       return -ENODEV;
>               }
>  
> +             if (usblp->sleeping) {
> +                     up (&usblp->sem);
> +                     return writecount ? writecount : -ENODEV;
> +             }
> +
>               if (usblp->writeurb->status != 0) {
>                       if (usblp->quirks & USBLP_QUIRK_BIDIR) {
>                               if (!usblp->wcomplete)
> @@ -749,6 +770,11 @@
>               goto done;
>       }
>  
> +     if (usblp->sleeping) {
> +             count = -ENODEV;
> +             goto done;
> +     }
> +
>       if (usblp->readurb->status) {
>               err("usblp%d: error %d reading from printer",
>                       usblp->minor, usblp->readurb->status);
> @@ -1170,6 +1196,41 @@
>       mutex_unlock (&usblp_mutex);
>  }
>  
> +static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
> +{
> +     struct usblp *usblp = usb_get_intfdata (intf);
> +
> +     /* this races against normal access and open */
> +     mutex_lock (&usblp_mutex);
> +     down (&usblp->sem);
> +     /* we take no more IO */
> +     usblp->sleeping = 1;
> +     /* we wait for anything printing */
> +     wait_event (usblp->wait, usblp->wcomplete || !usblp->present);
> +     usblp_unlink_urbs(usblp);
> +     up (&usblp->sem);
> +     mutex_unlock (&usblp_mutex);
> +
> +     return 0;
> +}
> +
> +static int usblp_resume (struct usb_interface *intf)
> +{
> +     struct usblp *usblp = usb_get_intfdata (intf);
> +     int r;
> +
> +     mutex_lock (&usblp_mutex);
> +     down (&usblp->sem);
> +
> +     usblp->sleeping = 0;
> +     r = handle_bidir (usblp);
> +
> +     up (&usblp->sem);
> +     mutex_unlock (&usblp_mutex);
> +
> +     return r;
> +}
> +
>  static struct usb_device_id usblp_ids [] = {
>       { USB_DEVICE_INFO(7, 1, 1) },
>       { USB_DEVICE_INFO(7, 1, 2) },
> @@ -1186,6 +1247,8 @@
>       .name =         "usblp",
>       .probe =        usblp_probe,
>       .disconnect =   usblp_disconnect,
> +     .suspend =      usblp_suspend,
> +     .resume =       usblp_resume,
>       .id_table =     usblp_ids,
>  };
>  


-- 
Vojtech Pavlik
Director SuSE Labs

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to