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

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

Merge "usb: dwc3: Use high priority worker as bottom half handler"

parents cd2915d4 7af71579
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -670,6 +670,16 @@ int dwc3_core_init(struct dwc3 *dwc)
		}
	}

	/*
	 * Workaround for STAR 9000961433 which affects only version
	 * 3.00a of the DWC_usb3 core. This prevents the controller
	 * interrupt from being masked while handling events. IMOD
	 * allows us to work around this issue. Enable it for the
	 * affected version.
	 */
	 if (!dwc->imod_interval && (dwc->revision == DWC3_REVISION_300A))
		dwc->imod_interval = 1;

	ret = dwc3_core_reset(dwc);
	if (ret)
		goto err0;
@@ -1000,6 +1010,15 @@ err0:

#define DWC3_ALIGN_MASK		(16 - 1)

/* check whether the core supports IMOD */
bool dwc3_has_imod(struct dwc3 *dwc)
{
	return ((dwc3_is_usb3(dwc) &&
		dwc->revision >= DWC3_REVISION_300A) ||
		(dwc3_is_usb31(dwc) &&
		dwc->revision >= DWC3_USB31_REVISION_120A));
}

static int dwc3_probe(struct platform_device *pdev)
{
	struct device		*dev = &pdev->dev;
@@ -1040,8 +1059,8 @@ static int dwc3_probe(struct platform_device *pdev)

	/* will be enabled in dwc3_msm_resume() */
	irq_set_status_flags(irq, IRQ_NOAUTOEN);
	ret = devm_request_threaded_irq(dev, irq, NULL, dwc3_interrupt,
				IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
	ret = devm_request_irq(dev, irq, dwc3_interrupt, IRQF_SHARED, "dwc3",
			dwc);
	if (ret) {
		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
				irq, ret);
@@ -1219,6 +1238,14 @@ static int dwc3_probe(struct platform_device *pdev)
	dev->dma_parms	= dev->parent->dma_parms;
	dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);

	dwc->dwc_wq = alloc_ordered_workqueue("dwc_wq", WQ_HIGHPRI);
	if (!dwc->dwc_wq) {
		pr_err("%s: Unable to create workqueue dwc_wq\n", __func__);
		return -ENOMEM;
	}

	INIT_WORK(&dwc->bh_work, dwc3_bh_work);

	pm_runtime_no_callbacks(dev);
	pm_runtime_set_active(dev);
	pm_runtime_enable(dev);
@@ -1284,6 +1311,7 @@ err0:
	 * memory region the next time probe is called.
	 */
	res->start -= DWC3_GLOBALS_REGS_START;
	destroy_workqueue(dwc->dwc_wq);

	return ret;
}
@@ -1313,6 +1341,8 @@ static int dwc3_remove(struct platform_device *pdev)
	dwc3_core_exit(dwc);
	dwc3_ulpi_exit(dwc);

	destroy_workqueue(dwc->dwc_wq);

	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);

+31 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@
#define DWC3_DEVICE_EVENT_OVERFLOW		11

#define DWC3_GEVNTCOUNT_MASK	0xfffc
#define DWC3_GEVNTCOUNT_EHB	(1 << 31)
#define DWC3_GSNPSID_MASK	0xffff0000
#define DWC3_GSNPSREV_MASK	0xffff

@@ -149,6 +150,8 @@
#define DWC3_DEPCMDPAR0(n)	(0xc808 + (n * 0x10))
#define DWC3_DEPCMD(n)		(0xc80c + (n * 0x10))

#define DWC3_DEV_IMOD(n)	(0xca00 + (n * 0x4))

/* OTG Registers */
#define DWC3_OCFG		0xcc00
#define DWC3_OCTL		0xcc04
@@ -433,6 +436,11 @@
#define DWC3_DEPCMD_TYPE_BULK		2
#define DWC3_DEPCMD_TYPE_INTR		3

#define DWC3_DEV_IMOD_COUNT_SHIFT	16
#define DWC3_DEV_IMOD_COUNT_MASK	(0xffff << 16)
#define DWC3_DEV_IMOD_INTERVAL_SHIFT	0
#define DWC3_DEV_IMOD_INTERVAL_MASK	(0xffff << 0)

/* Structures */

struct dwc3_trb;
@@ -837,6 +845,8 @@ struct dwc3_scratchpad_array {
 * @bh_dbg_index: index for capturing bh_completion_time and bh_handled_evt_cnt
 * @wait_linkstate: waitqueue for waiting LINK to move into required state
 * @vbus_draw: current to be drawn from USB
 * @imod_interval: set the interrupt moderation interval in 250ns
 *			increments or 0 to disable.
 */
struct dwc3 {
	struct usb_ctrlrequest	*ctrl_req;
@@ -920,6 +930,7 @@ struct dwc3 {
#define DWC3_REVISION_260A	0x5533260a
#define DWC3_REVISION_270A	0x5533270a
#define DWC3_REVISION_280A	0x5533280a
#define DWC3_REVISION_300A	0x5533300a
#define DWC3_REVISION_310A	0x5533310a

/*
@@ -928,6 +939,7 @@ struct dwc3 {
 */
#define DWC3_REVISION_IS_DWC31		0x80000000
#define DWC3_USB31_REVISION_110A	(0x3131302a | DWC3_REVISION_IS_USB31)
#define DWC3_USB31_REVISION_120A	(0x3132302a | DWC3_REVISION_IS_DWC31)

	enum dwc3_ep0_next	ep0_next_event;
	enum dwc3_ep0_state	ep0state;
@@ -1008,6 +1020,11 @@ struct dwc3 {
	bool			b_suspend;
	unsigned		vbus_draw;

	u16			imod_interval;

	struct workqueue_struct	*dwc_wq;
	struct work_struct	bh_work;

	/* IRQ timing statistics */
	int			irq;
	unsigned long		irq_cnt;
@@ -1175,6 +1192,20 @@ struct dwc3_gadget_ep_cmd_params {
void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);

/* check whether we are on the DWC_usb3 core */
static inline bool dwc3_is_usb3(struct dwc3 *dwc)
{
	return !(dwc->revision & DWC3_REVISION_IS_DWC31);
}

/* check whether we are on the DWC_usb31 core */
static inline bool dwc3_is_usb31(struct dwc3 *dwc)
{
	return !!(dwc->revision & DWC3_REVISION_IS_DWC31);
}

bool dwc3_has_imod(struct dwc3 *dwc);

#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_host_init(struct dwc3 *dwc);
void dwc3_host_exit(struct dwc3 *dwc);
+3 −0
Original line number Diff line number Diff line
@@ -2053,6 +2053,9 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
	if (dwc->irq)
		disable_irq(dwc->irq);

	if (work_busy(&dwc->bh_work))
		dbg_event(0xFF, "pend evt", 0);

	/* disable power event irq, hs and ss phy irq is used as wake up src */
	disable_irq(mdwc->pwr_event_irq);

+27 −3
Original line number Diff line number Diff line
@@ -2011,6 +2011,17 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
	int			ret = 0;
	u32			reg;

	/*
	 * Use IMOD if enabled via dwc->imod_interval. Otherwise, if
	 * the core supports IMOD, disable it.
	 */
	if (dwc->imod_interval) {
		dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval);
		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB);
	} else if (dwc3_has_imod(dwc)) {
		dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), 0);
	}

	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
	reg &= ~(DWC3_DCFG_SPEED_MASK);

@@ -3362,8 +3373,6 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
		 */
		evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
		left -= 4;

		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
	}

	dwc->bh_handled_evt_cnt[dwc->bh_dbg_index] += (evt->count / 4);
@@ -3377,9 +3386,22 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
	reg &= ~DWC3_GEVNTSIZ_INTMASK;
	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);

	if (dwc->imod_interval)
		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf),
				DWC3_GEVNTCOUNT_EHB);

	return ret;
}

void dwc3_bh_work(struct work_struct *w)
{
	struct dwc3 *dwc = container_of(w, struct dwc3, bh_work);

	 pm_runtime_get_sync(dwc->dev);
	 dwc3_thread_interrupt(dwc->irq, dwc);
	 pm_runtime_put(dwc->dev);
}

static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
{
	struct dwc3 *dwc = _dwc;
@@ -3434,6 +3456,8 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf)
	reg |= DWC3_GEVNTSIZ_INTMASK;
	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);

	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), count);

	return IRQ_WAKE_THREAD;
}

@@ -3469,7 +3493,7 @@ irqreturn_t dwc3_interrupt(int irq, void *_dwc)
	dwc->irq_dbg_index = (dwc->irq_dbg_index + 1) % MAX_INTR_STATS;

	if (ret == IRQ_WAKE_THREAD)
		dwc3_thread_interrupt(dwc->irq, dwc);
		queue_work(dwc->dwc_wq, &dwc->bh_work);

	return IRQ_HANDLED;
}
+1 −0
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force);
irqreturn_t dwc3_interrupt(int irq, void *_dwc);
void dwc3_bh_work(struct work_struct *w);

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