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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel