--- /dev/null
+From 9d6be54b130a08eb5a4cbc3af1e4a26db9fa155d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Nov 2023 14:41:13 +0100
+Subject: cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily
+
+From: Christoph Niedermaier <cniedermaier@dh-electronics.com>
+
+[ Upstream commit 2e4e0984c7d696cc74cf2fd7e7f62997f0e9ebe6 ]
+
+For a 900MHz i.MX6ULL CPU the 792MHz OPP is disabled. There is no
+convincing reason to disable this OPP. If a CPU can run at 900MHz,
+it should also be able to cope with 792MHz. Looking at the voltage
+level of 792MHz in [1] (page 24, table 10. "Operating Ranges") the
+current defined OPP is above the minimum. So the voltage level
+shouldn't be a problem. However in [2] (page 24, table 10.
+"Operating Ranges"), it is not mentioned that 792MHz OPP isn't
+allowed. Change it to only disable 792MHz OPP for i.MX6ULL types
+below 792 MHz.
+
+[1] https://www.nxp.com/docs/en/data-sheet/IMX6ULLIEC.pdf
+[2] https://www.nxp.com/docs/en/data-sheet/IMX6ULLCEC.pdf
+
+Fixes: 0aa9abd4c212 ("cpufreq: imx6q: check speed grades for i.MX6ULL")
+Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
+Reviewed-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Fabio Estevam <festevam@denx.de>
+[ Viresh: Edited subject ]
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/imx6q-cpufreq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
+index ae834fb9bfbd5..925fc17eaacb2 100644
+--- a/drivers/cpufreq/imx6q-cpufreq.c
++++ b/drivers/cpufreq/imx6q-cpufreq.c
+@@ -327,7 +327,7 @@ static int imx6ul_opp_check_speed_grading(struct device *dev)
+ imx6x_disable_freq_in_opp(dev, 696000000);
+
+ if (of_machine_is_compatible("fsl,imx6ull")) {
+- if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
++ if (val < OCOTP_CFG3_6ULL_SPEED_792MHZ)
+ imx6x_disable_freq_in_opp(dev, 792000000);
+
+ if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
+--
+2.42.0
+
--- /dev/null
+From 25a47f7db20ba653a9365e85d61575c6cd42433f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 May 2023 17:07:11 +0200
+Subject: cpufreq: imx6q: don't warn for disabling a non-existing frequency
+
+From: Christoph Niedermaier <cniedermaier@dh-electronics.com>
+
+[ Upstream commit 11a3b0ac33d95aa84be426e801f800997262a225 ]
+
+It is confusing if a warning is given for disabling a non-existent
+frequency of the operating performance points (OPP). In this case
+the function dev_pm_opp_disable() returns -ENODEV. Check the return
+value and avoid the output of a warning in this case. Avoid code
+duplication by using a separate function.
+
+Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
+[ Viresh : Updated commit subject ]
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Stable-dep-of: 2e4e0984c7d6 ("cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/imx6q-cpufreq.c | 30 ++++++++++++++++--------------
+ 1 file changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
+index ad4ce84931446..ae834fb9bfbd5 100644
+--- a/drivers/cpufreq/imx6q-cpufreq.c
++++ b/drivers/cpufreq/imx6q-cpufreq.c
+@@ -209,6 +209,14 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
+ .suspend = cpufreq_generic_suspend,
+ };
+
++static void imx6x_disable_freq_in_opp(struct device *dev, unsigned long freq)
++{
++ int ret = dev_pm_opp_disable(dev, freq);
++
++ if (ret < 0 && ret != -ENODEV)
++ dev_warn(dev, "failed to disable %ldMHz OPP\n", freq / 1000000);
++}
++
+ #define OCOTP_CFG3 0x440
+ #define OCOTP_CFG3_SPEED_SHIFT 16
+ #define OCOTP_CFG3_SPEED_1P2GHZ 0x3
+@@ -254,17 +262,15 @@ static int imx6q_opp_check_speed_grading(struct device *dev)
+ val &= 0x3;
+
+ if (val < OCOTP_CFG3_SPEED_996MHZ)
+- if (dev_pm_opp_disable(dev, 996000000))
+- dev_warn(dev, "failed to disable 996MHz OPP\n");
++ imx6x_disable_freq_in_opp(dev, 996000000);
+
+ if (of_machine_is_compatible("fsl,imx6q") ||
+ of_machine_is_compatible("fsl,imx6qp")) {
+ if (val != OCOTP_CFG3_SPEED_852MHZ)
+- if (dev_pm_opp_disable(dev, 852000000))
+- dev_warn(dev, "failed to disable 852MHz OPP\n");
++ imx6x_disable_freq_in_opp(dev, 852000000);
++
+ if (val != OCOTP_CFG3_SPEED_1P2GHZ)
+- if (dev_pm_opp_disable(dev, 1200000000))
+- dev_warn(dev, "failed to disable 1.2GHz OPP\n");
++ imx6x_disable_freq_in_opp(dev, 1200000000);
+ }
+
+ return 0;
+@@ -316,20 +322,16 @@ static int imx6ul_opp_check_speed_grading(struct device *dev)
+ val >>= OCOTP_CFG3_SPEED_SHIFT;
+ val &= 0x3;
+
+- if (of_machine_is_compatible("fsl,imx6ul")) {
++ if (of_machine_is_compatible("fsl,imx6ul"))
+ if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
+- if (dev_pm_opp_disable(dev, 696000000))
+- dev_warn(dev, "failed to disable 696MHz OPP\n");
+- }
++ imx6x_disable_freq_in_opp(dev, 696000000);
+
+ if (of_machine_is_compatible("fsl,imx6ull")) {
+ if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
+- if (dev_pm_opp_disable(dev, 792000000))
+- dev_warn(dev, "failed to disable 792MHz OPP\n");
++ imx6x_disable_freq_in_opp(dev, 792000000);
+
+ if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
+- if (dev_pm_opp_disable(dev, 900000000))
+- dev_warn(dev, "failed to disable 900MHz OPP\n");
++ imx6x_disable_freq_in_opp(dev, 900000000);
+ }
+
+ return ret;
+--
+2.42.0
+
--- /dev/null
+From 8848229f2cdb73218198561a653913ae250a6dc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Nov 2023 12:28:04 +0200
+Subject: dpaa2-eth: increase the needed headroom to account for alignment
+
+From: Ioana Ciornei <ioana.ciornei@nxp.com>
+
+[ Upstream commit f422abe3f23d483cf01f386819f26fb3fe0dbb2b ]
+
+Increase the needed headroom to account for a 64 byte alignment
+restriction which, with this patch, we make mandatory on the Tx path.
+The case in which the amount of headroom needed is not available is
+already handled by the driver which instead sends a S/G frame with the
+first buffer only holding the SW and HW annotation areas.
+
+Without this patch, we can empirically see data corruption happening
+between Tx and Tx confirmation which sometimes leads to the SW
+annotation area being overwritten.
+
+Since this is an old IP where the hardware team cannot help to
+understand the underlying behavior, we make the Tx alignment mandatory
+for all frames to avoid the crash on Tx conf. Also, remove the comment
+that suggested that this is just an optimization.
+
+This patch also sets the needed_headroom net device field to the usual
+value that the driver would need on the Tx path:
+ - 64 bytes for the software annotation area
+ - 64 bytes to account for a 64 byte aligned buffer address
+
+Fixes: 6e2387e8f19e ("staging: fsl-dpaa2/eth: Add Freescale DPAA2 Ethernet driver")
+Closes: https://lore.kernel.org/netdev/aa784d0c-85eb-4e5d-968b-c8f74fa86be6@gin.de/
+Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 8 ++++----
+ drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 2 +-
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+index 6383d9805dac9..b58162ce81d87 100644
+--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+@@ -1043,14 +1043,12 @@ static int dpaa2_eth_build_single_fd(struct dpaa2_eth_priv *priv,
+ dma_addr_t addr;
+
+ buffer_start = skb->data - dpaa2_eth_needed_headroom(skb);
+-
+- /* If there's enough room to align the FD address, do it.
+- * It will help hardware optimize accesses.
+- */
+ aligned_start = PTR_ALIGN(buffer_start - DPAA2_ETH_TX_BUF_ALIGN,
+ DPAA2_ETH_TX_BUF_ALIGN);
+ if (aligned_start >= skb->head)
+ buffer_start = aligned_start;
++ else
++ return -ENOMEM;
+
+ /* Store a backpointer to the skb at the beginning of the buffer
+ * (in the private data area) such that we can release it
+@@ -4738,6 +4736,8 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
+ if (err)
+ goto err_dl_port_add;
+
++ net_dev->needed_headroom = DPAA2_ETH_SWA_SIZE + DPAA2_ETH_TX_BUF_ALIGN;
++
+ err = register_netdev(net_dev);
+ if (err < 0) {
+ dev_err(dev, "register_netdev() failed\n");
+diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
+index 447718483ef47..e703846adc9f0 100644
+--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
+@@ -702,7 +702,7 @@ static inline bool dpaa2_eth_rx_pause_enabled(u64 link_options)
+
+ static inline unsigned int dpaa2_eth_needed_headroom(struct sk_buff *skb)
+ {
+- unsigned int headroom = DPAA2_ETH_SWA_SIZE;
++ unsigned int headroom = DPAA2_ETH_SWA_SIZE + DPAA2_ETH_TX_BUF_ALIGN;
+
+ /* If we don't have an skb (e.g. XDP buffer), we only need space for
+ * the software annotation area
+--
+2.42.0
+
--- /dev/null
+From e391f20fb86dfb9ca968ae291feab32953b046c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Nov 2023 09:21:28 +0100
+Subject: drivers: perf: Check find_first_bit() return value
+
+From: Alexandre Ghiti <alexghiti@rivosinc.com>
+
+[ Upstream commit c6e316ac05532febb0c966fa9b55f5258ed037be ]
+
+We must check the return value of find_first_bit() before using the
+return value as an index array since it happens to overflow the array
+and then panic:
+
+[ 107.318430] Kernel BUG [#1]
+[ 107.319434] CPU: 3 PID: 1238 Comm: kill Tainted: G E 6.6.0-rc6ubuntu-defconfig #2
+[ 107.319465] Hardware name: riscv-virtio,qemu (DT)
+[ 107.319551] epc : pmu_sbi_ovf_handler+0x3a4/0x3ae
+[ 107.319840] ra : pmu_sbi_ovf_handler+0x52/0x3ae
+[ 107.319868] epc : ffffffff80a0a77c ra : ffffffff80a0a42a sp : ffffaf83fecda350
+[ 107.319884] gp : ffffffff823961a8 tp : ffffaf8083db1dc0 t0 : ffffaf83fecda480
+[ 107.319899] t1 : ffffffff80cafe62 t2 : 000000000000ff00 s0 : ffffaf83fecda520
+[ 107.319921] s1 : ffffaf83fecda380 a0 : 00000018fca29df0 a1 : ffffffffffffffff
+[ 107.319936] a2 : 0000000001073734 a3 : 0000000000000004 a4 : 0000000000000000
+[ 107.319951] a5 : 0000000000000040 a6 : 000000001d1c8774 a7 : 0000000000504d55
+[ 107.319965] s2 : ffffffff82451f10 s3 : ffffffff82724e70 s4 : 000000000000003f
+[ 107.319980] s5 : 0000000000000011 s6 : ffffaf8083db27c0 s7 : 0000000000000000
+[ 107.319995] s8 : 0000000000000001 s9 : 00007fffb45d6558 s10: 00007fffb45d81a0
+[ 107.320009] s11: ffffaf7ffff60000 t3 : 0000000000000004 t4 : 0000000000000000
+[ 107.320023] t5 : ffffaf7f80000000 t6 : ffffaf8000000000
+[ 107.320037] status: 0000000200000100 badaddr: 0000000000000000 cause: 0000000000000003
+[ 107.320081] [<ffffffff80a0a77c>] pmu_sbi_ovf_handler+0x3a4/0x3ae
+[ 107.320112] [<ffffffff800b42d0>] handle_percpu_devid_irq+0x9e/0x1a0
+[ 107.320131] [<ffffffff800ad92c>] generic_handle_domain_irq+0x28/0x36
+[ 107.320148] [<ffffffff8065f9f8>] riscv_intc_irq+0x36/0x4e
+[ 107.320166] [<ffffffff80caf4a0>] handle_riscv_irq+0x54/0x86
+[ 107.320189] [<ffffffff80cb0036>] do_irq+0x64/0x96
+[ 107.320271] Code: 85a6 855e b097 ff7f 80e7 9220 b709 9002 4501 bbd9 (9002) 6097
+[ 107.320585] ---[ end trace 0000000000000000 ]---
+[ 107.320704] Kernel panic - not syncing: Fatal exception in interrupt
+[ 107.320775] SMP: stopping secondary CPUs
+[ 107.321219] Kernel Offset: 0x0 from 0xffffffff80000000
+[ 107.333051] ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---
+
+Fixes: 4905ec2fb7e6 ("RISC-V: Add sscofpmf extension support")
+Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Link: https://lore.kernel.org/r/20231109082128.40777-1-alexghiti@rivosinc.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/riscv_pmu_sbi.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
+index 382fe5ee6100b..e0a84046435b1 100644
+--- a/drivers/perf/riscv_pmu_sbi.c
++++ b/drivers/perf/riscv_pmu_sbi.c
+@@ -578,6 +578,11 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
+
+ /* Firmware counter don't support overflow yet */
+ fidx = find_first_bit(cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS);
++ if (fidx == RISCV_MAX_COUNTERS) {
++ csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num));
++ return IRQ_NONE;
++ }
++
+ event = cpu_hw_evt->events[fidx];
+ if (!event) {
+ csr_clear(CSR_SIP, SIP_LCOFIP);
+--
+2.42.0
+
--- /dev/null
+From 4e8b031b3917aec2fbed2cffadb2def89aa4da3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Sep 2023 16:18:44 -0400
+Subject: drm/amd/display: Guard against invalid RPTR/WPTR being set
+
+From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+
+[ Upstream commit 1ffa8602e39b89469dc703ebab7a7e44c33da0f7 ]
+
+[WHY]
+HW can return invalid values on register read, guard against these being
+set and causing us to access memory out of range and page fault.
+
+[HOW]
+Guard at sync_inbox1 and guard at pushing commands.
+
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Hansen Dsouza <hansen.dsouza@amd.com>
+Acked-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+index 6b8bd556c872f..e951fd837aa27 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+@@ -675,9 +675,16 @@ enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub)
+ return DMUB_STATUS_INVALID;
+
+ if (dmub->hw_funcs.get_inbox1_rptr && dmub->hw_funcs.get_inbox1_wptr) {
+- dmub->inbox1_rb.rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);
+- dmub->inbox1_rb.wrpt = dmub->hw_funcs.get_inbox1_wptr(dmub);
+- dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt;
++ uint32_t rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);
++ uint32_t wptr = dmub->hw_funcs.get_inbox1_wptr(dmub);
++
++ if (rptr > dmub->inbox1_rb.capacity || wptr > dmub->inbox1_rb.capacity) {
++ return DMUB_STATUS_HW_FAILURE;
++ } else {
++ dmub->inbox1_rb.rptr = rptr;
++ dmub->inbox1_rb.wrpt = wptr;
++ dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt;
++ }
+ }
+
+ return DMUB_STATUS_OK;
+@@ -711,6 +718,11 @@ enum dmub_status dmub_srv_cmd_queue(struct dmub_srv *dmub,
+ if (!dmub->hw_init)
+ return DMUB_STATUS_INVALID;
+
++ if (dmub->inbox1_rb.rptr > dmub->inbox1_rb.capacity ||
++ dmub->inbox1_rb.wrpt > dmub->inbox1_rb.capacity) {
++ return DMUB_STATUS_HW_FAILURE;
++ }
++
+ if (dmub_rb_push_front(&dmub->inbox1_rb, cmd))
+ return DMUB_STATUS_OK;
+
+--
+2.42.0
+
--- /dev/null
+From 97cbc3e29b52ecd1974c0acca4dffda14364c9f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Apr 2023 23:23:37 +0800
+Subject: drm/amd/display: Restore rptr/wptr for DMCUB as workaround
+
+From: JinZe.Xu <JinZe.Xu@amd.com>
+
+[ Upstream commit 8f3589bb6fcea397775398cba4fbcc46829a60ed ]
+
+[Why]
+States may be desync after resume.
+
+[How]
+Sync sw state with hw state.
+
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
+Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: JinZe.Xu <JinZe.Xu@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 1ffa8602e39b ("drm/amd/display: Guard against invalid RPTR/WPTR being set")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 14 ++++++++++++++
+ .../gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 5 +++++
+ .../gpu/drm/amd/display/dmub/src/dmub_dcn20.h | 2 ++
+ .../gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 5 +++++
+ .../gpu/drm/amd/display/dmub/src/dmub_dcn31.h | 2 ++
+ .../gpu/drm/amd/display/dmub/src/dmub_dcn32.c | 5 +++++
+ .../gpu/drm/amd/display/dmub/src/dmub_dcn32.h | 2 ++
+ drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 17 +++++++++++++++++
+ 8 files changed, 52 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+index a21fe7b037d1f..aaabaab49809d 100644
+--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
++++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+@@ -332,6 +332,8 @@ struct dmub_srv_hw_funcs {
+ void (*setup_mailbox)(struct dmub_srv *dmub,
+ const struct dmub_region *inbox1);
+
++ uint32_t (*get_inbox1_wptr)(struct dmub_srv *dmub);
++
+ uint32_t (*get_inbox1_rptr)(struct dmub_srv *dmub);
+
+ void (*set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset);
+@@ -590,6 +592,18 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
+ */
+ enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub);
+
++/**
++ * dmub_srv_sync_inbox1() - sync sw state with hw state
++ * @dmub: the dmub service
++ *
++ * Sync sw state with hw state when resume from S0i3
++ *
++ * Return:
++ * DMUB_STATUS_OK - success
++ * DMUB_STATUS_INVALID - unspecified error
++ */
++enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub);
++
+ /**
+ * dmub_srv_cmd_queue() - queues a command to the DMUB
+ * @dmub: the dmub service
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+index a6540e27044d2..98dad0d47e72c 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+@@ -282,6 +282,11 @@ void dmub_dcn20_setup_mailbox(struct dmub_srv *dmub,
+ REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
+ }
+
++uint32_t dmub_dcn20_get_inbox1_wptr(struct dmub_srv *dmub)
++{
++ return REG_READ(DMCUB_INBOX1_WPTR);
++}
++
+ uint32_t dmub_dcn20_get_inbox1_rptr(struct dmub_srv *dmub)
+ {
+ return REG_READ(DMCUB_INBOX1_RPTR);
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
+index c2e5831ac52cc..1df128e57ed3b 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
+@@ -202,6 +202,8 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
+ void dmub_dcn20_setup_mailbox(struct dmub_srv *dmub,
+ const struct dmub_region *inbox1);
+
++uint32_t dmub_dcn20_get_inbox1_wptr(struct dmub_srv *dmub);
++
+ uint32_t dmub_dcn20_get_inbox1_rptr(struct dmub_srv *dmub);
+
+ void dmub_dcn20_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+index 89d24fb7024e2..5e952541e72d5 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+@@ -242,6 +242,11 @@ void dmub_dcn31_setup_mailbox(struct dmub_srv *dmub,
+ REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
+ }
+
++uint32_t dmub_dcn31_get_inbox1_wptr(struct dmub_srv *dmub)
++{
++ return REG_READ(DMCUB_INBOX1_WPTR);
++}
++
+ uint32_t dmub_dcn31_get_inbox1_rptr(struct dmub_srv *dmub)
+ {
+ return REG_READ(DMCUB_INBOX1_RPTR);
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
+index eb62410941473..89c5a948b67d5 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
+@@ -204,6 +204,8 @@ void dmub_dcn31_setup_windows(struct dmub_srv *dmub,
+ void dmub_dcn31_setup_mailbox(struct dmub_srv *dmub,
+ const struct dmub_region *inbox1);
+
++uint32_t dmub_dcn31_get_inbox1_wptr(struct dmub_srv *dmub);
++
+ uint32_t dmub_dcn31_get_inbox1_rptr(struct dmub_srv *dmub);
+
+ void dmub_dcn31_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
+index 9c20516be066c..d2f03f797279f 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
+@@ -266,6 +266,11 @@ void dmub_dcn32_setup_mailbox(struct dmub_srv *dmub,
+ REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
+ }
+
++uint32_t dmub_dcn32_get_inbox1_wptr(struct dmub_srv *dmub)
++{
++ return REG_READ(DMCUB_INBOX1_WPTR);
++}
++
+ uint32_t dmub_dcn32_get_inbox1_rptr(struct dmub_srv *dmub)
+ {
+ return REG_READ(DMCUB_INBOX1_RPTR);
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h
+index 7d1a6eb4d6657..f15336b6e22be 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h
+@@ -206,6 +206,8 @@ void dmub_dcn32_setup_windows(struct dmub_srv *dmub,
+ void dmub_dcn32_setup_mailbox(struct dmub_srv *dmub,
+ const struct dmub_region *inbox1);
+
++uint32_t dmub_dcn32_get_inbox1_wptr(struct dmub_srv *dmub);
++
+ uint32_t dmub_dcn32_get_inbox1_rptr(struct dmub_srv *dmub);
+
+ void dmub_dcn32_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
+diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+index f58803de37cb0..6b8bd556c872f 100644
+--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+@@ -167,6 +167,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
+ funcs->backdoor_load = dmub_dcn20_backdoor_load;
+ funcs->setup_windows = dmub_dcn20_setup_windows;
+ funcs->setup_mailbox = dmub_dcn20_setup_mailbox;
++ funcs->get_inbox1_wptr = dmub_dcn20_get_inbox1_wptr;
+ funcs->get_inbox1_rptr = dmub_dcn20_get_inbox1_rptr;
+ funcs->set_inbox1_wptr = dmub_dcn20_set_inbox1_wptr;
+ funcs->is_supported = dmub_dcn20_is_supported;
+@@ -243,6 +244,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
+ funcs->backdoor_load = dmub_dcn31_backdoor_load;
+ funcs->setup_windows = dmub_dcn31_setup_windows;
+ funcs->setup_mailbox = dmub_dcn31_setup_mailbox;
++ funcs->get_inbox1_wptr = dmub_dcn31_get_inbox1_wptr;
+ funcs->get_inbox1_rptr = dmub_dcn31_get_inbox1_rptr;
+ funcs->set_inbox1_wptr = dmub_dcn31_set_inbox1_wptr;
+ funcs->setup_out_mailbox = dmub_dcn31_setup_out_mailbox;
+@@ -281,6 +283,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
+ funcs->backdoor_load_zfb_mode = dmub_dcn32_backdoor_load_zfb_mode;
+ funcs->setup_windows = dmub_dcn32_setup_windows;
+ funcs->setup_mailbox = dmub_dcn32_setup_mailbox;
++ funcs->get_inbox1_wptr = dmub_dcn32_get_inbox1_wptr;
+ funcs->get_inbox1_rptr = dmub_dcn32_get_inbox1_rptr;
+ funcs->set_inbox1_wptr = dmub_dcn32_set_inbox1_wptr;
+ funcs->setup_out_mailbox = dmub_dcn32_setup_out_mailbox;
+@@ -666,6 +669,20 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
+ return DMUB_STATUS_OK;
+ }
+
++enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub)
++{
++ if (!dmub->sw_init)
++ return DMUB_STATUS_INVALID;
++
++ if (dmub->hw_funcs.get_inbox1_rptr && dmub->hw_funcs.get_inbox1_wptr) {
++ dmub->inbox1_rb.rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);
++ dmub->inbox1_rb.wrpt = dmub->hw_funcs.get_inbox1_wptr(dmub);
++ dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt;
++ }
++
++ return DMUB_STATUS_OK;
++}
++
+ enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub)
+ {
+ if (!dmub->sw_init)
+--
+2.42.0
+
--- /dev/null
+From 9d85a8d99e74b0e9d9a943240c35019c4fc7903b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Nov 2023 15:33:22 +0800
+Subject: drm/amd/pm: fix a memleak in aldebaran_tables_init
+
+From: Dinghao Liu <dinghao.liu@zju.edu.cn>
+
+[ Upstream commit 7a88f23e768491bae653b444a96091d2aaeb0818 ]
+
+When kzalloc() for smu_table->ecc_table fails, we should free
+the previously allocated resources to prevent memleak.
+
+Fixes: edd794208555 ("drm/amd/pm: add message smu to get ecc_table v2")
+Signed-off-by: Dinghao Liu <dinghao.liu@zju.edu.cn>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+index d30ec3005ea19..cd8b0ab0112ae 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+@@ -258,8 +258,11 @@ static int aldebaran_tables_init(struct smu_context *smu)
+ }
+
+ smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL);
+- if (!smu_table->ecc_table)
++ if (!smu_table->ecc_table) {
++ kfree(smu_table->metrics_table);
++ kfree(smu_table->gpu_metrics_table);
+ return -ENOMEM;
++ }
+
+ return 0;
+ }
+--
+2.42.0
+
--- /dev/null
+From de261af876a201343f3a6185a57aeb5321ba79d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Nov 2023 07:43:15 +0200
+Subject: drm/i915: Call intel_pre_plane_updates() also for pipes getting
+ enabled
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+[ Upstream commit d21a3962d3042e6f56ad324cf18bdd64a1e6ecfa ]
+
+We used to call intel_pre_plane_updates() for any pipe going through
+a modeset whether the pipe was previously enabled or not. This in
+fact needed to apply all the necessary clock gating workarounds/etc.
+Restore the correct behaviour.
+
+Fixes: 39919997322f ("drm/i915: Disable all planes before modesetting any pipes")
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231121054324.9988-3-ville.syrjala@linux.intel.com
+(cherry picked from commit e0d5ce11ed0a21bb2bf328ad82fd261783c7ad88)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_display.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
+index 96e679a176e94..1977f4c6fd889 100644
+--- a/drivers/gpu/drm/i915/display/intel_display.c
++++ b/drivers/gpu/drm/i915/display/intel_display.c
+@@ -7188,10 +7188,11 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
+ if (!intel_crtc_needs_modeset(new_crtc_state))
+ continue;
+
++ intel_pre_plane_update(state, crtc);
++
+ if (!old_crtc_state->hw.active)
+ continue;
+
+- intel_pre_plane_update(state, crtc);
+ intel_crtc_disable_planes(state, crtc);
+ }
+
+--
+2.42.0
+
--- /dev/null
+From df847c0738e51ee9c5fcfbdd5e4041e25d691ad4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Oct 2023 13:36:48 +0200
+Subject: fbdev: stifb: Make the STI next font pointer a 32-bit signed offset
+
+From: Helge Deller <deller@gmx.de>
+
+[ Upstream commit 8a32aa17c1cd48df1ddaa78e45abcb8c7a2220d6 ]
+
+The pointer to the next STI font is actually a signed 32-bit
+offset. With this change the 64-bit kernel will correctly subract
+the (signed 32-bit) offset instead of adding a (unsigned 32-bit)
+offset. It has no effect on 32-bit kernels.
+
+This fixes the stifb driver with a 64-bit kernel on qemu.
+
+Signed-off-by: Helge Deller <deller@gmx.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/sticore.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/fbdev/sticore.h b/drivers/video/fbdev/sticore.h
+index 0ebdd28a0b813..d83ab3ded5f3d 100644
+--- a/drivers/video/fbdev/sticore.h
++++ b/drivers/video/fbdev/sticore.h
+@@ -231,7 +231,7 @@ struct sti_rom_font {
+ u8 height;
+ u8 font_type; /* language type */
+ u8 bytes_per_char;
+- u32 next_font;
++ s32 next_font; /* note: signed int */
+ u8 underline_height;
+ u8 underline_pos;
+ u8 res008[2];
+--
+2.42.0
+
--- /dev/null
+From 2786ffccc72291601ee7a2c91fe01f1a8aa68a2a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Nov 2022 08:29:44 +0800
+Subject: iommu/vt-d: Add device_block_translation() helper
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit c7be17c2903d4acbf9aa372bfb6e2a418387fce0 ]
+
+If domain attaching to device fails, the IOMMU driver should bring the
+device to blocking DMA state. The upper layer is expected to recover it
+by attaching a new domain. Use device_block_translation() in the error
+path of dev_attach to make the behavior specific.
+
+The difference between device_block_translation() and the previous
+dmar_remove_one_dev_info() is that, in the scalable mode, it is the
+RID2PASID entry instead of context entry being cleared. As a result,
+enabling PCI capabilities is moved up.
+
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20221118132451.114406-3-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: da37dddcf4ca ("iommu/vt-d: Disable PCI ATS in legacy passthrough mode")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/iommu.c | 44 ++++++++++++++++++++++++++++++++-----
+ 1 file changed, 38 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 3dbf86c61f073..de76272d0fb02 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -277,7 +277,7 @@ static LIST_HEAD(dmar_satc_units);
+ #define for_each_rmrr_units(rmrr) \
+ list_for_each_entry(rmrr, &dmar_rmrr_units, list)
+
+-static void dmar_remove_one_dev_info(struct device *dev);
++static void device_block_translation(struct device *dev);
+
+ int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
+ int intel_iommu_sm = IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON);
+@@ -1418,7 +1418,7 @@ static void iommu_enable_pci_caps(struct device_domain_info *info)
+ {
+ struct pci_dev *pdev;
+
+- if (!info || !dev_is_pci(info->dev))
++ if (!dev_is_pci(info->dev))
+ return;
+
+ pdev = to_pci_dev(info->dev);
+@@ -2064,7 +2064,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
+ } else {
+ iommu_flush_write_buffer(iommu);
+ }
+- iommu_enable_pci_caps(info);
+
+ ret = 0;
+
+@@ -2506,7 +2505,7 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
+ dev, PASID_RID2PASID);
+ if (ret) {
+ dev_err(dev, "Setup RID2PASID failed\n");
+- dmar_remove_one_dev_info(dev);
++ device_block_translation(dev);
+ return ret;
+ }
+ }
+@@ -2514,10 +2513,12 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
+ ret = domain_context_mapping(domain, dev);
+ if (ret) {
+ dev_err(dev, "Domain context map failed\n");
+- dmar_remove_one_dev_info(dev);
++ device_block_translation(dev);
+ return ret;
+ }
+
++ iommu_enable_pci_caps(info);
++
+ return 0;
+ }
+
+@@ -4115,6 +4116,37 @@ static void dmar_remove_one_dev_info(struct device *dev)
+ info->domain = NULL;
+ }
+
++/*
++ * Clear the page table pointer in context or pasid table entries so that
++ * all DMA requests without PASID from the device are blocked. If the page
++ * table has been set, clean up the data structures.
++ */
++static void device_block_translation(struct device *dev)
++{
++ struct device_domain_info *info = dev_iommu_priv_get(dev);
++ struct intel_iommu *iommu = info->iommu;
++ unsigned long flags;
++
++ iommu_disable_dev_iotlb(info);
++ if (!dev_is_real_dma_subdevice(dev)) {
++ if (sm_supported(iommu))
++ intel_pasid_tear_down_entry(iommu, dev,
++ PASID_RID2PASID, false);
++ else
++ domain_context_clear(info);
++ }
++
++ if (!info->domain)
++ return;
++
++ spin_lock_irqsave(&info->domain->lock, flags);
++ list_del(&info->link);
++ spin_unlock_irqrestore(&info->domain->lock, flags);
++
++ domain_detach_iommu(info->domain, iommu);
++ info->domain = NULL;
++}
++
+ static int md_domain_init(struct dmar_domain *domain, int guest_width)
+ {
+ int adjust_width;
+@@ -4238,7 +4270,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+
+ if (info->domain)
+- dmar_remove_one_dev_info(dev);
++ device_block_translation(dev);
+ }
+
+ ret = prepare_domain_attach_device(domain, dev);
+--
+2.42.0
+
--- /dev/null
+From ef2d0171134fcab4370bc5b399011fef7ded0644 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Nov 2022 08:29:43 +0800
+Subject: iommu/vt-d: Allocate pasid table in device probe path
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit ec62b4424174f41bdcedd08d12d7bed80088453d ]
+
+Whether or not a domain is attached to the device, the pasid table should
+always be valid as long as it has been probed. This moves the pasid table
+allocation from the domain attaching device path to device probe path and
+frees it in the device release path.
+
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20221118132451.114406-2-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: da37dddcf4ca ("iommu/vt-d: Disable PCI ATS in legacy passthrough mode")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/iommu.c | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index bd34fcc5a5274..3dbf86c61f073 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -2494,13 +2494,6 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
+
+ /* PASID table is mandatory for a PCI device in scalable mode. */
+ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
+- ret = intel_pasid_alloc_table(dev);
+- if (ret) {
+- dev_err(dev, "PASID table allocation failed\n");
+- dmar_remove_one_dev_info(dev);
+- return ret;
+- }
+-
+ /* Setup the PASID entry for requests without PASID: */
+ if (hw_pass_through && domain_type_is_si(domain))
+ ret = intel_pasid_setup_pass_through(iommu, domain,
+@@ -4112,7 +4105,6 @@ static void dmar_remove_one_dev_info(struct device *dev)
+
+ iommu_disable_dev_iotlb(info);
+ domain_context_clear(info);
+- intel_pasid_free_table(info->dev);
+ }
+
+ spin_lock_irqsave(&domain->lock, flags);
+@@ -4477,6 +4469,7 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev)
+ struct device_domain_info *info;
+ struct intel_iommu *iommu;
+ u8 bus, devfn;
++ int ret;
+
+ iommu = device_to_iommu(dev, &bus, &devfn);
+ if (!iommu || !iommu->iommu.ops)
+@@ -4521,6 +4514,16 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev)
+
+ dev_iommu_priv_set(dev, info);
+
++ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
++ ret = intel_pasid_alloc_table(dev);
++ if (ret) {
++ dev_err(dev, "PASID table allocation failed\n");
++ dev_iommu_priv_set(dev, NULL);
++ kfree(info);
++ return ERR_PTR(ret);
++ }
++ }
++
+ return &iommu->iommu;
+ }
+
+@@ -4529,6 +4532,7 @@ static void intel_iommu_release_device(struct device *dev)
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+
+ dmar_remove_one_dev_info(dev);
++ intel_pasid_free_table(dev);
+ dev_iommu_priv_set(dev, NULL);
+ kfree(info);
+ set_dma_ops(dev, NULL);
+--
+2.42.0
+
--- /dev/null
+From 8b16ac5945c4590f0f92c36c284317a9a3432ece Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Nov 2023 11:26:04 +0800
+Subject: iommu/vt-d: Disable PCI ATS in legacy passthrough mode
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit da37dddcf4caf015c400a930301d2ee27a7a15fb ]
+
+When IOMMU hardware operates in legacy mode, the TT field of the context
+entry determines the translation type, with three supported types (Section
+9.3 Context Entry):
+
+- DMA translation without device TLB support
+- DMA translation with device TLB support
+- Passthrough mode with translated and translation requests blocked
+
+Device TLB support is absent when hardware is configured in passthrough
+mode.
+
+Disable the PCI ATS feature when IOMMU is configured for passthrough
+translation type in legacy (non-scalable) mode.
+
+Fixes: 0faa19a1515f ("iommu/vt-d: Decouple PASID & PRI enabling from SVA")
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20231114011036.70142-3-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/iommu.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index de76272d0fb02..807abf4707be7 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -2517,7 +2517,8 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
+ return ret;
+ }
+
+- iommu_enable_pci_caps(info);
++ if (sm_supported(info->iommu) || !domain_type_is_si(info->domain))
++ iommu_enable_pci_caps(info);
+
+ return 0;
+ }
+--
+2.42.0
+
--- /dev/null
+From 7be071bce67c9a014d231c46c5e22b179e46c334 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Nov 2023 11:26:05 +0800
+Subject: iommu/vt-d: Make context clearing consistent with context mapping
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit 9a16ab9d640274b20813d2d17475e18d3e99d834 ]
+
+In the iommu probe_device path, domain_context_mapping() allows setting
+up the context entry for a non-PCI device. However, in the iommu
+release_device path, domain_context_clear() only clears context entries
+for PCI devices.
+
+Make domain_context_clear() behave consistently with
+domain_context_mapping() by clearing context entries for both PCI and
+non-PCI devices.
+
+Fixes: 579305f75d34 ("iommu/vt-d: Update to use PCI DMA aliases")
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20231114011036.70142-4-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/iommu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 807abf4707be7..e111b35a7aff2 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -4086,8 +4086,8 @@ static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *op
+ */
+ static void domain_context_clear(struct device_domain_info *info)
+ {
+- if (!info->iommu || !info->dev || !dev_is_pci(info->dev))
+- return;
++ if (!dev_is_pci(info->dev))
++ domain_context_clear_one(info, info->bus, info->devfn);
+
+ pci_for_each_dma_alias(to_pci_dev(info->dev),
+ &domain_context_clear_one_cb, info);
+--
+2.42.0
+
--- /dev/null
+From 2a1e4be64f281854850d6a48fb04a565ca5a7687 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Nov 2023 11:26:03 +0800
+Subject: iommu/vt-d: Omit devTLB invalidation requests when TES=0
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit 0f5432a9b839847dcfe9fa369d72e3d646102ddf ]
+
+The latest VT-d spec indicates that when remapping hardware is disabled
+(TES=0 in Global Status Register), upstream ATS Invalidation Completion
+requests are treated as UR (Unsupported Request).
+
+Consequently, the spec recommends in section 4.3 Handling of Device-TLB
+Invalidations that software refrain from submitting any Device-TLB
+invalidation requests when address remapping hardware is disabled.
+
+Verify address remapping hardware is enabled prior to submitting Device-
+TLB invalidation requests.
+
+Fixes: 792fb43ce2c9 ("iommu/vt-d: Enable Intel IOMMU scalable mode by default")
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20231114011036.70142-2-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/dmar.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
+index f800989ea0462..418af1db0192d 100644
+--- a/drivers/iommu/intel/dmar.c
++++ b/drivers/iommu/intel/dmar.c
+@@ -1495,6 +1495,15 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 pfsid,
+ {
+ struct qi_desc desc;
+
++ /*
++ * VT-d spec, section 4.3:
++ *
++ * Software is recommended to not submit any Device-TLB invalidation
++ * requests while address remapping hardware is disabled.
++ */
++ if (!(iommu->gcmd & DMA_GCMD_TE))
++ return;
++
+ if (mask) {
+ addr |= (1ULL << (VTD_PAGE_SHIFT + mask - 1)) - 1;
+ desc.qw1 = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
+@@ -1560,6 +1569,15 @@ void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
+ unsigned long mask = 1UL << (VTD_PAGE_SHIFT + size_order - 1);
+ struct qi_desc desc = {.qw1 = 0, .qw2 = 0, .qw3 = 0};
+
++ /*
++ * VT-d spec, section 4.3:
++ *
++ * Software is recommended to not submit any Device-TLB invalidation
++ * requests while address remapping hardware is disabled.
++ */
++ if (!(iommu->gcmd & DMA_GCMD_TE))
++ return;
++
+ desc.qw0 = QI_DEV_EIOTLB_PASID(pasid) | QI_DEV_EIOTLB_SID(sid) |
+ QI_DEV_EIOTLB_QDEP(qdep) | QI_DEIOTLB_TYPE |
+ QI_DEV_IOTLB_PFSID(pfsid);
+--
+2.42.0
+
--- /dev/null
+From 507ea1ce1d3ecf191ee4a1fb6c1f0c25ab91db59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Nov 2023 15:13:14 +0800
+Subject: ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet
+
+From: Zhengchao Shao <shaozhengchao@huawei.com>
+
+[ Upstream commit e2b706c691905fe78468c361aaabc719d0a496f1 ]
+
+When I perform the following test operations:
+1.ip link add br0 type bridge
+2.brctl addif br0 eth0
+3.ip addr add 239.0.0.1/32 dev eth0
+4.ip addr add 239.0.0.1/32 dev br0
+5.ip addr add 224.0.0.1/32 dev br0
+6.while ((1))
+ do
+ ifconfig br0 up
+ ifconfig br0 down
+ done
+7.send IGMPv2 query packets to port eth0 continuously. For example,
+./mausezahn ethX -c 0 "01 00 5e 00 00 01 00 72 19 88 aa 02 08 00 45 00 00
+1c 00 01 00 00 01 02 0e 7f c0 a8 0a b7 e0 00 00 01 11 64 ee 9b 00 00 00 00"
+
+The preceding tests may trigger the refcnt uaf issue of the mc list. The
+stack is as follows:
+ refcount_t: addition on 0; use-after-free.
+ WARNING: CPU: 21 PID: 144 at lib/refcount.c:25 refcount_warn_saturate (lib/refcount.c:25)
+ CPU: 21 PID: 144 Comm: ksoftirqd/21 Kdump: loaded Not tainted 6.7.0-rc1-next-20231117-dirty #80
+ Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
+ RIP: 0010:refcount_warn_saturate (lib/refcount.c:25)
+ RSP: 0018:ffffb68f00657910 EFLAGS: 00010286
+ RAX: 0000000000000000 RBX: ffff8a00c3bf96c0 RCX: ffff8a07b6160908
+ RDX: 00000000ffffffd8 RSI: 0000000000000027 RDI: ffff8a07b6160900
+ RBP: ffff8a00cba36862 R08: 0000000000000000 R09: 00000000ffff7fff
+ R10: ffffb68f006577c0 R11: ffffffffb0fdcdc8 R12: ffff8a00c3bf9680
+ R13: ffff8a00c3bf96f0 R14: 0000000000000000 R15: ffff8a00d8766e00
+ FS: 0000000000000000(0000) GS:ffff8a07b6140000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 000055f10b520b28 CR3: 000000039741a000 CR4: 00000000000006f0
+ Call Trace:
+ <TASK>
+ igmp_heard_query (net/ipv4/igmp.c:1068)
+ igmp_rcv (net/ipv4/igmp.c:1132)
+ ip_protocol_deliver_rcu (net/ipv4/ip_input.c:205)
+ ip_local_deliver_finish (net/ipv4/ip_input.c:234)
+ __netif_receive_skb_one_core (net/core/dev.c:5529)
+ netif_receive_skb_internal (net/core/dev.c:5729)
+ netif_receive_skb (net/core/dev.c:5788)
+ br_handle_frame_finish (net/bridge/br_input.c:216)
+ nf_hook_bridge_pre (net/bridge/br_input.c:294)
+ __netif_receive_skb_core (net/core/dev.c:5423)
+ __netif_receive_skb_list_core (net/core/dev.c:5606)
+ __netif_receive_skb_list (net/core/dev.c:5674)
+ netif_receive_skb_list_internal (net/core/dev.c:5764)
+ napi_gro_receive (net/core/gro.c:609)
+ e1000_clean_rx_irq (drivers/net/ethernet/intel/e1000/e1000_main.c:4467)
+ e1000_clean (drivers/net/ethernet/intel/e1000/e1000_main.c:3805)
+ __napi_poll (net/core/dev.c:6533)
+ net_rx_action (net/core/dev.c:6735)
+ __do_softirq (kernel/softirq.c:554)
+ run_ksoftirqd (kernel/softirq.c:913)
+ smpboot_thread_fn (kernel/smpboot.c:164)
+ kthread (kernel/kthread.c:388)
+ ret_from_fork (arch/x86/kernel/process.c:153)
+ ret_from_fork_asm (arch/x86/entry/entry_64.S:250)
+ </TASK>
+
+The root causes are as follows:
+Thread A Thread B
+... netif_receive_skb
+br_dev_stop ...
+ br_multicast_leave_snoopers ...
+ __ip_mc_dec_group ...
+ __igmp_group_dropped igmp_rcv
+ igmp_stop_timer igmp_heard_query //ref = 1
+ ip_ma_put igmp_mod_timer
+ refcount_dec_and_test igmp_start_timer //ref = 0
+ ... refcount_inc //ref increases from 0
+When the device receives an IGMPv2 Query message, it starts the timer
+immediately, regardless of whether the device is running. If the device is
+down and has left the multicast group, it will cause the mc list refcount
+uaf issue.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Zhengchao Shao <shaozhengchao@huawei.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Hangbin Liu <liuhangbin@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/igmp.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
+index cbc4816ed7d83..ac53ef7eec915 100644
+--- a/net/ipv4/igmp.c
++++ b/net/ipv4/igmp.c
+@@ -216,8 +216,10 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay)
+ int tv = prandom_u32_max(max_delay);
+
+ im->tm_running = 1;
+- if (!mod_timer(&im->timer, jiffies+tv+2))
+- refcount_inc(&im->refcnt);
++ if (refcount_inc_not_zero(&im->refcnt)) {
++ if (mod_timer(&im->timer, jiffies + tv + 2))
++ ip_ma_put(im);
++ }
+ }
+
+ static void igmp_gq_start_timer(struct in_device *in_dev)
+--
+2.42.0
+
--- /dev/null
+From 165753f3821befe8c41a5ef6e28ec5477224625b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 16:55:45 -0700
+Subject: KVM: x86: Fix lapic timer interrupt lost after loading a snapshot.
+
+From: Haitao Shan <hshan@google.com>
+
+[ Upstream commit 9cfec6d097c607e36199cf0cfbb8cf5acbd8e9b2 ]
+
+When running android emulator (which is based on QEMU 2.12) on
+certain Intel hosts with kernel version 6.3-rc1 or above, guest
+will freeze after loading a snapshot. This is almost 100%
+reproducible. By default, the android emulator will use snapshot
+to speed up the next launching of the same android guest. So
+this breaks the android emulator badly.
+
+I tested QEMU 8.0.4 from Debian 12 with an Ubuntu 22.04 guest by
+running command "loadvm" after "savevm". The same issue is
+observed. At the same time, none of our AMD platforms is impacted.
+More experiments show that loading the KVM module with
+"enable_apicv=false" can workaround it.
+
+The issue started to show up after commit 8e6ed96cdd50 ("KVM: x86:
+fire timer when it is migrated and expired, and in oneshot mode").
+However, as is pointed out by Sean Christopherson, it is introduced
+by commit 967235d32032 ("KVM: vmx: clear pending interrupts on
+KVM_SET_LAPIC"). commit 8e6ed96cdd50 ("KVM: x86: fire timer when
+it is migrated and expired, and in oneshot mode") just makes it
+easier to hit the issue.
+
+Having both commits, the oneshot lapic timer gets fired immediately
+inside the KVM_SET_LAPIC call when loading the snapshot. On Intel
+platforms with APIC virtualization and posted interrupt processing,
+this eventually leads to setting the corresponding PIR bit. However,
+the whole PIR bits get cleared later in the same KVM_SET_LAPIC call
+by apicv_post_state_restore. This leads to timer interrupt lost.
+
+The fix is to move vmx_apicv_post_state_restore to the beginning of
+the KVM_SET_LAPIC call and rename to vmx_apicv_pre_state_restore.
+What vmx_apicv_post_state_restore does is actually clearing any
+former apicv state and this behavior is more suitable to carry out
+in the beginning.
+
+Fixes: 967235d32032 ("KVM: vmx: clear pending interrupts on KVM_SET_LAPIC")
+Cc: stable@vger.kernel.org
+Suggested-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Haitao Shan <hshan@google.com>
+Link: https://lore.kernel.org/r/20230913000215.478387-1-hshan@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/kvm-x86-ops.h | 1 +
+ arch/x86/include/asm/kvm_host.h | 1 +
+ arch/x86/kvm/lapic.c | 4 ++++
+ arch/x86/kvm/vmx/vmx.c | 4 ++--
+ 4 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
+index 2c6698aa218b1..abc07d0045897 100644
+--- a/arch/x86/include/asm/kvm-x86-ops.h
++++ b/arch/x86/include/asm/kvm-x86-ops.h
+@@ -106,6 +106,7 @@ KVM_X86_OP_OPTIONAL(vcpu_blocking)
+ KVM_X86_OP_OPTIONAL(vcpu_unblocking)
+ KVM_X86_OP_OPTIONAL(pi_update_irte)
+ KVM_X86_OP_OPTIONAL(pi_start_assignment)
++KVM_X86_OP_OPTIONAL(apicv_pre_state_restore)
+ KVM_X86_OP_OPTIONAL(apicv_post_state_restore)
+ KVM_X86_OP_OPTIONAL_RET0(dy_apicv_has_pending_interrupt)
+ KVM_X86_OP_OPTIONAL(set_hv_timer)
+diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
+index c1dcaa3d2d6eb..dfcdcafe3a2cd 100644
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -1603,6 +1603,7 @@ struct kvm_x86_ops {
+ int (*pi_update_irte)(struct kvm *kvm, unsigned int host_irq,
+ uint32_t guest_irq, bool set);
+ void (*pi_start_assignment)(struct kvm *kvm);
++ void (*apicv_pre_state_restore)(struct kvm_vcpu *vcpu);
+ void (*apicv_post_state_restore)(struct kvm_vcpu *vcpu);
+ bool (*dy_apicv_has_pending_interrupt)(struct kvm_vcpu *vcpu);
+
+diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
+index 4dba0a84ba2f3..edcf45e312b99 100644
+--- a/arch/x86/kvm/lapic.c
++++ b/arch/x86/kvm/lapic.c
+@@ -2446,6 +2446,8 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
+ u64 msr_val;
+ int i;
+
++ static_call_cond(kvm_x86_apicv_pre_state_restore)(vcpu);
++
+ if (!init_event) {
+ msr_val = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE;
+ if (kvm_vcpu_is_reset_bsp(vcpu))
+@@ -2757,6 +2759,8 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
+ struct kvm_lapic *apic = vcpu->arch.apic;
+ int r;
+
++ static_call_cond(kvm_x86_apicv_pre_state_restore)(vcpu);
++
+ kvm_lapic_set_base(vcpu, vcpu->arch.apic_base);
+ /* set SPIV separately to get count of SW disabled APICs right */
+ apic_set_spiv(apic, *((u32 *)(s->regs + APIC_SPIV)));
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index 31a10d774df6d..98d732b9418f1 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -6799,7 +6799,7 @@ static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
+ vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);
+ }
+
+-static void vmx_apicv_post_state_restore(struct kvm_vcpu *vcpu)
++static void vmx_apicv_pre_state_restore(struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+@@ -8172,7 +8172,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
+ .set_apic_access_page_addr = vmx_set_apic_access_page_addr,
+ .refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
+ .load_eoi_exitmap = vmx_load_eoi_exitmap,
+- .apicv_post_state_restore = vmx_apicv_post_state_restore,
++ .apicv_pre_state_restore = vmx_apicv_pre_state_restore,
+ .check_apicv_inhibit_reasons = vmx_check_apicv_inhibit_reasons,
+ .hwapic_irr_update = vmx_hwapic_irr_update,
+ .hwapic_isr_update = vmx_hwapic_isr_update,
+--
+2.42.0
+
--- /dev/null
+From 4d9cbf201fda0f1d363d63144ddcefe72663ca4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 10:04:34 +0200
+Subject: net: ravb: Check return value of reset_control_deassert()
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit d8eb6ea4b302e7ff78535c205510e359ac10a0bd ]
+
+reset_control_deassert() could return an error. Some devices cannot work
+if reset signal de-assert operation fails. To avoid this check the return
+code of reset_control_deassert() in ravb_probe() and take proper action.
+
+Along with it, the free_netdev() call from the error path was moved after
+reset_control_assert() on its own label (out_free_netdev) to free
+netdev in case reset_control_deassert() fails.
+
+Fixes: 0d13a1a464a0 ("ravb: Add reset support")
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 020edbd0a44a6..2bcea9fdd2653 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -2670,7 +2670,10 @@ static int ravb_probe(struct platform_device *pdev)
+ ndev->features = info->net_features;
+ ndev->hw_features = info->net_hw_features;
+
+- reset_control_deassert(rstc);
++ error = reset_control_deassert(rstc);
++ if (error)
++ goto out_free_netdev;
++
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
+@@ -2897,11 +2900,11 @@ static int ravb_probe(struct platform_device *pdev)
+ out_disable_refclk:
+ clk_disable_unprepare(priv->refclk);
+ out_release:
+- free_netdev(ndev);
+-
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ reset_control_assert(rstc);
++out_free_netdev:
++ free_netdev(ndev);
+ return error;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From c1a9f5c2b8c8132179bf8ad1e5d51cc3961e5332 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 10:04:39 +0200
+Subject: net: ravb: Keep reverse order of operations in ravb_remove()
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit edf9bc396e05081ca281ffb0cd41e44db478ff26 ]
+
+On RZ/G3S SMARC Carrier II board having RGMII connections b/w Ethernet
+MACs and PHYs it has been discovered that doing unbind/bind for ravb
+driver in a loop leads to wrong speed and duplex for Ethernet links and
+broken connectivity (the connectivity cannot be restored even with
+bringing interface down/up). Before doing unbind/bind the Ethernet
+interfaces were configured though systemd. The sh instructions used to
+do unbind/bind were:
+
+$ cd /sys/bus/platform/drivers/ravb/
+$ while :; do echo 11c30000.ethernet > unbind ; \
+ echo 11c30000.ethernet > bind; done
+
+It has been discovered that there is a race b/w IOCTLs initialized by
+systemd at the response of success binding and the
+"ravb_write(ndev, CCC_OPC_RESET, CCC)" call in ravb_remove() as
+follows:
+
+1/ as a result of bind success the user space open/configures the
+ interfaces tough an IOCTL; the following stack trace has been
+ identified on RZ/G3S:
+
+Call trace:
+dump_backtrace+0x9c/0x100
+show_stack+0x20/0x38
+dump_stack_lvl+0x48/0x60
+dump_stack+0x18/0x28
+ravb_open+0x70/0xa58
+__dev_open+0xf4/0x1e8
+__dev_change_flags+0x198/0x218
+dev_change_flags+0x2c/0x80
+devinet_ioctl+0x640/0x708
+inet_ioctl+0x1e4/0x200
+sock_do_ioctl+0x50/0x108
+sock_ioctl+0x240/0x358
+__arm64_sys_ioctl+0xb0/0x100
+invoke_syscall+0x50/0x128
+el0_svc_common.constprop.0+0xc8/0xf0
+do_el0_svc+0x24/0x38
+el0_svc+0x34/0xb8
+el0t_64_sync_handler+0xc0/0xc8
+el0t_64_sync+0x190/0x198
+
+2/ this call may execute concurrently with ravb_remove() as the
+ unbind/bind operation was executed in a loop
+3/ if the operation mode is changed to RESET (through
+ ravb_write(ndev, CCC_OPC_RESET, CCC) call in ravb_remove())
+ while the above ravb_open() is in progress it may lead to MAC
+ (or PHY, or MAC-PHY connection, the right point hasn't been identified
+ at the moment) to be broken, thus the Ethernet connectivity fails to
+ restore.
+
+The simple fix for this is to move ravb_write(ndev, CCC_OPC_RESET, CCC))
+after unregister_netdev() to avoid resetting the controller while the
+netdev interface is still registered.
+
+To avoid future issues in ravb_remove(), the patch follows the proper order
+of operations in ravb_remove(): reverse order compared with ravb_probe().
+This avoids described races as the IOCTLs as well as unregister_netdev()
+(called now at the beginning of ravb_remove()) calls rtnl_lock() before
+continuing and IOCTLs check (though devinet_ioctl()) if device is still
+registered just after taking the lock:
+
+int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
+{
+ // ...
+
+ rtnl_lock();
+
+ ret = -ENODEV;
+ dev = __dev_get_by_name(net, ifr->ifr_name);
+ if (!dev)
+ goto done;
+
+ // ...
+done:
+ rtnl_unlock();
+out:
+ return ret;
+}
+
+Fixes: c156633f1353 ("Renesas Ethernet AVB driver proper")
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 22 +++++++++++++---------
+ 1 file changed, 13 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index e1c4a0ca4493f..68cb5616ef991 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -2919,22 +2919,26 @@ static int ravb_remove(struct platform_device *pdev)
+ struct ravb_private *priv = netdev_priv(ndev);
+ const struct ravb_hw_info *info = priv->info;
+
+- /* Stop PTP Clock driver */
+- if (info->ccc_gac)
+- ravb_ptp_stop(ndev);
+-
+- clk_disable_unprepare(priv->gptp_clk);
+- clk_disable_unprepare(priv->refclk);
+-
+- /* Set reset mode */
+- ravb_write(ndev, CCC_OPC_RESET, CCC);
+ unregister_netdev(ndev);
+ if (info->nc_queues)
+ netif_napi_del(&priv->napi[RAVB_NC]);
+ netif_napi_del(&priv->napi[RAVB_BE]);
++
+ ravb_mdio_release(priv);
++
++ /* Stop PTP Clock driver */
++ if (info->ccc_gac)
++ ravb_ptp_stop(ndev);
++
+ dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
+ priv->desc_bat_dma);
++
++ /* Set reset mode */
++ ravb_write(ndev, CCC_OPC_RESET, CCC);
++
++ clk_disable_unprepare(priv->gptp_clk);
++ clk_disable_unprepare(priv->refclk);
++
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ reset_control_assert(priv->rstc);
+--
+2.42.0
+
--- /dev/null
+From 7a13abb3de3314179b3eba584f9bb20410fccba8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 10:04:36 +0200
+Subject: net: ravb: Make write access to CXR35 first before accessing other
+ EMAC registers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit d78c0ced60d5e2f8b5a4a0468a5c400b24aeadf2 ]
+
+Hardware manual of RZ/G3S (and RZ/G2L) specifies the following on the
+description of CXR35 register (chapter "PHY interface select register
+(CXR35)"): "After release reset, make write-access to this register before
+making write-access to other registers (except MDIOMOD). Even if not need
+to change the value of this register, make write-access to this register
+at least one time. Because RGMII/MII MODE is recognized by accessing this
+register".
+
+The setup procedure for EMAC module (chapter "Setup procedure" of RZ/G3S,
+RZ/G2L manuals) specifies the E-MAC.CXR35 register is the first EMAC
+register that is to be configured.
+
+Note [A] from chapter "PHY interface select register (CXR35)" specifies
+the following:
+[A] The case which CXR35 SEL_XMII is used for the selection of RGMII/MII
+in APB Clock 100 MHz.
+(1) To use RGMII interface, Set ‘H’03E8_0000’ to this register.
+(2) To use MII interface, Set ‘H’03E8_0002’ to this register.
+
+Take into account these indication.
+
+Fixes: 1089877ada8d ("ravb: Add RZ/G2L MII interface support")
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 0cfa1d09c92e8..3dab9eae5aaf2 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -517,6 +517,15 @@ static void ravb_emac_init_gbeth(struct net_device *ndev)
+ {
+ struct ravb_private *priv = netdev_priv(ndev);
+
++ if (priv->phy_interface == PHY_INTERFACE_MODE_MII) {
++ ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_MII, CXR35);
++ ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, 0);
++ } else {
++ ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_RGMII, CXR35);
++ ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1,
++ CXR31_SEL_LINK0);
++ }
++
+ /* Receive frame limit set register */
+ ravb_write(ndev, GBETH_RX_BUFF_MAX + ETH_FCS_LEN, RFLR);
+
+@@ -539,14 +548,6 @@ static void ravb_emac_init_gbeth(struct net_device *ndev)
+
+ /* E-MAC interrupt enable register */
+ ravb_write(ndev, ECSIPR_ICDIP, ECSIPR);
+-
+- if (priv->phy_interface == PHY_INTERFACE_MODE_MII) {
+- ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, 0);
+- ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_MII, CXR35);
+- } else {
+- ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1,
+- CXR31_SEL_LINK0);
+- }
+ }
+
+ static void ravb_emac_init_rcar(struct net_device *ndev)
+--
+2.42.0
+
--- /dev/null
+From d4883e94764328aace2b0dda671d8905bc69f07a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 10:04:37 +0200
+Subject: net: ravb: Start TX queues after HW initialization succeeded
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 6f32c086602050fc11157adeafaa1c1eb393f0af ]
+
+ravb_phy_start() may fail. If that happens, the TX queues will remain
+started. Thus, move the netif_tx_start_all_queues() after PHY is
+successfully initialized.
+
+Fixes: c156633f1353 ("Renesas Ethernet AVB driver proper")
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 3dab9eae5aaf2..6d4c1b9f568ba 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -1828,13 +1828,13 @@ static int ravb_open(struct net_device *ndev)
+ if (info->gptp)
+ ravb_ptp_init(ndev, priv->pdev);
+
+- netif_tx_start_all_queues(ndev);
+-
+ /* PHY control start */
+ error = ravb_phy_start(ndev);
+ if (error)
+ goto out_ptp_stop;
+
++ netif_tx_start_all_queues(ndev);
++
+ return 0;
+
+ out_ptp_stop:
+--
+2.42.0
+
--- /dev/null
+From b3e91e3db92dd709fc8522d557dd5c025f0e57d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 10:04:38 +0200
+Subject: net: ravb: Stop DMA in case of failures on ravb_open()
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit eac16a733427ba0de2449ffc7bd3da32ddb65cb7 ]
+
+In case ravb_phy_start() returns with error the settings applied in
+ravb_dmac_init() are not reverted (e.g. config mode). For this call
+ravb_stop_dma() on failure path of ravb_open().
+
+Fixes: a0d2f20650e8 ("Renesas Ethernet AVB PTP clock driver")
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 6d4c1b9f568ba..e1c4a0ca4493f 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -1841,6 +1841,7 @@ static int ravb_open(struct net_device *ndev)
+ /* Stop PTP Clock driver */
+ if (info->gptp)
+ ravb_ptp_stop(ndev);
++ ravb_stop_dma(ndev);
+ out_free_irq_mgmta:
+ if (!info->multi_irqs)
+ goto out_free_irq;
+--
+2.42.0
+
--- /dev/null
+From 94cdf48d662cd8f2363368d4a306fa5791462ce6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 10:04:35 +0200
+Subject: net: ravb: Use pm_runtime_resume_and_get()
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 88b74831faaee455c2af380382d979fc38e79270 ]
+
+pm_runtime_get_sync() may return an error. In case it returns with an error
+dev->power.usage_count needs to be decremented. pm_runtime_resume_and_get()
+takes care of this. Thus use it.
+
+Fixes: c156633f1353 ("Renesas Ethernet AVB driver proper")
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 2bcea9fdd2653..0cfa1d09c92e8 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -2675,7 +2675,9 @@ static int ravb_probe(struct platform_device *pdev)
+ goto out_free_netdev;
+
+ pm_runtime_enable(&pdev->dev);
+- pm_runtime_get_sync(&pdev->dev);
++ error = pm_runtime_resume_and_get(&pdev->dev);
++ if (error < 0)
++ goto out_rpm_disable;
+
+ if (info->multi_irqs) {
+ if (info->err_mgmt_irqs)
+@@ -2901,6 +2903,7 @@ static int ravb_probe(struct platform_device *pdev)
+ clk_disable_unprepare(priv->refclk);
+ out_release:
+ pm_runtime_put(&pdev->dev);
++out_rpm_disable:
+ pm_runtime_disable(&pdev->dev);
+ reset_control_assert(rstc);
+ out_free_netdev:
+--
+2.42.0
+
--- /dev/null
+From 38238b33bf090323efb32d41db32f17724d42698 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Nov 2023 14:01:26 +0800
+Subject: net: stmmac: xgmac: Disable FPE MMC interrupts
+
+From: Furong Xu <0x1207@gmail.com>
+
+[ Upstream commit e54d628a2721bfbb002c19f6e8ca6746cec7640f ]
+
+Commit aeb18dd07692 ("net: stmmac: xgmac: Disable MMC interrupts
+by default") tries to disable MMC interrupts to avoid a storm of
+unhandled interrupts, but leaves the FPE(Frame Preemption) MMC
+interrupts enabled, FPE MMC interrupts can cause the same problem.
+Now we mask FPE TX and RX interrupts to disable all MMC interrupts.
+
+Fixes: aeb18dd07692 ("net: stmmac: xgmac: Disable MMC interrupts by default")
+Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
+Signed-off-by: Furong Xu <0x1207@gmail.com>
+Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
+Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
+Link: https://lore.kernel.org/r/20231125060126.2328690-1-0x1207@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/mmc_core.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
+index ea4910ae0921a..6a7c1d325c464 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
+@@ -177,8 +177,10 @@
+ #define MMC_XGMAC_RX_DISCARD_OCT_GB 0x1b4
+ #define MMC_XGMAC_RX_ALIGN_ERR_PKT 0x1bc
+
++#define MMC_XGMAC_TX_FPE_INTR_MASK 0x204
+ #define MMC_XGMAC_TX_FPE_FRAG 0x208
+ #define MMC_XGMAC_TX_HOLD_REQ 0x20c
++#define MMC_XGMAC_RX_FPE_INTR_MASK 0x224
+ #define MMC_XGMAC_RX_PKT_ASSEMBLY_ERR 0x228
+ #define MMC_XGMAC_RX_PKT_SMD_ERR 0x22c
+ #define MMC_XGMAC_RX_PKT_ASSEMBLY_OK 0x230
+@@ -352,6 +354,8 @@ static void dwxgmac_mmc_intr_all_mask(void __iomem *mmcaddr)
+ {
+ writel(0x0, mmcaddr + MMC_RX_INTR_MASK);
+ writel(0x0, mmcaddr + MMC_TX_INTR_MASK);
++ writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_TX_FPE_INTR_MASK);
++ writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_RX_FPE_INTR_MASK);
+ writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_RX_IPC_INTR_MASK);
+ }
+
+--
+2.42.0
+
--- /dev/null
+From bc372976c87c8d5b4ca00f0ab9257173c7344a6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Nov 2023 00:08:02 +0300
+Subject: octeontx2-af: Fix possible buffer overflow
+
+From: Elena Salomatkina <elena.salomatkina.cmc@gmail.com>
+
+[ Upstream commit ad31c629ca3c87f6d557488c1f9faaebfbcd203c ]
+
+A loop in rvu_mbox_handler_nix_bandprof_free() contains
+a break if (idx == MAX_BANDPROF_PER_PFFUNC),
+but if idx may reach MAX_BANDPROF_PER_PFFUNC
+buffer '(*req->prof_idx)[layer]' overflow happens before that check.
+
+The patch moves the break to the
+beginning of the loop.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: e8e095b3b370 ("octeontx2-af: cn10k: Bandwidth profiles config support").
+Signed-off-by: Elena Salomatkina <elena.salomatkina.cmc@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Link: https://lore.kernel.org/r/20231124210802.109763-1-elena.salomatkina.cmc@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+index 1f3a8cf42765e..7310047136986 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+@@ -5236,6 +5236,8 @@ int rvu_mbox_handler_nix_bandprof_free(struct rvu *rvu,
+
+ ipolicer = &nix_hw->ipolicer[layer];
+ for (idx = 0; idx < req->prof_count[layer]; idx++) {
++ if (idx == MAX_BANDPROF_PER_PFFUNC)
++ break;
+ prof_idx = req->prof_idx[layer][idx];
+ if (prof_idx >= ipolicer->band_prof.max ||
+ ipolicer->pfvf_map[prof_idx] != pcifunc)
+@@ -5249,8 +5251,6 @@ int rvu_mbox_handler_nix_bandprof_free(struct rvu *rvu,
+ ipolicer->pfvf_map[prof_idx] = 0x00;
+ ipolicer->match_id[prof_idx] = 0;
+ rvu_free_rsrc(&ipolicer->band_prof, prof_idx);
+- if (idx == MAX_BANDPROF_PER_PFFUNC)
+- break;
+ }
+ }
+ mutex_unlock(&rvu->rsrc_lock);
+--
+2.42.0
+
--- /dev/null
+From bff4941aceeb80d265fe1b0060d654a2cddf7a35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Jul 2023 10:09:25 +0530
+Subject: octeontx2-af: Install TC filter rules in hardware based on priority
+
+From: Suman Ghosh <sumang@marvell.com>
+
+[ Upstream commit ec87f05402f592d27507e1aa6b2fd21c486f2cc0 ]
+
+As of today, hardware does not support installing tc filter
+rules based on priority. This patch adds support to install
+the hardware rules based on priority. The final hardware rules
+will not be dependent on rule installation order, it will be strictly
+priority based, same as software.
+
+Signed-off-by: Suman Ghosh <sumang@marvell.com>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Link: https://lore.kernel.org/r/20230721043925.2627806-1-sumang@marvell.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: fd7f98b2e12a ("octeontx2-pf: Restore TC ingress police rules when interface is up")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/mbox.h | 9 +-
+ .../marvell/octeontx2/af/rvu_npc_fs.c | 9 +-
+ .../marvell/octeontx2/af/rvu_switch.c | 6 +-
+ .../marvell/octeontx2/nic/otx2_common.h | 11 +-
+ .../marvell/octeontx2/nic/otx2_devlink.c | 1 -
+ .../marvell/octeontx2/nic/otx2_ethtool.c | 1 +
+ .../marvell/octeontx2/nic/otx2_flows.c | 2 +
+ .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 320 +++++++++++++-----
+ 8 files changed, 255 insertions(+), 104 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+index 11eeb36cf9a54..a0c31f5b2ce05 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+@@ -232,7 +232,7 @@ M(NPC_GET_KEX_CFG, 0x600c, npc_get_kex_cfg, \
+ M(NPC_INSTALL_FLOW, 0x600d, npc_install_flow, \
+ npc_install_flow_req, npc_install_flow_rsp) \
+ M(NPC_DELETE_FLOW, 0x600e, npc_delete_flow, \
+- npc_delete_flow_req, msg_rsp) \
++ npc_delete_flow_req, npc_delete_flow_rsp) \
+ M(NPC_MCAM_READ_ENTRY, 0x600f, npc_mcam_read_entry, \
+ npc_mcam_read_entry_req, \
+ npc_mcam_read_entry_rsp) \
+@@ -1471,6 +1471,8 @@ struct npc_install_flow_req {
+ u8 vtag0_op;
+ u16 vtag1_def;
+ u8 vtag1_op;
++ /* old counter value */
++ u16 cntr_val;
+ };
+
+ struct npc_install_flow_rsp {
+@@ -1486,6 +1488,11 @@ struct npc_delete_flow_req {
+ u8 all; /* PF + VFs */
+ };
+
++struct npc_delete_flow_rsp {
++ struct mbox_msghdr hdr;
++ u16 cntr_val;
++};
++
+ struct npc_mcam_read_entry_req {
+ struct mbox_msghdr hdr;
+ u16 entry; /* MCAM entry to read */
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+index 1eb5eb29a2ba6..80d6aa3f14c11 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+@@ -1184,7 +1184,7 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
+ write_req.enable_entry = (u8)enable;
+ /* if counter is available then clear and use it */
+ if (req->set_cntr && rule->has_cntr) {
+- rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(rule->cntr), 0x00);
++ rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(rule->cntr), req->cntr_val);
+ write_req.set_cntr = 1;
+ write_req.cntr = rule->cntr;
+ }
+@@ -1399,12 +1399,13 @@ static int npc_delete_flow(struct rvu *rvu, struct rvu_npc_mcam_rule *rule,
+
+ int rvu_mbox_handler_npc_delete_flow(struct rvu *rvu,
+ struct npc_delete_flow_req *req,
+- struct msg_rsp *rsp)
++ struct npc_delete_flow_rsp *rsp)
+ {
+ struct npc_mcam *mcam = &rvu->hw->mcam;
+ struct rvu_npc_mcam_rule *iter, *tmp;
+ u16 pcifunc = req->hdr.pcifunc;
+ struct list_head del_list;
++ int blkaddr;
+
+ INIT_LIST_HEAD(&del_list);
+
+@@ -1420,6 +1421,10 @@ int rvu_mbox_handler_npc_delete_flow(struct rvu *rvu,
+ list_move_tail(&iter->list, &del_list);
+ /* single rule */
+ } else if (req->entry == iter->entry) {
++ blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
++ if (blkaddr)
++ rsp->cntr_val = rvu_read64(rvu, blkaddr,
++ NPC_AF_MATCH_STATX(iter->cntr));
+ list_move_tail(&iter->list, &del_list);
+ break;
+ }
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
+index 3392487f6b47b..329b5a02914d7 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
+@@ -145,6 +145,7 @@ void rvu_switch_enable(struct rvu *rvu)
+ struct npc_mcam_alloc_entry_req alloc_req = { 0 };
+ struct npc_mcam_alloc_entry_rsp alloc_rsp = { 0 };
+ struct npc_delete_flow_req uninstall_req = { 0 };
++ struct npc_delete_flow_rsp uninstall_rsp = { 0 };
+ struct npc_mcam_free_entry_req free_req = { 0 };
+ struct rvu_switch *rswitch = &rvu->rswitch;
+ struct msg_rsp rsp;
+@@ -184,7 +185,7 @@ void rvu_switch_enable(struct rvu *rvu)
+ uninstall_rules:
+ uninstall_req.start = rswitch->start_entry;
+ uninstall_req.end = rswitch->start_entry + rswitch->used_entries - 1;
+- rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp);
++ rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);
+ kfree(rswitch->entry2pcifunc);
+ free_entries:
+ free_req.all = 1;
+@@ -196,6 +197,7 @@ void rvu_switch_enable(struct rvu *rvu)
+ void rvu_switch_disable(struct rvu *rvu)
+ {
+ struct npc_delete_flow_req uninstall_req = { 0 };
++ struct npc_delete_flow_rsp uninstall_rsp = { 0 };
+ struct npc_mcam_free_entry_req free_req = { 0 };
+ struct rvu_switch *rswitch = &rvu->rswitch;
+ struct rvu_hwinfo *hw = rvu->hw;
+@@ -232,7 +234,7 @@ void rvu_switch_disable(struct rvu *rvu)
+ uninstall_req.start = rswitch->start_entry;
+ uninstall_req.end = rswitch->start_entry + rswitch->used_entries - 1;
+ free_req.all = 1;
+- rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp);
++ rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);
+ rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
+ rswitch->used_entries = 0;
+ kfree(rswitch->entry2pcifunc);
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+index efd66224b3dbf..a6f2632b44679 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+@@ -339,13 +339,8 @@ struct otx2_flow_config {
+ struct list_head flow_list;
+ u32 dmacflt_max_flows;
+ u16 max_flows;
+-};
+-
+-struct otx2_tc_info {
+- /* hash table to store TC offloaded flows */
+- struct rhashtable flow_table;
+- struct rhashtable_params flow_ht_params;
+- unsigned long *tc_entries_bitmap;
++ struct list_head flow_list_tc;
++ bool ntuple;
+ };
+
+ struct dev_hw_ops {
+@@ -465,7 +460,6 @@ struct otx2_nic {
+ /* NPC MCAM */
+ struct otx2_flow_config *flow_cfg;
+ struct otx2_mac_table *mac_table;
+- struct otx2_tc_info tc_info;
+
+ u64 reset_count;
+ struct work_struct reset_task;
+@@ -1024,7 +1018,6 @@ int otx2_init_tc(struct otx2_nic *nic);
+ void otx2_shutdown_tc(struct otx2_nic *nic);
+ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
+ void *type_data);
+-int otx2_tc_alloc_ent_bitmap(struct otx2_nic *nic);
+ /* CGX/RPM DMAC filters support */
+ int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf);
+ int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos);
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
+index 777a27047c8e8..5f71a72f95e50 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
+@@ -41,7 +41,6 @@ static int otx2_dl_mcam_count_set(struct devlink *devlink, u32 id,
+ return 0;
+
+ otx2_alloc_mcam_entries(pfvf, ctx->val.vu16);
+- otx2_tc_alloc_ent_bitmap(pfvf);
+
+ return 0;
+ }
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+index 0eb74e8c553dd..aaf1af2a402ec 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+@@ -753,6 +753,7 @@ static int otx2_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc)
+ struct otx2_nic *pfvf = netdev_priv(dev);
+ int ret = -EOPNOTSUPP;
+
++ pfvf->flow_cfg->ntuple = ntuple;
+ switch (nfc->cmd) {
+ case ETHTOOL_SRXFH:
+ ret = otx2_set_rss_hash_opts(pfvf, nfc);
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+index 5c4a4d3557702..5c757508322b9 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+@@ -276,6 +276,7 @@ int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
+
+ flow_cfg = pfvf->flow_cfg;
+ INIT_LIST_HEAD(&flow_cfg->flow_list);
++ INIT_LIST_HEAD(&flow_cfg->flow_list_tc);
+ flow_cfg->max_flows = 0;
+
+ return 0;
+@@ -298,6 +299,7 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&pf->flow_cfg->flow_list);
++ INIT_LIST_HEAD(&pf->flow_cfg->flow_list_tc);
+
+ /* Allocate bare minimum number of MCAM entries needed for
+ * unicast and ntuple filters.
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+index 1aeb18a901b13..3b169b1b12d98 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+@@ -48,9 +48,8 @@ struct otx2_tc_flow_stats {
+ };
+
+ struct otx2_tc_flow {
+- struct rhash_head node;
++ struct list_head list;
+ unsigned long cookie;
+- unsigned int bitpos;
+ struct rcu_head rcu;
+ struct otx2_tc_flow_stats stats;
+ spinlock_t lock; /* lock for stats */
+@@ -58,31 +57,10 @@ struct otx2_tc_flow {
+ u16 entry;
+ u16 leaf_profile;
+ bool is_act_police;
++ u32 prio;
++ struct npc_install_flow_req req;
+ };
+
+-int otx2_tc_alloc_ent_bitmap(struct otx2_nic *nic)
+-{
+- struct otx2_tc_info *tc = &nic->tc_info;
+-
+- if (!nic->flow_cfg->max_flows)
+- return 0;
+-
+- /* Max flows changed, free the existing bitmap */
+- kfree(tc->tc_entries_bitmap);
+-
+- tc->tc_entries_bitmap =
+- kcalloc(BITS_TO_LONGS(nic->flow_cfg->max_flows),
+- sizeof(long), GFP_KERNEL);
+- if (!tc->tc_entries_bitmap) {
+- netdev_err(nic->netdev,
+- "Unable to alloc TC flow entries bitmap\n");
+- return -ENOMEM;
+- }
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(otx2_tc_alloc_ent_bitmap);
+-
+ static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst,
+ u32 *burst_exp, u32 *burst_mantissa)
+ {
+@@ -689,8 +667,117 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
+ return otx2_tc_parse_actions(nic, &rule->action, req, f, node);
+ }
+
+-static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry)
++static void otx2_destroy_tc_flow_list(struct otx2_nic *pfvf)
++{
++ struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
++ struct otx2_tc_flow *iter, *tmp;
++
++ if (!(pfvf->flags & OTX2_FLAG_MCAM_ENTRIES_ALLOC))
++ return;
++
++ list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list_tc, list) {
++ list_del(&iter->list);
++ kfree(iter);
++ flow_cfg->nr_flows--;
++ }
++}
++
++static struct otx2_tc_flow *otx2_tc_get_entry_by_cookie(struct otx2_flow_config *flow_cfg,
++ unsigned long cookie)
++{
++ struct otx2_tc_flow *tmp;
++
++ list_for_each_entry(tmp, &flow_cfg->flow_list_tc, list) {
++ if (tmp->cookie == cookie)
++ return tmp;
++ }
++
++ return NULL;
++}
++
++static struct otx2_tc_flow *otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg,
++ int index)
+ {
++ struct otx2_tc_flow *tmp;
++ int i = 0;
++
++ list_for_each_entry(tmp, &flow_cfg->flow_list_tc, list) {
++ if (i == index)
++ return tmp;
++ i++;
++ }
++
++ return NULL;
++}
++
++static void otx2_tc_del_from_flow_list(struct otx2_flow_config *flow_cfg,
++ struct otx2_tc_flow *node)
++{
++ struct list_head *pos, *n;
++ struct otx2_tc_flow *tmp;
++
++ list_for_each_safe(pos, n, &flow_cfg->flow_list_tc) {
++ tmp = list_entry(pos, struct otx2_tc_flow, list);
++ if (node == tmp) {
++ list_del(&node->list);
++ return;
++ }
++ }
++}
++
++static int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg,
++ struct otx2_tc_flow *node)
++{
++ struct list_head *pos, *n;
++ struct otx2_tc_flow *tmp;
++ int index = 0;
++
++ /* If the flow list is empty then add the new node */
++ if (list_empty(&flow_cfg->flow_list_tc)) {
++ list_add(&node->list, &flow_cfg->flow_list_tc);
++ return index;
++ }
++
++ list_for_each_safe(pos, n, &flow_cfg->flow_list_tc) {
++ tmp = list_entry(pos, struct otx2_tc_flow, list);
++ if (node->prio < tmp->prio)
++ break;
++ index++;
++ }
++
++ list_add(&node->list, pos->prev);
++ return index;
++}
++
++static int otx2_add_mcam_flow_entry(struct otx2_nic *nic, struct npc_install_flow_req *req)
++{
++ struct npc_install_flow_req *tmp_req;
++ int err;
++
++ mutex_lock(&nic->mbox.lock);
++ tmp_req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox);
++ if (!tmp_req) {
++ mutex_unlock(&nic->mbox.lock);
++ return -ENOMEM;
++ }
++
++ memcpy(tmp_req, req, sizeof(struct npc_install_flow_req));
++ /* Send message to AF */
++ err = otx2_sync_mbox_msg(&nic->mbox);
++ if (err) {
++ netdev_err(nic->netdev, "Failed to install MCAM flow entry %d\n",
++ req->entry);
++ mutex_unlock(&nic->mbox.lock);
++ return -EFAULT;
++ }
++
++ mutex_unlock(&nic->mbox.lock);
++ return 0;
++}
++
++static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, u16 *cntr_val)
++{
++ struct npc_delete_flow_rsp *rsp;
+ struct npc_delete_flow_req *req;
+ int err;
+
+@@ -711,22 +798,113 @@ static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry)
+ mutex_unlock(&nic->mbox.lock);
+ return -EFAULT;
+ }
++
++ if (cntr_val) {
++ rsp = (struct npc_delete_flow_rsp *)otx2_mbox_get_rsp(&nic->mbox.mbox,
++ 0, &req->hdr);
++ if (IS_ERR(rsp)) {
++ netdev_err(nic->netdev, "Failed to get MCAM delete response for entry %d\n",
++ entry);
++ mutex_unlock(&nic->mbox.lock);
++ return -EFAULT;
++ }
++
++ *cntr_val = rsp->cntr_val;
++ }
++
+ mutex_unlock(&nic->mbox.lock);
++ return 0;
++}
++
++static int otx2_tc_update_mcam_table_del_req(struct otx2_nic *nic,
++ struct otx2_flow_config *flow_cfg,
++ struct otx2_tc_flow *node)
++{
++ struct list_head *pos, *n;
++ struct otx2_tc_flow *tmp;
++ int i = 0, index = 0;
++ u16 cntr_val;
++
++ /* Find and delete the entry from the list and re-install
++ * all the entries from beginning to the index of the
++ * deleted entry to higher mcam indexes.
++ */
++ list_for_each_safe(pos, n, &flow_cfg->flow_list_tc) {
++ tmp = list_entry(pos, struct otx2_tc_flow, list);
++ if (node == tmp) {
++ list_del(&tmp->list);
++ break;
++ }
++
++ otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val);
++ tmp->entry++;
++ tmp->req.entry = tmp->entry;
++ tmp->req.cntr_val = cntr_val;
++ index++;
++ }
++
++ list_for_each_safe(pos, n, &flow_cfg->flow_list_tc) {
++ if (i == index)
++ break;
++
++ tmp = list_entry(pos, struct otx2_tc_flow, list);
++ otx2_add_mcam_flow_entry(nic, &tmp->req);
++ i++;
++ }
+
+ return 0;
+ }
+
++static int otx2_tc_update_mcam_table_add_req(struct otx2_nic *nic,
++ struct otx2_flow_config *flow_cfg,
++ struct otx2_tc_flow *node)
++{
++ int mcam_idx = flow_cfg->max_flows - flow_cfg->nr_flows - 1;
++ struct otx2_tc_flow *tmp;
++ int list_idx, i;
++ u16 cntr_val;
++
++ /* Find the index of the entry(list_idx) whose priority
++ * is greater than the new entry and re-install all
++ * the entries from beginning to list_idx to higher
++ * mcam indexes.
++ */
++ list_idx = otx2_tc_add_to_flow_list(flow_cfg, node);
++ for (i = 0; i < list_idx; i++) {
++ tmp = otx2_tc_get_entry_by_index(flow_cfg, i);
++ if (!tmp)
++ return -ENOMEM;
++
++ otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val);
++ tmp->entry = flow_cfg->flow_ent[mcam_idx];
++ tmp->req.entry = tmp->entry;
++ tmp->req.cntr_val = cntr_val;
++ otx2_add_mcam_flow_entry(nic, &tmp->req);
++ mcam_idx++;
++ }
++
++ return mcam_idx;
++}
++
++static int otx2_tc_update_mcam_table(struct otx2_nic *nic,
++ struct otx2_flow_config *flow_cfg,
++ struct otx2_tc_flow *node,
++ bool add_req)
++{
++ if (add_req)
++ return otx2_tc_update_mcam_table_add_req(nic, flow_cfg, node);
++
++ return otx2_tc_update_mcam_table_del_req(nic, flow_cfg, node);
++}
++
+ static int otx2_tc_del_flow(struct otx2_nic *nic,
+ struct flow_cls_offload *tc_flow_cmd)
+ {
+ struct otx2_flow_config *flow_cfg = nic->flow_cfg;
+- struct otx2_tc_info *tc_info = &nic->tc_info;
+ struct otx2_tc_flow *flow_node;
+ int err;
+
+- flow_node = rhashtable_lookup_fast(&tc_info->flow_table,
+- &tc_flow_cmd->cookie,
+- tc_info->flow_ht_params);
++ flow_node = otx2_tc_get_entry_by_cookie(flow_cfg, tc_flow_cmd->cookie);
+ if (!flow_node) {
+ netdev_err(nic->netdev, "tc flow not found for cookie 0x%lx\n",
+ tc_flow_cmd->cookie);
+@@ -754,16 +932,10 @@ static int otx2_tc_del_flow(struct otx2_nic *nic,
+ mutex_unlock(&nic->mbox.lock);
+ }
+
+- otx2_del_mcam_flow_entry(nic, flow_node->entry);
+-
+- WARN_ON(rhashtable_remove_fast(&nic->tc_info.flow_table,
+- &flow_node->node,
+- nic->tc_info.flow_ht_params));
++ otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL);
++ otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false);
+ kfree_rcu(flow_node, rcu);
+-
+- clear_bit(flow_node->bitpos, tc_info->tc_entries_bitmap);
+ flow_cfg->nr_flows--;
+-
+ return 0;
+ }
+
+@@ -772,15 +944,14 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
+ {
+ struct netlink_ext_ack *extack = tc_flow_cmd->common.extack;
+ struct otx2_flow_config *flow_cfg = nic->flow_cfg;
+- struct otx2_tc_info *tc_info = &nic->tc_info;
+ struct otx2_tc_flow *new_node, *old_node;
+ struct npc_install_flow_req *req, dummy;
+- int rc, err;
++ int rc, err, mcam_idx;
+
+ if (!(nic->flags & OTX2_FLAG_TC_FLOWER_SUPPORT))
+ return -ENOMEM;
+
+- if (bitmap_full(tc_info->tc_entries_bitmap, flow_cfg->max_flows)) {
++ if (flow_cfg->nr_flows == flow_cfg->max_flows) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Free MCAM entry not available to add the flow");
+ return -ENOMEM;
+@@ -792,6 +963,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
+ return -ENOMEM;
+ spin_lock_init(&new_node->lock);
+ new_node->cookie = tc_flow_cmd->cookie;
++ new_node->prio = tc_flow_cmd->common.prio;
+
+ memset(&dummy, 0, sizeof(struct npc_install_flow_req));
+
+@@ -802,12 +974,11 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
+ }
+
+ /* If a flow exists with the same cookie, delete it */
+- old_node = rhashtable_lookup_fast(&tc_info->flow_table,
+- &tc_flow_cmd->cookie,
+- tc_info->flow_ht_params);
++ old_node = otx2_tc_get_entry_by_cookie(flow_cfg, tc_flow_cmd->cookie);
+ if (old_node)
+ otx2_tc_del_flow(nic, tc_flow_cmd);
+
++ mcam_idx = otx2_tc_update_mcam_table(nic, flow_cfg, new_node, true);
+ mutex_lock(&nic->mbox.lock);
+ req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox);
+ if (!req) {
+@@ -818,11 +989,8 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
+
+ memcpy(&dummy.hdr, &req->hdr, sizeof(struct mbox_msghdr));
+ memcpy(req, &dummy, sizeof(struct npc_install_flow_req));
+-
+- new_node->bitpos = find_first_zero_bit(tc_info->tc_entries_bitmap,
+- flow_cfg->max_flows);
+ req->channel = nic->hw.rx_chan_base;
+- req->entry = flow_cfg->flow_ent[flow_cfg->max_flows - new_node->bitpos - 1];
++ req->entry = flow_cfg->flow_ent[mcam_idx];
+ req->intf = NIX_INTF_RX;
+ req->set_cntr = 1;
+ new_node->entry = req->entry;
+@@ -832,26 +1000,18 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
+ if (rc) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to install MCAM flow entry");
+ mutex_unlock(&nic->mbox.lock);
+- kfree_rcu(new_node, rcu);
+ goto free_leaf;
+ }
+- mutex_unlock(&nic->mbox.lock);
+
+- /* add new flow to flow-table */
+- rc = rhashtable_insert_fast(&nic->tc_info.flow_table, &new_node->node,
+- nic->tc_info.flow_ht_params);
+- if (rc) {
+- otx2_del_mcam_flow_entry(nic, req->entry);
+- kfree_rcu(new_node, rcu);
+- goto free_leaf;
+- }
++ mutex_unlock(&nic->mbox.lock);
++ memcpy(&new_node->req, req, sizeof(struct npc_install_flow_req));
+
+- set_bit(new_node->bitpos, tc_info->tc_entries_bitmap);
+ flow_cfg->nr_flows++;
+-
+ return 0;
+
+ free_leaf:
++ otx2_tc_del_from_flow_list(flow_cfg, new_node);
++ kfree_rcu(new_node, rcu);
+ if (new_node->is_act_police) {
+ mutex_lock(&nic->mbox.lock);
+
+@@ -878,16 +1038,13 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
+ static int otx2_tc_get_flow_stats(struct otx2_nic *nic,
+ struct flow_cls_offload *tc_flow_cmd)
+ {
+- struct otx2_tc_info *tc_info = &nic->tc_info;
+ struct npc_mcam_get_stats_req *req;
+ struct npc_mcam_get_stats_rsp *rsp;
+ struct otx2_tc_flow_stats *stats;
+ struct otx2_tc_flow *flow_node;
+ int err;
+
+- flow_node = rhashtable_lookup_fast(&tc_info->flow_table,
+- &tc_flow_cmd->cookie,
+- tc_info->flow_ht_params);
++ flow_node = otx2_tc_get_entry_by_cookie(nic->flow_cfg, tc_flow_cmd->cookie);
+ if (!flow_node) {
+ netdev_info(nic->netdev, "tc flow not found for cookie %lx",
+ tc_flow_cmd->cookie);
+@@ -1035,12 +1192,20 @@ static int otx2_setup_tc_block_ingress_cb(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+ {
+ struct otx2_nic *nic = cb_priv;
++ bool ntuple;
+
+ if (!tc_cls_can_offload_and_chain0(nic->netdev, type_data))
+ return -EOPNOTSUPP;
+
++ ntuple = nic->netdev->features & NETIF_F_NTUPLE;
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
++ if (ntuple) {
++ netdev_warn(nic->netdev,
++ "Can't install TC flower offload rule when NTUPLE is active");
++ return -EOPNOTSUPP;
++ }
++
+ return otx2_setup_tc_cls_flower(nic, type_data);
+ case TC_SETUP_CLSMATCHALL:
+ return otx2_setup_tc_ingress_matchall(nic, type_data);
+@@ -1123,18 +1288,8 @@ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
+ }
+ EXPORT_SYMBOL(otx2_setup_tc);
+
+-static const struct rhashtable_params tc_flow_ht_params = {
+- .head_offset = offsetof(struct otx2_tc_flow, node),
+- .key_offset = offsetof(struct otx2_tc_flow, cookie),
+- .key_len = sizeof(((struct otx2_tc_flow *)0)->cookie),
+- .automatic_shrinking = true,
+-};
+-
+ int otx2_init_tc(struct otx2_nic *nic)
+ {
+- struct otx2_tc_info *tc = &nic->tc_info;
+- int err;
+-
+ /* Exclude receive queue 0 being used for police action */
+ set_bit(0, &nic->rq_bmap);
+
+@@ -1144,25 +1299,12 @@ int otx2_init_tc(struct otx2_nic *nic)
+ return -EINVAL;
+ }
+
+- err = otx2_tc_alloc_ent_bitmap(nic);
+- if (err)
+- return err;
+-
+- tc->flow_ht_params = tc_flow_ht_params;
+- err = rhashtable_init(&tc->flow_table, &tc->flow_ht_params);
+- if (err) {
+- kfree(tc->tc_entries_bitmap);
+- tc->tc_entries_bitmap = NULL;
+- }
+- return err;
++ return 0;
+ }
+ EXPORT_SYMBOL(otx2_init_tc);
+
+ void otx2_shutdown_tc(struct otx2_nic *nic)
+ {
+- struct otx2_tc_info *tc = &nic->tc_info;
+-
+- kfree(tc->tc_entries_bitmap);
+- rhashtable_destroy(&tc->flow_table);
++ otx2_destroy_tc_flow_list(nic);
+ }
+ EXPORT_SYMBOL(otx2_shutdown_tc);
+--
+2.42.0
+
--- /dev/null
+From 538480c57a5e290c2f50695817dafa0a5e301531 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Nov 2023 22:04:02 +0530
+Subject: octeontx2-pf: Fix adding mbox work queue entry when num_vfs > 64
+
+From: Geetha sowjanya <gakula@marvell.com>
+
+[ Upstream commit 51597219e0cd5157401d4d0ccb5daa4d9961676f ]
+
+When more than 64 VFs are enabled for a PF then mbox communication
+between VF and PF is not working as mbox work queueing for few VFs
+are skipped due to wrong calculation of VF numbers.
+
+Fixes: d424b6c02415 ("octeontx2-pf: Enable SRIOV and added VF mbox handling")
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Link: https://lore.kernel.org/r/1700930042-5400-1-git-send-email-sbhatta@marvell.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+index 1d2d72c60a12c..42f2ff83b47f7 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+@@ -566,7 +566,9 @@ static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)
+ otx2_write64(pf, RVU_PF_VFPF_MBOX_INTX(1), intr);
+ otx2_queue_work(mbox, pf->mbox_pfvf_wq, 64, vfs, intr,
+ TYPE_PFVF);
+- vfs -= 64;
++ if (intr)
++ trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr);
++ vfs = 64;
+ }
+
+ intr = otx2_read64(pf, RVU_PF_VFPF_MBOX_INTX(0));
+@@ -574,7 +576,8 @@ static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)
+
+ otx2_queue_work(mbox, pf->mbox_pfvf_wq, 0, vfs, intr, TYPE_PFVF);
+
+- trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr);
++ if (intr)
++ trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr);
+
+ return IRQ_HANDLED;
+ }
+--
+2.42.0
+
--- /dev/null
+From 33a086cda6787b95c9ab3b879abd3e248070fe80 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Nov 2023 22:06:57 +0530
+Subject: octeontx2-pf: Restore TC ingress police rules when interface is up
+
+From: Subbaraya Sundeep <sbhatta@marvell.com>
+
+[ Upstream commit fd7f98b2e12a3d96a92bde6640657ec7116f4372 ]
+
+TC ingress policer rules depends on interface receive queue
+contexts since the bandwidth profiles are attached to RQ
+contexts. When an interface is brought down all the queue
+contexts are freed. This in turn frees bandwidth profiles in
+hardware causing ingress police rules non-functional after
+the interface is brought up. Fix this by applying all the ingress
+police rules config to hardware in otx2_open. Also allow
+adding ingress rules only when interface is running
+since no contexts exist for the interface when it is down.
+
+Fixes: 68fbff68dbea ("octeontx2-pf: Add police action for TC flower")
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Link: https://lore.kernel.org/r/1700930217-5707-1-git-send-email-sbhatta@marvell.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/marvell/octeontx2/nic/cn10k.c | 3 +
+ .../marvell/octeontx2/nic/otx2_common.h | 2 +
+ .../ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +
+ .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 120 ++++++++++++++----
+ 4 files changed, 102 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
+index 826f691de2595..59d8d1ba15c28 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
+@@ -448,6 +448,9 @@ int cn10k_set_ipolicer_rate(struct otx2_nic *pfvf, u16 profile,
+ aq->prof.pebs_mantissa = 0;
+ aq->prof_mask.pebs_mantissa = 0xFF;
+
++ aq->prof.hl_en = 0;
++ aq->prof_mask.hl_en = 1;
++
+ /* Fill AQ info */
+ aq->qidx = profile;
+ aq->ctype = NIX_AQ_CTYPE_BANDPROF;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+index a6f2632b44679..44950c2542bb7 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+@@ -1018,6 +1018,8 @@ int otx2_init_tc(struct otx2_nic *nic);
+ void otx2_shutdown_tc(struct otx2_nic *nic);
+ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
+ void *type_data);
++void otx2_tc_apply_ingress_police_rules(struct otx2_nic *nic);
++
+ /* CGX/RPM DMAC filters support */
+ int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf);
+ int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos);
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+index 42f2ff83b47f7..18c5d2b3f7f95 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+@@ -1858,6 +1858,8 @@ int otx2_open(struct net_device *netdev)
+ if (pf->flags & OTX2_FLAG_DMACFLTR_SUPPORT)
+ otx2_dmacflt_reinstall_flows(pf);
+
++ otx2_tc_apply_ingress_police_rules(pf);
++
+ err = otx2_rxtx_enable(pf, true);
+ /* If a mbox communication error happens at this point then interface
+ * will end up in a state such that it is in down state but hardware
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+index 3b169b1b12d98..8e67409af5372 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+@@ -59,6 +59,9 @@ struct otx2_tc_flow {
+ bool is_act_police;
+ u32 prio;
+ struct npc_install_flow_req req;
++ u64 rate;
++ u32 burst;
++ bool is_pps;
+ };
+
+ static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst,
+@@ -299,21 +302,10 @@ static int otx2_tc_egress_matchall_delete(struct otx2_nic *nic,
+ return err;
+ }
+
+-static int otx2_tc_act_set_police(struct otx2_nic *nic,
+- struct otx2_tc_flow *node,
+- struct flow_cls_offload *f,
+- u64 rate, u32 burst, u32 mark,
+- struct npc_install_flow_req *req, bool pps)
++static int otx2_tc_act_set_hw_police(struct otx2_nic *nic,
++ struct otx2_tc_flow *node)
+ {
+- struct netlink_ext_ack *extack = f->common.extack;
+- struct otx2_hw *hw = &nic->hw;
+- int rq_idx, rc;
+-
+- rq_idx = find_first_zero_bit(&nic->rq_bmap, hw->rx_queues);
+- if (rq_idx >= hw->rx_queues) {
+- NL_SET_ERR_MSG_MOD(extack, "Police action rules exceeded");
+- return -EINVAL;
+- }
++ int rc;
+
+ mutex_lock(&nic->mbox.lock);
+
+@@ -323,23 +315,17 @@ static int otx2_tc_act_set_police(struct otx2_nic *nic,
+ return rc;
+ }
+
+- rc = cn10k_set_ipolicer_rate(nic, node->leaf_profile, burst, rate, pps);
++ rc = cn10k_set_ipolicer_rate(nic, node->leaf_profile,
++ node->burst, node->rate, node->is_pps);
+ if (rc)
+ goto free_leaf;
+
+- rc = cn10k_map_unmap_rq_policer(nic, rq_idx, node->leaf_profile, true);
++ rc = cn10k_map_unmap_rq_policer(nic, node->rq, node->leaf_profile, true);
+ if (rc)
+ goto free_leaf;
+
+ mutex_unlock(&nic->mbox.lock);
+
+- req->match_id = mark & 0xFFFFULL;
+- req->index = rq_idx;
+- req->op = NIX_RX_ACTIONOP_UCAST;
+- set_bit(rq_idx, &nic->rq_bmap);
+- node->is_act_police = true;
+- node->rq = rq_idx;
+-
+ return 0;
+
+ free_leaf:
+@@ -351,6 +337,39 @@ static int otx2_tc_act_set_police(struct otx2_nic *nic,
+ return rc;
+ }
+
++static int otx2_tc_act_set_police(struct otx2_nic *nic,
++ struct otx2_tc_flow *node,
++ struct flow_cls_offload *f,
++ u64 rate, u32 burst, u32 mark,
++ struct npc_install_flow_req *req, bool pps)
++{
++ struct netlink_ext_ack *extack = f->common.extack;
++ struct otx2_hw *hw = &nic->hw;
++ int rq_idx, rc;
++
++ rq_idx = find_first_zero_bit(&nic->rq_bmap, hw->rx_queues);
++ if (rq_idx >= hw->rx_queues) {
++ NL_SET_ERR_MSG_MOD(extack, "Police action rules exceeded");
++ return -EINVAL;
++ }
++
++ req->match_id = mark & 0xFFFFULL;
++ req->index = rq_idx;
++ req->op = NIX_RX_ACTIONOP_UCAST;
++
++ node->is_act_police = true;
++ node->rq = rq_idx;
++ node->burst = burst;
++ node->rate = rate;
++ node->is_pps = pps;
++
++ rc = otx2_tc_act_set_hw_police(nic, node);
++ if (!rc)
++ set_bit(rq_idx, &nic->rq_bmap);
++
++ return rc;
++}
++
+ static int otx2_tc_parse_actions(struct otx2_nic *nic,
+ struct flow_action *flow_action,
+ struct npc_install_flow_req *req,
+@@ -912,6 +931,11 @@ static int otx2_tc_del_flow(struct otx2_nic *nic,
+ }
+
+ if (flow_node->is_act_police) {
++ __clear_bit(flow_node->rq, &nic->rq_bmap);
++
++ if (nic->flags & OTX2_FLAG_INTF_DOWN)
++ goto free_mcam_flow;
++
+ mutex_lock(&nic->mbox.lock);
+
+ err = cn10k_map_unmap_rq_policer(nic, flow_node->rq,
+@@ -927,11 +951,10 @@ static int otx2_tc_del_flow(struct otx2_nic *nic,
+ "Unable to free leaf bandwidth profile(%d)\n",
+ flow_node->leaf_profile);
+
+- __clear_bit(flow_node->rq, &nic->rq_bmap);
+-
+ mutex_unlock(&nic->mbox.lock);
+ }
+
++free_mcam_flow:
+ otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL);
+ otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false);
+ kfree_rcu(flow_node, rcu);
+@@ -951,6 +974,11 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
+ if (!(nic->flags & OTX2_FLAG_TC_FLOWER_SUPPORT))
+ return -ENOMEM;
+
++ if (nic->flags & OTX2_FLAG_INTF_DOWN) {
++ NL_SET_ERR_MSG_MOD(extack, "Interface not initialized");
++ return -EINVAL;
++ }
++
+ if (flow_cfg->nr_flows == flow_cfg->max_flows) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Free MCAM entry not available to add the flow");
+@@ -1308,3 +1336,45 @@ void otx2_shutdown_tc(struct otx2_nic *nic)
+ otx2_destroy_tc_flow_list(nic);
+ }
+ EXPORT_SYMBOL(otx2_shutdown_tc);
++
++static void otx2_tc_config_ingress_rule(struct otx2_nic *nic,
++ struct otx2_tc_flow *node)
++{
++ struct npc_install_flow_req *req;
++
++ if (otx2_tc_act_set_hw_police(nic, node))
++ return;
++
++ mutex_lock(&nic->mbox.lock);
++
++ req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox);
++ if (!req)
++ goto err;
++
++ memcpy(req, &node->req, sizeof(struct npc_install_flow_req));
++
++ if (otx2_sync_mbox_msg(&nic->mbox))
++ netdev_err(nic->netdev,
++ "Failed to install MCAM flow entry for ingress rule");
++err:
++ mutex_unlock(&nic->mbox.lock);
++}
++
++void otx2_tc_apply_ingress_police_rules(struct otx2_nic *nic)
++{
++ struct otx2_flow_config *flow_cfg = nic->flow_cfg;
++ struct otx2_tc_flow *node;
++
++ /* If any ingress policer rules exist for the interface then
++ * apply those rules. Ingress policer rules depend on bandwidth
++ * profiles linked to the receive queues. Since no receive queues
++ * exist when interface is down, ingress policer rules are stored
++ * and configured in hardware after all receive queues are allocated
++ * in otx2_open.
++ */
++ list_for_each_entry(node, &flow_cfg->flow_list_tc, list) {
++ if (node->is_act_police)
++ otx2_tc_config_ingress_rule(nic, node);
++ }
++}
++EXPORT_SYMBOL(otx2_tc_apply_ingress_police_rules);
+--
+2.42.0
+
--- /dev/null
+From cf28a605c7e7a5873627334c64836c64c59d9195 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 16:23:34 +0200
+Subject: PCI: Lengthen reset delay for VideoPropulsion Torrent QN16e card
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit c9260693aa0c1e029ed23693cfd4d7814eee6624 ]
+
+Commit ac91e6980563 ("PCI: Unify delay handling for reset and resume")
+shortened an unconditional 1 sec delay after a Secondary Bus Reset to 100
+msec for PCIe (per PCIe r6.1 sec 6.6.1). The 1 sec delay is only required
+for Conventional PCI.
+
+But it turns out that there are PCIe devices which require a longer delay
+than prescribed before first config space access after reset recovery or
+resume from D3cold:
+
+Chad reports that a "VideoPropulsion Torrent QN16e" MPEG QAM Modulator
+"raises a PCI system error (PERR), as reported by the IPMI event log, and
+the hardware itself would suffer a catastrophic event, cycling the server"
+unless the longer delay is observed.
+
+The card is specified to conform to PCIe r1.0 and indeed only supports Gen1
+speed (2.5 GT/s) according to lspci. PCIe r1.0 sec 7.6 prescribes the same
+100 msec delay as PCIe r6.1 sec 6.6.1:
+
+ To allow components to perform internal initialization, system software
+ must wait for at least 100 ms from the end of a reset (cold/warm/hot)
+ before it is permitted to issue Configuration Requests
+
+The behavior of the Torrent QN16e card thus appears to be a quirk. Treat
+it as such and lengthen the reset delay for this specific device.
+
+Fixes: ac91e6980563 ("PCI: Unify delay handling for reset and resume")
+Link: https://lore.kernel.org/r/47727e792c7f0282dc144e3ec8ce8eb6e713394e.1695304512.git.lukas@wunner.de
+Reported-by: Chad Schroeder <CSchroeder@sonifi.com>
+Closes: https://lore.kernel.org/linux-pci/DM6PR16MB2844903E34CAB910082DF019B1FAA@DM6PR16MB2844.namprd16.prod.outlook.com/
+Tested-by: Chad Schroeder <CSchroeder@sonifi.com>
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@vger.kernel.org # v5.4+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/quirks.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 48389785d9247..c132839d99dc8 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -6058,3 +6058,15 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2d, dpc_log_size);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2f, dpc_log_size);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a31, dpc_log_size);
+ #endif
++
++/*
++ * Devices known to require a longer delay before first config space access
++ * after reset recovery or resume from D3cold:
++ *
++ * VideoPropulsion (aka Genroco) Torrent QN16e MPEG QAM Modulator
++ */
++static void pci_fixup_d3cold_delay_1sec(struct pci_dev *pdev)
++{
++ pdev->d3cold_delay = 1000;
++}
++DECLARE_PCI_FIXUP_FINAL(0x5555, 0x0004, pci_fixup_d3cold_delay_1sec);
+--
+2.42.0
+
--- /dev/null
+From 9e558c21c1c826b108b76d4155de58b8f8ae3b5b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Oct 2023 18:30:29 +0530
+Subject: PCI: qcom-ep: Add dedicated callback for writing to DBI2 registers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+[ Upstream commit a07d2497ed657eb2efeb967af47e22f573dcd1d6 ]
+
+The DWC core driver exposes the write_dbi2() callback for writing to the
+DBI2 registers in a vendor-specific way.
+
+On the Qcom EP platforms, the DBI_CS2 bit in the ELBI region needs to be
+asserted before writing to any DBI2 registers and deasserted once done.
+
+So, let's implement the callback for the Qcom PCIe EP driver so that the
+DBI2 writes are correctly handled in the hardware.
+
+Without this callback, the DBI2 register writes like BAR size won't go
+through and as a result, the default BAR size is set for all BARs.
+
+[kwilczynski: commit log, renamed function to match the DWC convention]
+Fixes: f55fee56a631 ("PCI: qcom-ep: Add Qualcomm PCIe Endpoint controller driver")
+Suggested-by: Serge Semin <fancer.lancer@gmail.com>
+Link: https://lore.kernel.org/linux-pci/20231025130029.74693-2-manivannan.sadhasivam@linaro.org
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
+Cc: stable@vger.kernel.org # 5.16+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-qcom-ep.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c
+index d4c566c1c8725..1c7fd05ce0280 100644
+--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
++++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
+@@ -120,6 +120,7 @@
+
+ /* ELBI registers */
+ #define ELBI_SYS_STTS 0x08
++#define ELBI_CS2_ENABLE 0xa4
+
+ /* DBI registers */
+ #define DBI_CON_STATUS 0x44
+@@ -252,6 +253,21 @@ static void qcom_pcie_dw_stop_link(struct dw_pcie *pci)
+ disable_irq(pcie_ep->perst_irq);
+ }
+
++static void qcom_pcie_dw_write_dbi2(struct dw_pcie *pci, void __iomem *base,
++ u32 reg, size_t size, u32 val)
++{
++ struct qcom_pcie_ep *pcie_ep = to_pcie_ep(pci);
++ int ret;
++
++ writel(1, pcie_ep->elbi + ELBI_CS2_ENABLE);
++
++ ret = dw_pcie_write(pci->dbi_base2 + reg, size, val);
++ if (ret)
++ dev_err(pci->dev, "Failed to write DBI2 register (0x%x): %d\n", reg, ret);
++
++ writel(0, pcie_ep->elbi + ELBI_CS2_ENABLE);
++}
++
+ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
+ {
+ int ret;
+@@ -446,6 +462,7 @@ static const struct dw_pcie_ops pci_ops = {
+ .link_up = qcom_pcie_dw_link_up,
+ .start_link = qcom_pcie_dw_start_link,
+ .stop_link = qcom_pcie_dw_stop_link,
++ .write_dbi2 = qcom_pcie_dw_write_dbi2,
+ };
+
+ static int qcom_pcie_ep_get_io_resources(struct platform_device *pdev,
+--
+2.42.0
+
--- /dev/null
+From 4df071627fb4624e8327d931278e835914f40deb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Oct 2023 22:08:02 -0500
+Subject: powerpc/pseries/iommu: enable_ddw incorrectly returns direct mapping
+ for SR-IOV device
+
+From: Gaurav Batra <gbatra@linux.vnet.ibm.com>
+
+[ Upstream commit 3bf983e4e93ce8e6d69e9d63f52a66ec0856672e ]
+
+When a device is initialized, the driver invokes dma_supported() twice -
+first for streaming mappings followed by coherent mappings. For an
+SR-IOV device, default window is deleted and DDW created. With vPMEM
+enabled, TCE mappings are dynamically created for both vPMEM and SR-IOV
+device. There are no direct mappings.
+
+First time when dma_supported() is called with 64 bit mask, DDW is created
+and marked as dynamic window. The second time dma_supported() is called,
+enable_ddw() finds existing window for the device and incorrectly returns
+it as "direct mapping".
+
+This only happens when size of DDW is big enough to map max LPAR memory.
+
+This results in streaming TCEs to not get dynamically mapped, since code
+incorrently assumes these are already pre-mapped. The adapter initially
+comes up but goes down due to EEH.
+
+Fixes: 381ceda88c4c ("powerpc/pseries/iommu: Make use of DDW for indirect mapping")
+Cc: stable@vger.kernel.org # v5.15+
+Signed-off-by: Gaurav Batra <gbatra@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20231003030802.47914-1-gbatra@linux.vnet.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/platforms/pseries/iommu.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
+index 97b026130c71b..ad089d3f2d7c1 100644
+--- a/arch/powerpc/platforms/pseries/iommu.c
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -909,7 +909,8 @@ static int remove_ddw(struct device_node *np, bool remove_prop, const char *win_
+ return 0;
+ }
+
+-static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *window_shift)
++static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *window_shift,
++ bool *direct_mapping)
+ {
+ struct dma_win *window;
+ const struct dynamic_dma_window_prop *dma64;
+@@ -922,6 +923,7 @@ static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *windo
+ dma64 = window->prop;
+ *dma_addr = be64_to_cpu(dma64->dma_base);
+ *window_shift = be32_to_cpu(dma64->window_shift);
++ *direct_mapping = window->direct;
+ found = true;
+ break;
+ }
+@@ -1275,10 +1277,8 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+
+ mutex_lock(&dma_win_init_mutex);
+
+- if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len)) {
+- direct_mapping = (len >= max_ram_len);
++ if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len, &direct_mapping))
+ goto out_unlock;
+- }
+
+ /*
+ * If we already went through this for a previous function of
+--
+2.42.0
+
--- /dev/null
+From bdc481a48c03698a02ef11eb49229620255ca6b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 Nov 2023 23:01:02 +0100
+Subject: r8169: prevent potential deadlock in rtl8169_close
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 91d3d149978ba7b238198dd80e4b823756aa7cfa ]
+
+ndo_stop() is RTNL-protected by net core, and the worker function takes
+RTNL as well. Therefore we will deadlock when trying to execute a
+pending work synchronously. To fix this execute any pending work
+asynchronously. This will do no harm because netif_running() is false
+in ndo_stop(), and therefore the work function is effectively a no-op.
+However we have to ensure that no task is running or pending after
+rtl_remove_one(), therefore add a call to cancel_work_sync().
+
+Fixes: abe5fc42f9ce ("r8169: use RTNL to protect critical sections")
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/12395867-1d17-4cac-aa7d-c691938fcddf@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 770391cefb4e4..d293c996252cd 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -4656,7 +4656,7 @@ static int rtl8169_close(struct net_device *dev)
+ rtl8169_down(tp);
+ rtl8169_rx_clear(tp);
+
+- cancel_work_sync(&tp->wk.work);
++ cancel_work(&tp->wk.work);
+
+ free_irq(tp->irq, tp);
+
+@@ -4890,6 +4890,8 @@ static void rtl_remove_one(struct pci_dev *pdev)
+ if (pci_dev_run_wake(pdev))
+ pm_runtime_get_noresume(&pdev->dev);
+
++ cancel_work_sync(&tp->wk.work);
++
+ unregister_netdev(tp->dev);
+
+ if (tp->dash_type != RTL_DASH_NONE)
+--
+2.42.0
+
--- /dev/null
+From 90d55a0f6a8936258f1bdd4dbde4c2890bce894a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Nov 2023 21:24:20 +0900
+Subject: ravb: Fix races between ravb_tx_timeout_work() and net related ops
+
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+[ Upstream commit 9870257a0a338cd8d6c1cddab74e703f490f6779 ]
+
+Fix races between ravb_tx_timeout_work() and functions of net_device_ops
+and ethtool_ops by using rtnl_trylock() and rtnl_unlock(). Note that
+since ravb_close() is under the rtnl lock and calls cancel_work_sync(),
+ravb_tx_timeout_work() should calls rtnl_trylock(). Otherwise, a deadlock
+may happen in ravb_tx_timeout_work() like below:
+
+CPU0 CPU1
+ ravb_tx_timeout()
+ schedule_work()
+...
+__dev_close_many()
+// Under rtnl lock
+ravb_close()
+cancel_work_sync()
+// Waiting
+ ravb_tx_timeout_work()
+ rtnl_lock()
+ // This is possible to cause a deadlock
+
+If rtnl_trylock() fails, rescheduling the work with sleep for 1 msec.
+
+Fixes: c156633f1353 ("Renesas Ethernet AVB driver proper")
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Link: https://lore.kernel.org/r/20231127122420.3706751-1-yoshihiro.shimoda.uh@renesas.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 9a52283d77544..020edbd0a44a6 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -1890,6 +1890,12 @@ static void ravb_tx_timeout_work(struct work_struct *work)
+ struct net_device *ndev = priv->ndev;
+ int error;
+
++ if (!rtnl_trylock()) {
++ usleep_range(1000, 2000);
++ schedule_work(&priv->work);
++ return;
++ }
++
+ netif_tx_stop_all_queues(ndev);
+
+ /* Stop PTP Clock driver */
+@@ -1923,7 +1929,7 @@ static void ravb_tx_timeout_work(struct work_struct *work)
+ */
+ netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n",
+ __func__, error);
+- return;
++ goto out_unlock;
+ }
+ ravb_emac_init(ndev);
+
+@@ -1933,6 +1939,9 @@ static void ravb_tx_timeout_work(struct work_struct *work)
+ ravb_ptp_init(ndev, priv->pdev);
+
+ netif_tx_start_all_queues(ndev);
++
++out_unlock:
++ rtnl_unlock();
+ }
+
+ /* Packet transmit function for Ethernet AVB */
+--
+2.42.0
+
--- /dev/null
+From 7e345172ed606a5193d78ef0664b6061754fbee8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Oct 2023 10:15:20 +0200
+Subject: s390/cmma: fix handling of swapper_pg_dir and invalid_pg_dir
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+[ Upstream commit 84bb41d5df48868055d159d9247b80927f1f70f9 ]
+
+If the cmma no-dat feature is available the kernel page tables are walked
+to identify and mark all pages which are used for address translation (all
+region, segment, and page tables). In a subsequent loop all other pages are
+marked as "no-dat" pages with the ESSA instruction.
+
+This information is visible to the hypervisor, so that the hypervisor can
+optimize purging of guest TLB entries. All pages used for swapper_pg_dir
+and invalid_pg_dir are incorrectly marked as no-dat, which in turn can
+result in incorrect guest TLB flushes.
+
+Fix this by marking those pages correctly as being used for DAT.
+
+Cc: <stable@vger.kernel.org>
+Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/mm/page-states.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c
+index 7bea3be8b8280..c112762e38015 100644
+--- a/arch/s390/mm/page-states.c
++++ b/arch/s390/mm/page-states.c
+@@ -192,6 +192,12 @@ void __init cmma_init_nodat(void)
+ return;
+ /* Mark pages used in kernel page tables */
+ mark_kernel_pgd();
++ page = virt_to_page(&swapper_pg_dir);
++ for (i = 0; i < 4; i++)
++ set_bit(PG_arch_1, &page[i].flags);
++ page = virt_to_page(&invalid_pg_dir);
++ for (i = 0; i < 4; i++)
++ set_bit(PG_arch_1, &page[i].flags);
+
+ /* Set all kernel pages not used for page tables to stable/no-dat */
+ for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, NULL) {
+--
+2.42.0
+
--- /dev/null
+From d2208fab18b552fac856775254d212b6f7799072 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Nov 2023 12:15:20 -0500
+Subject: selftests/net: fix a char signedness issue
+
+From: Willem de Bruijn <willemb@google.com>
+
+[ Upstream commit 7b29828c5af6841bdeb9fafa32fdfeff7ab9c407 ]
+
+Signedness of char is signed on x86_64, but unsigned on arm64.
+
+Fix the warning building cmsg_sender.c on signed platforms or
+forced with -fsigned-char:
+
+ msg_sender.c:455:12:
+ error: implicit conversion from 'int' to 'char'
+ changes value from 128 to -128
+ [-Werror,-Wconstant-conversion]
+ buf[0] = ICMPV6_ECHO_REQUEST;
+
+constant ICMPV6_ECHO_REQUEST is 128.
+
+Link: https://lwn.net/Articles/911914
+Fixes: de17e305a810 ("selftests: net: cmsg_sender: support icmp and raw sockets")
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+Link: https://lore.kernel.org/r/20231124171645.1011043-3-willemdebruijn.kernel@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/cmsg_sender.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/net/cmsg_sender.c b/tools/testing/selftests/net/cmsg_sender.c
+index 24b21b15ed3fb..6ff3e732f449f 100644
+--- a/tools/testing/selftests/net/cmsg_sender.c
++++ b/tools/testing/selftests/net/cmsg_sender.c
+@@ -416,9 +416,9 @@ int main(int argc, char *argv[])
+ {
+ struct addrinfo hints, *ai;
+ struct iovec iov[1];
++ unsigned char *buf;
+ struct msghdr msg;
+ char cbuf[1024];
+- char *buf;
+ int err;
+ int fd;
+
+--
+2.42.0
+
--- /dev/null
+From 6582ef1545c8deb9ea112b435f8c3d376ab03dc7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Nov 2023 12:15:19 -0500
+Subject: selftests/net: ipsec: fix constant out of range
+
+From: Willem de Bruijn <willemb@google.com>
+
+[ Upstream commit 088559815477c6f623a5db5993491ddd7facbec7 ]
+
+Fix a small compiler warning.
+
+nr_process must be a signed long: it is assigned a signed long by
+strtol() and is compared against LONG_MIN and LONG_MAX.
+
+ipsec.c:2280:65:
+ error: result of comparison of constant -9223372036854775808
+ with expression of type 'unsigned int' is always false
+ [-Werror,-Wtautological-constant-out-of-range-compare]
+
+ if ((errno == ERANGE && (nr_process == LONG_MAX || nr_process == LONG_MIN))
+
+Fixes: bc2652b7ae1e ("selftest/net/xfrm: Add test for ipsec tunnel")
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
+Link: https://lore.kernel.org/r/20231124171645.1011043-2-willemdebruijn.kernel@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/ipsec.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/testing/selftests/net/ipsec.c b/tools/testing/selftests/net/ipsec.c
+index 9a8229abfa026..be4a30a0d02ae 100644
+--- a/tools/testing/selftests/net/ipsec.c
++++ b/tools/testing/selftests/net/ipsec.c
+@@ -2263,7 +2263,7 @@ static int check_results(void)
+
+ int main(int argc, char **argv)
+ {
+- unsigned int nr_process = 1;
++ long nr_process = 1;
+ int route_sock = -1, ret = KSFT_SKIP;
+ int test_desc_fd[2];
+ uint32_t route_seq;
+@@ -2284,7 +2284,7 @@ int main(int argc, char **argv)
+ exit_usage(argv);
+ }
+
+- if (nr_process > MAX_PROCESSES || !nr_process) {
++ if (nr_process > MAX_PROCESSES || nr_process < 1) {
+ printk("nr_process should be between [1; %u]",
+ MAX_PROCESSES);
+ exit_usage(argv);
+--
+2.42.0
+
--- /dev/null
+From ea7ef9e9a478dbef10030a05fcb024d5e830c41d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Nov 2023 12:15:22 -0500
+Subject: selftests/net: mptcp: fix uninitialized variable warnings
+
+From: Willem de Bruijn <willemb@google.com>
+
+[ Upstream commit 00a4f8fd9c750f20d8fd4535c71c9caa7ef5ff2f ]
+
+Same init_rng() in both tests. The function reads /dev/urandom to
+initialize srand(). In case of failure, it falls back onto the
+entropy in the uninitialized variable. Not sure if this is on purpose.
+But failure reading urandom should be rare, so just fail hard. While
+at it, convert to getrandom(). Which man 4 random suggests is simpler
+and more robust.
+
+ mptcp_inq.c:525:6:
+ mptcp_connect.c:1131:6:
+
+ error: variable 'foo' is used uninitialized
+ whenever 'if' condition is false
+ [-Werror,-Wsometimes-uninitialized]
+
+Fixes: 048d19d444be ("mptcp: add basic kselftest for mptcp")
+Fixes: b51880568f20 ("selftests: mptcp: add inq test case")
+Cc: Florian Westphal <fw@strlen.de>
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+
+----
+
+When input is randomized because this is expected to meaningfully
+explore edge cases, should we also add
+1. logging the random seed to stdout and
+2. adding a command line argument to replay from a specific seed
+I can do this in net-next, if authors find it useful in this case.
+Reviewed-by: Matthieu Baerts <matttbe@kernel.org>
+
+Link: https://lore.kernel.org/r/20231124171645.1011043-5-willemdebruijn.kernel@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/mptcp/mptcp_connect.c | 11 ++++-------
+ tools/testing/selftests/net/mptcp/mptcp_inq.c | 11 ++++-------
+ 2 files changed, 8 insertions(+), 14 deletions(-)
+
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
+index 7df6b9b6f9a84..e6b514cb7bdda 100644
+--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
+@@ -18,6 +18,7 @@
+
+ #include <sys/ioctl.h>
+ #include <sys/poll.h>
++#include <sys/random.h>
+ #include <sys/sendfile.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
+@@ -1050,15 +1051,11 @@ int main_loop_s(int listensock)
+
+ static void init_rng(void)
+ {
+- int fd = open("/dev/urandom", O_RDONLY);
+ unsigned int foo;
+
+- if (fd > 0) {
+- int ret = read(fd, &foo, sizeof(foo));
+-
+- if (ret < 0)
+- srand(fd + foo);
+- close(fd);
++ if (getrandom(&foo, sizeof(foo), 0) == -1) {
++ perror("getrandom");
++ exit(1);
+ }
+
+ srand(foo);
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_inq.c b/tools/testing/selftests/net/mptcp/mptcp_inq.c
+index 8672d898f8cda..218aac4673212 100644
+--- a/tools/testing/selftests/net/mptcp/mptcp_inq.c
++++ b/tools/testing/selftests/net/mptcp/mptcp_inq.c
+@@ -18,6 +18,7 @@
+ #include <time.h>
+
+ #include <sys/ioctl.h>
++#include <sys/random.h>
+ #include <sys/socket.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+@@ -519,15 +520,11 @@ static int client(int unixfd)
+
+ static void init_rng(void)
+ {
+- int fd = open("/dev/urandom", O_RDONLY);
+ unsigned int foo;
+
+- if (fd > 0) {
+- int ret = read(fd, &foo, sizeof(foo));
+-
+- if (ret < 0)
+- srand(fd + foo);
+- close(fd);
++ if (getrandom(&foo, sizeof(foo), 0) == -1) {
++ perror("getrandom");
++ exit(1);
+ }
+
+ srand(foo);
+--
+2.42.0
+
--- /dev/null
+From 058d5e24fafae82d2bc29bfd36f507a99382061b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Nov 2023 12:15:21 -0500
+Subject: selftests/net: unix: fix unused variable compiler warning
+
+From: Willem de Bruijn <willemb@google.com>
+
+[ Upstream commit 59fef379d453781f0dabfa1f1a1e86e78aee919a ]
+
+Remove an unused variable.
+
+ diag_uid.c:151:24:
+ error: unused variable 'udr'
+ [-Werror,-Wunused-variable]
+
+Fixes: ac011361bd4f ("af_unix: Add test for sock_diag and UDIAG_SHOW_UID.")
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+Link: https://lore.kernel.org/r/20231124171645.1011043-4-willemdebruijn.kernel@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/af_unix/diag_uid.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/tools/testing/selftests/net/af_unix/diag_uid.c b/tools/testing/selftests/net/af_unix/diag_uid.c
+index 5b88f7129fea4..79a3dd75590e8 100644
+--- a/tools/testing/selftests/net/af_unix/diag_uid.c
++++ b/tools/testing/selftests/net/af_unix/diag_uid.c
+@@ -148,7 +148,6 @@ void receive_response(struct __test_metadata *_metadata,
+ .msg_iov = &iov,
+ .msg_iovlen = 1
+ };
+- struct unix_diag_req *udr;
+ struct nlmsghdr *nlh;
+ int ret;
+
+--
+2.42.0
+
auxdisplay-hd44780-move-cursor-home-after-clear-display-command.patch
serial-sc16is7xx-put-iocontrol-register-into-regmap_volatile.patch
serial-sc16is7xx-add-missing-support-for-rs485-devicetree-properties.patch
+usb-xhci-plat-fix-legacy-phy-double-init.patch
+usb-core-change-configuration-warnings-to-notices.patch
+usb-config-fix-iteration-issue-in-usb_get_bos_descri.patch
+ipv4-igmp-fix-refcnt-uaf-issue-when-receiving-igmp-q.patch
+dpaa2-eth-increase-the-needed-headroom-to-account-fo.patch
+uapi-propagate-__struct_group-attributes-to-the-cont.patch
+selftests-net-ipsec-fix-constant-out-of-range.patch
+selftests-net-fix-a-char-signedness-issue.patch
+selftests-net-unix-fix-unused-variable-compiler-warn.patch
+selftests-net-mptcp-fix-uninitialized-variable-warni.patch
+octeontx2-af-fix-possible-buffer-overflow.patch
+net-stmmac-xgmac-disable-fpe-mmc-interrupts.patch
+octeontx2-pf-fix-adding-mbox-work-queue-entry-when-n.patch
+octeontx2-af-install-tc-filter-rules-in-hardware-bas.patch
+octeontx2-pf-restore-tc-ingress-police-rules-when-in.patch
+r8169-prevent-potential-deadlock-in-rtl8169_close.patch
+ravb-fix-races-between-ravb_tx_timeout_work-and-net-.patch
+net-ravb-check-return-value-of-reset_control_deasser.patch
+net-ravb-use-pm_runtime_resume_and_get.patch
+net-ravb-make-write-access-to-cxr35-first-before-acc.patch
+net-ravb-start-tx-queues-after-hw-initialization-suc.patch
+net-ravb-stop-dma-in-case-of-failures-on-ravb_open.patch
+net-ravb-keep-reverse-order-of-operations-in-ravb_re.patch
+kvm-x86-fix-lapic-timer-interrupt-lost-after-loading.patch
+pci-lengthen-reset-delay-for-videopropulsion-torrent.patch
+powerpc-pseries-iommu-enable_ddw-incorrectly-returns.patch
+s390-cmma-fix-handling-of-swapper_pg_dir-and-invalid.patch
+pci-qcom-ep-add-dedicated-callback-for-writing-to-db.patch
+fbdev-stifb-make-the-sti-next-font-pointer-a-32-bit-.patch
+drivers-perf-check-find_first_bit-return-value.patch
+spi-fix-null-dereference-on-suspend.patch
+drm-amd-display-restore-rptr-wptr-for-dmcub-as-worka.patch
+drm-amd-display-guard-against-invalid-rptr-wptr-bein.patch
+cpufreq-imx6q-don-t-warn-for-disabling-a-non-existin.patch
+cpufreq-imx6q-don-t-disable-792-mhz-opp-unnecessaril.patch
+iommu-vt-d-omit-devtlb-invalidation-requests-when-te.patch
+iommu-vt-d-allocate-pasid-table-in-device-probe-path.patch
+iommu-vt-d-add-device_block_translation-helper.patch
+iommu-vt-d-disable-pci-ats-in-legacy-passthrough-mod.patch
+iommu-vt-d-make-context-clearing-consistent-with-con.patch
+drm-i915-call-intel_pre_plane_updates-also-for-pipes.patch
+drm-amd-pm-fix-a-memleak-in-aldebaran_tables_init.patch
--- /dev/null
+From 909c42cc0de2432e35c3f1c1574b3c7c5910b089 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Nov 2023 14:47:43 -0700
+Subject: spi: Fix null dereference on suspend
+
+From: Mark Hasemeyer <markhas@chromium.org>
+
+[ Upstream commit bef4a48f4ef798c4feddf045d49e53c8a97d5e37 ]
+
+A race condition exists where a synchronous (noqueue) transfer can be
+active during a system suspend. This can cause a null pointer
+dereference exception to occur when the system resumes.
+
+Example order of events leading to the exception:
+1. spi_sync() calls __spi_transfer_message_noqueue() which sets
+ ctlr->cur_msg
+2. Spi transfer begins via spi_transfer_one_message()
+3. System is suspended interrupting the transfer context
+4. System is resumed
+6. spi_controller_resume() calls spi_start_queue() which resets cur_msg
+ to NULL
+7. Spi transfer context resumes and spi_finalize_current_message() is
+ called which dereferences cur_msg (which is now NULL)
+
+Wait for synchronous transfers to complete before suspending by
+acquiring the bus mutex and setting/checking a suspend flag.
+
+Signed-off-by: Mark Hasemeyer <markhas@chromium.org>
+Link: https://lore.kernel.org/r/20231107144743.v1.1.I7987f05f61901f567f7661763646cb7d7919b528@changeid
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Cc: stable@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi.c | 56 ++++++++++++++++++++++++++++-------------
+ include/linux/spi/spi.h | 1 +
+ 2 files changed, 40 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 151fef199c380..5d046be8b2dd5 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -3299,33 +3299,52 @@ void spi_unregister_controller(struct spi_controller *ctlr)
+ }
+ EXPORT_SYMBOL_GPL(spi_unregister_controller);
+
++static inline int __spi_check_suspended(const struct spi_controller *ctlr)
++{
++ return ctlr->flags & SPI_CONTROLLER_SUSPENDED ? -ESHUTDOWN : 0;
++}
++
++static inline void __spi_mark_suspended(struct spi_controller *ctlr)
++{
++ mutex_lock(&ctlr->bus_lock_mutex);
++ ctlr->flags |= SPI_CONTROLLER_SUSPENDED;
++ mutex_unlock(&ctlr->bus_lock_mutex);
++}
++
++static inline void __spi_mark_resumed(struct spi_controller *ctlr)
++{
++ mutex_lock(&ctlr->bus_lock_mutex);
++ ctlr->flags &= ~SPI_CONTROLLER_SUSPENDED;
++ mutex_unlock(&ctlr->bus_lock_mutex);
++}
++
+ int spi_controller_suspend(struct spi_controller *ctlr)
+ {
+- int ret;
++ int ret = 0;
+
+ /* Basically no-ops for non-queued controllers */
+- if (!ctlr->queued)
+- return 0;
+-
+- ret = spi_stop_queue(ctlr);
+- if (ret)
+- dev_err(&ctlr->dev, "queue stop failed\n");
++ if (ctlr->queued) {
++ ret = spi_stop_queue(ctlr);
++ if (ret)
++ dev_err(&ctlr->dev, "queue stop failed\n");
++ }
+
++ __spi_mark_suspended(ctlr);
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(spi_controller_suspend);
+
+ int spi_controller_resume(struct spi_controller *ctlr)
+ {
+- int ret;
+-
+- if (!ctlr->queued)
+- return 0;
++ int ret = 0;
+
+- ret = spi_start_queue(ctlr);
+- if (ret)
+- dev_err(&ctlr->dev, "queue restart failed\n");
++ __spi_mark_resumed(ctlr);
+
++ if (ctlr->queued) {
++ ret = spi_start_queue(ctlr);
++ if (ret)
++ dev_err(&ctlr->dev, "queue restart failed\n");
++ }
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(spi_controller_resume);
+@@ -4050,8 +4069,7 @@ static void __spi_transfer_message_noqueue(struct spi_controller *ctlr, struct s
+ ctlr->cur_msg = msg;
+ ret = __spi_pump_transfer_message(ctlr, msg, was_busy);
+ if (ret)
+- goto out;
+-
++ dev_err(&ctlr->dev, "noqueue transfer failed\n");
+ ctlr->cur_msg = NULL;
+ ctlr->fallback = false;
+
+@@ -4067,7 +4085,6 @@ static void __spi_transfer_message_noqueue(struct spi_controller *ctlr, struct s
+ spi_idle_runtime_pm(ctlr);
+ }
+
+-out:
+ mutex_unlock(&ctlr->io_mutex);
+ }
+
+@@ -4090,6 +4107,11 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
+ int status;
+ struct spi_controller *ctlr = spi->controller;
+
++ if (__spi_check_suspended(ctlr)) {
++ dev_warn_once(&spi->dev, "Attempted to sync while suspend\n");
++ return -ESHUTDOWN;
++ }
++
+ status = __spi_validate(spi, message);
+ if (status != 0)
+ return status;
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index fbf8c0d95968e..877395e075afe 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -531,6 +531,7 @@ struct spi_controller {
+ #define SPI_CONTROLLER_MUST_TX BIT(4) /* Requires tx */
+
+ #define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */
++#define SPI_CONTROLLER_SUSPENDED BIT(6) /* Currently suspended */
+
+ /* Flag indicating if the allocation of this struct is devres-managed */
+ bool devm_allocated;
+--
+2.42.0
+
--- /dev/null
+From 24e3539cd9020756bca8e2eb222f7bca08728a87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Nov 2023 14:05:08 +0300
+Subject: uapi: propagate __struct_group() attributes to the container union
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 4e86f32a13af1970d21be94f659cae56bbe487ee ]
+
+Recently the kernel test robot has reported an ARM-specific BUILD_BUG_ON()
+in an old and unmaintained wil6210 wireless driver. The problem comes from
+the structure packing rules of old ARM ABI ('-mabi=apcs-gnu'). For example,
+the following structure is packed to 18 bytes instead of 16:
+
+struct poorly_packed {
+ unsigned int a;
+ unsigned int b;
+ unsigned short c;
+ union {
+ struct {
+ unsigned short d;
+ unsigned int e;
+ } __attribute__((packed));
+ struct {
+ unsigned short d;
+ unsigned int e;
+ } __attribute__((packed)) inner;
+ };
+} __attribute__((packed));
+
+To fit it into 16 bytes, it's required to add packed attribute to the
+container union as well:
+
+struct poorly_packed {
+ unsigned int a;
+ unsigned int b;
+ unsigned short c;
+ union {
+ struct {
+ unsigned short d;
+ unsigned int e;
+ } __attribute__((packed));
+ struct {
+ unsigned short d;
+ unsigned int e;
+ } __attribute__((packed)) inner;
+ } __attribute__((packed));
+} __attribute__((packed));
+
+Thanks to Andrew Pinski of GCC team for sorting the things out at
+https://gcc.gnu.org/pipermail/gcc/2023-November/242888.html.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202311150821.cI4yciFE-lkp@intel.com
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Link: https://lore.kernel.org/r/20231120110607.98956-1-dmantipov@yandex.ru
+Fixes: 50d7bd38c3aa ("stddef: Introduce struct_group() helper macro")
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/uapi/linux/stddef.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h
+index 7837ba4fe7289..dcd50fb2164a1 100644
+--- a/include/uapi/linux/stddef.h
++++ b/include/uapi/linux/stddef.h
+@@ -27,7 +27,7 @@
+ union { \
+ struct { MEMBERS } ATTRS; \
+ struct TAG { MEMBERS } ATTRS NAME; \
+- }
++ } ATTRS
+
+ /**
+ * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
+--
+2.42.0
+
--- /dev/null
+From 9614a90f3a4e983c306addc2b31420f7d660d752 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Nov 2023 14:13:25 +0200
+Subject: usb: config: fix iteration issue in 'usb_get_bos_descriptor()'
+
+From: Niklas Neronin <niklas.neronin@linux.intel.com>
+
+[ Upstream commit 974bba5c118f4c2baf00de0356e3e4f7928b4cbc ]
+
+The BOS descriptor defines a root descriptor and is the base descriptor for
+accessing a family of related descriptors.
+
+Function 'usb_get_bos_descriptor()' encounters an iteration issue when
+skipping the 'USB_DT_DEVICE_CAPABILITY' descriptor type. This results in
+the same descriptor being read repeatedly.
+
+To address this issue, a 'goto' statement is introduced to ensure that the
+pointer and the amount read is updated correctly. This ensures that the
+function iterates to the next descriptor instead of reading the same
+descriptor repeatedly.
+
+Cc: stable@vger.kernel.org
+Fixes: 3dd550a2d365 ("USB: usbcore: Fix slab-out-of-bounds bug during device reset")
+Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
+Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20231115121325.471454-1-niklas.neronin@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/core/config.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 725b8dbcfe5f0..d396ac8b9cedd 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -1047,7 +1047,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+
+ if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
+ dev_notice(ddev, "descriptor type invalid, skip\n");
+- continue;
++ goto skip_to_next_descriptor;
+ }
+
+ switch (cap_type) {
+@@ -1081,6 +1081,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ break;
+ }
+
++skip_to_next_descriptor:
+ total_len -= length;
+ buffer += length;
+ }
+--
+2.42.0
+
--- /dev/null
+From 6d31be806213ae4fcad830df353e0cefbeed4c42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Nov 2022 14:13:19 -0400
+Subject: USB: core: Change configuration warnings to notices
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+[ Upstream commit 7a09c1269702db8eccb6f718da2b00173e1e0034 ]
+
+It has been pointed out that the kernel log messages warning about
+problems in USB configuration and related descriptors are vexing for
+users. The warning log level has a fairly high priority, but the user
+can do nothing to fix the underlying errors in the device's firmware.
+
+To reduce the amount of useless information produced by tools that
+filter high-priority log messages, we can change these warnings to
+notices, i.e., change dev_warn() to dev_notice(). The same holds for
+a few messages that currently use dev_err(): Unless they indicate a
+failure that might make a device unusable (such as inability to
+transfer a config descriptor), change them to dev_notice() also.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=216630
+Suggested-by: Artem S. Tashkinov <aros@gmx.com>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/Y2KzPx0h6z1jXCuN@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 974bba5c118f ("usb: config: fix iteration issue in 'usb_get_bos_descriptor()'")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/core/config.c | 82 +++++++++++++++++++--------------------
+ 1 file changed, 41 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 48bc8a4814ac4..725b8dbcfe5f0 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -61,7 +61,7 @@ static void usb_parse_ssp_isoc_endpoint_companion(struct device *ddev,
+ desc = (struct usb_ssp_isoc_ep_comp_descriptor *) buffer;
+ if (desc->bDescriptorType != USB_DT_SSP_ISOC_ENDPOINT_COMP ||
+ size < USB_DT_SSP_ISOC_EP_COMP_SIZE) {
+- dev_warn(ddev, "Invalid SuperSpeedPlus isoc endpoint companion"
++ dev_notice(ddev, "Invalid SuperSpeedPlus isoc endpoint companion"
+ "for config %d interface %d altsetting %d ep %d.\n",
+ cfgno, inum, asnum, ep->desc.bEndpointAddress);
+ return;
+@@ -83,7 +83,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+
+ if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP ||
+ size < USB_DT_SS_EP_COMP_SIZE) {
+- dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
++ dev_notice(ddev, "No SuperSpeed endpoint companion for config %d "
+ " interface %d altsetting %d ep %d: "
+ "using minimum values\n",
+ cfgno, inum, asnum, ep->desc.bEndpointAddress);
+@@ -109,13 +109,13 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+
+ /* Check the various values */
+ if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) {
+- dev_warn(ddev, "Control endpoint with bMaxBurst = %d in "
++ dev_notice(ddev, "Control endpoint with bMaxBurst = %d in "
+ "config %d interface %d altsetting %d ep %d: "
+ "setting to zero\n", desc->bMaxBurst,
+ cfgno, inum, asnum, ep->desc.bEndpointAddress);
+ ep->ss_ep_comp.bMaxBurst = 0;
+ } else if (desc->bMaxBurst > 15) {
+- dev_warn(ddev, "Endpoint with bMaxBurst = %d in "
++ dev_notice(ddev, "Endpoint with bMaxBurst = %d in "
+ "config %d interface %d altsetting %d ep %d: "
+ "setting to 15\n", desc->bMaxBurst,
+ cfgno, inum, asnum, ep->desc.bEndpointAddress);
+@@ -125,7 +125,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ if ((usb_endpoint_xfer_control(&ep->desc) ||
+ usb_endpoint_xfer_int(&ep->desc)) &&
+ desc->bmAttributes != 0) {
+- dev_warn(ddev, "%s endpoint with bmAttributes = %d in "
++ dev_notice(ddev, "%s endpoint with bmAttributes = %d in "
+ "config %d interface %d altsetting %d ep %d: "
+ "setting to zero\n",
+ usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk",
+@@ -134,7 +134,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ ep->ss_ep_comp.bmAttributes = 0;
+ } else if (usb_endpoint_xfer_bulk(&ep->desc) &&
+ desc->bmAttributes > 16) {
+- dev_warn(ddev, "Bulk endpoint with more than 65536 streams in "
++ dev_notice(ddev, "Bulk endpoint with more than 65536 streams in "
+ "config %d interface %d altsetting %d ep %d: "
+ "setting to max\n",
+ cfgno, inum, asnum, ep->desc.bEndpointAddress);
+@@ -142,7 +142,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ } else if (usb_endpoint_xfer_isoc(&ep->desc) &&
+ !USB_SS_SSP_ISOC_COMP(desc->bmAttributes) &&
+ USB_SS_MULT(desc->bmAttributes) > 3) {
+- dev_warn(ddev, "Isoc endpoint has Mult of %d in "
++ dev_notice(ddev, "Isoc endpoint has Mult of %d in "
+ "config %d interface %d altsetting %d ep %d: "
+ "setting to 3\n",
+ USB_SS_MULT(desc->bmAttributes),
+@@ -160,7 +160,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ else
+ max_tx = 999999;
+ if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) {
+- dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in "
++ dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
+ "config %d interface %d altsetting %d ep %d: "
+ "setting to %d\n",
+ usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
+@@ -273,7 +273,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ else if (d->bLength >= USB_DT_ENDPOINT_SIZE)
+ n = USB_DT_ENDPOINT_SIZE;
+ else {
+- dev_warn(ddev, "config %d interface %d altsetting %d has an "
++ dev_notice(ddev, "config %d interface %d altsetting %d has an "
+ "invalid endpoint descriptor of length %d, skipping\n",
+ cfgno, inum, asnum, d->bLength);
+ goto skip_to_next_endpoint_or_interface_descriptor;
+@@ -281,7 +281,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+
+ i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK;
+ if (i >= 16 || i == 0) {
+- dev_warn(ddev, "config %d interface %d altsetting %d has an "
++ dev_notice(ddev, "config %d interface %d altsetting %d has an "
+ "invalid endpoint with address 0x%X, skipping\n",
+ cfgno, inum, asnum, d->bEndpointAddress);
+ goto skip_to_next_endpoint_or_interface_descriptor;
+@@ -293,7 +293,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+
+ /* Check for duplicate endpoint addresses */
+ if (config_endpoint_is_duplicate(config, inum, asnum, d)) {
+- dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
++ dev_notice(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
+ cfgno, inum, asnum, d->bEndpointAddress);
+ goto skip_to_next_endpoint_or_interface_descriptor;
+ }
+@@ -301,7 +301,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ /* Ignore some endpoints */
+ if (udev->quirks & USB_QUIRK_ENDPOINT_IGNORE) {
+ if (usb_endpoint_is_ignored(udev, ifp, d)) {
+- dev_warn(ddev, "config %d interface %d altsetting %d has an ignored endpoint with address 0x%X, skipping\n",
++ dev_notice(ddev, "config %d interface %d altsetting %d has an ignored endpoint with address 0x%X, skipping\n",
+ cfgno, inum, asnum,
+ d->bEndpointAddress);
+ goto skip_to_next_endpoint_or_interface_descriptor;
+@@ -378,7 +378,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ }
+ }
+ if (d->bInterval < i || d->bInterval > j) {
+- dev_warn(ddev, "config %d interface %d altsetting %d "
++ dev_notice(ddev, "config %d interface %d altsetting %d "
+ "endpoint 0x%X has an invalid bInterval %d, "
+ "changing to %d\n",
+ cfgno, inum, asnum,
+@@ -391,7 +391,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ * them usable, we will try treating them as Interrupt endpoints.
+ */
+ if (udev->speed == USB_SPEED_LOW && usb_endpoint_xfer_bulk(d)) {
+- dev_warn(ddev, "config %d interface %d altsetting %d "
++ dev_notice(ddev, "config %d interface %d altsetting %d "
+ "endpoint 0x%X is Bulk; changing to Interrupt\n",
+ cfgno, inum, asnum, d->bEndpointAddress);
+ endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
+@@ -408,7 +408,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ */
+ maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize);
+ if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) {
+- dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n",
++ dev_notice(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n",
+ cfgno, inum, asnum, d->bEndpointAddress);
+ }
+
+@@ -439,7 +439,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ j = maxpacket_maxes[usb_endpoint_type(&endpoint->desc)];
+
+ if (maxp > j) {
+- dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid maxpacket %d, setting to %d\n",
++ dev_notice(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid maxpacket %d, setting to %d\n",
+ cfgno, inum, asnum, d->bEndpointAddress, maxp, j);
+ maxp = j;
+ endpoint->desc.wMaxPacketSize = cpu_to_le16(i | maxp);
+@@ -452,7 +452,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ */
+ if (udev->speed == USB_SPEED_HIGH && usb_endpoint_xfer_bulk(d)) {
+ if (maxp != 512)
+- dev_warn(ddev, "config %d interface %d altsetting %d "
++ dev_notice(ddev, "config %d interface %d altsetting %d "
+ "bulk endpoint 0x%X has invalid maxpacket %d\n",
+ cfgno, inum, asnum, d->bEndpointAddress,
+ maxp);
+@@ -533,7 +533,7 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
+ i < intfc->num_altsetting;
+ (++i, ++alt)) {
+ if (alt->desc.bAlternateSetting == asnum) {
+- dev_warn(ddev, "Duplicate descriptor for config %d "
++ dev_notice(ddev, "Duplicate descriptor for config %d "
+ "interface %d altsetting %d, skipping\n",
+ cfgno, inum, asnum);
+ goto skip_to_next_interface_descriptor;
+@@ -559,7 +559,7 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
+ num_ep = num_ep_orig = alt->desc.bNumEndpoints;
+ alt->desc.bNumEndpoints = 0; /* Use as a counter */
+ if (num_ep > USB_MAXENDPOINTS) {
+- dev_warn(ddev, "too many endpoints for config %d interface %d "
++ dev_notice(ddev, "too many endpoints for config %d interface %d "
+ "altsetting %d: %d, using maximum allowed: %d\n",
+ cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS);
+ num_ep = USB_MAXENDPOINTS;
+@@ -590,7 +590,7 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
+ }
+
+ if (n != num_ep_orig)
+- dev_warn(ddev, "config %d interface %d altsetting %d has %d "
++ dev_notice(ddev, "config %d interface %d altsetting %d has %d "
+ "endpoint descriptor%s, different from the interface "
+ "descriptor's value: %d\n",
+ cfgno, inum, asnum, n, plural(n), num_ep_orig);
+@@ -625,7 +625,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ if (config->desc.bDescriptorType != USB_DT_CONFIG ||
+ config->desc.bLength < USB_DT_CONFIG_SIZE ||
+ config->desc.bLength > size) {
+- dev_err(ddev, "invalid descriptor for config index %d: "
++ dev_notice(ddev, "invalid descriptor for config index %d: "
+ "type = 0x%X, length = %d\n", cfgidx,
+ config->desc.bDescriptorType, config->desc.bLength);
+ return -EINVAL;
+@@ -636,7 +636,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ size -= config->desc.bLength;
+
+ if (nintf > USB_MAXINTERFACES) {
+- dev_warn(ddev, "config %d has too many interfaces: %d, "
++ dev_notice(ddev, "config %d has too many interfaces: %d, "
+ "using maximum allowed: %d\n",
+ cfgno, nintf, USB_MAXINTERFACES);
+ nintf = USB_MAXINTERFACES;
+@@ -650,7 +650,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ (buffer2 += header->bLength, size2 -= header->bLength)) {
+
+ if (size2 < sizeof(struct usb_descriptor_header)) {
+- dev_warn(ddev, "config %d descriptor has %d excess "
++ dev_notice(ddev, "config %d descriptor has %d excess "
+ "byte%s, ignoring\n",
+ cfgno, size2, plural(size2));
+ break;
+@@ -658,7 +658,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+
+ header = (struct usb_descriptor_header *) buffer2;
+ if ((header->bLength > size2) || (header->bLength < 2)) {
+- dev_warn(ddev, "config %d has an invalid descriptor "
++ dev_notice(ddev, "config %d has an invalid descriptor "
+ "of length %d, skipping remainder of the config\n",
+ cfgno, header->bLength);
+ break;
+@@ -670,7 +670,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+
+ d = (struct usb_interface_descriptor *) header;
+ if (d->bLength < USB_DT_INTERFACE_SIZE) {
+- dev_warn(ddev, "config %d has an invalid "
++ dev_notice(ddev, "config %d has an invalid "
+ "interface descriptor of length %d, "
+ "skipping\n", cfgno, d->bLength);
+ continue;
+@@ -680,7 +680,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+
+ if ((dev->quirks & USB_QUIRK_HONOR_BNUMINTERFACES) &&
+ n >= nintf_orig) {
+- dev_warn(ddev, "config %d has more interface "
++ dev_notice(ddev, "config %d has more interface "
+ "descriptors, than it declares in "
+ "bNumInterfaces, ignoring interface "
+ "number: %d\n", cfgno, inum);
+@@ -688,7 +688,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ }
+
+ if (inum >= nintf_orig)
+- dev_warn(ddev, "config %d has an invalid "
++ dev_notice(ddev, "config %d has an invalid "
+ "interface number: %d but max is %d\n",
+ cfgno, inum, nintf_orig - 1);
+
+@@ -713,14 +713,14 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+
+ d = (struct usb_interface_assoc_descriptor *)header;
+ if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) {
+- dev_warn(ddev,
++ dev_notice(ddev,
+ "config %d has an invalid interface association descriptor of length %d, skipping\n",
+ cfgno, d->bLength);
+ continue;
+ }
+
+ if (iad_num == USB_MAXIADS) {
+- dev_warn(ddev, "found more Interface "
++ dev_notice(ddev, "found more Interface "
+ "Association Descriptors "
+ "than allocated for in "
+ "configuration %d\n", cfgno);
+@@ -731,7 +731,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+
+ } else if (header->bDescriptorType == USB_DT_DEVICE ||
+ header->bDescriptorType == USB_DT_CONFIG)
+- dev_warn(ddev, "config %d contains an unexpected "
++ dev_notice(ddev, "config %d contains an unexpected "
+ "descriptor of type 0x%X, skipping\n",
+ cfgno, header->bDescriptorType);
+
+@@ -740,11 +740,11 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);
+
+ if (n != nintf)
+- dev_warn(ddev, "config %d has %d interface%s, different from "
++ dev_notice(ddev, "config %d has %d interface%s, different from "
+ "the descriptor's value: %d\n",
+ cfgno, n, plural(n), nintf_orig);
+ else if (n == 0)
+- dev_warn(ddev, "config %d has no interfaces?\n", cfgno);
++ dev_notice(ddev, "config %d has no interfaces?\n", cfgno);
+ config->desc.bNumInterfaces = nintf = n;
+
+ /* Check for missing interface numbers */
+@@ -754,7 +754,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ break;
+ }
+ if (j >= nintf)
+- dev_warn(ddev, "config %d has no interface number "
++ dev_notice(ddev, "config %d has no interface number "
+ "%d\n", cfgno, i);
+ }
+
+@@ -762,7 +762,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ for (i = 0; i < nintf; ++i) {
+ j = nalts[i];
+ if (j > USB_MAXALTSETTING) {
+- dev_warn(ddev, "too many alternate settings for "
++ dev_notice(ddev, "too many alternate settings for "
+ "config %d interface %d: %d, "
+ "using maximum allowed: %d\n",
+ cfgno, inums[i], j, USB_MAXALTSETTING);
+@@ -811,7 +811,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ break;
+ }
+ if (n >= intfc->num_altsetting)
+- dev_warn(ddev, "config %d interface %d has no "
++ dev_notice(ddev, "config %d interface %d has no "
+ "altsetting %d\n", cfgno, inums[i], j);
+ }
+ }
+@@ -868,7 +868,7 @@ int usb_get_configuration(struct usb_device *dev)
+ int result;
+
+ if (ncfg > USB_MAXCONFIG) {
+- dev_warn(ddev, "too many configurations: %d, "
++ dev_notice(ddev, "too many configurations: %d, "
+ "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
+ dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
+ }
+@@ -902,7 +902,7 @@ int usb_get_configuration(struct usb_device *dev)
+ "descriptor/%s: %d\n", cfgno, "start", result);
+ if (result != -EPIPE)
+ goto err;
+- dev_err(ddev, "chopping to %d config(s)\n", cfgno);
++ dev_notice(ddev, "chopping to %d config(s)\n", cfgno);
+ dev->descriptor.bNumConfigurations = cfgno;
+ break;
+ } else if (result < 4) {
+@@ -934,7 +934,7 @@ int usb_get_configuration(struct usb_device *dev)
+ goto err;
+ }
+ if (result < length) {
+- dev_warn(ddev, "config index %d descriptor too short "
++ dev_notice(ddev, "config index %d descriptor too short "
+ "(expected %i, got %i)\n", cfgno, length, result);
+ length = result;
+ }
+@@ -993,7 +993,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ /* Get BOS descriptor */
+ ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE);
+ if (ret < USB_DT_BOS_SIZE || bos->bLength < USB_DT_BOS_SIZE) {
+- dev_err(ddev, "unable to get BOS descriptor or descriptor too short\n");
++ dev_notice(ddev, "unable to get BOS descriptor or descriptor too short\n");
+ if (ret >= 0)
+ ret = -ENOMSG;
+ kfree(bos);
+@@ -1021,7 +1021,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+
+ ret = usb_get_descriptor(dev, USB_DT_BOS, 0, buffer, total_len);
+ if (ret < total_len) {
+- dev_err(ddev, "unable to get BOS descriptor set\n");
++ dev_notice(ddev, "unable to get BOS descriptor set\n");
+ if (ret >= 0)
+ ret = -ENOMSG;
+ goto err;
+@@ -1046,7 +1046,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ }
+
+ if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
+- dev_warn(ddev, "descriptor type invalid, skip\n");
++ dev_notice(ddev, "descriptor type invalid, skip\n");
+ continue;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 594e50a713a04a04fc11a7dc1e5fe8f5a3e657c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Nov 2023 17:43:23 +0100
+Subject: USB: xhci-plat: fix legacy PHY double init
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit 16b7e0cccb243033de4406ffb4d892365041a1e7 ]
+
+Commits 7b8ef22ea547 ("usb: xhci: plat: Add USB phy support") and
+9134c1fd0503 ("usb: xhci: plat: Add USB 3.0 phy support") added support
+for looking up legacy PHYs from the sysdev devicetree node and
+initialising them.
+
+This broke drivers such as dwc3 which manages PHYs themself as the PHYs
+would now be initialised twice, something which specifically can lead to
+resources being left enabled during suspend (e.g. with the
+usb_phy_generic PHY driver).
+
+As the dwc3 driver uses driver-name matching for the xhci platform
+device, fix this by only looking up and initialising PHYs for devices
+that have been matched using OF.
+
+Note that checking that the platform device has a devicetree node would
+currently be sufficient, but that could lead to subtle breakages in case
+anyone ever tries to reuse an ancestor's node.
+
+Fixes: 7b8ef22ea547 ("usb: xhci: plat: Add USB phy support")
+Fixes: 9134c1fd0503 ("usb: xhci: plat: Add USB 3.0 phy support")
+Cc: stable@vger.kernel.org # 4.1
+Cc: Maxime Ripard <mripard@kernel.org>
+Cc: Stanley Chang <stanley_chang@realtek.com>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Tested-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+Tested-by: Stanley Chang <stanley_chang@realtek.com>
+Link: https://lore.kernel.org/r/20231103164323.14294-1-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-plat.c | 29 ++++++++++++++++++-----------
+ 1 file changed, 18 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
+index c9a101f0e8d01..c9438dc56f5fc 100644
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -184,7 +184,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
+ int ret;
+ int irq;
+ struct xhci_plat_priv *priv = NULL;
+-
++ bool of_match;
+
+ if (usb_disabled())
+ return -ENODEV;
+@@ -305,16 +305,23 @@ static int xhci_plat_probe(struct platform_device *pdev)
+ &xhci->imod_interval);
+ }
+
+- hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
+- if (IS_ERR(hcd->usb_phy)) {
+- ret = PTR_ERR(hcd->usb_phy);
+- if (ret == -EPROBE_DEFER)
+- goto disable_clk;
+- hcd->usb_phy = NULL;
+- } else {
+- ret = usb_phy_init(hcd->usb_phy);
+- if (ret)
+- goto disable_clk;
++ /*
++ * Drivers such as dwc3 manages PHYs themself (and rely on driver name
++ * matching for the xhci platform device).
++ */
++ of_match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
++ if (of_match) {
++ hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
++ if (IS_ERR(hcd->usb_phy)) {
++ ret = PTR_ERR(hcd->usb_phy);
++ if (ret == -EPROBE_DEFER)
++ goto disable_clk;
++ hcd->usb_phy = NULL;
++ } else {
++ ret = usb_phy_init(hcd->usb_phy);
++ if (ret)
++ goto disable_clk;
++ }
+ }
+
+ hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
+--
+2.42.0
+