--- /dev/null
+From e10d6ffb0aa8944422e52adb0afc7b5e6393d3fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Jun 2022 05:41:46 -0700
+Subject: ARM: dts: am33xx: Fix MMCHS0 dma properties
+
+From: YuTong Chang <mtwget@gmail.com>
+
+[ Upstream commit 2eb502f496f7764027b7958d4e74356fed918059 ]
+
+According to technical manual(table 11-24), the DMA of MMCHS0 should be
+direct mapped.
+
+Fixes: b5e509066074 ("ARM: DTS: am33xx: Use the new DT bindings for the eDMA3")
+Signed-off-by: YuTong Chang <mtwget@gmail.com>
+Message-Id: <20220620124146.5330-1-mtwget@gmail.com>
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/am33xx-l4.dtsi | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am33xx-l4.dtsi b/arch/arm/boot/dts/am33xx-l4.dtsi
+index 7da42a5b959c..7e50fe633d8a 100644
+--- a/arch/arm/boot/dts/am33xx-l4.dtsi
++++ b/arch/arm/boot/dts/am33xx-l4.dtsi
+@@ -1502,8 +1502,7 @@
+ mmc1: mmc@0 {
+ compatible = "ti,am335-sdhci";
+ ti,needs-special-reset;
+- dmas = <&edma_xbar 24 0 0
+- &edma_xbar 25 0 0>;
++ dmas = <&edma 24 0>, <&edma 25 0>;
+ dma-names = "tx", "rx";
+ interrupts = <64>;
+ reg = <0x0 0x1000>;
+--
+2.35.1
+
--- /dev/null
+From 7ea878619f50157bbb40a3d4406d40fbc0722b65 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Aug 2022 09:27:42 +0200
+Subject: ARM: dts: am5748: keep usb4_tm disabled
+
+From: Romain Naour <romain.naour@skf.com>
+
+[ Upstream commit 6a6d9ecff14a2a46c1deeffa3eb3825349639bdd ]
+
+Commit bcbb63b80284 ("ARM: dts: dra7: Separate AM57 dtsi files")
+disabled usb4_tm for am5748 devices since USB4 IP is not present
+in this SoC.
+
+The commit log explained the difference between AM5 and DRA7 families:
+
+AM5 and DRA7 SoC families have different set of modules in them so the
+SoC sepecific dtsi files need to be separated.
+
+e.g. Some of the major differences between AM576 and DRA76
+
+ DRA76x AM576x
+
+USB3 x
+USB4 x
+ATL x
+VCP x
+MLB x
+ISS x
+PRU-ICSS1 x
+PRU-ICSS2 x
+
+Then commit 176f26bcd41a ("ARM: dts: Add support for dra762 abz
+package") removed usb4_tm part from am5748.dtsi and introcuded new
+ti-sysc errors in dmesg:
+
+ti-sysc 48940000.target-module: clock get error for fck: -2
+ti-sysc: probe of 48940000.target-module failed with error -2
+
+Fixes: 176f26bcd41a ("ARM: dts: Add support for dra762 abz package")
+
+Signed-off-by: Romain Naour <romain.naour@skf.com>
+Signed-off-by: Romain Naour <romain.naour@smile.fr>
+Message-Id: <20220823072742.351368-1-romain.naour@smile.fr>
+Reviewed-by: Roger Quadros <rogerq@kernel.org>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/am5748.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am5748.dtsi b/arch/arm/boot/dts/am5748.dtsi
+index c260aa1a85bd..a1f029e9d1f3 100644
+--- a/arch/arm/boot/dts/am5748.dtsi
++++ b/arch/arm/boot/dts/am5748.dtsi
+@@ -25,6 +25,10 @@
+ status = "disabled";
+ };
+
++&usb4_tm {
++ status = "disabled";
++};
++
+ &atl_tm {
+ status = "disabled";
+ };
+--
+2.35.1
+
--- /dev/null
+From 579553f3ba02a8703964adde942b166ceb9623a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Sep 2022 11:36:03 +0200
+Subject: arm64: dts: qcom: sm8350: fix UFS PHY serdes size
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit 40e9541959100e017533e18e44d07eed44f91dc5 ]
+
+The size of the UFS PHY serdes register region is 0x1c4 and the
+corresponding 'reg' property should specifically not include the
+adjacent regions that are defined in the child node (e.g. tx and rx).
+
+Fixes: 59c7cf814783 ("arm64: dts: qcom: sm8350: Add UFS nodes")
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Link: https://lore.kernel.org/r/20220916093603.24263-1-johan+linaro@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm8350.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi
+index 3293f76478df..0e5a4fbb5eb1 100644
+--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi
+@@ -2128,7 +2128,7 @@
+
+ ufs_mem_phy: phy@1d87000 {
+ compatible = "qcom,sm8350-qmp-ufs-phy";
+- reg = <0 0x01d87000 0 0xe10>;
++ reg = <0 0x01d87000 0 0x1c4>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+--
+2.35.1
+
--- /dev/null
+From 638d3203de61befe2a0d901dcf27cbc10c10a38a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Sep 2022 17:00:01 +0800
+Subject: ASoC: imx-card: Fix refcount issue with of_node_put
+
+From: Shengjiu Wang <shengjiu.wang@nxp.com>
+
+[ Upstream commit d56ba9a04d7548d4149c46ec86a0e3cc41a70f4a ]
+
+imx_card_parse_of will search all the node with loop,
+if there is defer probe happen in the middle of loop,
+the previous released codec node will be released
+twice, then cause refcount issue.
+
+Here assign NULL to pointer of released nodes to fix
+the issue.
+
+Fixes: aa736700f42f ("ASoC: imx-card: Add imx-card machine driver")
+Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
+Link: https://lore.kernel.org/r/1663059601-29259-1-git-send-email-shengjiu.wang@nxp.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/fsl/imx-card.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c
+index 4a8609b0d700..5153af3281d2 100644
+--- a/sound/soc/fsl/imx-card.c
++++ b/sound/soc/fsl/imx-card.c
+@@ -698,6 +698,10 @@ static int imx_card_parse_of(struct imx_card_data *data)
+ of_node_put(cpu);
+ of_node_put(codec);
+ of_node_put(platform);
++
++ cpu = NULL;
++ codec = NULL;
++ platform = NULL;
+ }
+
+ return 0;
+--
+2.35.1
+
--- /dev/null
+From 5e518dc0aff5239e6ede53ab9bcbae54fbeb12ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Sep 2022 19:34:53 +0200
+Subject: ASoC: tas2770: Reinit regcache on reset
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Martin Povišer <povik+lin@cutebit.org>
+
+[ Upstream commit 0a0342ede303fc420f3a388e1ae82da3ae8ff6bd ]
+
+On probe of the ASoC component, the device is reset but the regcache is
+retained. This means the regcache gets out of sync if the codec is
+rebound to a sound card for a second time. Fix it by reinitializing the
+regcache to defaults after the device is reset.
+
+Fixes: b0bcbe615756 ("ASoC: tas2770: Fix calling reset in probe")
+Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
+Link: https://lore.kernel.org/r/20220919173453.84292-1-povik+lin@cutebit.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/tas2770.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
+index 9ea2aca65e89..e02ad765351b 100644
+--- a/sound/soc/codecs/tas2770.c
++++ b/sound/soc/codecs/tas2770.c
+@@ -495,6 +495,8 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = {
+ },
+ };
+
++static const struct regmap_config tas2770_i2c_regmap;
++
+ static int tas2770_codec_probe(struct snd_soc_component *component)
+ {
+ struct tas2770_priv *tas2770 =
+@@ -508,6 +510,7 @@ static int tas2770_codec_probe(struct snd_soc_component *component)
+ }
+
+ tas2770_reset(tas2770);
++ regmap_reinit_cache(tas2770->regmap, &tas2770_i2c_regmap);
+
+ return 0;
+ }
+--
+2.35.1
+
--- /dev/null
+From dcbfbd95b2ca32266290ade8b2cd85f2169e4e82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Sep 2022 10:09:59 -0500
+Subject: clk: imx: imx6sx: remove the SET_RATE_PARENT flag for QSPI clocks
+
+From: Han Xu <han.xu@nxp.com>
+
+[ Upstream commit b1ff1bfe81e763420afd5f3f25f0b3cbfd97055c ]
+
+There is no dedicate parent clock for QSPI so SET_RATE_PARENT flag
+should not be used. For instance, the default parent clock for QSPI is
+pll2_bus, which is also the parent clock for quite a few modules, such
+as MMDC, once GPMI NAND set clock rate for EDO5 mode can cause system
+hang due to pll2_bus rate changed.
+
+Fixes: f1541e15e38e ("clk: imx6sx: Switch to clk_hw based API")
+Signed-off-by: Han Xu <han.xu@nxp.com>
+Link: https://lore.kernel.org/r/20220915150959.3646702-1-han.xu@nxp.com
+Tested-by: Fabio Estevam <festevam@denx.de>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/imx/clk-imx6sx.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c
+index fc1bd23d4583..598f3cf4eba4 100644
+--- a/drivers/clk/imx/clk-imx6sx.c
++++ b/drivers/clk/imx/clk-imx6sx.c
+@@ -280,13 +280,13 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
+ hws[IMX6SX_CLK_SSI3_SEL] = imx_clk_hw_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+ hws[IMX6SX_CLK_SSI2_SEL] = imx_clk_hw_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+ hws[IMX6SX_CLK_SSI1_SEL] = imx_clk_hw_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+- hws[IMX6SX_CLK_QSPI1_SEL] = imx_clk_hw_mux_flags("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT);
++ hws[IMX6SX_CLK_QSPI1_SEL] = imx_clk_hw_mux("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
+ hws[IMX6SX_CLK_PERCLK_SEL] = imx_clk_hw_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels));
+ hws[IMX6SX_CLK_VID_SEL] = imx_clk_hw_mux("vid_sel", base + 0x20, 21, 3, vid_sels, ARRAY_SIZE(vid_sels));
+ hws[IMX6SX_CLK_ESAI_SEL] = imx_clk_hw_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
+ hws[IMX6SX_CLK_CAN_SEL] = imx_clk_hw_mux("can_sel", base + 0x20, 8, 2, can_sels, ARRAY_SIZE(can_sels));
+ hws[IMX6SX_CLK_UART_SEL] = imx_clk_hw_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
+- hws[IMX6SX_CLK_QSPI2_SEL] = imx_clk_hw_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT);
++ hws[IMX6SX_CLK_QSPI2_SEL] = imx_clk_hw_mux("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels));
+ hws[IMX6SX_CLK_SPDIF_SEL] = imx_clk_hw_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
+ hws[IMX6SX_CLK_AUDIO_SEL] = imx_clk_hw_mux("audio_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
+ hws[IMX6SX_CLK_ENET_PRE_SEL] = imx_clk_hw_mux("enet_pre_sel", base + 0x34, 15, 3, enet_pre_sels, ARRAY_SIZE(enet_pre_sels));
+--
+2.35.1
+
--- /dev/null
+From feab25fe1722b94aff9d52ae1677d37db79c4253 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Aug 2022 11:31:31 +0800
+Subject: clk: imx93: drop of_match_ptr
+
+From: Peng Fan <peng.fan@nxp.com>
+
+[ Upstream commit daaa2fbe678efdaced53d1c635f4d326751addf8 ]
+
+There is build warning when CONFIG_OF is not selected.
+>> drivers/clk/imx/clk-imx93.c:324:34: warning: 'imx93_clk_of_match'
+>> defined but not used [-Wunused-const-variable=]
+ 324 | static const struct of_device_id imx93_clk_of_match[] = {
+ | ^~~~~~~~~~~~~~~~~~
+
+The driver only support DT table, no sense to use of_match_ptr.
+
+Fixes: 24defbe194b6 ("clk: imx: add i.MX93 clk")
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Peng Fan <peng.fan@nxp.com>
+Link: https://lore.kernel.org/r/20220830033137.4149542-3-peng.fan@oss.nxp.com
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/imx/clk-imx93.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
+index f5c9fa40491c..dcc41d178238 100644
+--- a/drivers/clk/imx/clk-imx93.c
++++ b/drivers/clk/imx/clk-imx93.c
+@@ -332,7 +332,7 @@ static struct platform_driver imx93_clk_driver = {
+ .driver = {
+ .name = "imx93-ccm",
+ .suppress_bind_attrs = true,
+- .of_match_table = of_match_ptr(imx93_clk_of_match),
++ .of_match_table = imx93_clk_of_match,
+ },
+ };
+ module_platform_driver(imx93_clk_driver);
+--
+2.35.1
+
--- /dev/null
+From 3d49a6ae18988c75b3122550e116289d7b5f9442 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Sep 2022 09:15:03 -0700
+Subject: clk: iproc: Do not rely on node name for correct PLL setup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Florian Fainelli <f.fainelli@gmail.com>
+
+[ Upstream commit 1b24a132eba7a1c19475ba2510ec1c00af3ff914 ]
+
+After commit 31fd9b79dc58 ("ARM: dts: BCM5301X: update CRU block
+description") a warning from clk-iproc-pll.c was generated due to a
+duplicate PLL name as well as the console stopped working. Upon closer
+inspection it became clear that iproc_pll_clk_setup() used the Device
+Tree node unit name as an unique identifier as well as a parent name to
+parent all clocks under the PLL.
+
+BCM5301X was the first platform on which that got noticed because of the
+DT node unit name renaming but the same assumptions hold true for any
+user of the iproc_pll_clk_setup() function.
+
+The first 'clock-output-names' property is always guaranteed to be
+unique as well as providing the actual desired PLL clock name, so we
+utilize that to register the PLL and as a parent name of all children
+clock.
+
+Fixes: 5fe225c105fd ("clk: iproc: add initial common clock support")
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+Acked-by: Rafał Miłecki <rafal@milecki.pl>
+Link: https://lore.kernel.org/r/20220905161504.1526-1-f.fainelli@gmail.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/bcm/clk-iproc-pll.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c
+index 33da30f99c79..d39c44b61c52 100644
+--- a/drivers/clk/bcm/clk-iproc-pll.c
++++ b/drivers/clk/bcm/clk-iproc-pll.c
+@@ -736,6 +736,7 @@ void iproc_pll_clk_setup(struct device_node *node,
+ const char *parent_name;
+ struct iproc_clk *iclk_array;
+ struct clk_hw_onecell_data *clk_data;
++ const char *clk_name;
+
+ if (WARN_ON(!pll_ctrl) || WARN_ON(!clk_ctrl))
+ return;
+@@ -783,7 +784,12 @@ void iproc_pll_clk_setup(struct device_node *node,
+ iclk = &iclk_array[0];
+ iclk->pll = pll;
+
+- init.name = node->name;
++ ret = of_property_read_string_index(node, "clock-output-names",
++ 0, &clk_name);
++ if (WARN_ON(ret))
++ goto err_pll_register;
++
++ init.name = clk_name;
+ init.ops = &iproc_pll_ops;
+ init.flags = 0;
+ parent_name = of_clk_get_parent_name(node, 0);
+@@ -803,13 +809,11 @@ void iproc_pll_clk_setup(struct device_node *node,
+ goto err_pll_register;
+
+ clk_data->hws[0] = &iclk->hw;
++ parent_name = clk_name;
+
+ /* now initialize and register all leaf clocks */
+ for (i = 1; i < num_clks; i++) {
+- const char *clk_name;
+-
+ memset(&init, 0, sizeof(init));
+- parent_name = node->name;
+
+ ret = of_property_read_string_index(node, "clock-output-names",
+ i, &clk_name);
+--
+2.35.1
+
--- /dev/null
+From 09deaaada2e6dbe0bebf671b34b7ea18c7ce3ddc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Sep 2022 13:31:10 +0100
+Subject: clk: microchip: mpfs: fix clk_cfg array bounds violation
+
+From: Conor Dooley <conor.dooley@microchip.com>
+
+[ Upstream commit 5da39ac5d648cdbfdfa8bea0e0cde279ded5c7c2 ]
+
+There is an array bounds violation present during clock registration,
+triggered by current code by only specific toolchains. This seems to
+fail gracefully in v6.0-rc1, using a toolchain build from the riscv-
+gnu-toolchain repo and with clang-15, and life carries on. While
+converting the driver to use standard clock structs/ops, kernel panics
+were seen during boot when built with clang-15:
+
+[ 0.581754] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000b1
+[ 0.591520] Oops [#1]
+[ 0.594045] Modules linked in:
+[ 0.597435] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc1-00011-g8e1459cf4eca #1
+[ 0.606188] Hardware name: Microchip PolarFire-SoC Icicle Kit (DT)
+[ 0.613012] epc : __clk_register+0x4a6/0x85c
+[ 0.617759] ra : __clk_register+0x49e/0x85c
+[ 0.622489] epc : ffffffff803faf7c ra : ffffffff803faf74 sp : ffffffc80400b720
+[ 0.630466] gp : ffffffff810e93f8 tp : ffffffe77fe60000 t0 : ffffffe77ffb3800
+[ 0.638443] t1 : 000000000000000a t2 : ffffffffffffffff s0 : ffffffc80400b7c0
+[ 0.646420] s1 : 0000000000000001 a0 : 0000000000000001 a1 : 0000000000000000
+[ 0.654396] a2 : 0000000000000001 a3 : 0000000000000000 a4 : 0000000000000000
+[ 0.662373] a5 : ffffffff803a5810 a6 : 0000000200000022 a7 : 0000000000000006
+[ 0.670350] s2 : ffffffff81099d48 s3 : ffffffff80d6e28e s4 : 0000000000000028
+[ 0.678327] s5 : ffffffff810ed3c8 s6 : ffffffff810ed3d0 s7 : ffffffe77ffbc100
+[ 0.686304] s8 : ffffffe77ffb1540 s9 : ffffffe77ffb1540 s10: 0000000000000008
+[ 0.694281] s11: 0000000000000000 t3 : 00000000000000c6 t4 : 0000000000000007
+[ 0.702258] t5 : ffffffff810c78c0 t6 : ffffffe77ff88cd0
+[ 0.708125] status: 0000000200000120 badaddr: 00000000000000b1 cause: 000000000000000d
+[ 0.716869] [<ffffffff803fb892>] devm_clk_hw_register+0x62/0xaa
+[ 0.723420] [<ffffffff80403412>] mpfs_clk_probe+0x1e0/0x244
+
+In v6.0-rc1 and later, this issue is visible without the follow on
+patches doing the conversion using toolchains provided by our Yocto
+meta layer too.
+
+It fails on "clk_periph_timer" - which uses a different parent, that it
+tries to find using the macro:
+\#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT].cfg.hw)
+
+If parent is RTCREF, so the macro becomes: &mpfs_cfg_clks[33].cfg.hw
+which is well beyond the end of the array. Amazingly, builds with GCC
+11.1 see no problem here, booting correctly and hooking the parent up
+etc. Builds with clang-15 do not, with the above panic.
+
+Change the macro to use specific offsets depending on the parent rather
+than the dt-binding's clock IDs.
+
+Fixes: 1c6a7ea32b8c ("clk: microchip: mpfs: add RTCREF clock control")
+CC: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
+Reviewed-by: Claudiu Beznea <claudiu.beznea@microchip.com>
+Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
+Link: https://lore.kernel.org/r/20220909123123.2699583-2-conor.dooley@microchip.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/microchip/clk-mpfs.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c
+index 070c3b896559..f0f9c9a1cc48 100644
+--- a/drivers/clk/microchip/clk-mpfs.c
++++ b/drivers/clk/microchip/clk-mpfs.c
+@@ -239,6 +239,11 @@ static const struct clk_ops mpfs_clk_cfg_ops = {
+ .hw.init = CLK_HW_INIT(_name, _parent, &mpfs_clk_cfg_ops, 0), \
+ }
+
++#define CLK_CPU_OFFSET 0u
++#define CLK_AXI_OFFSET 1u
++#define CLK_AHB_OFFSET 2u
++#define CLK_RTCREF_OFFSET 3u
++
+ static struct mpfs_cfg_hw_clock mpfs_cfg_clks[] = {
+ CLK_CFG(CLK_CPU, "clk_cpu", "clk_msspll", 0, 2, mpfs_div_cpu_axi_table, 0,
+ REG_CLOCK_CONFIG_CR),
+@@ -362,7 +367,7 @@ static const struct clk_ops mpfs_periph_clk_ops = {
+ _flags), \
+ }
+
+-#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT].hw)
++#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT##_OFFSET].hw)
+
+ /*
+ * Critical clocks:
+--
+2.35.1
+
--- /dev/null
+From c112c1c905cb06ba3e548d6e253e7b941870cd5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Sep 2022 13:31:11 +0100
+Subject: clk: microchip: mpfs: make the rtc's ahb clock critical
+
+From: Conor Dooley <conor.dooley@microchip.com>
+
+[ Upstream commit 05d27090b6dc88bce71a608d1271536e582b73d1 ]
+
+The onboard RTC's AHB bus clock must be kept running as the RTC will
+stop & lose track of time if the AHB interface clock is disabled.
+
+Fixes: 635e5e73370e ("clk: microchip: Add driver for Microchip PolarFire SoC")
+Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
+Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
+Link: https://lore.kernel.org/r/20220909123123.2699583-3-conor.dooley@microchip.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/microchip/clk-mpfs.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c
+index f0f9c9a1cc48..b6b89413e090 100644
+--- a/drivers/clk/microchip/clk-mpfs.c
++++ b/drivers/clk/microchip/clk-mpfs.c
+@@ -375,6 +375,8 @@ static const struct clk_ops mpfs_periph_clk_ops = {
+ * trap handler
+ * - CLK_MMUART0: reserved by the hss
+ * - CLK_DDRC: provides clock to the ddr subsystem
++ * - CLK_RTC: the onboard RTC's AHB bus clock must be kept running as the rtc will stop
++ * if the AHB interface clock is disabled
+ * - CLK_FICx: these provide the processor side clocks to the "FIC" (Fabric InterConnect)
+ * clock domain crossers which provide the interface to the FPGA fabric. Disabling them
+ * causes the FPGA fabric to go into reset.
+@@ -399,7 +401,7 @@ static struct mpfs_periph_hw_clock mpfs_periph_clks[] = {
+ CLK_PERIPH(CLK_CAN0, "clk_periph_can0", PARENT_CLK(AHB), 14, 0),
+ CLK_PERIPH(CLK_CAN1, "clk_periph_can1", PARENT_CLK(AHB), 15, 0),
+ CLK_PERIPH(CLK_USB, "clk_periph_usb", PARENT_CLK(AHB), 16, 0),
+- CLK_PERIPH(CLK_RTC, "clk_periph_rtc", PARENT_CLK(AHB), 18, 0),
++ CLK_PERIPH(CLK_RTC, "clk_periph_rtc", PARENT_CLK(AHB), 18, CLK_IS_CRITICAL),
+ CLK_PERIPH(CLK_QSPI, "clk_periph_qspi", PARENT_CLK(AHB), 19, 0),
+ CLK_PERIPH(CLK_GPIO0, "clk_periph_gpio0", PARENT_CLK(AHB), 20, 0),
+ CLK_PERIPH(CLK_GPIO1, "clk_periph_gpio1", PARENT_CLK(AHB), 21, 0),
+--
+2.35.1
+
--- /dev/null
+From 51af011630be456ba629b6ab7381a14bff48c55c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Sep 2022 14:51:08 -0300
+Subject: cxgb4: fix missing unlock on ETHOFLD desc collect fail path
+
+From: Rafael Mendonca <rafaelmendsr@gmail.com>
+
+[ Upstream commit c635ebe8d911a93bd849a9419b01a58783de76f1 ]
+
+The label passed to the QDESC_GET for the ETHOFLD TXQ, RXQ, and FLQ, is the
+'out' one, which skips the 'out_unlock' label, and thus doesn't unlock the
+'uld_mutex' before returning. Additionally, since commit 5148e5950c67
+("cxgb4: add EOTID tracking and software context dump"), the access to
+these ETHOFLD hardware queues should be protected by the 'mqprio_mutex'
+instead.
+
+Fixes: 2d0cb84dd973 ("cxgb4: add ETHOFLD hardware queue support")
+Fixes: 5148e5950c67 ("cxgb4: add EOTID tracking and software context dump")
+Signed-off-by: Rafael Mendonca <rafaelmendsr@gmail.com>
+Reviewed-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
+Link: https://lore.kernel.org/r/20220922175109.764898-1-rafaelmendsr@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/chelsio/cxgb4/cudbg_lib.c | 28 +++++++++++++------
+ 1 file changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
+index a7f291c89702..557c591a6ce3 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
+@@ -14,6 +14,7 @@
+ #include "cudbg_entity.h"
+ #include "cudbg_lib.h"
+ #include "cudbg_zlib.h"
++#include "cxgb4_tc_mqprio.h"
+
+ static const u32 t6_tp_pio_array[][IREG_NUM_ELEM] = {
+ {0x7e40, 0x7e44, 0x020, 28}, /* t6_tp_pio_regs_20_to_3b */
+@@ -3458,7 +3459,7 @@ int cudbg_collect_qdesc(struct cudbg_init *pdbg_init,
+ for (i = 0; i < utxq->ntxq; i++)
+ QDESC_GET_TXQ(&utxq->uldtxq[i].q,
+ cudbg_uld_txq_to_qtype(j),
+- out_unlock);
++ out_unlock_uld);
+ }
+ }
+
+@@ -3475,7 +3476,7 @@ int cudbg_collect_qdesc(struct cudbg_init *pdbg_init,
+ for (i = 0; i < urxq->nrxq; i++)
+ QDESC_GET_RXQ(&urxq->uldrxq[i].rspq,
+ cudbg_uld_rxq_to_qtype(j),
+- out_unlock);
++ out_unlock_uld);
+ }
+
+ /* ULD FLQ */
+@@ -3487,7 +3488,7 @@ int cudbg_collect_qdesc(struct cudbg_init *pdbg_init,
+ for (i = 0; i < urxq->nrxq; i++)
+ QDESC_GET_FLQ(&urxq->uldrxq[i].fl,
+ cudbg_uld_flq_to_qtype(j),
+- out_unlock);
++ out_unlock_uld);
+ }
+
+ /* ULD CIQ */
+@@ -3500,29 +3501,34 @@ int cudbg_collect_qdesc(struct cudbg_init *pdbg_init,
+ for (i = 0; i < urxq->nciq; i++)
+ QDESC_GET_RXQ(&urxq->uldrxq[base + i].rspq,
+ cudbg_uld_ciq_to_qtype(j),
+- out_unlock);
++ out_unlock_uld);
+ }
+ }
++ mutex_unlock(&uld_mutex);
++
++ if (!padap->tc_mqprio)
++ goto out;
+
++ mutex_lock(&padap->tc_mqprio->mqprio_mutex);
+ /* ETHOFLD TXQ */
+ if (s->eohw_txq)
+ for (i = 0; i < s->eoqsets; i++)
+ QDESC_GET_TXQ(&s->eohw_txq[i].q,
+- CUDBG_QTYPE_ETHOFLD_TXQ, out);
++ CUDBG_QTYPE_ETHOFLD_TXQ, out_unlock_mqprio);
+
+ /* ETHOFLD RXQ and FLQ */
+ if (s->eohw_rxq) {
+ for (i = 0; i < s->eoqsets; i++)
+ QDESC_GET_RXQ(&s->eohw_rxq[i].rspq,
+- CUDBG_QTYPE_ETHOFLD_RXQ, out);
++ CUDBG_QTYPE_ETHOFLD_RXQ, out_unlock_mqprio);
+
+ for (i = 0; i < s->eoqsets; i++)
+ QDESC_GET_FLQ(&s->eohw_rxq[i].fl,
+- CUDBG_QTYPE_ETHOFLD_FLQ, out);
++ CUDBG_QTYPE_ETHOFLD_FLQ, out_unlock_mqprio);
+ }
+
+-out_unlock:
+- mutex_unlock(&uld_mutex);
++out_unlock_mqprio:
++ mutex_unlock(&padap->tc_mqprio->mqprio_mutex);
+
+ out:
+ qdesc_info->qdesc_entry_size = sizeof(*qdesc_entry);
+@@ -3559,6 +3565,10 @@ int cudbg_collect_qdesc(struct cudbg_init *pdbg_init,
+ #undef QDESC_GET
+
+ return rc;
++
++out_unlock_uld:
++ mutex_unlock(&uld_mutex);
++ goto out;
+ }
+
+ int cudbg_collect_flash(struct cudbg_init *pdbg_init,
+--
+2.35.1
+
--- /dev/null
+From bbb6fad0e391971325367d5ceb857b80f754c626 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Sep 2022 11:59:14 -0400
+Subject: don't use __kernel_write() on kmap_local_page()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 06bbaa6dc53cb72040db952053432541acb9adc7 ]
+
+passing kmap_local_page() result to __kernel_write() is unsafe -
+random ->write_iter() might (and 9p one does) get unhappy when
+passed ITER_KVEC with pointer that came from kmap_local_page().
+
+Fix by providing a variant of __kernel_write() that takes an iov_iter
+from caller (__kernel_write() becomes a trivial wrapper) and adding
+dump_emit_page() that parallels dump_emit(), except that instead of
+__kernel_write() it uses __kernel_write_iter() with ITER_BVEC source.
+
+Fixes: 3159ed57792b "fs/coredump: use kmap_local_page()"
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/coredump.c | 38 +++++++++++++++++++++++++++++++++-----
+ fs/internal.h | 3 +++
+ fs/read_write.c | 22 ++++++++++++++--------
+ 3 files changed, 50 insertions(+), 13 deletions(-)
+
+diff --git a/fs/coredump.c b/fs/coredump.c
+index ebc43f960b64..f1355e52614a 100644
+--- a/fs/coredump.c
++++ b/fs/coredump.c
+@@ -832,6 +832,38 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr)
+ }
+ }
+
++static int dump_emit_page(struct coredump_params *cprm, struct page *page)
++{
++ struct bio_vec bvec = {
++ .bv_page = page,
++ .bv_offset = 0,
++ .bv_len = PAGE_SIZE,
++ };
++ struct iov_iter iter;
++ struct file *file = cprm->file;
++ loff_t pos = file->f_pos;
++ ssize_t n;
++
++ if (cprm->to_skip) {
++ if (!__dump_skip(cprm, cprm->to_skip))
++ return 0;
++ cprm->to_skip = 0;
++ }
++ if (cprm->written + PAGE_SIZE > cprm->limit)
++ return 0;
++ if (dump_interrupted())
++ return 0;
++ iov_iter_bvec(&iter, WRITE, &bvec, 1, PAGE_SIZE);
++ n = __kernel_write_iter(cprm->file, &iter, &pos);
++ if (n != PAGE_SIZE)
++ return 0;
++ file->f_pos = pos;
++ cprm->written += PAGE_SIZE;
++ cprm->pos += PAGE_SIZE;
++
++ return 1;
++}
++
+ int dump_emit(struct coredump_params *cprm, const void *addr, int nr)
+ {
+ if (cprm->to_skip) {
+@@ -863,7 +895,6 @@ int dump_user_range(struct coredump_params *cprm, unsigned long start,
+
+ for (addr = start; addr < start + len; addr += PAGE_SIZE) {
+ struct page *page;
+- int stop;
+
+ /*
+ * To avoid having to allocate page tables for virtual address
+@@ -874,10 +905,7 @@ int dump_user_range(struct coredump_params *cprm, unsigned long start,
+ */
+ page = get_dump_page(addr);
+ if (page) {
+- void *kaddr = kmap_local_page(page);
+-
+- stop = !dump_emit(cprm, kaddr, PAGE_SIZE);
+- kunmap_local(kaddr);
++ int stop = !dump_emit_page(cprm, page);
+ put_page(page);
+ if (stop)
+ return 0;
+diff --git a/fs/internal.h b/fs/internal.h
+index 87e96b9024ce..3e206d3e317c 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -16,6 +16,7 @@ struct shrink_control;
+ struct fs_context;
+ struct user_namespace;
+ struct pipe_inode_info;
++struct iov_iter;
+
+ /*
+ * block/bdev.c
+@@ -221,3 +222,5 @@ ssize_t do_getxattr(struct user_namespace *mnt_userns,
+ int setxattr_copy(const char __user *name, struct xattr_ctx *ctx);
+ int do_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
+ struct xattr_ctx *ctx);
++
++ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *pos);
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 397da0236607..a0a3d35e2c0f 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -509,14 +509,9 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
+ }
+
+ /* caller is responsible for file_start_write/file_end_write */
+-ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
++ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *pos)
+ {
+- struct kvec iov = {
+- .iov_base = (void *)buf,
+- .iov_len = min_t(size_t, count, MAX_RW_COUNT),
+- };
+ struct kiocb kiocb;
+- struct iov_iter iter;
+ ssize_t ret;
+
+ if (WARN_ON_ONCE(!(file->f_mode & FMODE_WRITE)))
+@@ -532,8 +527,7 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
+
+ init_sync_kiocb(&kiocb, file);
+ kiocb.ki_pos = pos ? *pos : 0;
+- iov_iter_kvec(&iter, WRITE, &iov, 1, iov.iov_len);
+- ret = file->f_op->write_iter(&kiocb, &iter);
++ ret = file->f_op->write_iter(&kiocb, from);
+ if (ret > 0) {
+ if (pos)
+ *pos = kiocb.ki_pos;
+@@ -543,6 +537,18 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
+ inc_syscw(current);
+ return ret;
+ }
++
++/* caller is responsible for file_start_write/file_end_write */
++ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
++{
++ struct kvec iov = {
++ .iov_base = (void *)buf,
++ .iov_len = min_t(size_t, count, MAX_RW_COUNT),
++ };
++ struct iov_iter iter;
++ iov_iter_kvec(&iter, WRITE, &iov, 1, iov.iov_len);
++ return __kernel_write_iter(file, &iter, pos);
++}
+ /*
+ * This "EXPORT_SYMBOL_GPL()" is more of a "EXPORT_SYMBOL_DONTUSE()",
+ * but autofs is one of the few internal kernel users that actually
+--
+2.35.1
+
--- /dev/null
+From 78816e7f3538520c61b98669c3f78842ae277a72 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Sep 2022 14:43:03 +0200
+Subject: drm/bridge: lt8912b: add vsync hsync
+
+From: Philippe Schenker <philippe.schenker@toradex.com>
+
+[ Upstream commit da73a94fa282f78d485bd0aab36c8ac15b6f792c ]
+
+Currently the bridge driver does not take care whether or not the display
+needs positive/negative vertical/horizontal syncs. Pass these two flags
+to the bridge from the EDID that was read out from the display.
+
+Fixes: 30e2ae943c26 ("drm/bridge: Introduce LT8912B DSI to HDMI bridge")
+Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com>
+Acked-by: Adrien Grassein <adrien.grassein@gmail.com>
+Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220922124306.34729-2-dev@pschenker.ch
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index c642d1e02b2f..e011a2763621 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -266,7 +266,7 @@ static int lt8912_video_setup(struct lt8912 *lt)
+ u32 hactive, h_total, hpw, hfp, hbp;
+ u32 vactive, v_total, vpw, vfp, vbp;
+ u8 settle = 0x08;
+- int ret;
++ int ret, hsync_activehigh, vsync_activehigh;
+
+ if (!lt)
+ return -EINVAL;
+@@ -276,12 +276,14 @@ static int lt8912_video_setup(struct lt8912 *lt)
+ hpw = lt->mode.hsync_len;
+ hbp = lt->mode.hback_porch;
+ h_total = hactive + hfp + hpw + hbp;
++ hsync_activehigh = lt->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH;
+
+ vactive = lt->mode.vactive;
+ vfp = lt->mode.vfront_porch;
+ vpw = lt->mode.vsync_len;
+ vbp = lt->mode.vback_porch;
+ v_total = vactive + vfp + vpw + vbp;
++ vsync_activehigh = lt->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH;
+
+ if (vactive <= 600)
+ settle = 0x04;
+@@ -315,6 +317,11 @@ static int lt8912_video_setup(struct lt8912 *lt)
+ ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3e, hfp & 0xff);
+ ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3f, hfp >> 8);
+
++ ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xab, BIT(0),
++ vsync_activehigh ? BIT(0) : 0);
++ ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xab, BIT(1),
++ hsync_activehigh ? BIT(1) : 0);
++
+ return ret;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 3857d44f2cca3c658cda52e087acfd6f1873eec4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Sep 2022 14:43:05 +0200
+Subject: drm/bridge: lt8912b: fix corrupted image output
+
+From: Francesco Dolcini <francesco.dolcini@toradex.com>
+
+[ Upstream commit 051ad2788d35ca07aec8402542e5d38429f2426a ]
+
+Correct I2C address for the register list in lt8912_write_lvds_config(),
+these registers are on the first I2C address (0x48), the current
+function is just writing garbage to the wrong registers and this creates
+multiple issues (artifacts and output completely corrupted) on some HDMI
+displays.
+
+Correct I2C address comes from Lontium documentation and it is the one
+used on other out-of-tree LT8912B drivers [1].
+
+[1] https://github.com/boundarydevices/linux/blob/boundary-imx_5.10.x_2.0.0/drivers/video/lt8912.c#L296
+
+Fixes: 30e2ae943c26 ("drm/bridge: Introduce LT8912B DSI to HDMI bridge")
+Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
+Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com>
+Acked-by: Adrien Grassein <adrien.grassein@gmail.com>
+Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220922124306.34729-4-dev@pschenker.ch
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index bab3772c8407..167cd7d85dbb 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -186,7 +186,7 @@ static int lt8912_write_lvds_config(struct lt8912 *lt)
+ {0x03, 0xff},
+ };
+
+- return regmap_multi_reg_write(lt->regmap[I2C_CEC_DSI], seq, ARRAY_SIZE(seq));
++ return regmap_multi_reg_write(lt->regmap[I2C_MAIN], seq, ARRAY_SIZE(seq));
+ };
+
+ static inline struct lt8912 *bridge_to_lt8912(struct drm_bridge *b)
+--
+2.35.1
+
--- /dev/null
+From 6fd13acc9b389b3311cde40eb0740983dcd64f7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Sep 2022 14:43:04 +0200
+Subject: drm/bridge: lt8912b: set hdmi or dvi mode
+
+From: Philippe Schenker <philippe.schenker@toradex.com>
+
+[ Upstream commit 6dd1de12e1243f2013e4fabf31e99e63b1a860d0 ]
+
+The Lontium LT8912 does have a setting for DVI or HDMI. This patch reads
+from EDID what the display needs and sets it accordingly.
+
+Fixes: 30e2ae943c26 ("drm/bridge: Introduce LT8912B DSI to HDMI bridge")
+Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com>
+Acked-by: Adrien Grassein <adrien.grassein@gmail.com>
+Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220922124306.34729-3-dev@pschenker.ch
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index e011a2763621..bab3772c8407 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -321,6 +321,8 @@ static int lt8912_video_setup(struct lt8912 *lt)
+ vsync_activehigh ? BIT(0) : 0);
+ ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xab, BIT(1),
+ hsync_activehigh ? BIT(1) : 0);
++ ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xb2, BIT(0),
++ lt->connector.display_info.is_hdmi ? BIT(0) : 0);
+
+ return ret;
+ }
+--
+2.35.1
+
--- /dev/null
+From 2482242d5abe4452394e4569a2eb8dbc97b9894a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Sep 2022 12:02:12 -0700
+Subject: drm/i915/gt: Perf_limit_reasons are only available for Gen11+
+
+From: Ashutosh Dixit <ashutosh.dixit@intel.com>
+
+[ Upstream commit 7738be973fc4e2ba22154fafd3a5d7b9666f9abf ]
+
+Register GT0_PERF_LIMIT_REASONS (0x1381a8) is available only for
+Gen11+. Therefore ensure perf_limit_reasons sysfs files are created only
+for Gen11+. Otherwise on Gen < 5 accessing these files results in the
+following oops:
+
+<1> [88.829420] BUG: unable to handle page fault for address: ffffc90000bb81a8
+<1> [88.829438] #PF: supervisor read access in kernel mode
+<1> [88.829447] #PF: error_code(0x0000) - not-present page
+
+This patch is a backport of the drm-tip commit 0d2d201095e9
+("drm/i915: Perf_limit_reasons are only available for Gen11+") to
+drm-intel-fixes. The backport is not identical to the original, it only
+includes the sysfs portions of if. The debugfs portion is not available
+in drm-intel-fixes so has not been backported.
+
+Bspec: 20008
+Bug: https://gitlab.freedesktop.org/drm/intel/-/issues/6863
+Fixes: fa68bff7cf27 ("drm/i915/gt: Add sysfs throttle frequency interfaces")
+Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220919162401.2077713-1-ashutosh.dixit@intel.com
+(backported from commit 0d2d201095e9f141d6a9fb44320afce761f8b5c2)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
+index f76b6cf8040e..b8cb58e2819a 100644
+--- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
++++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
+@@ -544,8 +544,7 @@ static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_ratl, RATL_MASK);
+ static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_thermalert, VR_THERMALERT_MASK);
+ static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_tdc, VR_TDC_MASK);
+
+-static const struct attribute *freq_attrs[] = {
+- &dev_attr_punit_req_freq_mhz.attr,
++static const struct attribute *throttle_reason_attrs[] = {
+ &attr_throttle_reason_status.attr,
+ &attr_throttle_reason_pl1.attr,
+ &attr_throttle_reason_pl2.attr,
+@@ -594,9 +593,17 @@ void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
+ if (!is_object_gt(kobj))
+ return;
+
+- ret = sysfs_create_files(kobj, freq_attrs);
++ ret = sysfs_create_file(kobj, &dev_attr_punit_req_freq_mhz.attr);
+ if (ret)
+ drm_warn(>->i915->drm,
+- "failed to create gt%u throttle sysfs files (%pe)",
++ "failed to create gt%u punit_req_freq_mhz sysfs (%pe)",
+ gt->info.id, ERR_PTR(ret));
++
++ if (GRAPHICS_VER(gt->i915) >= 11) {
++ ret = sysfs_create_files(kobj, throttle_reason_attrs);
++ if (ret)
++ drm_warn(>->i915->drm,
++ "failed to create gt%u throttle sysfs files (%pe)",
++ gt->info.id, ERR_PTR(ret));
++ }
+ }
+--
+2.35.1
+
--- /dev/null
+From 94385f9f0eca46a41b9879a77bb8e2f11e9581b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 20:33:25 +0200
+Subject: gpio: mvebu: Fix check for pwm support on non-A8K platforms
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 4335417da2b8d6d9b2d4411b5f9e248e5bb2d380 ]
+
+pwm support incompatible with Armada 80x0/70x0 API is not only in
+Armada 370, but also in Armada XP, 38x and 39x. So basically every non-A8K
+platform. Fix check for pwm support appropriately.
+
+Fixes: 85b7d8abfec7 ("gpio: mvebu: add pwm support for Armada 8K/7K")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-mvebu.c | 15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
+index 2db19cd640a4..de1e7a1a76f2 100644
+--- a/drivers/gpio/gpio-mvebu.c
++++ b/drivers/gpio/gpio-mvebu.c
+@@ -793,8 +793,12 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
+ u32 offset;
+ u32 set;
+
+- if (of_device_is_compatible(mvchip->chip.of_node,
+- "marvell,armada-370-gpio")) {
++ if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) {
++ int ret = of_property_read_u32(dev->of_node,
++ "marvell,pwm-offset", &offset);
++ if (ret < 0)
++ return 0;
++ } else {
+ /*
+ * There are only two sets of PWM configuration registers for
+ * all the GPIO lines on those SoCs which this driver reserves
+@@ -804,13 +808,6 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
+ if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm"))
+ return 0;
+ offset = 0;
+- } else if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) {
+- int ret = of_property_read_u32(dev->of_node,
+- "marvell,pwm-offset", &offset);
+- if (ret < 0)
+- return 0;
+- } else {
+- return 0;
+ }
+
+ if (IS_ERR(mvchip->clk))
+--
+2.35.1
+
--- /dev/null
+From 296a51992871862e86b93ffee214c0275fc3e833 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Sep 2022 12:40:39 +0200
+Subject: ice: xsk: change batched Tx descriptor cleaning
+
+From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+
+[ Upstream commit 29322791bc8b4f42fc65734840826e3ddc30921e ]
+
+AF_XDP Tx descriptor cleaning in ice driver currently works in a "lazy"
+way - descriptors are not cleaned immediately after send. We rather hold
+on with cleaning until we see that free space in ring drops below
+particular threshold. This was supposed to reduce the amount of
+unnecessary work related to cleaning and instead of keeping the ring
+empty, ring was rather saturated.
+
+In AF_XDP realm cleaning Tx descriptors implies producing them to CQ.
+This is a way of letting know user space that particular descriptor has
+been sent, as John points out in [0].
+
+We tried to implement serial descriptor cleaning which would be used in
+conjunction with batched cleaning but it made code base more convoluted
+and probably harder to maintain in future. Therefore we step away from
+batched cleaning in a current form in favor of an approach where we set
+RS bit on every last descriptor from a batch and clean always at the
+beginning of ice_xmit_zc().
+
+This means that we give up a bit of Tx performance, but this doesn't
+hurt l2fwd scenario which is way more meaningful than txonly as this can
+be treaten as AF_XDP based packet generator. l2fwd is not hurt due to
+the fact that Tx side is much faster than Rx and Rx is the one that has
+to catch Tx up.
+
+FWIW Tx descriptors are still produced in a batched way.
+
+[0]: https://lore.kernel.org/bpf/62b0a20232920_3573208ab@john.notmuch/
+
+Fixes: 126cdfe1007a ("ice: xsk: Improve AF_XDP ZC Tx and use batching API")
+Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Tested-by: George Kuruvinakunnel <george.kuruvinakunnel@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +-
+ drivers/net/ethernet/intel/ice/ice_xsk.c | 143 +++++++++-------------
+ drivers/net/ethernet/intel/ice/ice_xsk.h | 7 +-
+ 3 files changed, 64 insertions(+), 88 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
+index 97453d1dfafe..dd2285d4bef4 100644
+--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
+@@ -1467,7 +1467,7 @@ int ice_napi_poll(struct napi_struct *napi, int budget)
+ bool wd;
+
+ if (tx_ring->xsk_pool)
+- wd = ice_xmit_zc(tx_ring, ICE_DESC_UNUSED(tx_ring), budget);
++ wd = ice_xmit_zc(tx_ring);
+ else if (ice_ring_is_xdp(tx_ring))
+ wd = true;
+ else
+diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
+index 03ce85f6e6df..8833b66b4e54 100644
+--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
++++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
+@@ -788,69 +788,57 @@ ice_clean_xdp_tx_buf(struct ice_tx_ring *xdp_ring, struct ice_tx_buf *tx_buf)
+ }
+
+ /**
+- * ice_clean_xdp_irq_zc - Reclaim resources after transmit completes on XDP ring
+- * @xdp_ring: XDP ring to clean
+- * @napi_budget: amount of descriptors that NAPI allows us to clean
+- *
+- * Returns count of cleaned descriptors
++ * ice_clean_xdp_irq_zc - produce AF_XDP descriptors to CQ
++ * @xdp_ring: XDP Tx ring
+ */
+-static u16 ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring, int napi_budget)
++static void ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring)
+ {
+- u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
+- int budget = napi_budget / tx_thresh;
+- u16 next_dd = xdp_ring->next_dd;
+- u16 ntc, cleared_dds = 0;
+-
+- do {
+- struct ice_tx_desc *next_dd_desc;
+- u16 desc_cnt = xdp_ring->count;
+- struct ice_tx_buf *tx_buf;
+- u32 xsk_frames;
+- u16 i;
+-
+- next_dd_desc = ICE_TX_DESC(xdp_ring, next_dd);
+- if (!(next_dd_desc->cmd_type_offset_bsz &
+- cpu_to_le64(ICE_TX_DESC_DTYPE_DESC_DONE)))
+- break;
++ u16 ntc = xdp_ring->next_to_clean;
++ struct ice_tx_desc *tx_desc;
++ u16 cnt = xdp_ring->count;
++ struct ice_tx_buf *tx_buf;
++ u16 xsk_frames = 0;
++ u16 last_rs;
++ int i;
+
+- cleared_dds++;
+- xsk_frames = 0;
+- if (likely(!xdp_ring->xdp_tx_active)) {
+- xsk_frames = tx_thresh;
+- goto skip;
+- }
++ last_rs = xdp_ring->next_to_use ? xdp_ring->next_to_use - 1 : cnt - 1;
++ tx_desc = ICE_TX_DESC(xdp_ring, last_rs);
++ if ((tx_desc->cmd_type_offset_bsz &
++ cpu_to_le64(ICE_TX_DESC_DTYPE_DESC_DONE))) {
++ if (last_rs >= ntc)
++ xsk_frames = last_rs - ntc + 1;
++ else
++ xsk_frames = last_rs + cnt - ntc + 1;
++ }
+
+- ntc = xdp_ring->next_to_clean;
++ if (!xsk_frames)
++ return;
+
+- for (i = 0; i < tx_thresh; i++) {
+- tx_buf = &xdp_ring->tx_buf[ntc];
++ if (likely(!xdp_ring->xdp_tx_active))
++ goto skip;
+
+- if (tx_buf->raw_buf) {
+- ice_clean_xdp_tx_buf(xdp_ring, tx_buf);
+- tx_buf->raw_buf = NULL;
+- } else {
+- xsk_frames++;
+- }
++ ntc = xdp_ring->next_to_clean;
++ for (i = 0; i < xsk_frames; i++) {
++ tx_buf = &xdp_ring->tx_buf[ntc];
+
+- ntc++;
+- if (ntc >= xdp_ring->count)
+- ntc = 0;
++ if (tx_buf->raw_buf) {
++ ice_clean_xdp_tx_buf(xdp_ring, tx_buf);
++ tx_buf->raw_buf = NULL;
++ } else {
++ xsk_frames++;
+ }
++
++ ntc++;
++ if (ntc >= xdp_ring->count)
++ ntc = 0;
++ }
+ skip:
+- xdp_ring->next_to_clean += tx_thresh;
+- if (xdp_ring->next_to_clean >= desc_cnt)
+- xdp_ring->next_to_clean -= desc_cnt;
+- if (xsk_frames)
+- xsk_tx_completed(xdp_ring->xsk_pool, xsk_frames);
+- next_dd_desc->cmd_type_offset_bsz = 0;
+- next_dd = next_dd + tx_thresh;
+- if (next_dd >= desc_cnt)
+- next_dd = tx_thresh - 1;
+- } while (--budget);
+-
+- xdp_ring->next_dd = next_dd;
+-
+- return cleared_dds * tx_thresh;
++ tx_desc->cmd_type_offset_bsz = 0;
++ xdp_ring->next_to_clean += xsk_frames;
++ if (xdp_ring->next_to_clean >= cnt)
++ xdp_ring->next_to_clean -= cnt;
++ if (xsk_frames)
++ xsk_tx_completed(xdp_ring->xsk_pool, xsk_frames);
+ }
+
+ /**
+@@ -885,7 +873,6 @@ static void ice_xmit_pkt(struct ice_tx_ring *xdp_ring, struct xdp_desc *desc,
+ static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *descs,
+ unsigned int *total_bytes)
+ {
+- u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
+ u16 ntu = xdp_ring->next_to_use;
+ struct ice_tx_desc *tx_desc;
+ u32 i;
+@@ -905,13 +892,6 @@ static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *de
+ }
+
+ xdp_ring->next_to_use = ntu;
+-
+- if (xdp_ring->next_to_use > xdp_ring->next_rs) {
+- tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_rs);
+- tx_desc->cmd_type_offset_bsz |=
+- cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
+- xdp_ring->next_rs += tx_thresh;
+- }
+ }
+
+ /**
+@@ -924,7 +904,6 @@ static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *de
+ static void ice_fill_tx_hw_ring(struct ice_tx_ring *xdp_ring, struct xdp_desc *descs,
+ u32 nb_pkts, unsigned int *total_bytes)
+ {
+- u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
+ u32 batched, leftover, i;
+
+ batched = ALIGN_DOWN(nb_pkts, PKTS_PER_BATCH);
+@@ -933,54 +912,54 @@ static void ice_fill_tx_hw_ring(struct ice_tx_ring *xdp_ring, struct xdp_desc *d
+ ice_xmit_pkt_batch(xdp_ring, &descs[i], total_bytes);
+ for (; i < batched + leftover; i++)
+ ice_xmit_pkt(xdp_ring, &descs[i], total_bytes);
++}
+
+- if (xdp_ring->next_to_use > xdp_ring->next_rs) {
+- struct ice_tx_desc *tx_desc;
++/**
++ * ice_set_rs_bit - set RS bit on last produced descriptor (one behind current NTU)
++ * @xdp_ring: XDP ring to produce the HW Tx descriptors on
++ */
++static void ice_set_rs_bit(struct ice_tx_ring *xdp_ring)
++{
++ u16 ntu = xdp_ring->next_to_use ? xdp_ring->next_to_use - 1 : xdp_ring->count - 1;
++ struct ice_tx_desc *tx_desc;
+
+- tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_rs);
+- tx_desc->cmd_type_offset_bsz |=
+- cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
+- xdp_ring->next_rs += tx_thresh;
+- }
++ tx_desc = ICE_TX_DESC(xdp_ring, ntu);
++ tx_desc->cmd_type_offset_bsz |=
++ cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
+ }
+
+ /**
+ * ice_xmit_zc - take entries from XSK Tx ring and place them onto HW Tx ring
+ * @xdp_ring: XDP ring to produce the HW Tx descriptors on
+- * @budget: number of free descriptors on HW Tx ring that can be used
+- * @napi_budget: amount of descriptors that NAPI allows us to clean
+ *
+ * Returns true if there is no more work that needs to be done, false otherwise
+ */
+-bool ice_xmit_zc(struct ice_tx_ring *xdp_ring, u32 budget, int napi_budget)
++bool ice_xmit_zc(struct ice_tx_ring *xdp_ring)
+ {
+ struct xdp_desc *descs = xdp_ring->xsk_pool->tx_descs;
+- u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
+ u32 nb_pkts, nb_processed = 0;
+ unsigned int total_bytes = 0;
++ int budget;
++
++ ice_clean_xdp_irq_zc(xdp_ring);
+
+- if (budget < tx_thresh)
+- budget += ice_clean_xdp_irq_zc(xdp_ring, napi_budget);
++ budget = ICE_DESC_UNUSED(xdp_ring);
++ budget = min_t(u16, budget, ICE_RING_QUARTER(xdp_ring));
+
+ nb_pkts = xsk_tx_peek_release_desc_batch(xdp_ring->xsk_pool, budget);
+ if (!nb_pkts)
+ return true;
+
+ if (xdp_ring->next_to_use + nb_pkts >= xdp_ring->count) {
+- struct ice_tx_desc *tx_desc;
+-
+ nb_processed = xdp_ring->count - xdp_ring->next_to_use;
+ ice_fill_tx_hw_ring(xdp_ring, descs, nb_processed, &total_bytes);
+- tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_rs);
+- tx_desc->cmd_type_offset_bsz |=
+- cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
+- xdp_ring->next_rs = tx_thresh - 1;
+ xdp_ring->next_to_use = 0;
+ }
+
+ ice_fill_tx_hw_ring(xdp_ring, &descs[nb_processed], nb_pkts - nb_processed,
+ &total_bytes);
+
++ ice_set_rs_bit(xdp_ring);
+ ice_xdp_ring_update_tail(xdp_ring);
+ ice_update_tx_ring_stats(xdp_ring, nb_pkts, total_bytes);
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.h b/drivers/net/ethernet/intel/ice/ice_xsk.h
+index 4edbe81eb646..6fa181f080ef 100644
+--- a/drivers/net/ethernet/intel/ice/ice_xsk.h
++++ b/drivers/net/ethernet/intel/ice/ice_xsk.h
+@@ -26,13 +26,10 @@ bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count);
+ bool ice_xsk_any_rx_ring_ena(struct ice_vsi *vsi);
+ void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring);
+ void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring);
+-bool ice_xmit_zc(struct ice_tx_ring *xdp_ring, u32 budget, int napi_budget);
++bool ice_xmit_zc(struct ice_tx_ring *xdp_ring);
+ int ice_realloc_zc_buf(struct ice_vsi *vsi, bool zc);
+ #else
+-static inline bool
+-ice_xmit_zc(struct ice_tx_ring __always_unused *xdp_ring,
+- u32 __always_unused budget,
+- int __always_unused napi_budget)
++static inline bool ice_xmit_zc(struct ice_tx_ring __always_unused *xdp_ring)
+ {
+ return false;
+ }
+--
+2.35.1
+
--- /dev/null
+From b1287dd68c7951b4880ded64862e1716fbf90df1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Sep 2022 12:40:40 +0200
+Subject: ice: xsk: drop power of 2 ring size restriction for AF_XDP
+
+From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+
+[ Upstream commit b3056ae2b57858b02b376b3fed6077040caf14b4 ]
+
+We had multiple customers in the past months that reported commit
+296f13ff3854 ("ice: xsk: Force rings to be sized to power of 2")
+makes them unable to use ring size of 8160 in conjunction with AF_XDP.
+Remove this restriction.
+
+Fixes: 296f13ff3854 ("ice: xsk: Force rings to be sized to power of 2")
+CC: Alasdair McWilliam <alasdair.mcwilliam@outlook.com>
+Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Tested-by: George Kuruvinakunnel <george.kuruvinakunnel@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_xsk.c | 20 +++++++-------------
+ 1 file changed, 7 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
+index 8833b66b4e54..056c904b83cc 100644
+--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
++++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
+@@ -392,13 +392,6 @@ int ice_xsk_pool_setup(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)
+ goto failure;
+ }
+
+- if (!is_power_of_2(vsi->rx_rings[qid]->count) ||
+- !is_power_of_2(vsi->tx_rings[qid]->count)) {
+- netdev_err(vsi->netdev, "Please align ring sizes to power of 2\n");
+- pool_failure = -EINVAL;
+- goto failure;
+- }
+-
+ if_running = netif_running(vsi->netdev) && ice_is_xdp_ena_vsi(vsi);
+
+ if (if_running) {
+@@ -534,11 +527,10 @@ static bool __ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count)
+ bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count)
+ {
+ u16 rx_thresh = ICE_RING_QUARTER(rx_ring);
+- u16 batched, leftover, i, tail_bumps;
++ u16 leftover, i, tail_bumps;
+
+- batched = ALIGN_DOWN(count, rx_thresh);
+- tail_bumps = batched / rx_thresh;
+- leftover = count & (rx_thresh - 1);
++ tail_bumps = count / rx_thresh;
++ leftover = count - (tail_bumps * rx_thresh);
+
+ for (i = 0; i < tail_bumps; i++)
+ if (!__ice_alloc_rx_bufs_zc(rx_ring, rx_thresh))
+@@ -1037,14 +1029,16 @@ bool ice_xsk_any_rx_ring_ena(struct ice_vsi *vsi)
+ */
+ void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring)
+ {
+- u16 count_mask = rx_ring->count - 1;
+ u16 ntc = rx_ring->next_to_clean;
+ u16 ntu = rx_ring->next_to_use;
+
+- for ( ; ntc != ntu; ntc = (ntc + 1) & count_mask) {
++ while (ntc != ntu) {
+ struct xdp_buff *xdp = *ice_xdp_buf(rx_ring, ntc);
+
+ xsk_buff_free(xdp);
++ ntc++;
++ if (ntc >= rx_ring->count)
++ ntc = 0;
+ }
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 66092630107c983b98459f718d755a9e62b1bf68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 24 Sep 2022 11:07:15 +0800
+Subject: Input: melfas_mip4 - fix return value check in mip4_probe()
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit a54dc27bd25f20ee3ea2009584b3166d25178243 ]
+
+devm_gpiod_get_optional() may return ERR_PTR(-EPROBE_DEFER),
+add a minus sign to fix it.
+
+Fixes: 6ccb1d8f78bd ("Input: add MELFAS MIP4 Touchscreen driver")
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Link: https://lore.kernel.org/r/20220924030715.1653538-1-yangyingliang@huawei.com
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/touchscreen/melfas_mip4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
+index 2745bf1aee38..83f4be05e27b 100644
+--- a/drivers/input/touchscreen/melfas_mip4.c
++++ b/drivers/input/touchscreen/melfas_mip4.c
+@@ -1453,7 +1453,7 @@ static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ "ce", GPIOD_OUT_LOW);
+ if (IS_ERR(ts->gpio_ce)) {
+ error = PTR_ERR(ts->gpio_ce);
+- if (error != EPROBE_DEFER)
++ if (error != -EPROBE_DEFER)
+ dev_err(&client->dev,
+ "Failed to get gpio: %d\n", error);
+ return error;
+--
+2.35.1
+
--- /dev/null
+From 827f850631dc39a7aea68c52fe0d64123ac81167 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Sep 2022 16:18:54 -0700
+Subject: KVM: x86: Hide IA32_PLATFORM_DCA_CAP[31:0] from the guest
+
+From: Jim Mattson <jmattson@google.com>
+
+[ Upstream commit aae2e72229cdb21f90df2dbe4244c977e5d3265b ]
+
+The only thing reported by CPUID.9 is the value of
+IA32_PLATFORM_DCA_CAP[31:0] in EAX. This MSR doesn't even exist in the
+guest, since CPUID.1:ECX.DCA[bit 18] is clear in the guest.
+
+Clear CPUID.9 in KVM_GET_SUPPORTED_CPUID.
+
+Fixes: 24c82e576b78 ("KVM: Sanitize cpuid")
+Signed-off-by: Jim Mattson <jmattson@google.com>
+Message-Id: <20220922231854.249383-1-jmattson@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/cpuid.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
+index 3ab498165639..cb14441cee37 100644
+--- a/arch/x86/kvm/cpuid.c
++++ b/arch/x86/kvm/cpuid.c
+@@ -870,8 +870,6 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
+ entry->edx = 0;
+ }
+ break;
+- case 9:
+- break;
+ case 0xa: { /* Architectural Performance Monitoring */
+ struct x86_pmu_capability cap;
+ union cpuid10_eax eax;
+--
+2.35.1
+
--- /dev/null
+From cef396fb50fde98ec11f41b8b068d5dad362feed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Sep 2022 16:30:02 +0100
+Subject: net: ethernet: mtk_eth_soc: fix mask of RX_DMA_GET_SPORT{,_V2}
+
+From: Daniel Golle <daniel@makrotopia.org>
+
+[ Upstream commit c9da02bfb1112461e048d3b736afb1873f6f4ccf ]
+
+The bitmasks applied in RX_DMA_GET_SPORT and RX_DMA_GET_SPORT_V2 macros
+were swapped. Fix that.
+
+Reported-by: Chen Minqiang <ptpt52@gmail.com>
+Fixes: 160d3a9b192985 ("net: ethernet: mtk_eth_soc: introduce MTK_NETSYS_V2 support")
+Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Link: https://lore.kernel.org/r/YzMW+mg9UsaCdKRQ@makrotopia.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+index 98d6a6d047e3..c1fe1a2cb746 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -312,8 +312,8 @@
+ #define MTK_RXD5_PPE_CPU_REASON GENMASK(22, 18)
+ #define MTK_RXD5_SRC_PORT GENMASK(29, 26)
+
+-#define RX_DMA_GET_SPORT(x) (((x) >> 19) & 0xf)
+-#define RX_DMA_GET_SPORT_V2(x) (((x) >> 26) & 0x7)
++#define RX_DMA_GET_SPORT(x) (((x) >> 19) & 0x7)
++#define RX_DMA_GET_SPORT_V2(x) (((x) >> 26) & 0xf)
+
+ /* PDMA V2 descriptor rxd3 */
+ #define RX_DMA_VTAG_V2 BIT(0)
+--
+2.35.1
+
--- /dev/null
+From f628388172818793eab881b054ca7751d9fc68ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Sep 2022 19:06:10 +0530
+Subject: net: macb: Fix ZynqMP SGMII non-wakeup source resume failure
+
+From: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+
+[ Upstream commit f22bd29ba19a43e758b192429613e04aa7abb70d ]
+
+When GEM is in SGMII mode and disabled as a wakeup source, the power
+management controller can power down the entire full power domain(FPD)
+if none of the FPD devices are in use.
+
+Incase of FPD off, there are below ethernet link up issues on non-wakeup
+suspend/resume. To fix it add phy_exit() in suspend and phy_init() in the
+resume path which reinitializes PS GTR SGMII lanes.
+
+$ echo +20 > /sys/class/rtc/rtc0/wakealarm
+$ echo mem > /sys/power/state
+
+After resume:
+
+$ ifconfig eth0 up
+xilinx-psgtr fd400000.phy: lane 0 (type 10, protocol 5): PLL lock timeout
+phy phy-fd400000.phy.0: phy poweron failed --> -110
+xilinx-psgtr fd400000.phy: lane 0 (type 10, protocol 5): PLL lock timeout
+SIOCSIFFLAGS: Connection timed out
+phy phy-fd400000.phy.0: phy poweron failed --> -110
+
+Fixes: 8b73fa3ae02b ("net: macb: Added ZynqMP-specific initialization")
+Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/cadence/macb_main.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
+index d89098f4ede8..e9aa41949a4b 100644
+--- a/drivers/net/ethernet/cadence/macb_main.c
++++ b/drivers/net/ethernet/cadence/macb_main.c
+@@ -5092,6 +5092,7 @@ static int __maybe_unused macb_suspend(struct device *dev)
+ if (!(bp->wol & MACB_WOL_ENABLED)) {
+ rtnl_lock();
+ phylink_stop(bp->phylink);
++ phy_exit(bp->sgmii_phy);
+ rtnl_unlock();
+ spin_lock_irqsave(&bp->lock, flags);
+ macb_reset_hw(bp);
+@@ -5181,6 +5182,9 @@ static int __maybe_unused macb_resume(struct device *dev)
+ macb_set_rx_mode(netdev);
+ macb_restore_features(bp);
+ rtnl_lock();
++ if (!device_may_wakeup(&bp->dev->dev))
++ phy_init(bp->sgmii_phy);
++
+ phylink_start(bp->phylink);
+ rtnl_unlock();
+
+--
+2.35.1
+
--- /dev/null
+From 13d1197739e4f9f29cb03e3ba1024aa7ddc2aff5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Sep 2022 02:36:40 +0000
+Subject: net/mlxbf_gige: Fix an IS_ERR() vs NULL bug in mlxbf_gige_mdio_probe
+
+From: Peng Wu <wupeng58@huawei.com>
+
+[ Upstream commit 4774db8dfc6a2e6649920ebb2fc8e2f062c2080d ]
+
+The devm_ioremap() function returns NULL on error, it doesn't return
+error pointers.
+
+Fixes: 3a1a274e933f ("mlxbf_gige: compute MDIO period based on i1clk")
+Signed-off-by: Peng Wu <wupeng58@huawei.com>
+Link: https://lore.kernel.org/r/20220923023640.116057-1-wupeng58@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
+index 4aeb927c3715..aa780b1614a3 100644
+--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
+@@ -246,8 +246,8 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
+ }
+
+ priv->clk_io = devm_ioremap(dev, res->start, resource_size(res));
+- if (IS_ERR(priv->clk_io))
+- return PTR_ERR(priv->clk_io);
++ if (!priv->clk_io)
++ return -ENOMEM;
+
+ mlxbf_gige_mdio_cfg(priv);
+
+--
+2.35.1
+
--- /dev/null
+From 0ddff6a150f6ade4dcf05ed74ed14056ec9db3dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Sep 2022 15:20:42 +0300
+Subject: net: mscc: ocelot: fix tagged VLAN refusal while under a VLAN-unaware
+ bridge
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 276d37eb449133bc22872b8f0a6f878e120deeff ]
+
+Currently the following set of commands fails:
+
+$ ip link add br0 type bridge # vlan_filtering 0
+$ ip link set swp0 master br0
+$ bridge vlan
+port vlan-id
+swp0 1 PVID Egress Untagged
+$ bridge vlan add dev swp0 vid 10
+Error: mscc_ocelot_switch_lib: Port with more than one egress-untagged VLAN cannot have egress-tagged VLANs.
+
+Dumping ocelot->vlans, one can see that the 2 egress-untagged VLANs on swp0 are
+vid 1 (the bridge PVID) and vid 4094, a PVID used privately by the driver for
+VLAN-unaware bridging. So this is why bridge vid 10 is refused, despite
+'bridge vlan' showing a single egress untagged VLAN.
+
+As mentioned in the comment added, having this private VLAN does not impose
+restrictions to the hardware configuration, yet it is a bookkeeping problem.
+
+There are 2 possible solutions.
+
+One is to make the functions that operate on VLAN-unaware pvids:
+- ocelot_add_vlan_unaware_pvid()
+- ocelot_del_vlan_unaware_pvid()
+- ocelot_port_setup_dsa_8021q_cpu()
+- ocelot_port_teardown_dsa_8021q_cpu()
+call something different than ocelot_vlan_member_(add|del)(), the latter being
+the real problem, because it allocates a struct ocelot_bridge_vlan *vlan which
+it adds to ocelot->vlans. We don't really *need* the private VLANs in
+ocelot->vlans, it's just that we have the extra convenience of having the
+vlan->portmask cached in software (whereas without these structures, we'd have
+to create a raw ocelot_vlant_rmw_mask() procedure which reads back the current
+port mask from hardware).
+
+The other solution is to filter out the private VLANs from
+ocelot_port_num_untagged_vlans(), since they aren't what callers care about.
+We only need to do this to the mentioned function and not to
+ocelot_port_num_tagged_vlans(), because private VLANs are never egress-tagged.
+
+Nothing else seems to be broken in either solution, but the first one requires
+more rework which will conflict with the net-next change 36a0bf443585 ("net:
+mscc: ocelot: set up tag_8021q CPU ports independent of user port affinity"),
+and I'd like to avoid that. So go with the other one.
+
+Fixes: 54c319846086 ("net: mscc: ocelot: enforce FDB isolation when VLAN-unaware")
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Link: https://lore.kernel.org/r/20220927122042.1100231-1-vladimir.oltean@nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mscc/ocelot.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
+index 68991b021c56..c250ad6dc956 100644
+--- a/drivers/net/ethernet/mscc/ocelot.c
++++ b/drivers/net/ethernet/mscc/ocelot.c
+@@ -290,6 +290,13 @@ static int ocelot_port_num_untagged_vlans(struct ocelot *ocelot, int port)
+ if (!(vlan->portmask & BIT(port)))
+ continue;
+
++ /* Ignore the VLAN added by ocelot_add_vlan_unaware_pvid(),
++ * because this is never active in hardware at the same time as
++ * the bridge VLANs, which only matter in VLAN-aware mode.
++ */
++ if (vlan->vid >= OCELOT_RSV_VLAN_RANGE_START)
++ continue;
++
+ if (vlan->untagged & BIT(port))
+ num_untagged++;
+ }
+--
+2.35.1
+
--- /dev/null
+From d5d5902b31101076a1e35308d915abce6c808bac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Sep 2022 06:09:52 +0200
+Subject: net: phy: Don't WARN for PHY_UP state in mdio_bus_phy_resume()
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit ea64cdfad124922c931633e39287c5a31a9b14a1 ]
+
+Commit 744d23c71af3 ("net: phy: Warn about incorrect mdio_bus_phy_resume()
+state") introduced a WARN() on resume from system sleep if a PHY is not
+in PHY_HALTED state.
+
+Commit 6dbe852c379f ("net: phy: Don't WARN for PHY_READY state in
+mdio_bus_phy_resume()") added an exemption for PHY_READY state from
+the WARN().
+
+It turns out PHY_UP state needs to be exempted as well because the
+following may happen on suspend:
+
+ mdio_bus_phy_suspend()
+ phy_stop_machine()
+ phydev->state = PHY_UP # if (phydev->state >= PHY_UP)
+
+Fixes: 744d23c71af3 ("net: phy: Warn about incorrect mdio_bus_phy_resume() state")
+Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Link: https://lore.kernel.org/netdev/2b1a1588-505e-dff3-301d-bfc1fb14d685@samsung.com/
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+Cc: Xiaolei Wang <xiaolei.wang@windriver.com>
+Link: https://lore.kernel.org/r/8128fdb51eeebc9efbf3776a4097363a1317aaf1.1663905575.git.lukas@wunner.de
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/phy_device.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index f90a21781d8d..adc9d97cbb88 100644
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -316,11 +316,13 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
+
+ phydev->suspended_by_mdio_bus = 0;
+
+- /* If we manged to get here with the PHY state machine in a state neither
+- * PHY_HALTED nor PHY_READY this is an indication that something went wrong
+- * and we should most likely be using MAC managed PM and we are not.
++ /* If we managed to get here with the PHY state machine in a state
++ * neither PHY_HALTED, PHY_READY nor PHY_UP, this is an indication
++ * that something went wrong and we should most likely be using
++ * MAC managed PM, but we are not.
+ */
+- WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY);
++ WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY &&
++ phydev->state != PHY_UP);
+
+ ret = phy_init_hw(phydev);
+ if (ret < 0)
+--
+2.35.1
+
--- /dev/null
+From f241f40b72fd649f34f8b7232385263990ee47f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Sep 2022 10:00:46 +0800
+Subject: net: sched: act_ct: fix possible refcount leak in tcf_ct_init()
+
+From: Hangyu Hua <hbh25y@gmail.com>
+
+[ Upstream commit 6e23ec0ba92d426c77a73a9ccab16346e5e0ef49 ]
+
+nf_ct_put need to be called to put the refcount got by tcf_ct_fill_params
+to avoid possible refcount leak when tcf_ct_flow_table_get fails.
+
+Fixes: c34b961a2492 ("net/sched: act_ct: Create nf flow table per zone")
+Signed-off-by: Hangyu Hua <hbh25y@gmail.com>
+Link: https://lore.kernel.org/r/20220923020046.8021-1-hbh25y@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_ct.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
+index e013253b10d1..4d44a1bf4a04 100644
+--- a/net/sched/act_ct.c
++++ b/net/sched/act_ct.c
+@@ -1393,7 +1393,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
+
+ err = tcf_ct_flow_table_get(params);
+ if (err)
+- goto cleanup;
++ goto cleanup_params;
+
+ spin_lock_bh(&c->tcf_lock);
+ goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
+@@ -1408,6 +1408,9 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
+
+ return res;
+
++cleanup_params:
++ if (params->tmpl)
++ nf_ct_put(params->tmpl);
+ cleanup:
+ if (goto_ch)
+ tcf_chain_put_by_act(goto_ch);
+--
+2.35.1
+
--- /dev/null
+From dee91ab757964ac15f2f1e37d15df87e08d430a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Sep 2022 13:04:48 +0800
+Subject: net: stmmac: power up/down serdes in stmmac_open/release
+
+From: Junxiao Chang <junxiao.chang@intel.com>
+
+[ Upstream commit 49725ffc15fc4e9fae68c55b691fd25168cbe5c1 ]
+
+This commit fixes DMA engine reset timeout issue in suspend/resume
+with ADLink I-Pi SMARC Plus board which dmesg shows:
+...
+[ 54.678271] PM: suspend exit
+[ 54.754066] intel-eth-pci 0000:00:1d.2 enp0s29f2: PHY [stmmac-3:01] driver [Maxlinear Ethernet GPY215B] (irq=POLL)
+[ 54.755808] intel-eth-pci 0000:00:1d.2 enp0s29f2: Register MEM_TYPE_PAGE_POOL RxQ-0
+...
+[ 54.780482] intel-eth-pci 0000:00:1d.2 enp0s29f2: Register MEM_TYPE_PAGE_POOL RxQ-7
+[ 55.784098] intel-eth-pci 0000:00:1d.2: Failed to reset the dma
+[ 55.784111] intel-eth-pci 0000:00:1d.2 enp0s29f2: stmmac_hw_setup: DMA engine initialization failed
+[ 55.784115] intel-eth-pci 0000:00:1d.2 enp0s29f2: stmmac_open: Hw setup failed
+...
+
+The issue is related with serdes which impacts clock. There is
+serdes in ADLink I-Pi SMARC board ethernet controller. Please refer to
+commit b9663b7ca6ff78 ("net: stmmac: Enable SERDES power up/down sequence")
+for detial. When issue is reproduced, DMA engine clock is not ready
+because serdes is not powered up.
+
+To reproduce DMA engine reset timeout issue with hardware which has
+serdes in GBE controller, install Ubuntu. In Ubuntu GUI, click
+"Power Off/Log Out" -> "Suspend" menu, it disables network interface,
+then goes to sleep mode. When it wakes up, it enables network
+interface again. Stmmac driver is called in this way:
+
+1. stmmac_release: Stop network interface. In this function, it
+ disables DMA engine and network interface;
+2. stmmac_suspend: It is called in kernel suspend flow. But because
+ network interface has been disabled(netif_running(ndev) is
+ false), it does nothing and returns directly;
+3. System goes into S3 or S0ix state. Some time later, system is
+ waken up by keyboard or mouse;
+4. stmmac_resume: It does nothing because network interface has
+ been disabled;
+5. stmmac_open: It is called to enable network interace again. DMA
+ engine is initialized in this API, but serdes is not power on so
+ there will be DMA engine reset timeout issue.
+
+Similarly, serdes powerdown should be added in stmmac_release.
+Network interface might be disabled by cmd "ifconfig eth0 down",
+DMA engine, phy and mac have been disabled in ndo_stop callback,
+serdes should be powered down as well. It doesn't make sense that
+serdes is on while other components have been turned off.
+
+If ethernet interface is in enabled state(netif_running(ndev) is true)
+before suspend/resume, the issue couldn't be reproduced because serdes
+could be powered up in stmmac_resume.
+
+Because serdes_powerup is added in stmmac_open, it doesn't need to be
+called in probe function.
+
+Fixes: b9663b7ca6ff78 ("net: stmmac: Enable SERDES power up/down sequence")
+Signed-off-by: Junxiao Chang <junxiao.chang@intel.com>
+Reviewed-by: Voon Weifeng <weifeng.voon@intel.com>
+Tested-by: Jimmy JS Chen <jimmyjs.chen@adlinktech.com>
+Tested-by: Looi, Hong Aun <hong.aun.looi@intel.com>
+Link: https://lore.kernel.org/r/20220923050448.1220250-1-junxiao.chang@intel.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 23 +++++++++++--------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 78f11dabca05..8d9272f01e31 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -3704,6 +3704,15 @@ static int stmmac_open(struct net_device *dev)
+ goto init_error;
+ }
+
++ if (priv->plat->serdes_powerup) {
++ ret = priv->plat->serdes_powerup(dev, priv->plat->bsp_priv);
++ if (ret < 0) {
++ netdev_err(priv->dev, "%s: Serdes powerup failed\n",
++ __func__);
++ goto init_error;
++ }
++ }
++
+ ret = stmmac_hw_setup(dev, true);
+ if (ret < 0) {
+ netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
+@@ -3793,6 +3802,10 @@ static int stmmac_release(struct net_device *dev)
+ /* Disable the MAC Rx/Tx */
+ stmmac_mac_set(priv, priv->ioaddr, false);
+
++ /* Powerdown Serdes if there is */
++ if (priv->plat->serdes_powerdown)
++ priv->plat->serdes_powerdown(dev, priv->plat->bsp_priv);
++
+ netif_carrier_off(dev);
+
+ stmmac_release_ptp(priv);
+@@ -7158,14 +7171,6 @@ int stmmac_dvr_probe(struct device *device,
+ goto error_netdev_register;
+ }
+
+- if (priv->plat->serdes_powerup) {
+- ret = priv->plat->serdes_powerup(ndev,
+- priv->plat->bsp_priv);
+-
+- if (ret < 0)
+- goto error_serdes_powerup;
+- }
+-
+ #ifdef CONFIG_DEBUG_FS
+ stmmac_init_fs(ndev);
+ #endif
+@@ -7180,8 +7185,6 @@ int stmmac_dvr_probe(struct device *device,
+
+ return ret;
+
+-error_serdes_powerup:
+- unregister_netdev(ndev);
+ error_netdev_register:
+ phylink_destroy(priv->phylink);
+ error_xpcs_setup:
+--
+2.35.1
+
--- /dev/null
+From 7c002dcfb951f2c4d3fed273d45086531059e2c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Sep 2022 21:49:09 -0700
+Subject: nvme: Fix IOC_PR_CLEAR and IOC_PR_RELEASE ioctls for nvme devices
+
+From: Michael Kelley <mikelley@microsoft.com>
+
+[ Upstream commit c292a337d0e45a292c301e3cd51c35aa0ae91e95 ]
+
+The IOC_PR_CLEAR and IOC_PR_RELEASE ioctls are
+non-functional on NVMe devices because the nvme_pr_clear()
+and nvme_pr_release() functions set the IEKEY field incorrectly.
+The IEKEY field should be set only when the key is zero (i.e,
+not specified). The current code does it backwards.
+
+Furthermore, the NVMe spec describes the persistent
+reservation "clear" function as an option on the reservation
+release command. The current implementation of nvme_pr_clear()
+erroneously uses the reservation register command.
+
+Fix these errors. Note that NVMe version 1.3 and later specify
+that setting the IEKEY field will return an error of Invalid
+Field in Command. The fix will set IEKEY when the key is zero,
+which is appropriate as these ioctls consider a zero key to
+be "unspecified", and the intention of the spec change is
+to require a valid key.
+
+Tested on a version 1.4 PCI NVMe device in an Azure VM.
+
+Fixes: 1673f1f08c88 ("nvme: move block_device_operations and ns/ctrl freeing to common code")
+Fixes: 1d277a637a71 ("NVMe: Add persistent reservation ops")
+Signed-off-by: Michael Kelley <mikelley@microsoft.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/core.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 6d76fc608b74..326ad33537ed 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -2069,14 +2069,14 @@ static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new,
+
+ static int nvme_pr_clear(struct block_device *bdev, u64 key)
+ {
+- u32 cdw10 = 1 | (key ? 1 << 3 : 0);
++ u32 cdw10 = 1 | (key ? 0 : 1 << 3);
+
+- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_register);
++ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ }
+
+ static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
+ {
+- u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 1 << 3 : 0);
++ u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 0 : 1 << 3);
+
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ }
+--
+2.35.1
+
--- /dev/null
+From a25650f8fe8b8590684391276eb3a366c5d07d63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Jul 2022 13:42:17 -0700
+Subject: perf parse-events: Break out tracepoint and printing
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 9b7c7728f4e4ba8dd75269fb111fa187faa018c6 ]
+
+Move print_*_events functions out of parse-events.c into a new
+print-events.c. Move tracepoint code into tracepoint.c or
+trace-event-info.c (sole user). This reduces the dependencies of
+parse-events.c and makes it more amenable to being a library in the
+future.
+
+Remove some unnecessary definitions from parse-events.h. Fix a
+checkpatch.pl warning on using unsigned rather than unsigned int. Fix
+some line length warnings too.
+
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Stephane Eranian <eranian@google.com>
+Link: https://lore.kernel.org/r/20220729204217.250166-3-irogers@google.com
+[ Add include linux/stddef.h before perf_events.h for systems where __always_inline isn't pulled in before used, such as older Alpine Linux ]
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: 71c86cda750b ("perf parse-events: Remove "not supported" hybrid cache events")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-list.c | 2 +-
+ tools/perf/builtin-lock.c | 1 +
+ tools/perf/builtin-timechart.c | 1 +
+ tools/perf/builtin-trace.c | 1 +
+ tools/perf/util/Build | 2 +
+ tools/perf/util/parse-events.c | 713 +----------------------------
+ tools/perf/util/parse-events.h | 31 --
+ tools/perf/util/print-events.c | 572 +++++++++++++++++++++++
+ tools/perf/util/print-events.h | 22 +
+ tools/perf/util/trace-event-info.c | 96 ++++
+ tools/perf/util/tracepoint.c | 63 +++
+ tools/perf/util/tracepoint.h | 25 +
+ 12 files changed, 791 insertions(+), 738 deletions(-)
+ create mode 100644 tools/perf/util/print-events.c
+ create mode 100644 tools/perf/util/print-events.h
+ create mode 100644 tools/perf/util/tracepoint.c
+ create mode 100644 tools/perf/util/tracepoint.h
+
+diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
+index 468958154ed9..744dd3520584 100644
+--- a/tools/perf/builtin-list.c
++++ b/tools/perf/builtin-list.c
+@@ -10,7 +10,7 @@
+ */
+ #include "builtin.h"
+
+-#include "util/parse-events.h"
++#include "util/print-events.h"
+ #include "util/pmu.h"
+ #include "util/pmu-hybrid.h"
+ #include "util/debug.h"
+diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
+index 23a33ac15e68..dcc079a80585 100644
+--- a/tools/perf/builtin-lock.c
++++ b/tools/perf/builtin-lock.c
+@@ -13,6 +13,7 @@
+ #include <subcmd/pager.h>
+ #include <subcmd/parse-options.h>
+ #include "util/trace-event.h"
++#include "util/tracepoint.h"
+
+ #include "util/debug.h"
+ #include "util/session.h"
+diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
+index afce731cec16..e2e9ad929baf 100644
+--- a/tools/perf/builtin-timechart.c
++++ b/tools/perf/builtin-timechart.c
+@@ -36,6 +36,7 @@
+ #include "util/data.h"
+ #include "util/debug.h"
+ #include "util/string2.h"
++#include "util/tracepoint.h"
+ #include <linux/err.h>
+
+ #ifdef LACKS_OPEN_MEMSTREAM_PROTOTYPE
+diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
+index f075cf37a65e..1e1f10a1971d 100644
+--- a/tools/perf/builtin-trace.c
++++ b/tools/perf/builtin-trace.c
+@@ -53,6 +53,7 @@
+ #include "trace-event.h"
+ #include "util/parse-events.h"
+ #include "util/bpf-loader.h"
++#include "util/tracepoint.h"
+ #include "callchain.h"
+ #include "print_binary.h"
+ #include "string2.h"
+diff --git a/tools/perf/util/Build b/tools/perf/util/Build
+index a51267d88ca9..038e4cf8f488 100644
+--- a/tools/perf/util/Build
++++ b/tools/perf/util/Build
+@@ -26,6 +26,8 @@ perf-y += mmap.o
+ perf-y += memswap.o
+ perf-y += parse-events.o
+ perf-y += parse-events-hybrid.o
++perf-y += print-events.o
++perf-y += tracepoint.o
+ perf-y += perf_regs.o
+ perf-y += path.o
+ perf-y += print_binary.o
+diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
+index 700c95eafd62..3acf7452572c 100644
+--- a/tools/perf/util/parse-events.c
++++ b/tools/perf/util/parse-events.c
+@@ -5,18 +5,12 @@
+ #include <dirent.h>
+ #include <errno.h>
+ #include <sys/ioctl.h>
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#include <fcntl.h>
+ #include <sys/param.h>
+ #include "term.h"
+-#include "build-id.h"
+ #include "evlist.h"
+ #include "evsel.h"
+-#include <subcmd/pager.h>
+ #include <subcmd/parse-options.h>
+ #include "parse-events.h"
+-#include <subcmd/exec-cmd.h>
+ #include "string2.h"
+ #include "strlist.h"
+ #include "bpf-loader.h"
+@@ -27,20 +21,22 @@
+ #define YY_EXTRA_TYPE void*
+ #include "parse-events-flex.h"
+ #include "pmu.h"
+-#include "thread_map.h"
+-#include "probe-file.h"
+ #include "asm/bug.h"
+ #include "util/parse-branch-options.h"
+-#include "metricgroup.h"
+ #include "util/evsel_config.h"
+ #include "util/event.h"
+-#include "util/pfm.h"
++#include "perf.h"
+ #include "util/parse-events-hybrid.h"
+ #include "util/pmu-hybrid.h"
+-#include "perf.h"
++#include "tracepoint.h"
+
+ #define MAX_NAME_LEN 100
+
++struct perf_pmu_event_symbol {
++ char *symbol;
++ enum perf_pmu_event_symbol_type type;
++};
++
+ #ifdef PARSER_DEBUG
+ extern int parse_events_debug;
+ #endif
+@@ -154,21 +150,6 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
+ },
+ };
+
+-struct event_symbol event_symbols_tool[PERF_TOOL_MAX] = {
+- [PERF_TOOL_DURATION_TIME] = {
+- .symbol = "duration_time",
+- .alias = "",
+- },
+- [PERF_TOOL_USER_TIME] = {
+- .symbol = "user_time",
+- .alias = "",
+- },
+- [PERF_TOOL_SYSTEM_TIME] = {
+- .symbol = "system_time",
+- .alias = "",
+- },
+-};
+-
+ #define __PERF_EVENT_FIELD(config, name) \
+ ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
+
+@@ -177,121 +158,6 @@ struct event_symbol event_symbols_tool[PERF_TOOL_MAX] = {
+ #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
+ #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
+
+-#define for_each_subsystem(sys_dir, sys_dirent) \
+- while ((sys_dirent = readdir(sys_dir)) != NULL) \
+- if (sys_dirent->d_type == DT_DIR && \
+- (strcmp(sys_dirent->d_name, ".")) && \
+- (strcmp(sys_dirent->d_name, "..")))
+-
+-static int tp_event_has_id(const char *dir_path, struct dirent *evt_dir)
+-{
+- char evt_path[MAXPATHLEN];
+- int fd;
+-
+- snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dir->d_name);
+- fd = open(evt_path, O_RDONLY);
+- if (fd < 0)
+- return -EINVAL;
+- close(fd);
+-
+- return 0;
+-}
+-
+-#define for_each_event(dir_path, evt_dir, evt_dirent) \
+- while ((evt_dirent = readdir(evt_dir)) != NULL) \
+- if (evt_dirent->d_type == DT_DIR && \
+- (strcmp(evt_dirent->d_name, ".")) && \
+- (strcmp(evt_dirent->d_name, "..")) && \
+- (!tp_event_has_id(dir_path, evt_dirent)))
+-
+-#define MAX_EVENT_LENGTH 512
+-
+-struct tracepoint_path *tracepoint_id_to_path(u64 config)
+-{
+- struct tracepoint_path *path = NULL;
+- DIR *sys_dir, *evt_dir;
+- struct dirent *sys_dirent, *evt_dirent;
+- char id_buf[24];
+- int fd;
+- u64 id;
+- char evt_path[MAXPATHLEN];
+- char *dir_path;
+-
+- sys_dir = tracing_events__opendir();
+- if (!sys_dir)
+- return NULL;
+-
+- for_each_subsystem(sys_dir, sys_dirent) {
+- dir_path = get_events_file(sys_dirent->d_name);
+- if (!dir_path)
+- continue;
+- evt_dir = opendir(dir_path);
+- if (!evt_dir)
+- goto next;
+-
+- for_each_event(dir_path, evt_dir, evt_dirent) {
+-
+- scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
+- evt_dirent->d_name);
+- fd = open(evt_path, O_RDONLY);
+- if (fd < 0)
+- continue;
+- if (read(fd, id_buf, sizeof(id_buf)) < 0) {
+- close(fd);
+- continue;
+- }
+- close(fd);
+- id = atoll(id_buf);
+- if (id == config) {
+- put_events_file(dir_path);
+- closedir(evt_dir);
+- closedir(sys_dir);
+- path = zalloc(sizeof(*path));
+- if (!path)
+- return NULL;
+- if (asprintf(&path->system, "%.*s", MAX_EVENT_LENGTH, sys_dirent->d_name) < 0) {
+- free(path);
+- return NULL;
+- }
+- if (asprintf(&path->name, "%.*s", MAX_EVENT_LENGTH, evt_dirent->d_name) < 0) {
+- zfree(&path->system);
+- free(path);
+- return NULL;
+- }
+- return path;
+- }
+- }
+- closedir(evt_dir);
+-next:
+- put_events_file(dir_path);
+- }
+-
+- closedir(sys_dir);
+- return NULL;
+-}
+-
+-struct tracepoint_path *tracepoint_name_to_path(const char *name)
+-{
+- struct tracepoint_path *path = zalloc(sizeof(*path));
+- char *str = strchr(name, ':');
+-
+- if (path == NULL || str == NULL) {
+- free(path);
+- return NULL;
+- }
+-
+- path->system = strndup(name, str - name);
+- path->name = strdup(str+1);
+-
+- if (path->system == NULL || path->name == NULL) {
+- zfree(&path->system);
+- zfree(&path->name);
+- zfree(&path);
+- }
+-
+- return path;
+-}
+-
+ const char *event_type(int type)
+ {
+ switch (type) {
+@@ -2674,571 +2540,6 @@ int exclude_perf(const struct option *opt,
+ NULL);
+ }
+
+-static const char * const event_type_descriptors[] = {
+- "Hardware event",
+- "Software event",
+- "Tracepoint event",
+- "Hardware cache event",
+- "Raw hardware event descriptor",
+- "Hardware breakpoint",
+-};
+-
+-static int cmp_string(const void *a, const void *b)
+-{
+- const char * const *as = a;
+- const char * const *bs = b;
+-
+- return strcmp(*as, *bs);
+-}
+-
+-/*
+- * Print the events from <debugfs_mount_point>/tracing/events
+- */
+-
+-void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
+- bool name_only)
+-{
+- DIR *sys_dir, *evt_dir;
+- struct dirent *sys_dirent, *evt_dirent;
+- char evt_path[MAXPATHLEN];
+- char *dir_path;
+- char **evt_list = NULL;
+- unsigned int evt_i = 0, evt_num = 0;
+- bool evt_num_known = false;
+-
+-restart:
+- sys_dir = tracing_events__opendir();
+- if (!sys_dir)
+- return;
+-
+- if (evt_num_known) {
+- evt_list = zalloc(sizeof(char *) * evt_num);
+- if (!evt_list)
+- goto out_close_sys_dir;
+- }
+-
+- for_each_subsystem(sys_dir, sys_dirent) {
+- if (subsys_glob != NULL &&
+- !strglobmatch(sys_dirent->d_name, subsys_glob))
+- continue;
+-
+- dir_path = get_events_file(sys_dirent->d_name);
+- if (!dir_path)
+- continue;
+- evt_dir = opendir(dir_path);
+- if (!evt_dir)
+- goto next;
+-
+- for_each_event(dir_path, evt_dir, evt_dirent) {
+- if (event_glob != NULL &&
+- !strglobmatch(evt_dirent->d_name, event_glob))
+- continue;
+-
+- if (!evt_num_known) {
+- evt_num++;
+- continue;
+- }
+-
+- snprintf(evt_path, MAXPATHLEN, "%s:%s",
+- sys_dirent->d_name, evt_dirent->d_name);
+-
+- evt_list[evt_i] = strdup(evt_path);
+- if (evt_list[evt_i] == NULL) {
+- put_events_file(dir_path);
+- goto out_close_evt_dir;
+- }
+- evt_i++;
+- }
+- closedir(evt_dir);
+-next:
+- put_events_file(dir_path);
+- }
+- closedir(sys_dir);
+-
+- if (!evt_num_known) {
+- evt_num_known = true;
+- goto restart;
+- }
+- qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+- evt_i = 0;
+- while (evt_i < evt_num) {
+- if (name_only) {
+- printf("%s ", evt_list[evt_i++]);
+- continue;
+- }
+- printf(" %-50s [%s]\n", evt_list[evt_i++],
+- event_type_descriptors[PERF_TYPE_TRACEPOINT]);
+- }
+- if (evt_num && pager_in_use())
+- printf("\n");
+-
+-out_free:
+- evt_num = evt_i;
+- for (evt_i = 0; evt_i < evt_num; evt_i++)
+- zfree(&evt_list[evt_i]);
+- zfree(&evt_list);
+- return;
+-
+-out_close_evt_dir:
+- closedir(evt_dir);
+-out_close_sys_dir:
+- closedir(sys_dir);
+-
+- printf("FATAL: not enough memory to print %s\n",
+- event_type_descriptors[PERF_TYPE_TRACEPOINT]);
+- if (evt_list)
+- goto out_free;
+-}
+-
+-/*
+- * Check whether event is in <debugfs_mount_point>/tracing/events
+- */
+-
+-int is_valid_tracepoint(const char *event_string)
+-{
+- DIR *sys_dir, *evt_dir;
+- struct dirent *sys_dirent, *evt_dirent;
+- char evt_path[MAXPATHLEN];
+- char *dir_path;
+-
+- sys_dir = tracing_events__opendir();
+- if (!sys_dir)
+- return 0;
+-
+- for_each_subsystem(sys_dir, sys_dirent) {
+- dir_path = get_events_file(sys_dirent->d_name);
+- if (!dir_path)
+- continue;
+- evt_dir = opendir(dir_path);
+- if (!evt_dir)
+- goto next;
+-
+- for_each_event(dir_path, evt_dir, evt_dirent) {
+- snprintf(evt_path, MAXPATHLEN, "%s:%s",
+- sys_dirent->d_name, evt_dirent->d_name);
+- if (!strcmp(evt_path, event_string)) {
+- closedir(evt_dir);
+- closedir(sys_dir);
+- return 1;
+- }
+- }
+- closedir(evt_dir);
+-next:
+- put_events_file(dir_path);
+- }
+- closedir(sys_dir);
+- return 0;
+-}
+-
+-static bool is_event_supported(u8 type, u64 config)
+-{
+- bool ret = true;
+- int open_return;
+- struct evsel *evsel;
+- struct perf_event_attr attr = {
+- .type = type,
+- .config = config,
+- .disabled = 1,
+- };
+- struct perf_thread_map *tmap = thread_map__new_by_tid(0);
+-
+- if (tmap == NULL)
+- return false;
+-
+- evsel = evsel__new(&attr);
+- if (evsel) {
+- open_return = evsel__open(evsel, NULL, tmap);
+- ret = open_return >= 0;
+-
+- if (open_return == -EACCES) {
+- /*
+- * This happens if the paranoid value
+- * /proc/sys/kernel/perf_event_paranoid is set to 2
+- * Re-run with exclude_kernel set; we don't do that
+- * by default as some ARM machines do not support it.
+- *
+- */
+- evsel->core.attr.exclude_kernel = 1;
+- ret = evsel__open(evsel, NULL, tmap) >= 0;
+- }
+- evsel__delete(evsel);
+- }
+-
+- perf_thread_map__put(tmap);
+- return ret;
+-}
+-
+-void print_sdt_events(const char *subsys_glob, const char *event_glob,
+- bool name_only)
+-{
+- struct probe_cache *pcache;
+- struct probe_cache_entry *ent;
+- struct strlist *bidlist, *sdtlist;
+- struct strlist_config cfg = {.dont_dupstr = true};
+- struct str_node *nd, *nd2;
+- char *buf, *path, *ptr = NULL;
+- bool show_detail = false;
+- int ret;
+-
+- sdtlist = strlist__new(NULL, &cfg);
+- if (!sdtlist) {
+- pr_debug("Failed to allocate new strlist for SDT\n");
+- return;
+- }
+- bidlist = build_id_cache__list_all(true);
+- if (!bidlist) {
+- pr_debug("Failed to get buildids: %d\n", errno);
+- return;
+- }
+- strlist__for_each_entry(nd, bidlist) {
+- pcache = probe_cache__new(nd->s, NULL);
+- if (!pcache)
+- continue;
+- list_for_each_entry(ent, &pcache->entries, node) {
+- if (!ent->sdt)
+- continue;
+- if (subsys_glob &&
+- !strglobmatch(ent->pev.group, subsys_glob))
+- continue;
+- if (event_glob &&
+- !strglobmatch(ent->pev.event, event_glob))
+- continue;
+- ret = asprintf(&buf, "%s:%s@%s", ent->pev.group,
+- ent->pev.event, nd->s);
+- if (ret > 0)
+- strlist__add(sdtlist, buf);
+- }
+- probe_cache__delete(pcache);
+- }
+- strlist__delete(bidlist);
+-
+- strlist__for_each_entry(nd, sdtlist) {
+- buf = strchr(nd->s, '@');
+- if (buf)
+- *(buf++) = '\0';
+- if (name_only) {
+- printf("%s ", nd->s);
+- continue;
+- }
+- nd2 = strlist__next(nd);
+- if (nd2) {
+- ptr = strchr(nd2->s, '@');
+- if (ptr)
+- *ptr = '\0';
+- if (strcmp(nd->s, nd2->s) == 0)
+- show_detail = true;
+- }
+- if (show_detail) {
+- path = build_id_cache__origname(buf);
+- ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf);
+- if (ret > 0) {
+- printf(" %-50s [%s]\n", buf, "SDT event");
+- free(buf);
+- }
+- free(path);
+- } else
+- printf(" %-50s [%s]\n", nd->s, "SDT event");
+- if (nd2) {
+- if (strcmp(nd->s, nd2->s) != 0)
+- show_detail = false;
+- if (ptr)
+- *ptr = '@';
+- }
+- }
+- strlist__delete(sdtlist);
+-}
+-
+-int print_hwcache_events(const char *event_glob, bool name_only)
+-{
+- unsigned int type, op, i, evt_i = 0, evt_num = 0, npmus = 0;
+- char name[64], new_name[128];
+- char **evt_list = NULL, **evt_pmus = NULL;
+- bool evt_num_known = false;
+- struct perf_pmu *pmu = NULL;
+-
+- if (perf_pmu__has_hybrid()) {
+- npmus = perf_pmu__hybrid_pmu_num();
+- evt_pmus = zalloc(sizeof(char *) * npmus);
+- if (!evt_pmus)
+- goto out_enomem;
+- }
+-
+-restart:
+- if (evt_num_known) {
+- evt_list = zalloc(sizeof(char *) * evt_num);
+- if (!evt_list)
+- goto out_enomem;
+- }
+-
+- for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
+- for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
+- /* skip invalid cache type */
+- if (!evsel__is_cache_op_valid(type, op))
+- continue;
+-
+- for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
+- unsigned int hybrid_supported = 0, j;
+- bool supported;
+-
+- __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name));
+- if (event_glob != NULL && !strglobmatch(name, event_glob))
+- continue;
+-
+- if (!perf_pmu__has_hybrid()) {
+- if (!is_event_supported(PERF_TYPE_HW_CACHE,
+- type | (op << 8) | (i << 16))) {
+- continue;
+- }
+- } else {
+- perf_pmu__for_each_hybrid_pmu(pmu) {
+- if (!evt_num_known) {
+- evt_num++;
+- continue;
+- }
+-
+- supported = is_event_supported(
+- PERF_TYPE_HW_CACHE,
+- type | (op << 8) | (i << 16) |
+- ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT));
+- if (supported) {
+- snprintf(new_name, sizeof(new_name), "%s/%s/",
+- pmu->name, name);
+- evt_pmus[hybrid_supported] = strdup(new_name);
+- hybrid_supported++;
+- }
+- }
+-
+- if (hybrid_supported == 0)
+- continue;
+- }
+-
+- if (!evt_num_known) {
+- evt_num++;
+- continue;
+- }
+-
+- if ((hybrid_supported == 0) ||
+- (hybrid_supported == npmus)) {
+- evt_list[evt_i] = strdup(name);
+- if (npmus > 0) {
+- for (j = 0; j < npmus; j++)
+- zfree(&evt_pmus[j]);
+- }
+- } else {
+- for (j = 0; j < hybrid_supported; j++) {
+- evt_list[evt_i++] = evt_pmus[j];
+- evt_pmus[j] = NULL;
+- }
+- continue;
+- }
+-
+- if (evt_list[evt_i] == NULL)
+- goto out_enomem;
+- evt_i++;
+- }
+- }
+- }
+-
+- if (!evt_num_known) {
+- evt_num_known = true;
+- goto restart;
+- }
+-
+- for (evt_i = 0; evt_i < evt_num; evt_i++) {
+- if (!evt_list[evt_i])
+- break;
+- }
+-
+- evt_num = evt_i;
+- qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+- evt_i = 0;
+- while (evt_i < evt_num) {
+- if (name_only) {
+- printf("%s ", evt_list[evt_i++]);
+- continue;
+- }
+- printf(" %-50s [%s]\n", evt_list[evt_i++],
+- event_type_descriptors[PERF_TYPE_HW_CACHE]);
+- }
+- if (evt_num && pager_in_use())
+- printf("\n");
+-
+-out_free:
+- evt_num = evt_i;
+- for (evt_i = 0; evt_i < evt_num; evt_i++)
+- zfree(&evt_list[evt_i]);
+- zfree(&evt_list);
+-
+- for (evt_i = 0; evt_i < npmus; evt_i++)
+- zfree(&evt_pmus[evt_i]);
+- zfree(&evt_pmus);
+- return evt_num;
+-
+-out_enomem:
+- printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
+- if (evt_list)
+- goto out_free;
+- return evt_num;
+-}
+-
+-static void print_tool_event(const struct event_symbol *syms, const char *event_glob,
+- bool name_only)
+-{
+- if (syms->symbol == NULL)
+- return;
+-
+- if (event_glob && !(strglobmatch(syms->symbol, event_glob) ||
+- (syms->alias && strglobmatch(syms->alias, event_glob))))
+- return;
+-
+- if (name_only)
+- printf("%s ", syms->symbol);
+- else {
+- char name[MAX_NAME_LEN];
+- if (syms->alias && strlen(syms->alias))
+- snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
+- else
+- strlcpy(name, syms->symbol, MAX_NAME_LEN);
+- printf(" %-50s [%s]\n", name, "Tool event");
+- }
+-}
+-
+-void print_tool_events(const char *event_glob, bool name_only)
+-{
+- // Start at 1 because the first enum entry symbols no tool event
+- for (int i = 1; i < PERF_TOOL_MAX; ++i) {
+- print_tool_event(event_symbols_tool + i, event_glob, name_only);
+- }
+- if (pager_in_use())
+- printf("\n");
+-}
+-
+-void print_symbol_events(const char *event_glob, unsigned type,
+- struct event_symbol *syms, unsigned max,
+- bool name_only)
+-{
+- unsigned int i, evt_i = 0, evt_num = 0;
+- char name[MAX_NAME_LEN];
+- char **evt_list = NULL;
+- bool evt_num_known = false;
+-
+-restart:
+- if (evt_num_known) {
+- evt_list = zalloc(sizeof(char *) * evt_num);
+- if (!evt_list)
+- goto out_enomem;
+- syms -= max;
+- }
+-
+- for (i = 0; i < max; i++, syms++) {
+- /*
+- * New attr.config still not supported here, the latest
+- * example was PERF_COUNT_SW_CGROUP_SWITCHES
+- */
+- if (syms->symbol == NULL)
+- continue;
+-
+- if (event_glob != NULL && !(strglobmatch(syms->symbol, event_glob) ||
+- (syms->alias && strglobmatch(syms->alias, event_glob))))
+- continue;
+-
+- if (!is_event_supported(type, i))
+- continue;
+-
+- if (!evt_num_known) {
+- evt_num++;
+- continue;
+- }
+-
+- if (!name_only && strlen(syms->alias))
+- snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
+- else
+- strlcpy(name, syms->symbol, MAX_NAME_LEN);
+-
+- evt_list[evt_i] = strdup(name);
+- if (evt_list[evt_i] == NULL)
+- goto out_enomem;
+- evt_i++;
+- }
+-
+- if (!evt_num_known) {
+- evt_num_known = true;
+- goto restart;
+- }
+- qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+- evt_i = 0;
+- while (evt_i < evt_num) {
+- if (name_only) {
+- printf("%s ", evt_list[evt_i++]);
+- continue;
+- }
+- printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
+- }
+- if (evt_num && pager_in_use())
+- printf("\n");
+-
+-out_free:
+- evt_num = evt_i;
+- for (evt_i = 0; evt_i < evt_num; evt_i++)
+- zfree(&evt_list[evt_i]);
+- zfree(&evt_list);
+- return;
+-
+-out_enomem:
+- printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
+- if (evt_list)
+- goto out_free;
+-}
+-
+-/*
+- * Print the help text for the event symbols:
+- */
+-void print_events(const char *event_glob, bool name_only, bool quiet_flag,
+- bool long_desc, bool details_flag, bool deprecated,
+- const char *pmu_name)
+-{
+- print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
+- event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
+-
+- print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
+- event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
+- print_tool_events(event_glob, name_only);
+-
+- print_hwcache_events(event_glob, name_only);
+-
+- print_pmu_events(event_glob, name_only, quiet_flag, long_desc,
+- details_flag, deprecated, pmu_name);
+-
+- if (event_glob != NULL)
+- return;
+-
+- if (!name_only) {
+- printf(" %-50s [%s]\n",
+- "rNNN",
+- event_type_descriptors[PERF_TYPE_RAW]);
+- printf(" %-50s [%s]\n",
+- "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
+- event_type_descriptors[PERF_TYPE_RAW]);
+- if (pager_in_use())
+- printf(" (see 'man perf-list' on how to encode it)\n\n");
+-
+- printf(" %-50s [%s]\n",
+- "mem:<addr>[/len][:access]",
+- event_type_descriptors[PERF_TYPE_BREAKPOINT]);
+- if (pager_in_use())
+- printf("\n");
+- }
+-
+- print_tracepoint_events(NULL, NULL, name_only);
+-
+- print_sdt_events(NULL, NULL, name_only);
+-
+- metricgroup__print(true, true, NULL, name_only, details_flag,
+- pmu_name);
+-
+- print_libpfm_events(name_only, long_desc);
+-}
+-
+ int parse_events__is_hardcoded_term(struct parse_events_term *term)
+ {
+ return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
+diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
+index a38b8b160e80..ba9fa3ddaf6e 100644
+--- a/tools/perf/util/parse-events.h
++++ b/tools/perf/util/parse-events.h
+@@ -11,7 +11,6 @@
+ #include <linux/perf_event.h>
+ #include <string.h>
+
+-struct list_head;
+ struct evsel;
+ struct evlist;
+ struct parse_events_error;
+@@ -19,14 +18,6 @@ struct parse_events_error;
+ struct option;
+ struct perf_pmu;
+
+-struct tracepoint_path {
+- char *system;
+- char *name;
+- struct tracepoint_path *next;
+-};
+-
+-struct tracepoint_path *tracepoint_id_to_path(u64 config);
+-struct tracepoint_path *tracepoint_name_to_path(const char *name);
+ bool have_tracepoints(struct list_head *evlist);
+
+ const char *event_type(int type);
+@@ -46,8 +37,6 @@ int parse_events_terms(struct list_head *terms, const char *str);
+ int parse_filter(const struct option *opt, const char *str, int unset);
+ int exclude_perf(const struct option *opt, const char *arg, int unset);
+
+-#define EVENTS_HELP_MAX (128*1024)
+-
+ enum perf_pmu_event_symbol_type {
+ PMU_EVENT_SYMBOL_ERR, /* not a PMU EVENT */
+ PMU_EVENT_SYMBOL, /* normal style PMU event */
+@@ -56,11 +45,6 @@ enum perf_pmu_event_symbol_type {
+ PMU_EVENT_SYMBOL_SUFFIX2, /* suffix of pre-suf2 style event */
+ };
+
+-struct perf_pmu_event_symbol {
+- char *symbol;
+- enum perf_pmu_event_symbol_type type;
+-};
+-
+ enum {
+ PARSE_EVENTS__TERM_TYPE_NUM,
+ PARSE_EVENTS__TERM_TYPE_STR,
+@@ -219,28 +203,13 @@ void parse_events_update_lists(struct list_head *list_event,
+ void parse_events_evlist_error(struct parse_events_state *parse_state,
+ int idx, const char *str);
+
+-void print_events(const char *event_glob, bool name_only, bool quiet,
+- bool long_desc, bool details_flag, bool deprecated,
+- const char *pmu_name);
+-
+ struct event_symbol {
+ const char *symbol;
+ const char *alias;
+ };
+ extern struct event_symbol event_symbols_hw[];
+ extern struct event_symbol event_symbols_sw[];
+-void print_symbol_events(const char *event_glob, unsigned type,
+- struct event_symbol *syms, unsigned max,
+- bool name_only);
+-void print_tool_events(const char *event_glob, bool name_only);
+-void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
+- bool name_only);
+-int print_hwcache_events(const char *event_glob, bool name_only);
+-void print_sdt_events(const char *subsys_glob, const char *event_glob,
+- bool name_only);
+-int is_valid_tracepoint(const char *event_string);
+
+-int valid_event_mount(const char *eventfs);
+ char *parse_events_formats_error_string(char *additional_terms);
+
+ void parse_events_error__init(struct parse_events_error *err);
+diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
+new file mode 100644
+index 000000000000..ba1ab5134685
+--- /dev/null
++++ b/tools/perf/util/print-events.c
+@@ -0,0 +1,572 @@
++// SPDX-License-Identifier: GPL-2.0
++#include <dirent.h>
++#include <errno.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/param.h>
++
++#include <api/fs/tracing_path.h>
++#include <linux/stddef.h>
++#include <linux/perf_event.h>
++#include <linux/zalloc.h>
++#include <subcmd/pager.h>
++
++#include "build-id.h"
++#include "debug.h"
++#include "evsel.h"
++#include "metricgroup.h"
++#include "parse-events.h"
++#include "pmu.h"
++#include "print-events.h"
++#include "probe-file.h"
++#include "string2.h"
++#include "strlist.h"
++#include "thread_map.h"
++#include "tracepoint.h"
++#include "pfm.h"
++#include "pmu-hybrid.h"
++
++#define MAX_NAME_LEN 100
++
++static const char * const event_type_descriptors[] = {
++ "Hardware event",
++ "Software event",
++ "Tracepoint event",
++ "Hardware cache event",
++ "Raw hardware event descriptor",
++ "Hardware breakpoint",
++};
++
++static const struct event_symbol event_symbols_tool[PERF_TOOL_MAX] = {
++ [PERF_TOOL_DURATION_TIME] = {
++ .symbol = "duration_time",
++ .alias = "",
++ },
++ [PERF_TOOL_USER_TIME] = {
++ .symbol = "user_time",
++ .alias = "",
++ },
++ [PERF_TOOL_SYSTEM_TIME] = {
++ .symbol = "system_time",
++ .alias = "",
++ },
++};
++
++static int cmp_string(const void *a, const void *b)
++{
++ const char * const *as = a;
++ const char * const *bs = b;
++
++ return strcmp(*as, *bs);
++}
++
++/*
++ * Print the events from <debugfs_mount_point>/tracing/events
++ */
++void print_tracepoint_events(const char *subsys_glob,
++ const char *event_glob, bool name_only)
++{
++ DIR *sys_dir, *evt_dir;
++ struct dirent *sys_dirent, *evt_dirent;
++ char evt_path[MAXPATHLEN];
++ char *dir_path;
++ char **evt_list = NULL;
++ unsigned int evt_i = 0, evt_num = 0;
++ bool evt_num_known = false;
++
++restart:
++ sys_dir = tracing_events__opendir();
++ if (!sys_dir)
++ return;
++
++ if (evt_num_known) {
++ evt_list = zalloc(sizeof(char *) * evt_num);
++ if (!evt_list)
++ goto out_close_sys_dir;
++ }
++
++ for_each_subsystem(sys_dir, sys_dirent) {
++ if (subsys_glob != NULL &&
++ !strglobmatch(sys_dirent->d_name, subsys_glob))
++ continue;
++
++ dir_path = get_events_file(sys_dirent->d_name);
++ if (!dir_path)
++ continue;
++ evt_dir = opendir(dir_path);
++ if (!evt_dir)
++ goto next;
++
++ for_each_event(dir_path, evt_dir, evt_dirent) {
++ if (event_glob != NULL &&
++ !strglobmatch(evt_dirent->d_name, event_glob))
++ continue;
++
++ if (!evt_num_known) {
++ evt_num++;
++ continue;
++ }
++
++ snprintf(evt_path, MAXPATHLEN, "%s:%s",
++ sys_dirent->d_name, evt_dirent->d_name);
++
++ evt_list[evt_i] = strdup(evt_path);
++ if (evt_list[evt_i] == NULL) {
++ put_events_file(dir_path);
++ goto out_close_evt_dir;
++ }
++ evt_i++;
++ }
++ closedir(evt_dir);
++next:
++ put_events_file(dir_path);
++ }
++ closedir(sys_dir);
++
++ if (!evt_num_known) {
++ evt_num_known = true;
++ goto restart;
++ }
++ qsort(evt_list, evt_num, sizeof(char *), cmp_string);
++ evt_i = 0;
++ while (evt_i < evt_num) {
++ if (name_only) {
++ printf("%s ", evt_list[evt_i++]);
++ continue;
++ }
++ printf(" %-50s [%s]\n", evt_list[evt_i++],
++ event_type_descriptors[PERF_TYPE_TRACEPOINT]);
++ }
++ if (evt_num && pager_in_use())
++ printf("\n");
++
++out_free:
++ evt_num = evt_i;
++ for (evt_i = 0; evt_i < evt_num; evt_i++)
++ zfree(&evt_list[evt_i]);
++ zfree(&evt_list);
++ return;
++
++out_close_evt_dir:
++ closedir(evt_dir);
++out_close_sys_dir:
++ closedir(sys_dir);
++
++ printf("FATAL: not enough memory to print %s\n",
++ event_type_descriptors[PERF_TYPE_TRACEPOINT]);
++ if (evt_list)
++ goto out_free;
++}
++
++void print_sdt_events(const char *subsys_glob, const char *event_glob,
++ bool name_only)
++{
++ struct probe_cache *pcache;
++ struct probe_cache_entry *ent;
++ struct strlist *bidlist, *sdtlist;
++ struct strlist_config cfg = {.dont_dupstr = true};
++ struct str_node *nd, *nd2;
++ char *buf, *path, *ptr = NULL;
++ bool show_detail = false;
++ int ret;
++
++ sdtlist = strlist__new(NULL, &cfg);
++ if (!sdtlist) {
++ pr_debug("Failed to allocate new strlist for SDT\n");
++ return;
++ }
++ bidlist = build_id_cache__list_all(true);
++ if (!bidlist) {
++ pr_debug("Failed to get buildids: %d\n", errno);
++ return;
++ }
++ strlist__for_each_entry(nd, bidlist) {
++ pcache = probe_cache__new(nd->s, NULL);
++ if (!pcache)
++ continue;
++ list_for_each_entry(ent, &pcache->entries, node) {
++ if (!ent->sdt)
++ continue;
++ if (subsys_glob &&
++ !strglobmatch(ent->pev.group, subsys_glob))
++ continue;
++ if (event_glob &&
++ !strglobmatch(ent->pev.event, event_glob))
++ continue;
++ ret = asprintf(&buf, "%s:%s@%s", ent->pev.group,
++ ent->pev.event, nd->s);
++ if (ret > 0)
++ strlist__add(sdtlist, buf);
++ }
++ probe_cache__delete(pcache);
++ }
++ strlist__delete(bidlist);
++
++ strlist__for_each_entry(nd, sdtlist) {
++ buf = strchr(nd->s, '@');
++ if (buf)
++ *(buf++) = '\0';
++ if (name_only) {
++ printf("%s ", nd->s);
++ continue;
++ }
++ nd2 = strlist__next(nd);
++ if (nd2) {
++ ptr = strchr(nd2->s, '@');
++ if (ptr)
++ *ptr = '\0';
++ if (strcmp(nd->s, nd2->s) == 0)
++ show_detail = true;
++ }
++ if (show_detail) {
++ path = build_id_cache__origname(buf);
++ ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf);
++ if (ret > 0) {
++ printf(" %-50s [%s]\n", buf, "SDT event");
++ free(buf);
++ }
++ free(path);
++ } else
++ printf(" %-50s [%s]\n", nd->s, "SDT event");
++ if (nd2) {
++ if (strcmp(nd->s, nd2->s) != 0)
++ show_detail = false;
++ if (ptr)
++ *ptr = '@';
++ }
++ }
++ strlist__delete(sdtlist);
++}
++
++static bool is_event_supported(u8 type, unsigned int config)
++{
++ bool ret = true;
++ int open_return;
++ struct evsel *evsel;
++ struct perf_event_attr attr = {
++ .type = type,
++ .config = config,
++ .disabled = 1,
++ };
++ struct perf_thread_map *tmap = thread_map__new_by_tid(0);
++
++ if (tmap == NULL)
++ return false;
++
++ evsel = evsel__new(&attr);
++ if (evsel) {
++ open_return = evsel__open(evsel, NULL, tmap);
++ ret = open_return >= 0;
++
++ if (open_return == -EACCES) {
++ /*
++ * This happens if the paranoid value
++ * /proc/sys/kernel/perf_event_paranoid is set to 2
++ * Re-run with exclude_kernel set; we don't do that
++ * by default as some ARM machines do not support it.
++ *
++ */
++ evsel->core.attr.exclude_kernel = 1;
++ ret = evsel__open(evsel, NULL, tmap) >= 0;
++ }
++ evsel__delete(evsel);
++ }
++
++ perf_thread_map__put(tmap);
++ return ret;
++}
++
++int print_hwcache_events(const char *event_glob, bool name_only)
++{
++ unsigned int type, op, i, evt_i = 0, evt_num = 0, npmus = 0;
++ char name[64], new_name[128];
++ char **evt_list = NULL, **evt_pmus = NULL;
++ bool evt_num_known = false;
++ struct perf_pmu *pmu = NULL;
++
++ if (perf_pmu__has_hybrid()) {
++ npmus = perf_pmu__hybrid_pmu_num();
++ evt_pmus = zalloc(sizeof(char *) * npmus);
++ if (!evt_pmus)
++ goto out_enomem;
++ }
++
++restart:
++ if (evt_num_known) {
++ evt_list = zalloc(sizeof(char *) * evt_num);
++ if (!evt_list)
++ goto out_enomem;
++ }
++
++ for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
++ for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
++ /* skip invalid cache type */
++ if (!evsel__is_cache_op_valid(type, op))
++ continue;
++
++ for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
++ unsigned int hybrid_supported = 0, j;
++ bool supported;
++
++ __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name));
++ if (event_glob != NULL && !strglobmatch(name, event_glob))
++ continue;
++
++ if (!perf_pmu__has_hybrid()) {
++ if (!is_event_supported(PERF_TYPE_HW_CACHE,
++ type | (op << 8) | (i << 16))) {
++ continue;
++ }
++ } else {
++ perf_pmu__for_each_hybrid_pmu(pmu) {
++ if (!evt_num_known) {
++ evt_num++;
++ continue;
++ }
++
++ supported = is_event_supported(
++ PERF_TYPE_HW_CACHE,
++ type | (op << 8) | (i << 16) |
++ ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT));
++ if (supported) {
++ snprintf(new_name, sizeof(new_name),
++ "%s/%s/", pmu->name, name);
++ evt_pmus[hybrid_supported] =
++ strdup(new_name);
++ hybrid_supported++;
++ }
++ }
++
++ if (hybrid_supported == 0)
++ continue;
++ }
++
++ if (!evt_num_known) {
++ evt_num++;
++ continue;
++ }
++
++ if ((hybrid_supported == 0) ||
++ (hybrid_supported == npmus)) {
++ evt_list[evt_i] = strdup(name);
++ if (npmus > 0) {
++ for (j = 0; j < npmus; j++)
++ zfree(&evt_pmus[j]);
++ }
++ } else {
++ for (j = 0; j < hybrid_supported; j++) {
++ evt_list[evt_i++] = evt_pmus[j];
++ evt_pmus[j] = NULL;
++ }
++ continue;
++ }
++
++ if (evt_list[evt_i] == NULL)
++ goto out_enomem;
++ evt_i++;
++ }
++ }
++ }
++
++ if (!evt_num_known) {
++ evt_num_known = true;
++ goto restart;
++ }
++
++ for (evt_i = 0; evt_i < evt_num; evt_i++) {
++ if (!evt_list[evt_i])
++ break;
++ }
++
++ evt_num = evt_i;
++ qsort(evt_list, evt_num, sizeof(char *), cmp_string);
++ evt_i = 0;
++ while (evt_i < evt_num) {
++ if (name_only) {
++ printf("%s ", evt_list[evt_i++]);
++ continue;
++ }
++ printf(" %-50s [%s]\n", evt_list[evt_i++],
++ event_type_descriptors[PERF_TYPE_HW_CACHE]);
++ }
++ if (evt_num && pager_in_use())
++ printf("\n");
++
++out_free:
++ evt_num = evt_i;
++ for (evt_i = 0; evt_i < evt_num; evt_i++)
++ zfree(&evt_list[evt_i]);
++ zfree(&evt_list);
++
++ for (evt_i = 0; evt_i < npmus; evt_i++)
++ zfree(&evt_pmus[evt_i]);
++ zfree(&evt_pmus);
++ return evt_num;
++
++out_enomem:
++ printf("FATAL: not enough memory to print %s\n",
++ event_type_descriptors[PERF_TYPE_HW_CACHE]);
++ if (evt_list)
++ goto out_free;
++ return evt_num;
++}
++
++static void print_tool_event(const struct event_symbol *syms, const char *event_glob,
++ bool name_only)
++{
++ if (syms->symbol == NULL)
++ return;
++
++ if (event_glob && !(strglobmatch(syms->symbol, event_glob) ||
++ (syms->alias && strglobmatch(syms->alias, event_glob))))
++ return;
++
++ if (name_only)
++ printf("%s ", syms->symbol);
++ else {
++ char name[MAX_NAME_LEN];
++
++ if (syms->alias && strlen(syms->alias))
++ snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
++ else
++ strlcpy(name, syms->symbol, MAX_NAME_LEN);
++ printf(" %-50s [%s]\n", name, "Tool event");
++ }
++}
++
++void print_tool_events(const char *event_glob, bool name_only)
++{
++ // Start at 1 because the first enum entry means no tool event.
++ for (int i = 1; i < PERF_TOOL_MAX; ++i)
++ print_tool_event(event_symbols_tool + i, event_glob, name_only);
++
++ if (pager_in_use())
++ printf("\n");
++}
++
++void print_symbol_events(const char *event_glob, unsigned int type,
++ struct event_symbol *syms, unsigned int max,
++ bool name_only)
++{
++ unsigned int i, evt_i = 0, evt_num = 0;
++ char name[MAX_NAME_LEN];
++ char **evt_list = NULL;
++ bool evt_num_known = false;
++
++restart:
++ if (evt_num_known) {
++ evt_list = zalloc(sizeof(char *) * evt_num);
++ if (!evt_list)
++ goto out_enomem;
++ syms -= max;
++ }
++
++ for (i = 0; i < max; i++, syms++) {
++ /*
++ * New attr.config still not supported here, the latest
++ * example was PERF_COUNT_SW_CGROUP_SWITCHES
++ */
++ if (syms->symbol == NULL)
++ continue;
++
++ if (event_glob != NULL && !(strglobmatch(syms->symbol, event_glob) ||
++ (syms->alias && strglobmatch(syms->alias, event_glob))))
++ continue;
++
++ if (!is_event_supported(type, i))
++ continue;
++
++ if (!evt_num_known) {
++ evt_num++;
++ continue;
++ }
++
++ if (!name_only && strlen(syms->alias))
++ snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
++ else
++ strlcpy(name, syms->symbol, MAX_NAME_LEN);
++
++ evt_list[evt_i] = strdup(name);
++ if (evt_list[evt_i] == NULL)
++ goto out_enomem;
++ evt_i++;
++ }
++
++ if (!evt_num_known) {
++ evt_num_known = true;
++ goto restart;
++ }
++ qsort(evt_list, evt_num, sizeof(char *), cmp_string);
++ evt_i = 0;
++ while (evt_i < evt_num) {
++ if (name_only) {
++ printf("%s ", evt_list[evt_i++]);
++ continue;
++ }
++ printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
++ }
++ if (evt_num && pager_in_use())
++ printf("\n");
++
++out_free:
++ evt_num = evt_i;
++ for (evt_i = 0; evt_i < evt_num; evt_i++)
++ zfree(&evt_list[evt_i]);
++ zfree(&evt_list);
++ return;
++
++out_enomem:
++ printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
++ if (evt_list)
++ goto out_free;
++}
++
++/*
++ * Print the help text for the event symbols:
++ */
++void print_events(const char *event_glob, bool name_only, bool quiet_flag,
++ bool long_desc, bool details_flag, bool deprecated,
++ const char *pmu_name)
++{
++ print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
++ event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
++
++ print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
++ event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
++ print_tool_events(event_glob, name_only);
++
++ print_hwcache_events(event_glob, name_only);
++
++ print_pmu_events(event_glob, name_only, quiet_flag, long_desc,
++ details_flag, deprecated, pmu_name);
++
++ if (event_glob != NULL)
++ return;
++
++ if (!name_only) {
++ printf(" %-50s [%s]\n",
++ "rNNN",
++ event_type_descriptors[PERF_TYPE_RAW]);
++ printf(" %-50s [%s]\n",
++ "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
++ event_type_descriptors[PERF_TYPE_RAW]);
++ if (pager_in_use())
++ printf(" (see 'man perf-list' on how to encode it)\n\n");
++
++ printf(" %-50s [%s]\n",
++ "mem:<addr>[/len][:access]",
++ event_type_descriptors[PERF_TYPE_BREAKPOINT]);
++ if (pager_in_use())
++ printf("\n");
++ }
++
++ print_tracepoint_events(NULL, NULL, name_only);
++
++ print_sdt_events(NULL, NULL, name_only);
++
++ metricgroup__print(true, true, NULL, name_only, details_flag,
++ pmu_name);
++
++ print_libpfm_events(name_only, long_desc);
++}
+diff --git a/tools/perf/util/print-events.h b/tools/perf/util/print-events.h
+new file mode 100644
+index 000000000000..1da9910d83a6
+--- /dev/null
++++ b/tools/perf/util/print-events.h
+@@ -0,0 +1,22 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __PERF_PRINT_EVENTS_H
++#define __PERF_PRINT_EVENTS_H
++
++#include <stdbool.h>
++
++struct event_symbol;
++
++void print_events(const char *event_glob, bool name_only, bool quiet_flag,
++ bool long_desc, bool details_flag, bool deprecated,
++ const char *pmu_name);
++int print_hwcache_events(const char *event_glob, bool name_only);
++void print_sdt_events(const char *subsys_glob, const char *event_glob,
++ bool name_only);
++void print_symbol_events(const char *event_glob, unsigned int type,
++ struct event_symbol *syms, unsigned int max,
++ bool name_only);
++void print_tool_events(const char *event_glob, bool name_only);
++void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
++ bool name_only);
++
++#endif /* __PERF_PRINT_EVENTS_H */
+diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
+index a65f65d0857e..892c323b4ac9 100644
+--- a/tools/perf/util/trace-event-info.c
++++ b/tools/perf/util/trace-event-info.c
+@@ -19,16 +19,24 @@
+ #include <linux/kernel.h>
+ #include <linux/zalloc.h>
+ #include <internal/lib.h> // page_size
++#include <sys/param.h>
+
+ #include "trace-event.h"
++#include "tracepoint.h"
+ #include <api/fs/tracing_path.h>
+ #include "evsel.h"
+ #include "debug.h"
+
+ #define VERSION "0.6"
++#define MAX_EVENT_LENGTH 512
+
+ static int output_fd;
+
++struct tracepoint_path {
++ char *system;
++ char *name;
++ struct tracepoint_path *next;
++};
+
+ int bigendian(void)
+ {
+@@ -400,6 +408,94 @@ put_tracepoints_path(struct tracepoint_path *tps)
+ }
+ }
+
++static struct tracepoint_path *tracepoint_id_to_path(u64 config)
++{
++ struct tracepoint_path *path = NULL;
++ DIR *sys_dir, *evt_dir;
++ struct dirent *sys_dirent, *evt_dirent;
++ char id_buf[24];
++ int fd;
++ u64 id;
++ char evt_path[MAXPATHLEN];
++ char *dir_path;
++
++ sys_dir = tracing_events__opendir();
++ if (!sys_dir)
++ return NULL;
++
++ for_each_subsystem(sys_dir, sys_dirent) {
++ dir_path = get_events_file(sys_dirent->d_name);
++ if (!dir_path)
++ continue;
++ evt_dir = opendir(dir_path);
++ if (!evt_dir)
++ goto next;
++
++ for_each_event(dir_path, evt_dir, evt_dirent) {
++
++ scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
++ evt_dirent->d_name);
++ fd = open(evt_path, O_RDONLY);
++ if (fd < 0)
++ continue;
++ if (read(fd, id_buf, sizeof(id_buf)) < 0) {
++ close(fd);
++ continue;
++ }
++ close(fd);
++ id = atoll(id_buf);
++ if (id == config) {
++ put_events_file(dir_path);
++ closedir(evt_dir);
++ closedir(sys_dir);
++ path = zalloc(sizeof(*path));
++ if (!path)
++ return NULL;
++ if (asprintf(&path->system, "%.*s",
++ MAX_EVENT_LENGTH, sys_dirent->d_name) < 0) {
++ free(path);
++ return NULL;
++ }
++ if (asprintf(&path->name, "%.*s",
++ MAX_EVENT_LENGTH, evt_dirent->d_name) < 0) {
++ zfree(&path->system);
++ free(path);
++ return NULL;
++ }
++ return path;
++ }
++ }
++ closedir(evt_dir);
++next:
++ put_events_file(dir_path);
++ }
++
++ closedir(sys_dir);
++ return NULL;
++}
++
++static struct tracepoint_path *tracepoint_name_to_path(const char *name)
++{
++ struct tracepoint_path *path = zalloc(sizeof(*path));
++ char *str = strchr(name, ':');
++
++ if (path == NULL || str == NULL) {
++ free(path);
++ return NULL;
++ }
++
++ path->system = strndup(name, str - name);
++ path->name = strdup(str+1);
++
++ if (path->system == NULL || path->name == NULL) {
++ zfree(&path->system);
++ zfree(&path->name);
++ zfree(&path);
++ }
++
++ return path;
++}
++
+ static struct tracepoint_path *
+ get_tracepoints_path(struct list_head *pattrs)
+ {
+diff --git a/tools/perf/util/tracepoint.c b/tools/perf/util/tracepoint.c
+new file mode 100644
+index 000000000000..89ef56c43311
+--- /dev/null
++++ b/tools/perf/util/tracepoint.c
+@@ -0,0 +1,63 @@
++// SPDX-License-Identifier: GPL-2.0
++#include "tracepoint.h"
++
++#include <errno.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <sys/param.h>
++#include <unistd.h>
++
++#include <api/fs/tracing_path.h>
++
++int tp_event_has_id(const char *dir_path, struct dirent *evt_dir)
++{
++ char evt_path[MAXPATHLEN];
++ int fd;
++
++ snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dir->d_name);
++ fd = open(evt_path, O_RDONLY);
++ if (fd < 0)
++ return -EINVAL;
++ close(fd);
++
++ return 0;
++}
++
++/*
++ * Check whether event is in <debugfs_mount_point>/tracing/events
++ */
++int is_valid_tracepoint(const char *event_string)
++{
++ DIR *sys_dir, *evt_dir;
++ struct dirent *sys_dirent, *evt_dirent;
++ char evt_path[MAXPATHLEN];
++ char *dir_path;
++
++ sys_dir = tracing_events__opendir();
++ if (!sys_dir)
++ return 0;
++
++ for_each_subsystem(sys_dir, sys_dirent) {
++ dir_path = get_events_file(sys_dirent->d_name);
++ if (!dir_path)
++ continue;
++ evt_dir = opendir(dir_path);
++ if (!evt_dir)
++ goto next;
++
++ for_each_event(dir_path, evt_dir, evt_dirent) {
++ snprintf(evt_path, MAXPATHLEN, "%s:%s",
++ sys_dirent->d_name, evt_dirent->d_name);
++ if (!strcmp(evt_path, event_string)) {
++ closedir(evt_dir);
++ closedir(sys_dir);
++ return 1;
++ }
++ }
++ closedir(evt_dir);
++next:
++ put_events_file(dir_path);
++ }
++ closedir(sys_dir);
++ return 0;
++}
+diff --git a/tools/perf/util/tracepoint.h b/tools/perf/util/tracepoint.h
+new file mode 100644
+index 000000000000..c4a110fe87d7
+--- /dev/null
++++ b/tools/perf/util/tracepoint.h
+@@ -0,0 +1,25 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __PERF_TRACEPOINT_H
++#define __PERF_TRACEPOINT_H
++
++#include <dirent.h>
++#include <string.h>
++
++int tp_event_has_id(const char *dir_path, struct dirent *evt_dir);
++
++#define for_each_event(dir_path, evt_dir, evt_dirent) \
++ while ((evt_dirent = readdir(evt_dir)) != NULL) \
++ if (evt_dirent->d_type == DT_DIR && \
++ (strcmp(evt_dirent->d_name, ".")) && \
++ (strcmp(evt_dirent->d_name, "..")) && \
++ (!tp_event_has_id(dir_path, evt_dirent)))
++
++#define for_each_subsystem(sys_dir, sys_dirent) \
++ while ((sys_dirent = readdir(sys_dir)) != NULL) \
++ if (sys_dirent->d_type == DT_DIR && \
++ (strcmp(sys_dirent->d_name, ".")) && \
++ (strcmp(sys_dirent->d_name, "..")))
++
++int is_valid_tracepoint(const char *event_string);
++
++#endif /* __PERF_TRACEPOINT_H */
+--
+2.35.1
+
--- /dev/null
+From 068bb60fb09466ffe23a658e3738f3c42cba141c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Sep 2022 11:00:13 +0800
+Subject: perf parse-events: Remove "not supported" hybrid cache events
+
+From: Zhengjun Xing <zhengjun.xing@linux.intel.com>
+
+[ Upstream commit 71c86cda750b001100e0d6dc04a88449b7381a59 ]
+
+By default, we create two hybrid cache events, one is for cpu_core, and
+another is for cpu_atom. But Some hybrid hardware cache events are only
+available on one CPU PMU. For example, the 'L1-dcache-load-misses' is only
+available on cpu_core, while the 'L1-icache-loads' is only available on
+cpu_atom. We need to remove "not supported" hybrid cache events. By
+extending is_event_supported() to global API and using it to check if the
+hybrid cache events are supported before being created, we can remove the
+"not supported" hybrid cache events.
+
+Before:
+
+ # ./perf stat -e L1-dcache-load-misses,L1-icache-loads -a sleep 1
+
+ Performance counter stats for 'system wide':
+
+ 52,570 cpu_core/L1-dcache-load-misses/
+ <not supported> cpu_atom/L1-dcache-load-misses/
+ <not supported> cpu_core/L1-icache-loads/
+ 1,471,817 cpu_atom/L1-icache-loads/
+
+ 1.004915229 seconds time elapsed
+
+After:
+
+ # ./perf stat -e L1-dcache-load-misses,L1-icache-loads -a sleep 1
+
+ Performance counter stats for 'system wide':
+
+ 54,510 cpu_core/L1-dcache-load-misses/
+ 1,441,286 cpu_atom/L1-icache-loads/
+
+ 1.005114281 seconds time elapsed
+
+Fixes: 30def61f64bac5f5 ("perf parse-events: Create two hybrid cache events")
+Reported-by: Yi Ammy <ammy.yi@intel.com>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Xing Zhengjun <zhengjun.xing@linux.intel.com>
+Acked-by: Ian Rogers <irogers@google.com>
+Cc: Alexander Shishkin <alexander.shishkin@intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jin Yao <yao.jin@linux.intel.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20220923030013.3726410-2-zhengjun.xing@linux.intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/parse-events-hybrid.c | 21 ++++++++++++---
+ tools/perf/util/parse-events.c | 39 +++++++++++++++++++++++++++
+ tools/perf/util/parse-events.h | 1 +
+ tools/perf/util/print-events.c | 39 ---------------------------
+ 4 files changed, 57 insertions(+), 43 deletions(-)
+
+diff --git a/tools/perf/util/parse-events-hybrid.c b/tools/perf/util/parse-events-hybrid.c
+index 284f8eabd3b9..7c9f9150bad5 100644
+--- a/tools/perf/util/parse-events-hybrid.c
++++ b/tools/perf/util/parse-events-hybrid.c
+@@ -33,7 +33,8 @@ static void config_hybrid_attr(struct perf_event_attr *attr,
+ * If the PMU type ID is 0, the PERF_TYPE_RAW will be applied.
+ */
+ attr->type = type;
+- attr->config = attr->config | ((__u64)pmu_type << PERF_PMU_TYPE_SHIFT);
++ attr->config = (attr->config & PERF_HW_EVENT_MASK) |
++ ((__u64)pmu_type << PERF_PMU_TYPE_SHIFT);
+ }
+
+ static int create_event_hybrid(__u32 config_type, int *idx,
+@@ -48,13 +49,25 @@ static int create_event_hybrid(__u32 config_type, int *idx,
+ __u64 config = attr->config;
+
+ config_hybrid_attr(attr, config_type, pmu->type);
++
++ /*
++ * Some hybrid hardware cache events are only available on one CPU
++ * PMU. For example, the 'L1-dcache-load-misses' is only available
++ * on cpu_core, while the 'L1-icache-loads' is only available on
++ * cpu_atom. We need to remove "not supported" hybrid cache events.
++ */
++ if (attr->type == PERF_TYPE_HW_CACHE
++ && !is_event_supported(attr->type, attr->config))
++ return 0;
++
+ evsel = parse_events__add_event_hybrid(list, idx, attr, name, metric_id,
+ pmu, config_terms);
+- if (evsel)
++ if (evsel) {
+ evsel->pmu_name = strdup(pmu->name);
+- else
++ if (!evsel->pmu_name)
++ return -ENOMEM;
++ } else
+ return -ENOMEM;
+-
+ attr->type = type;
+ attr->config = config;
+ return 0;
+diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
+index 3acf7452572c..b51c646c212e 100644
+--- a/tools/perf/util/parse-events.c
++++ b/tools/perf/util/parse-events.c
+@@ -29,6 +29,7 @@
+ #include "util/parse-events-hybrid.h"
+ #include "util/pmu-hybrid.h"
+ #include "tracepoint.h"
++#include "thread_map.h"
+
+ #define MAX_NAME_LEN 100
+
+@@ -158,6 +159,44 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
+ #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
+ #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
+
++bool is_event_supported(u8 type, u64 config)
++{
++ bool ret = true;
++ int open_return;
++ struct evsel *evsel;
++ struct perf_event_attr attr = {
++ .type = type,
++ .config = config,
++ .disabled = 1,
++ };
++ struct perf_thread_map *tmap = thread_map__new_by_tid(0);
++
++ if (tmap == NULL)
++ return false;
++
++ evsel = evsel__new(&attr);
++ if (evsel) {
++ open_return = evsel__open(evsel, NULL, tmap);
++ ret = open_return >= 0;
++
++ if (open_return == -EACCES) {
++ /*
++ * This happens if the paranoid value
++ * /proc/sys/kernel/perf_event_paranoid is set to 2
++ * Re-run with exclude_kernel set; we don't do that
++ * by default as some ARM machines do not support it.
++ *
++ */
++ evsel->core.attr.exclude_kernel = 1;
++ ret = evsel__open(evsel, NULL, tmap) >= 0;
++ }
++ evsel__delete(evsel);
++ }
++
++ perf_thread_map__put(tmap);
++ return ret;
++}
++
+ const char *event_type(int type)
+ {
+ switch (type) {
+diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
+index ba9fa3ddaf6e..fd97bb74559e 100644
+--- a/tools/perf/util/parse-events.h
++++ b/tools/perf/util/parse-events.h
+@@ -19,6 +19,7 @@ struct option;
+ struct perf_pmu;
+
+ bool have_tracepoints(struct list_head *evlist);
++bool is_event_supported(u8 type, u64 config);
+
+ const char *event_type(int type);
+
+diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
+index 04050d4f6db8..c4d5d87fae2f 100644
+--- a/tools/perf/util/print-events.c
++++ b/tools/perf/util/print-events.c
+@@ -22,7 +22,6 @@
+ #include "probe-file.h"
+ #include "string2.h"
+ #include "strlist.h"
+-#include "thread_map.h"
+ #include "tracepoint.h"
+ #include "pfm.h"
+ #include "pmu-hybrid.h"
+@@ -239,44 +238,6 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
+ strlist__delete(sdtlist);
+ }
+
+-static bool is_event_supported(u8 type, u64 config)
+-{
+- bool ret = true;
+- int open_return;
+- struct evsel *evsel;
+- struct perf_event_attr attr = {
+- .type = type,
+- .config = config,
+- .disabled = 1,
+- };
+- struct perf_thread_map *tmap = thread_map__new_by_tid(0);
+-
+- if (tmap == NULL)
+- return false;
+-
+- evsel = evsel__new(&attr);
+- if (evsel) {
+- open_return = evsel__open(evsel, NULL, tmap);
+- ret = open_return >= 0;
+-
+- if (open_return == -EACCES) {
+- /*
+- * This happens if the paranoid value
+- * /proc/sys/kernel/perf_event_paranoid is set to 2
+- * Re-run with exclude_kernel set; we don't do that
+- * by default as some ARM machines do not support it.
+- *
+- */
+- evsel->core.attr.exclude_kernel = 1;
+- ret = evsel__open(evsel, NULL, tmap) >= 0;
+- }
+- evsel__delete(evsel);
+- }
+-
+- perf_thread_map__put(tmap);
+- return ret;
+-}
+-
+ int print_hwcache_events(const char *event_glob, bool name_only)
+ {
+ unsigned int type, op, i, evt_i = 0, evt_num = 0, npmus = 0;
+--
+2.35.1
+
--- /dev/null
+From 0e0b25b2b9a8392a7e0c842cff160f02f3af9dc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Sep 2022 11:00:12 +0800
+Subject: perf print-events: Fix "perf list" can not display the PMU prefix for
+ some hybrid cache events
+
+From: Zhengjun Xing <zhengjun.xing@linux.intel.com>
+
+[ Upstream commit e28c07871c3f2107e316c2590d4703496bd114f4 ]
+
+Some hybrid hardware cache events are only available on one CPU PMU. For
+example, 'L1-dcache-load-misses' is only available on cpu_core.
+
+We have supported in the perf list clearly reporting this info, the
+function works fine before but recently the argument "config" in API
+is_event_supported() is changed from "u64" to "unsigned int" which
+caused a regression, the "perf list" then can not display the PMU prefix
+for some hybrid cache events.
+
+For the hybrid systems, the PMU type ID is stored at config[63:32],
+define config to "unsigned int" will miss the PMU type ID information,
+then the regression happened, the config should be defined as "u64".
+
+Before:
+ # ./perf list |grep "Hardware cache event"
+ L1-dcache-load-misses [Hardware cache event]
+ L1-dcache-loads [Hardware cache event]
+ L1-dcache-stores [Hardware cache event]
+ L1-icache-load-misses [Hardware cache event]
+ L1-icache-loads [Hardware cache event]
+ LLC-load-misses [Hardware cache event]
+ LLC-loads [Hardware cache event]
+ LLC-store-misses [Hardware cache event]
+ LLC-stores [Hardware cache event]
+ branch-load-misses [Hardware cache event]
+ branch-loads [Hardware cache event]
+ dTLB-load-misses [Hardware cache event]
+ dTLB-loads [Hardware cache event]
+ dTLB-store-misses [Hardware cache event]
+ dTLB-stores [Hardware cache event]
+ iTLB-load-misses [Hardware cache event]
+ node-load-misses [Hardware cache event]
+ node-loads [Hardware cache event]
+
+After:
+ # ./perf list |grep "Hardware cache event"
+ L1-dcache-loads [Hardware cache event]
+ L1-dcache-stores [Hardware cache event]
+ L1-icache-load-misses [Hardware cache event]
+ LLC-load-misses [Hardware cache event]
+ LLC-loads [Hardware cache event]
+ LLC-store-misses [Hardware cache event]
+ LLC-stores [Hardware cache event]
+ branch-load-misses [Hardware cache event]
+ branch-loads [Hardware cache event]
+ cpu_atom/L1-icache-loads/ [Hardware cache event]
+ cpu_core/L1-dcache-load-misses/ [Hardware cache event]
+ cpu_core/node-load-misses/ [Hardware cache event]
+ cpu_core/node-loads/ [Hardware cache event]
+ dTLB-load-misses [Hardware cache event]
+ dTLB-loads [Hardware cache event]
+ dTLB-store-misses [Hardware cache event]
+ dTLB-stores [Hardware cache event]
+ iTLB-load-misses [Hardware cache event]
+
+Fixes: 9b7c7728f4e4ba8d ("perf parse-events: Break out tracepoint and printing")
+Reported-by: Yi Ammy <ammy.yi@intel.com>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Xing Zhengjun <zhengjun.xing@linux.intel.com>
+Acked-by: Ian Rogers <irogers@google.com>
+Cc: Alexander Shishkin <alexander.shishkin@intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20220923030013.3726410-1-zhengjun.xing@linux.intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: 71c86cda750b ("perf parse-events: Remove "not supported" hybrid cache events")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/print-events.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
+index ba1ab5134685..04050d4f6db8 100644
+--- a/tools/perf/util/print-events.c
++++ b/tools/perf/util/print-events.c
+@@ -239,7 +239,7 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
+ strlist__delete(sdtlist);
+ }
+
+-static bool is_event_supported(u8 type, unsigned int config)
++static bool is_event_supported(u8 type, u64 config)
+ {
+ bool ret = true;
+ int open_return;
+--
+2.35.1
+
--- /dev/null
+From 26dd7b925f68e1c5ec94f5370caf374d96fc0355 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Sep 2022 13:15:13 +0800
+Subject: perf test: Fix test case 87 ("perf record tests") for hybrid systems
+
+From: Zhengjun Xing <zhengjun.xing@linux.intel.com>
+
+[ Upstream commit 457c8b60267054869513ab1fb5513abb0a566dd0 ]
+
+The test case 87 ("perf record tests") failed on hybrid systems,the event
+"cpu/br_inst_retired.near_call/p" is only for non-hybrid system. Correct
+the test event to support both non-hybrid and hybrid systems.
+
+Before:
+
+ # ./perf test 87
+ 87: perf record tests : FAILED!
+
+After:
+
+ # ./perf test 87
+ 87: perf record tests : Ok
+
+Fixes: 24f378e66021f559 ("perf test: Add basic perf record tests")
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Xing Zhengjun <zhengjun.xing@linux.intel.com>
+Acked-by: Ian Rogers <irogers@google.com>
+Cc: Alexander Shishkin <alexander.shishkin@intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20220927051513.3768717-1-zhengjun.xing@linux.intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/tests/shell/record.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/tests/shell/record.sh b/tools/perf/tests/shell/record.sh
+index 00c7285ce1ac..301f95427159 100755
+--- a/tools/perf/tests/shell/record.sh
++++ b/tools/perf/tests/shell/record.sh
+@@ -61,7 +61,7 @@ test_register_capture() {
+ echo "Register capture test [Skipped missing registers]"
+ return
+ fi
+- if ! perf record -o - --intr-regs=di,r8,dx,cx -e cpu/br_inst_retired.near_call/p \
++ if ! perf record -o - --intr-regs=di,r8,dx,cx -e br_inst_retired.near_call:p \
+ -c 1000 --per-thread true 2> /dev/null \
+ | perf script -F ip,sym,iregs -i - 2> /dev/null \
+ | egrep -q "DI:"
+--
+2.35.1
+
--- /dev/null
+From 2be3625fcc4a3d9d7344f652fc1fd435f27e7e20 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Sep 2022 12:55:43 -0300
+Subject: perf tests record: Fail the test if the 'errs' counter is not zero
+
+From: Arnaldo Carvalho de Melo <acme@redhat.com>
+
+[ Upstream commit 25c5e67cdf744cbb93fd06647611d3036218debe ]
+
+We were just checking for the 'err' variable, when we should really see
+if there was some of the many checked errors that don't stop the test
+right away.
+
+Detected with clang 15.0.0:
+
+ 44 75.23 fedora:37 : FAIL clang version 15.0.0 (Fedora 15.0.0-2.fc37)
+
+ tests/perf-record.c:68:16: error: variable 'errs' set but not used [-Werror,-Wunused-but-set-variable]
+ int err = -1, errs = 0, i, wakeups = 0;
+ ^
+ 1 error generated.
+
+The patch introducing this 'perf test' entry had that check:
+
+ + return (err < 0 || errs > 0) ? -1 : 0;
+
+But at some point we lost that:
+
+ - return (err < 0 || errs > 0) ? -1 : 0;
+ + if (err == -EACCES)
+ + return TEST_SKIP;
+ + if (err < 0)
+ + return TEST_FAIL;
+ + return TEST_OK
+
+Put it back.
+
+Fixes: 2cf88f4614c996e5 ("perf test: Use skip in PERF_RECORD_*")
+Acked-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Link: https://lore.kernel.org/lkml/YzR0n5QhsH9VyYB0@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/tests/perf-record.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
+index 6a001fcfed68..4952abe716f3 100644
+--- a/tools/perf/tests/perf-record.c
++++ b/tools/perf/tests/perf-record.c
+@@ -332,7 +332,7 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
+ out:
+ if (err == -EACCES)
+ return TEST_SKIP;
+- if (err < 0)
++ if (err < 0 || errs != 0)
+ return TEST_FAIL;
+ return TEST_OK;
+ }
+--
+2.35.1
+
--- /dev/null
+From aec760f79a9c3313e605b5d0fbab5671065ec6e9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Aug 2022 15:46:01 +0800
+Subject: reset: imx7: Fix the iMX8MP PCIe PHY PERST support
+
+From: Richard Zhu <hongxing.zhu@nxp.com>
+
+[ Upstream commit 051d9eb403887bb11852b7a4f744728a6a4b1b58 ]
+
+On i.MX7/iMX8MM/iMX8MQ, the initialized default value of PERST bit(BIT3)
+of SRC_PCIEPHY_RCR is 1b'1.
+But i.MX8MP has one inversed default value 1b'0 of PERST bit.
+
+And the PERST bit should be kept 1b'1 after power and clocks are stable.
+So fix the i.MX8MP PCIe PHY PERST support here.
+
+Fixes: e08672c03981 ("reset: imx7: Add support for i.MX8MP SoC")
+Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
+Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
+Tested-by: Marek Vasut <marex@denx.de>
+Tested-by: Richard Leitner <richard.leitner@skidata.com>
+Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
+Link: https://lore.kernel.org/r/1661845564-11373-5-git-send-email-hongxing.zhu@nxp.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/reset/reset-imx7.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
+index 185a333df66c..d2408725eb2c 100644
+--- a/drivers/reset/reset-imx7.c
++++ b/drivers/reset/reset-imx7.c
+@@ -329,6 +329,7 @@ static int imx8mp_reset_set(struct reset_controller_dev *rcdev,
+ break;
+
+ case IMX8MP_RESET_PCIE_CTRL_APPS_EN:
++ case IMX8MP_RESET_PCIEPHY_PERST:
+ value = assert ? 0 : bit;
+ break;
+ }
+--
+2.35.1
+
--- /dev/null
+From 1fc5e5879ca4422e69268b8e6a20c7069d0b53a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Aug 2022 18:08:04 -0700
+Subject: Revert "drm: bridge: analogix/dp: add panel prepare/unprepare in
+ suspend/resume time"
+
+From: Brian Norris <briannorris@chromium.org>
+
+[ Upstream commit cc62d98bd56d45de4531844ca23913a15136c05b ]
+
+This reverts commit 211f276ed3d96e964d2d1106a198c7f4a4b3f4c0.
+
+For quite some time, core DRM helpers already ensure that any relevant
+connectors/CRTCs/etc. are disabled, as well as their associated
+components (e.g., bridges) when suspending the system. Thus,
+analogix_dp_bridge_{enable,disable}() already get called, which in turn
+call drm_panel_{prepare,unprepare}(). This makes these drm_panel_*()
+calls redundant.
+
+Besides redundancy, there are a few problems with this handling:
+
+(1) drm_panel_{prepare,unprepare}() are *not* reference-counted APIs and
+are not in general designed to be handled by multiple callers --
+although some panel drivers have a coarse 'prepared' flag that mitigates
+some damage, at least. So at a minimum this is redundant and confusing,
+but in some cases, this could be actively harmful.
+
+(2) The error-handling is a bit non-standard. We ignored errors in
+suspend(), but handled errors in resume(). And recently, people noticed
+that the clk handling is unbalanced in error paths, and getting *that*
+right is not actually trivial, given the current way errors are mostly
+ignored.
+
+(3) In the particular way analogix_dp_{suspend,resume}() get used (e.g.,
+in rockchip_dp_*(), as a late/early callback), we don't necessarily have
+a proper PM relationship between the DP/bridge device and the panel
+device. So while the DP bridge gets resumed, the panel's parent device
+(e.g., platform_device) may still be suspended, and so any prepare()
+calls may fail.
+
+So remove the superfluous, possibly-harmful suspend()/resume() handling
+of panel state.
+
+Fixes: 211f276ed3d9 ("drm: bridge: analogix/dp: add panel prepare/unprepare in suspend/resume time")
+Link: https://lore.kernel.org/all/Yv2CPBD3Picg%2FgVe@google.com/
+Signed-off-by: Brian Norris <briannorris@chromium.org>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220822180729.1.I8ac5abe3a4c1c6fd5c061686c6e883c22f69022c@changeid
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 13 -------------
+ 1 file changed, 13 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+index 01c8b80e34ec..41431b9d55bd 100644
+--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
++++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+@@ -1863,12 +1863,6 @@ EXPORT_SYMBOL_GPL(analogix_dp_remove);
+ int analogix_dp_suspend(struct analogix_dp_device *dp)
+ {
+ clk_disable_unprepare(dp->clock);
+-
+- if (dp->plat_data->panel) {
+- if (drm_panel_unprepare(dp->plat_data->panel))
+- DRM_ERROR("failed to turnoff the panel\n");
+- }
+-
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(analogix_dp_suspend);
+@@ -1883,13 +1877,6 @@ int analogix_dp_resume(struct analogix_dp_device *dp)
+ return ret;
+ }
+
+- if (dp->plat_data->panel) {
+- if (drm_panel_prepare(dp->plat_data->panel)) {
+- DRM_ERROR("failed to setup the panel\n");
+- return -EBUSY;
+- }
+- }
+-
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(analogix_dp_resume);
+--
+2.35.1
+
--- /dev/null
+From 7c3214bcc3823e45077662c0fbe970ab2caaef19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Sep 2022 15:02:37 +0800
+Subject: selftests: Fix the if conditions of in test_extra_filter()
+
+From: Wang Yufen <wangyufen@huawei.com>
+
+[ Upstream commit bc7a319844891746135dc1f34ab9df78d636a3ac ]
+
+The socket 2 bind the addr in use, bind should fail with EADDRINUSE. So
+if bind success or errno != EADDRINUSE, testcase should be failed.
+
+Fixes: 3ca8e4029969 ("soreuseport: BPF selection functional test")
+Signed-off-by: Wang Yufen <wangyufen@huawei.com>
+Link: https://lore.kernel.org/r/1663916557-10730-1-git-send-email-wangyufen@huawei.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/reuseport_bpf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/net/reuseport_bpf.c b/tools/testing/selftests/net/reuseport_bpf.c
+index 072d709c96b4..65aea27d761c 100644
+--- a/tools/testing/selftests/net/reuseport_bpf.c
++++ b/tools/testing/selftests/net/reuseport_bpf.c
+@@ -328,7 +328,7 @@ static void test_extra_filter(const struct test_params p)
+ if (bind(fd1, addr, sockaddr_size()))
+ error(1, errno, "failed to bind recv socket 1");
+
+- if (!bind(fd2, addr, sockaddr_size()) && errno != EADDRINUSE)
++ if (!bind(fd2, addr, sockaddr_size()) || errno != EADDRINUSE)
+ error(1, errno, "bind socket 2 should fail with EADDRINUSE");
+
+ free(addr);
+--
+2.35.1
+
media-rkvdec-disable-h.264-error-detection.patch
media-mediatek-vcodec-drop-platform_get_resource-ioresource_irq.patch
media-v4l2-compat-ioctl32.c-zero-buffer-passed-to-v4l2_compat_get_array_args.patch
+arm-dts-am33xx-fix-mmchs0-dma-properties.patch
+reset-imx7-fix-the-imx8mp-pcie-phy-perst-support.patch
+arm-dts-am5748-keep-usb4_tm-disabled.patch
+soc-sunxi-sram-actually-claim-sram-regions.patch
+soc-sunxi-sram-prevent-the-driver-from-being-unbound.patch
+soc-sunxi-sram-fix-probe-function-ordering-issues.patch
+soc-sunxi-sram-fix-debugfs-info-for-a64-sram-c.patch
+asoc-imx-card-fix-refcount-issue-with-of_node_put.patch
+clk-microchip-mpfs-fix-clk_cfg-array-bounds-violatio.patch
+clk-microchip-mpfs-make-the-rtc-s-ahb-clock-critical.patch
+arm64-dts-qcom-sm8350-fix-ufs-phy-serdes-size.patch
+asoc-tas2770-reinit-regcache-on-reset.patch
+drm-bridge-lt8912b-add-vsync-hsync.patch
+drm-bridge-lt8912b-set-hdmi-or-dvi-mode.patch
+drm-bridge-lt8912b-fix-corrupted-image-output.patch
+net-macb-fix-zynqmp-sgmii-non-wakeup-source-resume-f.patch
+revert-drm-bridge-analogix-dp-add-panel-prepare-unpr.patch
+input-melfas_mip4-fix-return-value-check-in-mip4_pro.patch
+gpio-mvebu-fix-check-for-pwm-support-on-non-a8k-plat.patch
+perf-parse-events-break-out-tracepoint-and-printing.patch
+perf-print-events-fix-perf-list-can-not-display-the-.patch
+perf-parse-events-remove-not-supported-hybrid-cache-.patch
+usbnet-fix-memory-leak-in-usbnet_disconnect.patch
+net-sched-act_ct-fix-possible-refcount-leak-in-tcf_c.patch
+cxgb4-fix-missing-unlock-on-ethofld-desc-collect-fai.patch
+net-mlxbf_gige-fix-an-is_err-vs-null-bug-in-mlxbf_gi.patch
+nvme-fix-ioc_pr_clear-and-ioc_pr_release-ioctls-for-.patch
+wifi-cfg80211-fix-mcs-divisor-value.patch
+wifi-mac80211-fix-regression-with-non-qos-drivers.patch
+wifi-mac80211-fix-memory-corruption-in-minstrel_ht_u.patch
+net-stmmac-power-up-down-serdes-in-stmmac_open-relea.patch
+net-phy-don-t-warn-for-phy_up-state-in-mdio_bus_phy_.patch
+selftests-fix-the-if-conditions-of-in-test_extra_fil.patch
+ice-xsk-change-batched-tx-descriptor-cleaning.patch
+ice-xsk-drop-power-of-2-ring-size-restriction-for-af.patch
+vdpa-ifcvf-fix-the-calculation-of-queuepair.patch
+virtio-blk-fix-warn_on_once-in-virtio_queue_rq.patch
+vdpa-mlx5-fix-mq-to-support-non-power-of-two-num-que.patch
+don-t-use-__kernel_write-on-kmap_local_page.patch
+clk-imx-imx6sx-remove-the-set_rate_parent-flag-for-q.patch
+drm-i915-gt-perf_limit_reasons-are-only-available-fo.patch
+clk-iproc-do-not-rely-on-node-name-for-correct-pll-s.patch
+clk-imx93-drop-of_match_ptr.patch
+net-mscc-ocelot-fix-tagged-vlan-refusal-while-under-.patch
+net-ethernet-mtk_eth_soc-fix-mask-of-rx_dma_get_spor.patch
+perf-test-fix-test-case-87-perf-record-tests-for-hyb.patch
+perf-tests-record-fail-the-test-if-the-errs-counter-.patch
+kvm-x86-hide-ia32_platform_dca_cap-31-0-from-the-gue.patch
--- /dev/null
+From dcb34d96025f1835ee0d9b36a15378024eed7fbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Aug 2022 23:12:40 -0500
+Subject: soc: sunxi: sram: Actually claim SRAM regions
+
+From: Samuel Holland <samuel@sholland.org>
+
+[ Upstream commit fd362baad2e659ef0fb5652f023a606b248f1781 ]
+
+sunxi_sram_claim() checks the sram_desc->claimed flag before updating
+the register, with the intent that only one device can claim a region.
+However, this was ineffective because the flag was never set.
+
+Fixes: 4af34b572a85 ("drivers: soc: sunxi: Introduce SoC driver to map SRAMs")
+Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Tested-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Link: https://lore.kernel.org/r/20220815041248.53268-4-samuel@sholland.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/sunxi/sunxi_sram.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
+index a8f3876963a0..f3d3f9259df9 100644
+--- a/drivers/soc/sunxi/sunxi_sram.c
++++ b/drivers/soc/sunxi/sunxi_sram.c
+@@ -254,6 +254,7 @@ int sunxi_sram_claim(struct device *dev)
+ writel(val | ((device << sram_data->offset) & mask),
+ base + sram_data->reg);
+
++ sram_desc->claimed = true;
+ spin_unlock(&sram_lock);
+
+ return 0;
+--
+2.35.1
+
--- /dev/null
+From 97aa423aed1cc98e02d5b20acd38780dc01a5928 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Aug 2022 23:12:43 -0500
+Subject: soc: sunxi: sram: Fix debugfs info for A64 SRAM C
+
+From: Samuel Holland <samuel@sholland.org>
+
+[ Upstream commit e3c95edb1bd8b9c2cb0caa6ae382fc8080f6a0ed ]
+
+The labels were backward with respect to the register values. The SRAM
+is mapped to the CPU when the register value is 1.
+
+Fixes: 5e4fb6429761 ("drivers: soc: sunxi: add support for A64 and its SRAM C")
+Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Link: https://lore.kernel.org/r/20220815041248.53268-7-samuel@sholland.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/sunxi/sunxi_sram.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
+index 52d07bed7664..09754cd1d57d 100644
+--- a/drivers/soc/sunxi/sunxi_sram.c
++++ b/drivers/soc/sunxi/sunxi_sram.c
+@@ -78,8 +78,8 @@ static struct sunxi_sram_desc sun4i_a10_sram_d = {
+
+ static struct sunxi_sram_desc sun50i_a64_sram_c = {
+ .data = SUNXI_SRAM_DATA("C", 0x4, 24, 1,
+- SUNXI_SRAM_MAP(0, 1, "cpu"),
+- SUNXI_SRAM_MAP(1, 0, "de2")),
++ SUNXI_SRAM_MAP(1, 0, "cpu"),
++ SUNXI_SRAM_MAP(0, 1, "de2")),
+ };
+
+ static const struct of_device_id sunxi_sram_dt_ids[] = {
+--
+2.35.1
+
--- /dev/null
+From dc3b5f0fb39694bcb32d04ccecf9c0c6f8a24332 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Aug 2022 23:12:42 -0500
+Subject: soc: sunxi: sram: Fix probe function ordering issues
+
+From: Samuel Holland <samuel@sholland.org>
+
+[ Upstream commit 49fad91a7b8941979c3e9a35f9894ac45bc5d3d6 ]
+
+Errors from debugfs are intended to be non-fatal, and should not prevent
+the driver from probing.
+
+Since debugfs file creation is treated as infallible, move it below the
+parts of the probe function that can fail. This prevents an error
+elsewhere in the probe function from causing the file to leak. Do the
+same for the call to of_platform_populate().
+
+Finally, checkpatch suggests an octal literal for the file permissions.
+
+Fixes: 4af34b572a85 ("drivers: soc: sunxi: Introduce SoC driver to map SRAMs")
+Fixes: 5828729bebbb ("soc: sunxi: export a regmap for EMAC clock reg on A64")
+Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Tested-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Link: https://lore.kernel.org/r/20220815041248.53268-6-samuel@sholland.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/sunxi/sunxi_sram.c | 13 +++++--------
+ 1 file changed, 5 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
+index a858a37fcdd4..52d07bed7664 100644
+--- a/drivers/soc/sunxi/sunxi_sram.c
++++ b/drivers/soc/sunxi/sunxi_sram.c
+@@ -332,9 +332,9 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = {
+
+ static int __init sunxi_sram_probe(struct platform_device *pdev)
+ {
+- struct dentry *d;
+ struct regmap *emac_clock;
+ const struct sunxi_sramc_variant *variant;
++ struct device *dev = &pdev->dev;
+
+ sram_dev = &pdev->dev;
+
+@@ -346,13 +346,6 @@ static int __init sunxi_sram_probe(struct platform_device *pdev)
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+- of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+-
+- d = debugfs_create_file("sram", S_IRUGO, NULL, NULL,
+- &sunxi_sram_fops);
+- if (!d)
+- return -ENOMEM;
+-
+ if (variant->num_emac_clocks > 0) {
+ emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
+ &sunxi_sram_emac_clock_regmap);
+@@ -361,6 +354,10 @@ static int __init sunxi_sram_probe(struct platform_device *pdev)
+ return PTR_ERR(emac_clock);
+ }
+
++ of_platform_populate(dev->of_node, NULL, NULL, dev);
++
++ debugfs_create_file("sram", 0444, NULL, NULL, &sunxi_sram_fops);
++
+ return 0;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 3f9a71e17bad10e1d4cb38e330e11c5b09cef9aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Aug 2022 23:12:41 -0500
+Subject: soc: sunxi: sram: Prevent the driver from being unbound
+
+From: Samuel Holland <samuel@sholland.org>
+
+[ Upstream commit 90e10a1fcd9b24b4ba8c0d35136127473dcd829e ]
+
+This driver exports a regmap tied to the platform device (as opposed to
+a syscon, which exports a regmap tied to the OF node). Because of this,
+the driver can never be unbound, as that would destroy the regmap. Use
+builtin_platform_driver_probe() to enforce this limitation.
+
+Fixes: 5828729bebbb ("soc: sunxi: export a regmap for EMAC clock reg on A64")
+Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Tested-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Link: https://lore.kernel.org/r/20220815041248.53268-5-samuel@sholland.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/sunxi/sunxi_sram.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
+index f3d3f9259df9..a858a37fcdd4 100644
+--- a/drivers/soc/sunxi/sunxi_sram.c
++++ b/drivers/soc/sunxi/sunxi_sram.c
+@@ -330,7 +330,7 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = {
+ .writeable_reg = sunxi_sram_regmap_accessible_reg,
+ };
+
+-static int sunxi_sram_probe(struct platform_device *pdev)
++static int __init sunxi_sram_probe(struct platform_device *pdev)
+ {
+ struct dentry *d;
+ struct regmap *emac_clock;
+@@ -410,9 +410,8 @@ static struct platform_driver sunxi_sram_driver = {
+ .name = "sunxi-sram",
+ .of_match_table = sunxi_sram_dt_match,
+ },
+- .probe = sunxi_sram_probe,
+ };
+-module_platform_driver(sunxi_sram_driver);
++builtin_platform_driver_probe(sunxi_sram_driver, sunxi_sram_probe);
+
+ MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+ MODULE_DESCRIPTION("Allwinner sunXi SRAM Controller Driver");
+--
+2.35.1
+
--- /dev/null
+From 274f2dc6e10bfdba2bb1f3ef3176ad24384c8997 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Sep 2022 21:25:51 -0700
+Subject: usbnet: Fix memory leak in usbnet_disconnect()
+
+From: Peilin Ye <peilin.ye@bytedance.com>
+
+[ Upstream commit a43206156263fbaf1f2b7f96257441f331e91bb7 ]
+
+Currently usbnet_disconnect() unanchors and frees all deferred URBs
+using usb_scuttle_anchored_urbs(), which does not free urb->context,
+causing a memory leak as reported by syzbot.
+
+Use a usb_get_from_anchor() while loop instead, similar to what we did
+in commit 19cfe912c37b ("Bluetooth: btusb: Fix memory leak in
+play_deferred"). Also free urb->sg.
+
+Reported-and-tested-by: syzbot+dcd3e13cf4472f2e0ba1@syzkaller.appspotmail.com
+Fixes: 69ee472f2706 ("usbnet & cdc-ether: Autosuspend for online devices")
+Fixes: 638c5115a794 ("USBNET: support DMA SG")
+Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
+Link: https://lore.kernel.org/r/20220923042551.2745-1-yepeilin.cs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/usbnet.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
+index 0ed09bb91c44..bccf63aac6cd 100644
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -1601,6 +1601,7 @@ void usbnet_disconnect (struct usb_interface *intf)
+ struct usbnet *dev;
+ struct usb_device *xdev;
+ struct net_device *net;
++ struct urb *urb;
+
+ dev = usb_get_intfdata(intf);
+ usb_set_intfdata(intf, NULL);
+@@ -1617,7 +1618,11 @@ void usbnet_disconnect (struct usb_interface *intf)
+ net = dev->net;
+ unregister_netdev (net);
+
+- usb_scuttle_anchored_urbs(&dev->deferred);
++ while ((urb = usb_get_from_anchor(&dev->deferred))) {
++ dev_kfree_skb(urb->context);
++ kfree(urb->sg);
++ usb_free_urb(urb);
++ }
+
+ if (dev->driver_info->unbind)
+ dev->driver_info->unbind(dev, intf);
+--
+2.35.1
+
--- /dev/null
+From 810df6c2e953bb028e80c13d9ce925ca7906646f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Sep 2022 17:10:13 +0800
+Subject: vdpa/ifcvf: fix the calculation of queuepair
+
+From: Angus Chen <angus.chen@jaguarmicro.com>
+
+[ Upstream commit db5db1a00d0816207be3a0166fcb4f523eaf3b52 ]
+
+The q_pair_id to address a queue pair in the lm bar should be
+calculated by queue_id / 2 rather than queue_id / nr_vring.
+
+Fixes: 2ddae773c93b ("vDPA/ifcvf: detect and use the onboard number of queues directly")
+Signed-off-by: Angus Chen <angus.chen@jaguarmicro.com>
+Reviewed-by: Jason Wang <jasowang@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Acked-by: Zhu Lingshan <lingshan.zhu@intel.com>
+Message-Id: <20220923091013.191-1-angus.chen@jaguarmicro.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/ifcvf/ifcvf_base.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/vdpa/ifcvf/ifcvf_base.c b/drivers/vdpa/ifcvf/ifcvf_base.c
+index 48c4dadb0c7c..a4c1b985f79a 100644
+--- a/drivers/vdpa/ifcvf/ifcvf_base.c
++++ b/drivers/vdpa/ifcvf/ifcvf_base.c
+@@ -315,7 +315,7 @@ u16 ifcvf_get_vq_state(struct ifcvf_hw *hw, u16 qid)
+ u32 q_pair_id;
+
+ ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg;
+- q_pair_id = qid / hw->nr_vring;
++ q_pair_id = qid / 2;
+ avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2];
+ last_avail_idx = vp_ioread16(avail_idx_addr);
+
+@@ -329,7 +329,7 @@ int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num)
+ u32 q_pair_id;
+
+ ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg;
+- q_pair_id = qid / hw->nr_vring;
++ q_pair_id = qid / 2;
+ avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2];
+ hw->vring[qid].last_avail_idx = num;
+ vp_iowrite16(num, avail_idx_addr);
+--
+2.35.1
+
--- /dev/null
+From 776038975f95f955f4d30505f582ec2e0e1d66c6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Sep 2022 15:50:19 +0300
+Subject: vdpa/mlx5: Fix MQ to support non power of two num queues
+
+From: Eli Cohen <elic@nvidia.com>
+
+[ Upstream commit a43ae8057cc154fd26a3a23c0e8643bef104d995 ]
+
+RQT objects require that a power of two value be configured for both
+rqt_max_size and rqt_actual size.
+
+For create_rqt, make sure to round up to the power of two the value of
+given by the user who created the vdpa device and given by
+ndev->rqt_size. The actual size is also rounded up to the power of two
+using the current number of VQs given by ndev->cur_num_vqs.
+
+Same goes with modify_rqt where we need to make sure act size is power
+of two based on the new number of QPs.
+
+Without this patch, attempt to create a device with non power of two QPs
+would result in error from firmware.
+
+Fixes: 52893733f2c5 ("vdpa/mlx5: Add multiqueue support")
+Signed-off-by: Eli Cohen <elic@nvidia.com>
+Message-Id: <20220912125019.833708-1-elic@nvidia.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/mlx5/net/mlx5_vnet.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+index e85c1d71f4ed..f527cbeb1169 100644
+--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+@@ -1297,6 +1297,8 @@ static void teardown_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *
+
+ static int create_rqt(struct mlx5_vdpa_net *ndev)
+ {
++ int rqt_table_size = roundup_pow_of_two(ndev->rqt_size);
++ int act_sz = roundup_pow_of_two(ndev->cur_num_vqs / 2);
+ __be32 *list;
+ void *rqtc;
+ int inlen;
+@@ -1304,7 +1306,7 @@ static int create_rqt(struct mlx5_vdpa_net *ndev)
+ int i, j;
+ int err;
+
+- inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + ndev->rqt_size * MLX5_ST_SZ_BYTES(rq_num);
++ inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + rqt_table_size * MLX5_ST_SZ_BYTES(rq_num);
+ in = kzalloc(inlen, GFP_KERNEL);
+ if (!in)
+ return -ENOMEM;
+@@ -1313,12 +1315,12 @@ static int create_rqt(struct mlx5_vdpa_net *ndev)
+ rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
+
+ MLX5_SET(rqtc, rqtc, list_q_type, MLX5_RQTC_LIST_Q_TYPE_VIRTIO_NET_Q);
+- MLX5_SET(rqtc, rqtc, rqt_max_size, ndev->rqt_size);
++ MLX5_SET(rqtc, rqtc, rqt_max_size, rqt_table_size);
+ list = MLX5_ADDR_OF(rqtc, rqtc, rq_num[0]);
+- for (i = 0, j = 0; i < ndev->rqt_size; i++, j += 2)
++ for (i = 0, j = 0; i < act_sz; i++, j += 2)
+ list[i] = cpu_to_be32(ndev->vqs[j % ndev->cur_num_vqs].virtq_id);
+
+- MLX5_SET(rqtc, rqtc, rqt_actual_size, ndev->rqt_size);
++ MLX5_SET(rqtc, rqtc, rqt_actual_size, act_sz);
+ err = mlx5_vdpa_create_rqt(&ndev->mvdev, in, inlen, &ndev->res.rqtn);
+ kfree(in);
+ if (err)
+@@ -1331,6 +1333,7 @@ static int create_rqt(struct mlx5_vdpa_net *ndev)
+
+ static int modify_rqt(struct mlx5_vdpa_net *ndev, int num)
+ {
++ int act_sz = roundup_pow_of_two(num / 2);
+ __be32 *list;
+ void *rqtc;
+ int inlen;
+@@ -1338,7 +1341,7 @@ static int modify_rqt(struct mlx5_vdpa_net *ndev, int num)
+ int i, j;
+ int err;
+
+- inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + ndev->rqt_size * MLX5_ST_SZ_BYTES(rq_num);
++ inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + act_sz * MLX5_ST_SZ_BYTES(rq_num);
+ in = kzalloc(inlen, GFP_KERNEL);
+ if (!in)
+ return -ENOMEM;
+@@ -1349,10 +1352,10 @@ static int modify_rqt(struct mlx5_vdpa_net *ndev, int num)
+ MLX5_SET(rqtc, rqtc, list_q_type, MLX5_RQTC_LIST_Q_TYPE_VIRTIO_NET_Q);
+
+ list = MLX5_ADDR_OF(rqtc, rqtc, rq_num[0]);
+- for (i = 0, j = 0; i < ndev->rqt_size; i++, j += 2)
++ for (i = 0, j = 0; i < act_sz; i++, j = j + 2)
+ list[i] = cpu_to_be32(ndev->vqs[j % num].virtq_id);
+
+- MLX5_SET(rqtc, rqtc, rqt_actual_size, ndev->rqt_size);
++ MLX5_SET(rqtc, rqtc, rqt_actual_size, act_sz);
+ err = mlx5_vdpa_modify_rqt(&ndev->mvdev, in, inlen, ndev->res.rqtn);
+ kfree(in);
+ if (err)
+--
+2.35.1
+
--- /dev/null
+From 4e24240c6bbfa754e2c81771f09e16d663ec7f63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Aug 2022 00:01:53 +0900
+Subject: virtio-blk: Fix WARN_ON_ONCE in virtio_queue_rq()
+
+From: Suwan Kim <suwan.kim027@gmail.com>
+
+[ Upstream commit 37fafe6b61e4f15d977982635bb785f4e605f7cd ]
+
+If a request fails at virtio_queue_rqs(), it is inserted to requeue_list
+and passed to virtio_queue_rq(). Then blk_mq_start_request() can be called
+again at virtio_queue_rq() and trigger WARN_ON_ONCE like below trace because
+request state was already set to MQ_RQ_IN_FLIGHT in virtio_queue_rqs()
+despite the failure.
+
+[ 1.890468] ------------[ cut here ]------------
+[ 1.890776] WARNING: CPU: 2 PID: 122 at block/blk-mq.c:1143
+blk_mq_start_request+0x8a/0xe0
+[ 1.891045] Modules linked in:
+[ 1.891250] CPU: 2 PID: 122 Comm: journal-offline Not tainted 5.19.0+ #44
+[ 1.891504] Hardware name: ChromiumOS crosvm, BIOS 0
+[ 1.891739] RIP: 0010:blk_mq_start_request+0x8a/0xe0
+[ 1.891961] Code: 12 80 74 22 48 8b 4b 10 8b 89 64 01 00 00 8b 53
+20 83 fa ff 75 08 ba 00 00 00 80 0b 53 24 c1 e1 10 09 d1 89 48 34 5b
+41 5e c3 <0f> 0b eb b8 65 8b 05 2b 39 b6 7e 89 c0 48 0f a3 05 39 77 5b
+01 0f
+[ 1.892443] RSP: 0018:ffffc900002777b0 EFLAGS: 00010202
+[ 1.892673] RAX: 0000000000000000 RBX: ffff888004bc0000 RCX: 0000000000000000
+[ 1.892952] RDX: 0000000000000000 RSI: ffff888003d7c200 RDI: ffff888004bc0000
+[ 1.893228] RBP: 0000000000000000 R08: 0000000000000001 R09: ffff888004bc0100
+[ 1.893506] R10: ffffffffffffffff R11: ffffffff8185ca10 R12: ffff888004bc0000
+[ 1.893797] R13: ffffc90000277900 R14: ffff888004ab2340 R15: ffff888003d86e00
+[ 1.894060] FS: 00007ffa143a4640(0000) GS:ffff88807dd00000(0000)
+knlGS:0000000000000000
+[ 1.894412] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 1.894682] CR2: 00005648577d9088 CR3: 00000000053da004 CR4: 0000000000170ee0
+[ 1.894953] Call Trace:
+[ 1.895139] <TASK>
+[ 1.895303] virtblk_prep_rq+0x1e5/0x280
+[ 1.895509] virtio_queue_rq+0x5c/0x310
+[ 1.895710] ? virtqueue_add_sgs+0x95/0xb0
+[ 1.895905] ? _raw_spin_unlock_irqrestore+0x16/0x30
+[ 1.896133] ? virtio_queue_rqs+0x340/0x390
+[ 1.896453] ? sbitmap_get+0xfa/0x220
+[ 1.896678] __blk_mq_issue_directly+0x41/0x180
+[ 1.896906] blk_mq_plug_issue_direct+0xd8/0x2c0
+[ 1.897115] blk_mq_flush_plug_list+0x115/0x180
+[ 1.897342] blk_add_rq_to_plug+0x51/0x130
+[ 1.897543] blk_mq_submit_bio+0x3a1/0x570
+[ 1.897750] submit_bio_noacct_nocheck+0x418/0x520
+[ 1.897985] ? submit_bio_noacct+0x1e/0x260
+[ 1.897989] ext4_bio_write_page+0x222/0x420
+[ 1.898000] mpage_process_page_bufs+0x178/0x1c0
+[ 1.899451] mpage_prepare_extent_to_map+0x2d2/0x440
+[ 1.899603] ext4_writepages+0x495/0x1020
+[ 1.899733] do_writepages+0xcb/0x220
+[ 1.899871] ? __seccomp_filter+0x171/0x7e0
+[ 1.900006] file_write_and_wait_range+0xcd/0xf0
+[ 1.900167] ext4_sync_file+0x72/0x320
+[ 1.900308] __x64_sys_fsync+0x66/0xa0
+[ 1.900449] do_syscall_64+0x31/0x50
+[ 1.900595] entry_SYSCALL_64_after_hwframe+0x63/0xcd
+[ 1.900747] RIP: 0033:0x7ffa16ec96ea
+[ 1.900883] Code: b8 4a 00 00 00 0f 05 48 3d 00 f0 ff ff 77 41 c3
+48 83 ec 18 89 7c 24 0c e8 e3 02 f8 ff 8b 7c 24 0c 89 c2 b8 4a 00 00
+00 0f 05 <48> 3d 00 f0 ff ff 77 36 89 d7 89 44 24 0c e8 43 03 f8 ff 8b
+44 24
+[ 1.901302] RSP: 002b:00007ffa143a3ac0 EFLAGS: 00000293 ORIG_RAX:
+000000000000004a
+[ 1.901499] RAX: ffffffffffffffda RBX: 0000560277ec6fe0 RCX: 00007ffa16ec96ea
+[ 1.901696] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000016
+[ 1.901884] RBP: 0000560277ec5910 R08: 0000000000000000 R09: 00007ffa143a4640
+[ 1.902082] R10: 00007ffa16e4d39e R11: 0000000000000293 R12: 00005602773f59e0
+[ 1.902459] R13: 0000000000000000 R14: 00007fffbfc007ff R15: 00007ffa13ba4000
+[ 1.902763] </TASK>
+[ 1.902877] ---[ end trace 0000000000000000 ]---
+
+To avoid calling blk_mq_start_request() twice, This patch moves the
+execution of blk_mq_start_request() to the end of virtblk_prep_rq().
+And instead of requeuing failed request to plug list in the error path of
+virtblk_add_req_batch(), it uses blk_mq_requeue_request() to change failed
+request state to MQ_RQ_IDLE. Then virtblk can safely handle the request
+on the next trial.
+
+Fixes: 0e9911fa768f ("virtio-blk: support mq_ops->queue_rqs()")
+Reported-by: Alexandre Courbot <acourbot@chromium.org>
+Tested-by: Alexandre Courbot <acourbot@chromium.org>
+Signed-off-by: Suwan Kim <suwan.kim027@gmail.com>
+Message-Id: <20220830150153.12627-1-suwan.kim027@gmail.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Pankaj Raghav <p.raghav@samsung.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/virtio_blk.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
+index 59d6d5faf739..dcd639e58ff0 100644
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -322,14 +322,14 @@ static blk_status_t virtblk_prep_rq(struct blk_mq_hw_ctx *hctx,
+ if (unlikely(status))
+ return status;
+
+- blk_mq_start_request(req);
+-
+ vbr->sg_table.nents = virtblk_map_data(hctx, req, vbr);
+ if (unlikely(vbr->sg_table.nents < 0)) {
+ virtblk_cleanup_cmd(req);
+ return BLK_STS_RESOURCE;
+ }
+
++ blk_mq_start_request(req);
++
+ return BLK_STS_OK;
+ }
+
+@@ -391,8 +391,7 @@ static bool virtblk_prep_rq_batch(struct request *req)
+ }
+
+ static bool virtblk_add_req_batch(struct virtio_blk_vq *vq,
+- struct request **rqlist,
+- struct request **requeue_list)
++ struct request **rqlist)
+ {
+ unsigned long flags;
+ int err;
+@@ -408,7 +407,7 @@ static bool virtblk_add_req_batch(struct virtio_blk_vq *vq,
+ if (err) {
+ virtblk_unmap_data(req, vbr);
+ virtblk_cleanup_cmd(req);
+- rq_list_add(requeue_list, req);
++ blk_mq_requeue_request(req, true);
+ }
+ }
+
+@@ -436,7 +435,7 @@ static void virtio_queue_rqs(struct request **rqlist)
+
+ if (!next || req->mq_hctx != next->mq_hctx) {
+ req->rq_next = NULL;
+- kick = virtblk_add_req_batch(vq, rqlist, &requeue_list);
++ kick = virtblk_add_req_batch(vq, rqlist);
+ if (kick)
+ virtqueue_notify(vq->vq);
+
+--
+2.35.1
+
--- /dev/null
+From 243642e8dfc50e77e2e249324fb78b5f9b6df358 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Sep 2022 23:40:34 +0530
+Subject: wifi: cfg80211: fix MCS divisor value
+
+From: Tamizh Chelvam Raja <quic_tamizhr@quicinc.com>
+
+[ Upstream commit 64e966d1e84b29c9fa916cfeaabbf4013703942e ]
+
+The Bitrate for HE/EHT MCS6 is calculated wrongly due to the
+incorrect MCS divisor value for mcs6. Fix it with the proper
+value.
+
+previous mcs_divisor value = (11769/6144) = 1.915527
+
+fixed mcs_divisor value = (11377/6144) = 1.851725
+
+Fixes: 9c97c88d2f4b ("cfg80211: Add support to calculate and report 4096-QAM HE rates")
+Signed-off-by: Tamizh Chelvam Raja <quic_tamizhr@quicinc.com>
+Link: https://lore.kernel.org/r/20220908181034.9936-1-quic_tamizhr@quicinc.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/util.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/wireless/util.c b/net/wireless/util.c
+index b7257862e0fe..28b7f120501a 100644
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -1361,7 +1361,7 @@ static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)
+ 25599, /* 4.166666... */
+ 17067, /* 2.777777... */
+ 12801, /* 2.083333... */
+- 11769, /* 1.851851... */
++ 11377, /* 1.851725... */
+ 10239, /* 1.666666... */
+ 8532, /* 1.388888... */
+ 7680, /* 1.250000... */
+@@ -1444,7 +1444,7 @@ static u32 cfg80211_calculate_bitrate_eht(struct rate_info *rate)
+ 25599, /* 4.166666... */
+ 17067, /* 2.777777... */
+ 12801, /* 2.083333... */
+- 11769, /* 1.851851... */
++ 11377, /* 1.851725... */
+ 10239, /* 1.666666... */
+ 8532, /* 1.388888... */
+ 7680, /* 1.250000... */
+--
+2.35.1
+
--- /dev/null
+From 9bc63d2369f273538f99d4ad380f3c8cf85b6e67 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Sep 2022 17:01:35 +0200
+Subject: wifi: mac80211: fix memory corruption in minstrel_ht_update_rates()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Paweł Lenkow <pawel.lenkow@camlingroup.com>
+
+[ Upstream commit be92292b90bfdc31f332c962882b6d3ea0285fdf ]
+
+During our testing of WFM200 module over SDIO on i.MX6Q-based platform,
+we discovered a memory corruption on the system, tracing back to the wfx
+driver. Using kfence, it was possible to trace it back to the root
+cause, which is hw->max_rates set to 8 in wfx_init_common,
+while the maximum defined by IEEE80211_TX_TABLE_SIZE is 4.
+
+This causes array out-of-bounds writes during updates of the rate table,
+as seen below:
+
+BUG: KFENCE: memory corruption in kfree_rcu_work+0x320/0x36c
+
+Corrupted memory at 0xe0a4ffe0 [ 0x03 0x03 0x03 0x03 0x01 0x00 0x00
+0x02 0x02 0x02 0x09 0x00 0x21 0xbb 0xbb 0xbb ] (in kfence-#81):
+kfree_rcu_work+0x320/0x36c
+process_one_work+0x3ec/0x920
+worker_thread+0x60/0x7a4
+kthread+0x174/0x1b4
+ret_from_fork+0x14/0x2c
+0x0
+
+kfence-#81: 0xe0a4ffc0-0xe0a4ffdf, size=32, cache=kmalloc-64
+
+allocated by task 297 on cpu 0 at 631.039555s:
+minstrel_ht_update_rates+0x38/0x2b0 [mac80211]
+rate_control_tx_status+0xb4/0x148 [mac80211]
+ieee80211_tx_status_ext+0x364/0x1030 [mac80211]
+ieee80211_tx_status+0xe0/0x118 [mac80211]
+ieee80211_tasklet_handler+0xb0/0xe0 [mac80211]
+tasklet_action_common.constprop.0+0x11c/0x148
+__do_softirq+0x1a4/0x61c
+irq_exit+0xcc/0x104
+call_with_stack+0x18/0x20
+__irq_svc+0x80/0xb0
+wq_worker_sleeping+0x10/0x100
+wq_worker_sleeping+0x10/0x100
+schedule+0x50/0xe0
+schedule_timeout+0x2e0/0x474
+wait_for_completion+0xdc/0x1ec
+mmc_wait_for_req_done+0xc4/0xf8
+mmc_io_rw_extended+0x3b4/0x4ec
+sdio_io_rw_ext_helper+0x290/0x384
+sdio_memcpy_toio+0x30/0x38
+wfx_sdio_copy_to_io+0x88/0x108 [wfx]
+wfx_data_write+0x88/0x1f0 [wfx]
+bh_work+0x1c8/0xcc0 [wfx]
+process_one_work+0x3ec/0x920
+worker_thread+0x60/0x7a4
+kthread+0x174/0x1b4
+ret_from_fork+0x14/0x2c 0x0
+
+After discussion on the wireless mailing list it was clarified
+that the issue has been introduced by:
+commit ee0e16ab756a ("mac80211: minstrel_ht: fill all requested rates")
+and fix shall be in minstrel_ht_update_rates in rc80211_minstrel_ht.c.
+
+Fixes: ee0e16ab756a ("mac80211: minstrel_ht: fill all requested rates")
+Link: https://lore.kernel.org/all/12e5adcd-8aed-f0f7-70cc-4fb7b656b829@camlingroup.com/
+Link: https://lore.kernel.org/linux-wireless/20220915131445.30600-1-lech.perczak@camlingroup.com/
+Cc: Jérôme Pouiller <jerome.pouiller@silabs.com>
+Cc: Johannes Berg <johannes@sipsolutions.net>
+Cc: Peter Seiderer <ps.report@gmx.net>
+Cc: Kalle Valo <kvalo@kernel.org>
+Cc: Krzysztof Drobiński <krzysztof.drobinski@camlingroup.com>,
+Signed-off-by: Paweł Lenkow <pawel.lenkow@camlingroup.com>
+Signed-off-by: Lech Perczak <lech.perczak@camlingroup.com>
+Reviewed-by: Peter Seiderer <ps.report@gmx.net>
+Reviewed-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
+Acked-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/rc80211_minstrel_ht.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
+index 5f27e6746762..788a82f9c74d 100644
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -10,6 +10,7 @@
+ #include <linux/random.h>
+ #include <linux/moduleparam.h>
+ #include <linux/ieee80211.h>
++#include <linux/minmax.h>
+ #include <net/mac80211.h>
+ #include "rate.h"
+ #include "sta_info.h"
+@@ -1550,6 +1551,7 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+ {
+ struct ieee80211_sta_rates *rates;
+ int i = 0;
++ int max_rates = min_t(int, mp->hw->max_rates, IEEE80211_TX_RATE_TABLE_SIZE);
+
+ rates = kzalloc(sizeof(*rates), GFP_ATOMIC);
+ if (!rates)
+@@ -1559,10 +1561,10 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[0]);
+
+ /* Fill up remaining, keep one entry for max_probe_rate */
+- for (; i < (mp->hw->max_rates - 1); i++)
++ for (; i < (max_rates - 1); i++)
+ minstrel_ht_set_rate(mp, mi, rates, i, mi->max_tp_rate[i]);
+
+- if (i < mp->hw->max_rates)
++ if (i < max_rates)
+ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
+
+ if (i < IEEE80211_TX_RATE_TABLE_SIZE)
+--
+2.35.1
+
--- /dev/null
+From 40da29cefedf0f9fcd55d408691046d42b1a0055 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Sep 2022 21:20:52 +0200
+Subject: wifi: mac80211: fix regression with non-QoS drivers
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit d873697ef2b7e1b6fdd8e9d449d9354bd5d29a4a ]
+
+Commit 10cb8e617560 ("mac80211: enable QoS support for nl80211 ctrl port")
+changed ieee80211_tx_control_port() to aways call
+__ieee80211_select_queue() without checking local->hw.queues.
+
+__ieee80211_select_queue() returns a queue-id between 0 and 3, which means
+that now ieee80211_tx_control_port() may end up setting the queue-mapping
+for a skb to a value higher then local->hw.queues if local->hw.queues
+is less then 4.
+
+Specifically this is a problem for ralink rt2500-pci cards where
+local->hw.queues is 2. There this causes rt2x00queue_get_tx_queue() to
+return NULL and the following error to be logged: "ieee80211 phy0:
+rt2x00mac_tx: Error - Attempt to send packet over invalid queue 2",
+after which association with the AP fails.
+
+Other callers of __ieee80211_select_queue() skip calling it when
+local->hw.queues < IEEE80211_NUM_ACS, add the same check to
+ieee80211_tx_control_port(). This fixes ralink rt2500-pci and
+similar cards when less then 4 tx-queues no longer working.
+
+Fixes: 10cb8e617560 ("mac80211: enable QoS support for nl80211 ctrl port")
+Cc: Markus Theil <markus.theil@tu-ilmenau.de>
+Suggested-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20220918192052.443529-1-hdegoede@redhat.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/tx.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 3cd24d8170d3..f6f09a3506aa 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -5761,6 +5761,9 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
+ skb_reset_network_header(skb);
+ skb_reset_mac_header(skb);
+
++ if (local->hw.queues < IEEE80211_NUM_ACS)
++ goto start_xmit;
++
+ /* update QoS header to prioritize control port frames if possible,
+ * priorization also happens for control port frames send over
+ * AF_PACKET
+@@ -5776,6 +5779,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
+
+ rcu_read_unlock();
+
++start_xmit:
+ /* mutex lock is only needed for incrementing the cookie counter */
+ mutex_lock(&local->mtx);
+
+--
+2.35.1
+