diff options
Diffstat (limited to 'drivers/usb/host/sl811-hcd.c')
-rw-r--r-- | drivers/usb/host/sl811-hcd.c | 74 |
1 files changed, 27 insertions, 47 deletions
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 4cfa3ff2c993..94d859aa73f8 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -435,14 +435,9 @@ static void finish_request( | |||
435 | if (usb_pipecontrol(urb->pipe)) | 435 | if (usb_pipecontrol(urb->pipe)) |
436 | ep->nextpid = USB_PID_SETUP; | 436 | ep->nextpid = USB_PID_SETUP; |
437 | 437 | ||
438 | spin_lock(&urb->lock); | 438 | usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb); |
439 | if (urb->status == -EINPROGRESS) | ||
440 | urb->status = status; | ||
441 | urb->hcpriv = NULL; | ||
442 | spin_unlock(&urb->lock); | ||
443 | |||
444 | spin_unlock(&sl811->lock); | 439 | spin_unlock(&sl811->lock); |
445 | usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb); | 440 | usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb, status); |
446 | spin_lock(&sl811->lock); | 441 | spin_lock(&sl811->lock); |
447 | 442 | ||
448 | /* leave active endpoints in the schedule */ | 443 | /* leave active endpoints in the schedule */ |
@@ -538,35 +533,21 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank) | |||
538 | bank + SL11H_XFERCNTREG); | 533 | bank + SL11H_XFERCNTREG); |
539 | if (len > ep->length) { | 534 | if (len > ep->length) { |
540 | len = ep->length; | 535 | len = ep->length; |
541 | urb->status = -EOVERFLOW; | 536 | urbstat = -EOVERFLOW; |
542 | } | 537 | } |
543 | urb->actual_length += len; | 538 | urb->actual_length += len; |
544 | sl811_read_buf(sl811, SL811HS_PACKET_BUF(bank == 0), | 539 | sl811_read_buf(sl811, SL811HS_PACKET_BUF(bank == 0), |
545 | buf, len); | 540 | buf, len); |
546 | usb_dotoggle(udev, ep->epnum, 0); | 541 | usb_dotoggle(udev, ep->epnum, 0); |
547 | if (urb->actual_length == urb->transfer_buffer_length) | 542 | if (urbstat == -EINPROGRESS && |
548 | urbstat = 0; | 543 | (len < ep->maxpacket || |
549 | else if (len < ep->maxpacket) { | 544 | urb->actual_length == |
550 | if (urb->transfer_flags & URB_SHORT_NOT_OK) | 545 | urb->transfer_buffer_length)) { |
551 | urbstat = -EREMOTEIO; | 546 | if (usb_pipecontrol(urb->pipe)) |
547 | ep->nextpid = USB_PID_ACK; | ||
552 | else | 548 | else |
553 | urbstat = 0; | 549 | urbstat = 0; |
554 | } | 550 | } |
555 | if (usb_pipecontrol(urb->pipe) | ||
556 | && (urbstat == -EREMOTEIO | ||
557 | || urbstat == 0)) { | ||
558 | |||
559 | /* NOTE if the status stage STALLs (why?), | ||
560 | * this reports the wrong urb status. | ||
561 | */ | ||
562 | spin_lock(&urb->lock); | ||
563 | if (urb->status == -EINPROGRESS) | ||
564 | urb->status = urbstat; | ||
565 | spin_unlock(&urb->lock); | ||
566 | |||
567 | urb = NULL; | ||
568 | ep->nextpid = USB_PID_ACK; | ||
569 | } | ||
570 | break; | 551 | break; |
571 | case USB_PID_SETUP: | 552 | case USB_PID_SETUP: |
572 | // PACKET("...ACK/setup_%02x qh%p\n", bank, ep); | 553 | // PACKET("...ACK/setup_%02x qh%p\n", bank, ep); |
@@ -605,7 +586,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank) | |||
605 | bank, status, ep, urbstat); | 586 | bank, status, ep, urbstat); |
606 | } | 587 | } |
607 | 588 | ||
608 | if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS)) | 589 | if (urbstat != -EINPROGRESS || urb->unlinked) |
609 | finish_request(sl811, ep, urb, urbstat); | 590 | finish_request(sl811, ep, urb, urbstat); |
610 | } | 591 | } |
611 | 592 | ||
@@ -807,7 +788,6 @@ static int balance(struct sl811 *sl811, u16 period, u16 load) | |||
807 | 788 | ||
808 | static int sl811h_urb_enqueue( | 789 | static int sl811h_urb_enqueue( |
809 | struct usb_hcd *hcd, | 790 | struct usb_hcd *hcd, |
810 | struct usb_host_endpoint *hep, | ||
811 | struct urb *urb, | 791 | struct urb *urb, |
812 | gfp_t mem_flags | 792 | gfp_t mem_flags |
813 | ) { | 793 | ) { |
@@ -820,7 +800,8 @@ static int sl811h_urb_enqueue( | |||
820 | struct sl811h_ep *ep = NULL; | 800 | struct sl811h_ep *ep = NULL; |
821 | unsigned long flags; | 801 | unsigned long flags; |
822 | int i; | 802 | int i; |
823 | int retval = 0; | 803 | int retval; |
804 | struct usb_host_endpoint *hep = urb->ep; | ||
824 | 805 | ||
825 | #ifdef DISABLE_ISO | 806 | #ifdef DISABLE_ISO |
826 | if (type == PIPE_ISOCHRONOUS) | 807 | if (type == PIPE_ISOCHRONOUS) |
@@ -838,7 +819,12 @@ static int sl811h_urb_enqueue( | |||
838 | || !HC_IS_RUNNING(hcd->state)) { | 819 | || !HC_IS_RUNNING(hcd->state)) { |
839 | retval = -ENODEV; | 820 | retval = -ENODEV; |
840 | kfree(ep); | 821 | kfree(ep); |
841 | goto fail; | 822 | goto fail_not_linked; |
823 | } | ||
824 | retval = usb_hcd_link_urb_to_ep(hcd, urb); | ||
825 | if (retval) { | ||
826 | kfree(ep); | ||
827 | goto fail_not_linked; | ||
842 | } | 828 | } |
843 | 829 | ||
844 | if (hep->hcpriv) { | 830 | if (hep->hcpriv) { |
@@ -951,37 +937,31 @@ static int sl811h_urb_enqueue( | |||
951 | sofirq_on(sl811); | 937 | sofirq_on(sl811); |
952 | } | 938 | } |
953 | 939 | ||
954 | /* in case of unlink-during-submit */ | ||
955 | spin_lock(&urb->lock); | ||
956 | if (urb->status != -EINPROGRESS) { | ||
957 | spin_unlock(&urb->lock); | ||
958 | finish_request(sl811, ep, urb, 0); | ||
959 | retval = 0; | ||
960 | goto fail; | ||
961 | } | ||
962 | urb->hcpriv = hep; | 940 | urb->hcpriv = hep; |
963 | spin_unlock(&urb->lock); | ||
964 | |||
965 | start_transfer(sl811); | 941 | start_transfer(sl811); |
966 | sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); | 942 | sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); |
967 | fail: | 943 | fail: |
944 | if (retval) | ||
945 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
946 | fail_not_linked: | ||
968 | spin_unlock_irqrestore(&sl811->lock, flags); | 947 | spin_unlock_irqrestore(&sl811->lock, flags); |
969 | return retval; | 948 | return retval; |
970 | } | 949 | } |
971 | 950 | ||
972 | static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | 951 | static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
973 | { | 952 | { |
974 | struct sl811 *sl811 = hcd_to_sl811(hcd); | 953 | struct sl811 *sl811 = hcd_to_sl811(hcd); |
975 | struct usb_host_endpoint *hep; | 954 | struct usb_host_endpoint *hep; |
976 | unsigned long flags; | 955 | unsigned long flags; |
977 | struct sl811h_ep *ep; | 956 | struct sl811h_ep *ep; |
978 | int retval = 0; | 957 | int retval; |
979 | 958 | ||
980 | spin_lock_irqsave(&sl811->lock, flags); | 959 | spin_lock_irqsave(&sl811->lock, flags); |
981 | hep = urb->hcpriv; | 960 | retval = usb_hcd_check_unlink_urb(hcd, urb, status); |
982 | if (!hep) | 961 | if (retval) |
983 | goto fail; | 962 | goto fail; |
984 | 963 | ||
964 | hep = urb->hcpriv; | ||
985 | ep = hep->hcpriv; | 965 | ep = hep->hcpriv; |
986 | if (ep) { | 966 | if (ep) { |
987 | /* finish right away if this urb can't be active ... | 967 | /* finish right away if this urb can't be active ... |
@@ -1029,8 +1009,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | |||
1029 | VDBG("dequeue, urb %p active %s; wait4irq\n", urb, | 1009 | VDBG("dequeue, urb %p active %s; wait4irq\n", urb, |
1030 | (sl811->active_a == ep) ? "A" : "B"); | 1010 | (sl811->active_a == ep) ? "A" : "B"); |
1031 | } else | 1011 | } else |
1032 | fail: | ||
1033 | retval = -EINVAL; | 1012 | retval = -EINVAL; |
1013 | fail: | ||
1034 | spin_unlock_irqrestore(&sl811->lock, flags); | 1014 | spin_unlock_irqrestore(&sl811->lock, flags); |
1035 | return retval; | 1015 | return retval; |
1036 | } | 1016 | } |