]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Sat, 14 Jan 2023 14:23:25 +0000 (09:23 -0500)
committerSasha Levin <sashal@kernel.org>
Sat, 14 Jan 2023 14:23:25 +0000 (09:23 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
18 files changed:
queue-5.10/bus-mhi-host-fix-race-between-channel-preparation-an.patch [new file with mode: 0644]
queue-5.10/clk-imx-imx8mp-add-shared-clk-gate-for-usb-suspend-c.patch [new file with mode: 0644]
queue-5.10/clk-imx8mp-add-clkout1-2-support.patch [new file with mode: 0644]
queue-5.10/clk-imx8mp-add-disp2-pixel-clock.patch [new file with mode: 0644]
queue-5.10/dt-bindings-clocks-imx8mp-add-id-for-usb-suspend-clo.patch [new file with mode: 0644]
queue-5.10/ext4-fix-uninititialized-value-in-ext4_evict_inode.patch [new file with mode: 0644]
queue-5.10/iommu-amd-add-pci-segment-support-for-ivrs_-ioapic-h.patch [new file with mode: 0644]
queue-5.10/iommu-amd-fix-ill-formed-ivrs_ioapic-ivrs_hpet-and-i.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch [new file with mode: 0644]
queue-5.10/xhci-add-xhci_reset_halted_ep-helper-function.patch [new file with mode: 0644]
queue-5.10/xhci-adjust-parameters-passed-to-cleanup_halted_endp.patch [new file with mode: 0644]
queue-5.10/xhci-avoid-parsing-transfer-events-several-times.patch [new file with mode: 0644]
queue-5.10/xhci-get-isochronous-ring-directly-from-endpoint-str.patch [new file with mode: 0644]
queue-5.10/xhci-move-and-rename-xhci_cleanup_halted_endpoint.patch [new file with mode: 0644]
queue-5.10/xhci-move-xhci_td_cleanup-so-it-can-be-called-by-mor.patch [new file with mode: 0644]
queue-5.10/xhci-prevent-infinite-loop-in-transaction-errors-rec.patch [new file with mode: 0644]
queue-5.10/xhci-store-td-status-in-the-td-struct-instead-of-pas.patch [new file with mode: 0644]

diff --git a/queue-5.10/bus-mhi-host-fix-race-between-channel-preparation-an.patch b/queue-5.10/bus-mhi-host-fix-race-between-channel-preparation-an.patch
new file mode 100644 (file)
index 0000000..ef168a4
--- /dev/null
@@ -0,0 +1,46 @@
+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
+
diff --git a/queue-5.10/clk-imx-imx8mp-add-shared-clk-gate-for-usb-suspend-c.patch b/queue-5.10/clk-imx-imx8mp-add-shared-clk-gate-for-usb-suspend-c.patch
new file mode 100644 (file)
index 0000000..952931c
--- /dev/null
@@ -0,0 +1,57 @@
+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
+
diff --git a/queue-5.10/clk-imx8mp-add-clkout1-2-support.patch b/queue-5.10/clk-imx8mp-add-clkout1-2-support.patch
new file mode 100644 (file)
index 0000000..fb1afa9
--- /dev/null
@@ -0,0 +1,80 @@
+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
+
diff --git a/queue-5.10/clk-imx8mp-add-disp2-pixel-clock.patch b/queue-5.10/clk-imx8mp-add-disp2-pixel-clock.patch
new file mode 100644 (file)
index 0000000..67fbf38
--- /dev/null
@@ -0,0 +1,77 @@
+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
+
diff --git a/queue-5.10/dt-bindings-clocks-imx8mp-add-id-for-usb-suspend-clo.patch b/queue-5.10/dt-bindings-clocks-imx8mp-add-id-for-usb-suspend-clo.patch
new file mode 100644 (file)
index 0000000..e4b8103
--- /dev/null
@@ -0,0 +1,41 @@
+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
+
diff --git a/queue-5.10/ext4-fix-uninititialized-value-in-ext4_evict_inode.patch b/queue-5.10/ext4-fix-uninititialized-value-in-ext4_evict_inode.patch
new file mode 100644 (file)
index 0000000..c1d1895
--- /dev/null
@@ -0,0 +1,97 @@
+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
+
diff --git a/queue-5.10/iommu-amd-add-pci-segment-support-for-ivrs_-ioapic-h.patch b/queue-5.10/iommu-amd-add-pci-segment-support-for-ivrs_-ioapic-h.patch
new file mode 100644 (file)
index 0000000..61158ea
--- /dev/null
@@ -0,0 +1,193 @@
+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
+
diff --git a/queue-5.10/iommu-amd-fix-ill-formed-ivrs_ioapic-ivrs_hpet-and-i.patch b/queue-5.10/iommu-amd-fix-ill-formed-ivrs_ioapic-ivrs_hpet-and-i.patch
new file mode 100644 (file)
index 0000000..270e9bb
--- /dev/null
@@ -0,0 +1,216 @@
+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
+
index 5efc9eb02534642783d301297cc847488baa8d15..e52fe34b9506f8f38811dcb5354cd86d2c34ce7e 100644 (file)
@@ -8,3 +8,20 @@ s390-kexec-fix-ipl-report-address-for-kdump.patch
 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
diff --git a/queue-5.10/usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch b/queue-5.10/usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch
new file mode 100644 (file)
index 0000000..5346b02
--- /dev/null
@@ -0,0 +1,49 @@
+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
+
diff --git a/queue-5.10/xhci-add-xhci_reset_halted_ep-helper-function.patch b/queue-5.10/xhci-add-xhci_reset_halted_ep-helper-function.patch
new file mode 100644 (file)
index 0000000..d1d41a9
--- /dev/null
@@ -0,0 +1,89 @@
+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
+
diff --git a/queue-5.10/xhci-adjust-parameters-passed-to-cleanup_halted_endp.patch b/queue-5.10/xhci-adjust-parameters-passed-to-cleanup_halted_endp.patch
new file mode 100644 (file)
index 0000000..c0fba29
--- /dev/null
@@ -0,0 +1,170 @@
+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
+
diff --git a/queue-5.10/xhci-avoid-parsing-transfer-events-several-times.patch b/queue-5.10/xhci-avoid-parsing-transfer-events-several-times.patch
new file mode 100644 (file)
index 0000000..7f063b4
--- /dev/null
@@ -0,0 +1,157 @@
+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
+
diff --git a/queue-5.10/xhci-get-isochronous-ring-directly-from-endpoint-str.patch b/queue-5.10/xhci-get-isochronous-ring-directly-from-endpoint-str.patch
new file mode 100644 (file)
index 0000000..28d374b
--- /dev/null
@@ -0,0 +1,97 @@
+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
+
diff --git a/queue-5.10/xhci-move-and-rename-xhci_cleanup_halted_endpoint.patch b/queue-5.10/xhci-move-and-rename-xhci_cleanup_halted_endpoint.patch
new file mode 100644 (file)
index 0000000..f3f7287
--- /dev/null
@@ -0,0 +1,168 @@
+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
+
diff --git a/queue-5.10/xhci-move-xhci_td_cleanup-so-it-can-be-called-by-mor.patch b/queue-5.10/xhci-move-xhci_td_cleanup-so-it-can-be-called-by-mor.patch
new file mode 100644 (file)
index 0000000..2764d91
--- /dev/null
@@ -0,0 +1,133 @@
+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
+
diff --git a/queue-5.10/xhci-prevent-infinite-loop-in-transaction-errors-rec.patch b/queue-5.10/xhci-prevent-infinite-loop-in-transaction-errors-rec.patch
new file mode 100644 (file)
index 0000000..eb9ed58
--- /dev/null
@@ -0,0 +1,92 @@
+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
+
diff --git a/queue-5.10/xhci-store-td-status-in-the-td-struct-instead-of-pas.patch b/queue-5.10/xhci-store-td-status-in-the-td-struct-instead-of-pas.patch
new file mode 100644 (file)
index 0000000..1487043
--- /dev/null
@@ -0,0 +1,237 @@
+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
+