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

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

Merge "xhci: hsic: kick stop ep command watchdog upon xHC halt failure"

parents 81e5235b 38ce1cfc
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -1025,6 +1025,50 @@ void mxhci_hsic_udev_enum_done(struct usb_hcd *hcd)
	}
}

/*
 * When stop ep command times out due to controller halt failure
 * no point waiting till XHCI_STOP_EP_CMD_TIMEOUT to giveback urbs.
 * Kick stop ep command watchdog to finish endpoint related cleanup
 * as early as possible.
 */
static void mxhci_hsic_ep_cleanup(struct usb_hcd *hcd)
{
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
	struct xhci_virt_ep *temp_ep;
	int i, j;
	unsigned long flags;
	int locked;
	bool kick_wdog = false;

	locked = spin_trylock_irqsave(&xhci->lock, flags);
	if (xhci->xhc_state & XHCI_STATE_DYING)
		goto unlock;

	for (i = 0; i < MAX_HC_SLOTS; i++) {
		if (!xhci->devs[i])
			continue;
		for (j = 0; j < 31; j++) {
			temp_ep = &xhci->devs[i]->eps[j];
			/* find first ep with pending stop ep cmd */
			if (temp_ep->stop_cmds_pending) {
				kick_wdog = true;
				/* kick stop ep cmd watchdog asap */
				mod_timer(&temp_ep->stop_cmd_timer, jiffies);
				goto unlock;
			}
		}
	}
unlock:
	/*
	 * if no stop ep cmd pending set xhci state to halted so that
	 * xhci_urb_dequeue() gives back urb right away.
	 */
	if (!kick_wdog)
		xhci->xhc_state |= XHCI_STATE_HALTED;
	if (locked)
		spin_unlock_irqrestore(&xhci->lock, flags);
}

static struct hc_driver mxhci_hsic_hc_driver = {
	.description =		"xhci-hcd",
	.product_desc =		"Qualcomm xHCI Host Controller using HSIC",
@@ -1060,6 +1104,7 @@ static struct hc_driver mxhci_hsic_hc_driver = {
	.address_device =	xhci_address_device,
	.update_hub_device =	xhci_update_hub_device,
	.reset_device =		xhci_discover_or_reset_device,
	.halt_failed_cleanup =	mxhci_hsic_ep_cleanup,

	/*
	 * scheduling support
+8 −1
Original line number Diff line number Diff line
@@ -101,6 +101,8 @@ void xhci_quiesce(struct xhci_hcd *xhci)
int xhci_halt(struct xhci_hcd *xhci)
{
	int ret;
	struct usb_hcd *hcd = xhci_to_hcd(xhci);

	xhci_dbg(xhci, "// Halt the HC\n");
	xhci_quiesce(xhci);

@@ -109,9 +111,14 @@ int xhci_halt(struct xhci_hcd *xhci)
	if (!ret) {
		xhci->xhc_state |= XHCI_STATE_HALTED;
		xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
	} else
	} else {
		xhci_warn(xhci, "Host not halted after %u microseconds.\n",
				XHCI_MAX_HALT_USEC);

		if (hcd->driver->halt_failed_cleanup)
			hcd->driver->halt_failed_cleanup(hcd);
	}

	return ret;
}

+2 −0
Original line number Diff line number Diff line
@@ -360,6 +360,8 @@ struct hc_driver {
	int	(*disable_usb3_lpm_timeout)(struct usb_hcd *,
			struct usb_device *, enum usb3_link_state state);
	int	(*find_raw_port_number)(struct usb_hcd *, int);
	/* if hcd needs to finish ep cleanup asap after HC halt failiure */
	void (*halt_failed_cleanup)(struct usb_hcd *);

	/* to log submission/completion events*/
	void	(*log_urb)(struct urb *urb, char *event, unsigned extra);