From: Sasha Levin Date: Sun, 3 Dec 2023 20:07:02 +0000 (-0500) Subject: Fixes for 6.1 X-Git-Tag: v4.14.332~23^2~41 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1263e63925437f7e6f7eb41f6d5b518f5e98152e;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/cpufreq-imx6q-don-t-disable-792-mhz-opp-unnecessaril.patch b/queue-6.1/cpufreq-imx6q-don-t-disable-792-mhz-opp-unnecessaril.patch new file mode 100644 index 00000000000..b2e4b64ca9a --- /dev/null +++ b/queue-6.1/cpufreq-imx6q-don-t-disable-792-mhz-opp-unnecessaril.patch @@ -0,0 +1,49 @@ +From 9d6be54b130a08eb5a4cbc3af1e4a26db9fa155d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Nov 2023 14:41:13 +0100 +Subject: cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily + +From: Christoph Niedermaier + +[ 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 +Reviewed-by: Marek Vasut +Reviewed-by: Fabio Estevam +[ Viresh: Edited subject ] +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/cpufreq-imx6q-don-t-warn-for-disabling-a-non-existin.patch b/queue-6.1/cpufreq-imx6q-don-t-warn-for-disabling-a-non-existin.patch new file mode 100644 index 00000000000..2815446f32b --- /dev/null +++ b/queue-6.1/cpufreq-imx6q-don-t-warn-for-disabling-a-non-existin.patch @@ -0,0 +1,93 @@ +From 25a47f7db20ba653a9365e85d61575c6cd42433f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 May 2023 17:07:11 +0200 +Subject: cpufreq: imx6q: don't warn for disabling a non-existing frequency + +From: Christoph Niedermaier + +[ 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 +[ Viresh : Updated commit subject ] +Signed-off-by: Viresh Kumar +Stable-dep-of: 2e4e0984c7d6 ("cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/dpaa2-eth-increase-the-needed-headroom-to-account-fo.patch b/queue-6.1/dpaa2-eth-increase-the-needed-headroom-to-account-fo.patch new file mode 100644 index 00000000000..92dec0e5637 --- /dev/null +++ b/queue-6.1/dpaa2-eth-increase-the-needed-headroom-to-account-fo.patch @@ -0,0 +1,85 @@ +From 8848229f2cdb73218198561a653913ae250a6dc6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Nov 2023 12:28:04 +0200 +Subject: dpaa2-eth: increase the needed headroom to account for alignment + +From: Ioana Ciornei + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/drivers-perf-check-find_first_bit-return-value.patch b/queue-6.1/drivers-perf-check-find_first_bit-return-value.patch new file mode 100644 index 00000000000..3912f29e4ec --- /dev/null +++ b/queue-6.1/drivers-perf-check-find_first_bit-return-value.patch @@ -0,0 +1,72 @@ +From e391f20fb86dfb9ca968ae291feab32953b046c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Nov 2023 09:21:28 +0100 +Subject: drivers: perf: Check find_first_bit() return value + +From: Alexandre Ghiti + +[ 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] [] pmu_sbi_ovf_handler+0x3a4/0x3ae +[ 107.320112] [] handle_percpu_devid_irq+0x9e/0x1a0 +[ 107.320131] [] generic_handle_domain_irq+0x28/0x36 +[ 107.320148] [] riscv_intc_irq+0x36/0x4e +[ 107.320166] [] handle_riscv_irq+0x54/0x86 +[ 107.320189] [] 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 +Link: https://lore.kernel.org/r/20231109082128.40777-1-alexghiti@rivosinc.com +Cc: stable@vger.kernel.org +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/drm-amd-display-guard-against-invalid-rptr-wptr-bein.patch b/queue-6.1/drm-amd-display-guard-against-invalid-rptr-wptr-bein.patch new file mode 100644 index 00000000000..1bb1b55279b --- /dev/null +++ b/queue-6.1/drm-amd-display-guard-against-invalid-rptr-wptr-bein.patch @@ -0,0 +1,68 @@ +From 4e8b031b3917aec2fbed2cffadb2def89aa4da3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 16:18:44 -0400 +Subject: drm/amd/display: Guard against invalid RPTR/WPTR being set + +From: Nicholas Kazlauskas + +[ 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 +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Reviewed-by: Hansen Dsouza +Acked-by: Alex Hung +Signed-off-by: Nicholas Kazlauskas +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.1/drm-amd-display-restore-rptr-wptr-for-dmcub-as-worka.patch b/queue-6.1/drm-amd-display-restore-rptr-wptr-for-dmcub-as-worka.patch new file mode 100644 index 00000000000..9c7bec2e2bb --- /dev/null +++ b/queue-6.1/drm-amd-display-restore-rptr-wptr-for-dmcub-as-worka.patch @@ -0,0 +1,204 @@ +From 97cbc3e29b52ecd1974c0acca4dffda14364c9f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Apr 2023 23:23:37 +0800 +Subject: drm/amd/display: Restore rptr/wptr for DMCUB as workaround + +From: JinZe.Xu + +[ Upstream commit 8f3589bb6fcea397775398cba4fbcc46829a60ed ] + +[Why] +States may be desync after resume. + +[How] +Sync sw state with hw state. + +Tested-by: Daniel Wheeler +Reviewed-by: Nicholas Kazlauskas +Acked-by: Rodrigo Siqueira +Signed-off-by: JinZe.Xu +Signed-off-by: Alex Deucher +Stable-dep-of: 1ffa8602e39b ("drm/amd/display: Guard against invalid RPTR/WPTR being set") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/drm-amd-pm-fix-a-memleak-in-aldebaran_tables_init.patch b/queue-6.1/drm-amd-pm-fix-a-memleak-in-aldebaran_tables_init.patch new file mode 100644 index 00000000000..53229d310c9 --- /dev/null +++ b/queue-6.1/drm-amd-pm-fix-a-memleak-in-aldebaran_tables_init.patch @@ -0,0 +1,40 @@ +From 9d85a8d99e74b0e9d9a943240c35019c4fc7903b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Nov 2023 15:33:22 +0800 +Subject: drm/amd/pm: fix a memleak in aldebaran_tables_init + +From: Dinghao Liu + +[ 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 +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/drm-i915-call-intel_pre_plane_updates-also-for-pipes.patch b/queue-6.1/drm-i915-call-intel_pre_plane_updates-also-for-pipes.patch new file mode 100644 index 00000000000..d20fac35c78 --- /dev/null +++ b/queue-6.1/drm-i915-call-intel_pre_plane_updates-also-for-pipes.patch @@ -0,0 +1,49 @@ +From de261af876a201343f3a6185a57aeb5321ba79d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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ä + +[ 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 +Signed-off-by: Ville Syrjälä +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/fbdev-stifb-make-the-sti-next-font-pointer-a-32-bit-.patch b/queue-6.1/fbdev-stifb-make-the-sti-next-font-pointer-a-32-bit-.patch new file mode 100644 index 00000000000..af6e8765f3e --- /dev/null +++ b/queue-6.1/fbdev-stifb-make-the-sti-next-font-pointer-a-32-bit-.patch @@ -0,0 +1,39 @@ +From df847c0738e51ee9c5fcfbdd5e4041e25d691ad4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/iommu-vt-d-add-device_block_translation-helper.patch b/queue-6.1/iommu-vt-d-add-device_block_translation-helper.patch new file mode 100644 index 00000000000..40662fe53ea --- /dev/null +++ b/queue-6.1/iommu-vt-d-add-device_block_translation-helper.patch @@ -0,0 +1,132 @@ +From 2786ffccc72291601ee7a2c91fe01f1a8aa68a2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 08:29:44 +0800 +Subject: iommu/vt-d: Add device_block_translation() helper + +From: Lu Baolu + +[ 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 +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20221118132451.114406-3-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Stable-dep-of: da37dddcf4ca ("iommu/vt-d: Disable PCI ATS in legacy passthrough mode") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/iommu-vt-d-allocate-pasid-table-in-device-probe-path.patch b/queue-6.1/iommu-vt-d-allocate-pasid-table-in-device-probe-path.patch new file mode 100644 index 00000000000..78eaf9d5585 --- /dev/null +++ b/queue-6.1/iommu-vt-d-allocate-pasid-table-in-device-probe-path.patch @@ -0,0 +1,86 @@ +From ef2d0171134fcab4370bc5b399011fef7ded0644 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 08:29:43 +0800 +Subject: iommu/vt-d: Allocate pasid table in device probe path + +From: Lu Baolu + +[ 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 +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20221118132451.114406-2-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Stable-dep-of: da37dddcf4ca ("iommu/vt-d: Disable PCI ATS in legacy passthrough mode") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/iommu-vt-d-disable-pci-ats-in-legacy-passthrough-mod.patch b/queue-6.1/iommu-vt-d-disable-pci-ats-in-legacy-passthrough-mod.patch new file mode 100644 index 00000000000..9829815c374 --- /dev/null +++ b/queue-6.1/iommu-vt-d-disable-pci-ats-in-legacy-passthrough-mod.patch @@ -0,0 +1,50 @@ +From 8b16ac5945c4590f0f92c36c284317a9a3432ece Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Nov 2023 11:26:04 +0800 +Subject: iommu/vt-d: Disable PCI ATS in legacy passthrough mode + +From: Lu Baolu + +[ 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 +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20231114011036.70142-3-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/iommu-vt-d-make-context-clearing-consistent-with-con.patch b/queue-6.1/iommu-vt-d-make-context-clearing-consistent-with-con.patch new file mode 100644 index 00000000000..6ed1514714e --- /dev/null +++ b/queue-6.1/iommu-vt-d-make-context-clearing-consistent-with-con.patch @@ -0,0 +1,46 @@ +From 7be071bce67c9a014d231c46c5e22b179e46c334 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Nov 2023 11:26:05 +0800 +Subject: iommu/vt-d: Make context clearing consistent with context mapping + +From: Lu Baolu + +[ 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 +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20231114011036.70142-4-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/iommu-vt-d-omit-devtlb-invalidation-requests-when-te.patch b/queue-6.1/iommu-vt-d-omit-devtlb-invalidation-requests-when-te.patch new file mode 100644 index 00000000000..66233181a4c --- /dev/null +++ b/queue-6.1/iommu-vt-d-omit-devtlb-invalidation-requests-when-te.patch @@ -0,0 +1,69 @@ +From 2a1e4be64f281854850d6a48fb04a565ca5a7687 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Nov 2023 11:26:03 +0800 +Subject: iommu/vt-d: Omit devTLB invalidation requests when TES=0 + +From: Lu Baolu + +[ 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 +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20231114011036.70142-2-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/ipv4-igmp-fix-refcnt-uaf-issue-when-receiving-igmp-q.patch b/queue-6.1/ipv4-igmp-fix-refcnt-uaf-issue-when-receiving-igmp-q.patch new file mode 100644 index 00000000000..b4e7374484a --- /dev/null +++ b/queue-6.1/ipv4-igmp-fix-refcnt-uaf-issue-when-receiving-igmp-q.patch @@ -0,0 +1,114 @@ +From 507ea1ce1d3ecf191ee4a1fb6c1f0c25ab91db59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Nov 2023 15:13:14 +0800 +Subject: ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet + +From: Zhengchao Shao + +[ 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: + + 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) + + +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 +Reviewed-by: Eric Dumazet +Reviewed-by: Hangbin Liu +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/kvm-x86-fix-lapic-timer-interrupt-lost-after-loading.patch b/queue-6.1/kvm-x86-fix-lapic-timer-interrupt-lost-after-loading.patch new file mode 100644 index 00000000000..1d35ef775e0 --- /dev/null +++ b/queue-6.1/kvm-x86-fix-lapic-timer-interrupt-lost-after-loading.patch @@ -0,0 +1,128 @@ +From 165753f3821befe8c41a5ef6e28ec5477224625b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Sep 2023 16:55:45 -0700 +Subject: KVM: x86: Fix lapic timer interrupt lost after loading a snapshot. + +From: Haitao Shan + +[ 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 +Signed-off-by: Haitao Shan +Link: https://lore.kernel.org/r/20230913000215.478387-1-hshan@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-ravb-check-return-value-of-reset_control_deasser.patch b/queue-6.1/net-ravb-check-return-value-of-reset_control_deasser.patch new file mode 100644 index 00000000000..6b7ec9c26a9 --- /dev/null +++ b/queue-6.1/net-ravb-check-return-value-of-reset_control_deasser.patch @@ -0,0 +1,60 @@ +From 4d9cbf201fda0f1d363d63144ddcefe72663ca4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 10:04:34 +0200 +Subject: net: ravb: Check return value of reset_control_deassert() + +From: Claudiu Beznea + +[ 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 +Reviewed-by: Philipp Zabel +Signed-off-by: Claudiu Beznea +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-ravb-keep-reverse-order-of-operations-in-ravb_re.patch b/queue-6.1/net-ravb-keep-reverse-order-of-operations-in-ravb_re.patch new file mode 100644 index 00000000000..06a7c35c2e5 --- /dev/null +++ b/queue-6.1/net-ravb-keep-reverse-order-of-operations-in-ravb_re.patch @@ -0,0 +1,141 @@ +From c1a9f5c2b8c8132179bf8ad1e5d51cc3961e5332 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 10:04:39 +0200 +Subject: net: ravb: Keep reverse order of operations in ravb_remove() + +From: Claudiu Beznea + +[ 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 +Signed-off-by: Claudiu Beznea +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-ravb-make-write-access-to-cxr35-first-before-acc.patch b/queue-6.1/net-ravb-make-write-access-to-cxr35-first-before-acc.patch new file mode 100644 index 00000000000..c1998644357 --- /dev/null +++ b/queue-6.1/net-ravb-make-write-access-to-cxr35-first-before-acc.patch @@ -0,0 +1,81 @@ +From 7a13abb3de3314179b3eba584f9bb20410fccba8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Claudiu Beznea +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-ravb-start-tx-queues-after-hw-initialization-suc.patch b/queue-6.1/net-ravb-start-tx-queues-after-hw-initialization-suc.patch new file mode 100644 index 00000000000..501bdbc2c31 --- /dev/null +++ b/queue-6.1/net-ravb-start-tx-queues-after-hw-initialization-suc.patch @@ -0,0 +1,46 @@ +From d4883e94764328aace2b0dda671d8905bc69f07a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 10:04:37 +0200 +Subject: net: ravb: Start TX queues after HW initialization succeeded + +From: Claudiu Beznea + +[ 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 +Signed-off-by: Claudiu Beznea +Reviewed-by: Kalesh AP +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-ravb-stop-dma-in-case-of-failures-on-ravb_open.patch b/queue-6.1/net-ravb-stop-dma-in-case-of-failures-on-ravb_open.patch new file mode 100644 index 00000000000..86794ee7ac9 --- /dev/null +++ b/queue-6.1/net-ravb-stop-dma-in-case-of-failures-on-ravb_open.patch @@ -0,0 +1,37 @@ +From b3e91e3db92dd709fc8522d557dd5c025f0e57d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 10:04:38 +0200 +Subject: net: ravb: Stop DMA in case of failures on ravb_open() + +From: Claudiu Beznea + +[ 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 +Signed-off-by: Claudiu Beznea +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-ravb-use-pm_runtime_resume_and_get.patch b/queue-6.1/net-ravb-use-pm_runtime_resume_and_get.patch new file mode 100644 index 00000000000..5c9043c690d --- /dev/null +++ b/queue-6.1/net-ravb-use-pm_runtime_resume_and_get.patch @@ -0,0 +1,48 @@ +From 94cdf48d662cd8f2363368d4a306fa5791462ce6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 10:04:35 +0200 +Subject: net: ravb: Use pm_runtime_resume_and_get() + +From: Claudiu Beznea + +[ 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 +Signed-off-by: Claudiu Beznea +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-stmmac-xgmac-disable-fpe-mmc-interrupts.patch b/queue-6.1/net-stmmac-xgmac-disable-fpe-mmc-interrupts.patch new file mode 100644 index 00000000000..d37e66fc467 --- /dev/null +++ b/queue-6.1/net-stmmac-xgmac-disable-fpe-mmc-interrupts.patch @@ -0,0 +1,54 @@ +From 38238b33bf090323efb32d41db32f17724d42698 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 +Signed-off-by: Furong Xu <0x1207@gmail.com> +Reviewed-by: Serge Semin +Reviewed-by: Wojciech Drewek +Link: https://lore.kernel.org/r/20231125060126.2328690-1-0x1207@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/octeontx2-af-fix-possible-buffer-overflow.patch b/queue-6.1/octeontx2-af-fix-possible-buffer-overflow.patch new file mode 100644 index 00000000000..a89fd8c743a --- /dev/null +++ b/queue-6.1/octeontx2-af-fix-possible-buffer-overflow.patch @@ -0,0 +1,55 @@ +From bc372976c87c8d5b4ca00f0ab9257173c7344a6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 25 Nov 2023 00:08:02 +0300 +Subject: octeontx2-af: Fix possible buffer overflow + +From: Elena Salomatkina + +[ 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 +Reviewed-by: Simon Horman +Reviewed-by: Subbaraya Sundeep +Link: https://lore.kernel.org/r/20231124210802.109763-1-elena.salomatkina.cmc@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/octeontx2-af-install-tc-filter-rules-in-hardware-bas.patch b/queue-6.1/octeontx2-af-install-tc-filter-rules-in-hardware-bas.patch new file mode 100644 index 00000000000..44324b42404 --- /dev/null +++ b/queue-6.1/octeontx2-af-install-tc-filter-rules-in-hardware-bas.patch @@ -0,0 +1,702 @@ +From bff4941aceeb80d265fe1b0060d654a2cddf7a35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Jul 2023 10:09:25 +0530 +Subject: octeontx2-af: Install TC filter rules in hardware based on priority + +From: Suman Ghosh + +[ 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 +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/20230721043925.2627806-1-sumang@marvell.com +Signed-off-by: Paolo Abeni +Stable-dep-of: fd7f98b2e12a ("octeontx2-pf: Restore TC ingress police rules when interface is up") +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.1/octeontx2-pf-fix-adding-mbox-work-queue-entry-when-n.patch b/queue-6.1/octeontx2-pf-fix-adding-mbox-work-queue-entry-when-n.patch new file mode 100644 index 00000000000..b8b98bb7444 --- /dev/null +++ b/queue-6.1/octeontx2-pf-fix-adding-mbox-work-queue-entry-when-n.patch @@ -0,0 +1,51 @@ +From 538480c57a5e290c2f50695817dafa0a5e301531 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Subbaraya Sundeep +Link: https://lore.kernel.org/r/1700930042-5400-1-git-send-email-sbhatta@marvell.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/octeontx2-pf-restore-tc-ingress-police-rules-when-in.patch b/queue-6.1/octeontx2-pf-restore-tc-ingress-police-rules-when-in.patch new file mode 100644 index 00000000000..02ff02c8992 --- /dev/null +++ b/queue-6.1/octeontx2-pf-restore-tc-ingress-police-rules-when-in.patch @@ -0,0 +1,263 @@ +From 33a086cda6787b95c9ab3b879abd3e248070fe80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 25 Nov 2023 22:06:57 +0530 +Subject: octeontx2-pf: Restore TC ingress police rules when interface is up + +From: Subbaraya Sundeep + +[ 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 +Link: https://lore.kernel.org/r/1700930217-5707-1-git-send-email-sbhatta@marvell.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.1/pci-lengthen-reset-delay-for-videopropulsion-torrent.patch b/queue-6.1/pci-lengthen-reset-delay-for-videopropulsion-torrent.patch new file mode 100644 index 00000000000..369145add5b --- /dev/null +++ b/queue-6.1/pci-lengthen-reset-delay-for-videopropulsion-torrent.patch @@ -0,0 +1,70 @@ +From cf28a605c7e7a5873627334c64836c64c59d9195 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Sep 2023 16:23:34 +0200 +Subject: PCI: Lengthen reset delay for VideoPropulsion Torrent QN16e card + +From: Lukas Wunner + +[ 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 +Closes: https://lore.kernel.org/linux-pci/DM6PR16MB2844903E34CAB910082DF019B1FAA@DM6PR16MB2844.namprd16.prod.outlook.com/ +Tested-by: Chad Schroeder +Signed-off-by: Lukas Wunner +Signed-off-by: Bjorn Helgaas +Cc: stable@vger.kernel.org # v5.4+ +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/pci-qcom-ep-add-dedicated-callback-for-writing-to-db.patch b/queue-6.1/pci-qcom-ep-add-dedicated-callback-for-writing-to-db.patch new file mode 100644 index 00000000000..ad1e5906ff9 --- /dev/null +++ b/queue-6.1/pci-qcom-ep-add-dedicated-callback-for-writing-to-db.patch @@ -0,0 +1,82 @@ +From 9e558c21c1c826b108b76d4155de58b8f8ae3b5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/linux-pci/20231025130029.74693-2-manivannan.sadhasivam@linaro.org +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: Serge Semin +Cc: stable@vger.kernel.org # 5.16+ +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/powerpc-pseries-iommu-enable_ddw-incorrectly-returns.patch b/queue-6.1/powerpc-pseries-iommu-enable_ddw-incorrectly-returns.patch new file mode 100644 index 00000000000..14ea0431db0 --- /dev/null +++ b/queue-6.1/powerpc-pseries-iommu-enable_ddw-incorrectly-returns.patch @@ -0,0 +1,74 @@ +From 4df071627fb4624e8327d931278e835914f40deb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Michael Ellerman +Link: https://msgid.link/20231003030802.47914-1-gbatra@linux.vnet.ibm.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/r8169-prevent-potential-deadlock-in-rtl8169_close.patch b/queue-6.1/r8169-prevent-potential-deadlock-in-rtl8169_close.patch new file mode 100644 index 00000000000..6258c9fd3e1 --- /dev/null +++ b/queue-6.1/r8169-prevent-potential-deadlock-in-rtl8169_close.patch @@ -0,0 +1,51 @@ +From bdc481a48c03698a02ef11eb49229620255ca6b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Nov 2023 23:01:02 +0100 +Subject: r8169: prevent potential deadlock in rtl8169_close + +From: Heiner Kallweit + +[ 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 +Link: https://lore.kernel.org/r/12395867-1d17-4cac-aa7d-c691938fcddf@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/ravb-fix-races-between-ravb_tx_timeout_work-and-net-.patch b/queue-6.1/ravb-fix-races-between-ravb_tx_timeout_work-and-net-.patch new file mode 100644 index 00000000000..4cacb5bf0b6 --- /dev/null +++ b/queue-6.1/ravb-fix-races-between-ravb_tx_timeout_work-and-net-.patch @@ -0,0 +1,79 @@ +From 90d55a0f6a8936258f1bdd4dbde4c2890bce894a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Sergey Shtylyov +Link: https://lore.kernel.org/r/20231127122420.3706751-1-yoshihiro.shimoda.uh@renesas.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/s390-cmma-fix-handling-of-swapper_pg_dir-and-invalid.patch b/queue-6.1/s390-cmma-fix-handling-of-swapper_pg_dir-and-invalid.patch new file mode 100644 index 00000000000..480eba6ffe9 --- /dev/null +++ b/queue-6.1/s390-cmma-fix-handling-of-swapper_pg_dir-and-invalid.patch @@ -0,0 +1,50 @@ +From 7e345172ed606a5193d78ef0664b6061754fbee8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: +Reviewed-by: Claudio Imbrenda +Signed-off-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/selftests-net-fix-a-char-signedness-issue.patch b/queue-6.1/selftests-net-fix-a-char-signedness-issue.patch new file mode 100644 index 00000000000..761414b66c3 --- /dev/null +++ b/queue-6.1/selftests-net-fix-a-char-signedness-issue.patch @@ -0,0 +1,50 @@ +From d2208fab18b552fac856775254d212b6f7799072 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Nov 2023 12:15:20 -0500 +Subject: selftests/net: fix a char signedness issue + +From: Willem de Bruijn + +[ 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 +Link: https://lore.kernel.org/r/20231124171645.1011043-3-willemdebruijn.kernel@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/selftests-net-ipsec-fix-constant-out-of-range.patch b/queue-6.1/selftests-net-ipsec-fix-constant-out-of-range.patch new file mode 100644 index 00000000000..fcce94f35db --- /dev/null +++ b/queue-6.1/selftests-net-ipsec-fix-constant-out-of-range.patch @@ -0,0 +1,56 @@ +From 6582ef1545c8deb9ea112b435f8c3d376ab03dc7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Nov 2023 12:15:19 -0500 +Subject: selftests/net: ipsec: fix constant out of range + +From: Willem de Bruijn + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/selftests-net-mptcp-fix-uninitialized-variable-warni.patch b/queue-6.1/selftests-net-mptcp-fix-uninitialized-variable-warni.patch new file mode 100644 index 00000000000..7c060ba7dde --- /dev/null +++ b/queue-6.1/selftests-net-mptcp-fix-uninitialized-variable-warni.patch @@ -0,0 +1,110 @@ +From ea7ef9e9a478dbef10030a05fcb024d5e830c41d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Nov 2023 12:15:22 -0500 +Subject: selftests/net: mptcp: fix uninitialized variable warnings + +From: Willem de Bruijn + +[ 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 +Signed-off-by: Willem de Bruijn + +---- + +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 + +Link: https://lore.kernel.org/r/20231124171645.1011043-5-willemdebruijn.kernel@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + #include ++#include + #include + #include + #include +@@ -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 + + #include ++#include + #include + #include + #include +@@ -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 + diff --git a/queue-6.1/selftests-net-unix-fix-unused-variable-compiler-warn.patch b/queue-6.1/selftests-net-unix-fix-unused-variable-compiler-warn.patch new file mode 100644 index 00000000000..21cdea251d1 --- /dev/null +++ b/queue-6.1/selftests-net-unix-fix-unused-variable-compiler-warn.patch @@ -0,0 +1,39 @@ +From 058d5e24fafae82d2bc29bfd36f507a99382061b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Nov 2023 12:15:21 -0500 +Subject: selftests/net: unix: fix unused variable compiler warning + +From: Willem de Bruijn + +[ 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 +Link: https://lore.kernel.org/r/20231124171645.1011043-4-willemdebruijn.kernel@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/series b/queue-6.1/series index 4857044d09a..e5f7c9a9925 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -51,3 +51,45 @@ input-xpad-add-hyperx-clutch-gladiate-support.patch 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 diff --git a/queue-6.1/spi-fix-null-dereference-on-suspend.patch b/queue-6.1/spi-fix-null-dereference-on-suspend.patch new file mode 100644 index 00000000000..f6bd0495ee0 --- /dev/null +++ b/queue-6.1/spi-fix-null-dereference-on-suspend.patch @@ -0,0 +1,153 @@ +From 909c42cc0de2432e35c3f1c1574b3c7c5910b089 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Nov 2023 14:47:43 -0700 +Subject: spi: Fix null dereference on suspend + +From: Mark Hasemeyer + +[ 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 +Link: https://lore.kernel.org/r/20231107144743.v1.1.I7987f05f61901f567f7661763646cb7d7919b528@changeid +Signed-off-by: Mark Brown +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/uapi-propagate-__struct_group-attributes-to-the-cont.patch b/queue-6.1/uapi-propagate-__struct_group-attributes-to-the-cont.patch new file mode 100644 index 00000000000..51307a2c0e2 --- /dev/null +++ b/queue-6.1/uapi-propagate-__struct_group-attributes-to-the-cont.patch @@ -0,0 +1,79 @@ +From 24e3539cd9020756bca8e2eb222f7bca08728a87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Nov 2023 14:05:08 +0300 +Subject: uapi: propagate __struct_group() attributes to the container union + +From: Dmitry Antipov + +[ 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 +Closes: https://lore.kernel.org/oe-kbuild-all/202311150821.cI4yciFE-lkp@intel.com +Signed-off-by: Dmitry Antipov +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/usb-config-fix-iteration-issue-in-usb_get_bos_descri.patch b/queue-6.1/usb-config-fix-iteration-issue-in-usb_get_bos_descri.patch new file mode 100644 index 00000000000..9d96446244f --- /dev/null +++ b/queue-6.1/usb-config-fix-iteration-issue-in-usb_get_bos_descri.patch @@ -0,0 +1,57 @@ +From 9614a90f3a4e983c306addc2b31420f7d660d752 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Nov 2023 14:13:25 +0200 +Subject: usb: config: fix iteration issue in 'usb_get_bos_descriptor()' + +From: Niklas Neronin + +[ 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 +Acked-by: Mathias Nyman +Reviewed-by: Alan Stern +Link: https://lore.kernel.org/r/20231115121325.471454-1-niklas.neronin@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/usb-core-change-configuration-warnings-to-notices.patch b/queue-6.1/usb-core-change-configuration-warnings-to-notices.patch new file mode 100644 index 00000000000..7127d5d27f8 --- /dev/null +++ b/queue-6.1/usb-core-change-configuration-warnings-to-notices.patch @@ -0,0 +1,401 @@ +From 6d31be806213ae4fcad830df353e0cefbeed4c42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 14:13:19 -0400 +Subject: USB: core: Change configuration warnings to notices + +From: Alan Stern + +[ 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 +Signed-off-by: Alan Stern +Link: https://lore.kernel.org/r/Y2KzPx0h6z1jXCuN@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 974bba5c118f ("usb: config: fix iteration issue in 'usb_get_bos_descriptor()'") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/usb-xhci-plat-fix-legacy-phy-double-init.patch b/queue-6.1/usb-xhci-plat-fix-legacy-phy-double-init.patch new file mode 100644 index 00000000000..34c694c6d45 --- /dev/null +++ b/queue-6.1/usb-xhci-plat-fix-legacy-phy-double-init.patch @@ -0,0 +1,92 @@ +From 594e50a713a04a04fc11a7dc1e5fe8f5a3e657c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Nov 2023 17:43:23 +0100 +Subject: USB: xhci-plat: fix legacy PHY double init + +From: Johan Hovold + +[ 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 +Cc: Stanley Chang +Signed-off-by: Johan Hovold +Tested-by: Stefan Eichenberger +Tested-by: Stanley Chang +Link: https://lore.kernel.org/r/20231103164323.14294-1-johan+linaro@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 +