Commit 5aba179c authored by Chunfeng Yun's avatar Chunfeng Yun Committed by Greg Kroah-Hartman
Browse files

usb: mtu3: fix the failure of qmu stop



This happens when do stress test of uvc stream on/off which will
enable/disable endpoints. uvc has four tx requests, and may disable
endpoint between queue tx requests as following:
    enable ep --> start qmu
    queue tx request0
    queue tx request1
    queue tx request2 --> resume qmu
    disable ep --> stop qmu may fail [1]
    queue tx request3 --> will resume qmu, may cause qmu can't work
                          when enable ep next time [2]

[1]: when the tx fifo has some data to transmit, and
    try to stop qmu (stop ep) meanwhile resume qmu (queue tx request),
    it may cause stop qmu timeout, then can be fixed by flushing fifo
    when stop qmu.
[2]: it resumes qmu again, shall stop qmu again.

Signed-off-by: default avatarChunfeng Yun <chunfeng.yun@mediatek.com>
Reported-by: default avatarMin Guo <min.guo@mediatek.com>
Link: https://lore.kernel.org/r/20230119033322.21426-1-chunfeng.yun@mediatek.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3e679bde
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -133,10 +133,9 @@ static int mtu3_ep_disable(struct mtu3_ep *mep)
{
{
	struct mtu3 *mtu = mep->mtu;
	struct mtu3 *mtu = mep->mtu;


	mtu3_qmu_stop(mep);

	/* abort all pending requests */
	/* abort all pending requests */
	nuke(mep, -ESHUTDOWN);
	nuke(mep, -ESHUTDOWN);
	mtu3_qmu_stop(mep);
	mtu3_deconfig_ep(mtu, mep);
	mtu3_deconfig_ep(mtu, mep);
	mtu3_gpd_ring_free(mep);
	mtu3_gpd_ring_free(mep);


+1 −0
Original line number Original line Diff line number Diff line
@@ -128,6 +128,7 @@
#define TX_FIFOEMPTY		BIT(24)
#define TX_FIFOEMPTY		BIT(24)
#define TX_SENTSTALL		BIT(22)
#define TX_SENTSTALL		BIT(22)
#define TX_SENDSTALL		BIT(21)
#define TX_SENDSTALL		BIT(21)
#define TX_FLUSHFIFO		BIT(20)
#define TX_TXPKTRDY		BIT(16)
#define TX_TXPKTRDY		BIT(16)
#define TX_TXMAXPKTSZ_MSK	GENMASK(10, 0)
#define TX_TXMAXPKTSZ_MSK	GENMASK(10, 0)
#define TX_TXMAXPKTSZ(x)	((x) & TX_TXMAXPKTSZ_MSK)
#define TX_TXMAXPKTSZ(x)	((x) & TX_TXMAXPKTSZ_MSK)
+7 −0
Original line number Original line Diff line number Diff line
@@ -388,6 +388,9 @@ void mtu3_qmu_stop(struct mtu3_ep *mep)
	}
	}
	mtu3_writel(mbase, qcsr, QMU_Q_STOP);
	mtu3_writel(mbase, qcsr, QMU_Q_STOP);


	if (mep->is_in)
		mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_FLUSHFIFO);

	ret = readl_poll_timeout_atomic(mbase + qcsr, value,
	ret = readl_poll_timeout_atomic(mbase + qcsr, value,
			!(value & QMU_Q_ACTIVE), 1, 1000);
			!(value & QMU_Q_ACTIVE), 1, 1000);
	if (ret) {
	if (ret) {
@@ -395,6 +398,10 @@ void mtu3_qmu_stop(struct mtu3_ep *mep)
		return;
		return;
	}
	}


	/* flush fifo again to make sure the fifo is empty */
	if (mep->is_in)
		mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_FLUSHFIFO);

	dev_dbg(mtu->dev, "%s's qmu stop now!\n", mep->name);
	dev_dbg(mtu->dev, "%s's qmu stop now!\n", mep->name);
}
}