diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-08 14:42:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-08 14:42:04 -0500 |
commit | 83280e90ef001f77a64e2ce59c25ab66e47ab1f0 (patch) | |
tree | ec0a5842e2fbc0f4abaff55299acac397b8da5c3 /drivers/usb/dwc3/ep0.c | |
parent | cc250e267bd56c531b0bee455fc724d50af83fac (diff) | |
parent | 0a8fd1346254974c3a852338508e4a4cddbb35f1 (diff) |
Merge tag 'usb-4.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH:
"Here are a bunch of USB fixes for 4.10-rc3. Yeah, it's a lot, an
artifact of the holiday break I think.
Lots of gadget and the usual XHCI fixups for reported issues (one day
that driver will calm down...) Also included are a bunch of usb-serial
driver fixes, and for good measure, a number of much-reported MUSB
driver issues have finally been resolved.
All of these have been in linux-next with no reported issues"
* tag 'usb-4.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (72 commits)
USB: fix problems with duplicate endpoint addresses
usb: ohci-at91: use descriptor-based gpio APIs correctly
usb: storage: unusual_uas: Add JMicron JMS56x to unusual device
usb: hub: Move hub_port_disable() to fix warning if PM is disabled
usb: musb: blackfin: add bfin_fifo_offset in bfin_ops
usb: musb: fix compilation warning on unused function
usb: musb: Fix trying to free already-free IRQ 4
usb: musb: dsps: implement clear_ep_rxintr() callback
usb: musb: core: add clear_ep_rxintr() to musb_platform_ops
USB: serial: ti_usb_3410_5052: fix NULL-deref at open
USB: serial: spcp8x5: fix NULL-deref at open
USB: serial: quatech2: fix sleep-while-atomic in close
USB: serial: pl2303: fix NULL-deref at open
USB: serial: oti6858: fix NULL-deref at open
USB: serial: omninet: fix NULL-derefs at open and disconnect
USB: serial: mos7840: fix misleading interrupt-URB comment
USB: serial: mos7840: remove unused write URB
USB: serial: mos7840: fix NULL-deref at open
USB: serial: mos7720: remove obsolete port initialisation
USB: serial: mos7720: fix parallel probe
...
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) |