diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/usb-drv-arc.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/firmware/target/arm/usb-drv-arc.c b/firmware/target/arm/usb-drv-arc.c index 94dc9b7b5e..3b1146cc5c 100644 --- a/firmware/target/arm/usb-drv-arc.c +++ b/firmware/target/arm/usb-drv-arc.c | |||
@@ -917,20 +917,33 @@ static void transfer_completed(void) | |||
917 | int pipe = ep * 2 + dir; | 917 | int pipe = ep * 2 + dir; |
918 | if (mask & pipe2mask[pipe]) { | 918 | if (mask & pipe2mask[pipe]) { |
919 | struct queue_head* qh = &qh_array[pipe]; | 919 | struct queue_head* qh = &qh_array[pipe]; |
920 | if(qh->wait) { | 920 | |
921 | qh->wait=0; | ||
922 | wakeup_signal(&transfer_completion_signal[pipe]); | ||
923 | } | ||
924 | int length=0; | 921 | int length=0; |
925 | struct transfer_descriptor* td=&td_array[pipe*NUM_TDS_PER_EP]; | 922 | struct transfer_descriptor* td=&td_array[pipe*NUM_TDS_PER_EP]; |
926 | while(td!=(struct transfer_descriptor*)DTD_NEXT_TERMINATE && td!=0) | 923 | while(td!=(struct transfer_descriptor*)DTD_NEXT_TERMINATE && td!=0) |
927 | { | 924 | { |
925 | /* It seems that the controller sets the pipe bit to one even if the TD | ||
926 | * dosn't have the IOC bit set. So we have the rely the active status bit | ||
927 | * to check that all the TDs of the transfer are really finished and let | ||
928 | * the transfer continue if it's no the case */ | ||
929 | if(td->size_ioc_sts & DTD_STATUS_ACTIVE) | ||
930 | { | ||
931 | logf("skip half finished transfer"); | ||
932 | goto Lskip; | ||
933 | } | ||
928 | length += ((td->reserved & DTD_RESERVED_LENGTH_MASK) - | 934 | length += ((td->reserved & DTD_RESERVED_LENGTH_MASK) - |
929 | ((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS)); | 935 | ((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS)); |
930 | td=(struct transfer_descriptor*) td->next_td_ptr; | 936 | td=(struct transfer_descriptor*) td->next_td_ptr; |
931 | } | 937 | } |
938 | if(qh->wait) { | ||
939 | qh->wait=0; | ||
940 | wakeup_signal(&transfer_completion_signal[pipe]); | ||
941 | } | ||
942 | |||
932 | usb_core_transfer_complete(ep, dir?USB_DIR_IN:USB_DIR_OUT, | 943 | usb_core_transfer_complete(ep, dir?USB_DIR_IN:USB_DIR_OUT, |
933 | qh->status, length); | 944 | qh->status, length); |
945 | Lskip: | ||
946 | continue; | ||
934 | } | 947 | } |
935 | } | 948 | } |
936 | } | 949 | } |