USB: fix urb dequeue bug to avoid kernel panic
[firefly-linux-kernel-4.4.55.git] / drivers / usb / core / hcd.c
old mode 100644 (file)
new mode 100755 (executable)
index ace9f84..1a1dfe5
@@ -977,10 +977,7 @@ static int register_root_hub(struct usb_hcd *hcd)
        if (retval) {
                dev_err (parent_dev, "can't register root hub for %s, %d\n",
                                dev_name(&usb_dev->dev), retval);
-       }
-       mutex_unlock(&usb_bus_list_lock);
-
-       if (retval == 0) {
+       } else {
                spin_lock_irq (&hcd_root_hub_lock);
                hcd->rh_registered = 1;
                spin_unlock_irq (&hcd_root_hub_lock);
@@ -989,6 +986,7 @@ static int register_root_hub(struct usb_hcd *hcd)
                if (HCD_DEAD(hcd))
                        usb_hc_died (hcd);      /* This time clean up */
        }
+       mutex_unlock(&usb_bus_list_lock);
 
        return retval;
 }
@@ -1387,11 +1385,10 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
                                        ret = -EAGAIN;
                                else
                                        urb->transfer_flags |= URB_DMA_MAP_SG;
-                               if (n != urb->num_sgs) {
-                                       urb->num_sgs = n;
+                               urb->num_mapped_sgs = n;
+                               if (n != urb->num_sgs)
                                        urb->transfer_flags |=
                                                        URB_DMA_SG_COMBINED;
-                               }
                        } else if (urb->sg) {
                                struct scatterlist *sg = urb->sg;
                                urb->transfer_dma = dma_map_page(
@@ -1583,8 +1580,12 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
 
        /* pass ownership to the completion handler */
        urb->status = status;
-       urb->complete (urb);
+       if(!atomic_read(&urb->use_count)){
+               printk("%s %d\n", __func__, atomic_read(&urb->use_count));
+               return;
+       }
        atomic_dec (&urb->use_count);
+       urb->complete (urb);
        if (unlikely(atomic_read(&urb->reject)))
                wake_up (&usb_kill_urb_queue);
        usb_put_urb (urb);
@@ -1764,6 +1765,8 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev,
                struct usb_interface *iface = usb_ifnum_to_if(udev,
                                cur_alt->desc.bInterfaceNumber);
 
+               if (!iface)
+                       return -EINVAL;
                if (iface->resetting_device) {
                        /*
                         * The USB core just reset the device, so the xHCI host
@@ -1956,6 +1959,7 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
        }
 
        if (!hcd->driver->bus_suspend) {
+               printk("%s,error,everest\n",__func__);
                status = -ENOENT;
        } else {
                clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
@@ -2434,8 +2438,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
                        && device_can_wakeup(&hcd->self.root_hub->dev))
                dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
 
-       /* enable irqs just before we start the controller */
-       if (usb_hcd_is_primary_hcd(hcd)) {
+       /* enable irqs just before we start the controller,
+        * if the BIOS provides legacy PCI irqs.
+        */
+       if (usb_hcd_is_primary_hcd(hcd) && irqnum) {
                retval = usb_hcd_request_irqs(hcd, irqnum, irqflags);
                if (retval)
                        goto err_request_irq;