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

Commit 24116304 authored by Mayank Rana's avatar Mayank Rana
Browse files

dwc3: gadget: restart timer on bus resume



Commit 80c2ae83 ("drivers: usb: dwc3: Remove xfer timer when going
to suspend") has dis-arm timer on bus suspend. Hence case where all
USB requests are queued at time of USB bus suspend and on resume there
is no request available to queue with USB controller, this timer is
not being re-arm. This results into temporarily data stall in UL as
controller is receiving sent data packets from host but software is
not receiving any completion on that bulk-out endpoint.

Also add macro to get bulk transfer timeout value in nanoseconds.

CRs-Fixed: 771888
Change-Id: I9f126b2ced15f3d7dcc93798c00c91f397a24302
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 2a4b1904
Loading
Loading
Loading
Loading
+37 −6
Original line number Diff line number Diff line
@@ -63,9 +63,10 @@
static int bulk_ep_xfer_timeout_ms;
module_param(bulk_ep_xfer_timeout_ms, int, S_IRUGO | S_IWUSR);

#define bulk_ep_xfer_timeout_ns (bulk_ep_xfer_timeout_ms * NSEC_PER_MSEC)
static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc);
static int dwc3_gadget_wakeup_int(struct dwc3 *dwc);

static void dwc3_restart_hrtimer(struct dwc3 *dwc);

struct dwc3_usb_gadget {
	struct work_struct wakeup_work;
@@ -1268,8 +1269,8 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,

		if (usb_endpoint_xfer_bulk(dep->endpoint.desc) &&
						bulk_ep_xfer_timeout_ms) {
			hrtimer_start(&dep->xfer_timer, ktime_set(0,
				bulk_ep_xfer_timeout_ms * NSEC_PER_MSEC),
			hrtimer_start(&dep->xfer_timer,
				ktime_set(0, bulk_ep_xfer_timeout_ns),
				HRTIMER_MODE_REL);
		}
	}
@@ -1727,7 +1728,7 @@ static int dwc3_gadget_wakeup_int(struct dwc3 *dwc)
	default:
		dev_dbg(dwc->dev, "can't wakeup from link state %d\n",
				link_state);
		ret = -EINVAL;
		dwc3_restart_hrtimer(dwc);
		goto out;
	}

@@ -2286,6 +2287,33 @@ out:
	return HRTIMER_NORESTART;
}

static void dwc3_restart_hrtimer(struct dwc3 *dwc)
{
	int i;
	struct dwc3_ep	*dep;

	if (!bulk_ep_xfer_timeout_ms)
		return;

	for (i = 0; i < dwc->num_out_eps; i++) {
		dep = dwc->eps[i];

		/* check if bulk-out endpoint is enabled or not */
		if (dep && dep->endpoint.desc &&
			usb_endpoint_xfer_bulk(dep->endpoint.desc) &&
			!dep->direction && (dep->flags & DWC3_EP_ENABLED)) {

			if (!hrtimer_active(&dep->xfer_timer)) {
				pr_debug("%s(): restart hrtimer of (%s)\n",
						__func__, dep->name);
				hrtimer_start(&dep->xfer_timer,
					ktime_set(0, bulk_ep_xfer_timeout_ns),
					HRTIMER_MODE_REL);
			}
		}
	}
}

static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
		u8 num, u32 direction)
{
@@ -2589,8 +2617,8 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
		if (event->status & DEPEVT_STATUS_LST)
			hrtimer_try_to_cancel(&dep->xfer_timer);
		else if (!clean_busy && (dwc->link_state != DWC3_LINK_STATE_U3))
			hrtimer_start(&dep->xfer_timer, ktime_set(0,
				bulk_ep_xfer_timeout_ms * NSEC_PER_MSEC),
			hrtimer_start(&dep->xfer_timer,
				ktime_set(0, bulk_ep_xfer_timeout_ns),
				HRTIMER_MODE_REL);
	}

@@ -3095,6 +3123,9 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
		if (dwc->enable_bus_suspend)
			usb_phy_set_suspend(dwc->dotg->otg.phy, 0);

		/* restart bulk-out timer if needed */
		dwc3_restart_hrtimer(dwc);

		/*
		 * gadget_driver resume function might require some dwc3-gadget
		 * operations, such as ep_enable. Hence, dwc->lock must be