--- /dev/null
+From 566de723a12a67f70e5c839e9fa9cd401ab3be9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 16 Oct 2022 11:05:32 +0800
+Subject: bus: mhi: host: Fix race between channel preparation and M0 event
+
+From: Qiang Yu <quic_qianyu@quicinc.com>
+
+[ Upstream commit 869a99907faea6d1835b0bd0d0422ae3519c6ea9 ]
+
+There is a race condition where mhi_prepare_channel() updates the
+read and write pointers as the base address and in parallel, if
+an M0 transition occurs, the tasklet goes ahead and rings
+doorbells for all channels with a delta in TRE rings assuming
+they are already enabled. This causes a null pointer access. Fix
+it by adding a channel enabled check before ringing channel
+doorbells.
+
+Cc: stable@vger.kernel.org # 5.19
+Fixes: a6e2e3522f29 "bus: mhi: core: Add support for PM state transitions"
+Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
+Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
+Link: https://lore.kernel.org/r/1665889532-13634-1-git-send-email-quic_qianyu@quicinc.com
+[mani: CCed stable list]
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bus/mhi/core/pm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
+index 044dcdd723a7..7d69b740b9f9 100644
+--- a/drivers/bus/mhi/core/pm.c
++++ b/drivers/bus/mhi/core/pm.c
+@@ -298,7 +298,8 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl)
+ read_lock_irq(&mhi_chan->lock);
+
+ /* Only ring DB if ring is not empty */
+- if (tre_ring->base && tre_ring->wp != tre_ring->rp)
++ if (tre_ring->base && tre_ring->wp != tre_ring->rp &&
++ mhi_chan->ch_state == MHI_CH_STATE_ENABLED)
+ mhi_ring_chan_db(mhi_cntrl, mhi_chan);
+ read_unlock_irq(&mhi_chan->lock);
+ }
+--
+2.35.1
+
--- /dev/null
+From d595e40aee8722550fb056a9e739a722734f5e46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 Sep 2022 22:54:22 +0800
+Subject: clk: imx: imx8mp: add shared clk gate for usb suspend clk
+
+From: Li Jun <jun.li@nxp.com>
+
+[ Upstream commit ed1f4ccfe947a3e1018a3bd7325134574c7ff9b3 ]
+
+32K usb suspend clock gate is shared with usb_root_clk, this
+shared clock gate was initially defined only for usb suspend
+clock, usb suspend clk is kept on while system is active or
+system sleep with usb wakeup enabled, so usb root clock is
+fine with this situation; with the commit cf7f3f4fa9e5
+("clk: imx8mp: fix usb_root_clk parent"), this clock gate is
+changed to be for usb root clock, but usb root clock will
+be off while usb is suspended, so usb suspend clock will be
+gated too, this cause some usb functionalities will not work,
+so define this clock to be a shared clock gate to conform with
+the real HW status.
+
+Fixes: 9c140d9926761 ("clk: imx: Add support for i.MX8MP clock driver")
+Cc: stable@vger.kernel.org # v5.19+
+Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Signed-off-by: Li Jun <jun.li@nxp.com>
+Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
+Link: https://lore.kernel.org/r/1664549663-20364-2-git-send-email-jun.li@nxp.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/imx/clk-imx8mp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
+index 187044b98bde..72592e35836b 100644
+--- a/drivers/clk/imx/clk-imx8mp.c
++++ b/drivers/clk/imx/clk-imx8mp.c
+@@ -17,6 +17,7 @@
+
+ static u32 share_count_nand;
+ static u32 share_count_media;
++static u32 share_count_usb;
+
+ static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
+ static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+@@ -706,7 +707,8 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
+ hws[IMX8MP_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", ccm_base + 0x44a0, 0);
+ hws[IMX8MP_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", ccm_base + 0x44b0, 0);
+ hws[IMX8MP_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", ccm_base + 0x44c0, 0);
+- hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate4("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0);
++ hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate2_shared2("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0, &share_count_usb);
++ hws[IMX8MP_CLK_USB_SUSP] = imx_clk_hw_gate2_shared2("usb_suspend_clk", "osc_32k", ccm_base + 0x44d0, 0, &share_count_usb);
+ hws[IMX8MP_CLK_USB_PHY_ROOT] = imx_clk_hw_gate4("usb_phy_root_clk", "usb_phy_ref", ccm_base + 0x44f0, 0);
+ hws[IMX8MP_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", ccm_base + 0x4510, 0);
+ hws[IMX8MP_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", ccm_base + 0x4520, 0);
+--
+2.35.1
+
--- /dev/null
+From af13d19faf568dbf1ea31e5249ba88485d3e714e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Apr 2022 18:21:31 +0200
+Subject: clk: imx8mp: add clkout1/2 support
+
+From: Lucas Stach <l.stach@pengutronix.de>
+
+[ Upstream commit 43896f56b59eeaf08687fa976257ae7083d01b41 ]
+
+clkout1 and clkout2 allow to supply clocks from the SoC to the board,
+which is used by some board designs to provide reference clocks.
+
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Reviewed-by: Abel Vesa <abel.vesa@nxp.com>
+Link: https://lore.kernel.org/r/20220427162131.3127303-1-l.stach@pengutronix.de
+Signed-off-by: Abel Vesa <abel.vesa@nxp.com>
+Stable-dep-of: 5c1f7f109094 ("dt-bindings: clocks: imx8mp: Add ID for usb suspend clock")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/imx/clk-imx8mp.c | 14 ++++++++++++++
+ include/dt-bindings/clock/imx8mp-clock.h | 9 +++++++--
+ 2 files changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
+index 2af39c8240fa..187044b98bde 100644
+--- a/drivers/clk/imx/clk-imx8mp.c
++++ b/drivers/clk/imx/clk-imx8mp.c
+@@ -411,6 +411,11 @@ static const char * const imx8mp_sai7_sels[] = {"osc_24m", "audio_pll1_out", "au
+
+ static const char * const imx8mp_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
+
++static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out",
++ "dummy", "dummy", "gpu_pll_out", "vpu_pll_out",
++ "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
++ "dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
++
+ static struct clk_hw **hws;
+ static struct clk_hw_onecell_data *clk_hw_data;
+
+@@ -532,6 +537,15 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
+ hws[IMX8MP_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2);
+ hws[IMX8MP_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
+
++ hws[IMX8MP_CLK_CLKOUT1_SEL] = imx_clk_hw_mux2("clkout1_sel", anatop_base + 0x128, 4, 4,
++ imx8mp_clkout_sels, ARRAY_SIZE(imx8mp_clkout_sels));
++ hws[IMX8MP_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", anatop_base + 0x128, 0, 4);
++ hws[IMX8MP_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", anatop_base + 0x128, 8);
++ hws[IMX8MP_CLK_CLKOUT2_SEL] = imx_clk_hw_mux2("clkout2_sel", anatop_base + 0x128, 20, 4,
++ imx8mp_clkout_sels, ARRAY_SIZE(imx8mp_clkout_sels));
++ hws[IMX8MP_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", anatop_base + 0x128, 16, 4);
++ hws[IMX8MP_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", anatop_base + 0x128, 24);
++
+ hws[IMX8MP_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mp_a53_sels, ccm_base + 0x8000);
+ hws[IMX8MP_CLK_A53_SRC] = hws[IMX8MP_CLK_A53_DIV];
+ hws[IMX8MP_CLK_A53_CG] = hws[IMX8MP_CLK_A53_DIV];
+diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h
+index 4a621fddfcd3..0ba16b76eb2f 100644
+--- a/include/dt-bindings/clock/imx8mp-clock.h
++++ b/include/dt-bindings/clock/imx8mp-clock.h
+@@ -321,10 +321,15 @@
+ #define IMX8MP_CLK_AUDIO_AXI 310
+ #define IMX8MP_CLK_HSIO_AXI 311
+ #define IMX8MP_CLK_MEDIA_ISP 312
+-
+ #define IMX8MP_CLK_MEDIA_DISP2_PIX 313
++#define IMX8MP_CLK_CLKOUT1_SEL 314
++#define IMX8MP_CLK_CLKOUT1_DIV 315
++#define IMX8MP_CLK_CLKOUT1 316
++#define IMX8MP_CLK_CLKOUT2_SEL 317
++#define IMX8MP_CLK_CLKOUT2_DIV 318
++#define IMX8MP_CLK_CLKOUT2 319
+
+-#define IMX8MP_CLK_END 314
++#define IMX8MP_CLK_END 320
+
+ #define IMX8MP_CLK_AUDIOMIX_SAI1_IPG 0
+ #define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1 1
+--
+2.35.1
+
--- /dev/null
+From a0341e40173d7f5316f2fed0e32de671d17a6103 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 13 Mar 2022 13:39:49 +0100
+Subject: clk: imx8mp: Add DISP2 pixel clock
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit 39772efd98adecbd5b8c6096d465d2fcbafbde6a ]
+
+Add pixel clock for second LCDIFv3 interface. Both LCDIFv3 interfaces use
+the same set of parent clock, so deduplicate imx8mp_media_disp1_pix_sels
+into common imx8mp_media_disp_pix_sels and use it for both.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Cc: Abel Vesa <abel.vesa@nxp.com>
+Cc: Fabio Estevam <festevam@gmail.com>
+Cc: NXP Linux Team <linux-imx@nxp.com>
+Cc: Peng Fan <peng.fan@nxp.com>
+Cc: Shawn Guo <shawnguo@kernel.org>
+Reviewed-by: Abel Vesa <abel.vesa@nxp.com>
+Link: https://lore.kernel.org/r/20220313123949.207284-1-marex@denx.de
+Signed-off-by: Abel Vesa <abel.vesa@nxp.com>
+Stable-dep-of: 5c1f7f109094 ("dt-bindings: clocks: imx8mp: Add ID for usb suspend clock")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/imx/clk-imx8mp.c | 5 +++--
+ include/dt-bindings/clock/imx8mp-clock.h | 4 +++-
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
+index 36e8d619e334..2af39c8240fa 100644
+--- a/drivers/clk/imx/clk-imx8mp.c
++++ b/drivers/clk/imx/clk-imx8mp.c
+@@ -362,7 +362,7 @@ static const char * const imx8mp_media_mipi_phy1_ref_sels[] = {"osc_24m", "sys_p
+ "clk_ext2", "audio_pll2_out",
+ "video_pll1_out", };
+
+-static const char * const imx8mp_media_disp1_pix_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out",
++static const char * const imx8mp_media_disp_pix_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out",
+ "audio_pll1_out", "sys_pll1_800m",
+ "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
+
+@@ -566,6 +566,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
+ hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000);
+ hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100);
+ hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200);
++ hws[IMX8MP_CLK_MEDIA_DISP2_PIX] = imx8m_clk_hw_composite("media_disp2_pix", imx8mp_media_disp_pix_sels, ccm_base + 0x9300);
+
+ hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1);
+ hws[IMX8MP_CLK_IPG_AUDIO_ROOT] = imx_clk_hw_divider2("ipg_audio_root", "audio_ahb", ccm_base + 0x9180, 0, 1);
+@@ -630,7 +631,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
+ hws[IMX8MP_CLK_USDHC3] = imx8m_clk_hw_composite("usdhc3", imx8mp_usdhc3_sels, ccm_base + 0xbc80);
+ hws[IMX8MP_CLK_MEDIA_CAM1_PIX] = imx8m_clk_hw_composite("media_cam1_pix", imx8mp_media_cam1_pix_sels, ccm_base + 0xbd00);
+ hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF] = imx8m_clk_hw_composite("media_mipi_phy1_ref", imx8mp_media_mipi_phy1_ref_sels, ccm_base + 0xbd80);
+- hws[IMX8MP_CLK_MEDIA_DISP1_PIX] = imx8m_clk_hw_composite("media_disp1_pix", imx8mp_media_disp1_pix_sels, ccm_base + 0xbe00);
++ hws[IMX8MP_CLK_MEDIA_DISP1_PIX] = imx8m_clk_hw_composite("media_disp1_pix", imx8mp_media_disp_pix_sels, ccm_base + 0xbe00);
+ hws[IMX8MP_CLK_MEDIA_CAM2_PIX] = imx8m_clk_hw_composite("media_cam2_pix", imx8mp_media_cam2_pix_sels, ccm_base + 0xbe80);
+ hws[IMX8MP_CLK_MEDIA_LDB] = imx8m_clk_hw_composite("media_ldb", imx8mp_media_ldb_sels, ccm_base + 0xbf00);
+ hws[IMX8MP_CLK_MEMREPAIR] = imx8m_clk_hw_composite_critical("mem_repair", imx8mp_memrepair_sels, ccm_base + 0xbf80);
+diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h
+index e8d68fbb6e3f..4a621fddfcd3 100644
+--- a/include/dt-bindings/clock/imx8mp-clock.h
++++ b/include/dt-bindings/clock/imx8mp-clock.h
+@@ -322,7 +322,9 @@
+ #define IMX8MP_CLK_HSIO_AXI 311
+ #define IMX8MP_CLK_MEDIA_ISP 312
+
+-#define IMX8MP_CLK_END 313
++#define IMX8MP_CLK_MEDIA_DISP2_PIX 313
++
++#define IMX8MP_CLK_END 314
+
+ #define IMX8MP_CLK_AUDIOMIX_SAI1_IPG 0
+ #define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1 1
+--
+2.35.1
+
--- /dev/null
+From 11dd67b938adc87c404f897682fc7315643e00aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 Sep 2022 22:54:21 +0800
+Subject: dt-bindings: clocks: imx8mp: Add ID for usb suspend clock
+
+From: Li Jun <jun.li@nxp.com>
+
+[ Upstream commit 5c1f7f1090947d494c30042123e0ec846f696336 ]
+
+usb suspend clock has a gate shared with usb_root_clk.
+
+Fixes: 9c140d9926761 ("clk: imx: Add support for i.MX8MP clock driver")
+Cc: stable@vger.kernel.org # v5.19+
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Signed-off-by: Li Jun <jun.li@nxp.com>
+Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
+Link: https://lore.kernel.org/r/1664549663-20364-1-git-send-email-jun.li@nxp.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/dt-bindings/clock/imx8mp-clock.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h
+index 0ba16b76eb2f..d7e513243dd2 100644
+--- a/include/dt-bindings/clock/imx8mp-clock.h
++++ b/include/dt-bindings/clock/imx8mp-clock.h
+@@ -328,8 +328,9 @@
+ #define IMX8MP_CLK_CLKOUT2_SEL 317
+ #define IMX8MP_CLK_CLKOUT2_DIV 318
+ #define IMX8MP_CLK_CLKOUT2 319
++#define IMX8MP_CLK_USB_SUSP 320
+
+-#define IMX8MP_CLK_END 320
++#define IMX8MP_CLK_END 321
+
+ #define IMX8MP_CLK_AUDIOMIX_SAI1_IPG 0
+ #define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1 1
+--
+2.35.1
+
--- /dev/null
+From ecb19c78b1c8920fe5ee45c5a9356706da1593c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 15:36:03 +0800
+Subject: ext4: fix uninititialized value in 'ext4_evict_inode'
+
+From: Ye Bin <yebin10@huawei.com>
+
+[ Upstream commit 7ea71af94eaaaf6d9aed24bc94a05b977a741cb9 ]
+
+Syzbot found the following issue:
+=====================================================
+BUG: KMSAN: uninit-value in ext4_evict_inode+0xdd/0x26b0 fs/ext4/inode.c:180
+ ext4_evict_inode+0xdd/0x26b0 fs/ext4/inode.c:180
+ evict+0x365/0x9a0 fs/inode.c:664
+ iput_final fs/inode.c:1747 [inline]
+ iput+0x985/0xdd0 fs/inode.c:1773
+ __ext4_new_inode+0xe54/0x7ec0 fs/ext4/ialloc.c:1361
+ ext4_mknod+0x376/0x840 fs/ext4/namei.c:2844
+ vfs_mknod+0x79d/0x830 fs/namei.c:3914
+ do_mknodat+0x47d/0xaa0
+ __do_sys_mknodat fs/namei.c:3992 [inline]
+ __se_sys_mknodat fs/namei.c:3989 [inline]
+ __ia32_sys_mknodat+0xeb/0x150 fs/namei.c:3989
+ do_syscall_32_irqs_on arch/x86/entry/common.c:112 [inline]
+ __do_fast_syscall_32+0xa2/0x100 arch/x86/entry/common.c:178
+ do_fast_syscall_32+0x33/0x70 arch/x86/entry/common.c:203
+ do_SYSENTER_32+0x1b/0x20 arch/x86/entry/common.c:246
+ entry_SYSENTER_compat_after_hwframe+0x70/0x82
+
+Uninit was created at:
+ __alloc_pages+0x9f1/0xe80 mm/page_alloc.c:5578
+ alloc_pages+0xaae/0xd80 mm/mempolicy.c:2285
+ alloc_slab_page mm/slub.c:1794 [inline]
+ allocate_slab+0x1b5/0x1010 mm/slub.c:1939
+ new_slab mm/slub.c:1992 [inline]
+ ___slab_alloc+0x10c3/0x2d60 mm/slub.c:3180
+ __slab_alloc mm/slub.c:3279 [inline]
+ slab_alloc_node mm/slub.c:3364 [inline]
+ slab_alloc mm/slub.c:3406 [inline]
+ __kmem_cache_alloc_lru mm/slub.c:3413 [inline]
+ kmem_cache_alloc_lru+0x6f3/0xb30 mm/slub.c:3429
+ alloc_inode_sb include/linux/fs.h:3117 [inline]
+ ext4_alloc_inode+0x5f/0x860 fs/ext4/super.c:1321
+ alloc_inode+0x83/0x440 fs/inode.c:259
+ new_inode_pseudo fs/inode.c:1018 [inline]
+ new_inode+0x3b/0x430 fs/inode.c:1046
+ __ext4_new_inode+0x2a7/0x7ec0 fs/ext4/ialloc.c:959
+ ext4_mkdir+0x4d5/0x1560 fs/ext4/namei.c:2992
+ vfs_mkdir+0x62a/0x870 fs/namei.c:4035
+ do_mkdirat+0x466/0x7b0 fs/namei.c:4060
+ __do_sys_mkdirat fs/namei.c:4075 [inline]
+ __se_sys_mkdirat fs/namei.c:4073 [inline]
+ __ia32_sys_mkdirat+0xc4/0x120 fs/namei.c:4073
+ do_syscall_32_irqs_on arch/x86/entry/common.c:112 [inline]
+ __do_fast_syscall_32+0xa2/0x100 arch/x86/entry/common.c:178
+ do_fast_syscall_32+0x33/0x70 arch/x86/entry/common.c:203
+ do_SYSENTER_32+0x1b/0x20 arch/x86/entry/common.c:246
+ entry_SYSENTER_compat_after_hwframe+0x70/0x82
+
+CPU: 1 PID: 4625 Comm: syz-executor.2 Not tainted 6.1.0-rc4-syzkaller-62821-gcb231e2f67ec #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
+=====================================================
+
+Now, 'ext4_alloc_inode()' didn't init 'ei->i_flags'. If new inode failed
+before set 'ei->i_flags' in '__ext4_new_inode()', then do 'iput()'. As after
+6bc0d63dad7f commit will access 'ei->i_flags' in 'ext4_evict_inode()' which
+will lead to access uninit-value.
+To solve above issue just init 'ei->i_flags' in 'ext4_alloc_inode()'.
+
+Reported-by: syzbot+57b25da729eb0b88177d@syzkaller.appspotmail.com
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Fixes: 6bc0d63dad7f ("ext4: remove EA inode entry from mbcache on inode eviction")
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Eric Biggers <ebiggers@google.com>
+Link: https://lore.kernel.org/r/20221117073603.2598882-1-yebin@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/super.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 935589579b8f..e940fb07ef2e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1279,6 +1279,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ return NULL;
+
+ inode_set_iversion(&ei->vfs_inode, 1);
++ ei->i_flags = 0;
+ spin_lock_init(&ei->i_raw_lock);
+ INIT_LIST_HEAD(&ei->i_prealloc_list);
+ atomic_set(&ei->i_prealloc_active, 0);
+--
+2.35.1
+
--- /dev/null
+From fb7e49a1636534a029b41bafda6f748a53b9d4a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Jul 2022 17:08:22 +0530
+Subject: iommu/amd: Add PCI segment support for ivrs_[ioapic/hpet/acpihid]
+ commands
+
+From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+
+[ Upstream commit bbe3a106580c21bc883fb0c9fa3da01534392fe8 ]
+
+By default, PCI segment is zero and can be omitted. To support system
+with non-zero PCI segment ID, modify the parsing functions to allow
+PCI segment ID.
+
+Co-developed-by: Vasant Hegde <vasant.hegde@amd.com>
+Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
+Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Link: https://lore.kernel.org/r/20220706113825.25582-33-vasant.hegde@amd.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: 1198d2316dc4 ("iommu/amd: Fix ill-formed ivrs_ioapic, ivrs_hpet and ivrs_acpihid options")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../admin-guide/kernel-parameters.txt | 34 ++++++++++----
+ drivers/iommu/amd/init.c | 44 ++++++++++++-------
+ 2 files changed, 52 insertions(+), 26 deletions(-)
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index f577c29f2093..ce93bb358bc1 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -2103,23 +2103,39 @@
+
+ ivrs_ioapic [HW,X86-64]
+ Provide an override to the IOAPIC-ID<->DEVICE-ID
+- mapping provided in the IVRS ACPI table. For
+- example, to map IOAPIC-ID decimal 10 to
+- PCI device 00:14.0 write the parameter as:
++ mapping provided in the IVRS ACPI table.
++ By default, PCI segment is 0, and can be omitted.
++ For example:
++ * To map IOAPIC-ID decimal 10 to PCI device 00:14.0
++ write the parameter as:
+ ivrs_ioapic[10]=00:14.0
++ * To map IOAPIC-ID decimal 10 to PCI segment 0x1 and
++ PCI device 00:14.0 write the parameter as:
++ ivrs_ioapic[10]=0001:00:14.0
+
+ ivrs_hpet [HW,X86-64]
+ Provide an override to the HPET-ID<->DEVICE-ID
+- mapping provided in the IVRS ACPI table. For
+- example, to map HPET-ID decimal 0 to
+- PCI device 00:14.0 write the parameter as:
++ mapping provided in the IVRS ACPI table.
++ By default, PCI segment is 0, and can be omitted.
++ For example:
++ * To map HPET-ID decimal 0 to PCI device 00:14.0
++ write the parameter as:
+ ivrs_hpet[0]=00:14.0
++ * To map HPET-ID decimal 10 to PCI segment 0x1 and
++ PCI device 00:14.0 write the parameter as:
++ ivrs_ioapic[10]=0001:00:14.0
+
+ ivrs_acpihid [HW,X86-64]
+ Provide an override to the ACPI-HID:UID<->DEVICE-ID
+- mapping provided in the IVRS ACPI table. For
+- example, to map UART-HID:UID AMD0020:0 to
+- PCI device 00:14.5 write the parameter as:
++ mapping provided in the IVRS ACPI table.
++
++ For example, to map UART-HID:UID AMD0020:0 to
++ PCI segment 0x1 and PCI device ID 00:14.5,
++ write the parameter as:
++ ivrs_acpihid[0001:00:14.5]=AMD0020:0
++
++ By default, PCI segment is 0, and can be omitted.
++ For example, PCI device 00:14.5 write the parameter as:
+ ivrs_acpihid[00:14.5]=AMD0020:0
+
+ js= [HW,JOY] Analog joystick
+diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
+index 310ab24d003a..85370f305aa8 100644
+--- a/drivers/iommu/amd/init.c
++++ b/drivers/iommu/amd/init.c
+@@ -85,6 +85,10 @@
+ #define ACPI_DEVFLAG_ATSDIS 0x10000000
+
+ #define LOOP_TIMEOUT 2000000
++
++#define IVRS_GET_SBDF_ID(seg, bus, dev, fd) (((seg & 0xffff) << 16) | ((bus & 0xff) << 8) \
++ | ((dev & 0x1f) << 3) | (fn & 0x7))
++
+ /*
+ * ACPI table definitions
+ *
+@@ -3046,15 +3050,17 @@ static int __init parse_amd_iommu_options(char *str)
+
+ static int __init parse_ivrs_ioapic(char *str)
+ {
+- unsigned int bus, dev, fn;
++ u32 seg = 0, bus, dev, fn;
+ int ret, id, i;
+- u16 devid;
++ u32 devid;
+
+ ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+-
+ if (ret != 4) {
+- pr_err("Invalid command line: ivrs_ioapic%s\n", str);
+- return 1;
++ ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn);
++ if (ret != 5) {
++ pr_err("Invalid command line: ivrs_ioapic%s\n", str);
++ return 1;
++ }
+ }
+
+ if (early_ioapic_map_size == EARLY_MAP_SIZE) {
+@@ -3063,7 +3069,7 @@ static int __init parse_ivrs_ioapic(char *str)
+ return 1;
+ }
+
+- devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
++ devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
+
+ cmdline_maps = true;
+ i = early_ioapic_map_size++;
+@@ -3076,15 +3082,17 @@ static int __init parse_ivrs_ioapic(char *str)
+
+ static int __init parse_ivrs_hpet(char *str)
+ {
+- unsigned int bus, dev, fn;
++ u32 seg = 0, bus, dev, fn;
+ int ret, id, i;
+- u16 devid;
++ u32 devid;
+
+ ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+-
+ if (ret != 4) {
+- pr_err("Invalid command line: ivrs_hpet%s\n", str);
+- return 1;
++ ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn);
++ if (ret != 5) {
++ pr_err("Invalid command line: ivrs_hpet%s\n", str);
++ return 1;
++ }
+ }
+
+ if (early_hpet_map_size == EARLY_MAP_SIZE) {
+@@ -3093,7 +3101,7 @@ static int __init parse_ivrs_hpet(char *str)
+ return 1;
+ }
+
+- devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
++ devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
+
+ cmdline_maps = true;
+ i = early_hpet_map_size++;
+@@ -3106,15 +3114,18 @@ static int __init parse_ivrs_hpet(char *str)
+
+ static int __init parse_ivrs_acpihid(char *str)
+ {
+- u32 bus, dev, fn;
++ u32 seg = 0, bus, dev, fn;
+ char *hid, *uid, *p;
+ char acpiid[ACPIHID_UID_LEN + ACPIHID_HID_LEN] = {0};
+ int ret, i;
+
+ ret = sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid);
+ if (ret != 4) {
+- pr_err("Invalid command line: ivrs_acpihid(%s)\n", str);
+- return 1;
++ ret = sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid);
++ if (ret != 5) {
++ pr_err("Invalid command line: ivrs_acpihid(%s)\n", str);
++ return 1;
++ }
+ }
+
+ p = acpiid;
+@@ -3136,8 +3147,7 @@ static int __init parse_ivrs_acpihid(char *str)
+ i = early_acpihid_map_size++;
+ memcpy(early_acpihid_map[i].hid, hid, strlen(hid));
+ memcpy(early_acpihid_map[i].uid, uid, strlen(uid));
+- early_acpihid_map[i].devid =
+- ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
++ early_acpihid_map[i].devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
+ early_acpihid_map[i].cmd_line = true;
+
+ return 1;
+--
+2.35.1
+
--- /dev/null
+From dde85fa0d916e51ca426ff180c52014de65de714 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Sep 2022 10:56:38 -0500
+Subject: iommu/amd: Fix ill-formed ivrs_ioapic, ivrs_hpet and ivrs_acpihid
+ options
+
+From: Kim Phillips <kim.phillips@amd.com>
+
+[ Upstream commit 1198d2316dc4265a97d0e8445a22c7a6d17580a4 ]
+
+Currently, these options cause the following libkmod error:
+
+libkmod: ERROR ../libkmod/libkmod-config.c:489 kcmdline_parse_result: \
+ Ignoring bad option on kernel command line while parsing module \
+ name: 'ivrs_xxxx[XX:XX'
+
+Fix by introducing a new parameter format for these options and
+throw a warning for the deprecated format.
+
+Users are still allowed to omit the PCI Segment if zero.
+
+Adding a Link: to the reason why we're modding the syntax parsing
+in the driver and not in libkmod.
+
+Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter")
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/linux-modules/20200310082308.14318-2-lucas.demarchi@intel.com/
+Reported-by: Kim Phillips <kim.phillips@amd.com>
+Co-developed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Signed-off-by: Kim Phillips <kim.phillips@amd.com>
+Link: https://lore.kernel.org/r/20220919155638.391481-2-kim.phillips@amd.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../admin-guide/kernel-parameters.txt | 27 +++++--
+ drivers/iommu/amd/init.c | 79 +++++++++++++------
+ 2 files changed, 76 insertions(+), 30 deletions(-)
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index ce93bb358bc1..eb437d659f2c 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -2105,7 +2105,13 @@
+ Provide an override to the IOAPIC-ID<->DEVICE-ID
+ mapping provided in the IVRS ACPI table.
+ By default, PCI segment is 0, and can be omitted.
+- For example:
++
++ For example, to map IOAPIC-ID decimal 10 to
++ PCI segment 0x1 and PCI device 00:14.0,
++ write the parameter as:
++ ivrs_ioapic=10@0001:00:14.0
++
++ Deprecated formats:
+ * To map IOAPIC-ID decimal 10 to PCI device 00:14.0
+ write the parameter as:
+ ivrs_ioapic[10]=00:14.0
+@@ -2117,7 +2123,13 @@
+ Provide an override to the HPET-ID<->DEVICE-ID
+ mapping provided in the IVRS ACPI table.
+ By default, PCI segment is 0, and can be omitted.
+- For example:
++
++ For example, to map HPET-ID decimal 10 to
++ PCI segment 0x1 and PCI device 00:14.0,
++ write the parameter as:
++ ivrs_hpet=10@0001:00:14.0
++
++ Deprecated formats:
+ * To map HPET-ID decimal 0 to PCI device 00:14.0
+ write the parameter as:
+ ivrs_hpet[0]=00:14.0
+@@ -2128,15 +2140,20 @@
+ ivrs_acpihid [HW,X86-64]
+ Provide an override to the ACPI-HID:UID<->DEVICE-ID
+ mapping provided in the IVRS ACPI table.
++ By default, PCI segment is 0, and can be omitted.
+
+ For example, to map UART-HID:UID AMD0020:0 to
+ PCI segment 0x1 and PCI device ID 00:14.5,
+ write the parameter as:
+- ivrs_acpihid[0001:00:14.5]=AMD0020:0
++ ivrs_acpihid=AMD0020:0@0001:00:14.5
+
+- By default, PCI segment is 0, and can be omitted.
+- For example, PCI device 00:14.5 write the parameter as:
++ Deprecated formats:
++ * To map UART-HID:UID AMD0020:0 to PCI segment is 0,
++ PCI device ID 00:14.5, write the parameter as:
+ ivrs_acpihid[00:14.5]=AMD0020:0
++ * To map UART-HID:UID AMD0020:0 to PCI segment 0x1 and
++ PCI device ID 00:14.5, write the parameter as:
++ ivrs_acpihid[0001:00:14.5]=AMD0020:0
+
+ js= [HW,JOY] Analog joystick
+ See Documentation/input/joydev/joystick.rst.
+diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
+index 85370f305aa8..ce822347f747 100644
+--- a/drivers/iommu/amd/init.c
++++ b/drivers/iommu/amd/init.c
+@@ -3051,18 +3051,24 @@ static int __init parse_amd_iommu_options(char *str)
+ static int __init parse_ivrs_ioapic(char *str)
+ {
+ u32 seg = 0, bus, dev, fn;
+- int ret, id, i;
++ int id, i;
+ u32 devid;
+
+- ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+- if (ret != 4) {
+- ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn);
+- if (ret != 5) {
+- pr_err("Invalid command line: ivrs_ioapic%s\n", str);
+- return 1;
+- }
++ if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
++ sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5)
++ goto found;
++
++ if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
++ sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) {
++ pr_warn("ivrs_ioapic%s option format deprecated; use ivrs_ioapic=%d@%04x:%02x:%02x.%d instead\n",
++ str, id, seg, bus, dev, fn);
++ goto found;
+ }
+
++ pr_err("Invalid command line: ivrs_ioapic%s\n", str);
++ return 1;
++
++found:
+ if (early_ioapic_map_size == EARLY_MAP_SIZE) {
+ pr_err("Early IOAPIC map overflow - ignoring ivrs_ioapic%s\n",
+ str);
+@@ -3083,18 +3089,24 @@ static int __init parse_ivrs_ioapic(char *str)
+ static int __init parse_ivrs_hpet(char *str)
+ {
+ u32 seg = 0, bus, dev, fn;
+- int ret, id, i;
++ int id, i;
+ u32 devid;
+
+- ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+- if (ret != 4) {
+- ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn);
+- if (ret != 5) {
+- pr_err("Invalid command line: ivrs_hpet%s\n", str);
+- return 1;
+- }
++ if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
++ sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5)
++ goto found;
++
++ if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
++ sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) {
++ pr_warn("ivrs_hpet%s option format deprecated; use ivrs_hpet=%d@%04x:%02x:%02x.%d instead\n",
++ str, id, seg, bus, dev, fn);
++ goto found;
+ }
+
++ pr_err("Invalid command line: ivrs_hpet%s\n", str);
++ return 1;
++
++found:
+ if (early_hpet_map_size == EARLY_MAP_SIZE) {
+ pr_err("Early HPET map overflow - ignoring ivrs_hpet%s\n",
+ str);
+@@ -3115,19 +3127,36 @@ static int __init parse_ivrs_hpet(char *str)
+ static int __init parse_ivrs_acpihid(char *str)
+ {
+ u32 seg = 0, bus, dev, fn;
+- char *hid, *uid, *p;
++ char *hid, *uid, *p, *addr;
+ char acpiid[ACPIHID_UID_LEN + ACPIHID_HID_LEN] = {0};
+- int ret, i;
+-
+- ret = sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid);
+- if (ret != 4) {
+- ret = sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid);
+- if (ret != 5) {
+- pr_err("Invalid command line: ivrs_acpihid(%s)\n", str);
+- return 1;
++ int i;
++
++ addr = strchr(str, '@');
++ if (!addr) {
++ if (sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid) == 4 ||
++ sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid) == 5) {
++ pr_warn("ivrs_acpihid%s option format deprecated; use ivrs_acpihid=%s@%04x:%02x:%02x.%d instead\n",
++ str, acpiid, seg, bus, dev, fn);
++ goto found;
+ }
++ goto not_found;
+ }
+
++ /* We have the '@', make it the terminator to get just the acpiid */
++ *addr++ = 0;
++
++ if (sscanf(str, "=%s", acpiid) != 1)
++ goto not_found;
++
++ if (sscanf(addr, "%x:%x.%x", &bus, &dev, &fn) == 3 ||
++ sscanf(addr, "%x:%x:%x.%x", &seg, &bus, &dev, &fn) == 4)
++ goto found;
++
++not_found:
++ pr_err("Invalid command line: ivrs_acpihid%s\n", str);
++ return 1;
++
++found:
+ p = acpiid;
+ hid = strsep(&p, ":");
+ uid = p;
+--
+2.35.1
+
asoc-qcom-lpass-cpu-fix-fallback-sd-line-index-handling.patch
s390-cpum_sf-add-read_once-semantics-to-compare-and-swap-loops.patch
s390-percpu-add-read_once-to-arch_this_cpu_to_op_simple.patch
+bus-mhi-host-fix-race-between-channel-preparation-an.patch
+iommu-amd-add-pci-segment-support-for-ivrs_-ioapic-h.patch
+iommu-amd-fix-ill-formed-ivrs_ioapic-ivrs_hpet-and-i.patch
+clk-imx8mp-add-disp2-pixel-clock.patch
+clk-imx8mp-add-clkout1-2-support.patch
+dt-bindings-clocks-imx8mp-add-id-for-usb-suspend-clo.patch
+clk-imx-imx8mp-add-shared-clk-gate-for-usb-suspend-c.patch
+xhci-avoid-parsing-transfer-events-several-times.patch
+xhci-get-isochronous-ring-directly-from-endpoint-str.patch
+xhci-adjust-parameters-passed-to-cleanup_halted_endp.patch
+xhci-add-xhci_reset_halted_ep-helper-function.patch
+xhci-move-xhci_td_cleanup-so-it-can-be-called-by-mor.patch
+xhci-store-td-status-in-the-td-struct-instead-of-pas.patch
+xhci-move-and-rename-xhci_cleanup_halted_endpoint.patch
+xhci-prevent-infinite-loop-in-transaction-errors-rec.patch
+usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch
+ext4-fix-uninititialized-value-in-ext4_evict_inode.patch
--- /dev/null
+From eb5ff2547a8a34bc6c0b102f14b5cee50c045f2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Dec 2022 21:15:26 +0100
+Subject: usb: ulpi: defer ulpi_register on ulpi_read_id timeout
+
+From: Ferry Toth <ftoth@exalondelft.nl>
+
+[ Upstream commit 8a7b31d545d3a15f0e6f5984ae16f0ca4fd76aac ]
+
+Since commit 0f0101719138 ("usb: dwc3: Don't switch OTG -> peripheral
+if extcon is present") Dual Role support on Intel Merrifield platform
+broke due to rearranging the call to dwc3_get_extcon().
+
+It appears to be caused by ulpi_read_id() on the first test write failing
+with -ETIMEDOUT. Currently ulpi_read_id() expects to discover the phy via
+DT when the test write fails and returns 0 in that case, even if DT does not
+provide the phy. As a result usb probe completes without phy.
+
+Make ulpi_read_id() return -ETIMEDOUT to its user if the first test write
+fails. The user should then handle it appropriately. A follow up patch
+will make dwc3_core_init() set -EPROBE_DEFER in this case and bail out.
+
+Fixes: ef6a7bcfb01c ("usb: ulpi: Support device discovery via DT")
+Cc: stable@vger.kernel.org
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Ferry Toth <ftoth@exalondelft.nl>
+Link: https://lore.kernel.org/r/20221205201527.13525-2-ftoth@exalondelft.nl
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/common/ulpi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
+index 3c705f1bead8..1f077f2ea40f 100644
+--- a/drivers/usb/common/ulpi.c
++++ b/drivers/usb/common/ulpi.c
+@@ -208,7 +208,7 @@ static int ulpi_read_id(struct ulpi *ulpi)
+ /* Test the interface */
+ ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa);
+ if (ret < 0)
+- goto err;
++ return ret;
+
+ ret = ulpi_read(ulpi, ULPI_SCRATCH);
+ if (ret < 0)
+--
+2.35.1
+
--- /dev/null
+From c1b7975d93e4ff03e72349b2dc9e48ee49cc193c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Jan 2021 15:00:32 +0200
+Subject: xhci: Add xhci_reset_halted_ep() helper function
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit d8ac95001bea683d2088acb3e61613a27b8d2d5f ]
+
+Create a separate helper function to issue reset endpont commands
+to clear halted endpoints.
+
+This is useful for cases where a halted endpoint is discovered while
+completing another command, and the endpoint halt needs to be cleared
+with a endpoint reset first.
+
+No functional changes
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20210129130044.206855-16-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a1575120972e ("xhci: Prevent infinite loop in transaction errors recovery for streams")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 31 +++++++++++++++++++++++++------
+ 1 file changed, 25 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index a0d210d3a3c6..b4a510450ac2 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -773,6 +773,26 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
+ seg->bounce_offs = 0;
+ }
+
++static int xhci_reset_halted_ep(struct xhci_hcd *xhci, unsigned int slot_id,
++ unsigned int ep_index, enum xhci_ep_reset_type reset_type)
++{
++ struct xhci_command *command;
++ int ret = 0;
++
++ command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
++ if (!command) {
++ ret = -ENOMEM;
++ goto done;
++ }
++
++ ret = xhci_queue_reset_ep(xhci, command, slot_id, ep_index, reset_type);
++done:
++ if (ret)
++ xhci_err(xhci, "ERROR queuing reset endpoint for slot %d ep_index %d, %d\n",
++ slot_id, ep_index, ret);
++ return ret;
++}
++
+ /*
+ * When we get a command completion for a Stop Endpoint Command, we need to
+ * unlink any cancelled TDs from the ring. There are two ways to do that:
+@@ -1929,8 +1949,9 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
+ struct xhci_td *td,
+ enum xhci_ep_reset_type reset_type)
+ {
+- struct xhci_command *command;
+ unsigned int slot_id = ep->vdev->slot_id;
++ int err;
++
+ /*
+ * Avoid resetting endpoint if link is inactive. Can cause host hang.
+ * Device will be reset soon to recover the link so don't do anything
+@@ -1938,13 +1959,11 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
+ if (ep->vdev->flags & VDEV_PORT_ERROR)
+ return;
+
+- command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
+- if (!command)
+- return;
+-
+ ep->ep_state |= EP_HALTED;
+
+- xhci_queue_reset_ep(xhci, command, slot_id, ep->ep_index, reset_type);
++ err = xhci_reset_halted_ep(xhci, slot_id, ep->ep_index, reset_type);
++ if (err)
++ return;
+
+ if (reset_type == EP_HARD_RESET) {
+ ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
+--
+2.35.1
+
--- /dev/null
+From a143c99e8669f32c1df73b63de268b2352a990a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Jan 2021 15:00:20 +0200
+Subject: xhci: adjust parameters passed to cleanup_halted_endpoint()
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit d70f4231b81eeb6dd78bd913ff42729b524eec51 ]
+
+Instead of passing slot id and endpoint index to
+cleanup_halted_endpoint() pass the endpoint structure pointer
+as it's already known.
+
+Avoids again digging out the endpoint structure based on
+slot id and endpoint index, and passing them along the
+call chain for this purpose only.
+
+Add slot_id to the virt_dev structure so that it
+can easily be found from a virt_dev, or its child, the
+virt_ep endpoint structure.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20210129130044.206855-4-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a1575120972e ("xhci: Prevent infinite loop in transaction errors recovery for streams")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-mem.c | 2 ++
+ drivers/usb/host/xhci-ring.c | 35 ++++++++++++++---------------------
+ drivers/usb/host/xhci.h | 1 +
+ 3 files changed, 17 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index 002e4948993d..a8a9addb4d25 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1003,6 +1003,8 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
+ if (!dev)
+ return 0;
+
++ dev->slot_id = slot_id;
++
+ /* Allocate the (output) device context that will be used in the HC. */
+ dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags);
+ if (!dev->out_ctx)
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 6d34c56376e5..a0d210d3a3c6 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1925,13 +1925,12 @@ static void xhci_clear_hub_tt_buffer(struct xhci_hcd *xhci, struct xhci_td *td,
+ }
+
+ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
+- unsigned int slot_id, unsigned int ep_index,
+- unsigned int stream_id, struct xhci_td *td,
+- enum xhci_ep_reset_type reset_type)
++ struct xhci_virt_ep *ep, unsigned int stream_id,
++ struct xhci_td *td,
++ enum xhci_ep_reset_type reset_type)
+ {
+- struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
+ struct xhci_command *command;
+-
++ unsigned int slot_id = ep->vdev->slot_id;
+ /*
+ * Avoid resetting endpoint if link is inactive. Can cause host hang.
+ * Device will be reset soon to recover the link so don't do anything
+@@ -1945,11 +1944,11 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
+
+ ep->ep_state |= EP_HALTED;
+
+- xhci_queue_reset_ep(xhci, command, slot_id, ep_index, reset_type);
++ xhci_queue_reset_ep(xhci, command, slot_id, ep->ep_index, reset_type);
+
+ if (reset_type == EP_HARD_RESET) {
+ ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
+- xhci_cleanup_stalled_ring(xhci, slot_id, ep_index, stream_id,
++ xhci_cleanup_stalled_ring(xhci, slot_id, ep->ep_index, stream_id,
+ td);
+ }
+ xhci_ring_cmd_db(xhci);
+@@ -2047,10 +2046,8 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ {
+ struct xhci_ep_ctx *ep_ctx;
+ struct xhci_ring *ep_ring;
+- unsigned int slot_id;
+ u32 trb_comp_code;
+
+- slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+ ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index);
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
+@@ -2079,8 +2076,8 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ */
+ if ((ep->ep_index != 0) || (trb_comp_code != COMP_STALL_ERROR))
+ xhci_clear_hub_tt_buffer(xhci, td, ep);
+- xhci_cleanup_halted_endpoint(xhci, slot_id, ep->ep_index,
+- ep_ring->stream_id, td, EP_HARD_RESET);
++ xhci_cleanup_halted_endpoint(xhci, ep, ep_ring->stream_id, td,
++ EP_HARD_RESET);
+ } else {
+ /* Update ring dequeue pointer */
+ while (ep_ring->dequeue != td->last_trb)
+@@ -2323,9 +2320,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ struct xhci_ring *ep_ring;
+ u32 trb_comp_code;
+ u32 remaining, requested, ep_trb_len;
+- unsigned int slot_id;
+
+- slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
+ slot_ctx = xhci_get_slot_ctx(xhci, ep->vdev->out_ctx);
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
+@@ -2365,8 +2360,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
+ break;
+ *status = 0;
+- xhci_cleanup_halted_endpoint(xhci, slot_id, ep->ep_index,
+- ep_ring->stream_id, td, EP_SOFT_RESET);
++ xhci_cleanup_halted_endpoint(xhci, ep, ep_ring->stream_id, td,
++ EP_SOFT_RESET);
+ return 0;
+ default:
+ /* do nothing */
+@@ -2441,8 +2436,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ case COMP_USB_TRANSACTION_ERROR:
+ case COMP_INVALID_STREAM_TYPE_ERROR:
+ case COMP_INVALID_STREAM_ID_ERROR:
+- xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index, 0,
+- NULL, EP_SOFT_RESET);
++ xhci_cleanup_halted_endpoint(xhci, ep, 0, NULL,
++ EP_SOFT_RESET);
+ goto cleanup;
+ case COMP_RING_UNDERRUN:
+ case COMP_RING_OVERRUN:
+@@ -2625,8 +2620,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ if (trb_comp_code == COMP_STALL_ERROR ||
+ xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
+ trb_comp_code)) {
+- xhci_cleanup_halted_endpoint(xhci, slot_id,
+- ep_index,
++ xhci_cleanup_halted_endpoint(xhci, ep,
+ ep_ring->stream_id,
+ NULL,
+ EP_HARD_RESET);
+@@ -2720,8 +2714,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ if (trb_comp_code == COMP_STALL_ERROR ||
+ xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
+ trb_comp_code))
+- xhci_cleanup_halted_endpoint(xhci, slot_id,
+- ep_index,
++ xhci_cleanup_halted_endpoint(xhci, ep,
+ ep_ring->stream_id,
+ td, EP_HARD_RESET);
+ goto cleanup;
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 5fbd159f6fa5..9cbf106fb3ee 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1004,6 +1004,7 @@ struct xhci_interval_bw_table {
+ #define EP_CTX_PER_DEV 31
+
+ struct xhci_virt_device {
++ int slot_id;
+ struct usb_device *udev;
+ /*
+ * Commands to the hardware are passed an "input context" that
+--
+2.35.1
+
--- /dev/null
+From 0760d5b03f7260b1e3a366c86de1ff5777b6737c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Jan 2021 15:00:18 +0200
+Subject: xhci: Avoid parsing transfer events several times
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit ab58f3bb6aaaf98ba81d5c627ac25c08ff4ed4f1 ]
+
+When handling transfer events the event is passed along the handling
+callpath and parsed again in several occasions.
+
+The event contains slot_id and endpoint index, from which the driver
+endpoint structure can be found. There wasn't however a way to get the
+endpoint index or parent usb device from this endpoint structure.
+
+A lot of extra event parsing, and thus some DMA doublefetch cases,
+and excess variables and code can be avoided by adding endpoint index
+and parent usb virt device pointer to the endpoint structure.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20210129130044.206855-2-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a1575120972e ("xhci: Prevent infinite loop in transaction errors recovery for streams")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-mem.c | 2 ++
+ drivers/usb/host/xhci-ring.c | 28 ++++++++--------------------
+ drivers/usb/host/xhci.h | 2 ++
+ 3 files changed, 12 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index d1a42300ae58..002e4948993d 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1021,6 +1021,8 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
+
+ /* Initialize the cancellation list and watchdog timers for each ep */
+ for (i = 0; i < 31; i++) {
++ dev->eps[i].ep_index = i;
++ dev->eps[i].vdev = dev;
+ xhci_init_endpoint_timer(xhci, &dev->eps[i]);
+ INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list);
+ INIT_LIST_HEAD(&dev->eps[i].bw_endpoint_list);
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index fa3a7ac15f82..5cee7150376d 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1936,7 +1936,7 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
+ * Avoid resetting endpoint if link is inactive. Can cause host hang.
+ * Device will be reset soon to recover the link so don't do anything
+ */
+- if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR)
++ if (ep->vdev->flags & VDEV_PORT_ERROR)
+ return;
+
+ command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
+@@ -2045,18 +2045,14 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ struct xhci_transfer_event *event,
+ struct xhci_virt_ep *ep, int *status)
+ {
+- struct xhci_virt_device *xdev;
+ struct xhci_ep_ctx *ep_ctx;
+ struct xhci_ring *ep_ring;
+ unsigned int slot_id;
+ u32 trb_comp_code;
+- int ep_index;
+
+ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
+- xdev = xhci->devs[slot_id];
+- ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+- ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
++ ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index);
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
+
+ if (trb_comp_code == COMP_STOPPED_LENGTH_INVALID ||
+@@ -2081,9 +2077,9 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ * stall later. Hub TT buffer should only be cleared for FS/LS
+ * devices behind HS hubs for functional stalls.
+ */
+- if ((ep_index != 0) || (trb_comp_code != COMP_STALL_ERROR))
++ if ((ep->ep_index != 0) || (trb_comp_code != COMP_STALL_ERROR))
+ xhci_clear_hub_tt_buffer(xhci, td, ep);
+- xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
++ xhci_cleanup_halted_endpoint(xhci, slot_id, ep->ep_index,
+ ep_ring->stream_id, td, EP_HARD_RESET);
+ } else {
+ /* Update ring dequeue pointer */
+@@ -2117,19 +2113,13 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event,
+ struct xhci_virt_ep *ep, int *status)
+ {
+- struct xhci_virt_device *xdev;
+- unsigned int slot_id;
+- int ep_index;
+ struct xhci_ep_ctx *ep_ctx;
+ u32 trb_comp_code;
+ u32 remaining, requested;
+ u32 trb_type;
+
+ trb_type = TRB_FIELD_TO_TYPE(le32_to_cpu(ep_trb->generic.field[3]));
+- slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
+- xdev = xhci->devs[slot_id];
+- ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
+- ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
++ ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index);
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
+ requested = td->urb->transfer_buffer_length;
+ remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+@@ -2177,7 +2167,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ ep_ctx, trb_comp_code))
+ break;
+ xhci_dbg(xhci, "TRB error %u, halted endpoint index = %u\n",
+- trb_comp_code, ep_index);
++ trb_comp_code, ep->ep_index);
+ fallthrough;
+ case COMP_STALL_ERROR:
+ /* Did we transfer part of the data (middle) phase? */
+@@ -2339,11 +2329,9 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ u32 trb_comp_code;
+ u32 remaining, requested, ep_trb_len;
+ unsigned int slot_id;
+- int ep_index;
+
+ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
+- slot_ctx = xhci_get_slot_ctx(xhci, xhci->devs[slot_id]->out_ctx);
+- ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
++ slot_ctx = xhci_get_slot_ctx(xhci, ep->vdev->out_ctx);
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
+ remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+@@ -2382,7 +2370,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
+ break;
+ *status = 0;
+- xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
++ xhci_cleanup_halted_endpoint(xhci, slot_id, ep->ep_index,
+ ep_ring->stream_id, td, EP_SOFT_RESET);
+ return 0;
+ default:
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 059050f13522..5fbd159f6fa5 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -924,6 +924,8 @@ struct xhci_bw_info {
+ #define SS_BW_RESERVED 10
+
+ struct xhci_virt_ep {
++ struct xhci_virt_device *vdev; /* parent */
++ unsigned int ep_index;
+ struct xhci_ring *ring;
+ /* Related to endpoints that are configured to use stream IDs only */
+ struct xhci_stream_info *stream_info;
+--
+2.35.1
+
--- /dev/null
+From f423df4930ccfab33cd187579a063bdd9dbe1483 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Jan 2021 15:00:19 +0200
+Subject: xhci: get isochronous ring directly from endpoint structure
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit d4dff8043ea5b93a30cb9b19d4407bd506a6877a ]
+
+isochronous endpoints do not support streams, meaning that
+there is only one ring per endpoint.
+
+Avoid double-fetching the transfer event DMA to get the
+ring. Also makes passing the event to skip_isoc_td() uncecessary.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20210129130044.206855-3-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a1575120972e ("xhci: Prevent infinite loop in transaction errors recovery for streams")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 5cee7150376d..6d34c56376e5 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2209,7 +2209,6 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event,
+ struct xhci_virt_ep *ep, int *status)
+ {
+- struct xhci_ring *ep_ring;
+ struct urb_priv *urb_priv;
+ int idx;
+ struct usb_iso_packet_descriptor *frame;
+@@ -2218,7 +2217,6 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ u32 remaining, requested, ep_trb_len;
+ int short_framestatus;
+
+- ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
+ urb_priv = td->urb->hcpriv;
+ idx = urb_priv->num_tds_done;
+@@ -2279,7 +2277,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ }
+
+ if (sum_trbs_for_length)
+- frame->actual_length = sum_trb_lengths(xhci, ep_ring, ep_trb) +
++ frame->actual_length = sum_trb_lengths(xhci, ep->ring, ep_trb) +
+ ep_trb_len - remaining;
+ else
+ frame->actual_length = requested;
+@@ -2290,15 +2288,12 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ }
+
+ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+- struct xhci_transfer_event *event,
+ struct xhci_virt_ep *ep, int *status)
+ {
+- struct xhci_ring *ep_ring;
+ struct urb_priv *urb_priv;
+ struct usb_iso_packet_descriptor *frame;
+ int idx;
+
+- ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+ urb_priv = td->urb->hcpriv;
+ idx = urb_priv->num_tds_done;
+ frame = &td->urb->iso_frame_desc[idx];
+@@ -2310,11 +2305,11 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ frame->actual_length = 0;
+
+ /* Update ring dequeue pointer */
+- while (ep_ring->dequeue != td->last_trb)
+- inc_deq(xhci, ep_ring);
+- inc_deq(xhci, ep_ring);
++ while (ep->ring->dequeue != td->last_trb)
++ inc_deq(xhci, ep->ring);
++ inc_deq(xhci, ep->ring);
+
+- return xhci_td_cleanup(xhci, td, ep_ring, status);
++ return xhci_td_cleanup(xhci, td, ep->ring, status);
+ }
+
+ /*
+@@ -2693,7 +2688,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ return -ESHUTDOWN;
+ }
+
+- skip_isoc_td(xhci, td, event, ep, &status);
++ skip_isoc_td(xhci, td, ep, &status);
+ goto cleanup;
+ }
+ if (trb_comp_code == COMP_SHORT_PACKET)
+--
+2.35.1
+
--- /dev/null
+From 7cf62e065d3bdb30b0b9d6113df9cadf2c2dce33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Jan 2021 15:00:37 +0200
+Subject: xhci: move and rename xhci_cleanup_halted_endpoint()
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit 7c6c334e6fc8cd99e780fd74cd29687886a81862 ]
+
+Halted endpoints can be discoverd both when handling transfer events and
+command completion events. Move code that handles halted endpoints before
+both of those event handlers.
+
+Rename the function to xhci_handle_halted_ep() to better describe
+what it does. Try to reserve "cleanup" word in function names for last
+stage cleanup activities.
+
+No functional changes
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20210129130044.206855-21-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a1575120972e ("xhci: Prevent infinite loop in transaction errors recovery for streams")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 84 ++++++++++++++++++------------------
+ 1 file changed, 43 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 2bd407ff9f0b..edb712081815 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -839,6 +839,35 @@ static int xhci_reset_halted_ep(struct xhci_hcd *xhci, unsigned int slot_id,
+ return ret;
+ }
+
++static void xhci_handle_halted_endpoint(struct xhci_hcd *xhci,
++ struct xhci_virt_ep *ep, unsigned int stream_id,
++ struct xhci_td *td,
++ enum xhci_ep_reset_type reset_type)
++{
++ unsigned int slot_id = ep->vdev->slot_id;
++ int err;
++
++ /*
++ * Avoid resetting endpoint if link is inactive. Can cause host hang.
++ * Device will be reset soon to recover the link so don't do anything
++ */
++ if (ep->vdev->flags & VDEV_PORT_ERROR)
++ return;
++
++ ep->ep_state |= EP_HALTED;
++
++ err = xhci_reset_halted_ep(xhci, slot_id, ep->ep_index, reset_type);
++ if (err)
++ return;
++
++ if (reset_type == EP_HARD_RESET) {
++ ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
++ xhci_cleanup_stalled_ring(xhci, slot_id, ep->ep_index, stream_id,
++ td);
++ }
++ xhci_ring_cmd_db(xhci);
++}
++
+ /*
+ * When we get a command completion for a Stop Endpoint Command, we need to
+ * unlink any cancelled TDs from the ring. There are two ways to do that:
+@@ -1990,35 +2019,6 @@ static void xhci_clear_hub_tt_buffer(struct xhci_hcd *xhci, struct xhci_td *td,
+ }
+ }
+
+-static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
+- struct xhci_virt_ep *ep, unsigned int stream_id,
+- struct xhci_td *td,
+- enum xhci_ep_reset_type reset_type)
+-{
+- unsigned int slot_id = ep->vdev->slot_id;
+- int err;
+-
+- /*
+- * Avoid resetting endpoint if link is inactive. Can cause host hang.
+- * Device will be reset soon to recover the link so don't do anything
+- */
+- if (ep->vdev->flags & VDEV_PORT_ERROR)
+- return;
+-
+- ep->ep_state |= EP_HALTED;
+-
+- err = xhci_reset_halted_ep(xhci, slot_id, ep->ep_index, reset_type);
+- if (err)
+- return;
+-
+- if (reset_type == EP_HARD_RESET) {
+- ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
+- xhci_cleanup_stalled_ring(xhci, slot_id, ep->ep_index, stream_id,
+- td);
+- }
+- xhci_ring_cmd_db(xhci);
+-}
+-
+ /* Check if an error has halted the endpoint ring. The class driver will
+ * cleanup the halt for a non-default control endpoint if we indicate a stall.
+ * However, a babble and other errors also halt the endpoint ring, and the class
+@@ -2094,7 +2094,8 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ */
+ if ((ep->ep_index != 0) || (trb_comp_code != COMP_STALL_ERROR))
+ xhci_clear_hub_tt_buffer(xhci, td, ep);
+- xhci_cleanup_halted_endpoint(xhci, ep, ep_ring->stream_id, td,
++
++ xhci_handle_halted_endpoint(xhci, ep, ep_ring->stream_id, td,
+ EP_HARD_RESET);
+ } else {
+ /* Update ring dequeue pointer */
+@@ -2379,8 +2380,9 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ break;
+
+ td->status = 0;
+- xhci_cleanup_halted_endpoint(xhci, ep, ep_ring->stream_id, td,
+- EP_SOFT_RESET);
++
++ xhci_handle_halted_endpoint(xhci, ep, ep_ring->stream_id, td,
++ EP_SOFT_RESET);
+ return 0;
+ default:
+ /* do nothing */
+@@ -2455,8 +2457,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ case COMP_USB_TRANSACTION_ERROR:
+ case COMP_INVALID_STREAM_TYPE_ERROR:
+ case COMP_INVALID_STREAM_ID_ERROR:
+- xhci_cleanup_halted_endpoint(xhci, ep, 0, NULL,
+- EP_SOFT_RESET);
++ xhci_handle_halted_endpoint(xhci, ep, 0, NULL,
++ EP_SOFT_RESET);
+ goto cleanup;
+ case COMP_RING_UNDERRUN:
+ case COMP_RING_OVERRUN:
+@@ -2639,10 +2641,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ if (trb_comp_code == COMP_STALL_ERROR ||
+ xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
+ trb_comp_code)) {
+- xhci_cleanup_halted_endpoint(xhci, ep,
+- ep_ring->stream_id,
+- NULL,
+- EP_HARD_RESET);
++ xhci_handle_halted_endpoint(xhci, ep,
++ ep_ring->stream_id,
++ NULL,
++ EP_HARD_RESET);
+ }
+ goto cleanup;
+ }
+@@ -2734,9 +2736,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ if (trb_comp_code == COMP_STALL_ERROR ||
+ xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
+ trb_comp_code))
+- xhci_cleanup_halted_endpoint(xhci, ep,
+- ep_ring->stream_id,
+- td, EP_HARD_RESET);
++ xhci_handle_halted_endpoint(xhci, ep,
++ ep_ring->stream_id,
++ td, EP_HARD_RESET);
+ goto cleanup;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 2253542509fb011f596123fde46eace4cdfd8f76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Jan 2021 15:00:33 +0200
+Subject: xhci: move xhci_td_cleanup so it can be called by more functions
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit 69eaf9e79fa7c7ff4b1eb626493ce5a81e467520 ]
+
+No funtional changes
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20210129130044.206855-17-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a1575120972e ("xhci: Prevent infinite loop in transaction errors recovery for streams")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 92 ++++++++++++++++++------------------
+ 1 file changed, 46 insertions(+), 46 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index b4a510450ac2..d523cbe7fcf1 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -773,6 +773,52 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
+ seg->bounce_offs = 0;
+ }
+
++static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
++ struct xhci_ring *ep_ring, int *status)
++{
++ struct urb *urb = NULL;
++
++ /* Clean up the endpoint's TD list */
++ urb = td->urb;
++
++ /* if a bounce buffer was used to align this td then unmap it */
++ xhci_unmap_td_bounce_buffer(xhci, ep_ring, td);
++
++ /* Do one last check of the actual transfer length.
++ * If the host controller said we transferred more data than the buffer
++ * length, urb->actual_length will be a very big number (since it's
++ * unsigned). Play it safe and say we didn't transfer anything.
++ */
++ if (urb->actual_length > urb->transfer_buffer_length) {
++ xhci_warn(xhci, "URB req %u and actual %u transfer length mismatch\n",
++ urb->transfer_buffer_length, urb->actual_length);
++ urb->actual_length = 0;
++ *status = 0;
++ }
++ list_del_init(&td->td_list);
++ /* Was this TD slated to be cancelled but completed anyway? */
++ if (!list_empty(&td->cancelled_td_list))
++ list_del_init(&td->cancelled_td_list);
++
++ inc_td_cnt(urb);
++ /* Giveback the urb when all the tds are completed */
++ if (last_td_in_urb(td)) {
++ if ((urb->actual_length != urb->transfer_buffer_length &&
++ (urb->transfer_flags & URB_SHORT_NOT_OK)) ||
++ (*status != 0 && !usb_endpoint_xfer_isoc(&urb->ep->desc)))
++ xhci_dbg(xhci, "Giveback URB %p, len = %d, expected = %d, status = %d\n",
++ urb, urb->actual_length,
++ urb->transfer_buffer_length, *status);
++
++ /* set isoc urb status to 0 just as EHCI, UHCI, and OHCI */
++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
++ *status = 0;
++ xhci_giveback_urb_in_irq(xhci, td, *status);
++ }
++
++ return 0;
++}
++
+ static int xhci_reset_halted_ep(struct xhci_hcd *xhci, unsigned int slot_id,
+ unsigned int ep_index, enum xhci_ep_reset_type reset_type)
+ {
+@@ -2013,52 +2059,6 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code)
+ return 0;
+ }
+
+-static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
+- struct xhci_ring *ep_ring, int *status)
+-{
+- struct urb *urb = NULL;
+-
+- /* Clean up the endpoint's TD list */
+- urb = td->urb;
+-
+- /* if a bounce buffer was used to align this td then unmap it */
+- xhci_unmap_td_bounce_buffer(xhci, ep_ring, td);
+-
+- /* Do one last check of the actual transfer length.
+- * If the host controller said we transferred more data than the buffer
+- * length, urb->actual_length will be a very big number (since it's
+- * unsigned). Play it safe and say we didn't transfer anything.
+- */
+- if (urb->actual_length > urb->transfer_buffer_length) {
+- xhci_warn(xhci, "URB req %u and actual %u transfer length mismatch\n",
+- urb->transfer_buffer_length, urb->actual_length);
+- urb->actual_length = 0;
+- *status = 0;
+- }
+- list_del_init(&td->td_list);
+- /* Was this TD slated to be cancelled but completed anyway? */
+- if (!list_empty(&td->cancelled_td_list))
+- list_del_init(&td->cancelled_td_list);
+-
+- inc_td_cnt(urb);
+- /* Giveback the urb when all the tds are completed */
+- if (last_td_in_urb(td)) {
+- if ((urb->actual_length != urb->transfer_buffer_length &&
+- (urb->transfer_flags & URB_SHORT_NOT_OK)) ||
+- (*status != 0 && !usb_endpoint_xfer_isoc(&urb->ep->desc)))
+- xhci_dbg(xhci, "Giveback URB %p, len = %d, expected = %d, status = %d\n",
+- urb, urb->actual_length,
+- urb->transfer_buffer_length, *status);
+-
+- /* set isoc urb status to 0 just as EHCI, UHCI, and OHCI */
+- if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+- *status = 0;
+- xhci_giveback_urb_in_irq(xhci, td, *status);
+- }
+-
+- return 0;
+-}
+-
+ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ struct xhci_transfer_event *event,
+ struct xhci_virt_ep *ep, int *status)
+--
+2.35.1
+
--- /dev/null
+From ba0afe491497a64b38775963da0ab38854645c0a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Nov 2022 11:19:43 +0200
+Subject: xhci: Prevent infinite loop in transaction errors recovery for
+ streams
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit a1575120972ecd7baa6af6a69e4e7ea9213bde7c ]
+
+Make sure to also limit the amount of soft reset retries for transaction
+errors on streams in cases where the transaction error event doesn't point
+to any specific TRB.
+
+In these cases we don't know the TRB or stream ring, but we do know which
+endpoint had the error.
+
+To keep error counting simple and functional, move the current err_count
+from ring structure to endpoint structure.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20221130091944.2171610-6-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 14 ++++++++++----
+ drivers/usb/host/xhci.h | 2 +-
+ 2 files changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index edb712081815..ead42fc3e16d 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2349,7 +2349,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+
+ switch (trb_comp_code) {
+ case COMP_SUCCESS:
+- ep_ring->err_count = 0;
++ ep->err_count = 0;
+ /* handle success with untransferred data as short packet */
+ if (ep_trb != td->last_trb || remaining) {
+ xhci_warn(xhci, "WARN Successful completion on short TX\n");
+@@ -2375,7 +2375,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ break;
+ case COMP_USB_TRANSACTION_ERROR:
+ if (xhci->quirks & XHCI_NO_SOFT_RETRY ||
+- (ep_ring->err_count++ > MAX_SOFT_RETRY) ||
++ (ep->err_count++ > MAX_SOFT_RETRY) ||
+ le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
+ break;
+
+@@ -2457,8 +2457,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ case COMP_USB_TRANSACTION_ERROR:
+ case COMP_INVALID_STREAM_TYPE_ERROR:
+ case COMP_INVALID_STREAM_ID_ERROR:
+- xhci_handle_halted_endpoint(xhci, ep, 0, NULL,
+- EP_SOFT_RESET);
++ xhci_dbg(xhci, "Stream transaction error ep %u no id\n",
++ ep_index);
++ if (ep->err_count++ > MAX_SOFT_RETRY)
++ xhci_handle_halted_endpoint(xhci, ep, 0, NULL,
++ EP_HARD_RESET);
++ else
++ xhci_handle_halted_endpoint(xhci, ep, 0, NULL,
++ EP_SOFT_RESET);
+ goto cleanup;
+ case COMP_RING_UNDERRUN:
+ case COMP_RING_OVERRUN:
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index af3759928a95..ac09b171b783 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -933,6 +933,7 @@ struct xhci_virt_ep {
+ * have to restore the device state to the previous state
+ */
+ struct xhci_ring *new_ring;
++ unsigned int err_count;
+ unsigned int ep_state;
+ #define SET_DEQ_PENDING (1 << 0)
+ #define EP_HALTED (1 << 1) /* For stall handling */
+@@ -1616,7 +1617,6 @@ struct xhci_ring {
+ * if we own the TRB (if we are the consumer). See section 4.9.1.
+ */
+ u32 cycle_state;
+- unsigned int err_count;
+ unsigned int stream_id;
+ unsigned int num_segs;
+ unsigned int num_trbs_free;
+--
+2.35.1
+
--- /dev/null
+From 277f9eaf444bd3bf8606c49f1bad39c45898d561 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Jan 2021 15:00:35 +0200
+Subject: xhci: store TD status in the td struct instead of passing it along
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit a6ccd1fd4bd4fca37eaa3d76bef940d6332919bc ]
+
+In cases where the TD can't be given back in current handler we want
+to be able to store it until its time to return the TD.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20210129130044.206855-19-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a1575120972e ("xhci: Prevent infinite loop in transaction errors recovery for streams")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 56 +++++++++++++++++++-----------------
+ drivers/usb/host/xhci.h | 1 +
+ 2 files changed, 30 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index d523cbe7fcf1..2bd407ff9f0b 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -774,7 +774,7 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
+ }
+
+ static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
+- struct xhci_ring *ep_ring, int *status)
++ struct xhci_ring *ep_ring, int status)
+ {
+ struct urb *urb = NULL;
+
+@@ -793,7 +793,7 @@ static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
+ xhci_warn(xhci, "URB req %u and actual %u transfer length mismatch\n",
+ urb->transfer_buffer_length, urb->actual_length);
+ urb->actual_length = 0;
+- *status = 0;
++ status = 0;
+ }
+ list_del_init(&td->td_list);
+ /* Was this TD slated to be cancelled but completed anyway? */
+@@ -805,15 +805,15 @@ static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
+ if (last_td_in_urb(td)) {
+ if ((urb->actual_length != urb->transfer_buffer_length &&
+ (urb->transfer_flags & URB_SHORT_NOT_OK)) ||
+- (*status != 0 && !usb_endpoint_xfer_isoc(&urb->ep->desc)))
++ (status != 0 && !usb_endpoint_xfer_isoc(&urb->ep->desc)))
+ xhci_dbg(xhci, "Giveback URB %p, len = %d, expected = %d, status = %d\n",
+ urb, urb->actual_length,
+- urb->transfer_buffer_length, *status);
++ urb->transfer_buffer_length, status);
+
+ /* set isoc urb status to 0 just as EHCI, UHCI, and OHCI */
+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+- *status = 0;
+- xhci_giveback_urb_in_irq(xhci, td, *status);
++ status = 0;
++ xhci_giveback_urb_in_irq(xhci, td, status);
+ }
+
+ return 0;
+@@ -2060,8 +2060,7 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code)
+ }
+
+ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
+- struct xhci_transfer_event *event,
+- struct xhci_virt_ep *ep, int *status)
++ struct xhci_transfer_event *event, struct xhci_virt_ep *ep)
+ {
+ struct xhci_ep_ctx *ep_ctx;
+ struct xhci_ring *ep_ring;
+@@ -2104,7 +2103,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ inc_deq(xhci, ep_ring);
+ }
+
+- return xhci_td_cleanup(xhci, td, ep_ring, status);
++ return xhci_td_cleanup(xhci, td, ep_ring, td->status);
+ }
+
+ /* sum trb lengths from ring dequeue up to stop_trb, _excluding_ stop_trb */
+@@ -2127,7 +2126,7 @@ static int sum_trb_lengths(struct xhci_hcd *xhci, struct xhci_ring *ring,
+ */
+ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event,
+- struct xhci_virt_ep *ep, int *status)
++ struct xhci_virt_ep *ep)
+ {
+ struct xhci_ep_ctx *ep_ctx;
+ u32 trb_comp_code;
+@@ -2145,13 +2144,13 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ if (trb_type != TRB_STATUS) {
+ xhci_warn(xhci, "WARN: Success on ctrl %s TRB without IOC set?\n",
+ (trb_type == TRB_DATA) ? "data" : "setup");
+- *status = -ESHUTDOWN;
++ td->status = -ESHUTDOWN;
+ break;
+ }
+- *status = 0;
++ td->status = 0;
+ break;
+ case COMP_SHORT_PACKET:
+- *status = 0;
++ td->status = 0;
+ break;
+ case COMP_STOPPED_SHORT_PACKET:
+ if (trb_type == TRB_DATA || trb_type == TRB_NORMAL)
+@@ -2215,7 +2214,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ td->urb->actual_length = requested;
+
+ finish_td:
+- return finish_td(xhci, td, event, ep, status);
++ return finish_td(xhci, td, event, ep);
+ }
+
+ /*
+@@ -2223,7 +2222,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ */
+ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event,
+- struct xhci_virt_ep *ep, int *status)
++ struct xhci_virt_ep *ep)
+ {
+ struct urb_priv *urb_priv;
+ int idx;
+@@ -2300,11 +2299,11 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+
+ td->urb->actual_length += frame->actual_length;
+
+- return finish_td(xhci, td, event, ep, status);
++ return finish_td(xhci, td, event, ep);
+ }
+
+ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+- struct xhci_virt_ep *ep, int *status)
++ struct xhci_virt_ep *ep, int status)
+ {
+ struct urb_priv *urb_priv;
+ struct usb_iso_packet_descriptor *frame;
+@@ -2333,7 +2332,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ */
+ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event,
+- struct xhci_virt_ep *ep, int *status)
++ struct xhci_virt_ep *ep)
+ {
+ struct xhci_slot_ctx *slot_ctx;
+ struct xhci_ring *ep_ring;
+@@ -2357,13 +2356,13 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ td->urb->ep->desc.bEndpointAddress,
+ requested, remaining);
+ }
+- *status = 0;
++ td->status = 0;
+ break;
+ case COMP_SHORT_PACKET:
+ xhci_dbg(xhci, "ep %#x - asked for %d bytes, %d bytes untransferred\n",
+ td->urb->ep->desc.bEndpointAddress,
+ requested, remaining);
+- *status = 0;
++ td->status = 0;
+ break;
+ case COMP_STOPPED_SHORT_PACKET:
+ td->urb->actual_length = remaining;
+@@ -2378,7 +2377,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ (ep_ring->err_count++ > MAX_SOFT_RETRY) ||
+ le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
+ break;
+- *status = 0;
++
++ td->status = 0;
+ xhci_cleanup_halted_endpoint(xhci, ep, ep_ring->stream_id, td,
+ EP_SOFT_RESET);
+ return 0;
+@@ -2399,7 +2399,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ remaining);
+ td->urb->actual_length = 0;
+ }
+- return finish_td(xhci, td, event, ep, status);
++ return finish_td(xhci, td, event, ep);
+ }
+
+ /*
+@@ -2701,7 +2701,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ return -ESHUTDOWN;
+ }
+
+- skip_isoc_td(xhci, td, ep, &status);
++ skip_isoc_td(xhci, td, ep, status);
+ goto cleanup;
+ }
+ if (trb_comp_code == COMP_SHORT_PACKET)
+@@ -2729,6 +2729,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ * endpoint. Otherwise, the endpoint remains stalled
+ * indefinitely.
+ */
++
+ if (trb_is_noop(ep_trb)) {
+ if (trb_comp_code == COMP_STALL_ERROR ||
+ xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
+@@ -2739,14 +2740,15 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ goto cleanup;
+ }
+
++ td->status = status;
++
+ /* update the urb's actual_length and give back to the core */
+ if (usb_endpoint_xfer_control(&td->urb->ep->desc))
+- process_ctrl_td(xhci, td, ep_trb, event, ep, &status);
++ process_ctrl_td(xhci, td, ep_trb, event, ep);
+ else if (usb_endpoint_xfer_isoc(&td->urb->ep->desc))
+- process_isoc_td(xhci, td, ep_trb, event, ep, &status);
++ process_isoc_td(xhci, td, ep_trb, event, ep);
+ else
+- process_bulk_intr_td(xhci, td, ep_trb, event, ep,
+- &status);
++ process_bulk_intr_td(xhci, td, ep_trb, event, ep);
+ cleanup:
+ handling_skipped_tds = ep->skip &&
+ trb_comp_code != COMP_MISSED_SERVICE_ERROR &&
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 9cbf106fb3ee..af3759928a95 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1544,6 +1544,7 @@ struct xhci_segment {
+ struct xhci_td {
+ struct list_head td_list;
+ struct list_head cancelled_td_list;
++ int status;
+ struct urb *urb;
+ struct xhci_segment *start_seg;
+ union xhci_trb *first_trb;
+--
+2.35.1
+