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

Commit dbe2d1b7 authored by Chandana Kishori Chiluveru's avatar Chandana Kishori Chiluveru
Browse files

usb: host: xhci-plat: Fix interrupt storm issue in host mode



During xhci_suspend driver disables interrupt, clears HW_ACCESSIBLE and
halts the controller. There is still a possibility of a pending interrupt
before controller is halted which may get fired once interrupt is enabled
again in xhci_suspend. This results in interrupt storm as HCD irq handler
returns with IRQ_NONE due to HW_ACCESSIBLE is not set.

Fix this by disabling the irq before calling xhci_suspend and enable it
back after resume completion.

Change-Id: I68fbbb76eee533a4432e19443e875b981d316453
Signed-off-by: default avatarChandana Kishori Chiluveru <cchiluve@codeaurora.org>
parent fc23af4e
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -300,13 +300,19 @@ static int xhci_plat_runtime_suspend(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
	int ret;

	if (!xhci)
		return 0;

	dev_dbg(dev, "xhci-plat runtime suspend\n");

	return xhci_suspend(xhci, true);
	disable_irq(hcd->irq);
	ret = xhci_suspend(xhci, true);
	if (ret)
		enable_irq(hcd->irq);

	return ret;
}

static int xhci_plat_runtime_resume(struct device *dev)
@@ -321,6 +327,7 @@ static int xhci_plat_runtime_resume(struct device *dev)
	dev_dbg(dev, "xhci-plat runtime resume\n");

	ret = xhci_resume(xhci, false);
	enable_irq(hcd->irq);
	pm_runtime_mark_last_busy(dev);

	return ret;
+4 −0
Original line number Diff line number Diff line
@@ -949,6 +949,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
	if (xhci_handshake(xhci, &xhci->op_regs->status,
		      STS_HALT, STS_HALT, delay)) {
		xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
		set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
		set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
		spin_unlock_irq(&xhci->lock);
		return -ETIMEDOUT;
	}
@@ -964,6 +966,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
	if (xhci_handshake(xhci, &xhci->op_regs->status,
				STS_SAVE, 0, 10 * 1000)) {
		xhci_warn(xhci, "WARN: xHC save state timeout\n");
		set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
		set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
		spin_unlock_irq(&xhci->lock);
		return -ETIMEDOUT;
	}