diff options
Diffstat (limited to 'drivers/usb/class')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 30 | ||||
-rw-r--r-- | drivers/usb/class/usblp.c | 143 |
2 files changed, 104 insertions, 69 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index cd51520c7e7..f51e22490ed 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -257,9 +257,10 @@ static void acm_ctrl_irq(struct urb *urb) | |||
257 | struct usb_cdc_notification *dr = urb->transfer_buffer; | 257 | struct usb_cdc_notification *dr = urb->transfer_buffer; |
258 | unsigned char *data; | 258 | unsigned char *data; |
259 | int newctrl; | 259 | int newctrl; |
260 | int status; | 260 | int retval; |
261 | int status = urb->status; | ||
261 | 262 | ||
262 | switch (urb->status) { | 263 | switch (status) { |
263 | case 0: | 264 | case 0: |
264 | /* success */ | 265 | /* success */ |
265 | break; | 266 | break; |
@@ -267,10 +268,10 @@ static void acm_ctrl_irq(struct urb *urb) | |||
267 | case -ENOENT: | 268 | case -ENOENT: |
268 | case -ESHUTDOWN: | 269 | case -ESHUTDOWN: |
269 | /* this urb is terminated, clean up */ | 270 | /* this urb is terminated, clean up */ |
270 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 271 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, status); |
271 | return; | 272 | return; |
272 | default: | 273 | default: |
273 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 274 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, status); |
274 | goto exit; | 275 | goto exit; |
275 | } | 276 | } |
276 | 277 | ||
@@ -311,10 +312,10 @@ static void acm_ctrl_irq(struct urb *urb) | |||
311 | break; | 312 | break; |
312 | } | 313 | } |
313 | exit: | 314 | exit: |
314 | status = usb_submit_urb (urb, GFP_ATOMIC); | 315 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
315 | if (status) | 316 | if (retval) |
316 | err ("%s - usb_submit_urb failed with result %d", | 317 | err ("%s - usb_submit_urb failed with result %d", |
317 | __FUNCTION__, status); | 318 | __FUNCTION__, retval); |
318 | } | 319 | } |
319 | 320 | ||
320 | /* data interface returns incoming bytes, or we got unthrottled */ | 321 | /* data interface returns incoming bytes, or we got unthrottled */ |
@@ -324,7 +325,8 @@ static void acm_read_bulk(struct urb *urb) | |||
324 | struct acm_ru *rcv = urb->context; | 325 | struct acm_ru *rcv = urb->context; |
325 | struct acm *acm = rcv->instance; | 326 | struct acm *acm = rcv->instance; |
326 | int status = urb->status; | 327 | int status = urb->status; |
327 | dbg("Entering acm_read_bulk with status %d", urb->status); | 328 | |
329 | dbg("Entering acm_read_bulk with status %d", status); | ||
328 | 330 | ||
329 | if (!ACM_READY(acm)) | 331 | if (!ACM_READY(acm)) |
330 | return; | 332 | return; |
@@ -919,6 +921,10 @@ skip_normal_probe: | |||
919 | return -EINVAL; | 921 | return -EINVAL; |
920 | } | 922 | } |
921 | } | 923 | } |
924 | |||
925 | /* Accept probe requests only for the control interface */ | ||
926 | if (intf != control_interface) | ||
927 | return -ENODEV; | ||
922 | 928 | ||
923 | if (usb_interface_claimed(data_interface)) { /* valid in this context */ | 929 | if (usb_interface_claimed(data_interface)) { /* valid in this context */ |
924 | dev_dbg(&intf->dev,"The data interface isn't available"); | 930 | dev_dbg(&intf->dev,"The data interface isn't available"); |
@@ -1107,10 +1113,12 @@ static void acm_disconnect(struct usb_interface *intf) | |||
1107 | return; | 1113 | return; |
1108 | } | 1114 | } |
1109 | if (acm->country_codes){ | 1115 | if (acm->country_codes){ |
1110 | device_remove_file(&intf->dev, &dev_attr_wCountryCodes); | 1116 | device_remove_file(&acm->control->dev, |
1111 | device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate); | 1117 | &dev_attr_wCountryCodes); |
1118 | device_remove_file(&acm->control->dev, | ||
1119 | &dev_attr_iCountryCodeRelDate); | ||
1112 | } | 1120 | } |
1113 | device_remove_file(&intf->dev, &dev_attr_bmCapabilities); | 1121 | device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); |
1114 | acm->dev = NULL; | 1122 | acm->dev = NULL; |
1115 | usb_set_intfdata(acm->control, NULL); | 1123 | usb_set_intfdata(acm->control, NULL); |
1116 | usb_set_intfdata(acm->data, NULL); | 1124 | usb_set_intfdata(acm->data, NULL); |
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 9a1478972bf..ad632f2d6f9 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -28,6 +28,7 @@ | |||
28 | * v0.12 - add hpoj.sourceforge.net ioctls (David Paschal) | 28 | * v0.12 - add hpoj.sourceforge.net ioctls (David Paschal) |
29 | * v0.13 - alloc space for statusbuf (<status> not on stack); | 29 | * v0.13 - alloc space for statusbuf (<status> not on stack); |
30 | * use usb_buffer_alloc() for read buf & write buf; | 30 | * use usb_buffer_alloc() for read buf & write buf; |
31 | * none - Maintained in Linux kernel after v0.13 | ||
31 | */ | 32 | */ |
32 | 33 | ||
33 | /* | 34 | /* |
@@ -69,7 +70,6 @@ | |||
69 | #define USBLP_DEVICE_ID_SIZE 1024 | 70 | #define USBLP_DEVICE_ID_SIZE 1024 |
70 | 71 | ||
71 | /* ioctls: */ | 72 | /* ioctls: */ |
72 | #define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */ | ||
73 | #define IOCNR_GET_DEVICE_ID 1 | 73 | #define IOCNR_GET_DEVICE_ID 1 |
74 | #define IOCNR_GET_PROTOCOLS 2 | 74 | #define IOCNR_GET_PROTOCOLS 2 |
75 | #define IOCNR_SET_PROTOCOL 3 | 75 | #define IOCNR_SET_PROTOCOL 3 |
@@ -115,7 +115,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H | |||
115 | #define USBLP_MINORS 16 | 115 | #define USBLP_MINORS 16 |
116 | #define USBLP_MINOR_BASE 0 | 116 | #define USBLP_MINOR_BASE 0 |
117 | 117 | ||
118 | #define USBLP_WRITE_TIMEOUT (5000) /* 5 seconds */ | 118 | #define USBLP_CTL_TIMEOUT 5000 /* 5 seconds */ |
119 | 119 | ||
120 | #define USBLP_FIRST_PROTOCOL 1 | 120 | #define USBLP_FIRST_PROTOCOL 1 |
121 | #define USBLP_LAST_PROTOCOL 3 | 121 | #define USBLP_LAST_PROTOCOL 3 |
@@ -159,10 +159,12 @@ struct usblp { | |||
159 | int wstatus; /* bytes written or error */ | 159 | int wstatus; /* bytes written or error */ |
160 | int rstatus; /* bytes ready or error */ | 160 | int rstatus; /* bytes ready or error */ |
161 | unsigned int quirks; /* quirks flags */ | 161 | unsigned int quirks; /* quirks flags */ |
162 | unsigned int flags; /* mode flags */ | ||
162 | unsigned char used; /* True if open */ | 163 | unsigned char used; /* True if open */ |
163 | unsigned char present; /* True if not disconnected */ | 164 | unsigned char present; /* True if not disconnected */ |
164 | unsigned char bidir; /* interface is bidirectional */ | 165 | unsigned char bidir; /* interface is bidirectional */ |
165 | unsigned char sleeping; /* interface is suspended */ | 166 | unsigned char sleeping; /* interface is suspended */ |
167 | unsigned char no_paper; /* Paper Out happened */ | ||
166 | unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ | 168 | unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ |
167 | /* first 2 bytes are (big-endian) length */ | 169 | /* first 2 bytes are (big-endian) length */ |
168 | }; | 170 | }; |
@@ -259,7 +261,7 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i | |||
259 | 261 | ||
260 | retval = usb_control_msg(usblp->dev, | 262 | retval = usb_control_msg(usblp->dev, |
261 | dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), | 263 | dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), |
262 | request, type | dir | recip, value, index, buf, len, USBLP_WRITE_TIMEOUT); | 264 | request, type | dir | recip, value, index, buf, len, USBLP_CTL_TIMEOUT); |
263 | dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d", | 265 | dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d", |
264 | request, !!dir, recip, value, index, len, retval); | 266 | request, !!dir, recip, value, index, len, retval); |
265 | return retval < 0 ? retval : 0; | 267 | return retval < 0 ? retval : 0; |
@@ -289,16 +291,17 @@ static int proto_bias = -1; | |||
289 | static void usblp_bulk_read(struct urb *urb) | 291 | static void usblp_bulk_read(struct urb *urb) |
290 | { | 292 | { |
291 | struct usblp *usblp = urb->context; | 293 | struct usblp *usblp = urb->context; |
294 | int status = urb->status; | ||
292 | 295 | ||
293 | if (usblp->present && usblp->used) { | 296 | if (usblp->present && usblp->used) { |
294 | if (urb->status) | 297 | if (status) |
295 | printk(KERN_WARNING "usblp%d: " | 298 | printk(KERN_WARNING "usblp%d: " |
296 | "nonzero read bulk status received: %d\n", | 299 | "nonzero read bulk status received: %d\n", |
297 | usblp->minor, urb->status); | 300 | usblp->minor, status); |
298 | } | 301 | } |
299 | spin_lock(&usblp->lock); | 302 | spin_lock(&usblp->lock); |
300 | if (urb->status < 0) | 303 | if (status < 0) |
301 | usblp->rstatus = urb->status; | 304 | usblp->rstatus = status; |
302 | else | 305 | else |
303 | usblp->rstatus = urb->actual_length; | 306 | usblp->rstatus = urb->actual_length; |
304 | usblp->rcomplete = 1; | 307 | usblp->rcomplete = 1; |
@@ -311,25 +314,24 @@ static void usblp_bulk_read(struct urb *urb) | |||
311 | static void usblp_bulk_write(struct urb *urb) | 314 | static void usblp_bulk_write(struct urb *urb) |
312 | { | 315 | { |
313 | struct usblp *usblp = urb->context; | 316 | struct usblp *usblp = urb->context; |
317 | int status = urb->status; | ||
314 | 318 | ||
315 | if (usblp->present && usblp->used) { | 319 | if (usblp->present && usblp->used) { |
316 | if (urb->status) | 320 | if (status) |
317 | printk(KERN_WARNING "usblp%d: " | 321 | printk(KERN_WARNING "usblp%d: " |
318 | "nonzero write bulk status received: %d\n", | 322 | "nonzero write bulk status received: %d\n", |
319 | usblp->minor, urb->status); | 323 | usblp->minor, status); |
320 | } | 324 | } |
321 | spin_lock(&usblp->lock); | 325 | spin_lock(&usblp->lock); |
322 | if (urb->status < 0) | 326 | if (status < 0) |
323 | usblp->wstatus = urb->status; | 327 | usblp->wstatus = status; |
324 | else | 328 | else |
325 | usblp->wstatus = urb->actual_length; | 329 | usblp->wstatus = urb->actual_length; |
330 | usblp->no_paper = 0; | ||
326 | usblp->wcomplete = 1; | 331 | usblp->wcomplete = 1; |
327 | wake_up(&usblp->wwait); | 332 | wake_up(&usblp->wwait); |
328 | spin_unlock(&usblp->lock); | 333 | spin_unlock(&usblp->lock); |
329 | 334 | ||
330 | /* XXX Use usb_setup_bulk_urb when available. Talk to Marcel. */ | ||
331 | kfree(urb->transfer_buffer); | ||
332 | urb->transfer_buffer = NULL; /* Not refcounted, so to be safe... */ | ||
333 | usb_free_urb(urb); | 335 | usb_free_urb(urb); |
334 | } | 336 | } |
335 | 337 | ||
@@ -344,16 +346,17 @@ static int usblp_check_status(struct usblp *usblp, int err) | |||
344 | unsigned char status, newerr = 0; | 346 | unsigned char status, newerr = 0; |
345 | int error; | 347 | int error; |
346 | 348 | ||
347 | error = usblp_read_status (usblp, usblp->statusbuf); | 349 | mutex_lock(&usblp->mut); |
348 | if (error < 0) { | 350 | if ((error = usblp_read_status(usblp, usblp->statusbuf)) < 0) { |
351 | mutex_unlock(&usblp->mut); | ||
349 | if (printk_ratelimit()) | 352 | if (printk_ratelimit()) |
350 | printk(KERN_ERR | 353 | printk(KERN_ERR |
351 | "usblp%d: error %d reading printer status\n", | 354 | "usblp%d: error %d reading printer status\n", |
352 | usblp->minor, error); | 355 | usblp->minor, error); |
353 | return 0; | 356 | return 0; |
354 | } | 357 | } |
355 | |||
356 | status = *usblp->statusbuf; | 358 | status = *usblp->statusbuf; |
359 | mutex_unlock(&usblp->mut); | ||
357 | 360 | ||
358 | if (~status & LP_PERRORP) | 361 | if (~status & LP_PERRORP) |
359 | newerr = 3; | 362 | newerr = 3; |
@@ -409,18 +412,10 @@ static int usblp_open(struct inode *inode, struct file *file) | |||
409 | goto out; | 412 | goto out; |
410 | 413 | ||
411 | /* | 414 | /* |
412 | * TODO: need to implement LP_ABORTOPEN + O_NONBLOCK as in drivers/char/lp.c ??? | 415 | * We do not implement LP_ABORTOPEN/LPABORTOPEN for two reasons: |
413 | * This is #if 0-ed because we *don't* want to fail an open | 416 | * - We do not want persistent state which close(2) does not clear |
414 | * just because the printer is off-line. | 417 | * - It is not used anyway, according to CUPS people |
415 | */ | 418 | */ |
416 | #if 0 | ||
417 | if ((retval = usblp_check_status(usblp, 0))) { | ||
418 | retval = retval > 1 ? -EIO : -ENOSPC; | ||
419 | goto out; | ||
420 | } | ||
421 | #else | ||
422 | retval = 0; | ||
423 | #endif | ||
424 | 419 | ||
425 | retval = usb_autopm_get_interface(intf); | 420 | retval = usb_autopm_get_interface(intf); |
426 | if (retval < 0) | 421 | if (retval < 0) |
@@ -461,6 +456,8 @@ static int usblp_release(struct inode *inode, struct file *file) | |||
461 | { | 456 | { |
462 | struct usblp *usblp = file->private_data; | 457 | struct usblp *usblp = file->private_data; |
463 | 458 | ||
459 | usblp->flags &= ~LP_ABORT; | ||
460 | |||
464 | mutex_lock (&usblp_mutex); | 461 | mutex_lock (&usblp_mutex); |
465 | usblp->used = 0; | 462 | usblp->used = 0; |
466 | if (usblp->present) { | 463 | if (usblp->present) { |
@@ -483,8 +480,8 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait | |||
483 | poll_wait(file, &usblp->rwait, wait); | 480 | poll_wait(file, &usblp->rwait, wait); |
484 | poll_wait(file, &usblp->wwait, wait); | 481 | poll_wait(file, &usblp->wwait, wait); |
485 | spin_lock_irqsave(&usblp->lock, flags); | 482 | spin_lock_irqsave(&usblp->lock, flags); |
486 | ret = ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN | POLLRDNORM) | 483 | ret = ((usblp->bidir && usblp->rcomplete) ? POLLIN | POLLRDNORM : 0) | |
487 | | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM); | 484 | ((usblp->no_paper || usblp->wcomplete) ? POLLOUT | POLLWRNORM : 0); |
488 | spin_unlock_irqrestore(&usblp->lock, flags); | 485 | spin_unlock_irqrestore(&usblp->lock, flags); |
489 | return ret; | 486 | return ret; |
490 | } | 487 | } |
@@ -673,6 +670,13 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
673 | retval = -EFAULT; | 670 | retval = -EFAULT; |
674 | break; | 671 | break; |
675 | 672 | ||
673 | case LPABORT: | ||
674 | if (arg) | ||
675 | usblp->flags |= LP_ABORT; | ||
676 | else | ||
677 | usblp->flags &= ~LP_ABORT; | ||
678 | break; | ||
679 | |||
676 | default: | 680 | default: |
677 | retval = -ENOTTY; | 681 | retval = -ENOTTY; |
678 | } | 682 | } |
@@ -682,10 +686,30 @@ done: | |||
682 | return retval; | 686 | return retval; |
683 | } | 687 | } |
684 | 688 | ||
689 | static struct urb *usblp_new_writeurb(struct usblp *usblp, int transfer_length) | ||
690 | { | ||
691 | struct urb *urb; | ||
692 | char *writebuf; | ||
693 | |||
694 | if ((writebuf = kmalloc(transfer_length, GFP_KERNEL)) == NULL) | ||
695 | return NULL; | ||
696 | if ((urb = usb_alloc_urb(0, GFP_KERNEL)) == NULL) { | ||
697 | kfree(writebuf); | ||
698 | return NULL; | ||
699 | } | ||
700 | |||
701 | usb_fill_bulk_urb(urb, usblp->dev, | ||
702 | usb_sndbulkpipe(usblp->dev, | ||
703 | usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress), | ||
704 | writebuf, transfer_length, usblp_bulk_write, usblp); | ||
705 | urb->transfer_flags |= URB_FREE_BUFFER; | ||
706 | |||
707 | return urb; | ||
708 | } | ||
709 | |||
685 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 710 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
686 | { | 711 | { |
687 | struct usblp *usblp = file->private_data; | 712 | struct usblp *usblp = file->private_data; |
688 | char *writebuf; | ||
689 | struct urb *writeurb; | 713 | struct urb *writeurb; |
690 | int rv; | 714 | int rv; |
691 | int transfer_length; | 715 | int transfer_length; |
@@ -706,17 +730,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
706 | transfer_length = USBLP_BUF_SIZE; | 730 | transfer_length = USBLP_BUF_SIZE; |
707 | 731 | ||
708 | rv = -ENOMEM; | 732 | rv = -ENOMEM; |
709 | if ((writebuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL)) == NULL) | 733 | if ((writeurb = usblp_new_writeurb(usblp, transfer_length)) == NULL) |
710 | goto raise_buf; | ||
711 | if ((writeurb = usb_alloc_urb(0, GFP_KERNEL)) == NULL) | ||
712 | goto raise_urb; | 734 | goto raise_urb; |
713 | usb_fill_bulk_urb(writeurb, usblp->dev, | ||
714 | usb_sndbulkpipe(usblp->dev, | ||
715 | usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress), | ||
716 | writebuf, transfer_length, usblp_bulk_write, usblp); | ||
717 | usb_anchor_urb(writeurb, &usblp->urbs); | 735 | usb_anchor_urb(writeurb, &usblp->urbs); |
718 | 736 | ||
719 | if (copy_from_user(writebuf, | 737 | if (copy_from_user(writeurb->transfer_buffer, |
720 | buffer + writecount, transfer_length)) { | 738 | buffer + writecount, transfer_length)) { |
721 | rv = -EFAULT; | 739 | rv = -EFAULT; |
722 | goto raise_badaddr; | 740 | goto raise_badaddr; |
@@ -728,6 +746,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
728 | if ((rv = usb_submit_urb(writeurb, GFP_KERNEL)) < 0) { | 746 | if ((rv = usb_submit_urb(writeurb, GFP_KERNEL)) < 0) { |
729 | usblp->wstatus = 0; | 747 | usblp->wstatus = 0; |
730 | spin_lock_irq(&usblp->lock); | 748 | spin_lock_irq(&usblp->lock); |
749 | usblp->no_paper = 0; | ||
731 | usblp->wcomplete = 1; | 750 | usblp->wcomplete = 1; |
732 | wake_up(&usblp->wwait); | 751 | wake_up(&usblp->wwait); |
733 | spin_unlock_irq(&usblp->lock); | 752 | spin_unlock_irq(&usblp->lock); |
@@ -741,15 +760,21 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
741 | */ | 760 | */ |
742 | rv = usblp_wwait(usblp, !!(file->f_flags&O_NONBLOCK)); | 761 | rv = usblp_wwait(usblp, !!(file->f_flags&O_NONBLOCK)); |
743 | if (rv < 0) { | 762 | if (rv < 0) { |
744 | /* | 763 | if (rv == -EAGAIN) { |
745 | * If interrupted, we simply leave the URB to dangle, | 764 | /* Presume that it's going to complete well. */ |
746 | * so the ->release will call usb_kill_urb(). | 765 | writecount += transfer_length; |
747 | */ | 766 | } |
767 | if (rv == -ENOSPC) { | ||
768 | spin_lock_irq(&usblp->lock); | ||
769 | usblp->no_paper = 1; /* Mark for poll(2) */ | ||
770 | spin_unlock_irq(&usblp->lock); | ||
771 | writecount += transfer_length; | ||
772 | } | ||
773 | /* Leave URB dangling, to be cleaned on close. */ | ||
748 | goto collect_error; | 774 | goto collect_error; |
749 | } | 775 | } |
750 | 776 | ||
751 | if (usblp->wstatus < 0) { | 777 | if (usblp->wstatus < 0) { |
752 | usblp_check_status(usblp, 0); | ||
753 | rv = -EIO; | 778 | rv = -EIO; |
754 | goto collect_error; | 779 | goto collect_error; |
755 | } | 780 | } |
@@ -768,8 +793,6 @@ raise_badaddr: | |||
768 | usb_unanchor_urb(writeurb); | 793 | usb_unanchor_urb(writeurb); |
769 | usb_free_urb(writeurb); | 794 | usb_free_urb(writeurb); |
770 | raise_urb: | 795 | raise_urb: |
771 | kfree(writebuf); | ||
772 | raise_buf: | ||
773 | raise_wait: | 796 | raise_wait: |
774 | collect_error: /* Out of raise sequence */ | 797 | collect_error: /* Out of raise sequence */ |
775 | mutex_unlock(&usblp->wmut); | 798 | mutex_unlock(&usblp->wmut); |
@@ -835,32 +858,36 @@ done: | |||
835 | * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use | 858 | * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use |
836 | * select(2) or poll(2) to wait for the buffer to drain before closing. | 859 | * select(2) or poll(2) to wait for the buffer to drain before closing. |
837 | * Alternatively, set blocking mode with fcntl and issue a zero-size write. | 860 | * Alternatively, set blocking mode with fcntl and issue a zero-size write. |
838 | * | ||
839 | * Old v0.13 code had a non-functional timeout for wait_event(). Someone forgot | ||
840 | * to check the return code for timeout expiration, so it had no effect. | ||
841 | * Apparently, it was intended to check for error conditons, such as out | ||
842 | * of paper. It is going to return when we settle things with CUPS. XXX | ||
843 | */ | 861 | */ |
844 | static int usblp_wwait(struct usblp *usblp, int nonblock) | 862 | static int usblp_wwait(struct usblp *usblp, int nonblock) |
845 | { | 863 | { |
846 | DECLARE_WAITQUEUE(waita, current); | 864 | DECLARE_WAITQUEUE(waita, current); |
847 | int rc; | 865 | int rc; |
866 | int err = 0; | ||
848 | 867 | ||
849 | add_wait_queue(&usblp->wwait, &waita); | 868 | add_wait_queue(&usblp->wwait, &waita); |
850 | for (;;) { | 869 | for (;;) { |
870 | set_current_state(TASK_INTERRUPTIBLE); | ||
851 | if (mutex_lock_interruptible(&usblp->mut)) { | 871 | if (mutex_lock_interruptible(&usblp->mut)) { |
852 | rc = -EINTR; | 872 | rc = -EINTR; |
853 | break; | 873 | break; |
854 | } | 874 | } |
855 | set_current_state(TASK_INTERRUPTIBLE); | 875 | rc = usblp_wtest(usblp, nonblock); |
856 | if ((rc = usblp_wtest(usblp, nonblock)) < 0) { | ||
857 | mutex_unlock(&usblp->mut); | ||
858 | break; | ||
859 | } | ||
860 | mutex_unlock(&usblp->mut); | 876 | mutex_unlock(&usblp->mut); |
861 | if (rc == 0) | 877 | if (rc <= 0) |
862 | break; | 878 | break; |
863 | schedule(); | 879 | |
880 | if (usblp->flags & LP_ABORT) { | ||
881 | if (schedule_timeout(msecs_to_jiffies(5000)) == 0) { | ||
882 | err = usblp_check_status(usblp, err); | ||
883 | if (err == 1) { /* Paper out */ | ||
884 | rc = -ENOSPC; | ||
885 | break; | ||
886 | } | ||
887 | } | ||
888 | } else { | ||
889 | schedule(); | ||
890 | } | ||
864 | } | 891 | } |
865 | set_current_state(TASK_RUNNING); | 892 | set_current_state(TASK_RUNNING); |
866 | remove_wait_queue(&usblp->wwait, &waita); | 893 | remove_wait_queue(&usblp->wwait, &waita); |