--- /dev/null
+From 7b32286981d332a4970cd8847bdf3808f229908e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 16:37:47 +0800
+Subject: i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit b795e68bf3073d67bebbb5a44d93f49efc5b8cc7 ]
+
+The logic used to abort the DMA ring contains several flaws:
+
+ 1. The driver unconditionally issues a ring abort even when the ring has
+ already stopped.
+ 2. The completion used to wait for abort completion is never
+ re-initialized, resulting in incorrect wait behavior.
+ 3. The abort sequence unintentionally clears RING_CTRL_ENABLE, which
+ resets hardware ring pointers and disrupts the controller state.
+ 4. If the ring is already stopped, the abort operation should be
+ considered successful without attempting further action.
+
+Fix the abort handling by checking whether the ring is running before
+issuing an abort, re-initializing the completion when needed, ensuring that
+RING_CTRL_ENABLE remains asserted during abort, and treating an already
+stopped ring as a successful condition.
+
+Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20260306072451.11131-9-adrian.hunter@intel.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Jianqiang kang <jianqkang@sina.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/mipi-i3c-hci/dma.c | 27 +++++++++++++++++----------
+ 1 file changed, 17 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
+index 168b21f6cf37c..d6678bee725b6 100644
+--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
+@@ -448,16 +448,23 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
+ struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number];
+ unsigned int i;
+ bool did_unqueue = false;
+-
+- /* stop the ring */
+- rh_reg_write(RING_CONTROL, RING_CTRL_ABORT);
+- if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) {
+- /*
+- * We're deep in it if ever this condition is ever met.
+- * Hardware might still be writing to memory, etc.
+- */
+- dev_crit(&hci->master.dev, "unable to abort the ring\n");
+- WARN_ON(1);
++ u32 ring_status;
++
++ ring_status = rh_reg_read(RING_STATUS);
++ if (ring_status & RING_STATUS_RUNNING) {
++ /* stop the ring */
++ reinit_completion(&rh->op_done);
++ rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);
++ wait_for_completion_timeout(&rh->op_done, HZ);
++ ring_status = rh_reg_read(RING_STATUS);
++ if (ring_status & RING_STATUS_RUNNING) {
++ /*
++ * We're deep in it if ever this condition is ever met.
++ * Hardware might still be writing to memory, etc.
++ */
++ dev_crit(&hci->master.dev, "unable to abort the ring\n");
++ WARN_ON(1);
++ }
+ }
+
+ for (i = 0; i < n; i++) {
+--
+2.53.0
+
kvm-x86-acquire-srcu-in-kvm_get_mp_state-to-protect-.patch
revert-s390-cio-fix-device-lifecycle-handling-in-css.patch
smb-client-reject-userspace-cifs.spnego-descriptions.patch
+i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in.patch
--- /dev/null
+From 65cff8906fcf152c60bf7130fb4004824dc54288 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 14:21:07 +0800
+Subject: i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit b795e68bf3073d67bebbb5a44d93f49efc5b8cc7 ]
+
+The logic used to abort the DMA ring contains several flaws:
+
+ 1. The driver unconditionally issues a ring abort even when the ring has
+ already stopped.
+ 2. The completion used to wait for abort completion is never
+ re-initialized, resulting in incorrect wait behavior.
+ 3. The abort sequence unintentionally clears RING_CTRL_ENABLE, which
+ resets hardware ring pointers and disrupts the controller state.
+ 4. If the ring is already stopped, the abort operation should be
+ considered successful without attempting further action.
+
+Fix the abort handling by checking whether the ring is running before
+issuing an abort, re-initializing the completion when needed, ensuring that
+RING_CTRL_ENABLE remains asserted during abort, and treating an already
+stopped ring as a successful condition.
+
+Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20260306072451.11131-9-adrian.hunter@intel.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Jianqiang kang <jianqkang@sina.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/mipi-i3c-hci/dma.c | 27 +++++++++++++++++----------
+ 1 file changed, 17 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
+index 624d00b853a51..61007167606fd 100644
+--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
+@@ -448,16 +448,23 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
+ struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number];
+ unsigned int i;
+ bool did_unqueue = false;
+-
+- /* stop the ring */
+- rh_reg_write(RING_CONTROL, RING_CTRL_ABORT);
+- if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) {
+- /*
+- * We're deep in it if ever this condition is ever met.
+- * Hardware might still be writing to memory, etc.
+- */
+- dev_crit(&hci->master.dev, "unable to abort the ring\n");
+- WARN_ON(1);
++ u32 ring_status;
++
++ ring_status = rh_reg_read(RING_STATUS);
++ if (ring_status & RING_STATUS_RUNNING) {
++ /* stop the ring */
++ reinit_completion(&rh->op_done);
++ rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);
++ wait_for_completion_timeout(&rh->op_done, HZ);
++ ring_status = rh_reg_read(RING_STATUS);
++ if (ring_status & RING_STATUS_RUNNING) {
++ /*
++ * We're deep in it if ever this condition is ever met.
++ * Hardware might still be writing to memory, etc.
++ */
++ dev_crit(&hci->master.dev, "unable to abort the ring\n");
++ WARN_ON(1);
++ }
+ }
+
+ for (i = 0; i < n; i++) {
+--
+2.53.0
+
revert-x86-vdso-fix-output-operand-size-of-rdpid.patch
revert-s390-cio-fix-device-lifecycle-handling-in-css.patch
smb-client-reject-userspace-cifs.spnego-descriptions.patch
+i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in.patch
--- /dev/null
+From 39bda3851566c41919488aecade3f727e3a3696d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:24:40 +0000
+Subject: arm64: Kconfig: Remove selecting replaced HAVE_FUNCTION_GRAPH_RETVAL
+
+From: Lukas Bulwahn <lukas.bulwahn@redhat.com>
+
+commit f458b2165d7ac0f2401fff48f19c8f864e7e1e38 upstream.
+
+Commit a3ed4157b7d8 ("fgraph: Replace fgraph_ret_regs with ftrace_regs")
+replaces the config HAVE_FUNCTION_GRAPH_RETVAL with the config
+HAVE_FUNCTION_GRAPH_FREGS, and it replaces all the select commands in the
+various architecture Kconfig files. In the arm64 architecture, the commit
+adds the 'select HAVE_FUNCTION_GRAPH_FREGS', but misses to remove the
+'select HAVE_FUNCTION_GRAPH_RETVAL', i.e., the select on the replaced
+config.
+
+Remove selecting the replaced config. No functional change, just cleanup.
+
+Fixes: a3ed4157b7d8 ("fgraph: Replace fgraph_ret_regs with ftrace_regs")
+Signed-off-by: Lukas Bulwahn <lukas.bulwahn@redhat.com>
+Link: https://lore.kernel.org/r/20250117125522.99071-1-lukas.bulwahn@redhat.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/Kconfig | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index f487c5e21e2f1..d4ebdc16cdb4f 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -219,7 +219,6 @@ config ARM64
+ select HAVE_FUNCTION_ERROR_INJECTION
+ select HAVE_FUNCTION_GRAPH_FREGS
+ select HAVE_FUNCTION_GRAPH_TRACER
+- select HAVE_FUNCTION_GRAPH_RETVAL
+ select HAVE_GCC_PLUGINS
+ select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \
+ HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI
+--
+2.53.0
+
--- /dev/null
+From b0c77c3a6481a24fcdf012f078666dcff4bf3c00 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 10:22:30 +0800
+Subject: hwmon: (pmbus/core) Protect regulator operations with mutex
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 754bd2b4a084b90b5e7b630e1f423061a9b9b761 ]
+
+The regulator operations pmbus_regulator_get_voltage(),
+pmbus_regulator_set_voltage(), and pmbus_regulator_list_voltage()
+access PMBus registers and shared data but were not protected by
+the update_lock mutex. This could lead to race conditions.
+
+However, adding mutex protection directly to these functions causes
+a deadlock because pmbus_regulator_notify() (which calls
+regulator_notifier_call_chain()) is often called with the mutex
+already held (e.g., from pmbus_fault_handler()). If a regulator
+callback then calls one of the now-protected voltage functions,
+it will attempt to acquire the same mutex.
+
+Rework pmbus_regulator_notify() to utilize a worker function to
+send notifications outside of the mutex protection. Events are
+stored as atomics in a per-page bitmask and processed by the worker.
+
+Initialize the worker and its associated data during regulator
+registration, and ensure it is cancelled on device removal using
+devm_add_action_or_reset().
+
+While at it, remove the unnecessary include of linux/of.h.
+
+Cc: Sanman Pradhan <psanman@juniper.net>
+Fixes: ddbb4db4ced1b ("hwmon: (pmbus) Add regulator support")
+Reviewed-by: Sanman Pradhan <psanman@juniper.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Fang Wang <32840572@qq.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 117 ++++++++++++++++++++++++-------
+ 1 file changed, 91 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index 41c66ece5177e..e37fd206510a6 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -6,6 +6,7 @@
+ * Copyright (c) 2012 Guenter Roeck
+ */
+
++#include <linux/atomic.h>
+ #include <linux/debugfs.h>
+ #include <linux/delay.h>
+ #include <linux/kernel.h>
+@@ -20,8 +21,8 @@
+ #include <linux/pmbus.h>
+ #include <linux/regulator/driver.h>
+ #include <linux/regulator/machine.h>
+-#include <linux/of.h>
+ #include <linux/thermal.h>
++#include <linux/workqueue.h>
+ #include "pmbus.h"
+
+ /*
+@@ -102,6 +103,11 @@ struct pmbus_data {
+
+ struct mutex update_lock;
+
++#if IS_ENABLED(CONFIG_REGULATOR)
++ atomic_t regulator_events[PMBUS_PAGES];
++ struct work_struct regulator_notify_work;
++#endif
++
+ bool has_status_word; /* device uses STATUS_WORD register */
+ int (*read_status)(struct i2c_client *client, int page);
+
+@@ -3181,12 +3187,19 @@ static int pmbus_regulator_get_voltage(struct regulator_dev *rdev)
+ .class = PSC_VOLTAGE_OUT,
+ .convert = true,
+ };
++ int ret;
+
++ mutex_lock(&data->update_lock);
+ s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_READ_VOUT);
+- if (s.data < 0)
+- return s.data;
++ if (s.data < 0) {
++ ret = s.data;
++ goto unlock;
++ }
+
+- return (int)pmbus_reg2data(data, &s) * 1000; /* unit is uV */
++ ret = (int)pmbus_reg2data(data, &s) * 1000; /* unit is uV */
++unlock:
++ mutex_unlock(&data->update_lock);
++ return ret;
+ }
+
+ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
+@@ -3203,16 +3216,22 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
+ };
+ int val = DIV_ROUND_CLOSEST(min_uv, 1000); /* convert to mV */
+ int low, high;
++ int ret;
+
+ *selector = 0;
+
++ mutex_lock(&data->update_lock);
+ low = pmbus_regulator_get_low_margin(client, s.page);
+- if (low < 0)
+- return low;
++ if (low < 0) {
++ ret = low;
++ goto unlock;
++ }
+
+ high = pmbus_regulator_get_high_margin(client, s.page);
+- if (high < 0)
+- return high;
++ if (high < 0) {
++ ret = high;
++ goto unlock;
++ }
+
+ /* Make sure we are within margins */
+ if (low > val)
+@@ -3222,7 +3241,10 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
+
+ val = pmbus_data2reg(data, &s, val);
+
+- return _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, (u16)val);
++ ret = _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, (u16)val);
++unlock:
++ mutex_unlock(&data->update_lock);
++ return ret;
+ }
+
+ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
+@@ -3230,7 +3252,9 @@ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
+ {
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
++ struct pmbus_data *data = i2c_get_clientdata(client);
+ int val, low, high;
++ int ret;
+
+ if (selector >= rdev->desc->n_voltages ||
+ selector < rdev->desc->linear_min_sel)
+@@ -3240,18 +3264,29 @@ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
+ val = DIV_ROUND_CLOSEST(rdev->desc->min_uV +
+ (rdev->desc->uV_step * selector), 1000); /* convert to mV */
+
++ mutex_lock(&data->update_lock);
++
+ low = pmbus_regulator_get_low_margin(client, rdev_get_id(rdev));
+- if (low < 0)
+- return low;
++ if (low < 0) {
++ ret = low;
++ goto unlock;
++ }
+
+ high = pmbus_regulator_get_high_margin(client, rdev_get_id(rdev));
+- if (high < 0)
+- return high;
++ if (high < 0) {
++ ret = high;
++ goto unlock;
++ }
+
+- if (val >= low && val <= high)
+- return val * 1000; /* unit is uV */
++ if (val >= low && val <= high) {
++ ret = val * 1000; /* unit is uV */
++ goto unlock;
++ }
+
+- return 0;
++ ret = 0;
++unlock:
++ mutex_unlock(&data->update_lock);
++ return ret;
+ }
+
+ const struct regulator_ops pmbus_regulator_ops = {
+@@ -3266,12 +3301,42 @@ const struct regulator_ops pmbus_regulator_ops = {
+ };
+ EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, PMBUS);
+
++static void pmbus_regulator_notify_work_cancel(void *data)
++{
++ struct pmbus_data *pdata = data;
++
++ cancel_work_sync(&pdata->regulator_notify_work);
++}
++
++static void pmbus_regulator_notify_worker(struct work_struct *work)
++{
++ struct pmbus_data *data =
++ container_of(work, struct pmbus_data, regulator_notify_work);
++ int i, j;
++
++ for (i = 0; i < data->info->pages; i++) {
++ int event;
++
++ event = atomic_xchg(&data->regulator_events[i], 0);
++ if (!event)
++ continue;
++
++ for (j = 0; j < data->info->num_regulators; j++) {
++ if (i == rdev_get_id(data->rdevs[j])) {
++ regulator_notifier_call_chain(data->rdevs[j],
++ event, NULL);
++ break;
++ }
++ }
++ }
++}
++
+ static int pmbus_regulator_register(struct pmbus_data *data)
+ {
+ struct device *dev = data->dev;
+ const struct pmbus_driver_info *info = data->info;
+ const struct pmbus_platform_data *pdata = dev_get_platdata(dev);
+- int i;
++ int i, ret;
+
+ data->rdevs = devm_kzalloc(dev, sizeof(struct regulator_dev *) * info->num_regulators,
+ GFP_KERNEL);
+@@ -3295,20 +3360,20 @@ static int pmbus_regulator_register(struct pmbus_data *data)
+ info->reg_desc[i].name);
+ }
+
++ INIT_WORK(&data->regulator_notify_work, pmbus_regulator_notify_worker);
++
++ ret = devm_add_action_or_reset(dev, pmbus_regulator_notify_work_cancel, data);
++ if (ret)
++ return ret;
++
+ return 0;
+ }
+
+ static int pmbus_regulator_notify(struct pmbus_data *data, int page, int event)
+ {
+- int j;
+-
+- for (j = 0; j < data->info->num_regulators; j++) {
+- if (page == rdev_get_id(data->rdevs[j])) {
+- regulator_notifier_call_chain(data->rdevs[j], event, NULL);
+- break;
+- }
+- }
+- return 0;
++ atomic_or(event, &data->regulator_events[page]);
++ schedule_work(&data->regulator_notify_work);
++ return 0;
+ }
+ #else
+ static int pmbus_regulator_register(struct pmbus_data *data)
+--
+2.53.0
+
--- /dev/null
+From 840018a00e1073ee50daf3f11644707b6c5bc9a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 14:19:33 +0800
+Subject: i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit b795e68bf3073d67bebbb5a44d93f49efc5b8cc7 ]
+
+The logic used to abort the DMA ring contains several flaws:
+
+ 1. The driver unconditionally issues a ring abort even when the ring has
+ already stopped.
+ 2. The completion used to wait for abort completion is never
+ re-initialized, resulting in incorrect wait behavior.
+ 3. The abort sequence unintentionally clears RING_CTRL_ENABLE, which
+ resets hardware ring pointers and disrupts the controller state.
+ 4. If the ring is already stopped, the abort operation should be
+ considered successful without attempting further action.
+
+Fix the abort handling by checking whether the ring is running before
+issuing an abort, re-initializing the completion when needed, ensuring that
+RING_CTRL_ENABLE remains asserted during abort, and treating an already
+stopped ring as a successful condition.
+
+Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20260306072451.11131-9-adrian.hunter@intel.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Jianqiang kang <jianqkang@sina.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/mipi-i3c-hci/dma.c | 27 +++++++++++++++++----------
+ 1 file changed, 17 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
+index b9496e8c4784d..44461f13b54cd 100644
+--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
+@@ -457,16 +457,23 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
+ struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number];
+ unsigned int i;
+ bool did_unqueue = false;
+-
+- /* stop the ring */
+- rh_reg_write(RING_CONTROL, RING_CTRL_ABORT);
+- if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) {
+- /*
+- * We're deep in it if ever this condition is ever met.
+- * Hardware might still be writing to memory, etc.
+- */
+- dev_crit(&hci->master.dev, "unable to abort the ring\n");
+- WARN_ON(1);
++ u32 ring_status;
++
++ ring_status = rh_reg_read(RING_STATUS);
++ if (ring_status & RING_STATUS_RUNNING) {
++ /* stop the ring */
++ reinit_completion(&rh->op_done);
++ rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);
++ wait_for_completion_timeout(&rh->op_done, HZ);
++ ring_status = rh_reg_read(RING_STATUS);
++ if (ring_status & RING_STATUS_RUNNING) {
++ /*
++ * We're deep in it if ever this condition is ever met.
++ * Hardware might still be writing to memory, etc.
++ */
++ dev_crit(&hci->master.dev, "unable to abort the ring\n");
++ WARN_ON(1);
++ }
+ }
+
+ for (i = 0; i < n; i++) {
+--
+2.53.0
+
--- /dev/null
+From 4143b816f34d1f9422e57b4c2f0de6445cb720f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:24:01 +0000
+Subject: iommu/vt-d: Draining PRQ in sva unbind path when FPD bit set
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+commit cf08ca81d08a04b3b304e8fb4e052f323a09783d upstream.
+
+When a device uses a PASID for SVA (Shared Virtual Address), it's possible
+that the PASID entry is marked as non-present and FPD bit set before the
+device flushes all ongoing DMA requests and removes the SVA domain. This
+can occur when an exception happens and the process terminates before the
+device driver stops DMA and calls the iommu driver to unbind the PASID.
+
+There's no need to drain the PRQ in the mm release path. Instead, the PRQ
+will be drained in the SVA unbind path. But in such case,
+intel_pasid_tear_down_entry() only checks the presence of the pasid entry
+and returns directly.
+
+Add the code to clear the FPD bit and drain the PRQ.
+
+Fixes: c43e1ccdebf2 ("iommu/vt-d: Drain PRQs when domain removed from RID")
+Suggested-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20241217024240.139615-1-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/pasid.c | 22 +++++++++++++++++++++-
+ drivers/iommu/intel/pasid.h | 6 ++++++
+ 2 files changed, 27 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
+index 3d1d43675bf22..74be6b547fc0c 100644
+--- a/drivers/iommu/intel/pasid.c
++++ b/drivers/iommu/intel/pasid.c
+@@ -245,11 +245,31 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
+
+ spin_lock(&iommu->lock);
+ pte = intel_pasid_get_entry(dev, pasid);
+- if (WARN_ON(!pte) || !pasid_pte_is_present(pte)) {
++ if (WARN_ON(!pte)) {
+ spin_unlock(&iommu->lock);
+ return;
+ }
+
++ if (!pasid_pte_is_present(pte)) {
++ if (!pasid_pte_is_fault_disabled(pte)) {
++ WARN_ON(READ_ONCE(pte->val[0]) != 0);
++ spin_unlock(&iommu->lock);
++ return;
++ }
++
++ /*
++ * When a PASID is used for SVA by a device, it's possible
++ * that the pasid entry is non-present with the Fault
++ * Processing Disabled bit set. Clear the pasid entry and
++ * drain the PRQ for the PASID before return.
++ */
++ pasid_clear_entry(pte);
++ spin_unlock(&iommu->lock);
++ intel_iommu_drain_pasid_prq(dev, pasid);
++
++ return;
++ }
++
+ did = pasid_get_domain_id(pte);
+ pgtt = pasid_pte_get_pgtt(pte);
+ pasid_clear_present(pte);
+diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
+index 55cad7bfa294e..8ffb01163f0e6 100644
+--- a/drivers/iommu/intel/pasid.h
++++ b/drivers/iommu/intel/pasid.h
+@@ -80,6 +80,12 @@ static inline bool pasid_pte_is_present(struct pasid_entry *pte)
+ return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
+ }
+
++/* Get FPD(Fault Processing Disable) bit of a PASID table entry */
++static inline bool pasid_pte_is_fault_disabled(struct pasid_entry *pte)
++{
++ return READ_ONCE(pte->val[0]) & PASID_PTE_FPD;
++}
++
+ /* Get PGTT field of a PASID table entry */
+ static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
+ {
+--
+2.53.0
+
--- /dev/null
+From eefae856833005cae6b15cc7bb544820027cf712 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:21:20 +0000
+Subject: net/mlx5e: Trigger neighbor resolution for unresolved destinations
+
+From: Jianbo Liu <jianbol@nvidia.com>
+
+commit 9ab89bde13e5251e1d0507e1cc426edcdfe19142 upstream.
+
+When initializing the MAC addresses for an outbound IPsec packet offload
+rule in mlx5e_ipsec_init_macs, the call to dst_neigh_lookup is used to
+find the next-hop neighbor (typically the gateway in tunnel mode).
+This call might create a new neighbor entry if one doesn't already
+exist. This newly created entry starts in the INCOMPLETE state, as the
+kernel hasn't yet sent an ARP or NDISC probe to resolve the MAC
+address. In this case, neigh_ha_snapshot will correctly return an
+all-zero MAC address.
+
+IPsec packet offload requires the actual next-hop MAC address to
+program the rule correctly. If the neighbor state is INCOMPLETE when
+the rule is created, the hardware rule is programmed with an all-zero
+destination MAC address. Packets sent using this rule will be
+subsequently dropped by the receiving network infrastructure or host.
+
+This patch adds a check specifically for the outbound offload path. If
+neigh_ha_snapshot returns an all-zero MAC address, it proactively
+calls neigh_event_send(n, NULL). This ensures the kernel immediately
+sends the initial ARP or NDISC probe if one isn't already pending,
+accelerating the resolution process. This helps prevent the hardware
+rule from being programmed with an invalid MAC address and avoids
+packet drops due to unresolved neighbors.
+
+Fixes: 71670f766b8f ("net/mlx5e: Support routed networks during IPsec MACs initialization")
+Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
+Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/1765284977-1363052-8-git-send-email-tariqt@nvidia.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+index 486f05112f5a6..e2915d3143e6b 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+@@ -365,6 +365,9 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
+
+ neigh_ha_snapshot(addr, n, netdev);
+ ether_addr_copy(dst, addr);
++ if (attrs->dir == XFRM_DEV_OFFLOAD_OUT &&
++ is_zero_ether_addr(addr))
++ neigh_event_send(n, NULL);
+ dst_release(rt_dst_entry);
+ neigh_release(n);
+ return;
+--
+2.53.0
+
--- /dev/null
+From e36c6858da13c57ce6af47635049cc0342db4c12 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:22:14 +0000
+Subject: net/mlx5e: Use ip6_dst_lookup instead of ipv6_dst_lookup_flow for MAC
+ init
+
+From: Jianbo Liu <jianbol@nvidia.com>
+
+commit e35d7da8dd9e55b37c3e8ab548f6793af0c2ab49 upstream.
+
+Replace ipv6_stub->ipv6_dst_lookup_flow() with ip6_dst_lookup() in
+mlx5e_ipsec_init_macs() since IPsec transformations are not needed
+during Security Association setup - only basic routing information is
+required for nexthop MAC address resolution.
+
+This resolves an issue where XfrmOutNoStates error counter would be
+incremented when xfrm policy is configured before xfrm state, as the
+IPsec-aware routing function would attempt policy checks during SA
+initialization.
+
+Fixes: 71670f766b8f ("net/mlx5e: Support routed networks during IPsec MACs initialization")
+Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
+Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/1765284977-1363052-7-git-send-email-tariqt@nvidia.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+index e2915d3143e6b..c1b6893389fdf 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+@@ -348,9 +348,8 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
+ rt_dst_entry = &rt->dst;
+ break;
+ case AF_INET6:
+- rt_dst_entry = ipv6_stub->ipv6_dst_lookup_flow(
+- dev_net(netdev), NULL, &fl6, NULL);
+- if (IS_ERR(rt_dst_entry))
++ if (!IS_ENABLED(CONFIG_IPV6) ||
++ ip6_dst_lookup(dev_net(netdev), NULL, &rt_dst_entry, &fl6))
+ goto neigh;
+ break;
+ default:
+--
+2.53.0
+
--- /dev/null
+From 81f79355bf3e5904a5f34f00e759683ba4325e38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 20:20:06 -0700
+Subject: perf parse-events: Expose/rename config_term_name
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit d2f3ecb0ca2099d13bf8bf69219214c1425dc453 ]
+
+Expose config_term_name as parse_events__term_type_str so that PMUs not
+in pmu.c may access it.
+
+Signed-off-by: Ian Rogers <irogers@google.com>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Link: https://lore.kernel.org/r/20241002032016.333748-4-irogers@google.com
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/parse-events.c | 20 +++++++++++---------
+ tools/perf/util/parse-events.h | 2 ++
+ 2 files changed, 13 insertions(+), 9 deletions(-)
+
+diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
+index fcc4dab618bee..3d221608b13a5 100644
+--- a/tools/perf/util/parse-events.c
++++ b/tools/perf/util/parse-events.c
+@@ -801,7 +801,7 @@ static int check_type_val(struct parse_events_term *term,
+
+ static bool config_term_shrinked;
+
+-static const char *config_term_name(enum parse_events__term_type term_type)
++const char *parse_events__term_type_str(enum parse_events__term_type term_type)
+ {
+ /*
+ * Update according to parse-events.l
+@@ -887,7 +887,7 @@ config_term_avail(enum parse_events__term_type term_type, struct parse_events_er
+
+ /* term_type is validated so indexing is safe */
+ if (asprintf(&err_str, "'%s' is not usable in 'perf stat'",
+- config_term_name(term_type)) >= 0)
++ parse_events__term_type_str(term_type)) >= 0)
+ parse_events_error__handle(err, -1, err_str, NULL);
+ return false;
+ }
+@@ -1011,7 +1011,7 @@ do { \
+ case PARSE_EVENTS__TERM_TYPE_HARDWARE:
+ default:
+ parse_events_error__handle(err, term->err_term,
+- strdup(config_term_name(term->type_term)),
++ strdup(parse_events__term_type_str(term->type_term)),
+ parse_events_formats_error_string(NULL));
+ return -EINVAL;
+ }
+@@ -1135,8 +1135,9 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
+ default:
+ if (err) {
+ parse_events_error__handle(err, term->err_term,
+- strdup(config_term_name(term->type_term)),
+- strdup("valid terms: call-graph,stack-size\n"));
++ strdup(parse_events__term_type_str(term->type_term)),
++ strdup("valid terms: call-graph,stack-size\n")
++ );
+ }
+ return -EINVAL;
+ }
+@@ -2581,7 +2582,7 @@ int parse_events_term__num(struct parse_events_term **term,
+ struct parse_events_term temp = {
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = type_term,
+- .config = config ? : strdup(config_term_name(type_term)),
++ .config = config ? : strdup(parse_events__term_type_str(type_term)),
+ .no_value = no_value,
+ .err_term = loc_term ? loc_term->first_column : 0,
+ .err_val = loc_val ? loc_val->first_column : 0,
+@@ -2615,7 +2616,7 @@ int parse_events_term__term(struct parse_events_term **term,
+ void *loc_term, void *loc_val)
+ {
+ return parse_events_term__str(term, term_lhs, NULL,
+- strdup(config_term_name(term_rhs)),
++ strdup(parse_events__term_type_str(term_rhs)),
+ loc_term, loc_val);
+ }
+
+@@ -2722,7 +2723,8 @@ int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct
+ if (ret < 0)
+ return ret;
+ } else if ((unsigned int)term->type_term < __PARSE_EVENTS__TERM_TYPE_NR) {
+- ret = strbuf_addf(sb, "%s=", config_term_name(term->type_term));
++ ret = strbuf_addf(sb, "%s=",
++ parse_events__term_type_str(term->type_term));
+ if (ret < 0)
+ return ret;
+ }
+@@ -2742,7 +2744,7 @@ static void config_terms_list(char *buf, size_t buf_sz)
+
+ buf[0] = '\0';
+ for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) {
+- const char *name = config_term_name(i);
++ const char *name = parse_events__term_type_str(i);
+
+ if (!config_term_avail(i, NULL))
+ continue;
+diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
+index 2b52f8d6aa29a..ac1feaaeb8d5d 100644
+--- a/tools/perf/util/parse-events.h
++++ b/tools/perf/util/parse-events.h
+@@ -168,6 +168,8 @@ struct parse_events_state {
+ bool wild_card_pmus;
+ };
+
++const char *parse_events__term_type_str(enum parse_events__term_type term_type);
++
+ bool parse_events__filter_pmu(const struct parse_events_state *parse_state,
+ const struct perf_pmu *pmu);
+ void parse_events__shrink_config_terms(void);
+--
+2.53.0
+
--- /dev/null
+From 097e408d8dfd97daea39ac7ea757eaa1e084bab9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:48:53 -0400
+Subject: Revert "ice: fix double-free of tx_buf skb"
+
+This reverts commit fd95ef8d0f6dbe2daa95d6488c9e0f8a95a7e048.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_txrx.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
+index 48434a79869cb..08d1757f40888 100644
+--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
+@@ -2346,9 +2346,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+
+ ice_trace(xmit_frame_ring, tx_ring, skb);
+
+- /* record the location of the first descriptor for this packet */
+- first = &tx_ring->tx_buf[tx_ring->next_to_use];
+-
+ count = ice_xmit_desc_count(skb);
+ if (ice_chk_linearize(skb, count)) {
+ if (__skb_linearize(skb))
+@@ -2374,6 +2371,8 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+
+ offload.tx_ring = tx_ring;
+
++ /* record the location of the first descriptor for this packet */
++ first = &tx_ring->tx_buf[tx_ring->next_to_use];
+ first->skb = skb;
+ first->type = ICE_TX_BUF_SKB;
+ first->bytecount = max_t(unsigned int, skb->len, ETH_ZLEN);
+@@ -2437,7 +2436,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+ out_drop:
+ ice_trace(xmit_frame_ring_drop, tx_ring, skb);
+ dev_kfree_skb_any(skb);
+- first->type = ICE_TX_BUF_EMPTY;
+ return NETDEV_TX_OK;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From a651eade212687e1f5055b5308d1024c67dba31d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:48:54 -0400
+Subject: Revert "ice: Remove jumbo_remove step from TX path"
+
+This reverts commit 7332d208c9d2067546eb7af5339773c966ac5625.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_txrx.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
+index 08d1757f40888..431a6ed498a4e 100644
+--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
+@@ -2346,6 +2346,9 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+
+ ice_trace(xmit_frame_ring, tx_ring, skb);
+
++ if (unlikely(ipv6_hopopt_jumbo_remove(skb)))
++ goto out_drop;
++
+ count = ice_xmit_desc_count(skb);
+ if (ice_chk_linearize(skb, count)) {
+ if (__skb_linearize(skb))
+--
+2.53.0
+
--- /dev/null
+From d1e3c23c1423204d2f3a13b121ccb3e2e05dce2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:25:17 +0000
+Subject: riscv: fgraph: Fix stack layout to match __arch_ftrace_regs argument
+ of ftrace_return_to_handler
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pu Lehui <pulehui@huawei.com>
+
+commit 67a5ba8f742f247bc83e46dd2313c142b1383276 upstream.
+
+Naresh Kamboju reported a "Bad frame pointer" kernel warning while
+running LTP trace ftrace_stress_test.sh in riscv. We can reproduce the
+same issue with the following command:
+
+```
+$ cd /sys/kernel/debug/tracing
+$ echo 'f:myprobe do_nanosleep%return args1=$retval' > dynamic_events
+$ echo 1 > events/fprobes/enable
+$ echo 1 > tracing_on
+$ sleep 1
+```
+
+And we can get the following kernel warning:
+
+[ 127.692888] ------------[ cut here ]------------
+[ 127.693755] Bad frame pointer: expected ff2000000065be50, received ba34c141e9594000
+[ 127.693755] from func do_nanosleep return to ffffffff800ccb16
+[ 127.698699] WARNING: CPU: 1 PID: 129 at kernel/trace/fgraph.c:755 ftrace_return_to_handler+0x1b2/0x1be
+[ 127.699894] Modules linked in:
+[ 127.700908] CPU: 1 UID: 0 PID: 129 Comm: sleep Not tainted 6.14.0-rc3-g0ab191c74642 #32
+[ 127.701453] Hardware name: riscv-virtio,qemu (DT)
+[ 127.701859] epc : ftrace_return_to_handler+0x1b2/0x1be
+[ 127.702032] ra : ftrace_return_to_handler+0x1b2/0x1be
+[ 127.702151] epc : ffffffff8013b5e0 ra : ffffffff8013b5e0 sp : ff2000000065bd10
+[ 127.702221] gp : ffffffff819c12f8 tp : ff60000080853100 t0 : 6e00000000000000
+[ 127.702284] t1 : 0000000000000020 t2 : 6e7566206d6f7266 s0 : ff2000000065bd80
+[ 127.702346] s1 : ff60000081262000 a0 : 000000000000007b a1 : ffffffff81894f20
+[ 127.702408] a2 : 0000000000000010 a3 : fffffffffffffffe a4 : 0000000000000000
+[ 127.702470] a5 : 0000000000000000 a6 : 0000000000000008 a7 : 0000000000000038
+[ 127.702530] s2 : ba34c141e9594000 s3 : 0000000000000000 s4 : ff2000000065bdd0
+[ 127.702591] s5 : 00007fff8adcf400 s6 : 000055556dc1d8c0 s7 : 0000000000000068
+[ 127.702651] s8 : 00007fff8adf5d10 s9 : 000000000000006d s10: 0000000000000001
+[ 127.702710] s11: 00005555737377c8 t3 : ffffffff819d899e t4 : ffffffff819d899e
+[ 127.702769] t5 : ffffffff819d89a0 t6 : ff2000000065bb18
+[ 127.702826] status: 0000000200000120 badaddr: 0000000000000000 cause: 0000000000000003
+[ 127.703292] [<ffffffff8013b5e0>] ftrace_return_to_handler+0x1b2/0x1be
+[ 127.703760] [<ffffffff80017bce>] return_to_handler+0x16/0x26
+[ 127.704009] [<ffffffff80017bb8>] return_to_handler+0x0/0x26
+[ 127.704057] [<ffffffff800d3352>] common_nsleep+0x42/0x54
+[ 127.704117] [<ffffffff800d44a2>] __riscv_sys_clock_nanosleep+0xba/0x10a
+[ 127.704176] [<ffffffff80901c56>] do_trap_ecall_u+0x188/0x218
+[ 127.704295] [<ffffffff8090cc3e>] handle_exception+0x14a/0x156
+[ 127.705436] ---[ end trace 0000000000000000 ]---
+
+The reason is that the stack layout for constructing argument for the
+ftrace_return_to_handler in the return_to_handler does not match the
+__arch_ftrace_regs structure of riscv, leading to unexpected results.
+
+Fixes: a3ed4157b7d8 ("fgraph: Replace fgraph_ret_regs with ftrace_regs")
+Reported-by: Linux Kernel Functional Testing <lkft@linaro.org>
+Closes: https://lore.kernel.org/all/CA+G9fYvp_oAxeDFj88Tk2rfEZ7jtYKAKSwfYS66=57Db9TBdyA@mail.gmail.com
+Signed-off-by: Pu Lehui <pulehui@huawei.com>
+Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Tested-by: Björn Töpel <bjorn@rivosinc.com>
+Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Link: https://lore.kernel.org/r/20250317031214.4138436-2-pulehui@huaweicloud.com
+Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/kernel/mcount.S | 24 +++++++++++-------------
+ 1 file changed, 11 insertions(+), 13 deletions(-)
+
+diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S
+index 068168046e0ef..da4a4000e57ea 100644
+--- a/arch/riscv/kernel/mcount.S
++++ b/arch/riscv/kernel/mcount.S
+@@ -12,8 +12,6 @@
+ #include <asm/asm-offsets.h>
+ #include <asm/ftrace.h>
+
+-#define ABI_SIZE_ON_STACK 80
+-
+ .text
+
+ .macro SAVE_ABI_STATE
+@@ -28,12 +26,12 @@
+ * register if a0 was not saved.
+ */
+ .macro SAVE_RET_ABI_STATE
+- addi sp, sp, -ABI_SIZE_ON_STACK
+- REG_S ra, 1*SZREG(sp)
+- REG_S s0, 8*SZREG(sp)
+- REG_S a0, 10*SZREG(sp)
+- REG_S a1, 11*SZREG(sp)
+- addi s0, sp, ABI_SIZE_ON_STACK
++ addi sp, sp, -FREGS_SIZE_ON_STACK
++ REG_S ra, FREGS_RA(sp)
++ REG_S s0, FREGS_S0(sp)
++ REG_S a0, FREGS_A0(sp)
++ REG_S a1, FREGS_A1(sp)
++ addi s0, sp, FREGS_SIZE_ON_STACK
+ .endm
+
+ .macro RESTORE_ABI_STATE
+@@ -43,11 +41,11 @@
+ .endm
+
+ .macro RESTORE_RET_ABI_STATE
+- REG_L ra, 1*SZREG(sp)
+- REG_L s0, 8*SZREG(sp)
+- REG_L a0, 10*SZREG(sp)
+- REG_L a1, 11*SZREG(sp)
+- addi sp, sp, ABI_SIZE_ON_STACK
++ REG_L ra, FREGS_RA(sp)
++ REG_L s0, FREGS_S0(sp)
++ REG_L a0, FREGS_A0(sp)
++ REG_L a1, FREGS_A1(sp)
++ addi sp, sp, FREGS_SIZE_ON_STACK
+ .endm
+
+ SYM_TYPED_FUNC_START(ftrace_stub)
+--
+2.53.0
+
--- /dev/null
+From b8b94d07bdbd6d9b0401fc3054f7a0cd6ddfd21b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:26:35 +0000
+Subject: riscv: fgraph: Select HAVE_FUNCTION_GRAPH_TRACER depends on
+ HAVE_DYNAMIC_FTRACE_WITH_ARGS
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pu Lehui <pulehui@huawei.com>
+
+commit e8eb8e1bdae94b9e003f5909519fd311d0936890 upstream.
+
+Currently, fgraph on riscv relies on the infrastructure of
+DYNAMIC_FTRACE_WITH_ARGS. However, DYNAMIC_FTRACE_WITH_ARGS may be
+turned off on riscv, which will cause the enabled fgraph to be abnormal.
+Therefore, let's select HAVE_FUNCTION_GRAPH_TRACER depends on
+HAVE_DYNAMIC_FTRACE_WITH_ARGS.
+
+Fixes: a3ed4157b7d8 ("fgraph: Replace fgraph_ret_regs with ftrace_regs")
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202503160820.dvqMpH0g-lkp@intel.com/
+Signed-off-by: Pu Lehui <pulehui@huawei.com>
+Reviewed-by: Björn Töpel <bjorn@rivosinc.com>
+Link: https://lore.kernel.org/r/20250317031214.4138436-1-pulehui@huaweicloud.com
+Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index 9e8667a523d55..1c75758167956 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -143,7 +143,7 @@ config RISCV
+ select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE
+ select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
+- select HAVE_FUNCTION_GRAPH_TRACER
++ select HAVE_FUNCTION_GRAPH_TRACER if HAVE_DYNAMIC_FTRACE_WITH_ARGS
+ select HAVE_FUNCTION_GRAPH_FREGS
+ select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION
+ select HAVE_EBPF_JIT if MMU
+--
+2.53.0
+
ata-libata-scsi-do-not-use-the-deferred-qc-feature-for-ata_defer_port.patch
ata-libata-scsi-do-not-use-the-deferred-qc-feature-on-pmps-with-cbs.patch
ata-libata-scsi-do-not-needlessly-defer-commands-when-using-pmp-with-fbs.patch
+perf-parse-events-expose-rename-config_term_name.patch
+revert-ice-fix-double-free-of-tx_buf-skb.patch
+revert-ice-remove-jumbo_remove-step-from-tx-path.patch
+tracing-fix-the-bug-where-bpf_get_stackid-returns-ef.patch
+net-mlx5e-trigger-neighbor-resolution-for-unresolved.patch
+net-mlx5e-use-ip6_dst_lookup-instead-of-ipv6_dst_loo.patch
+x86-fgraph-fix-return_to_handler-regs.rsp-value.patch
+iommu-vt-d-draining-prq-in-sva-unbind-path-when-fpd-.patch
+riscv-fgraph-select-have_function_graph_tracer-depen.patch
+riscv-fgraph-fix-stack-layout-to-match-__arch_ftrace.patch
+hwmon-pmbus-core-protect-regulator-operations-with-m.patch
+arm64-kconfig-remove-selecting-replaced-have_functio.patch
+i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in.patch
--- /dev/null
+From b09ae9b26fe5bac4704da61c7a946b391ea35e35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:20:12 +0000
+Subject: tracing: Fix the bug where bpf_get_stackid returns -EFAULT on the
+ ARM64
+
+From: Feng Yang <yangfeng@kylinos.cn>
+
+commit fd2f74f8f3d3c1a524637caf5bead9757fae4332 upstream.
+
+When using bpf_program__attach_kprobe_multi_opts on ARM64 to hook a BPF program
+that contains the bpf_get_stackid function, the BPF program fails
+to obtain the stack trace and returns -EFAULT.
+
+This is because ftrace_partial_regs omits the configuration of the pstate register,
+leaving pstate at the default value of 0. When get_perf_callchain executes,
+it uses user_mode(regs) to determine whether it is in kernel mode.
+This leads to a misjudgment that the code is in user mode,
+so perf_callchain_kernel is not executed and the function returns directly.
+As a result, trace->nr becomes 0, and finally -EFAULT is returned.
+
+Therefore, the assignment of the pstate register is added here.
+
+Fixes: b9b55c8912ce ("tracing: Add ftrace_partial_regs() for converting ftrace_regs to pt_regs")
+Closes: https://lore.kernel.org/bpf/20250919071902.554223-1-yangfeng59949@163.com/
+Signed-off-by: Feng Yang <yangfeng@kylinos.cn>
+Tested-by: Jiri Olsa <jolsa@kernel.org>
+Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/ftrace.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
+index 10e56522122aa..46d4300dd48d3 100644
+--- a/arch/arm64/include/asm/ftrace.h
++++ b/arch/arm64/include/asm/ftrace.h
+@@ -145,6 +145,7 @@ ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs)
+ regs->pc = afregs->pc;
+ regs->regs[29] = afregs->fp;
+ regs->regs[30] = afregs->lr;
++ regs->pstate = PSR_MODE_EL1h;
+ return regs;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From f98c446f5e4b7846cf8940726cbc4f76c642e8c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:23:24 +0000
+Subject: x86/fgraph: Fix return_to_handler regs.rsp value
+
+From: Jiri Olsa <jolsa@kernel.org>
+
+commit 8bc11700e0d23d4fdb7d8d5a73b2e95de427cabc upstream.
+
+The previous change (Fixes commit) messed up the rsp register value,
+which is wrong because it's already adjusted with FRAME_SIZE, we need
+the original rsp value.
+
+This change does not affect fprobe current kernel unwind, the !perf_hw_regs
+path perf_callchain_kernel:
+
+ if (perf_hw_regs(regs)) {
+ if (perf_callchain_store(entry, regs->ip))
+ return;
+ unwind_start(&state, current, regs, NULL);
+ } else {
+ unwind_start(&state, current, NULL, (void *)regs->sp);
+ }
+
+which uses pt_regs.sp as first_frame boundary (FRAME_SIZE shift makes
+no difference, unwind stil stops at the right frame).
+
+This change fixes the other path when we want to unwind directly from
+pt_regs sp/fp/ip state, which is coming in following change.
+
+Fixes: 20a0bc10272f ("x86/fgraph,bpf: Fix stack ORC unwind from kprobe_multi return probe")
+Signed-off-by: Jiri Olsa <jolsa@kernel.org>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Link: https://lore.kernel.org/bpf/20260126211837.472802-2-jolsa@kernel.org
+Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/ftrace_64.S | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/kernel/ftrace_64.S b/arch/x86/kernel/ftrace_64.S
+index 8a3cff618692c..143fc62bf6f88 100644
+--- a/arch/x86/kernel/ftrace_64.S
++++ b/arch/x86/kernel/ftrace_64.S
+@@ -349,6 +349,9 @@ SYM_CODE_START(return_to_handler)
+ UNWIND_HINT_UNDEFINED
+ ANNOTATE_NOENDBR
+
++ /* Store original rsp for pt_regs.sp value. */
++ movq %rsp, %rdi
++
+ /* Restore return_to_handler value that got eaten by previous ret instruction. */
+ subq $8, %rsp
+ UNWIND_HINT_FUNC
+@@ -359,7 +362,7 @@ SYM_CODE_START(return_to_handler)
+ movq %rax, RAX(%rsp)
+ movq %rdx, RDX(%rsp)
+ movq %rbp, RBP(%rsp)
+- movq %rsp, RSP(%rsp)
++ movq %rdi, RSP(%rsp)
+ movq %rsp, %rdi
+
+ call ftrace_return_to_handler
+--
+2.53.0
+
--- /dev/null
+From 0328cc6de2e09b3894ef93b56b4708d2420fd0c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:31:22 +0800
+Subject: drm/atomic: Increase timeout in drm_atomic_helper_wait_for_vblanks()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 79ae8510b5b81b9500370f89c619b50ca9c0990f ]
+
+Increase the timeout for vblank events from 100 ms to 1000 ms. This
+is the same fix as in commit f050da08a4ed ("drm/vblank: Increase
+timeout in drm_wait_one_vblank()") for another vblank timeout.
+
+After merging generic DRM vblank timers [1] and converting several
+DRM drivers for virtual hardware, these drivers synchronize their
+vblank events to the display refresh rate. This can trigger timeouts
+within the DRM framework.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://lore.kernel.org/dri-devel/20250904145806.430568-1-tzimmermann@suse.de/ # [1]
+Reported-by: syzbot+fcede535e7eb57cf5b43@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/dri-devel/69381d6c.050a0220.4004e.0017.GAE@google.com/
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Fixes: 74afeb812850 ("drm/vblank: Add vblank timer")
+Link: https://patch.msgid.link/20251209143325.102056-1-tzimmermann@suse.de
+Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_atomic_helper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
+index bbec1c184f652..b06a5cba52958 100644
+--- a/drivers/gpu/drm/drm_atomic_helper.c
++++ b/drivers/gpu/drm/drm_atomic_helper.c
+@@ -1913,7 +1913,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
+ ret = wait_event_timeout(dev->vblank[i].queue,
+ state->crtcs[i].last_vblank_count !=
+ drm_crtc_vblank_count(crtc),
+- msecs_to_jiffies(100));
++ msecs_to_jiffies(1000));
+
+ WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n",
+ crtc->base.id, crtc->name);
+--
+2.53.0
+
--- /dev/null
+From b0fe7515c74d5c520f8a3fdb83dc5eaf1747fcc7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:31:20 +0800
+Subject: drm/vblank: Add CRTC helpers for simple use cases
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit d54dbb5963bdbdf8559903fe2b2343e871adcb30 ]
+
+Implement atomic_flush, atomic_enable and atomic_disable of struct
+drm_crtc_helper_funcs for vblank handling. Driver with no further
+requirements can use these functions instead of adding their own.
+Also simplifies the use of vblank timers.
+
+The code has been adopted from vkms, which added the funtionality
+in commit 3a0709928b17 ("drm/vkms: Add vblank events simulated by
+hrtimers").
+
+v3:
+- mention vkms (Javier)
+v2:
+- fix docs
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Tested-by: Michael Kelley <mhklinux@outlook.com>
+Link: https://lore.kernel.org/r/20250916083816.30275-3-tzimmermann@suse.de
+Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_vblank_helper.c | 80 +++++++++++++++++++++++++++++
+ include/drm/drm_vblank_helper.h | 23 +++++++++
+ 2 files changed, 103 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_vblank_helper.c b/drivers/gpu/drm/drm_vblank_helper.c
+index f94d1e706191b..a04a6ba1b0ca0 100644
+--- a/drivers/gpu/drm/drm_vblank_helper.c
++++ b/drivers/gpu/drm/drm_vblank_helper.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: MIT
+
++#include <drm/drm_atomic.h>
+ #include <drm/drm_crtc.h>
+ #include <drm/drm_managed.h>
+ #include <drm/drm_modeset_helper_vtables.h>
+@@ -17,6 +18,12 @@
+ * Drivers enable support for vblank timers by setting the vblank callbacks
+ * in struct &drm_crtc_funcs to the helpers provided by this library. The
+ * initializer macro DRM_CRTC_VBLANK_TIMER_FUNCS does this conveniently.
++ * The driver further has to send the VBLANK event from its atomic_flush
++ * callback and control vblank from the CRTC's atomic_enable and atomic_disable
++ * callbacks. The callbacks are located in struct &drm_crtc_helper_funcs.
++ * The vblank helper library provides implementations of these callbacks
++ * for drivers without further requirements. The initializer macro
++ * DRM_CRTC_HELPER_VBLANK_FUNCS sets them coveniently.
+ *
+ * Once the driver enables vblank support with drm_vblank_init(), each
+ * CRTC's vblank timer fires according to the programmed display mode. By
+@@ -25,6 +32,79 @@
+ * struct &drm_crtc_helper_funcs.handle_vblank_timeout.
+ */
+
++/*
++ * VBLANK helpers
++ */
++
++/**
++ * drm_crtc_vblank_atomic_flush -
++ * Implements struct &drm_crtc_helper_funcs.atomic_flush
++ * @crtc: The CRTC
++ * @state: The atomic state to apply
++ *
++ * The helper drm_crtc_vblank_atomic_flush() implements atomic_flush of
++ * struct drm_crtc_helper_funcs for CRTCs that only need to send out a
++ * VBLANK event.
++ *
++ * See also struct &drm_crtc_helper_funcs.atomic_flush.
++ */
++void drm_crtc_vblank_atomic_flush(struct drm_crtc *crtc,
++ struct drm_atomic_state *state)
++{
++ struct drm_device *dev = crtc->dev;
++ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
++ struct drm_pending_vblank_event *event;
++
++ spin_lock_irq(&dev->event_lock);
++
++ event = crtc_state->event;
++ crtc_state->event = NULL;
++
++ if (event) {
++ if (drm_crtc_vblank_get(crtc) == 0)
++ drm_crtc_arm_vblank_event(crtc, event);
++ else
++ drm_crtc_send_vblank_event(crtc, event);
++ }
++
++ spin_unlock_irq(&dev->event_lock);
++}
++EXPORT_SYMBOL(drm_crtc_vblank_atomic_flush);
++
++/**
++ * drm_crtc_vblank_atomic_enable - Implements struct &drm_crtc_helper_funcs.atomic_enable
++ * @crtc: The CRTC
++ * @state: The atomic state
++ *
++ * The helper drm_crtc_vblank_atomic_enable() implements atomic_enable
++ * of struct drm_crtc_helper_funcs for CRTCs the only need to enable VBLANKs.
++ *
++ * See also struct &drm_crtc_helper_funcs.atomic_enable.
++ */
++void drm_crtc_vblank_atomic_enable(struct drm_crtc *crtc,
++ struct drm_atomic_state *state)
++{
++ drm_crtc_vblank_on(crtc);
++}
++EXPORT_SYMBOL(drm_crtc_vblank_atomic_enable);
++
++/**
++ * drm_crtc_vblank_atomic_disable - Implements struct &drm_crtc_helper_funcs.atomic_disable
++ * @crtc: The CRTC
++ * @state: The atomic state
++ *
++ * The helper drm_crtc_vblank_atomic_disable() implements atomic_disable
++ * of struct drm_crtc_helper_funcs for CRTCs the only need to disable VBLANKs.
++ *
++ * See also struct &drm_crtc_funcs.atomic_disable.
++ */
++void drm_crtc_vblank_atomic_disable(struct drm_crtc *crtc,
++ struct drm_atomic_state *state)
++{
++ drm_crtc_vblank_off(crtc);
++}
++EXPORT_SYMBOL(drm_crtc_vblank_atomic_disable);
++
+ /*
+ * VBLANK timer
+ */
+diff --git a/include/drm/drm_vblank_helper.h b/include/drm/drm_vblank_helper.h
+index 74a971d0cfba0..fcd8a9b358463 100644
+--- a/include/drm/drm_vblank_helper.h
++++ b/include/drm/drm_vblank_helper.h
+@@ -6,8 +6,31 @@
+ #include <linux/hrtimer_types.h>
+ #include <linux/types.h>
+
++struct drm_atomic_state;
+ struct drm_crtc;
+
++/*
++ * VBLANK helpers
++ */
++
++void drm_crtc_vblank_atomic_flush(struct drm_crtc *crtc,
++ struct drm_atomic_state *state);
++void drm_crtc_vblank_atomic_enable(struct drm_crtc *crtc,
++ struct drm_atomic_state *state);
++void drm_crtc_vblank_atomic_disable(struct drm_crtc *crtc,
++ struct drm_atomic_state *crtc_state);
++
++/**
++ * DRM_CRTC_HELPER_VBLANK_FUNCS - Default implementation for VBLANK helpers
++ *
++ * This macro initializes struct &drm_crtc_helper_funcs to default helpers
++ * for VBLANK handling.
++ */
++#define DRM_CRTC_HELPER_VBLANK_FUNCS \
++ .atomic_flush = drm_crtc_vblank_atomic_flush, \
++ .atomic_enable = drm_crtc_vblank_atomic_enable, \
++ .atomic_disable = drm_crtc_vblank_atomic_disable
++
+ /*
+ * VBLANK timer
+ */
+--
+2.53.0
+
--- /dev/null
+From 6f54e07c43a2d03aa6245613760eb1d1288d3ef0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:31:19 +0800
+Subject: drm/vblank: Add vblank timer
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 74afeb8128502a529041a2566febd26053a7be11 ]
+
+The vblank timer simulates a vblank interrupt for hardware without
+support. Rate-limits the display update frequency.
+
+DRM drivers for hardware without vblank support apply display updates
+ASAP. A vblank event informs DRM clients of the completed update.
+Userspace compositors immediately schedule the next update, which
+creates significant load on virtualization outputs. Display updates
+are usually fast on virtualization outputs, as their framebuffers are
+in regular system memory and there's no hardware vblank interrupt to
+throttle the update rate.
+
+The vblank timer is a HR timer that signals the vblank in software.
+It limits the update frequency of a DRM driver similar to a hardware
+vblank interrupt. The timer is not synchronized to the actual vblank
+interval of the display.
+
+The code has been adopted from vkms, which added the funtionality
+in commit 3a0709928b17 ("drm/vkms: Add vblank events simulated by
+hrtimers").
+
+The new implementation is part of the existing vblank support,
+which sets up the timer automatically. Drivers only have to start
+and cancel the vblank timer as part of enabling and disabling the
+CRTC. The new vblank helper library provides callbacks for struct
+drm_crtc_funcs.
+
+The standard way for handling vblank is to call drm_crtc_handle_vblank().
+Drivers that require additional processing, such as vkms, can init
+handle_vblank_timeout in struct drm_crtc_helper_funcs to refer to
+their timeout handler.
+
+There's a possible deadlock between drm_crtc_handle_vblank() and
+hrtimer_cancel(). [1] The implementation avoids to call hrtimer_cancel()
+directly and instead signals to the timer function to not restart
+itself.
+
+v4:
+- fix possible race condition between timeout and atomic commit (Michael)
+v3:
+- avoid deadlock when cancelling timer (Ville, Lyude)
+v2:
+- implement vblank timer entirely in vblank helpers
+- downgrade overrun warning to debug
+- fix docs
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Tested-by: Louis Chauvet <louis.chauvet@bootlin.com>
+Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Tested-by: Michael Kelley <mhklinux@outlook.com>
+Link: https://lore.kernel.org/all/20250510094757.4174662-1-zengheng4@huawei.com/ # [1]
+Link: https://lore.kernel.org/r/20250916083816.30275-2-tzimmermann@suse.de
+Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/gpu/drm-kms-helpers.rst | 12 ++
+ drivers/gpu/drm/Makefile | 3 +-
+ drivers/gpu/drm/drm_vblank.c | 172 ++++++++++++++++++++++-
+ drivers/gpu/drm/drm_vblank_helper.c | 96 +++++++++++++
+ include/drm/drm_modeset_helper_vtables.h | 12 ++
+ include/drm/drm_vblank.h | 32 +++++
+ include/drm/drm_vblank_helper.h | 33 +++++
+ 7 files changed, 357 insertions(+), 3 deletions(-)
+ create mode 100644 drivers/gpu/drm/drm_vblank_helper.c
+ create mode 100644 include/drm/drm_vblank_helper.h
+
+diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
+index 5139705089f20..781129f78b06b 100644
+--- a/Documentation/gpu/drm-kms-helpers.rst
++++ b/Documentation/gpu/drm-kms-helpers.rst
+@@ -92,6 +92,18 @@ GEM Atomic Helper Reference
+ .. kernel-doc:: drivers/gpu/drm/drm_gem_atomic_helper.c
+ :export:
+
++VBLANK Helper Reference
++-----------------------
++
++.. kernel-doc:: drivers/gpu/drm/drm_vblank_helper.c
++ :doc: overview
++
++.. kernel-doc:: include/drm/drm_vblank_helper.h
++ :internal:
++
++.. kernel-doc:: drivers/gpu/drm/drm_vblank_helper.c
++ :export:
++
+ Simple KMS Helper Reference
+ ===========================
+
+diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
+index 742f0d590c5af..b248e64587ed4 100644
+--- a/drivers/gpu/drm/Makefile
++++ b/drivers/gpu/drm/Makefile
+@@ -152,7 +152,8 @@ drm_kms_helper-y := \
+ drm_plane_helper.o \
+ drm_probe_helper.o \
+ drm_self_refresh_helper.o \
+- drm_simple_kms_helper.o
++ drm_simple_kms_helper.o \
++ drm_vblank_helper.o
+ drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
+ drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
+ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
+diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
+index 46f59883183d9..61e211fd3c9c8 100644
+--- a/drivers/gpu/drm/drm_vblank.c
++++ b/drivers/gpu/drm/drm_vblank.c
+@@ -136,8 +136,17 @@
+ * vblanks after a timer has expired, which can be configured through the
+ * ``vblankoffdelay`` module parameter.
+ *
+- * Drivers for hardware without support for vertical-blanking interrupts
+- * must not call drm_vblank_init(). For such drivers, atomic helpers will
++ * Drivers for hardware without support for vertical-blanking interrupts can
++ * use DRM vblank timers to send vblank events at the rate of the current
++ * display mode's refresh. While not synchronized to the hardware's
++ * vertical-blanking regions, the timer helps DRM clients and compositors to
++ * adapt their update cycle to the display output. Drivers should set up
++ * vblanking as usual, but call drm_crtc_vblank_start_timer() and
++ * drm_crtc_vblank_cancel_timer() as part of their atomic mode setting.
++ * See also DRM vblank helpers for more information.
++ *
++ * Drivers without support for vertical-blanking interrupts nor timers must
++ * not call drm_vblank_init(). For these drivers, atomic helpers will
+ * automatically generate fake vblank events as part of the display update.
+ * This functionality also can be controlled by the driver by enabling and
+ * disabling struct drm_crtc_state.no_vblank.
+@@ -508,6 +517,9 @@ static void drm_vblank_init_release(struct drm_device *dev, void *ptr)
+ drm_WARN_ON(dev, READ_ONCE(vblank->enabled) &&
+ drm_core_check_feature(dev, DRIVER_MODESET));
+
++ if (vblank->vblank_timer.crtc)
++ hrtimer_cancel(&vblank->vblank_timer.timer);
++
+ drm_vblank_destroy_worker(vblank);
+ timer_delete_sync(&vblank->disable_timer);
+ }
+@@ -2162,3 +2174,159 @@ int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data,
+ return ret;
+ }
+
++/*
++ * VBLANK timer
++ */
++
++static enum hrtimer_restart drm_vblank_timer_function(struct hrtimer *timer)
++{
++ struct drm_vblank_crtc_timer *vtimer =
++ container_of(timer, struct drm_vblank_crtc_timer, timer);
++ struct drm_crtc *crtc = vtimer->crtc;
++ const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
++ struct drm_device *dev = crtc->dev;
++ unsigned long flags;
++ ktime_t interval;
++ u64 ret_overrun;
++ bool succ;
++
++ spin_lock_irqsave(&vtimer->interval_lock, flags);
++ interval = vtimer->interval;
++ spin_unlock_irqrestore(&vtimer->interval_lock, flags);
++
++ if (!interval)
++ return HRTIMER_NORESTART;
++
++ ret_overrun = hrtimer_forward_now(&vtimer->timer, interval);
++ if (ret_overrun != 1)
++ drm_dbg_vbl(dev, "vblank timer overrun\n");
++
++ if (crtc_funcs->handle_vblank_timeout)
++ succ = crtc_funcs->handle_vblank_timeout(crtc);
++ else
++ succ = drm_crtc_handle_vblank(crtc);
++ if (!succ)
++ return HRTIMER_NORESTART;
++
++ return HRTIMER_RESTART;
++}
++
++/**
++ * drm_crtc_vblank_start_timer - Starts the vblank timer on the given CRTC
++ * @crtc: the CRTC
++ *
++ * Drivers should call this function from their CRTC's enable_vblank
++ * function to start a vblank timer. The timer will fire after the duration
++ * of a full frame. drm_crtc_vblank_cancel_timer() disables a running timer.
++ *
++ * Returns:
++ * 0 on success, or a negative errno code otherwise.
++ */
++int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
++{
++ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
++ struct drm_vblank_crtc_timer *vtimer = &vblank->vblank_timer;
++ unsigned long flags;
++
++ if (!vtimer->crtc) {
++ /*
++ * Set up the data structures on the first invocation.
++ */
++ vtimer->crtc = crtc;
++ spin_lock_init(&vtimer->interval_lock);
++ hrtimer_setup(&vtimer->timer, drm_vblank_timer_function,
++ CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ } else {
++ /*
++ * Timer should not be active. If it is, wait for the
++ * previous cancel operations to finish.
++ */
++ while (hrtimer_active(&vtimer->timer))
++ hrtimer_try_to_cancel(&vtimer->timer);
++ }
++
++ drm_calc_timestamping_constants(crtc, &crtc->mode);
++
++ spin_lock_irqsave(&vtimer->interval_lock, flags);
++ vtimer->interval = ns_to_ktime(vblank->framedur_ns);
++ spin_unlock_irqrestore(&vtimer->interval_lock, flags);
++
++ hrtimer_start(&vtimer->timer, vtimer->interval, HRTIMER_MODE_REL);
++
++ return 0;
++}
++EXPORT_SYMBOL(drm_crtc_vblank_start_timer);
++
++/**
++ * drm_crtc_vblank_start_timer - Cancels the given CRTC's vblank timer
++ * @crtc: the CRTC
++ *
++ * Drivers should call this function from their CRTC's disable_vblank
++ * function to stop a vblank timer.
++ */
++void drm_crtc_vblank_cancel_timer(struct drm_crtc *crtc)
++{
++ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
++ struct drm_vblank_crtc_timer *vtimer = &vblank->vblank_timer;
++ unsigned long flags;
++
++ /*
++ * Calling hrtimer_cancel() can result in a deadlock with DRM's
++ * vblank_time_lime_lock and hrtimers' softirq_expiry_lock. So
++ * clear interval and indicate cancellation. The timer function
++ * will cancel itself on the next invocation.
++ */
++
++ spin_lock_irqsave(&vtimer->interval_lock, flags);
++ vtimer->interval = 0;
++ spin_unlock_irqrestore(&vtimer->interval_lock, flags);
++
++ hrtimer_try_to_cancel(&vtimer->timer);
++}
++EXPORT_SYMBOL(drm_crtc_vblank_cancel_timer);
++
++/**
++ * drm_crtc_vblank_get_vblank_timeout - Returns the vblank timeout
++ * @crtc: The CRTC
++ * @vblank_time: Returns the next vblank timestamp
++ *
++ * The helper drm_crtc_vblank_get_vblank_timeout() returns the next vblank
++ * timestamp of the CRTC's vblank timer according to the timer's expiry
++ * time.
++ */
++void drm_crtc_vblank_get_vblank_timeout(struct drm_crtc *crtc, ktime_t *vblank_time)
++{
++ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
++ struct drm_vblank_crtc_timer *vtimer = &vblank->vblank_timer;
++ u64 cur_count;
++ ktime_t cur_time;
++
++ if (!READ_ONCE(vblank->enabled)) {
++ *vblank_time = ktime_get();
++ return;
++ }
++
++ /*
++ * A concurrent vblank timeout could update the expires field before
++ * we compare it with the vblank time. Hence we'd compare the old
++ * expiry time to the new vblank time; deducing the timer had already
++ * expired. Reread until we get consistent values from both fields.
++ */
++ do {
++ cur_count = drm_crtc_vblank_count_and_time(crtc, &cur_time);
++ *vblank_time = READ_ONCE(vtimer->timer.node.expires);
++ } while (cur_count != drm_crtc_vblank_count_and_time(crtc, &cur_time));
++
++ if (drm_WARN_ON(crtc->dev, !ktime_compare(*vblank_time, cur_time)))
++ return; /* Already expired */
++
++ /*
++ * To prevent races we roll the hrtimer forward before we do any
++ * interrupt processing - this is how real hw works (the interrupt
++ * is only generated after all the vblank registers are updated)
++ * and what the vblank core expects. Therefore we need to always
++ * correct the timestamp by one frame.
++ */
++ *vblank_time = ktime_sub(*vblank_time, vtimer->interval);
++}
++EXPORT_SYMBOL(drm_crtc_vblank_get_vblank_timeout);
+diff --git a/drivers/gpu/drm/drm_vblank_helper.c b/drivers/gpu/drm/drm_vblank_helper.c
+new file mode 100644
+index 0000000000000..f94d1e706191b
+--- /dev/null
++++ b/drivers/gpu/drm/drm_vblank_helper.c
+@@ -0,0 +1,96 @@
++// SPDX-License-Identifier: MIT
++
++#include <drm/drm_crtc.h>
++#include <drm/drm_managed.h>
++#include <drm/drm_modeset_helper_vtables.h>
++#include <drm/drm_print.h>
++#include <drm/drm_vblank.h>
++#include <drm/drm_vblank_helper.h>
++
++/**
++ * DOC: overview
++ *
++ * The vblank helper library provides functions for supporting vertical
++ * blanking in DRM drivers.
++ *
++ * For vblank timers, several callback implementations are available.
++ * Drivers enable support for vblank timers by setting the vblank callbacks
++ * in struct &drm_crtc_funcs to the helpers provided by this library. The
++ * initializer macro DRM_CRTC_VBLANK_TIMER_FUNCS does this conveniently.
++ *
++ * Once the driver enables vblank support with drm_vblank_init(), each
++ * CRTC's vblank timer fires according to the programmed display mode. By
++ * default, the vblank timer invokes drm_crtc_handle_vblank(). Drivers with
++ * more specific requirements can set their own handler function in
++ * struct &drm_crtc_helper_funcs.handle_vblank_timeout.
++ */
++
++/*
++ * VBLANK timer
++ */
++
++/**
++ * drm_crtc_vblank_helper_enable_vblank_timer - Implements struct &drm_crtc_funcs.enable_vblank
++ * @crtc: The CRTC
++ *
++ * The helper drm_crtc_vblank_helper_enable_vblank_timer() implements
++ * enable_vblank of struct drm_crtc_helper_funcs for CRTCs that require
++ * a VBLANK timer. It sets up the timer on the first invocation. The
++ * started timer expires after the current frame duration. See struct
++ * &drm_vblank_crtc.framedur_ns.
++ *
++ * See also struct &drm_crtc_helper_funcs.enable_vblank.
++ *
++ * Returns:
++ * 0 on success, or a negative errno code otherwise.
++ */
++int drm_crtc_vblank_helper_enable_vblank_timer(struct drm_crtc *crtc)
++{
++ return drm_crtc_vblank_start_timer(crtc);
++}
++EXPORT_SYMBOL(drm_crtc_vblank_helper_enable_vblank_timer);
++
++/**
++ * drm_crtc_vblank_helper_disable_vblank_timer - Implements struct &drm_crtc_funcs.disable_vblank
++ * @crtc: The CRTC
++ *
++ * The helper drm_crtc_vblank_helper_disable_vblank_timer() implements
++ * disable_vblank of struct drm_crtc_funcs for CRTCs that require a
++ * VBLANK timer.
++ *
++ * See also struct &drm_crtc_helper_funcs.disable_vblank.
++ */
++void drm_crtc_vblank_helper_disable_vblank_timer(struct drm_crtc *crtc)
++{
++ drm_crtc_vblank_cancel_timer(crtc);
++}
++EXPORT_SYMBOL(drm_crtc_vblank_helper_disable_vblank_timer);
++
++/**
++ * drm_crtc_vblank_helper_get_vblank_timestamp_from_timer -
++ * Implements struct &drm_crtc_funcs.get_vblank_timestamp
++ * @crtc: The CRTC
++ * @max_error: Maximum acceptable error
++ * @vblank_time: Returns the next vblank timestamp
++ * @in_vblank_irq: True is called from drm_crtc_handle_vblank()
++ *
++ * The helper drm_crtc_helper_get_vblank_timestamp_from_timer() implements
++ * get_vblank_timestamp of struct drm_crtc_funcs for CRTCs that require a
++ * VBLANK timer. It returns the timestamp according to the timer's expiry
++ * time.
++ *
++ * See also struct &drm_crtc_funcs.get_vblank_timestamp.
++ *
++ * Returns:
++ * True on success, or false otherwise.
++ */
++bool drm_crtc_vblank_helper_get_vblank_timestamp_from_timer(struct drm_crtc *crtc,
++ int *max_error,
++ ktime_t *vblank_time,
++ bool in_vblank_irq)
++{
++ drm_crtc_vblank_get_vblank_timeout(crtc, vblank_time);
++
++ return true;
++}
++EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_from_timer);
+diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
+index ce7c7aeac887b..fe32854b7ffec 100644
+--- a/include/drm/drm_modeset_helper_vtables.h
++++ b/include/drm/drm_modeset_helper_vtables.h
+@@ -490,6 +490,18 @@ struct drm_crtc_helper_funcs {
+ bool in_vblank_irq, int *vpos, int *hpos,
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode);
++
++ /**
++ * @handle_vblank_timeout: Handles timeouts of the vblank timer.
++ *
++ * Called by CRTC's the vblank timer on each timeout. Semantics is
++ * equivalient to drm_crtc_handle_vblank(). Implementations should
++ * invoke drm_crtc_handle_vblank() as part of processing the timeout.
++ *
++ * This callback is optional. If unset, the vblank timer invokes
++ * drm_crtc_handle_vblank() directly.
++ */
++ bool (*handle_vblank_timeout)(struct drm_crtc *crtc);
+ };
+
+ /**
+diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
+index 151ab1e85b1b7..ffa564d796384 100644
+--- a/include/drm/drm_vblank.h
++++ b/include/drm/drm_vblank.h
+@@ -25,6 +25,7 @@
+ #define _DRM_VBLANK_H_
+
+ #include <linux/seqlock.h>
++#include <linux/hrtimer.h>
+ #include <linux/idr.h>
+ #include <linux/poll.h>
+ #include <linux/kthread.h>
+@@ -103,6 +104,28 @@ struct drm_vblank_crtc_config {
+ bool disable_immediate;
+ };
+
++/**
++ * struct drm_vblank_crtc_timer - vblank timer for a CRTC
++ */
++struct drm_vblank_crtc_timer {
++ /**
++ * @timer: The vblank's high-resolution timer
++ */
++ struct hrtimer timer;
++ /**
++ * @interval_lock: Protects @interval
++ */
++ spinlock_t interval_lock;
++ /**
++ * @interval: Duration between two vblanks
++ */
++ ktime_t interval;
++ /**
++ * @crtc: The timer's CRTC
++ */
++ struct drm_crtc *crtc;
++};
++
+ /**
+ * struct drm_vblank_crtc - vblank tracking for a CRTC
+ *
+@@ -254,6 +277,11 @@ struct drm_vblank_crtc {
+ * cancelled.
+ */
+ wait_queue_head_t work_wait_queue;
++
++ /**
++ * @vblank_timer: Holds the state of the vblank timer
++ */
++ struct drm_vblank_crtc_timer vblank_timer;
+ };
+
+ struct drm_vblank_crtc *drm_crtc_vblank_crtc(struct drm_crtc *crtc);
+@@ -290,6 +318,10 @@ wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
+ void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
+ u32 max_vblank_count);
+
++int drm_crtc_vblank_start_timer(struct drm_crtc *crtc);
++void drm_crtc_vblank_cancel_timer(struct drm_crtc *crtc);
++void drm_crtc_vblank_get_vblank_timeout(struct drm_crtc *crtc, ktime_t *vblank_time);
++
+ /*
+ * Helpers for struct drm_crtc_funcs
+ */
+diff --git a/include/drm/drm_vblank_helper.h b/include/drm/drm_vblank_helper.h
+new file mode 100644
+index 0000000000000..74a971d0cfba0
+--- /dev/null
++++ b/include/drm/drm_vblank_helper.h
+@@ -0,0 +1,33 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++
++#ifndef _DRM_VBLANK_HELPER_H_
++#define _DRM_VBLANK_HELPER_H_
++
++#include <linux/hrtimer_types.h>
++#include <linux/types.h>
++
++struct drm_crtc;
++
++/*
++ * VBLANK timer
++ */
++
++int drm_crtc_vblank_helper_enable_vblank_timer(struct drm_crtc *crtc);
++void drm_crtc_vblank_helper_disable_vblank_timer(struct drm_crtc *crtc);
++bool drm_crtc_vblank_helper_get_vblank_timestamp_from_timer(struct drm_crtc *crtc,
++ int *max_error,
++ ktime_t *vblank_time,
++ bool in_vblank_irq);
++
++/**
++ * DRM_CRTC_VBLANK_TIMER_FUNCS - Default implementation for VBLANK timers
++ *
++ * This macro initializes struct &drm_crtc_funcs to default helpers for
++ * VBLANK timers.
++ */
++#define DRM_CRTC_VBLANK_TIMER_FUNCS \
++ .enable_vblank = drm_crtc_vblank_helper_enable_vblank_timer, \
++ .disable_vblank = drm_crtc_vblank_helper_disable_vblank_timer, \
++ .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp_from_timer
++
++#endif
+--
+2.53.0
+
--- /dev/null
+From f7b83fd63a3e176b3c85143f712c8a32246b036e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:31:23 +0800
+Subject: drm/vblank: Fix kernel docs for vblank timer
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 3946d3ba99342f3b9996e621f05e7003d4308171 ]
+
+Fix documentation for drm_crtc_vblank_start_timer(), which referred
+to drm_crtc_vblank_cancel_timer().
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Closes: https://lore.kernel.org/dri-devel/20251106152201.6f248c09@canb.auug.org.au/
+Fixes: 74afeb812850 ("drm/vblank: Add vblank timer")
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: Louis Chauvet <louis.chauvet@bootlin.com>
+Cc: Javier Martinez Canillas <javierm@redhat.com>
+Cc: David Airlie <airlied@gmail.com>
+Cc: Simona Vetter <simona@ffwll.ch>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: Maxime Ripard <mripard@kernel.org>
+Cc: dri-devel@lists.freedesktop.org
+Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
+Link: https://patch.msgid.link/20251106073207.11192-1-tzimmermann@suse.de
+Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_vblank.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
+index 61e211fd3c9c8..451ec96202266 100644
+--- a/drivers/gpu/drm/drm_vblank.c
++++ b/drivers/gpu/drm/drm_vblank.c
+@@ -2258,7 +2258,7 @@ int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
+ EXPORT_SYMBOL(drm_crtc_vblank_start_timer);
+
+ /**
+- * drm_crtc_vblank_start_timer - Cancels the given CRTC's vblank timer
++ * drm_crtc_vblank_cancel_timer - Cancels the given CRTC's vblank timer
+ * @crtc: the CRTC
+ *
+ * Drivers should call this function from their CRTC's disable_vblank
+--
+2.53.0
+
--- /dev/null
+From 3bc5cf9c4b89d0278f2334a736e18ffca4cd279a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:31:21 +0800
+Subject: drm/vkms: Convert to DRM's vblank timer
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 02e2681ffe1addde1fc8c35d05657b16bfa79613 ]
+
+Replace vkms' vblank timer with the DRM implementation. The DRM
+code is identical in concept, but differs in implementation.
+
+Vblank timers are covered in vblank helpers and initializer macros,
+so remove the corresponding hrtimer in struct vkms_output. The
+vblank timer calls vkms' custom timeout code via handle_vblank_timeout
+in struct drm_crtc_helper_funcs.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Tested-by: Louis Chauvet <louis.chauvet@bootlin.com>
+Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://lore.kernel.org/r/20250916083816.30275-4-tzimmermann@suse.de
+Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vkms/vkms_crtc.c | 83 +++-----------------------------
+ drivers/gpu/drm/vkms/vkms_drv.h | 2 -
+ 2 files changed, 7 insertions(+), 78 deletions(-)
+
+diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
+index e60573e0f3e95..bd79f24686dce 100644
+--- a/drivers/gpu/drm/vkms/vkms_crtc.c
++++ b/drivers/gpu/drm/vkms/vkms_crtc.c
+@@ -7,25 +7,18 @@
+ #include <drm/drm_managed.h>
+ #include <drm/drm_probe_helper.h>
+ #include <drm/drm_vblank.h>
++#include <drm/drm_vblank_helper.h>
+
+ #include "vkms_drv.h"
+
+-static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
++static bool vkms_crtc_handle_vblank_timeout(struct drm_crtc *crtc)
+ {
+- struct vkms_output *output = container_of(timer, struct vkms_output,
+- vblank_hrtimer);
+- struct drm_crtc *crtc = &output->crtc;
++ struct vkms_output *output = drm_crtc_to_vkms_output(crtc);
+ struct vkms_crtc_state *state;
+- u64 ret_overrun;
+ bool ret, fence_cookie;
+
+ fence_cookie = dma_fence_begin_signalling();
+
+- ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
+- output->period_ns);
+- if (ret_overrun != 1)
+- pr_warn("%s: vblank timer overrun\n", __func__);
+-
+ spin_lock(&output->lock);
+ ret = drm_crtc_handle_vblank(crtc);
+ if (!ret)
+@@ -57,55 +50,6 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
+
+ dma_fence_end_signalling(fence_cookie);
+
+- return HRTIMER_RESTART;
+-}
+-
+-static int vkms_enable_vblank(struct drm_crtc *crtc)
+-{
+- struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
+- struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
+-
+- hrtimer_setup(&out->vblank_hrtimer, &vkms_vblank_simulate, CLOCK_MONOTONIC,
+- HRTIMER_MODE_REL);
+- out->period_ns = ktime_set(0, vblank->framedur_ns);
+- hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL);
+-
+- return 0;
+-}
+-
+-static void vkms_disable_vblank(struct drm_crtc *crtc)
+-{
+- struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
+-
+- hrtimer_cancel(&out->vblank_hrtimer);
+-}
+-
+-static bool vkms_get_vblank_timestamp(struct drm_crtc *crtc,
+- int *max_error, ktime_t *vblank_time,
+- bool in_vblank_irq)
+-{
+- struct vkms_output *output = drm_crtc_to_vkms_output(crtc);
+- struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
+-
+- if (!READ_ONCE(vblank->enabled)) {
+- *vblank_time = ktime_get();
+- return true;
+- }
+-
+- *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
+-
+- if (WARN_ON(*vblank_time == vblank->time))
+- return true;
+-
+- /*
+- * To prevent races we roll the hrtimer forward before we do any
+- * interrupt processing - this is how real hw works (the interrupt is
+- * only generated after all the vblank registers are updated) and what
+- * the vblank core expects. Therefore we need to always correct the
+- * timestampe by one frame.
+- */
+- *vblank_time -= output->period_ns;
+-
+ return true;
+ }
+
+@@ -159,9 +103,7 @@ static const struct drm_crtc_funcs vkms_crtc_funcs = {
+ .reset = vkms_atomic_crtc_reset,
+ .atomic_duplicate_state = vkms_atomic_crtc_duplicate_state,
+ .atomic_destroy_state = vkms_atomic_crtc_destroy_state,
+- .enable_vblank = vkms_enable_vblank,
+- .disable_vblank = vkms_disable_vblank,
+- .get_vblank_timestamp = vkms_get_vblank_timestamp,
++ DRM_CRTC_VBLANK_TIMER_FUNCS,
+ .get_crc_sources = vkms_get_crc_sources,
+ .set_crc_source = vkms_set_crc_source,
+ .verify_crc_source = vkms_verify_crc_source,
+@@ -213,18 +155,6 @@ static int vkms_crtc_atomic_check(struct drm_crtc *crtc,
+ return 0;
+ }
+
+-static void vkms_crtc_atomic_enable(struct drm_crtc *crtc,
+- struct drm_atomic_state *state)
+-{
+- drm_crtc_vblank_on(crtc);
+-}
+-
+-static void vkms_crtc_atomic_disable(struct drm_crtc *crtc,
+- struct drm_atomic_state *state)
+-{
+- drm_crtc_vblank_off(crtc);
+-}
+-
+ static void vkms_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+ __acquires(&vkms_output->lock)
+@@ -265,8 +195,9 @@ static const struct drm_crtc_helper_funcs vkms_crtc_helper_funcs = {
+ .atomic_check = vkms_crtc_atomic_check,
+ .atomic_begin = vkms_crtc_atomic_begin,
+ .atomic_flush = vkms_crtc_atomic_flush,
+- .atomic_enable = vkms_crtc_atomic_enable,
+- .atomic_disable = vkms_crtc_atomic_disable,
++ .atomic_enable = drm_crtc_vblank_atomic_enable,
++ .atomic_disable = drm_crtc_vblank_atomic_disable,
++ .handle_vblank_timeout = vkms_crtc_handle_vblank_timeout,
+ };
+
+ struct vkms_output *vkms_crtc_init(struct drm_device *dev, struct drm_plane *primary,
+diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
+index 8013c31efe3b1..fb9711e1c6fbd 100644
+--- a/drivers/gpu/drm/vkms/vkms_drv.h
++++ b/drivers/gpu/drm/vkms/vkms_drv.h
+@@ -215,8 +215,6 @@ struct vkms_output {
+ struct drm_crtc crtc;
+ struct drm_writeback_connector wb_connector;
+ struct drm_encoder wb_encoder;
+- struct hrtimer vblank_hrtimer;
+- ktime_t period_ns;
+ struct workqueue_struct *composer_workq;
+ spinlock_t lock;
+
+--
+2.53.0
+
--- /dev/null
+From cc19b6039a7bfce8697df1337fe7bc53e9de3563 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:43:10 -0400
+Subject: Revert "ice: fix double-free of tx_buf skb"
+
+This reverts commit 7cb19ec8ac087f33bee60f5d6054b284a5b9bb6f.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_txrx.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
+index e0774a640955d..90dbe5266ce78 100644
+--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
+@@ -2594,9 +2594,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+
+ ice_trace(xmit_frame_ring, tx_ring, skb);
+
+- /* record the location of the first descriptor for this packet */
+- first = &tx_ring->tx_buf[tx_ring->next_to_use];
+-
+ count = ice_xmit_desc_count(skb);
+ if (ice_chk_linearize(skb, count)) {
+ if (__skb_linearize(skb))
+@@ -2622,6 +2619,8 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+
+ offload.tx_ring = tx_ring;
+
++ /* record the location of the first descriptor for this packet */
++ first = &tx_ring->tx_buf[tx_ring->next_to_use];
+ first->skb = skb;
+ first->type = ICE_TX_BUF_SKB;
+ first->bytecount = max_t(unsigned int, skb->len, ETH_ZLEN);
+@@ -2686,7 +2685,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+ out_drop:
+ ice_trace(xmit_frame_ring_drop, tx_ring, skb);
+ dev_kfree_skb_any(skb);
+- first->type = ICE_TX_BUF_EMPTY;
+ return NETDEV_TX_OK;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From eafbcb9f51dc7061cc6b9f26c2302151d5e35aa2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:43:10 -0400
+Subject: Revert "ice: Remove jumbo_remove step from TX path"
+
+This reverts commit 55500245ec0420df96b2a89444aabf0cff2c60bc.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_txrx.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
+index 90dbe5266ce78..73f08d02f9c76 100644
+--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
+@@ -2594,6 +2594,9 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+
+ ice_trace(xmit_frame_ring, tx_ring, skb);
+
++ if (unlikely(ipv6_hopopt_jumbo_remove(skb)))
++ goto out_drop;
++
+ count = ice_xmit_desc_count(skb);
+ if (ice_chk_linearize(skb, count)) {
+ if (__skb_linearize(skb))
+--
+2.53.0
+
ata-libata-scsi-do-not-use-the-deferred-qc-feature-for-ata_defer_port.patch
ata-libata-scsi-do-not-use-the-deferred-qc-feature-on-pmps-with-cbs.patch
ata-libata-scsi-do-not-needlessly-defer-commands-when-using-pmp-with-fbs.patch
+revert-ice-fix-double-free-of-tx_buf-skb.patch
+revert-ice-remove-jumbo_remove-step-from-tx-path.patch
+drm-vblank-add-vblank-timer.patch
+drm-vblank-add-crtc-helpers-for-simple-use-cases.patch
+drm-vkms-convert-to-drm-s-vblank-timer.patch
+drm-atomic-increase-timeout-in-drm_atomic_helper_wai.patch
+drm-vblank-fix-kernel-docs-for-vblank-timer.patch
--- /dev/null
+From 05e5798e389f1bc3a815f1eeefd0c0c2641bbbd0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 14:20:39 +0800
+Subject: i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit b795e68bf3073d67bebbb5a44d93f49efc5b8cc7 ]
+
+The logic used to abort the DMA ring contains several flaws:
+
+ 1. The driver unconditionally issues a ring abort even when the ring has
+ already stopped.
+ 2. The completion used to wait for abort completion is never
+ re-initialized, resulting in incorrect wait behavior.
+ 3. The abort sequence unintentionally clears RING_CTRL_ENABLE, which
+ resets hardware ring pointers and disrupts the controller state.
+ 4. If the ring is already stopped, the abort operation should be
+ considered successful without attempting further action.
+
+Fix the abort handling by checking whether the ring is running before
+issuing an abort, re-initializing the completion when needed, ensuring that
+RING_CTRL_ENABLE remains asserted during abort, and treating an already
+stopped ring as a successful condition.
+
+Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20260306072451.11131-9-adrian.hunter@intel.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Jianqiang kang <jianqkang@sina.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/mipi-i3c-hci/dma.c | 27 +++++++++++++++++----------
+ 1 file changed, 17 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
+index 624d00b853a51..61007167606fd 100644
+--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
+@@ -448,16 +448,23 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
+ struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number];
+ unsigned int i;
+ bool did_unqueue = false;
+-
+- /* stop the ring */
+- rh_reg_write(RING_CONTROL, RING_CTRL_ABORT);
+- if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) {
+- /*
+- * We're deep in it if ever this condition is ever met.
+- * Hardware might still be writing to memory, etc.
+- */
+- dev_crit(&hci->master.dev, "unable to abort the ring\n");
+- WARN_ON(1);
++ u32 ring_status;
++
++ ring_status = rh_reg_read(RING_STATUS);
++ if (ring_status & RING_STATUS_RUNNING) {
++ /* stop the ring */
++ reinit_completion(&rh->op_done);
++ rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);
++ wait_for_completion_timeout(&rh->op_done, HZ);
++ ring_status = rh_reg_read(RING_STATUS);
++ if (ring_status & RING_STATUS_RUNNING) {
++ /*
++ * We're deep in it if ever this condition is ever met.
++ * Hardware might still be writing to memory, etc.
++ */
++ dev_crit(&hci->master.dev, "unable to abort the ring\n");
++ WARN_ON(1);
++ }
+ }
+
+ for (i = 0; i < n; i++) {
+--
+2.53.0
+
--- /dev/null
+From 4936aa60494249ff9b7c7521fb9efef33ede4b8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:04:10 -0400
+Subject: Revert "af_unix: Reject SIOCATMARK on non-stream sockets"
+
+This reverts commit 0d7e7235bc543c6ed7b873e3015db814d8e8c414.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/af_unix.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index c621f00902752..8f785b2600ae4 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2809,9 +2809,6 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
+ goto out;
+ }
+
+- if (sk->sk_type != SOCK_STREAM)
+- return -EOPNOTSUPP;
+-
+ mutex_lock(&u->iolock);
+ goto redo;
+ unlock:
+--
+2.53.0
+
--- /dev/null
+From db24f54e9526802a835bd0142be95c76f5e7ade1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:55:37 -0400
+Subject: Revert "ice: fix double-free of tx_buf skb"
+
+This reverts commit ca6f9d9aee5408c47e6c0fac10955cb6825ecd96.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_txrx.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
+index 4e110a008a257..66da8a34be0f1 100644
+--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
+@@ -2364,9 +2364,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+
+ ice_trace(xmit_frame_ring, tx_ring, skb);
+
+- /* record the location of the first descriptor for this packet */
+- first = &tx_ring->tx_buf[tx_ring->next_to_use];
+-
+ count = ice_xmit_desc_count(skb);
+ if (ice_chk_linearize(skb, count)) {
+ if (__skb_linearize(skb))
+@@ -2392,6 +2389,8 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+
+ offload.tx_ring = tx_ring;
+
++ /* record the location of the first descriptor for this packet */
++ first = &tx_ring->tx_buf[tx_ring->next_to_use];
+ first->skb = skb;
+ first->type = ICE_TX_BUF_SKB;
+ first->bytecount = max_t(unsigned int, skb->len, ETH_ZLEN);
+@@ -2453,7 +2452,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+ out_drop:
+ ice_trace(xmit_frame_ring_drop, tx_ring, skb);
+ dev_kfree_skb_any(skb);
+- first->type = ICE_TX_BUF_EMPTY;
+ return NETDEV_TX_OK;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 5120d53452c0531c33ff477f195a7c2b2213affb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 12:55:37 -0400
+Subject: Revert "ice: Remove jumbo_remove step from TX path"
+
+This reverts commit a753619ffecfe629ee73c821469edd8b37c72d3b.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_txrx.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
+index 66da8a34be0f1..eae4376c68595 100644
+--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
+@@ -2364,6 +2364,9 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
+
+ ice_trace(xmit_frame_ring, tx_ring, skb);
+
++ if (unlikely(ipv6_hopopt_jumbo_remove(skb)))
++ goto out_drop;
++
+ count = ice_xmit_desc_count(skb);
+ if (ice_chk_linearize(skb, count)) {
+ if (__skb_linearize(skb))
+--
+2.53.0
+
--- /dev/null
+From 17b1afa05c17845b837c24b5151c8b86b05957f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:03:59 -0400
+Subject: Revert "s390/cio: Update purge function to unregister the unused
+ subchannels"
+
+This reverts commit c34b09cbd6fc06f0f234182e462a1b010d13a5a6.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/cio/device.c | 37 +++++++++++++------------------------
+ 1 file changed, 13 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
+index 93307ca75c10b..e623359862ea2 100644
+--- a/drivers/s390/cio/device.c
++++ b/drivers/s390/cio/device.c
+@@ -1318,34 +1318,23 @@ void ccw_device_schedule_recovery(void)
+ spin_unlock_irqrestore(&recovery_lock, flags);
+ }
+
+-static int purge_fn(struct subchannel *sch, void *data)
++static int purge_fn(struct device *dev, void *data)
+ {
+- struct ccw_device *cdev;
+-
+- spin_lock_irq(sch->lock);
+- if (sch->st != SUBCHANNEL_TYPE_IO || !sch->schib.pmcw.dnv)
+- goto unlock;
+-
+- if (!is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev))
+- goto unlock;
+-
+- cdev = sch_get_cdev(sch);
+- if (cdev) {
+- if (cdev->private->state != DEV_STATE_OFFLINE)
+- goto unlock;
++ struct ccw_device *cdev = to_ccwdev(dev);
++ struct ccw_dev_id *id = &cdev->private->dev_id;
++ struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
+- if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
+- goto unlock;
++ spin_lock_irq(cdev->ccwlock);
++ if (is_blacklisted(id->ssid, id->devno) &&
++ (cdev->private->state == DEV_STATE_OFFLINE) &&
++ (atomic_cmpxchg(&cdev->private->onoff, 0, 1) == 0)) {
++ CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", id->ssid,
++ id->devno);
+ ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
++ css_sched_sch_todo(sch, SCH_TODO_UNREG);
+ atomic_set(&cdev->private->onoff, 0);
+ }
+-
+- css_sched_sch_todo(sch, SCH_TODO_UNREG);
+- CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x%s\n", sch->schid.ssid,
+- sch->schib.pmcw.dev, cdev ? "" : " (no cdev)");
+-
+-unlock:
+- spin_unlock_irq(sch->lock);
++ spin_unlock_irq(cdev->ccwlock);
+ /* Abort loop in case of pending signal. */
+ if (signal_pending(current))
+ return -EINTR;
+@@ -1361,7 +1350,7 @@ static int purge_fn(struct subchannel *sch, void *data)
+ int ccw_purge_blacklisted(void)
+ {
+ CIO_MSG_EVENT(2, "ccw: purging blacklisted devices\n");
+- for_each_subchannel_staged(purge_fn, NULL, NULL);
++ bus_for_each_dev(&ccw_bus_type, NULL, NULL, purge_fn);
+ return 0;
+ }
+
+--
+2.53.0
+
ksmbd-close-durable-scavenger-races-against-m_fp_lis.patch
af_unix-give-up-gc-if-msg_peek-intervened.patch
smb-client-reject-userspace-cifs.spnego-descriptions.patch
+revert-ice-fix-double-free-of-tx_buf-skb.patch
+revert-ice-remove-jumbo_remove-step-from-tx-path.patch
+revert-s390-cio-update-purge-function-to-unregister-.patch
+revert-af_unix-reject-siocatmark-on-non-stream-socke.patch
+i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in.patch