return ret;
  }
  
 -static int parse_usbdevfs_streams(struct dev_state *ps,
+ static struct usb_host_endpoint *ep_to_host_endpoint(struct usb_device *dev,
+                                                    unsigned char ep)
+ {
+       if (ep & USB_ENDPOINT_DIR_MASK)
+               return dev->ep_in[ep & USB_ENDPOINT_NUMBER_MASK];
+       else
+               return dev->ep_out[ep & USB_ENDPOINT_NUMBER_MASK];
+ }
+ 
++static int parse_usbdevfs_streams(struct usb_dev_state *ps,
+                                 struct usbdevfs_streams __user *streams,
+                                 unsigned int *num_streams_ret,
+                                 unsigned int *num_eps_ret,
+                                 struct usb_host_endpoint ***eps_ret,
+                                 struct usb_interface **intf_ret)
+ {
+       unsigned int i, num_streams, num_eps;
+       struct usb_host_endpoint **eps;
+       struct usb_interface *intf = NULL;
+       unsigned char ep;
+       int ifnum, ret;
+ 
+       if (get_user(num_streams, &streams->num_streams) ||
+           get_user(num_eps, &streams->num_eps))
+               return -EFAULT;
+ 
+       if (num_eps < 1 || num_eps > USB_MAXENDPOINTS)
+               return -EINVAL;
+ 
+       /* The XHCI controller allows max 2 ^ 16 streams */
+       if (num_streams_ret && (num_streams < 2 || num_streams > 65536))
+               return -EINVAL;
+ 
+       eps = kmalloc(num_eps * sizeof(*eps), GFP_KERNEL);
+       if (!eps)
+               return -ENOMEM;
+ 
+       for (i = 0; i < num_eps; i++) {
+               if (get_user(ep, &streams->eps[i])) {
+                       ret = -EFAULT;
+                       goto error;
+               }
+               eps[i] = ep_to_host_endpoint(ps->dev, ep);
+               if (!eps[i]) {
+                       ret = -EINVAL;
+                       goto error;
+               }
+ 
+               /* usb_alloc/free_streams operate on an usb_interface */
+               ifnum = findintfep(ps->dev, ep);
+               if (ifnum < 0) {
+                       ret = ifnum;
+                       goto error;
+               }
+ 
+               if (i == 0) {
+                       ret = checkintf(ps, ifnum);
+                       if (ret < 0)
+                               goto error;
+                       intf = usb_ifnum_to_if(ps->dev, ifnum);
+               } else {
+                       /* Verify all eps belong to the same interface */
+                       if (ifnum != intf->altsetting->desc.bInterfaceNumber) {
+                               ret = -EINVAL;
+                               goto error;
+                       }
+               }
+       }
+ 
+       if (num_streams_ret)
+               *num_streams_ret = num_streams;
+       *num_eps_ret = num_eps;
+       *eps_ret = eps;
+       *intf_ret = intf;
+ 
+       return 0;
+ 
+ error:
+       kfree(eps);
+       return ret;
+ }
+ 
  static int match_devt(struct device *dev, void *data)
  {
        return dev->devt == (dev_t) (unsigned long) data;
        return ret;
  }
  
 -static int proc_resetep(struct dev_state *ps, void __user *arg)
+ static void check_reset_of_active_ep(struct usb_device *udev,
+               unsigned int epnum, char *ioctl_name)
+ {
+       struct usb_host_endpoint **eps;
+       struct usb_host_endpoint *ep;
+ 
+       eps = (epnum & USB_DIR_IN) ? udev->ep_in : udev->ep_out;
+       ep = eps[epnum & 0x0f];
+       if (ep && !list_empty(&ep->urb_list))
+               dev_warn(&udev->dev, "Process %d (%s) called USBDEVFS_%s for active endpoint 0x%02x\n",
+                               task_pid_nr(current), current->comm,
+                               ioctl_name, epnum);
+ }
+ 
 +static int proc_resetep(struct usb_dev_state *ps, void __user *arg)
  {
        unsigned int ep;
        int ret;
        return claimintf(ps, dc.interface);
  }
  
 -static int proc_alloc_streams(struct dev_state *ps, void __user *arg)
++static int proc_alloc_streams(struct usb_dev_state *ps, void __user *arg)
+ {
+       unsigned num_streams, num_eps;
+       struct usb_host_endpoint **eps;
+       struct usb_interface *intf;
+       int r;
+ 
+       r = parse_usbdevfs_streams(ps, arg, &num_streams, &num_eps,
+                                  &eps, &intf);
+       if (r)
+               return r;
+ 
+       destroy_async_on_interface(ps,
+                                  intf->altsetting[0].desc.bInterfaceNumber);
+ 
+       r = usb_alloc_streams(intf, eps, num_eps, num_streams, GFP_KERNEL);
+       kfree(eps);
+       return r;
+ }
+ 
 -static int proc_free_streams(struct dev_state *ps, void __user *arg)
++static int proc_free_streams(struct usb_dev_state *ps, void __user *arg)
+ {
+       unsigned num_eps;
+       struct usb_host_endpoint **eps;
+       struct usb_interface *intf;
+       int r;
+ 
+       r = parse_usbdevfs_streams(ps, arg, NULL, &num_eps, &eps, &intf);
+       if (r)
+               return r;
+ 
+       destroy_async_on_interface(ps,
+                                  intf->altsetting[0].desc.bInterfaceNumber);
+ 
+       r = usb_free_streams(intf, eps, num_eps, GFP_KERNEL);
+       kfree(eps);
+       return r;
+ }
+ 
  /*
   * NOTE:  All requests here that have interface numbers as parameters
   * are assuming that somehow the configuration has been prevented from
 
                 */
                if (type == HUB_INIT) {
                        delay = hub_power_on(hub, false);
 -                      PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2);
 +                      INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
-                       schedule_delayed_work(&hub->init_work,
+                       queue_delayed_work(system_power_efficient_wq,
+                                       &hub->init_work,
                                        msecs_to_jiffies(delay));
  
                        /* Suppress autosuspend until init is done */
  
                /* Don't do a long sleep inside a workqueue routine */
                if (type == HUB_INIT2) {
 -                      PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3);
 +                      INIT_DELAYED_WORK(&hub->init_work, hub_init_func3);
-                       schedule_delayed_work(&hub->init_work,
+                       queue_delayed_work(system_power_efficient_wq,
+                                       &hub->init_work,
                                        msecs_to_jiffies(delay));
                        return;         /* Continues at init3: below */
                } else {
 
  extern int usb_match_device(struct usb_device *dev,
                            const struct usb_device_id *id);
  extern void usb_forced_unbind_intf(struct usb_interface *intf);
- extern void usb_rebind_intf(struct usb_interface *intf);
+ extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
  
 -extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port,
 -              struct dev_state *owner);
 -extern int usb_hub_release_port(struct usb_device *hdev, unsigned port,
 -              struct dev_state *owner);
  extern void usb_hub_release_all_ports(struct usb_device *hdev,
 -              struct dev_state *owner);
 +              struct usb_dev_state *owner);
  extern bool usb_device_is_owned(struct usb_device *udev);
  
  extern int  usb_hub_init(void);