diff options
author | Felipe Balbi <balbi@ti.com> | 2011-08-30 08:52:17 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-09-09 06:02:18 -0400 |
commit | 1ddcb218b5920fb20c2b3f029f0189568c2dc6e2 (patch) | |
tree | 4ae18461fed4e9b1aecae08ca83654323887cb64 /drivers/usb/dwc3 | |
parent | b53c772d16a9751554aabb05f95cef7b0b7fa2e9 (diff) |
usb: dwc3: use ep0_next_event field
Start tracking the next expected event and act
on the error conditions as suggested by databook.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/ep0.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 045c278274a5..48d3770bd765 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c | |||
@@ -120,6 +120,8 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, | |||
120 | dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, | 120 | dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, |
121 | dep->number); | 121 | dep->number); |
122 | 122 | ||
123 | dwc->ep0_next_event = DWC3_EP0_COMPLETE; | ||
124 | |||
123 | return 0; | 125 | return 0; |
124 | } | 126 | } |
125 | 127 | ||
@@ -250,7 +252,6 @@ static void dwc3_ep0_send_status_response(struct dwc3 *dwc) | |||
250 | dwc3_ep0_start_trans(dwc, 1, dwc->setup_buf_addr, | 252 | dwc3_ep0_start_trans(dwc, 1, dwc->setup_buf_addr, |
251 | dwc->ep0_usb_req.length, | 253 | dwc->ep0_usb_req.length, |
252 | DWC3_TRBCTL_CONTROL_DATA); | 254 | DWC3_TRBCTL_CONTROL_DATA); |
253 | dwc->ep0_status_pending = 1; | ||
254 | } | 255 | } |
255 | 256 | ||
256 | /* | 257 | /* |
@@ -295,7 +296,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl | |||
295 | response_pkt = (__le16 *) dwc->setup_buf; | 296 | response_pkt = (__le16 *) dwc->setup_buf; |
296 | *response_pkt = cpu_to_le16(usb_status); | 297 | *response_pkt = cpu_to_le16(usb_status); |
297 | dwc->ep0_usb_req.length = sizeof(*response_pkt); | 298 | dwc->ep0_usb_req.length = sizeof(*response_pkt); |
298 | dwc3_ep0_send_status_response(dwc); | 299 | dwc->ep0_status_pending = 1; |
299 | 300 | ||
300 | return 0; | 301 | return 0; |
301 | } | 302 | } |
@@ -526,10 +527,13 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, | |||
526 | goto err; | 527 | goto err; |
527 | 528 | ||
528 | len = le16_to_cpu(ctrl->wLength); | 529 | len = le16_to_cpu(ctrl->wLength); |
529 | if (!len) | 530 | if (!len) { |
530 | dwc->three_stage_setup = 0; | 531 | dwc->three_stage_setup = 0; |
531 | else | 532 | dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; |
533 | } else { | ||
532 | dwc->three_stage_setup = 1; | 534 | dwc->three_stage_setup = 1; |
535 | dwc->ep0_next_event = DWC3_EP0_NRDY_DATA; | ||
536 | } | ||
533 | 537 | ||
534 | if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) | 538 | if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) |
535 | ret = dwc3_ep0_std_request(dwc, ctrl); | 539 | ret = dwc3_ep0_std_request(dwc, ctrl); |
@@ -556,6 +560,8 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, | |||
556 | epnum = event->endpoint_number; | 560 | epnum = event->endpoint_number; |
557 | dep = dwc->eps[epnum]; | 561 | dep = dwc->eps[epnum]; |
558 | 562 | ||
563 | dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; | ||
564 | |||
559 | if (!dwc->ep0_status_pending) { | 565 | if (!dwc->ep0_status_pending) { |
560 | r = next_request(&dwc->eps[0]->request_list); | 566 | r = next_request(&dwc->eps[0]->request_list); |
561 | ur = &r->request; | 567 | ur = &r->request; |
@@ -655,6 +661,11 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc, | |||
655 | dep = dwc->eps[0]; | 661 | dep = dwc->eps[0]; |
656 | dwc->ep0state = EP0_DATA_PHASE; | 662 | dwc->ep0state = EP0_DATA_PHASE; |
657 | 663 | ||
664 | if (dwc->ep0_status_pending) { | ||
665 | dwc3_ep0_send_status_response(dwc); | ||
666 | return; | ||
667 | } | ||
668 | |||
658 | if (list_empty(&dep->request_list)) { | 669 | if (list_empty(&dep->request_list)) { |
659 | dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n"); | 670 | dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n"); |
660 | dep->flags |= DWC3_EP_PENDING_REQUEST; | 671 | dep->flags |= DWC3_EP_PENDING_REQUEST; |
@@ -724,12 +735,33 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, | |||
724 | dev_vdbg(dwc->dev, "Control Setup\n"); | 735 | dev_vdbg(dwc->dev, "Control Setup\n"); |
725 | dwc3_ep0_do_control_setup(dwc, event); | 736 | dwc3_ep0_do_control_setup(dwc, event); |
726 | break; | 737 | break; |
738 | |||
727 | case DEPEVT_STATUS_CONTROL_DATA: | 739 | case DEPEVT_STATUS_CONTROL_DATA: |
728 | dev_vdbg(dwc->dev, "Control Data\n"); | 740 | dev_vdbg(dwc->dev, "Control Data\n"); |
741 | |||
742 | if (dwc->ep0_next_event != DWC3_EP0_NRDY_DATA) { | ||
743 | dev_vdbg(dwc->dev, "Expected %d got %d\n", | ||
744 | DEPEVT_STATUS_CONTROL_DATA, | ||
745 | event->status); | ||
746 | |||
747 | dwc3_ep0_stall_and_restart(dwc); | ||
748 | return; | ||
749 | } | ||
750 | |||
729 | dwc3_ep0_do_control_data(dwc, event); | 751 | dwc3_ep0_do_control_data(dwc, event); |
730 | break; | 752 | break; |
753 | |||
731 | case DEPEVT_STATUS_CONTROL_STATUS: | 754 | case DEPEVT_STATUS_CONTROL_STATUS: |
732 | dev_vdbg(dwc->dev, "Control Status\n"); | 755 | dev_vdbg(dwc->dev, "Control Status\n"); |
756 | |||
757 | if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) { | ||
758 | dev_vdbg(dwc->dev, "Expected %d got %d\n", | ||
759 | DEPEVT_STATUS_CONTROL_STATUS, | ||
760 | event->status); | ||
761 | |||
762 | dwc3_ep0_stall_and_restart(dwc); | ||
763 | return; | ||
764 | } | ||
733 | dwc3_ep0_do_control_status(dwc, event); | 765 | dwc3_ep0_do_control_status(dwc, event); |
734 | } | 766 | } |
735 | } | 767 | } |