aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2006-10-05 03:04:11 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-10-17 17:46:31 -0400
commit516077c1ee8a4a47cc41634a29954b636f3975ea (patch)
tree937b43dd72ce5a745efb2f2b670c9ced199423d1 /drivers/usb/class
parent44960af1b6ab3e8fd23dc134fcf7862caf42936b (diff)
USB: fix suspend support for usblp
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. Signed-off-by: Oliver Neukum <oliver@neukum.name> Signed-off-by: Vojtech Pavlik <vojtech@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/usblp.c79
1 files changed, 71 insertions, 8 deletions
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index a161d70e1e42..809d465eb257 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -154,6 +154,7 @@ struct usblp {
154 unsigned char used; /* True if open */ 154 unsigned char used; /* True if open */
155 unsigned char present; /* True if not disconnected */ 155 unsigned char present; /* True if not disconnected */
156 unsigned char bidir; /* interface is bidirectional */ 156 unsigned char bidir; /* interface is bidirectional */
157 unsigned char sleeping; /* interface is suspended */
157 unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ 158 unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */
158 /* first 2 bytes are (big-endian) length */ 159 /* first 2 bytes are (big-endian) length */
159}; 160};
@@ -183,6 +184,7 @@ static void usblp_dump(struct usblp *usblp) {
183 dbg("quirks=%d", usblp->quirks); 184 dbg("quirks=%d", usblp->quirks);
184 dbg("used=%d", usblp->used); 185 dbg("used=%d", usblp->used);
185 dbg("bidir=%d", usblp->bidir); 186 dbg("bidir=%d", usblp->bidir);
187 dbg("sleeping=%d", usblp->sleeping);
186 dbg("device_id_string=\"%s\"", 188 dbg("device_id_string=\"%s\"",
187 usblp->device_id_string ? 189 usblp->device_id_string ?
188 usblp->device_id_string + 2 : 190 usblp->device_id_string + 2 :
@@ -338,6 +340,20 @@ static int usblp_check_status(struct usblp *usblp, int err)
338 return newerr; 340 return newerr;
339} 341}
340 342
343static int handle_bidir (struct usblp *usblp)
344{
345 if (usblp->bidir && usblp->used && !usblp->sleeping) {
346 usblp->readcount = 0;
347 usblp->readurb->dev = usblp->dev;
348 if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
349 usblp->used = 0;
350 return -EIO;
351 }
352 }
353
354 return 0;
355}
356
341/* 357/*
342 * File op functions. 358 * File op functions.
343 */ 359 */
@@ -390,14 +406,9 @@ static int usblp_open(struct inode *inode, struct file *file)
390 usblp->writeurb->status = 0; 406 usblp->writeurb->status = 0;
391 usblp->readurb->status = 0; 407 usblp->readurb->status = 0;
392 408
393 if (usblp->bidir) { 409 if (handle_bidir(usblp) < 0) {
394 usblp->readcount = 0; 410 file->private_data = NULL;
395 usblp->readurb->dev = usblp->dev; 411 retval = -EIO;
396 if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
397 retval = -EIO;
398 usblp->used = 0;
399 file->private_data = NULL;
400 }
401 } 412 }
402out: 413out:
403 mutex_unlock (&usblp_mutex); 414 mutex_unlock (&usblp_mutex);
@@ -460,6 +471,11 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
460 goto done; 471 goto done;
461 } 472 }
462 473
474 if (usblp->sleeping) {
475 retval = -ENODEV;
476 goto done;
477 }
478
463 dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), 479 dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd),
464 _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) ); 480 _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) );
465 481
@@ -658,6 +674,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
658 return -ENODEV; 674 return -ENODEV;
659 } 675 }
660 676
677 if (usblp->sleeping) {
678 up (&usblp->sem);
679 return writecount ? writecount : -ENODEV;
680 }
681
661 if (usblp->writeurb->status != 0) { 682 if (usblp->writeurb->status != 0) {
662 if (usblp->quirks & USBLP_QUIRK_BIDIR) { 683 if (usblp->quirks & USBLP_QUIRK_BIDIR) {
663 if (!usblp->wcomplete) 684 if (!usblp->wcomplete)
@@ -749,6 +770,11 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
749 goto done; 770 goto done;
750 } 771 }
751 772
773 if (usblp->sleeping) {
774 count = -ENODEV;
775 goto done;
776 }
777
752 if (usblp->readurb->status) { 778 if (usblp->readurb->status) {
753 err("usblp%d: error %d reading from printer", 779 err("usblp%d: error %d reading from printer",
754 usblp->minor, usblp->readurb->status); 780 usblp->minor, usblp->readurb->status);
@@ -1167,6 +1193,41 @@ static void usblp_disconnect(struct usb_interface *intf)
1167 mutex_unlock (&usblp_mutex); 1193 mutex_unlock (&usblp_mutex);
1168} 1194}
1169 1195
1196static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
1197{
1198 struct usblp *usblp = usb_get_intfdata (intf);
1199
1200 /* this races against normal access and open */
1201 mutex_lock (&usblp_mutex);
1202 down (&usblp->sem);
1203 /* we take no more IO */
1204 usblp->sleeping = 1;
1205 /* we wait for anything printing */
1206 wait_event (usblp->wait, usblp->wcomplete || !usblp->present);
1207 usblp_unlink_urbs(usblp);
1208 up (&usblp->sem);
1209 mutex_unlock (&usblp_mutex);
1210
1211 return 0;
1212}
1213
1214static int usblp_resume (struct usb_interface *intf)
1215{
1216 struct usblp *usblp = usb_get_intfdata (intf);
1217 int r;
1218
1219 mutex_lock (&usblp_mutex);
1220 down (&usblp->sem);
1221
1222 usblp->sleeping = 0;
1223 r = handle_bidir (usblp);
1224
1225 up (&usblp->sem);
1226 mutex_unlock (&usblp_mutex);
1227
1228 return r;
1229}
1230
1170static struct usb_device_id usblp_ids [] = { 1231static struct usb_device_id usblp_ids [] = {
1171 { USB_DEVICE_INFO(7, 1, 1) }, 1232 { USB_DEVICE_INFO(7, 1, 1) },
1172 { USB_DEVICE_INFO(7, 1, 2) }, 1233 { USB_DEVICE_INFO(7, 1, 2) },
@@ -1183,6 +1244,8 @@ static struct usb_driver usblp_driver = {
1183 .name = "usblp", 1244 .name = "usblp",
1184 .probe = usblp_probe, 1245 .probe = usblp_probe,
1185 .disconnect = usblp_disconnect, 1246 .disconnect = usblp_disconnect,
1247 .suspend = usblp_suspend,
1248 .resume = usblp_resume,
1186 .id_table = usblp_ids, 1249 .id_table = usblp_ids,
1187}; 1250};
1188 1251