Skip to content

Commit 017dbfc

Browse files
Chunfeng Yungregkh
authored andcommitted
usb: xhci-mtk: fix a short packet issue of gen1 isoc-in transfer
For Gen1 isoc-in transfer, host still send out unexpected ACK after device finish the burst with a short packet, this will cause an exception on the connected device, such as, a usb 4k camera. It can be fixed by setting rxfifo depth less than 4k bytes, prefer to use 3k here, the side-effect is that may cause performance drop about 10%, including bulk transfer. Fixes: 926d60a ("usb: xhci-mtk: modify the SOF/ITP interval for mt8195") Reviewed-by: AngeloGioacchino Del Regno <[email protected]> Signed-off-by: Chunfeng Yun <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 223b4ef commit 017dbfc

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

drivers/usb/host/xhci-mtk.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* Chunfeng Yun <[email protected]>
88
*/
99

10+
#include <linux/bitfield.h>
1011
#include <linux/dma-mapping.h>
1112
#include <linux/iopoll.h>
1213
#include <linux/kernel.h>
@@ -73,6 +74,9 @@
7374
#define FRMCNT_LEV1_RANG (0x12b << 8)
7475
#define FRMCNT_LEV1_RANG_MASK GENMASK(19, 8)
7576

77+
#define HSCH_CFG1 0x960
78+
#define SCH3_RXFIFO_DEPTH_MASK GENMASK(21, 20)
79+
7680
#define SS_GEN2_EOF_CFG 0x990
7781
#define SSG2EOF_OFFSET 0x3c
7882

@@ -114,6 +118,8 @@
114118
#define SSC_IP_SLEEP_EN BIT(4)
115119
#define SSC_SPM_INT_EN BIT(1)
116120

121+
#define SCH_FIFO_TO_KB(x) ((x) >> 10)
122+
117123
enum ssusb_uwk_vers {
118124
SSUSB_UWK_V1 = 1,
119125
SSUSB_UWK_V2,
@@ -165,6 +171,35 @@ static void xhci_mtk_set_frame_interval(struct xhci_hcd_mtk *mtk)
165171
writel(value, hcd->regs + SS_GEN2_EOF_CFG);
166172
}
167173

174+
/*
175+
* workaround: usb3.2 gen1 isoc rx hw issue
176+
* host send out unexpected ACK afer device fininsh a burst transfer with
177+
* a short packet.
178+
*/
179+
static void xhci_mtk_rxfifo_depth_set(struct xhci_hcd_mtk *mtk)
180+
{
181+
struct usb_hcd *hcd = mtk->hcd;
182+
u32 value;
183+
184+
if (!mtk->rxfifo_depth)
185+
return;
186+
187+
value = readl(hcd->regs + HSCH_CFG1);
188+
value &= ~SCH3_RXFIFO_DEPTH_MASK;
189+
value |= FIELD_PREP(SCH3_RXFIFO_DEPTH_MASK,
190+
SCH_FIFO_TO_KB(mtk->rxfifo_depth) - 1);
191+
writel(value, hcd->regs + HSCH_CFG1);
192+
}
193+
194+
static void xhci_mtk_init_quirk(struct xhci_hcd_mtk *mtk)
195+
{
196+
/* workaround only for mt8195 */
197+
xhci_mtk_set_frame_interval(mtk);
198+
199+
/* workaround for SoCs using SSUSB about before IPM v1.6.0 */
200+
xhci_mtk_rxfifo_depth_set(mtk);
201+
}
202+
168203
static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
169204
{
170205
struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
@@ -448,8 +483,7 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
448483
if (ret)
449484
return ret;
450485

451-
/* workaround only for mt8195 */
452-
xhci_mtk_set_frame_interval(mtk);
486+
xhci_mtk_init_quirk(mtk);
453487
}
454488

455489
ret = xhci_gen_setup(hcd, xhci_mtk_quirks);
@@ -527,6 +561,8 @@ static int xhci_mtk_probe(struct platform_device *pdev)
527561
of_property_read_u32(node, "mediatek,u2p-dis-msk",
528562
&mtk->u2p_dis_msk);
529563

564+
of_property_read_u32(node, "rx-fifo-depth", &mtk->rxfifo_depth);
565+
530566
ret = usb_wakeup_of_property_parse(mtk, node);
531567
if (ret) {
532568
dev_err(dev, "failed to parse uwk property\n");

drivers/usb/host/xhci-mtk.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ struct xhci_hcd_mtk {
171171
struct regmap *uwk;
172172
u32 uwk_reg_base;
173173
u32 uwk_vers;
174+
/* quirk */
175+
u32 rxfifo_depth;
174176
};
175177

176178
static inline struct xhci_hcd_mtk *hcd_to_mtk(struct usb_hcd *hcd)

0 commit comments

Comments
 (0)