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

Commit 61a365b7 authored by Udipto Goswami's avatar Udipto Goswami
Browse files

usb: gadget: Don't giveback request if ep command times out



Currently driver is giving back requests to gadget even if
the active transfers are not stopped. This might lead the
controller to access the requests which are already unmapped.
This change adds a judgement for giving back the requests to
gadget based on ep command status. Also if ep command times out
and the controller doesn't stop correctly  then mark it as an
error event and restart the USB session.

Change-Id: If32cddddf0544140d5bdf68df9144702e00dc758
Signed-off-by: default avatarUdipto Goswami <ugoswami@codeaurora.org>
parent c9d2eaf4
Loading
Loading
Loading
Loading
+23 −8
Original line number Diff line number Diff line
@@ -800,8 +800,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
{
	struct dwc3_request		*req;

	dwc3_stop_active_transfer(dep, true, false);
	int ret = -EINVAL;

	if (dep->number == 0 && dwc->ep0state != EP0_SETUP_PHASE) {
		unsigned int dir;
@@ -817,6 +816,13 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
		dwc->eps[1]->trb_enqueue = 0;
	}

	ret = dwc3_stop_active_transfer(dep, true, false);
	if (ret < 0) {
		dbg_log_string("transfer not stopped for %s(%d), status:%d",
				dep->name, dep->number, ret);
		return;
	}

	if (dep->flags & DWC3_EP_END_TRANSFER_PENDING)
		udelay(2000);

@@ -2189,7 +2195,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
	dwc->softconnect = is_on;

	if (((dwc->dr_mode > USB_DR_MODE_HOST) && !dwc->vbus_active)
			|| !dwc->gadget_driver) {
			|| !dwc->gadget_driver || dwc->err_evt_seen) {
		/*
		 * Need to wait for vbus_session(on) from otg driver or to
		 * the udc_start.
@@ -2251,8 +2257,15 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
	ret = dwc3_gadget_run_stop(dwc, is_on, false);
	spin_unlock_irqrestore(&dwc->lock, flags);
	if (!is_on && ret == -ETIMEDOUT) {
		dev_err(dwc->dev, "%s: Core soft reset...\n", __func__);
		ret = dwc3_device_core_soft_reset(dwc);
		/*
		 * If we fail to stop the controller then mark it as an error
		 * event since it can lead the controller to go into an unknown
		 * state.
		 */
		dbg_log_string("%s: error event seen\n", __func__);
		dwc->err_evt_seen = true;
		dwc3_notify_event(dwc, DWC3_CONTROLLER_ERROR_EVENT, 0);
		dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_CLEAR_DB, 0);
	}
	enable_irq(dwc->irq);

@@ -2260,7 +2273,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
	pm_runtime_put_autosuspend(dwc->dev);
	dbg_event(0xFF, "Pullup put",
		atomic_read(&dwc->dev->power.usage_count));
	return ret;
	return 0;
}

static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
@@ -3152,7 +3165,7 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
	}
}

void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
int dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
{
	struct dwc3 *dwc = dep->dwc;
	struct dwc3_gadget_ep_cmd_params params;
@@ -3161,7 +3174,7 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)

	if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
	    (dep->flags & DWC3_EP_END_TRANSFER_PENDING))
		return;
		return 0;

	dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER,
			dep->number);
@@ -3215,6 +3228,8 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)

	if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
		udelay(100);

	return ret;
}
EXPORT_SYMBOL(dwc3_stop_active_transfer);

+1 −1
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
		gfp_t gfp_flags);
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt);
int dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt);

static inline dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
		struct dwc3_trb *trb)