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

Commit 8ef037cd authored by Chandana Kishori Chiluveru's avatar Chandana Kishori Chiluveru Committed by Jack Pham
Browse files

usb: dwc3: Disable the irq before clearing run_stop bit



Consider a case of quick pull-up disable after pull-up is enabled.
If a SETUP packet comes after bus reset event followed by connection
done event, there is a possibility of race between
composite_dev_cleanup() freeing cdev->req called from
configfs_composite_unbind() and composite_setup() storing req pointer
to stack. This causes use after free of cdev->req. Fix this issue by
disabling the irq before clearing the run-stop bit so that interrupt
handling for setup packet is prevented. In order to prevent running
bottom half check pullups_connected flag in dwc3_interrupt and ack
the generated events and return. Also flush the bottom half work
if there was any work pending before disabling dwc3 irq.

Change-Id: I979da8536bd6766153e25cf6120f00f348427a72
Signed-off-by: default avatarChandana Kishori Chiluveru <cchiluve@codeaurora.org>
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 0f35545c
Loading
Loading
Loading
Loading
+21 −0
Original line number Original line Diff line number Diff line
@@ -2082,7 +2082,18 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
			dev_err(dwc->dev, "timed out waiting for SETUP phase\n");
			dev_err(dwc->dev, "timed out waiting for SETUP phase\n");
	}
	}


	/* pull-up disable: clear pending events without queueing bh */
	dwc->pullups_connected = is_on;

	disable_irq(dwc->irq);

	/* prevent pending bh to run later */
	flush_work(&dwc->bh_work);

	spin_lock_irqsave(&dwc->lock, flags);
	spin_lock_irqsave(&dwc->lock, flags);
	if (dwc->ep0state != EP0_SETUP_PHASE)
		dbg_event(0xFF, "EP0 is not in SETUP phase\n", 0);

	/*
	/*
	 * If we are here after bus suspend notify otg state machine to
	 * If we are here after bus suspend notify otg state machine to
	 * increment pm usage count of dwc to prevent pm_runtime_suspend
	 * increment pm usage count of dwc to prevent pm_runtime_suspend
@@ -2093,6 +2104,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)


	ret = dwc3_gadget_run_stop(dwc, is_on, false);
	ret = dwc3_gadget_run_stop(dwc, is_on, false);
	spin_unlock_irqrestore(&dwc->lock, flags);
	spin_unlock_irqrestore(&dwc->lock, flags);
	enable_irq(dwc->irq);


	pm_runtime_mark_last_busy(dwc->dev);
	pm_runtime_mark_last_busy(dwc->dev);
	pm_runtime_put_autosuspend(dwc->dev);
	pm_runtime_put_autosuspend(dwc->dev);
@@ -3636,6 +3648,15 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
	if (dwc->err_evt_seen)
	if (dwc->err_evt_seen)
		return IRQ_HANDLED;
		return IRQ_HANDLED;


	/* Controller is being halted, ignore the interrupts */
	if (!dwc->pullups_connected) {
		count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
		count &= DWC3_GEVNTCOUNT_MASK;
		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
		dbg_event(0xFF, "NO_PULLUP", count);
		return IRQ_HANDLED;
	}

	/*
	/*
	 * With PCIe legacy interrupt, test shows that top-half irq handler can
	 * With PCIe legacy interrupt, test shows that top-half irq handler can
	 * be called again after HW interrupt deassertion. Check if bottom-half
	 * be called again after HW interrupt deassertion. Check if bottom-half