diff options
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 9ac4835d7b6b..1c98aee051a5 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -1075,17 +1075,8 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |||
1075 | 1075 | ||
1076 | list_add_tail(&req->list, &dep->request_list); | 1076 | list_add_tail(&req->list, &dep->request_list); |
1077 | 1077 | ||
1078 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { | ||
1079 | if (dep->flags & DWC3_EP_BUSY) { | ||
1080 | dep->flags |= DWC3_EP_PENDING_REQUEST; | ||
1081 | } else if (dep->flags & DWC3_EP_MISSED_ISOC) { | ||
1082 | __dwc3_gadget_start_isoc(dwc, dep, dep->current_uf); | ||
1083 | dep->flags &= ~DWC3_EP_MISSED_ISOC; | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1087 | /* | 1078 | /* |
1088 | * There are two special cases: | 1079 | * There are a few special cases: |
1089 | * | 1080 | * |
1090 | * 1. XferNotReady with empty list of requests. We need to kick the | 1081 | * 1. XferNotReady with empty list of requests. We need to kick the |
1091 | * transfer here in that situation, otherwise we will be NAKing | 1082 | * transfer here in that situation, otherwise we will be NAKing |
@@ -1094,24 +1085,29 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |||
1094 | * able to receive the data until the next request is queued. | 1085 | * able to receive the data until the next request is queued. |
1095 | * The following code is handling exactly that. | 1086 | * The following code is handling exactly that. |
1096 | * | 1087 | * |
1097 | * 2. XferInProgress on Isoc EP with an active transfer. We need to | ||
1098 | * kick the transfer here after queuing a request, otherwise the | ||
1099 | * core may not see the modified TRB(s). | ||
1100 | */ | 1088 | */ |
1101 | if (dep->flags & DWC3_EP_PENDING_REQUEST) { | 1089 | if (dep->flags & DWC3_EP_PENDING_REQUEST) { |
1102 | int ret; | 1090 | int ret; |
1103 | int start_trans = 1; | ||
1104 | u8 trans_idx = dep->res_trans_idx; | ||
1105 | 1091 | ||
1106 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | 1092 | ret = __dwc3_gadget_kick_transfer(dep, 0, true); |
1107 | (dep->flags & DWC3_EP_BUSY)) { | 1093 | if (ret && ret != -EBUSY) { |
1108 | start_trans = 0; | 1094 | struct dwc3 *dwc = dep->dwc; |
1109 | WARN_ON_ONCE(!trans_idx); | 1095 | |
1110 | } else { | 1096 | dev_dbg(dwc->dev, "%s: failed to kick transfers\n", |
1111 | trans_idx = 0; | 1097 | dep->name); |
1112 | } | 1098 | } |
1099 | } | ||
1113 | 1100 | ||
1114 | ret = __dwc3_gadget_kick_transfer(dep, trans_idx, start_trans); | 1101 | /* |
1102 | * 2. XferInProgress on Isoc EP with an active transfer. We need to | ||
1103 | * kick the transfer here after queuing a request, otherwise the | ||
1104 | * core may not see the modified TRB(s). | ||
1105 | */ | ||
1106 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | ||
1107 | (dep->flags & DWC3_EP_BUSY)) { | ||
1108 | WARN_ON_ONCE(!dep->res_trans_idx); | ||
1109 | ret = __dwc3_gadget_kick_transfer(dep, dep->res_trans_idx, | ||
1110 | false); | ||
1115 | if (ret && ret != -EBUSY) { | 1111 | if (ret && ret != -EBUSY) { |
1116 | struct dwc3 *dwc = dep->dwc; | 1112 | struct dwc3 *dwc = dep->dwc; |
1117 | 1113 | ||
@@ -1120,6 +1116,16 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |||
1120 | } | 1116 | } |
1121 | } | 1117 | } |
1122 | 1118 | ||
1119 | /* | ||
1120 | * 3. Missed ISOC Handling. We need to start isoc transfer on the saved | ||
1121 | * uframe number. | ||
1122 | */ | ||
1123 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | ||
1124 | (dep->flags & DWC3_EP_MISSED_ISOC)) { | ||
1125 | __dwc3_gadget_start_isoc(dwc, dep, dep->current_uf); | ||
1126 | dep->flags &= ~DWC3_EP_MISSED_ISOC; | ||
1127 | } | ||
1128 | |||
1123 | return 0; | 1129 | return 0; |
1124 | } | 1130 | } |
1125 | 1131 | ||