Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2837c7d0 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3: Avoid processing of TRB if HWO bit is set"

parents b6da935c 0525b5cf
Loading
Loading
Loading
Loading
+33 −7
Original line number Diff line number Diff line
@@ -1163,7 +1163,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param)
{
	struct dwc3_gadget_ep_cmd_params params;
	struct dwc3_request		*req;
	struct dwc3_request		*req, *req1, *n;
	struct dwc3			*dwc = dep->dwc;
	int				starting;
	int				ret;
@@ -1193,6 +1193,30 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param)

	ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
	if (ret < 0) {
		if ((ret == -EAGAIN) && starting &&
				usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
			/* If bit13 in Command complete event is set, software
			 * must issue ENDTRANDFER command and wait for
			 * Xfernotready event to queue the requests again.
			 */
			if (!dep->resource_index) {
				dep->resource_index =
					 dwc3_gadget_ep_get_transfer_index(dep);
				WARN_ON_ONCE(!dep->resource_index);
			}
			dwc3_stop_active_transfer(dwc, dep->number, true);

			list_for_each_entry_safe_reverse(req1, n,
						&dep->started_list, list) {
				req1->trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
				req1->trb = NULL;
				dwc3_gadget_move_pending_list_front(req1);
				dwc3_ep_inc_deq(dep);
			}

			return ret;
		}

		/*
		 * FIXME we need to iterate over the list of requests
		 * here and stop, unmap, free and del each of the linked
@@ -1240,7 +1264,7 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
	 * Schedule the first trb for one interval in the future or at
	 * least 4 microframes.
	 */
	uf = cur_uf + max_t(u32, 4, dep->interval);
	uf = cur_uf + max_t(u32, 16, dep->interval);

	ret = __dwc3_gadget_kick_transfer(dep, uf);
	if (ret < 0)
@@ -2638,6 +2662,9 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
		unsigned actual;
		int chain;

		if (req->trb->ctrl & DWC3_TRB_CTRL_HWO)
			return 0;

		length = req->request.length;
		chain = req->num_pending_sgs > 0;
		if (chain) {
@@ -2696,18 +2723,17 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,

	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
			list_empty(&dep->started_list)) {
		if (list_empty(&dep->pending_list)) {
		if (list_empty(&dep->pending_list))
			/*
			 * If there is no entry in request list then do
			 * not issue END TRANSFER now. Just set PENDING
			 * flag, so that END TRANSFER is issued when an
			 * entry is added into request list.
			 */
			dep->flags = DWC3_EP_PENDING_REQUEST;
		} else {
			dep->flags |= DWC3_EP_PENDING_REQUEST;
		else
			dwc3_stop_active_transfer(dwc, dep->number, true);
			dep->flags = DWC3_EP_ENABLED;
		}
		dep->flags &= ~DWC3_EP_MISSED_ISOC;
		return 1;
	}

+8 −0
Original line number Diff line number Diff line
@@ -68,6 +68,14 @@ static inline struct dwc3_request *next_request(struct list_head *list)
	return list_first_entry(list, struct dwc3_request, list);
}

static inline void dwc3_gadget_move_pending_list_front(struct dwc3_request *req)
{
	struct dwc3_ep		*dep = req->dep;

	req->started = false;
	list_move(&req->list, &dep->pending_list);
}

static inline void dwc3_gadget_move_started_request(struct dwc3_request *req)
{
	struct dwc3_ep		*dep = req->dep;