.. | .. |
---|
44 | 44 | |
---|
45 | 45 | #include "usb.h" |
---|
46 | 46 | |
---|
| 47 | +#ifdef CONFIG_PM |
---|
| 48 | +#define MAYBE_CAP_SUSPEND USBDEVFS_CAP_SUSPEND |
---|
| 49 | +#else |
---|
| 50 | +#define MAYBE_CAP_SUSPEND 0 |
---|
| 51 | +#endif |
---|
| 52 | + |
---|
47 | 53 | #define USB_MAXBUS 64 |
---|
48 | 54 | #define USB_DEVICE_MAX (USB_MAXBUS * 128) |
---|
49 | 55 | #define USB_SG_SIZE 16384 /* split-size for large txs */ |
---|
50 | 56 | |
---|
51 | | -/* Mutual exclusion for removal, open, and release */ |
---|
52 | | -DEFINE_MUTEX(usbfs_mutex); |
---|
| 57 | +/* Mutual exclusion for ps->list in resume vs. release and remove */ |
---|
| 58 | +static DEFINE_MUTEX(usbfs_mutex); |
---|
53 | 59 | |
---|
54 | 60 | struct usb_dev_state { |
---|
55 | 61 | struct list_head list; /* state list */ |
---|
.. | .. |
---|
60 | 66 | struct list_head async_completed; |
---|
61 | 67 | struct list_head memory_list; |
---|
62 | 68 | wait_queue_head_t wait; /* wake up if a request completed */ |
---|
| 69 | + wait_queue_head_t wait_for_resume; /* wake up upon runtime resume */ |
---|
63 | 70 | unsigned int discsignr; |
---|
64 | 71 | struct pid *disc_pid; |
---|
65 | 72 | const struct cred *cred; |
---|
66 | | - void __user *disccontext; |
---|
| 73 | + sigval_t disccontext; |
---|
67 | 74 | unsigned long ifclaimed; |
---|
68 | 75 | u32 disabled_bulk_eps; |
---|
69 | | - bool privileges_dropped; |
---|
70 | 76 | unsigned long interface_allowed_mask; |
---|
| 77 | + int not_yet_resumed; |
---|
| 78 | + bool suspend_allowed; |
---|
| 79 | + bool privileges_dropped; |
---|
71 | 80 | }; |
---|
72 | 81 | |
---|
73 | 82 | struct usb_memory { |
---|
.. | .. |
---|
90 | 99 | unsigned int ifnum; |
---|
91 | 100 | void __user *userbuffer; |
---|
92 | 101 | void __user *userurb; |
---|
| 102 | + sigval_t userurb_sigval; |
---|
93 | 103 | struct urb *urb; |
---|
94 | 104 | struct usb_memory *usbm; |
---|
95 | 105 | unsigned int mem_usage; |
---|
.. | .. |
---|
207 | 217 | { |
---|
208 | 218 | struct usb_memory *usbm = NULL; |
---|
209 | 219 | struct usb_dev_state *ps = file->private_data; |
---|
| 220 | + struct usb_hcd *hcd = bus_to_hcd(ps->dev->bus); |
---|
210 | 221 | size_t size = vma->vm_end - vma->vm_start; |
---|
211 | 222 | void *mem; |
---|
212 | 223 | unsigned long flags; |
---|
.. | .. |
---|
240 | 251 | usbm->vma_use_count = 1; |
---|
241 | 252 | INIT_LIST_HEAD(&usbm->memlist); |
---|
242 | 253 | |
---|
243 | | - if (remap_pfn_range(vma, vma->vm_start, |
---|
244 | | - virt_to_phys(usbm->mem) >> PAGE_SHIFT, |
---|
245 | | - size, vma->vm_page_prot) < 0) { |
---|
246 | | - dec_usb_memory_use_count(usbm, &usbm->vma_use_count); |
---|
247 | | - return -EAGAIN; |
---|
| 254 | + if (hcd->localmem_pool || !hcd_uses_dma(hcd)) { |
---|
| 255 | + if (remap_pfn_range(vma, vma->vm_start, |
---|
| 256 | + virt_to_phys(usbm->mem) >> PAGE_SHIFT, |
---|
| 257 | + size, vma->vm_page_prot) < 0) { |
---|
| 258 | + dec_usb_memory_use_count(usbm, &usbm->vma_use_count); |
---|
| 259 | + return -EAGAIN; |
---|
| 260 | + } |
---|
| 261 | + } else { |
---|
| 262 | + if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle, |
---|
| 263 | + size)) { |
---|
| 264 | + dec_usb_memory_use_count(usbm, &usbm->vma_use_count); |
---|
| 265 | + return -EAGAIN; |
---|
| 266 | + } |
---|
248 | 267 | } |
---|
249 | 268 | |
---|
250 | 269 | vma->vm_flags |= VM_IO; |
---|
.. | .. |
---|
564 | 583 | |
---|
565 | 584 | /* Now carefully unlink all the marked pending URBs */ |
---|
566 | 585 | rescan: |
---|
567 | | - list_for_each_entry(as, &ps->async_pending, asynclist) { |
---|
| 586 | + list_for_each_entry_reverse(as, &ps->async_pending, asynclist) { |
---|
568 | 587 | if (as->bulk_status == AS_UNLINK) { |
---|
569 | 588 | as->bulk_status = 0; /* Only once */ |
---|
570 | 589 | urb = as->urb; |
---|
.. | .. |
---|
582 | 601 | { |
---|
583 | 602 | struct async *as = urb->context; |
---|
584 | 603 | struct usb_dev_state *ps = as->ps; |
---|
585 | | - struct siginfo sinfo; |
---|
586 | 604 | struct pid *pid = NULL; |
---|
587 | 605 | const struct cred *cred = NULL; |
---|
588 | 606 | unsigned long flags; |
---|
589 | | - int signr; |
---|
| 607 | + sigval_t addr; |
---|
| 608 | + int signr, errno; |
---|
590 | 609 | |
---|
591 | 610 | spin_lock_irqsave(&ps->lock, flags); |
---|
592 | 611 | list_move_tail(&as->asynclist, &ps->async_completed); |
---|
593 | 612 | as->status = urb->status; |
---|
594 | 613 | signr = as->signr; |
---|
595 | 614 | if (signr) { |
---|
596 | | - clear_siginfo(&sinfo); |
---|
597 | | - sinfo.si_signo = as->signr; |
---|
598 | | - sinfo.si_errno = as->status; |
---|
599 | | - sinfo.si_code = SI_ASYNCIO; |
---|
600 | | - sinfo.si_addr = as->userurb; |
---|
| 615 | + errno = as->status; |
---|
| 616 | + addr = as->userurb_sigval; |
---|
601 | 617 | pid = get_pid(as->pid); |
---|
602 | 618 | cred = get_cred(as->cred); |
---|
603 | 619 | } |
---|
604 | 620 | snoop(&urb->dev->dev, "urb complete\n"); |
---|
605 | 621 | snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length, |
---|
606 | 622 | as->status, COMPLETE, NULL, 0); |
---|
607 | | - if ((urb->transfer_flags & URB_DIR_MASK) == URB_DIR_IN) |
---|
| 623 | + if (usb_urb_dir_in(urb)) |
---|
608 | 624 | snoop_urb_data(urb, urb->actual_length); |
---|
609 | 625 | |
---|
610 | 626 | if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET && |
---|
.. | .. |
---|
615 | 631 | spin_unlock_irqrestore(&ps->lock, flags); |
---|
616 | 632 | |
---|
617 | 633 | if (signr) { |
---|
618 | | - kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred); |
---|
| 634 | + kill_pid_usb_asyncio(signr, errno, addr, pid, cred); |
---|
619 | 635 | put_pid(pid); |
---|
620 | 636 | put_cred(cred); |
---|
621 | 637 | } |
---|
.. | .. |
---|
629 | 645 | |
---|
630 | 646 | spin_lock_irqsave(&ps->lock, flags); |
---|
631 | 647 | while (!list_empty(list)) { |
---|
632 | | - as = list_entry(list->next, struct async, asynclist); |
---|
| 648 | + as = list_last_entry(list, struct async, asynclist); |
---|
633 | 649 | list_del_init(&as->asynclist); |
---|
634 | 650 | urb = as->urb; |
---|
635 | 651 | usb_get_urb(urb); |
---|
.. | .. |
---|
699 | 715 | destroy_async_on_interface(ps, ifnum); |
---|
700 | 716 | } |
---|
701 | 717 | |
---|
702 | | -/* The following routines are merely placeholders. There is no way |
---|
703 | | - * to inform a user task about suspend or resumes. |
---|
704 | | - */ |
---|
| 718 | +/* We don't care about suspend/resume of claimed interfaces */ |
---|
705 | 719 | static int driver_suspend(struct usb_interface *intf, pm_message_t msg) |
---|
706 | 720 | { |
---|
707 | 721 | return 0; |
---|
.. | .. |
---|
712 | 726 | return 0; |
---|
713 | 727 | } |
---|
714 | 728 | |
---|
| 729 | +/* The following routines apply to the entire device, not interfaces */ |
---|
| 730 | +void usbfs_notify_suspend(struct usb_device *udev) |
---|
| 731 | +{ |
---|
| 732 | + /* We don't need to handle this */ |
---|
| 733 | +} |
---|
| 734 | + |
---|
| 735 | +void usbfs_notify_resume(struct usb_device *udev) |
---|
| 736 | +{ |
---|
| 737 | + struct usb_dev_state *ps; |
---|
| 738 | + |
---|
| 739 | + /* Protect against simultaneous remove or release */ |
---|
| 740 | + mutex_lock(&usbfs_mutex); |
---|
| 741 | + list_for_each_entry(ps, &udev->filelist, list) { |
---|
| 742 | + WRITE_ONCE(ps->not_yet_resumed, 0); |
---|
| 743 | + wake_up_all(&ps->wait_for_resume); |
---|
| 744 | + } |
---|
| 745 | + mutex_unlock(&usbfs_mutex); |
---|
| 746 | +} |
---|
| 747 | + |
---|
715 | 748 | struct usb_driver usbfs_driver = { |
---|
716 | 749 | .name = "usbfs", |
---|
717 | 750 | .probe = driver_probe, |
---|
718 | 751 | .disconnect = driver_disconnect, |
---|
719 | 752 | .suspend = driver_suspend, |
---|
720 | 753 | .resume = driver_resume, |
---|
| 754 | + .supports_autosuspend = 1, |
---|
721 | 755 | }; |
---|
722 | 756 | |
---|
723 | 757 | static int claimintf(struct usb_dev_state *ps, unsigned int ifnum) |
---|
.. | .. |
---|
960 | 994 | return ret; |
---|
961 | 995 | } |
---|
962 | 996 | |
---|
963 | | -static int match_devt(struct device *dev, void *data) |
---|
964 | | -{ |
---|
965 | | - return dev->devt == (dev_t) (unsigned long) data; |
---|
966 | | -} |
---|
967 | | - |
---|
968 | 997 | static struct usb_device *usbdev_lookup_by_devt(dev_t devt) |
---|
969 | 998 | { |
---|
970 | 999 | struct device *dev; |
---|
971 | 1000 | |
---|
972 | | - dev = bus_find_device(&usb_bus_type, NULL, |
---|
973 | | - (void *) (unsigned long) devt, match_devt); |
---|
| 1001 | + dev = bus_find_device_by_devt(&usb_bus_type, devt); |
---|
974 | 1002 | if (!dev) |
---|
975 | 1003 | return NULL; |
---|
976 | 1004 | return to_usb_device(dev); |
---|
.. | .. |
---|
992 | 1020 | |
---|
993 | 1021 | ret = -ENODEV; |
---|
994 | 1022 | |
---|
995 | | - /* Protect against simultaneous removal or release */ |
---|
996 | | - mutex_lock(&usbfs_mutex); |
---|
997 | | - |
---|
998 | 1023 | /* usbdev device-node */ |
---|
999 | 1024 | if (imajor(inode) == USB_DEVICE_MAJOR) |
---|
1000 | 1025 | dev = usbdev_lookup_by_devt(inode->i_rdev); |
---|
1001 | | - |
---|
1002 | | - mutex_unlock(&usbfs_mutex); |
---|
1003 | | - |
---|
1004 | 1026 | if (!dev) |
---|
1005 | 1027 | goto out_free_ps; |
---|
1006 | 1028 | |
---|
.. | .. |
---|
1021 | 1043 | INIT_LIST_HEAD(&ps->async_completed); |
---|
1022 | 1044 | INIT_LIST_HEAD(&ps->memory_list); |
---|
1023 | 1045 | init_waitqueue_head(&ps->wait); |
---|
| 1046 | + init_waitqueue_head(&ps->wait_for_resume); |
---|
1024 | 1047 | ps->disc_pid = get_pid(task_pid(current)); |
---|
1025 | 1048 | ps->cred = get_current_cred(); |
---|
1026 | 1049 | smp_wmb(); |
---|
| 1050 | + |
---|
| 1051 | + /* Can't race with resume; the device is already active */ |
---|
1027 | 1052 | list_add_tail(&ps->list, &dev->filelist); |
---|
1028 | 1053 | file->private_data = ps; |
---|
1029 | 1054 | usb_unlock_device(dev); |
---|
.. | .. |
---|
1049 | 1074 | usb_lock_device(dev); |
---|
1050 | 1075 | usb_hub_release_all_ports(dev, ps); |
---|
1051 | 1076 | |
---|
| 1077 | + /* Protect against simultaneous resume */ |
---|
| 1078 | + mutex_lock(&usbfs_mutex); |
---|
1052 | 1079 | list_del_init(&ps->list); |
---|
| 1080 | + mutex_unlock(&usbfs_mutex); |
---|
1053 | 1081 | |
---|
1054 | 1082 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); |
---|
1055 | 1083 | ifnum++) { |
---|
.. | .. |
---|
1057 | 1085 | releaseintf(ps, ifnum); |
---|
1058 | 1086 | } |
---|
1059 | 1087 | destroy_all_async(ps); |
---|
1060 | | - usb_autosuspend_device(dev); |
---|
| 1088 | + if (!ps->suspend_allowed) |
---|
| 1089 | + usb_autosuspend_device(dev); |
---|
1061 | 1090 | usb_unlock_device(dev); |
---|
1062 | 1091 | usb_put_dev(dev); |
---|
1063 | 1092 | put_pid(ps->disc_pid); |
---|
.. | .. |
---|
1073 | 1102 | return 0; |
---|
1074 | 1103 | } |
---|
1075 | 1104 | |
---|
1076 | | -static int proc_control(struct usb_dev_state *ps, void __user *arg) |
---|
| 1105 | +static int do_proc_control(struct usb_dev_state *ps, |
---|
| 1106 | + struct usbdevfs_ctrltransfer *ctrl) |
---|
1077 | 1107 | { |
---|
1078 | 1108 | struct usb_device *dev = ps->dev; |
---|
1079 | | - struct usbdevfs_ctrltransfer ctrl; |
---|
1080 | 1109 | unsigned int tmo; |
---|
1081 | 1110 | unsigned char *tbuf; |
---|
1082 | 1111 | unsigned wLength; |
---|
1083 | 1112 | int i, pipe, ret; |
---|
1084 | 1113 | |
---|
1085 | | - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
---|
1086 | | - return -EFAULT; |
---|
1087 | | - ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.bRequest, |
---|
1088 | | - ctrl.wIndex); |
---|
| 1114 | + ret = check_ctrlrecip(ps, ctrl->bRequestType, ctrl->bRequest, |
---|
| 1115 | + ctrl->wIndex); |
---|
1089 | 1116 | if (ret) |
---|
1090 | 1117 | return ret; |
---|
1091 | | - wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */ |
---|
| 1118 | + wLength = ctrl->wLength; /* To suppress 64k PAGE_SIZE warning */ |
---|
1092 | 1119 | if (wLength > PAGE_SIZE) |
---|
1093 | 1120 | return -EINVAL; |
---|
1094 | 1121 | ret = usbfs_increase_memory_usage(PAGE_SIZE + sizeof(struct urb) + |
---|
.. | .. |
---|
1100 | 1127 | ret = -ENOMEM; |
---|
1101 | 1128 | goto done; |
---|
1102 | 1129 | } |
---|
1103 | | - tmo = ctrl.timeout; |
---|
| 1130 | + tmo = ctrl->timeout; |
---|
1104 | 1131 | snoop(&dev->dev, "control urb: bRequestType=%02x " |
---|
1105 | 1132 | "bRequest=%02x wValue=%04x " |
---|
1106 | 1133 | "wIndex=%04x wLength=%04x\n", |
---|
1107 | | - ctrl.bRequestType, ctrl.bRequest, ctrl.wValue, |
---|
1108 | | - ctrl.wIndex, ctrl.wLength); |
---|
1109 | | - if (ctrl.bRequestType & 0x80) { |
---|
1110 | | - if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, |
---|
1111 | | - ctrl.wLength)) { |
---|
1112 | | - ret = -EINVAL; |
---|
1113 | | - goto done; |
---|
1114 | | - } |
---|
| 1134 | + ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, |
---|
| 1135 | + ctrl->wIndex, ctrl->wLength); |
---|
| 1136 | + if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) { |
---|
1115 | 1137 | pipe = usb_rcvctrlpipe(dev, 0); |
---|
1116 | | - snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0); |
---|
| 1138 | + snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0); |
---|
1117 | 1139 | |
---|
1118 | 1140 | usb_unlock_device(dev); |
---|
1119 | | - i = usb_control_msg(dev, pipe, ctrl.bRequest, |
---|
1120 | | - ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, |
---|
1121 | | - tbuf, ctrl.wLength, tmo); |
---|
| 1141 | + i = usb_control_msg(dev, pipe, ctrl->bRequest, |
---|
| 1142 | + ctrl->bRequestType, ctrl->wValue, ctrl->wIndex, |
---|
| 1143 | + tbuf, ctrl->wLength, tmo); |
---|
1122 | 1144 | usb_lock_device(dev); |
---|
1123 | 1145 | snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, |
---|
1124 | 1146 | tbuf, max(i, 0)); |
---|
1125 | | - if ((i > 0) && ctrl.wLength) { |
---|
1126 | | - if (copy_to_user(ctrl.data, tbuf, i)) { |
---|
| 1147 | + if ((i > 0) && ctrl->wLength) { |
---|
| 1148 | + if (copy_to_user(ctrl->data, tbuf, i)) { |
---|
1127 | 1149 | ret = -EFAULT; |
---|
1128 | 1150 | goto done; |
---|
1129 | 1151 | } |
---|
1130 | 1152 | } |
---|
1131 | 1153 | } else { |
---|
1132 | | - if (ctrl.wLength) { |
---|
1133 | | - if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) { |
---|
| 1154 | + if (ctrl->wLength) { |
---|
| 1155 | + if (copy_from_user(tbuf, ctrl->data, ctrl->wLength)) { |
---|
1134 | 1156 | ret = -EFAULT; |
---|
1135 | 1157 | goto done; |
---|
1136 | 1158 | } |
---|
1137 | 1159 | } |
---|
1138 | 1160 | pipe = usb_sndctrlpipe(dev, 0); |
---|
1139 | | - snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, |
---|
1140 | | - tbuf, ctrl.wLength); |
---|
| 1161 | + snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, |
---|
| 1162 | + tbuf, ctrl->wLength); |
---|
1141 | 1163 | |
---|
1142 | 1164 | usb_unlock_device(dev); |
---|
1143 | | - i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, |
---|
1144 | | - ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, |
---|
1145 | | - tbuf, ctrl.wLength, tmo); |
---|
| 1165 | + i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl->bRequest, |
---|
| 1166 | + ctrl->bRequestType, ctrl->wValue, ctrl->wIndex, |
---|
| 1167 | + tbuf, ctrl->wLength, tmo); |
---|
1146 | 1168 | usb_lock_device(dev); |
---|
1147 | 1169 | snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0); |
---|
1148 | 1170 | } |
---|
1149 | 1171 | if (i < 0 && i != -EPIPE) { |
---|
1150 | 1172 | dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " |
---|
1151 | 1173 | "failed cmd %s rqt %u rq %u len %u ret %d\n", |
---|
1152 | | - current->comm, ctrl.bRequestType, ctrl.bRequest, |
---|
1153 | | - ctrl.wLength, i); |
---|
| 1174 | + current->comm, ctrl->bRequestType, ctrl->bRequest, |
---|
| 1175 | + ctrl->wLength, i); |
---|
1154 | 1176 | } |
---|
1155 | 1177 | ret = i; |
---|
1156 | 1178 | done: |
---|
.. | .. |
---|
1160 | 1182 | return ret; |
---|
1161 | 1183 | } |
---|
1162 | 1184 | |
---|
1163 | | -static int proc_bulk(struct usb_dev_state *ps, void __user *arg) |
---|
| 1185 | +static int proc_control(struct usb_dev_state *ps, void __user *arg) |
---|
| 1186 | +{ |
---|
| 1187 | + struct usbdevfs_ctrltransfer ctrl; |
---|
| 1188 | + |
---|
| 1189 | + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
---|
| 1190 | + return -EFAULT; |
---|
| 1191 | + return do_proc_control(ps, &ctrl); |
---|
| 1192 | +} |
---|
| 1193 | + |
---|
| 1194 | +static int do_proc_bulk(struct usb_dev_state *ps, |
---|
| 1195 | + struct usbdevfs_bulktransfer *bulk) |
---|
1164 | 1196 | { |
---|
1165 | 1197 | struct usb_device *dev = ps->dev; |
---|
1166 | | - struct usbdevfs_bulktransfer bulk; |
---|
1167 | 1198 | unsigned int tmo, len1, pipe; |
---|
1168 | 1199 | int len2; |
---|
1169 | 1200 | unsigned char *tbuf; |
---|
1170 | 1201 | int i, ret; |
---|
1171 | 1202 | |
---|
1172 | | - if (copy_from_user(&bulk, arg, sizeof(bulk))) |
---|
1173 | | - return -EFAULT; |
---|
1174 | | - ret = findintfep(ps->dev, bulk.ep); |
---|
| 1203 | + ret = findintfep(ps->dev, bulk->ep); |
---|
1175 | 1204 | if (ret < 0) |
---|
1176 | 1205 | return ret; |
---|
1177 | 1206 | ret = checkintf(ps, ret); |
---|
1178 | 1207 | if (ret) |
---|
1179 | 1208 | return ret; |
---|
1180 | | - if (bulk.ep & USB_DIR_IN) |
---|
1181 | | - pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f); |
---|
| 1209 | + if (bulk->ep & USB_DIR_IN) |
---|
| 1210 | + pipe = usb_rcvbulkpipe(dev, bulk->ep & 0x7f); |
---|
1182 | 1211 | else |
---|
1183 | | - pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f); |
---|
1184 | | - if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) |
---|
| 1212 | + pipe = usb_sndbulkpipe(dev, bulk->ep & 0x7f); |
---|
| 1213 | + if (!usb_maxpacket(dev, pipe, !(bulk->ep & USB_DIR_IN))) |
---|
1185 | 1214 | return -EINVAL; |
---|
1186 | | - len1 = bulk.len; |
---|
| 1215 | + len1 = bulk->len; |
---|
1187 | 1216 | if (len1 >= (INT_MAX - sizeof(struct urb))) |
---|
1188 | 1217 | return -EINVAL; |
---|
1189 | 1218 | ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); |
---|
.. | .. |
---|
1199 | 1228 | ret = -ENOMEM; |
---|
1200 | 1229 | goto done; |
---|
1201 | 1230 | } |
---|
1202 | | - tmo = bulk.timeout; |
---|
1203 | | - if (bulk.ep & 0x80) { |
---|
1204 | | - if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) { |
---|
1205 | | - ret = -EINVAL; |
---|
1206 | | - goto done; |
---|
1207 | | - } |
---|
| 1231 | + tmo = bulk->timeout; |
---|
| 1232 | + if (bulk->ep & 0x80) { |
---|
1208 | 1233 | snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0); |
---|
1209 | 1234 | |
---|
1210 | 1235 | usb_unlock_device(dev); |
---|
.. | .. |
---|
1213 | 1238 | snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2); |
---|
1214 | 1239 | |
---|
1215 | 1240 | if (!i && len2) { |
---|
1216 | | - if (copy_to_user(bulk.data, tbuf, len2)) { |
---|
| 1241 | + if (copy_to_user(bulk->data, tbuf, len2)) { |
---|
1217 | 1242 | ret = -EFAULT; |
---|
1218 | 1243 | goto done; |
---|
1219 | 1244 | } |
---|
1220 | 1245 | } |
---|
1221 | 1246 | } else { |
---|
1222 | 1247 | if (len1) { |
---|
1223 | | - if (copy_from_user(tbuf, bulk.data, len1)) { |
---|
| 1248 | + if (copy_from_user(tbuf, bulk->data, len1)) { |
---|
1224 | 1249 | ret = -EFAULT; |
---|
1225 | 1250 | goto done; |
---|
1226 | 1251 | } |
---|
.. | .. |
---|
1237 | 1262 | kfree(tbuf); |
---|
1238 | 1263 | usbfs_decrease_memory_usage(len1 + sizeof(struct urb)); |
---|
1239 | 1264 | return ret; |
---|
| 1265 | +} |
---|
| 1266 | + |
---|
| 1267 | +static int proc_bulk(struct usb_dev_state *ps, void __user *arg) |
---|
| 1268 | +{ |
---|
| 1269 | + struct usbdevfs_bulktransfer bulk; |
---|
| 1270 | + |
---|
| 1271 | + if (copy_from_user(&bulk, arg, sizeof(bulk))) |
---|
| 1272 | + return -EFAULT; |
---|
| 1273 | + return do_proc_bulk(ps, &bulk); |
---|
1240 | 1274 | } |
---|
1241 | 1275 | |
---|
1242 | 1276 | static void check_reset_of_active_ep(struct usb_device *udev, |
---|
.. | .. |
---|
1323 | 1357 | |
---|
1324 | 1358 | if (copy_to_user(arg, &ci, sizeof(ci))) |
---|
1325 | 1359 | return -EFAULT; |
---|
| 1360 | + return 0; |
---|
| 1361 | +} |
---|
| 1362 | + |
---|
| 1363 | +static int proc_conninfo_ex(struct usb_dev_state *ps, |
---|
| 1364 | + void __user *arg, size_t size) |
---|
| 1365 | +{ |
---|
| 1366 | + struct usbdevfs_conninfo_ex ci; |
---|
| 1367 | + struct usb_device *udev = ps->dev; |
---|
| 1368 | + |
---|
| 1369 | + if (size < sizeof(ci.size)) |
---|
| 1370 | + return -EINVAL; |
---|
| 1371 | + |
---|
| 1372 | + memset(&ci, 0, sizeof(ci)); |
---|
| 1373 | + ci.size = sizeof(ci); |
---|
| 1374 | + ci.busnum = udev->bus->busnum; |
---|
| 1375 | + ci.devnum = udev->devnum; |
---|
| 1376 | + ci.speed = udev->speed; |
---|
| 1377 | + |
---|
| 1378 | + while (udev && udev->portnum != 0) { |
---|
| 1379 | + if (++ci.num_ports <= ARRAY_SIZE(ci.ports)) |
---|
| 1380 | + ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports] = |
---|
| 1381 | + udev->portnum; |
---|
| 1382 | + udev = udev->parent; |
---|
| 1383 | + } |
---|
| 1384 | + |
---|
| 1385 | + if (ci.num_ports < ARRAY_SIZE(ci.ports)) |
---|
| 1386 | + memmove(&ci.ports[0], |
---|
| 1387 | + &ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports], |
---|
| 1388 | + ci.num_ports); |
---|
| 1389 | + |
---|
| 1390 | + if (copy_to_user(arg, &ci, min(sizeof(ci), size))) |
---|
| 1391 | + return -EFAULT; |
---|
| 1392 | + |
---|
1326 | 1393 | return 0; |
---|
1327 | 1394 | } |
---|
1328 | 1395 | |
---|
.. | .. |
---|
1445 | 1512 | |
---|
1446 | 1513 | static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb, |
---|
1447 | 1514 | struct usbdevfs_iso_packet_desc __user *iso_frame_desc, |
---|
1448 | | - void __user *arg) |
---|
| 1515 | + void __user *arg, sigval_t userurb_sigval) |
---|
1449 | 1516 | { |
---|
1450 | 1517 | struct usbdevfs_iso_packet_desc *isopkt = NULL; |
---|
1451 | 1518 | struct usb_host_endpoint *ep; |
---|
.. | .. |
---|
1504 | 1571 | ret = -EFAULT; |
---|
1505 | 1572 | goto error; |
---|
1506 | 1573 | } |
---|
1507 | | - if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) { |
---|
| 1574 | + if (uurb->buffer_length < (le16_to_cpu(dr->wLength) + 8)) { |
---|
1508 | 1575 | ret = -EINVAL; |
---|
1509 | 1576 | goto error; |
---|
1510 | 1577 | } |
---|
1511 | 1578 | ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest, |
---|
1512 | | - le16_to_cpup(&dr->wIndex)); |
---|
| 1579 | + le16_to_cpu(dr->wIndex)); |
---|
1513 | 1580 | if (ret) |
---|
1514 | 1581 | goto error; |
---|
1515 | | - uurb->buffer_length = le16_to_cpup(&dr->wLength); |
---|
| 1582 | + uurb->buffer_length = le16_to_cpu(dr->wLength); |
---|
1516 | 1583 | uurb->buffer += 8; |
---|
1517 | 1584 | if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) { |
---|
1518 | | - is_in = 1; |
---|
| 1585 | + is_in = true; |
---|
1519 | 1586 | uurb->endpoint |= USB_DIR_IN; |
---|
1520 | 1587 | } else { |
---|
1521 | | - is_in = 0; |
---|
| 1588 | + is_in = false; |
---|
1522 | 1589 | uurb->endpoint &= ~USB_DIR_IN; |
---|
1523 | 1590 | } |
---|
1524 | 1591 | if (is_in) |
---|
.. | .. |
---|
1527 | 1594 | "bRequest=%02x wValue=%04x " |
---|
1528 | 1595 | "wIndex=%04x wLength=%04x\n", |
---|
1529 | 1596 | dr->bRequestType, dr->bRequest, |
---|
1530 | | - __le16_to_cpup(&dr->wValue), |
---|
1531 | | - __le16_to_cpup(&dr->wIndex), |
---|
1532 | | - __le16_to_cpup(&dr->wLength)); |
---|
| 1597 | + __le16_to_cpu(dr->wValue), |
---|
| 1598 | + __le16_to_cpu(dr->wIndex), |
---|
| 1599 | + __le16_to_cpu(dr->wLength)); |
---|
1533 | 1600 | u = sizeof(struct usb_ctrlrequest); |
---|
1534 | 1601 | break; |
---|
1535 | 1602 | |
---|
.. | .. |
---|
1582 | 1649 | } |
---|
1583 | 1650 | for (totlen = u = 0; u < number_of_packets; u++) { |
---|
1584 | 1651 | /* |
---|
1585 | | - * arbitrary limit need for USB 3.0 |
---|
1586 | | - * bMaxBurst (0~15 allowed, 1~16 packets) |
---|
1587 | | - * bmAttributes (bit 1:0, mult 0~2, 1~3 packets) |
---|
1588 | | - * sizemax: 1024 * 16 * 3 = 49152 |
---|
| 1652 | + * arbitrary limit need for USB 3.1 Gen2 |
---|
| 1653 | + * sizemax: 96 DPs at SSP, 96 * 1024 = 98304 |
---|
1589 | 1654 | */ |
---|
1590 | | - if (isopkt[u].length > 49152) { |
---|
| 1655 | + if (isopkt[u].length > 98304) { |
---|
1591 | 1656 | ret = -EINVAL; |
---|
1592 | 1657 | goto error; |
---|
1593 | 1658 | } |
---|
.. | .. |
---|
1602 | 1667 | } |
---|
1603 | 1668 | |
---|
1604 | 1669 | if (uurb->buffer_length > 0 && |
---|
1605 | | - !access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, |
---|
1606 | | - uurb->buffer, uurb->buffer_length)) { |
---|
| 1670 | + !access_ok(uurb->buffer, uurb->buffer_length)) { |
---|
1607 | 1671 | ret = -EFAULT; |
---|
1608 | 1672 | goto error; |
---|
1609 | 1673 | } |
---|
.. | .. |
---|
1626 | 1690 | if (as->usbm) |
---|
1627 | 1691 | num_sgs = 0; |
---|
1628 | 1692 | |
---|
1629 | | - u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length + |
---|
| 1693 | + u += sizeof(struct async) + sizeof(struct urb) + |
---|
| 1694 | + (as->usbm ? 0 : uurb->buffer_length) + |
---|
1630 | 1695 | num_sgs * sizeof(struct scatterlist); |
---|
1631 | 1696 | ret = usbfs_increase_memory_usage(u); |
---|
1632 | 1697 | if (ret) |
---|
.. | .. |
---|
1748 | 1813 | isopkt = NULL; |
---|
1749 | 1814 | as->ps = ps; |
---|
1750 | 1815 | as->userurb = arg; |
---|
| 1816 | + as->userurb_sigval = userurb_sigval; |
---|
1751 | 1817 | if (as->usbm) { |
---|
1752 | 1818 | unsigned long uurb_start = (unsigned long)uurb->buffer; |
---|
1753 | 1819 | |
---|
.. | .. |
---|
1820 | 1886 | static int proc_submiturb(struct usb_dev_state *ps, void __user *arg) |
---|
1821 | 1887 | { |
---|
1822 | 1888 | struct usbdevfs_urb uurb; |
---|
| 1889 | + sigval_t userurb_sigval; |
---|
1823 | 1890 | |
---|
1824 | 1891 | if (copy_from_user(&uurb, arg, sizeof(uurb))) |
---|
1825 | 1892 | return -EFAULT; |
---|
1826 | 1893 | |
---|
| 1894 | + memset(&userurb_sigval, 0, sizeof(userurb_sigval)); |
---|
| 1895 | + userurb_sigval.sival_ptr = arg; |
---|
| 1896 | + |
---|
1827 | 1897 | return proc_do_submiturb(ps, &uurb, |
---|
1828 | 1898 | (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), |
---|
1829 | | - arg); |
---|
| 1899 | + arg, userurb_sigval); |
---|
1830 | 1900 | } |
---|
1831 | 1901 | |
---|
1832 | 1902 | static int proc_unlinkurb(struct usb_dev_state *ps, void __user *arg) |
---|
.. | .. |
---|
1962 | 2032 | static int proc_control_compat(struct usb_dev_state *ps, |
---|
1963 | 2033 | struct usbdevfs_ctrltransfer32 __user *p32) |
---|
1964 | 2034 | { |
---|
1965 | | - struct usbdevfs_ctrltransfer __user *p; |
---|
1966 | | - __u32 udata; |
---|
1967 | | - p = compat_alloc_user_space(sizeof(*p)); |
---|
1968 | | - if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) || |
---|
1969 | | - get_user(udata, &p32->data) || |
---|
1970 | | - put_user(compat_ptr(udata), &p->data)) |
---|
| 2035 | + struct usbdevfs_ctrltransfer ctrl; |
---|
| 2036 | + u32 udata; |
---|
| 2037 | + |
---|
| 2038 | + if (copy_from_user(&ctrl, p32, sizeof(*p32) - sizeof(compat_caddr_t)) || |
---|
| 2039 | + get_user(udata, &p32->data)) |
---|
1971 | 2040 | return -EFAULT; |
---|
1972 | | - return proc_control(ps, p); |
---|
| 2041 | + ctrl.data = compat_ptr(udata); |
---|
| 2042 | + return do_proc_control(ps, &ctrl); |
---|
1973 | 2043 | } |
---|
1974 | 2044 | |
---|
1975 | 2045 | static int proc_bulk_compat(struct usb_dev_state *ps, |
---|
1976 | 2046 | struct usbdevfs_bulktransfer32 __user *p32) |
---|
1977 | 2047 | { |
---|
1978 | | - struct usbdevfs_bulktransfer __user *p; |
---|
1979 | | - compat_uint_t n; |
---|
| 2048 | + struct usbdevfs_bulktransfer bulk; |
---|
1980 | 2049 | compat_caddr_t addr; |
---|
1981 | 2050 | |
---|
1982 | | - p = compat_alloc_user_space(sizeof(*p)); |
---|
1983 | | - |
---|
1984 | | - if (get_user(n, &p32->ep) || put_user(n, &p->ep) || |
---|
1985 | | - get_user(n, &p32->len) || put_user(n, &p->len) || |
---|
1986 | | - get_user(n, &p32->timeout) || put_user(n, &p->timeout) || |
---|
1987 | | - get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data)) |
---|
| 2051 | + if (get_user(bulk.ep, &p32->ep) || |
---|
| 2052 | + get_user(bulk.len, &p32->len) || |
---|
| 2053 | + get_user(bulk.timeout, &p32->timeout) || |
---|
| 2054 | + get_user(addr, &p32->data)) |
---|
1988 | 2055 | return -EFAULT; |
---|
1989 | | - |
---|
1990 | | - return proc_bulk(ps, p); |
---|
| 2056 | + bulk.data = compat_ptr(addr); |
---|
| 2057 | + return do_proc_bulk(ps, &bulk); |
---|
1991 | 2058 | } |
---|
| 2059 | + |
---|
1992 | 2060 | static int proc_disconnectsignal_compat(struct usb_dev_state *ps, void __user *arg) |
---|
1993 | 2061 | { |
---|
1994 | 2062 | struct usbdevfs_disconnectsignal32 ds; |
---|
.. | .. |
---|
1996 | 2064 | if (copy_from_user(&ds, arg, sizeof(ds))) |
---|
1997 | 2065 | return -EFAULT; |
---|
1998 | 2066 | ps->discsignr = ds.signr; |
---|
1999 | | - ps->disccontext = compat_ptr(ds.context); |
---|
| 2067 | + ps->disccontext.sival_int = ds.context; |
---|
2000 | 2068 | return 0; |
---|
2001 | 2069 | } |
---|
2002 | 2070 | |
---|
.. | .. |
---|
2024 | 2092 | static int proc_submiturb_compat(struct usb_dev_state *ps, void __user *arg) |
---|
2025 | 2093 | { |
---|
2026 | 2094 | struct usbdevfs_urb uurb; |
---|
| 2095 | + sigval_t userurb_sigval; |
---|
2027 | 2096 | |
---|
2028 | 2097 | if (get_urb32(&uurb, (struct usbdevfs_urb32 __user *)arg)) |
---|
2029 | 2098 | return -EFAULT; |
---|
2030 | 2099 | |
---|
| 2100 | + memset(&userurb_sigval, 0, sizeof(userurb_sigval)); |
---|
| 2101 | + userurb_sigval.sival_int = ptr_to_compat(arg); |
---|
| 2102 | + |
---|
2031 | 2103 | return proc_do_submiturb(ps, &uurb, |
---|
2032 | 2104 | ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, |
---|
2033 | | - arg); |
---|
| 2105 | + arg, userurb_sigval); |
---|
2034 | 2106 | } |
---|
2035 | 2107 | |
---|
2036 | 2108 | static int processcompl_compat(struct async *as, void __user * __user *arg) |
---|
.. | .. |
---|
2111 | 2183 | if (copy_from_user(&ds, arg, sizeof(ds))) |
---|
2112 | 2184 | return -EFAULT; |
---|
2113 | 2185 | ps->discsignr = ds.signr; |
---|
2114 | | - ps->disccontext = ds.context; |
---|
| 2186 | + ps->disccontext.sival_ptr = ds.context; |
---|
2115 | 2187 | return 0; |
---|
2116 | 2188 | } |
---|
2117 | 2189 | |
---|
.. | .. |
---|
2149 | 2221 | if (ps->privileges_dropped) |
---|
2150 | 2222 | return -EACCES; |
---|
2151 | 2223 | |
---|
| 2224 | + if (!connected(ps)) |
---|
| 2225 | + return -ENODEV; |
---|
| 2226 | + |
---|
2152 | 2227 | /* alloc buffer */ |
---|
2153 | 2228 | size = _IOC_SIZE(ctl->ioctl_code); |
---|
2154 | 2229 | if (size > 0) { |
---|
.. | .. |
---|
2163 | 2238 | } else { |
---|
2164 | 2239 | memset(buf, 0, size); |
---|
2165 | 2240 | } |
---|
2166 | | - } |
---|
2167 | | - |
---|
2168 | | - if (!connected(ps)) { |
---|
2169 | | - kfree(buf); |
---|
2170 | | - return -ENODEV; |
---|
2171 | 2241 | } |
---|
2172 | 2242 | |
---|
2173 | 2243 | if (ps->dev->state != USB_STATE_CONFIGURED) |
---|
.. | .. |
---|
2271 | 2341 | |
---|
2272 | 2342 | caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM | |
---|
2273 | 2343 | USBDEVFS_CAP_REAP_AFTER_DISCONNECT | USBDEVFS_CAP_MMAP | |
---|
2274 | | - USBDEVFS_CAP_DROP_PRIVILEGES; |
---|
| 2344 | + USBDEVFS_CAP_DROP_PRIVILEGES | |
---|
| 2345 | + USBDEVFS_CAP_CONNINFO_EX | MAYBE_CAP_SUSPEND; |
---|
2275 | 2346 | if (!ps->dev->bus->no_stop_on_short) |
---|
2276 | 2347 | caps |= USBDEVFS_CAP_BULK_CONTINUATION; |
---|
2277 | 2348 | if (ps->dev->bus->sg_tablesize) |
---|
.. | .. |
---|
2372 | 2443 | ps->privileges_dropped = true; |
---|
2373 | 2444 | |
---|
2374 | 2445 | return 0; |
---|
| 2446 | +} |
---|
| 2447 | + |
---|
| 2448 | +static int proc_forbid_suspend(struct usb_dev_state *ps) |
---|
| 2449 | +{ |
---|
| 2450 | + int ret = 0; |
---|
| 2451 | + |
---|
| 2452 | + if (ps->suspend_allowed) { |
---|
| 2453 | + ret = usb_autoresume_device(ps->dev); |
---|
| 2454 | + if (ret == 0) |
---|
| 2455 | + ps->suspend_allowed = false; |
---|
| 2456 | + else if (ret != -ENODEV) |
---|
| 2457 | + ret = -EIO; |
---|
| 2458 | + } |
---|
| 2459 | + return ret; |
---|
| 2460 | +} |
---|
| 2461 | + |
---|
| 2462 | +static int proc_allow_suspend(struct usb_dev_state *ps) |
---|
| 2463 | +{ |
---|
| 2464 | + if (!connected(ps)) |
---|
| 2465 | + return -ENODEV; |
---|
| 2466 | + |
---|
| 2467 | + WRITE_ONCE(ps->not_yet_resumed, 1); |
---|
| 2468 | + if (!ps->suspend_allowed) { |
---|
| 2469 | + usb_autosuspend_device(ps->dev); |
---|
| 2470 | + ps->suspend_allowed = true; |
---|
| 2471 | + } |
---|
| 2472 | + return 0; |
---|
| 2473 | +} |
---|
| 2474 | + |
---|
| 2475 | +static int proc_wait_for_resume(struct usb_dev_state *ps) |
---|
| 2476 | +{ |
---|
| 2477 | + int ret; |
---|
| 2478 | + |
---|
| 2479 | + usb_unlock_device(ps->dev); |
---|
| 2480 | + ret = wait_event_interruptible(ps->wait_for_resume, |
---|
| 2481 | + READ_ONCE(ps->not_yet_resumed) == 0); |
---|
| 2482 | + usb_lock_device(ps->dev); |
---|
| 2483 | + |
---|
| 2484 | + if (ret != 0) |
---|
| 2485 | + return -EINTR; |
---|
| 2486 | + return proc_forbid_suspend(ps); |
---|
2375 | 2487 | } |
---|
2376 | 2488 | |
---|
2377 | 2489 | /* |
---|
.. | .. |
---|
2568 | 2680 | case USBDEVFS_GET_SPEED: |
---|
2569 | 2681 | ret = ps->dev->speed; |
---|
2570 | 2682 | break; |
---|
| 2683 | + case USBDEVFS_FORBID_SUSPEND: |
---|
| 2684 | + ret = proc_forbid_suspend(ps); |
---|
| 2685 | + break; |
---|
| 2686 | + case USBDEVFS_ALLOW_SUSPEND: |
---|
| 2687 | + ret = proc_allow_suspend(ps); |
---|
| 2688 | + break; |
---|
| 2689 | + case USBDEVFS_WAIT_FOR_RESUME: |
---|
| 2690 | + ret = proc_wait_for_resume(ps); |
---|
| 2691 | + break; |
---|
| 2692 | + } |
---|
| 2693 | + |
---|
| 2694 | + /* Handle variable-length commands */ |
---|
| 2695 | + switch (cmd & ~IOCSIZE_MASK) { |
---|
| 2696 | + case USBDEVFS_CONNINFO_EX(0): |
---|
| 2697 | + ret = proc_conninfo_ex(ps, p, _IOC_SIZE(cmd)); |
---|
| 2698 | + break; |
---|
2571 | 2699 | } |
---|
2572 | 2700 | |
---|
2573 | 2701 | done: |
---|
.. | .. |
---|
2586 | 2714 | |
---|
2587 | 2715 | return ret; |
---|
2588 | 2716 | } |
---|
2589 | | - |
---|
2590 | | -#ifdef CONFIG_COMPAT |
---|
2591 | | -static long usbdev_compat_ioctl(struct file *file, unsigned int cmd, |
---|
2592 | | - unsigned long arg) |
---|
2593 | | -{ |
---|
2594 | | - int ret; |
---|
2595 | | - |
---|
2596 | | - ret = usbdev_do_ioctl(file, cmd, compat_ptr(arg)); |
---|
2597 | | - |
---|
2598 | | - return ret; |
---|
2599 | | -} |
---|
2600 | | -#endif |
---|
2601 | 2717 | |
---|
2602 | 2718 | /* No kernel lock - fine */ |
---|
2603 | 2719 | static __poll_t usbdev_poll(struct file *file, |
---|
.. | .. |
---|
2622 | 2738 | .read = usbdev_read, |
---|
2623 | 2739 | .poll = usbdev_poll, |
---|
2624 | 2740 | .unlocked_ioctl = usbdev_ioctl, |
---|
2625 | | -#ifdef CONFIG_COMPAT |
---|
2626 | | - .compat_ioctl = usbdev_compat_ioctl, |
---|
2627 | | -#endif |
---|
| 2741 | + .compat_ioctl = compat_ptr_ioctl, |
---|
2628 | 2742 | .mmap = usbdev_mmap, |
---|
2629 | 2743 | .open = usbdev_open, |
---|
2630 | 2744 | .release = usbdev_release, |
---|
.. | .. |
---|
2633 | 2747 | static void usbdev_remove(struct usb_device *udev) |
---|
2634 | 2748 | { |
---|
2635 | 2749 | struct usb_dev_state *ps; |
---|
2636 | | - struct siginfo sinfo; |
---|
2637 | 2750 | |
---|
| 2751 | + /* Protect against simultaneous resume */ |
---|
| 2752 | + mutex_lock(&usbfs_mutex); |
---|
2638 | 2753 | while (!list_empty(&udev->filelist)) { |
---|
2639 | 2754 | ps = list_entry(udev->filelist.next, struct usb_dev_state, list); |
---|
2640 | 2755 | destroy_all_async(ps); |
---|
2641 | 2756 | wake_up_all(&ps->wait); |
---|
| 2757 | + WRITE_ONCE(ps->not_yet_resumed, 0); |
---|
| 2758 | + wake_up_all(&ps->wait_for_resume); |
---|
2642 | 2759 | list_del_init(&ps->list); |
---|
2643 | | - if (ps->discsignr) { |
---|
2644 | | - clear_siginfo(&sinfo); |
---|
2645 | | - sinfo.si_signo = ps->discsignr; |
---|
2646 | | - sinfo.si_errno = EPIPE; |
---|
2647 | | - sinfo.si_code = SI_ASYNCIO; |
---|
2648 | | - sinfo.si_addr = ps->disccontext; |
---|
2649 | | - kill_pid_info_as_cred(ps->discsignr, &sinfo, |
---|
2650 | | - ps->disc_pid, ps->cred); |
---|
2651 | | - } |
---|
| 2760 | + if (ps->discsignr) |
---|
| 2761 | + kill_pid_usb_asyncio(ps->discsignr, EPIPE, ps->disccontext, |
---|
| 2762 | + ps->disc_pid, ps->cred); |
---|
2652 | 2763 | } |
---|
| 2764 | + mutex_unlock(&usbfs_mutex); |
---|
2653 | 2765 | } |
---|
2654 | 2766 | |
---|
2655 | 2767 | static int usbdev_notify(struct notifier_block *self, |
---|