Commit 490410b2 authored by Thinh Nguyen's avatar Thinh Nguyen Committed by Felipe Balbi

usb: dwc3: gadget: Check for number of TRBs prepared

By returning the number of TRBs prepared, we know whether to execute
__dwc3_gadget_kick_transfer(). This allows us to check if we ran out of
TRBs when extra TRBs are needed for OUT transfers. It also allows us to
properly handle usb_gadget_map_request_by_dev() error.

Fixes: c6267a51 ("usb: dwc3: gadget: align transfers to wMaxPacketSize")
Signed-off-by: default avatarThinh Nguyen <Thinh.Nguyen@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <balbi@kernel.org>
parent 13111fcb
...@@ -1257,10 +1257,13 @@ static int dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, ...@@ -1257,10 +1257,13 @@ static int dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
* The function goes through the requests list and sets up TRBs for the * The function goes through the requests list and sets up TRBs for the
* transfers. The function returns once there are no more TRBs available or * transfers. The function returns once there are no more TRBs available or
* it runs out of requests. * it runs out of requests.
*
* Returns the number of TRBs prepared or negative errno.
*/ */
static void dwc3_prepare_trbs(struct dwc3_ep *dep) static int dwc3_prepare_trbs(struct dwc3_ep *dep)
{ {
struct dwc3_request *req, *n; struct dwc3_request *req, *n;
int ret = 0;
BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
...@@ -1275,11 +1278,14 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) ...@@ -1275,11 +1278,14 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
* break things. * break things.
*/ */
list_for_each_entry(req, &dep->started_list, list) { list_for_each_entry(req, &dep->started_list, list) {
if (req->num_pending_sgs > 0) if (req->num_pending_sgs > 0) {
dwc3_prepare_one_trb_sg(dep, req); ret = dwc3_prepare_one_trb_sg(dep, req);
if (!ret)
return ret;
}
if (!dwc3_calc_trbs_left(dep)) if (!dwc3_calc_trbs_left(dep))
return; return ret;
/* /*
* Don't prepare beyond a transfer. In DWC_usb32, its transfer * Don't prepare beyond a transfer. In DWC_usb32, its transfer
...@@ -1287,17 +1293,16 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) ...@@ -1287,17 +1293,16 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
* active transfer instead of stopping. * active transfer instead of stopping.
*/ */
if (dep->stream_capable && req->request.is_last) if (dep->stream_capable && req->request.is_last)
return; return ret;
} }
list_for_each_entry_safe(req, n, &dep->pending_list, list) { list_for_each_entry_safe(req, n, &dep->pending_list, list) {
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
int ret;
ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request,
dep->direction); dep->direction);
if (ret) if (ret)
return; return ret;
req->sg = req->request.sg; req->sg = req->request.sg;
req->start_sg = req->sg; req->start_sg = req->sg;
...@@ -1305,12 +1310,12 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) ...@@ -1305,12 +1310,12 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
req->num_pending_sgs = req->request.num_mapped_sgs; req->num_pending_sgs = req->request.num_mapped_sgs;
if (req->num_pending_sgs > 0) if (req->num_pending_sgs > 0)
dwc3_prepare_one_trb_sg(dep, req); ret = dwc3_prepare_one_trb_sg(dep, req);
else else
dwc3_prepare_one_trb_linear(dep, req); ret = dwc3_prepare_one_trb_linear(dep, req);
if (!dwc3_calc_trbs_left(dep)) if (!ret || !dwc3_calc_trbs_left(dep))
return; return ret;
/* /*
* Don't prepare beyond a transfer. In DWC_usb32, its transfer * Don't prepare beyond a transfer. In DWC_usb32, its transfer
...@@ -1318,8 +1323,10 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) ...@@ -1318,8 +1323,10 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
* active transfer instead of stopping. * active transfer instead of stopping.
*/ */
if (dep->stream_capable && req->request.is_last) if (dep->stream_capable && req->request.is_last)
return; return ret;
} }
return ret;
} }
static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep); static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep);
...@@ -1332,12 +1339,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) ...@@ -1332,12 +1339,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
int ret; int ret;
u32 cmd; u32 cmd;
if (!dwc3_calc_trbs_left(dep)) ret = dwc3_prepare_trbs(dep);
return 0; if (ret <= 0)
return ret;
starting = !(dep->flags & DWC3_EP_TRANSFER_STARTED); starting = !(dep->flags & DWC3_EP_TRANSFER_STARTED);
dwc3_prepare_trbs(dep);
req = next_request(&dep->started_list); req = next_request(&dep->started_list);
if (!req) { if (!req) {
dep->flags |= DWC3_EP_PENDING_REQUEST; dep->flags |= DWC3_EP_PENDING_REQUEST;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment