diff options
Diffstat (limited to 'drivers/usb/class/usblp.c')
-rw-r--r-- | drivers/usb/class/usblp.c | 63 |
1 files changed, 31 insertions, 32 deletions
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 6303970e93c1..63e50a1f1396 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -130,7 +130,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H | |||
130 | 130 | ||
131 | struct usblp { | 131 | struct usblp { |
132 | struct usb_device *dev; /* USB device */ | 132 | struct usb_device *dev; /* USB device */ |
133 | struct semaphore sem; /* locks this struct, especially "dev" */ | 133 | struct mutex mut; /* locks this struct, especially "dev" */ |
134 | char *writebuf; /* write transfer_buffer */ | 134 | char *writebuf; /* write transfer_buffer */ |
135 | char *readbuf; /* read transfer_buffer */ | 135 | char *readbuf; /* read transfer_buffer */ |
136 | char *statusbuf; /* status transfer_buffer */ | 136 | char *statusbuf; /* status transfer_buffer */ |
@@ -217,6 +217,7 @@ static const struct quirk_printer_struct quirk_printers[] = { | |||
217 | { 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */ | 217 | { 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */ |
218 | { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */ | 218 | { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */ |
219 | { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ | 219 | { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ |
220 | { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */ | ||
220 | { 0, 0 } | 221 | { 0, 0 } |
221 | }; | 222 | }; |
222 | 223 | ||
@@ -397,6 +398,9 @@ static int usblp_open(struct inode *inode, struct file *file) | |||
397 | retval = 0; | 398 | retval = 0; |
398 | #endif | 399 | #endif |
399 | 400 | ||
401 | retval = usb_autopm_get_interface(intf); | ||
402 | if (retval < 0) | ||
403 | goto out; | ||
400 | usblp->used = 1; | 404 | usblp->used = 1; |
401 | file->private_data = usblp; | 405 | file->private_data = usblp; |
402 | 406 | ||
@@ -441,6 +445,7 @@ static int usblp_release(struct inode *inode, struct file *file) | |||
441 | usblp->used = 0; | 445 | usblp->used = 0; |
442 | if (usblp->present) { | 446 | if (usblp->present) { |
443 | usblp_unlink_urbs(usblp); | 447 | usblp_unlink_urbs(usblp); |
448 | usb_autopm_put_interface(usblp->intf); | ||
444 | } else /* finish cleanup from disconnect */ | 449 | } else /* finish cleanup from disconnect */ |
445 | usblp_cleanup (usblp); | 450 | usblp_cleanup (usblp); |
446 | mutex_unlock (&usblp_mutex); | 451 | mutex_unlock (&usblp_mutex); |
@@ -465,7 +470,7 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
465 | int twoints[2]; | 470 | int twoints[2]; |
466 | int retval = 0; | 471 | int retval = 0; |
467 | 472 | ||
468 | down (&usblp->sem); | 473 | mutex_lock (&usblp->mut); |
469 | if (!usblp->present) { | 474 | if (!usblp->present) { |
470 | retval = -ENODEV; | 475 | retval = -ENODEV; |
471 | goto done; | 476 | goto done; |
@@ -644,14 +649,14 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
644 | } | 649 | } |
645 | 650 | ||
646 | done: | 651 | done: |
647 | up (&usblp->sem); | 652 | mutex_unlock (&usblp->mut); |
648 | return retval; | 653 | return retval; |
649 | } | 654 | } |
650 | 655 | ||
651 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 656 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
652 | { | 657 | { |
653 | struct usblp *usblp = file->private_data; | 658 | struct usblp *usblp = file->private_data; |
654 | int timeout, rv, err = 0, transfer_length = 0; | 659 | int timeout, intr, rv, err = 0, transfer_length = 0; |
655 | size_t writecount = 0; | 660 | size_t writecount = 0; |
656 | 661 | ||
657 | while (writecount < count) { | 662 | while (writecount < count) { |
@@ -668,14 +673,16 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
668 | if (rv < 0) | 673 | if (rv < 0) |
669 | return writecount ? writecount : -EINTR; | 674 | return writecount ? writecount : -EINTR; |
670 | } | 675 | } |
671 | down (&usblp->sem); | 676 | intr = mutex_lock_interruptible (&usblp->mut); |
677 | if (intr) | ||
678 | return writecount ? writecount : -EINTR; | ||
672 | if (!usblp->present) { | 679 | if (!usblp->present) { |
673 | up (&usblp->sem); | 680 | mutex_unlock (&usblp->mut); |
674 | return -ENODEV; | 681 | return -ENODEV; |
675 | } | 682 | } |
676 | 683 | ||
677 | if (usblp->sleeping) { | 684 | if (usblp->sleeping) { |
678 | up (&usblp->sem); | 685 | mutex_unlock (&usblp->mut); |
679 | return writecount ? writecount : -ENODEV; | 686 | return writecount ? writecount : -ENODEV; |
680 | } | 687 | } |
681 | 688 | ||
@@ -687,10 +694,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
687 | err = usblp->writeurb->status; | 694 | err = usblp->writeurb->status; |
688 | } else | 695 | } else |
689 | err = usblp_check_status(usblp, err); | 696 | err = usblp_check_status(usblp, err); |
690 | up (&usblp->sem); | 697 | mutex_unlock (&usblp->mut); |
691 | 698 | ||
692 | /* if the fault was due to disconnect, let khubd's | 699 | /* if the fault was due to disconnect, let khubd's |
693 | * call to usblp_disconnect() grab usblp->sem ... | 700 | * call to usblp_disconnect() grab usblp->mut ... |
694 | */ | 701 | */ |
695 | schedule (); | 702 | schedule (); |
696 | continue; | 703 | continue; |
@@ -702,7 +709,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
702 | */ | 709 | */ |
703 | writecount += transfer_length; | 710 | writecount += transfer_length; |
704 | if (writecount == count) { | 711 | if (writecount == count) { |
705 | up(&usblp->sem); | 712 | mutex_unlock(&usblp->mut); |
706 | break; | 713 | break; |
707 | } | 714 | } |
708 | 715 | ||
@@ -714,7 +721,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
714 | 721 | ||
715 | if (copy_from_user(usblp->writeurb->transfer_buffer, | 722 | if (copy_from_user(usblp->writeurb->transfer_buffer, |
716 | buffer + writecount, transfer_length)) { | 723 | buffer + writecount, transfer_length)) { |
717 | up(&usblp->sem); | 724 | mutex_unlock(&usblp->mut); |
718 | return writecount ? writecount : -EFAULT; | 725 | return writecount ? writecount : -EFAULT; |
719 | } | 726 | } |
720 | 727 | ||
@@ -727,10 +734,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
727 | count = -EIO; | 734 | count = -EIO; |
728 | else | 735 | else |
729 | count = writecount ? writecount : -ENOMEM; | 736 | count = writecount ? writecount : -ENOMEM; |
730 | up (&usblp->sem); | 737 | mutex_unlock (&usblp->mut); |
731 | break; | 738 | break; |
732 | } | 739 | } |
733 | up (&usblp->sem); | 740 | mutex_unlock (&usblp->mut); |
734 | } | 741 | } |
735 | 742 | ||
736 | return count; | 743 | return count; |
@@ -739,12 +746,14 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
739 | static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 746 | static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
740 | { | 747 | { |
741 | struct usblp *usblp = file->private_data; | 748 | struct usblp *usblp = file->private_data; |
742 | int rv; | 749 | int rv, intr; |
743 | 750 | ||
744 | if (!usblp->bidir) | 751 | if (!usblp->bidir) |
745 | return -EINVAL; | 752 | return -EINVAL; |
746 | 753 | ||
747 | down (&usblp->sem); | 754 | intr = mutex_lock_interruptible (&usblp->mut); |
755 | if (intr) | ||
756 | return -EINTR; | ||
748 | if (!usblp->present) { | 757 | if (!usblp->present) { |
749 | count = -ENODEV; | 758 | count = -ENODEV; |
750 | goto done; | 759 | goto done; |
@@ -757,9 +766,9 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, | |||
757 | count = -EAGAIN; | 766 | count = -EAGAIN; |
758 | goto done; | 767 | goto done; |
759 | } | 768 | } |
760 | up(&usblp->sem); | 769 | mutex_unlock(&usblp->mut); |
761 | rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present); | 770 | rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present); |
762 | down(&usblp->sem); | 771 | mutex_lock(&usblp->mut); |
763 | if (rv < 0) { | 772 | if (rv < 0) { |
764 | count = -EINTR; | 773 | count = -EINTR; |
765 | goto done; | 774 | goto done; |
@@ -807,7 +816,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, | |||
807 | } | 816 | } |
808 | 817 | ||
809 | done: | 818 | done: |
810 | up (&usblp->sem); | 819 | mutex_unlock (&usblp->mut); |
811 | return count; | 820 | return count; |
812 | } | 821 | } |
813 | 822 | ||
@@ -886,7 +895,7 @@ static int usblp_probe(struct usb_interface *intf, | |||
886 | goto abort; | 895 | goto abort; |
887 | } | 896 | } |
888 | usblp->dev = dev; | 897 | usblp->dev = dev; |
889 | init_MUTEX (&usblp->sem); | 898 | mutex_init (&usblp->mut); |
890 | init_waitqueue_head(&usblp->wait); | 899 | init_waitqueue_head(&usblp->wait); |
891 | usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; | 900 | usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; |
892 | usblp->intf = intf; | 901 | usblp->intf = intf; |
@@ -1178,7 +1187,7 @@ static void usblp_disconnect(struct usb_interface *intf) | |||
1178 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); | 1187 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); |
1179 | 1188 | ||
1180 | mutex_lock (&usblp_mutex); | 1189 | mutex_lock (&usblp_mutex); |
1181 | down (&usblp->sem); | 1190 | mutex_lock (&usblp->mut); |
1182 | usblp->present = 0; | 1191 | usblp->present = 0; |
1183 | usb_set_intfdata (intf, NULL); | 1192 | usb_set_intfdata (intf, NULL); |
1184 | 1193 | ||
@@ -1187,7 +1196,7 @@ static void usblp_disconnect(struct usb_interface *intf) | |||
1187 | usblp->writebuf, usblp->writeurb->transfer_dma); | 1196 | usblp->writebuf, usblp->writeurb->transfer_dma); |
1188 | usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, | 1197 | usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, |
1189 | usblp->readbuf, usblp->readurb->transfer_dma); | 1198 | usblp->readbuf, usblp->readurb->transfer_dma); |
1190 | up (&usblp->sem); | 1199 | mutex_unlock (&usblp->mut); |
1191 | 1200 | ||
1192 | if (!usblp->used) | 1201 | if (!usblp->used) |
1193 | usblp_cleanup (usblp); | 1202 | usblp_cleanup (usblp); |
@@ -1198,14 +1207,9 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message) | |||
1198 | { | 1207 | { |
1199 | struct usblp *usblp = usb_get_intfdata (intf); | 1208 | struct usblp *usblp = usb_get_intfdata (intf); |
1200 | 1209 | ||
1201 | /* this races against normal access and open */ | ||
1202 | mutex_lock (&usblp_mutex); | ||
1203 | down (&usblp->sem); | ||
1204 | /* we take no more IO */ | 1210 | /* we take no more IO */ |
1205 | usblp->sleeping = 1; | 1211 | usblp->sleeping = 1; |
1206 | usblp_unlink_urbs(usblp); | 1212 | usblp_unlink_urbs(usblp); |
1207 | up (&usblp->sem); | ||
1208 | mutex_unlock (&usblp_mutex); | ||
1209 | 1213 | ||
1210 | return 0; | 1214 | return 0; |
1211 | } | 1215 | } |
@@ -1215,15 +1219,9 @@ static int usblp_resume (struct usb_interface *intf) | |||
1215 | struct usblp *usblp = usb_get_intfdata (intf); | 1219 | struct usblp *usblp = usb_get_intfdata (intf); |
1216 | int r; | 1220 | int r; |
1217 | 1221 | ||
1218 | mutex_lock (&usblp_mutex); | ||
1219 | down (&usblp->sem); | ||
1220 | |||
1221 | usblp->sleeping = 0; | 1222 | usblp->sleeping = 0; |
1222 | r = handle_bidir (usblp); | 1223 | r = handle_bidir (usblp); |
1223 | 1224 | ||
1224 | up (&usblp->sem); | ||
1225 | mutex_unlock (&usblp_mutex); | ||
1226 | |||
1227 | return r; | 1225 | return r; |
1228 | } | 1226 | } |
1229 | 1227 | ||
@@ -1246,6 +1244,7 @@ static struct usb_driver usblp_driver = { | |||
1246 | .suspend = usblp_suspend, | 1244 | .suspend = usblp_suspend, |
1247 | .resume = usblp_resume, | 1245 | .resume = usblp_resume, |
1248 | .id_table = usblp_ids, | 1246 | .id_table = usblp_ids, |
1247 | .supports_autosuspend = 1, | ||
1249 | }; | 1248 | }; |
1250 | 1249 | ||
1251 | static int __init usblp_init(void) | 1250 | static int __init usblp_init(void) |