diff options
Diffstat (limited to 'drivers/usb/host/isp116x-hcd.c')
-rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 5c851a36de72..d5027dc75a57 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -290,6 +290,7 @@ __releases(isp116x->lock) __acquires(isp116x->lock) | |||
290 | 290 | ||
291 | urb_dbg(urb, "Finish"); | 291 | urb_dbg(urb, "Finish"); |
292 | 292 | ||
293 | usb_hcd_unlink_urb_from_ep(isp116x_to_hcd(isp116x), urb); | ||
293 | spin_unlock(&isp116x->lock); | 294 | spin_unlock(&isp116x->lock); |
294 | usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb); | 295 | usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb); |
295 | spin_lock(&isp116x->lock); | 296 | spin_lock(&isp116x->lock); |
@@ -673,7 +674,7 @@ static int balance(struct isp116x *isp116x, u16 period, u16 load) | |||
673 | /*-----------------------------------------------------------------*/ | 674 | /*-----------------------------------------------------------------*/ |
674 | 675 | ||
675 | static int isp116x_urb_enqueue(struct usb_hcd *hcd, | 676 | static int isp116x_urb_enqueue(struct usb_hcd *hcd, |
676 | struct usb_host_endpoint *hep, struct urb *urb, | 677 | struct urb *urb, |
677 | gfp_t mem_flags) | 678 | gfp_t mem_flags) |
678 | { | 679 | { |
679 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 680 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
@@ -682,6 +683,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
682 | int is_out = !usb_pipein(pipe); | 683 | int is_out = !usb_pipein(pipe); |
683 | int type = usb_pipetype(pipe); | 684 | int type = usb_pipetype(pipe); |
684 | int epnum = usb_pipeendpoint(pipe); | 685 | int epnum = usb_pipeendpoint(pipe); |
686 | struct usb_host_endpoint *hep = urb->ep; | ||
685 | struct isp116x_ep *ep = NULL; | 687 | struct isp116x_ep *ep = NULL; |
686 | unsigned long flags; | 688 | unsigned long flags; |
687 | int i; | 689 | int i; |
@@ -705,7 +707,12 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
705 | if (!HC_IS_RUNNING(hcd->state)) { | 707 | if (!HC_IS_RUNNING(hcd->state)) { |
706 | kfree(ep); | 708 | kfree(ep); |
707 | ret = -ENODEV; | 709 | ret = -ENODEV; |
708 | goto fail; | 710 | goto fail_not_linked; |
711 | } | ||
712 | ret = usb_hcd_link_urb_to_ep(hcd, urb); | ||
713 | if (ret) { | ||
714 | kfree(ep); | ||
715 | goto fail_not_linked; | ||
709 | } | 716 | } |
710 | 717 | ||
711 | if (hep->hcpriv) | 718 | if (hep->hcpriv) |
@@ -818,6 +825,9 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
818 | start_atl_transfers(isp116x); | 825 | start_atl_transfers(isp116x); |
819 | 826 | ||
820 | fail: | 827 | fail: |
828 | if (ret) | ||
829 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
830 | fail_not_linked: | ||
821 | spin_unlock_irqrestore(&isp116x->lock, flags); | 831 | spin_unlock_irqrestore(&isp116x->lock, flags); |
822 | return ret; | 832 | return ret; |
823 | } | 833 | } |
@@ -825,20 +835,21 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
825 | /* | 835 | /* |
826 | Dequeue URBs. | 836 | Dequeue URBs. |
827 | */ | 837 | */ |
828 | static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | 838 | static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, |
839 | int status) | ||
829 | { | 840 | { |
830 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 841 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
831 | struct usb_host_endpoint *hep; | 842 | struct usb_host_endpoint *hep; |
832 | struct isp116x_ep *ep, *ep_act; | 843 | struct isp116x_ep *ep, *ep_act; |
833 | unsigned long flags; | 844 | unsigned long flags; |
845 | int rc; | ||
834 | 846 | ||
835 | spin_lock_irqsave(&isp116x->lock, flags); | 847 | spin_lock_irqsave(&isp116x->lock, flags); |
848 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
849 | if (rc) | ||
850 | goto done; | ||
851 | |||
836 | hep = urb->hcpriv; | 852 | hep = urb->hcpriv; |
837 | /* URB already unlinked (or never linked)? */ | ||
838 | if (!hep) { | ||
839 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
840 | return 0; | ||
841 | } | ||
842 | ep = hep->hcpriv; | 853 | ep = hep->hcpriv; |
843 | WARN_ON(hep != ep->hep); | 854 | WARN_ON(hep != ep->hep); |
844 | 855 | ||
@@ -856,9 +867,9 @@ static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | |||
856 | 867 | ||
857 | if (urb) | 868 | if (urb) |
858 | finish_request(isp116x, ep, urb); | 869 | finish_request(isp116x, ep, urb); |
859 | 870 | done: | |
860 | spin_unlock_irqrestore(&isp116x->lock, flags); | 871 | spin_unlock_irqrestore(&isp116x->lock, flags); |
861 | return 0; | 872 | return rc; |
862 | } | 873 | } |
863 | 874 | ||
864 | static void isp116x_endpoint_disable(struct usb_hcd *hcd, | 875 | static void isp116x_endpoint_disable(struct usb_hcd *hcd, |