diff options
Diffstat (limited to 'drivers/usb/dwc3/ep0.c')
| -rw-r--r-- | drivers/usb/dwc3/ep0.c | 46 |
1 files changed, 27 insertions, 19 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 4878d187c7d4..9bb1f8526f3e 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c | |||
| @@ -39,18 +39,13 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep); | |||
| 39 | static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | 39 | static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, |
| 40 | struct dwc3_ep *dep, struct dwc3_request *req); | 40 | struct dwc3_ep *dep, struct dwc3_request *req); |
| 41 | 41 | ||
| 42 | static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, | 42 | static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum, |
| 43 | u32 len, u32 type, bool chain) | 43 | dma_addr_t buf_dma, u32 len, u32 type, bool chain) |
| 44 | { | 44 | { |
| 45 | struct dwc3_gadget_ep_cmd_params params; | ||
| 46 | struct dwc3_trb *trb; | 45 | struct dwc3_trb *trb; |
| 47 | struct dwc3_ep *dep; | 46 | struct dwc3_ep *dep; |
| 48 | 47 | ||
| 49 | int ret; | ||
| 50 | |||
| 51 | dep = dwc->eps[epnum]; | 48 | dep = dwc->eps[epnum]; |
| 52 | if (dep->flags & DWC3_EP_BUSY) | ||
| 53 | return 0; | ||
| 54 | 49 | ||
| 55 | trb = &dwc->ep0_trb[dep->trb_enqueue]; | 50 | trb = &dwc->ep0_trb[dep->trb_enqueue]; |
| 56 | 51 | ||
| @@ -71,15 +66,23 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, | |||
| 71 | trb->ctrl |= (DWC3_TRB_CTRL_IOC | 66 | trb->ctrl |= (DWC3_TRB_CTRL_IOC |
| 72 | | DWC3_TRB_CTRL_LST); | 67 | | DWC3_TRB_CTRL_LST); |
| 73 | 68 | ||
| 74 | if (chain) | 69 | trace_dwc3_prepare_trb(dep, trb); |
| 70 | } | ||
| 71 | |||
| 72 | static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum) | ||
| 73 | { | ||
| 74 | struct dwc3_gadget_ep_cmd_params params; | ||
| 75 | struct dwc3_ep *dep; | ||
| 76 | int ret; | ||
| 77 | |||
| 78 | dep = dwc->eps[epnum]; | ||
| 79 | if (dep->flags & DWC3_EP_BUSY) | ||
| 75 | return 0; | 80 | return 0; |
| 76 | 81 | ||
| 77 | memset(¶ms, 0, sizeof(params)); | 82 | memset(¶ms, 0, sizeof(params)); |
| 78 | params.param0 = upper_32_bits(dwc->ep0_trb_addr); | 83 | params.param0 = upper_32_bits(dwc->ep0_trb_addr); |
| 79 | params.param1 = lower_32_bits(dwc->ep0_trb_addr); | 84 | params.param1 = lower_32_bits(dwc->ep0_trb_addr); |
| 80 | 85 | ||
| 81 | trace_dwc3_prepare_trb(dep, trb); | ||
| 82 | |||
| 83 | ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, ¶ms); | 86 | ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, ¶ms); |
| 84 | if (ret < 0) | 87 | if (ret < 0) |
| 85 | return ret; | 88 | return ret; |
| @@ -280,8 +283,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc) | |||
| 280 | 283 | ||
| 281 | complete(&dwc->ep0_in_setup); | 284 | complete(&dwc->ep0_in_setup); |
| 282 | 285 | ||
| 283 | ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8, | 286 | dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ctrl_req_addr, 8, |
| 284 | DWC3_TRBCTL_CONTROL_SETUP, false); | 287 | DWC3_TRBCTL_CONTROL_SETUP, false); |
| 288 | ret = dwc3_ep0_start_trans(dwc, 0); | ||
| 285 | WARN_ON(ret < 0); | 289 | WARN_ON(ret < 0); |
| 286 | } | 290 | } |
| 287 | 291 | ||
| @@ -912,9 +916,9 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, | |||
| 912 | 916 | ||
| 913 | dwc->ep0_next_event = DWC3_EP0_COMPLETE; | 917 | dwc->ep0_next_event = DWC3_EP0_COMPLETE; |
| 914 | 918 | ||
| 915 | ret = dwc3_ep0_start_trans(dwc, epnum, | 919 | dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ctrl_req_addr, |
| 916 | dwc->ctrl_req_addr, 0, | 920 | 0, DWC3_TRBCTL_CONTROL_DATA, false); |
| 917 | DWC3_TRBCTL_CONTROL_DATA, false); | 921 | ret = dwc3_ep0_start_trans(dwc, epnum); |
| 918 | WARN_ON(ret < 0); | 922 | WARN_ON(ret < 0); |
| 919 | } | 923 | } |
| 920 | } | 924 | } |
| @@ -993,9 +997,10 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | |||
| 993 | req->direction = !!dep->number; | 997 | req->direction = !!dep->number; |
| 994 | 998 | ||
| 995 | if (req->request.length == 0) { | 999 | if (req->request.length == 0) { |
| 996 | ret = dwc3_ep0_start_trans(dwc, dep->number, | 1000 | dwc3_ep0_prepare_one_trb(dwc, dep->number, |
| 997 | dwc->ctrl_req_addr, 0, | 1001 | dwc->ctrl_req_addr, 0, |
| 998 | DWC3_TRBCTL_CONTROL_DATA, false); | 1002 | DWC3_TRBCTL_CONTROL_DATA, false); |
| 1003 | ret = dwc3_ep0_start_trans(dwc, dep->number); | ||
| 999 | } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) | 1004 | } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) |
| 1000 | && (dep->number == 0)) { | 1005 | && (dep->number == 0)) { |
| 1001 | u32 transfer_size = 0; | 1006 | u32 transfer_size = 0; |
| @@ -1011,7 +1016,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | |||
| 1011 | if (req->request.length > DWC3_EP0_BOUNCE_SIZE) { | 1016 | if (req->request.length > DWC3_EP0_BOUNCE_SIZE) { |
| 1012 | transfer_size = ALIGN(req->request.length - maxpacket, | 1017 | transfer_size = ALIGN(req->request.length - maxpacket, |
| 1013 | maxpacket); | 1018 | maxpacket); |
| 1014 | ret = dwc3_ep0_start_trans(dwc, dep->number, | 1019 | dwc3_ep0_prepare_one_trb(dwc, dep->number, |
| 1015 | req->request.dma, | 1020 | req->request.dma, |
| 1016 | transfer_size, | 1021 | transfer_size, |
| 1017 | DWC3_TRBCTL_CONTROL_DATA, | 1022 | DWC3_TRBCTL_CONTROL_DATA, |
| @@ -1023,18 +1028,20 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | |||
| 1023 | 1028 | ||
| 1024 | dwc->ep0_bounced = true; | 1029 | dwc->ep0_bounced = true; |
| 1025 | 1030 | ||
| 1026 | ret = dwc3_ep0_start_trans(dwc, dep->number, | 1031 | dwc3_ep0_prepare_one_trb(dwc, dep->number, |
| 1027 | dwc->ep0_bounce_addr, transfer_size, | 1032 | dwc->ep0_bounce_addr, transfer_size, |
| 1028 | DWC3_TRBCTL_CONTROL_DATA, false); | 1033 | DWC3_TRBCTL_CONTROL_DATA, false); |
| 1034 | ret = dwc3_ep0_start_trans(dwc, dep->number); | ||
| 1029 | } else { | 1035 | } else { |
| 1030 | ret = usb_gadget_map_request_by_dev(dwc->sysdev, | 1036 | ret = usb_gadget_map_request_by_dev(dwc->sysdev, |
| 1031 | &req->request, dep->number); | 1037 | &req->request, dep->number); |
| 1032 | if (ret) | 1038 | if (ret) |
| 1033 | return; | 1039 | return; |
| 1034 | 1040 | ||
| 1035 | ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma, | 1041 | dwc3_ep0_prepare_one_trb(dwc, dep->number, req->request.dma, |
| 1036 | req->request.length, DWC3_TRBCTL_CONTROL_DATA, | 1042 | req->request.length, DWC3_TRBCTL_CONTROL_DATA, |
| 1037 | false); | 1043 | false); |
| 1044 | ret = dwc3_ep0_start_trans(dwc, dep->number); | ||
| 1038 | } | 1045 | } |
| 1039 | 1046 | ||
| 1040 | WARN_ON(ret < 0); | 1047 | WARN_ON(ret < 0); |
| @@ -1048,8 +1055,9 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) | |||
| 1048 | type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3 | 1055 | type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3 |
| 1049 | : DWC3_TRBCTL_CONTROL_STATUS2; | 1056 | : DWC3_TRBCTL_CONTROL_STATUS2; |
| 1050 | 1057 | ||
| 1051 | return dwc3_ep0_start_trans(dwc, dep->number, | 1058 | dwc3_ep0_prepare_one_trb(dwc, dep->number, |
| 1052 | dwc->ctrl_req_addr, 0, type, false); | 1059 | dwc->ctrl_req_addr, 0, type, false); |
| 1060 | return dwc3_ep0_start_trans(dwc, dep->number); | ||
| 1053 | } | 1061 | } |
| 1054 | 1062 | ||
| 1055 | static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) | 1063 | static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) |
