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

Commit bb86de26 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3: Disable ep cmd completion events before clearing R/S"

parents 301cd632 7b7e0654
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -968,8 +968,9 @@ struct dwc3_scratchpad_array {
#define DWC3_GSI_EVT_BUF_ALLOC			10
#define DWC3_GSI_EVT_BUF_ALLOC			10
#define DWC3_GSI_EVT_BUF_SETUP			11
#define DWC3_GSI_EVT_BUF_SETUP			11
#define DWC3_GSI_EVT_BUF_CLEANUP		12
#define DWC3_GSI_EVT_BUF_CLEANUP		12
#define DWC3_GSI_EVT_BUF_FREE			13
#define DWC3_GSI_EVT_BUF_CLEAR			13
#define DWC3_CONTROLLER_NOTIFY_CLEAR_DB		14
#define DWC3_GSI_EVT_BUF_FREE			14
#define DWC3_CONTROLLER_NOTIFY_CLEAR_DB		15


#define MAX_INTR_STATS				10
#define MAX_INTR_STATS				10


+9 −0
Original line number Original line Diff line number Diff line
@@ -2022,6 +2022,15 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
							evt->buf, evt->dma);
							evt->buf, evt->dma);
		}
		}
		break;
		break;
	case DWC3_GSI_EVT_BUF_CLEAR:
		dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_CLEAR\n");
		for (i = 0; i < mdwc->num_gsi_event_buffers; i++) {
			reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT((i+1)));
			reg &= DWC3_GEVNTCOUNT_MASK;
			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), reg);
			dbg_log_string("remaining EVNTCOUNT(%d)=%d", i+1, reg);
		}
		break;
	case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER:
	case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER:
		dwc3_msm_dbm_disable_updxfer(dwc, value);
		dwc3_msm_dbm_disable_updxfer(dwc, value);
		break;
		break;
+68 −1
Original line number Original line Diff line number Diff line
@@ -868,6 +868,42 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
	dbg_log_string("DONE");
	dbg_log_string("DONE");
}
}


static void dwc3_stop_active_transfers_to_halt(struct dwc3 *dwc)
{
	u32 epnum;
	struct dwc3_request *req;
	struct dwc3_ep *dep;

	dbg_log_string("START");
	for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
		dep = dwc->eps[epnum];
		if (!dep)
			continue;

		if (!(dep->flags & DWC3_EP_ENABLED))
			continue;

		dwc3_stop_active_transfer_noioc(dwc, dep->number, true);

		/* - giveback all requests to gadget driver */
		while (!list_empty(&dep->started_list)) {
			req = next_request(&dep->started_list);
			if (req)
				dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
		}

		while (!list_empty(&dep->pending_list)) {
			req = next_request(&dep->pending_list);
			if (req)
				dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
		}
	}

	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEAR, 0);

	dbg_log_string("DONE");
}

/**
/**
 * __dwc3_gadget_ep_disable - disables a hw endpoint
 * __dwc3_gadget_ep_disable - disables a hw endpoint
 * @dep: the endpoint to disable
 * @dep: the endpoint to disable
@@ -2138,7 +2174,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
		 * call dwc3_stop_active_transfers() API before stopping USB
		 * call dwc3_stop_active_transfers() API before stopping USB
		 * device controller.
		 * device controller.
		 */
		 */
		dwc3_stop_active_transfers(dwc);
		dwc3_stop_active_transfers_to_halt(dwc);


		reg &= ~DWC3_DCTL_RUN_STOP;
		reg &= ~DWC3_DCTL_RUN_STOP;


@@ -2153,6 +2189,9 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
		reg &= DWC3_DSTS_DEVCTRLHLT;
		reg &= DWC3_DSTS_DEVCTRLHLT;
	} while (--timeout && !(!is_on ^ !reg));
	} while (--timeout && !(!is_on ^ !reg));


	if (!is_on)
		dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_CLEAR_DB, 0);

	if (!timeout) {
	if (!timeout) {
		dev_err(dwc->dev, "failed to %s controller\n",
		dev_err(dwc->dev, "failed to %s controller\n",
				is_on ? "start" : "stop");
				is_on ? "start" : "stop");
@@ -3095,6 +3134,34 @@ void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
			dep->name, dep->number, ret);
			dep->name, dep->number, ret);
}
}


void dwc3_stop_active_transfer_noioc(struct dwc3 *dwc, u32 epnum, bool force)
{
	struct dwc3_ep *dep;
	struct dwc3_gadget_ep_cmd_params params;
	u32 cmd;
	int ret;

	dep = dwc->eps[epnum];

	if (!dep->resource_index)
		return;

	if (dep->endpoint.endless)
		dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER,
								dep->number);

	cmd = DWC3_DEPCMD_ENDTRANSFER;
	cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
	cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
	memset(&params, 0, sizeof(params));
	ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
	WARN_ON_ONCE(ret);
	dep->resource_index = 0;

	dbg_log_string("%s(%d): endxfer ret:%d)",
			dep->name, dep->number, ret);
}

static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
{
{
	u32 epnum;
	u32 epnum;
+1 −0
Original line number Original line Diff line number Diff line
@@ -111,6 +111,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
		gfp_t gfp_flags);
		gfp_t gfp_flags);
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force);
void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force);
void dwc3_stop_active_transfer_noioc(struct dwc3 *dwc, u32 epnum, bool force);
void dwc3_ep_inc_enq(struct dwc3_ep *dep);
void dwc3_ep_inc_enq(struct dwc3_ep *dep);
void dwc3_ep_inc_deq(struct dwc3_ep *dep);
void dwc3_ep_inc_deq(struct dwc3_ep *dep);