--- /dev/null
+From 7a3b884834625ff8d0d4e7a8cdf105920ba6fc16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 00:54:59 +0800
+Subject: ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f6484cadbcaf26b5844b51bd7307a663dda48ef6 ]
+
+When ec_install_handlers() returns -EPROBE_DEFER on reduced-hardware
+platforms, it has already started the EC and installed the address
+space handler with the struct acpi_ec pointer as handler context.
+However, acpi_ec_setup() propagates the error without any cleanup.
+
+The caller acpi_ec_add() then frees the struct acpi_ec for non-boot
+instances, leaving a dangling handler context in ACPICA.
+
+Any subsequent AML evaluation that accesses an EC OpRegion field
+dispatches into acpi_ec_space_handler() with the freed pointer,
+causing a use-after-free:
+
+ BUG: KASAN: slab-use-after-free in mutex_lock (kernel/locking/mutex.c:289)
+ Write of size 8 at addr ffff88800721de38 by task init/1
+ Call Trace:
+ <TASK>
+ mutex_lock (kernel/locking/mutex.c:289)
+ acpi_ec_space_handler (drivers/acpi/ec.c:1362)
+ acpi_ev_address_space_dispatch (drivers/acpi/acpica/evregion.c:293)
+ acpi_ex_access_region (drivers/acpi/acpica/exfldio.c:246)
+ acpi_ex_field_datum_io (drivers/acpi/acpica/exfldio.c:509)
+ acpi_ex_extract_from_field (drivers/acpi/acpica/exfldio.c:700)
+ acpi_ex_read_data_from_field (drivers/acpi/acpica/exfield.c:327)
+ acpi_ex_resolve_node_to_value (drivers/acpi/acpica/exresolv.c:392)
+ </TASK>
+
+ Allocated by task 1:
+ acpi_ec_alloc (drivers/acpi/ec.c:1424)
+ acpi_ec_add (drivers/acpi/ec.c:1692)
+
+ Freed by task 1:
+ kfree (mm/slub.c:6876)
+ acpi_ec_add (drivers/acpi/ec.c:1751)
+
+The bug triggers on reduced-hardware EC platforms (ec->gpe < 0)
+when the GPIO IRQ provider defers probing. Once the stale handler
+exists, any unprivileged sysfs read that causes AML to touch an
+EC OpRegion (battery, thermal, backlight) exercises the dangling
+pointer.
+
+Fix this by calling ec_remove_handlers() in the error path of
+acpi_ec_setup() before clearing first_ec. ec_remove_handlers()
+checks each EC_FLAGS_* bit before acting, so it is safe to call
+regardless of how far ec_install_handlers() progressed:
+
+ -ENODEV (handler not installed): only calls acpi_ec_stop()
+ -EPROBE_DEFER (handler installed): removes handler, stops EC
+
+Fixes: 03e9a0e05739 ("ACPI: EC: Consolidate event handler installation code")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 1d7e7e47ea0e4..aaf0add0dc081 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1636,6 +1636,8 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+
+ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret) {
++ ec_remove_handlers(ec);
++
+ if (ec == first_ec)
+ first_ec = NULL;
+
+--
+2.53.0
+
--- /dev/null
+From b48ce2fd05d2c29e570b3b53dda6f2a7e9680e09 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:34 +0100
+Subject: ACPI: EC: Fix EC address space handler unregistration
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit a5072078dbfaa9d70130805766dfa34bbb7bf2a7 ]
+
+When an ECDT table is present the EC address space handler gets registered
+on the root node. So to unregister it properly the unregister call also
+must be done on the root node.
+
+Store the ACPI handle used for the acpi_install_address_space_handler()
+call and use te same handle for the acpi_remove_address_space_handler()
+call.
+
+Reported-by: Rafael J. Wysocki <rafael@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 4 +++-
+ drivers/acpi/internal.h | 1 +
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index b20206316fbe4..bf829ebc9afee 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1526,6 +1526,7 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+ return -ENODEV;
+ }
+ set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
++ ec->address_space_handler_holder = ec->handle;
+ }
+
+ if (!device)
+@@ -1577,7 +1578,8 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+ static void ec_remove_handlers(struct acpi_ec *ec)
+ {
+ if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+- if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
++ if (ACPI_FAILURE(acpi_remove_address_space_handler(
++ ec->address_space_handler_holder,
+ ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
+ pr_err("failed to remove space handler\n");
+ clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
+index f6c929787c9e6..4edf591f8a3a5 100644
+--- a/drivers/acpi/internal.h
++++ b/drivers/acpi/internal.h
+@@ -169,6 +169,7 @@ static inline void acpi_early_processor_osc(void) {}
+ -------------------------------------------------------------------------- */
+ struct acpi_ec {
+ acpi_handle handle;
++ acpi_handle address_space_handler_holder;
+ int gpe;
+ int irq;
+ unsigned long command_addr;
+--
+2.53.0
+
--- /dev/null
+From 1cb9837a706fe6a86a1c26f82604f7f852259ff6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:35 +0100
+Subject: ACPI: EC: Fix ECDT probe ordering issues
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit ab4620f58d38206687b9f99d9d2cc1d5a2640985 ]
+
+ACPI-2.0 says that the EC OpRegion handler must be available immediately
+(like the standard default OpRegion handlers):
+
+Quoting from the ACPI spec version 6.3: "6.5.4 _REG (Region) ...
+2. OSPM must make Embedded Controller operation regions, accessed via
+the Embedded Controllers described in ECDT, available before executing
+any control method. These operation regions may become inaccessible
+after OSPM runs _REG(EmbeddedControl, 0)."
+
+So acpi_bus_init() calls acpi_ec_ecdt_probe(), which calls
+acpi_install_address_space_handler() to install the EC's OpRegion
+handler, early on.
+
+This not only installs the OpRegion handler, but also calls the EC's
+_REG method. The _REG method call is a problem because it may rely on
+initialization done by the _INI methods of one of the PCI / _SB root devs,
+see for example: https://bugzilla.kernel.org/show_bug.cgi?id=214899 .
+
+Generally speaking _REG methods are executed when the ACPI-device they
+are part of has a driver bound to it. Where as _INI methods must be
+executed at table load time (according to the spec). The problem here
+is that the early acpi_install_address_space_handler() call causes
+the _REG handler to run too early.
+
+To allow fixing this the ACPICA code now allows to split the OpRegion
+handler installation and the executing of _REG into 2 separate steps.
+
+This commit uses this ACPICA functionality to fix the EC probe ordering
+by delaying the executing of _REG for ECDT described ECs till the matching
+EC device in the DSDT gets parsed and acpi_ec_add() for it gets called.
+This moves the calling of _REG for the EC on devices with an ECDT to
+the same point in time where it is called on devices without an ECDT table.
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214899
+Reported-and-tested-by: Johannes Penßel <johannespenssel@posteo.net>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 28 ++++++++++++++++++----------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index bf829ebc9afee..10f7e3ef58791 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -96,6 +96,7 @@ enum {
+ EC_FLAGS_QUERY_GUARDING, /* Guard for SCI_EVT check */
+ EC_FLAGS_EVENT_HANDLER_INSTALLED, /* Event handler installed */
+ EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */
++ EC_FLAGS_EC_REG_CALLED, /* OpReg ACPI _REG method called */
+ EC_FLAGS_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */
+ EC_FLAGS_STARTED, /* Driver is started */
+ EC_FLAGS_STOPPED, /* Driver is stopped */
+@@ -1497,6 +1498,7 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+ * ec_install_handlers - Install service callbacks and register query methods.
+ * @ec: Target EC.
+ * @device: ACPI device object corresponding to @ec.
++ * @call_reg: If _REG should be called to notify OpRegion availability
+ *
+ * Install a handler for the EC address space type unless it has been installed
+ * already. If @device is not NULL, also look for EC query methods in the
+@@ -1509,7 +1511,8 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+ * -EPROBE_DEFER if GPIO IRQ acquisition needs to be deferred,
+ * or 0 (success) otherwise.
+ */
+-static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
++static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
++ bool call_reg)
+ {
+ acpi_status status;
+
+@@ -1517,10 +1520,10 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+
+ if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ acpi_ec_enter_noirq(ec);
+- status = acpi_install_address_space_handler(ec->handle,
+- ACPI_ADR_SPACE_EC,
+- &acpi_ec_space_handler,
+- NULL, ec);
++ status = acpi_install_address_space_handler_no_reg(ec->handle,
++ ACPI_ADR_SPACE_EC,
++ &acpi_ec_space_handler,
++ NULL, ec);
+ if (ACPI_FAILURE(status)) {
+ acpi_ec_stop(ec, false);
+ return -ENODEV;
+@@ -1529,6 +1532,11 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+ ec->address_space_handler_holder = ec->handle;
+ }
+
++ if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) {
++ acpi_execute_reg_methods(ec->handle, ACPI_ADR_SPACE_EC);
++ set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
++ }
++
+ if (!device)
+ return 0;
+
+@@ -1615,11 +1623,11 @@ static void ec_remove_handlers(struct acpi_ec *ec)
+ }
+ }
+
+-static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device)
++static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool call_reg)
+ {
+ int ret;
+
+- ret = ec_install_handlers(ec, device);
++ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret)
+ return ret;
+
+@@ -1681,7 +1689,7 @@ static int acpi_ec_add(struct acpi_device *device)
+ }
+ }
+
+- ret = acpi_ec_setup(ec, device);
++ ret = acpi_ec_setup(ec, device, true);
+ if (ret)
+ goto err;
+
+@@ -1801,7 +1809,7 @@ void __init acpi_ec_dsdt_probe(void)
+ * At this point, the GPE is not fully initialized, so do not to
+ * handle the events.
+ */
+- ret = acpi_ec_setup(ec, NULL);
++ ret = acpi_ec_setup(ec, NULL, true);
+ if (ret) {
+ acpi_ec_free(ec);
+ return;
+@@ -1965,7 +1973,7 @@ void __init acpi_ec_ecdt_probe(void)
+ * At this point, the namespace is not initialized, so do not find
+ * the namespace objects, or handle the events.
+ */
+- ret = acpi_ec_setup(ec, NULL);
++ ret = acpi_ec_setup(ec, NULL, false);
+ if (ret) {
+ acpi_ec_free(ec);
+ goto out;
+--
+2.53.0
+
--- /dev/null
+From 514c9d3959d766ac3a578cd1b42e88a3293fc078 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 May 2024 21:40:54 +0200
+Subject: ACPI: EC: Install address space handler at the namespace root
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 60fa6ae6e6d09e377fce6f8d9b6f6a4d88769f63 ]
+
+It is reported that _DSM evaluation fails in ucsi_acpi_dsm() on Lenovo
+IdeaPad Pro 5 due to a missing address space handler for the EC address
+space:
+
+ ACPI Error: No handler for Region [ECSI] (000000007b8176ee) [EmbeddedControl] (20230628/evregion-130)
+
+This happens because if there is no ECDT, the EC driver only registers
+the EC address space handler for operation regions defined in the EC
+device scope of the ACPI namespace while the operation region being
+accessed by the _DSM in question is located beyond that scope.
+
+To address this, modify the ACPI EC driver to install the EC address
+space handler at the root of the ACPI namespace for the first EC that
+can be found regardless of whether or not an ECDT is present.
+
+Note that this change is consistent with some examples in the ACPI
+specification in which EC operation regions located outside the EC
+device scope are used (for example, see Section 9.17.15 in ACPI 6.5),
+so the current behavior of the EC driver is arguably questionable.
+
+Reported-by: webcaptcha <webcapcha@gmail.com>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=218789
+Link: https://uefi.org/specs/ACPI/6.5/09_ACPI_Defined_Devices_and_Device_Specific_Objects.html#example-asl-code
+Link: https://lore.kernel.org/linux-acpi/Zi+0whTvDbAdveHq@kuha.fi.intel.com
+Suggested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 25 ++++++++++++++++---------
+ drivers/acpi/internal.h | 1 -
+ 2 files changed, 16 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 10f7e3ef58791..1d7e7e47ea0e4 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1514,13 +1514,14 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
+ bool call_reg)
+ {
++ acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle;
+ acpi_status status;
+
+ acpi_ec_start(ec, false);
+
+ if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ acpi_ec_enter_noirq(ec);
+- status = acpi_install_address_space_handler_no_reg(ec->handle,
++ status = acpi_install_address_space_handler_no_reg(scope_handle,
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler,
+ NULL, ec);
+@@ -1529,11 +1530,10 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
+ return -ENODEV;
+ }
+ set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+- ec->address_space_handler_holder = ec->handle;
+ }
+
+ if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) {
+- acpi_execute_reg_methods(ec->handle, ACPI_ADR_SPACE_EC);
++ acpi_execute_reg_methods(scope_handle, ACPI_ADR_SPACE_EC);
+ set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
+ }
+
+@@ -1585,10 +1585,13 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
+
+ static void ec_remove_handlers(struct acpi_ec *ec)
+ {
++ acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle;
++
+ if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ if (ACPI_FAILURE(acpi_remove_address_space_handler(
+- ec->address_space_handler_holder,
+- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
++ scope_handle,
++ ACPI_ADR_SPACE_EC,
++ &acpi_ec_space_handler)))
+ pr_err("failed to remove space handler\n");
+ clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+ }
+@@ -1627,14 +1630,18 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+ {
+ int ret;
+
+- ret = ec_install_handlers(ec, device, call_reg);
+- if (ret)
+- return ret;
+-
+ /* First EC capable of handling transactions */
+ if (!first_ec)
+ first_ec = ec;
+
++ ret = ec_install_handlers(ec, device, call_reg);
++ if (ret) {
++ if (ec == first_ec)
++ first_ec = NULL;
++
++ return ret;
++ }
++
+ pr_info("EC_CMD/EC_SC=0x%lx, EC_DATA=0x%lx\n", ec->command_addr,
+ ec->data_addr);
+
+diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
+index 4edf591f8a3a5..f6c929787c9e6 100644
+--- a/drivers/acpi/internal.h
++++ b/drivers/acpi/internal.h
+@@ -169,7 +169,6 @@ static inline void acpi_early_processor_osc(void) {}
+ -------------------------------------------------------------------------- */
+ struct acpi_ec {
+ acpi_handle handle;
+- acpi_handle address_space_handler_holder;
+ int gpe;
+ int irq;
+ unsigned long command_addr;
+--
+2.53.0
+
--- /dev/null
+From e2a118c9fd0e0ff62fc8dc7ba053271aa71fa2b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:33 +0100
+Subject: ACPICA: Allow address_space_handler Install and _REG execution as 2
+ separate steps
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 54c516aeb8b39eeae6450b7d8076d381568dca46 ]
+
+ACPI-2.0 says that the EC op_region handler must be available immediately
+(like the standard default op_region handlers):
+
+Quoting from the ACPI spec version 6.3: "6.5.4 _REG (Region) ...
+2. OSPM must make Embedded Controller operation regions, accessed via
+the Embedded Controllers described in ECDT, available before executing
+any control method. These operation regions may become inaccessible
+after OSPM runs _REG(EmbeddedControl, 0)."
+
+So the OS must probe the ECDT described EC and install the OpRegion handler
+before calling acpi_enable_subsystem() and acpi_initialize_objects().
+
+This is a problem because calling acpi_install_address_space_handler()
+does not just install the op_region handler, it also runs the EC's _REG
+method. This _REG method may rely on initialization done by the _INI
+methods of one of the PCI / _SB root devices.
+
+For the other early/default op_region handlers the op_region handler
+install and the _REG execution is split into 2 separate steps:
+1. acpi_ev_install_region_handlers(), called early from acpi_load_tables()
+2. acpi_ev_initialize_op_regions(), called from acpi_initialize_objects()
+
+To fix the EC op_region issue, add 2 bew functions:
+1. acpi_install_address_space_handler_no_reg()
+2. acpi_execute_reg_methods()
+to allow doing things in 2 steps for other op_region handlers,
+like the EC handler, too.
+
+Note that the comment describing acpi_ev_install_region_handlers() even has
+an alinea describing this problem. Using the new methods allows users
+to avoid this problem.
+
+Link: https://github.com/acpica/acpica/pull/786
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=214899
+Reported-and-tested-by: Johannes Penßel <johannespenssel@posteo.net>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/evxfregn.c | 92 +++++++++++++++++++++++++++++++---
+ include/acpi/acpixf.h | 10 ++++
+ 2 files changed, 95 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
+index da97fd0c6b51e..12384b3cdd6ed 100644
+--- a/drivers/acpi/acpica/evxfregn.c
++++ b/drivers/acpi/acpica/evxfregn.c
+@@ -20,13 +20,14 @@ ACPI_MODULE_NAME("evxfregn")
+
+ /*******************************************************************************
+ *
+- * FUNCTION: acpi_install_address_space_handler
++ * FUNCTION: acpi_install_address_space_handler_internal
+ *
+ * PARAMETERS: device - Handle for the device
+ * space_id - The address space ID
+ * handler - Address of the handler
+ * setup - Address of the setup function
+ * context - Value passed to the handler on each access
++ * Run_reg - Run _REG methods for this address space?
+ *
+ * RETURN: Status
+ *
+@@ -37,13 +38,16 @@ ACPI_MODULE_NAME("evxfregn")
+ * are executed here, and these methods can only be safely executed after
+ * the default handlers have been installed and the hardware has been
+ * initialized (via acpi_enable_subsystem.)
++ * To avoid this problem pass FALSE for Run_Reg and later on call
++ * acpi_execute_reg_methods() to execute _REG.
+ *
+ ******************************************************************************/
+-acpi_status
+-acpi_install_address_space_handler(acpi_handle device,
+- acpi_adr_space_type space_id,
+- acpi_adr_space_handler handler,
+- acpi_adr_space_setup setup, void *context)
++static acpi_status
++acpi_install_address_space_handler_internal(acpi_handle device,
++ acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup,
++ void *context, u8 run_reg)
+ {
+ struct acpi_namespace_node *node;
+ acpi_status status;
+@@ -80,14 +84,40 @@ acpi_install_address_space_handler(acpi_handle device,
+
+ /* Run all _REG methods for this address space */
+
+- acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
++ if (run_reg) {
++ acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
++ }
+
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
+ }
+
++acpi_status
++acpi_install_address_space_handler(acpi_handle device,
++ acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup, void *context)
++{
++ return acpi_install_address_space_handler_internal(device, space_id,
++ handler, setup,
++ context, TRUE);
++}
++
+ ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
++acpi_status
++acpi_install_address_space_handler_no_reg(acpi_handle device,
++ acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup,
++ void *context)
++{
++ return acpi_install_address_space_handler_internal(device, space_id,
++ handler, setup,
++ context, FALSE);
++}
++
++ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler_no_reg)
+
+ /*******************************************************************************
+ *
+@@ -226,3 +256,51 @@ acpi_remove_address_space_handler(acpi_handle device,
+ }
+
+ ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_execute_reg_methods
++ *
++ * PARAMETERS: device - Handle for the device
++ * space_id - The address space ID
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Execute _REG for all op_regions of a given space_id.
++ *
++ ******************************************************************************/
++acpi_status
++acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id)
++{
++ struct acpi_namespace_node *node;
++ acpi_status status;
++
++ ACPI_FUNCTION_TRACE(acpi_execute_reg_methods);
++
++ /* Parameter validation */
++
++ if (!device) {
++ return_ACPI_STATUS(AE_BAD_PARAMETER);
++ }
++
++ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ /* Convert and validate the device handle */
++
++ node = acpi_ns_validate_handle(device);
++ if (node) {
++
++ /* Run all _REG methods for this address space */
++
++ acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
++ } else {
++ status = AE_BAD_PARAMETER;
++ }
++
++ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
++ return_ACPI_STATUS(status);
++}
++
++ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods)
+diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
+index f9a86e3329715..890dbb8cc806a 100644
+--- a/include/acpi/acpixf.h
++++ b/include/acpi/acpixf.h
+@@ -650,6 +650,16 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+ acpi_adr_space_setup
+ setup,
+ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_address_space_handler_no_reg
++ (acpi_handle device, acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup,
++ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_execute_reg_methods(acpi_handle device,
++ acpi_adr_space_type
++ space_id))
+ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+ acpi_remove_address_space_handler(acpi_handle
+ device,
+--
+2.53.0
+
--- /dev/null
+From d8344b851905753191ed1dea37b9150f2c90d8fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:32 +0100
+Subject: ACPICA: include/acpi/acpixf.h: Fix indentation
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 7a9d74e7e403cb2e60d4d00c05f2f3ab2a33d0c3 ]
+
+A bunch of the functions declared in include/acpi/acpixf.h have their
+name aligned a space after the '(' of e.g. the
+`ACPI_EXTERNAL_RETURN_STATUS(acpi_status` line above rather then being
+directly aligned after the '('.
+
+This breaks applying patches generated from the ACPICA upstream git,
+remove the extra space before the function-names and all the arguments
+to fix this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/acpi/acpixf.h | 120 +++++++++++++++++++++---------------------
+ 1 file changed, 60 insertions(+), 60 deletions(-)
+
+diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
+index be7de305a6220..f9a86e3329715 100644
+--- a/include/acpi/acpixf.h
++++ b/include/acpi/acpixf.h
+@@ -587,82 +587,82 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+ acpi_install_initialization_handler
+ (acpi_init_handler handler, u32 function))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_sci_handler(acpi_sci_handler
+- address,
+- void *context))
+-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_remove_sci_handler(acpi_sci_handler
+- address))
++ acpi_install_sci_handler(acpi_sci_handler
++ address,
++ void *context))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_global_event_handler
+- (acpi_gbl_event_handler handler,
+- void *context))
++ acpi_remove_sci_handler(acpi_sci_handler
++ address))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_fixed_event_handler(u32
+- acpi_event,
+- acpi_event_handler
+- handler,
+- void
+- *context))
++ acpi_install_global_event_handler
++ (acpi_gbl_event_handler handler,
++ void *context))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_remove_fixed_event_handler(u32 acpi_event,
++ acpi_install_fixed_event_handler(u32
++ acpi_event,
+ acpi_event_handler
+- handler))
+-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_gpe_handler(acpi_handle
+- gpe_device,
+- u32 gpe_number,
+- u32 type,
+- acpi_gpe_handler
+- address,
+- void *context))
++ handler,
++ void
++ *context))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_gpe_raw_handler(acpi_handle
+- gpe_device,
+- u32 gpe_number,
+- u32 type,
+- acpi_gpe_handler
+- address,
+- void *context))
++ acpi_remove_fixed_event_handler(u32 acpi_event,
++ acpi_event_handler
++ handler))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_remove_gpe_handler(acpi_handle gpe_device,
++ acpi_install_gpe_handler(acpi_handle
++ gpe_device,
+ u32 gpe_number,
++ u32 type,
+ acpi_gpe_handler
+- address))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_notify_handler(acpi_handle device,
+- u32 handler_type,
+- acpi_notify_handler
+- handler,
++ address,
+ void *context))
++ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
++ acpi_install_gpe_raw_handler(acpi_handle
++ gpe_device,
++ u32 gpe_number,
++ u32 type,
++ acpi_gpe_handler
++ address,
++ void *context))
++ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
++ acpi_remove_gpe_handler(acpi_handle gpe_device,
++ u32 gpe_number,
++ acpi_gpe_handler
++ address))
+ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_remove_notify_handler(acpi_handle device,
++ acpi_install_notify_handler(acpi_handle device,
+ u32 handler_type,
+ acpi_notify_handler
+- handler))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_address_space_handler(acpi_handle
+- device,
+- acpi_adr_space_type
+- space_id,
+- acpi_adr_space_handler
+- handler,
+- acpi_adr_space_setup
+- setup,
+- void *context))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_remove_address_space_handler(acpi_handle
++ handler,
++ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_remove_notify_handler(acpi_handle device,
++ u32 handler_type,
++ acpi_notify_handler
++ handler))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_address_space_handler(acpi_handle
+ device,
+ acpi_adr_space_type
+ space_id,
+ acpi_adr_space_handler
+- handler))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_exception_handler
+- (acpi_exception_handler handler))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_interface_handler
+- (acpi_interface_handler handler))
++ handler,
++ acpi_adr_space_setup
++ setup,
++ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_remove_address_space_handler(acpi_handle
++ device,
++ acpi_adr_space_type
++ space_id,
++ acpi_adr_space_handler
++ handler))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_exception_handler
++ (acpi_exception_handler handler))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_interface_handler
++ (acpi_interface_handler handler))
+
+ /*
+ * Global Lock interfaces
+--
+2.53.0
+
--- /dev/null
+From 743e62c56e1b53e8655125cd977217778b4a4c88 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 11:12:17 +0100
+Subject: ASoC: Intel: catpt: Fix the device initialization
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 5a184f1cb43a8e035251c635f5c47da5dc3e3049 ]
+
+The DMA mask shall be coerced before any buffer allocations for the
+device are done. At the same time explain why DMA mask of 31 bits is
+used in the first place.
+
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle")
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/catpt/device.c | 10 +++++++++-
+ sound/soc/intel/catpt/dsp.c | 3 ---
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c
+index a701799597956..db67509f051ad 100644
+--- a/sound/soc/intel/catpt/device.c
++++ b/sound/soc/intel/catpt/device.c
+@@ -263,7 +263,15 @@ static int catpt_acpi_probe(struct platform_device *pdev)
+ if (IS_ERR(cdev->pci_ba))
+ return PTR_ERR(cdev->pci_ba);
+
+- /* alloc buffer for storing DRAM context during dx transitions */
++ /*
++ * As per design HOST is responsible for preserving firmware's runtime
++ * context during D0 -> D3 -> D0 transitions. Addresses used for DMA
++ * to/from HOST memory shall be outside the reserved range of 0xFFFxxxxx.
++ */
++ ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
++ if (ret)
++ return ret;
++
+ cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev),
+ &cdev->dxbuf_paddr, GFP_KERNEL);
+ if (!cdev->dxbuf_vaddr)
+diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
+index 38a92bbc1ed56..2c67d2d35cdae 100644
+--- a/sound/soc/intel/catpt/dsp.c
++++ b/sound/soc/intel/catpt/dsp.c
+@@ -125,9 +125,6 @@ int catpt_dmac_probe(struct catpt_dev *cdev)
+ dmac->dev = cdev->dev;
+ dmac->irq = cdev->irq;
+
+- ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
+- if (ret)
+- return ret;
+ /*
+ * Caller is responsible for putting device in D0 to allow
+ * for I/O and memory access before probing DW.
+--
+2.53.0
+
--- /dev/null
+From 7634ce3e3b63738496bff0621ed1abf9309dd70f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 16:19:19 -0700
+Subject: drm/i915/gmbus: fix spurious timeout on 512-byte burst reads
+
+From: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+
+[ Upstream commit 08441f10f4dc09fdeb64529953ac308abc79dd38 ]
+
+When reading exactly 512 bytes with burst read enabled, the
+extra_byte_added path breaks out of the inner do-while without
+decrementing len. The outer while(len) then re-enters and gmbus_wait()
+times out since all data has been delivered. Decrement len before the
+break so the outer loop terminates correctly.
+
+Fixes: d5dc0f43f268 ("drm/i915/gmbus: Enable burst read")
+Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_gmbus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
+index e6b8d6dfb598e..831e99c56ecb0 100644
+--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
++++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
+@@ -420,8 +420,10 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
+
+ val = intel_de_read_fw(dev_priv, GMBUS3);
+ do {
+- if (extra_byte_added && len == 1)
++ if (extra_byte_added && len == 1) {
++ len--;
+ break;
++ }
+
+ *buf++ = val & 0xff;
+ val >>= 8;
+--
+2.53.0
+
--- /dev/null
+From 9d1cc7f8e4563cad6be52f99ca89a6e1a85abf3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 05:13:06 +0000
+Subject: hwmon: (adm1177) fix sysfs ABI violation and current unit conversion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sanman Pradhan <psanman@juniper.net>
+
+[ Upstream commit bf08749a6abb6d1959bfdc0edc32c640df407558 ]
+
+The adm1177 driver exposes the current alert threshold through
+hwmon_curr_max_alarm. This violates the hwmon sysfs ABI, where
+*_alarm attributes are read-only status flags and writable thresholds
+must use currN_max.
+
+The driver also stores the threshold internally in microamps, while
+currN_max is defined in milliamps. Convert the threshold accordingly
+on both the read and write paths.
+
+Widen the cached threshold and related calculations to 64 bits so
+that small shunt resistor values do not cause truncation or overflow.
+Also use 64-bit arithmetic for the mA/uA conversions, clamp writes
+to the range the hardware can represent, and propagate failures from
+adm1177_write_alert_thr() instead of silently ignoring them.
+
+Update the hwmon documentation to reflect the attribute rename and
+the correct units returned by the driver.
+
+Fixes: 09b08ac9e8d5 ("hwmon: (adm1177) Add ADM1177 Hot Swap Controller and Digital Power Monitor driver")
+Signed-off-by: Sanman Pradhan <psanman@juniper.net>
+Acked-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/adm1177.rst | 8 ++---
+ drivers/hwmon/adm1177.c | 54 +++++++++++++++++++--------------
+ 2 files changed, 35 insertions(+), 27 deletions(-)
+
+diff --git a/Documentation/hwmon/adm1177.rst b/Documentation/hwmon/adm1177.rst
+index 471be1e98d6f6..fc0c3390c302a 100644
+--- a/Documentation/hwmon/adm1177.rst
++++ b/Documentation/hwmon/adm1177.rst
+@@ -26,10 +26,10 @@ devices explicitly. Please see :doc:`/i2c/instantiating-devices` for details.
+ Sysfs entries
+ -------------
+
+-The following attributes are supported. Current maxim attribute
++The following attributes are supported. Current maximum attribute
+ is read-write, all other attributes are read-only.
+
+-in0_input Measured voltage in microvolts.
++in0_input Measured voltage in millivolts.
+
+-curr1_input Measured current in microamperes.
+-curr1_max_alarm Overcurrent alarm in microamperes.
++curr1_input Measured current in milliamperes.
++curr1_max Overcurrent shutdown threshold in milliamperes.
+diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c
+index 6e8bb661894b9..1ddc95646f19a 100644
+--- a/drivers/hwmon/adm1177.c
++++ b/drivers/hwmon/adm1177.c
+@@ -10,6 +10,8 @@
+ #include <linux/hwmon.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
++#include <linux/math64.h>
++#include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/regulator/consumer.h>
+
+@@ -35,7 +37,7 @@ struct adm1177_state {
+ struct i2c_client *client;
+ struct regulator *reg;
+ u32 r_sense_uohm;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
+ bool vrange_high;
+ };
+
+@@ -50,7 +52,7 @@ static int adm1177_write_cmd(struct adm1177_state *st, u8 cmd)
+ }
+
+ static int adm1177_write_alert_thr(struct adm1177_state *st,
+- u32 alert_threshold_ua)
++ u64 alert_threshold_ua)
+ {
+ u64 val;
+ int ret;
+@@ -93,8 +95,8 @@ static int adm1177_read(struct device *dev, enum hwmon_sensor_types type,
+ *val = div_u64((105840000ull * dummy),
+ 4096 * st->r_sense_uohm);
+ return 0;
+- case hwmon_curr_max_alarm:
+- *val = st->alert_threshold_ua;
++ case hwmon_curr_max:
++ *val = div_u64(st->alert_threshold_ua, 1000);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+@@ -128,9 +130,10 @@ static int adm1177_write(struct device *dev, enum hwmon_sensor_types type,
+ switch (type) {
+ case hwmon_curr:
+ switch (attr) {
+- case hwmon_curr_max_alarm:
+- adm1177_write_alert_thr(st, val);
+- return 0;
++ case hwmon_curr_max:
++ val = clamp_val(val, 0,
++ div_u64(105840000ULL, st->r_sense_uohm));
++ return adm1177_write_alert_thr(st, (u64)val * 1000);
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -158,7 +161,7 @@ static umode_t adm1177_is_visible(const void *data,
+ if (st->r_sense_uohm)
+ return 0444;
+ return 0;
+- case hwmon_curr_max_alarm:
++ case hwmon_curr_max:
+ if (st->r_sense_uohm)
+ return 0644;
+ return 0;
+@@ -172,7 +175,7 @@ static umode_t adm1177_is_visible(const void *data,
+
+ static const struct hwmon_channel_info *adm1177_info[] = {
+ HWMON_CHANNEL_INFO(curr,
+- HWMON_C_INPUT | HWMON_C_MAX_ALARM),
++ HWMON_C_INPUT | HWMON_C_MAX),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT),
+ NULL
+@@ -201,7 +204,8 @@ static int adm1177_probe(struct i2c_client *client)
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct adm1177_state *st;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
++ u32 prop;
+ int ret;
+
+ st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+@@ -229,22 +233,26 @@ static int adm1177_probe(struct i2c_client *client)
+ if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
+ &st->r_sense_uohm))
+ st->r_sense_uohm = 0;
+- if (device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
+- &alert_threshold_ua)) {
+- if (st->r_sense_uohm)
+- /*
+- * set maximum default value from datasheet based on
+- * shunt-resistor
+- */
+- alert_threshold_ua = div_u64(105840000000,
+- st->r_sense_uohm);
+- else
+- alert_threshold_ua = 0;
++ if (!device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
++ &prop)) {
++ alert_threshold_ua = prop;
++ } else if (st->r_sense_uohm) {
++ /*
++ * set maximum default value from datasheet based on
++ * shunt-resistor
++ */
++ alert_threshold_ua = div_u64(105840000000ULL,
++ st->r_sense_uohm);
++ } else {
++ alert_threshold_ua = 0;
+ }
+ st->vrange_high = device_property_read_bool(dev,
+ "adi,vrange-high-enable");
+- if (alert_threshold_ua && st->r_sense_uohm)
+- adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (alert_threshold_ua && st->r_sense_uohm) {
++ ret = adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (ret)
++ return ret;
++ }
+
+ ret = adm1177_write_cmd(st, ADM1177_CMD_V_CONT |
+ ADM1177_CMD_I_CONT |
+--
+2.53.0
+
--- /dev/null
+From 7e1d2c706bc57ed164f74bba342d133707516f00 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Mar 2026 15:41:58 -0400
+Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 00da250c21b074ea9494c375d0117b69e5b1d0a4 ]
+
+When IOMMU passthrough mode is active, ib_dma_map_sgtable_attrs()
+produces no coalescing: each scatterlist page maps 1:1 to a DMA
+entry, so sgt.nents equals the raw page count. A 1 MB transfer
+yields 256 DMA entries. If that count exceeds the device's
+max_sgl_rd threshold (an optimization hint from mlx5 firmware),
+rdma_rw_io_needs_mr() steers the operation into the MR
+registration path. Each such operation consumes one or more MRs
+from a pool sized at max_rdma_ctxs -- roughly one MR per
+concurrent context. Under write-intensive workloads that issue
+many concurrent RDMA READs, the pool is rapidly exhausted,
+ib_mr_pool_get() returns NULL, and rdma_rw_init_one_mr() returns
+-EAGAIN. Upper layer protocols treat this as a fatal DMA mapping
+failure and tear down the connection.
+
+The max_sgl_rd check is a performance optimization, not a
+correctness requirement: the device can handle large SGE counts
+via direct posting, just less efficiently than with MR
+registration. When the MR pool cannot satisfy a request, falling
+back to the direct SGE (map_wrs) path avoids the connection
+reset while preserving the MR optimization for the common case
+where pool resources are available.
+
+Add a fallback in rdma_rw_ctx_init() so that -EAGAIN from
+rdma_rw_init_mr_wrs() triggers direct SGE posting instead of
+propagating the error. iWARP devices, which mandate MR
+registration for RDMA READs, and force_mr debug mode continue
+to treat -EAGAIN as terminal.
+
+Fixes: 00bd1439f464 ("RDMA/rw: Support threshold for registration vs scattering to local pages")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/rw.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
+index d479408a2cf73..58ce6c7eec4ef 100644
+--- a/drivers/infiniband/core/rw.c
++++ b/drivers/infiniband/core/rw.c
+@@ -341,14 +341,29 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
+ if (rdma_rw_io_needs_mr(qp->device, port_num, dir, sg_cnt)) {
+ ret = rdma_rw_init_mr_wrs(ctx, qp, port_num, sg, sg_cnt,
+ sg_offset, remote_addr, rkey, dir);
+- } else if (sg_cnt > 1) {
++ /*
++ * If MR init succeeded or failed for a reason other
++ * than pool exhaustion, that result is final.
++ *
++ * Pool exhaustion (-EAGAIN) from the max_sgl_rd
++ * optimization is recoverable: fall back to
++ * direct SGE posting. iWARP and force_mr require
++ * MRs unconditionally, so -EAGAIN is terminal.
++ */
++ if (ret != -EAGAIN ||
++ rdma_protocol_iwarp(qp->device, port_num) ||
++ unlikely(rdma_rw_force_mr))
++ goto out;
++ }
++
++ if (sg_cnt > 1)
+ ret = rdma_rw_init_map_wrs(ctx, qp, sg, sg_cnt, sg_offset,
+ remote_addr, rkey, dir);
+- } else {
++ else
+ ret = rdma_rw_init_single_wr(ctx, qp, sg, sg_offset,
+ remote_addr, rkey, dir);
+- }
+
++out:
+ if (ret < 0)
+ goto out_unmap_sg;
+ return ret;
+--
+2.53.0
+
--- /dev/null
+From 1e205e91476c1b853d7b34e12c6450a722e27db2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Mar 2026 19:43:31 +0100
+Subject: regmap: Synchronize cache for the page selector
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 09e70e4f119ff650d24c96161fd2f62ac7e424b0 ]
+
+If the selector register is represented in each page, its value
+according to the debugfs is stale because it gets synchronized
+only after the real page switch happens. Hence the regmap cache
+initialisation from the HW inherits outdated data in the selector
+register.
+
+Synchronize cache for the page selector just in time.
+
+Before (offset followed by hexdump, the first byte is selector):
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 05 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 01 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 02 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 03 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 04 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+After:
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 01 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 02 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 03 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 04 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+Fixes: 6863ca622759 ("regmap: Add support for register indirect addressing.")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap.c | 30 ++++++++++++++++++++++++++----
+ 1 file changed, 26 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index e86d069894c06..3ad37e5615ea4 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -1587,6 +1587,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ unsigned int val_num)
+ {
+ void *orig_work_buf;
++ unsigned int selector_reg;
+ unsigned int win_offset;
+ unsigned int win_page;
+ bool page_chg;
+@@ -1605,10 +1606,31 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ return -EINVAL;
+ }
+
+- /* It is possible to have selector register inside data window.
+- In that case, selector register is located on every page and
+- it needs no page switching, when accessed alone. */
++ /*
++ * Calculate the address of the selector register in the corresponding
++ * data window if it is located on every page.
++ */
++ page_chg = in_range(range->selector_reg, range->window_start, range->window_len);
++ if (page_chg)
++ selector_reg = range->range_min + win_page * range->window_len +
++ range->selector_reg - range->window_start;
++
++ /*
++ * It is possible to have selector register inside data window.
++ * In that case, selector register is located on every page and it
++ * needs no page switching, when accessed alone.
++ *
++ * Nevertheless we should synchronize the cache values for it.
++ * This can't be properly achieved if the selector register is
++ * the first and the only one to be read inside the data window.
++ * That's why we update it in that case as well.
++ *
++ * However, we specifically avoid updating it for the default page,
++ * when it's overlapped with the real data window, to prevent from
++ * infinite looping.
++ */
+ if (val_num > 1 ||
++ (page_chg && selector_reg != range->selector_reg) ||
+ range->window_start + win_offset != range->selector_reg) {
+ /* Use separate work_buf during page switching */
+ orig_work_buf = map->work_buf;
+@@ -1617,7 +1639,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ ret = _regmap_update_bits(map, range->selector_reg,
+ range->selector_mask,
+ win_page << range->selector_shift,
+- &page_chg, false);
++ NULL, false);
+
+ map->work_buf = orig_work_buf;
+
+--
+2.53.0
+
--- /dev/null
+From 54d07630f11aa9f92913e1582bf2a3910895447a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 14:31:47 +0800
+Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue
+
+From: Yihang Li <liyihang9@huawei.com>
+
+[ Upstream commit d71afa9deb4d413232ba16d693f7d43b321931b4 ]
+
+After commit 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard
+and multi-channel scans"), if the device supports multiple channels (0 to
+shost->max_channel), user_scan() invokes updated sas_user_scan() to perform
+the scan behavior for a specific transfer. However, when the user
+specifies shost->max_channel, it will return -EINVAL, which is not
+expected.
+
+Fix and support specifying the scan shost->max_channel for scanning.
+
+Fixes: 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans")
+Signed-off-by: Yihang Li <liyihang9@huawei.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_sas.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index 1eb58f8765e22..8766ec93652ca 100644
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -1703,7 +1703,7 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ break;
+
+ default:
+- if (channel < shost->max_channel) {
++ if (channel <= shost->max_channel) {
+ res = scsi_scan_host_selected(shost, channel, id, lun,
+ SCSI_SCAN_MANUAL);
+ } else {
+--
+2.53.0
+
netlink-allow-be16-and-be32-types-in-all-uint-policy.patch
netfilter-ctnetlink-use-netlink-policy-range-checks.patch
net-macb-use-the-current-queue-number-for-stats.patch
+regmap-synchronize-cache-for-the-page-selector.patch
+rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch
+scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch
+x86-fault-fold-mm_fault_error-into-do_user_addr_faul.patch
+x86-fault-improve-kernel-executing-user-memory-handl.patch
+x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch
+drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch
+asoc-intel-catpt-fix-the-device-initialization.patch
+acpica-include-acpi-acpixf.h-fix-indentation.patch
+acpica-allow-address_space_handler-install-and-_reg-.patch
+acpi-ec-fix-ec-address-space-handler-unregistration.patch
+acpi-ec-fix-ecdt-probe-ordering-issues.patch
+acpi-ec-install-address-space-handler-at-the-namespa.patch
+acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch
+hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch
+sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch
+spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch
--- /dev/null
+From 01279e4ff57e85e52d339fabc017b437b82cc29f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 19:38:12 +0100
+Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF)
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b341c1176f2e001b3adf0b47154fc31589f7410e ]
+
+There is a teardown order issue in the driver. The SPI controller is
+registered using devm_spi_register_controller(), which delays
+unregistration of the SPI controller until after the fsl_lpspi_remove()
+function returns.
+
+As the fsl_lpspi_remove() function synchronously tears down the DMA
+channels, a running SPI transfer triggers the following NULL pointer
+dereference due to use after free:
+
+| fsl_lpspi 42550000.spi: I/O Error in DMA RX
+| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
+[...]
+| Call trace:
+| fsl_lpspi_dma_transfer+0x260/0x340 [spi_fsl_lpspi]
+| fsl_lpspi_transfer_one+0x198/0x448 [spi_fsl_lpspi]
+| spi_transfer_one_message+0x49c/0x7c8
+| __spi_pump_transfer_message+0x120/0x420
+| __spi_sync+0x2c4/0x520
+| spi_sync+0x34/0x60
+| spidev_message+0x20c/0x378 [spidev]
+| spidev_ioctl+0x398/0x750 [spidev]
+[...]
+
+Switch from devm_spi_register_controller() to spi_register_controller() in
+fsl_lpspi_probe() and add the corresponding spi_unregister_controller() in
+fsl_lpspi_remove().
+
+Fixes: 5314987de5e5 ("spi: imx: add lpspi bus driver")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-fsl-lpspi.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
+index 319cd96bd201b..540815ae49e78 100644
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -914,7 +914,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+ enable_irq(irq);
+ }
+
+- ret = devm_spi_register_controller(&pdev->dev, controller);
++ ret = spi_register_controller(controller);
+ if (ret < 0) {
+ dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
+ goto free_dma;
+@@ -943,6 +943,7 @@ static int fsl_lpspi_remove(struct platform_device *pdev)
+ struct fsl_lpspi_data *fsl_lpspi =
+ spi_controller_get_devdata(controller);
+
++ spi_unregister_controller(controller);
+ fsl_lpspi_dma_exit(controller);
+
+ pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
+--
+2.53.0
+
--- /dev/null
+From 18dc92903f7332335280cfd29af42f4f20641804 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 23:29:50 +0100
+Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap
+
+From: Marc Buerg <buermarc@googlemail.com>
+
+[ Upstream commit f63a9df7e3f9f842945d292a19d9938924f066f9 ]
+
+proc_do_large_bitmap() does not initialize variable c, which is expected
+to be set to a trailing character by proc_get_long().
+
+However, proc_get_long() only sets c when the input buffer contains a
+trailing character after the parsed value.
+
+If c is not initialized it may happen to contain a '-'. If this is the
+case proc_do_large_bitmap() expects to be able to parse a second part of
+the input buffer. If there is no second part an unjustified -EINVAL will
+be returned.
+
+Initialize c to 0 to prevent returning -EINVAL on valid input.
+
+Fixes: 9f977fb7ae9d ("sysctl: add proc_do_large_bitmap")
+Signed-off-by: Marc Buerg <buermarc@googlemail.com>
+Reviewed-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sysctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index abe0f16d53641..c2870c9cae14a 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1549,7 +1549,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
+ unsigned long bitmap_len = table->maxlen;
+ unsigned long *bitmap = *(unsigned long **) table->data;
+ unsigned long *tmp_bitmap = NULL;
+- char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
++ char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c = 0;
+
+ if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
+ *lenp = 0;
+--
+2.53.0
+
--- /dev/null
+From da08823759800b90213f8eac02e48c74193e9877 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 15:59:48 +0200
+Subject: x86/efi: efi_unmap_boot_services: fix calculation of ranges_to_free
+ size
+
+From: Mike Rapoport (Microsoft) <rppt@kernel.org>
+
+[ Upstream commit 217c0a5c177a3d4f7c8497950cbf5c36756e8bbb ]
+
+ranges_to_free array should have enough room to store the entire EFI
+memmap plus an extra element for NULL entry.
+The calculation of this array size wrongly adds 1 to the overall size
+instead of adding 1 to the number of elements.
+
+Add parentheses to properly size the array.
+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory")
+Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/platform/efi/quirks.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
+index a152d57624004..99b282d6c1302 100644
+--- a/arch/x86/platform/efi/quirks.c
++++ b/arch/x86/platform/efi/quirks.c
+@@ -416,7 +416,7 @@ void __init efi_unmap_boot_services(void)
+ if (efi_enabled(EFI_DBG))
+ return;
+
+- sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;
++ sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1);
+ ranges_to_free = kzalloc(sz, GFP_KERNEL);
+ if (!ranges_to_free) {
+ pr_err("Failed to allocate storage for freeable EFI regions\n");
+--
+2.53.0
+
--- /dev/null
+From 0a9ba85121b34742a0391d446ea993f8b476c1b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Feb 2021 18:33:35 -0800
+Subject: x86/fault: Fold mm_fault_error() into do_user_addr_fault()
+
+From: Andy Lutomirski <luto@kernel.org>
+
+[ Upstream commit ec352711ceba890ea3a0c182c2d49c86c1a5e30e ]
+
+mm_fault_error() is logically just the end of do_user_addr_fault().
+Combine the functions. This makes the code easier to read.
+
+Most of the churn here is from renaming hw_error_code to error_code in
+do_user_addr_fault().
+
+This makes no difference at all to the generated code (objdump -dr) as
+compared to changing noinline to __always_inline in the definition of
+mm_fault_error().
+
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lkml.kernel.org/r/dedc4d9c9b047e51ce38b991bd23971a28af4e7b.1612924255.git.luto@kernel.org
+Stable-dep-of: 217c0a5c177a ("x86/efi: efi_unmap_boot_services: fix calculation of ranges_to_free size")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/fault.c | 97 +++++++++++++++++++++------------------------
+ 1 file changed, 45 insertions(+), 52 deletions(-)
+
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index 98a5924d98b72..07983b6208f52 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -925,40 +925,6 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
+ force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address);
+ }
+
+-static noinline void
+-mm_fault_error(struct pt_regs *regs, unsigned long error_code,
+- unsigned long address, vm_fault_t fault)
+-{
+- if (fatal_signal_pending(current) && !(error_code & X86_PF_USER)) {
+- no_context(regs, error_code, address, 0, 0);
+- return;
+- }
+-
+- if (fault & VM_FAULT_OOM) {
+- /* Kernel mode? Handle exceptions or die: */
+- if (!(error_code & X86_PF_USER)) {
+- no_context(regs, error_code, address,
+- SIGSEGV, SEGV_MAPERR);
+- return;
+- }
+-
+- /*
+- * We ran out of memory, call the OOM killer, and return the
+- * userspace (which will retry the fault, or kill us if we got
+- * oom-killed):
+- */
+- pagefault_out_of_memory();
+- } else {
+- if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
+- VM_FAULT_HWPOISON_LARGE))
+- do_sigbus(regs, error_code, address, fault);
+- else if (fault & VM_FAULT_SIGSEGV)
+- bad_area_nosemaphore(regs, error_code, address);
+- else
+- BUG();
+- }
+-}
+-
+ static int spurious_kernel_fault_check(unsigned long error_code, pte_t *pte)
+ {
+ if ((error_code & X86_PF_WRITE) && !pte_write(*pte))
+@@ -1184,7 +1150,7 @@ NOKPROBE_SYMBOL(do_kern_addr_fault);
+ /* Handle faults in the user portion of the address space */
+ static inline
+ void do_user_addr_fault(struct pt_regs *regs,
+- unsigned long hw_error_code,
++ unsigned long error_code,
+ unsigned long address)
+ {
+ struct vm_area_struct *vma;
+@@ -1204,8 +1170,8 @@ void do_user_addr_fault(struct pt_regs *regs,
+ * Reserved bits are never expected to be set on
+ * entries in the user portion of the page tables.
+ */
+- if (unlikely(hw_error_code & X86_PF_RSVD))
+- pgtable_bad(regs, hw_error_code, address);
++ if (unlikely(error_code & X86_PF_RSVD))
++ pgtable_bad(regs, error_code, address);
+
+ /*
+ * If SMAP is on, check for invalid kernel (supervisor) access to user
+@@ -1215,10 +1181,10 @@ void do_user_addr_fault(struct pt_regs *regs,
+ * enforcement appears to be consistent with the USER bit.
+ */
+ if (unlikely(cpu_feature_enabled(X86_FEATURE_SMAP) &&
+- !(hw_error_code & X86_PF_USER) &&
++ !(error_code & X86_PF_USER) &&
+ !(regs->flags & X86_EFLAGS_AC)))
+ {
+- bad_area_nosemaphore(regs, hw_error_code, address);
++ bad_area_nosemaphore(regs, error_code, address);
+ return;
+ }
+
+@@ -1227,7 +1193,7 @@ void do_user_addr_fault(struct pt_regs *regs,
+ * in a region with pagefaults disabled then we must not take the fault
+ */
+ if (unlikely(faulthandler_disabled() || !mm)) {
+- bad_area_nosemaphore(regs, hw_error_code, address);
++ bad_area_nosemaphore(regs, error_code, address);
+ return;
+ }
+
+@@ -1248,9 +1214,9 @@ void do_user_addr_fault(struct pt_regs *regs,
+
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
+
+- if (hw_error_code & X86_PF_WRITE)
++ if (error_code & X86_PF_WRITE)
+ flags |= FAULT_FLAG_WRITE;
+- if (hw_error_code & X86_PF_INSTR)
++ if (error_code & X86_PF_INSTR)
+ flags |= FAULT_FLAG_INSTRUCTION;
+
+ #ifdef CONFIG_X86_64
+@@ -1266,7 +1232,7 @@ void do_user_addr_fault(struct pt_regs *regs,
+ * to consider the PF_PK bit.
+ */
+ if (is_vsyscall_vaddr(address)) {
+- if (emulate_vsyscall(hw_error_code, regs, address))
++ if (emulate_vsyscall(error_code, regs, address))
+ return;
+ }
+ #endif
+@@ -1289,7 +1255,7 @@ void do_user_addr_fault(struct pt_regs *regs,
+ * Fault from code in kernel from
+ * which we do not expect faults.
+ */
+- bad_area_nosemaphore(regs, hw_error_code, address);
++ bad_area_nosemaphore(regs, error_code, address);
+ return;
+ }
+ retry:
+@@ -1305,17 +1271,17 @@ void do_user_addr_fault(struct pt_regs *regs,
+
+ vma = find_vma(mm, address);
+ if (unlikely(!vma)) {
+- bad_area(regs, hw_error_code, address);
++ bad_area(regs, error_code, address);
+ return;
+ }
+ if (likely(vma->vm_start <= address))
+ goto good_area;
+ if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) {
+- bad_area(regs, hw_error_code, address);
++ bad_area(regs, error_code, address);
+ return;
+ }
+ if (unlikely(expand_stack(vma, address))) {
+- bad_area(regs, hw_error_code, address);
++ bad_area(regs, error_code, address);
+ return;
+ }
+
+@@ -1324,8 +1290,8 @@ void do_user_addr_fault(struct pt_regs *regs,
+ * we can handle it..
+ */
+ good_area:
+- if (unlikely(access_error(hw_error_code, vma))) {
+- bad_area_access_error(regs, hw_error_code, address, vma);
++ if (unlikely(access_error(error_code, vma))) {
++ bad_area_access_error(regs, error_code, address, vma);
+ return;
+ }
+
+@@ -1347,7 +1313,7 @@ void do_user_addr_fault(struct pt_regs *regs,
+ /* Quick path to respond to signals */
+ if (fault_signal_pending(fault, regs)) {
+ if (!user_mode(regs))
+- no_context(regs, hw_error_code, address, SIGBUS,
++ no_context(regs, error_code, address, SIGBUS,
+ BUS_ADRERR);
+ return;
+ }
+@@ -1364,11 +1330,38 @@ void do_user_addr_fault(struct pt_regs *regs,
+ }
+
+ mmap_read_unlock(mm);
+- if (unlikely(fault & VM_FAULT_ERROR)) {
+- mm_fault_error(regs, hw_error_code, address, fault);
++ if (likely(!(fault & VM_FAULT_ERROR)))
++ return;
++
++ if (fatal_signal_pending(current) && !(error_code & X86_PF_USER)) {
++ no_context(regs, error_code, address, 0, 0);
+ return;
+ }
+
++ if (fault & VM_FAULT_OOM) {
++ /* Kernel mode? Handle exceptions or die: */
++ if (!(error_code & X86_PF_USER)) {
++ no_context(regs, error_code, address,
++ SIGSEGV, SEGV_MAPERR);
++ return;
++ }
++
++ /*
++ * We ran out of memory, call the OOM killer, and return the
++ * userspace (which will retry the fault, or kill us if we got
++ * oom-killed):
++ */
++ pagefault_out_of_memory();
++ } else {
++ if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
++ VM_FAULT_HWPOISON_LARGE))
++ do_sigbus(regs, error_code, address, fault);
++ else if (fault & VM_FAULT_SIGSEGV)
++ bad_area_nosemaphore(regs, error_code, address);
++ else
++ BUG();
++ }
++
+ check_v8086_mode(regs, address, tsk);
+ }
+ NOKPROBE_SYMBOL(do_user_addr_fault);
+--
+2.53.0
+
--- /dev/null
+From e07087dc03b5f0b000aa858aebc21cb370f60c03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Feb 2021 18:33:39 -0800
+Subject: x86/fault: Improve kernel-executing-user-memory handling
+
+From: Andy Lutomirski <luto@kernel.org>
+
+[ Upstream commit 03c81ea3331658f613bb2913d33764a4e0410cbd ]
+
+Right now, the case of the kernel trying to execute from user memory
+is treated more or less just like the kernel getting a page fault on a
+user access. In the failure path, it checks for erratum #93, tries to
+otherwise fix up the error, and then oopses.
+
+If it manages to jump to the user address space, with or without SMEP,
+it should not try to resolve the page fault. This is an error, pure and
+simple. Rearrange the code so that this case is caught early, check for
+erratum #93, and bail out.
+
+ [ bp: Massage commit message. ]
+
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lkml.kernel.org/r/ab8719c7afb8bd501c4eee0e36493150fbbe5f6a.1612924255.git.luto@kernel.org
+Stable-dep-of: 217c0a5c177a ("x86/efi: efi_unmap_boot_services: fix calculation of ranges_to_free size")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/fault.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index 07983b6208f52..e06182127e1c8 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -433,6 +433,9 @@ static int is_errata93(struct pt_regs *regs, unsigned long address)
+ || boot_cpu_data.x86 != 0xf)
+ return 0;
+
++ if (user_mode(regs))
++ return 0;
++
+ if (address != regs->ip)
+ return 0;
+
+@@ -697,9 +700,6 @@ no_context(struct pt_regs *regs, unsigned long error_code,
+ if (is_prefetch(regs, error_code, address))
+ return;
+
+- if (is_errata93(regs, address))
+- return;
+-
+ /*
+ * Buggy firmware could access regions which might page fault, try to
+ * recover from such faults.
+@@ -1162,6 +1162,21 @@ void do_user_addr_fault(struct pt_regs *regs,
+ tsk = current;
+ mm = tsk->mm;
+
++ if (unlikely((error_code & (X86_PF_USER | X86_PF_INSTR)) == X86_PF_INSTR)) {
++ /*
++ * Whoops, this is kernel mode code trying to execute from
++ * user memory. Unless this is AMD erratum #93, which
++ * corrupts RIP such that it looks like a user address,
++ * this is unrecoverable. Don't even try to look up the
++ * VMA.
++ */
++ if (is_errata93(regs, address))
++ return;
++
++ bad_area_nosemaphore(regs, error_code, address);
++ return;
++ }
++
+ /* kprobes don't want to hook the spurious faults: */
+ if (unlikely(kprobe_page_fault(regs, X86_TRAP_PF)))
+ return;
+--
+2.53.0
+
--- /dev/null
+From 5df19c7f7af6a069de3b21efa641659f5ef42837 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 00:54:59 +0800
+Subject: ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f6484cadbcaf26b5844b51bd7307a663dda48ef6 ]
+
+When ec_install_handlers() returns -EPROBE_DEFER on reduced-hardware
+platforms, it has already started the EC and installed the address
+space handler with the struct acpi_ec pointer as handler context.
+However, acpi_ec_setup() propagates the error without any cleanup.
+
+The caller acpi_ec_add() then frees the struct acpi_ec for non-boot
+instances, leaving a dangling handler context in ACPICA.
+
+Any subsequent AML evaluation that accesses an EC OpRegion field
+dispatches into acpi_ec_space_handler() with the freed pointer,
+causing a use-after-free:
+
+ BUG: KASAN: slab-use-after-free in mutex_lock (kernel/locking/mutex.c:289)
+ Write of size 8 at addr ffff88800721de38 by task init/1
+ Call Trace:
+ <TASK>
+ mutex_lock (kernel/locking/mutex.c:289)
+ acpi_ec_space_handler (drivers/acpi/ec.c:1362)
+ acpi_ev_address_space_dispatch (drivers/acpi/acpica/evregion.c:293)
+ acpi_ex_access_region (drivers/acpi/acpica/exfldio.c:246)
+ acpi_ex_field_datum_io (drivers/acpi/acpica/exfldio.c:509)
+ acpi_ex_extract_from_field (drivers/acpi/acpica/exfldio.c:700)
+ acpi_ex_read_data_from_field (drivers/acpi/acpica/exfield.c:327)
+ acpi_ex_resolve_node_to_value (drivers/acpi/acpica/exresolv.c:392)
+ </TASK>
+
+ Allocated by task 1:
+ acpi_ec_alloc (drivers/acpi/ec.c:1424)
+ acpi_ec_add (drivers/acpi/ec.c:1692)
+
+ Freed by task 1:
+ kfree (mm/slub.c:6876)
+ acpi_ec_add (drivers/acpi/ec.c:1751)
+
+The bug triggers on reduced-hardware EC platforms (ec->gpe < 0)
+when the GPIO IRQ provider defers probing. Once the stale handler
+exists, any unprivileged sysfs read that causes AML to touch an
+EC OpRegion (battery, thermal, backlight) exercises the dangling
+pointer.
+
+Fix this by calling ec_remove_handlers() in the error path of
+acpi_ec_setup() before clearing first_ec. ec_remove_handlers()
+checks each EC_FLAGS_* bit before acting, so it is safe to call
+regardless of how far ec_install_handlers() progressed:
+
+ -ENODEV (handler not installed): only calls acpi_ec_stop()
+ -EPROBE_DEFER (handler installed): removes handler, stops EC
+
+Fixes: 03e9a0e05739 ("ACPI: EC: Consolidate event handler installation code")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 8b54e8fe4a808..25de4e6b4c2ed 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1623,6 +1623,8 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+
+ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret) {
++ ec_remove_handlers(ec);
++
+ if (ec == first_ec)
+ first_ec = NULL;
+
+--
+2.53.0
+
--- /dev/null
+From 2acbeae2f50fec974ff68aa318c97df22503686d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:34 +0100
+Subject: ACPI: EC: Fix EC address space handler unregistration
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit a5072078dbfaa9d70130805766dfa34bbb7bf2a7 ]
+
+When an ECDT table is present the EC address space handler gets registered
+on the root node. So to unregister it properly the unregister call also
+must be done on the root node.
+
+Store the ACPI handle used for the acpi_install_address_space_handler()
+call and use te same handle for the acpi_remove_address_space_handler()
+call.
+
+Reported-by: Rafael J. Wysocki <rafael@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 4 +++-
+ drivers/acpi/internal.h | 1 +
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index ddc5b3a3d9b38..4d38a00dbf50a 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1513,6 +1513,7 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+ return -ENODEV;
+ }
+ set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
++ ec->address_space_handler_holder = ec->handle;
+ }
+
+ if (!device)
+@@ -1564,7 +1565,8 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+ static void ec_remove_handlers(struct acpi_ec *ec)
+ {
+ if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+- if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
++ if (ACPI_FAILURE(acpi_remove_address_space_handler(
++ ec->address_space_handler_holder,
+ ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
+ pr_err("failed to remove space handler\n");
+ clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
+index 54b2be94d23dc..33cf3f38f8530 100644
+--- a/drivers/acpi/internal.h
++++ b/drivers/acpi/internal.h
+@@ -168,6 +168,7 @@ static inline void acpi_early_processor_osc(void) {}
+ -------------------------------------------------------------------------- */
+ struct acpi_ec {
+ acpi_handle handle;
++ acpi_handle address_space_handler_holder;
+ int gpe;
+ int irq;
+ unsigned long command_addr;
+--
+2.53.0
+
--- /dev/null
+From 04c4bd15565b6d4714dcd19f69323a883043f00c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:35 +0100
+Subject: ACPI: EC: Fix ECDT probe ordering issues
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit ab4620f58d38206687b9f99d9d2cc1d5a2640985 ]
+
+ACPI-2.0 says that the EC OpRegion handler must be available immediately
+(like the standard default OpRegion handlers):
+
+Quoting from the ACPI spec version 6.3: "6.5.4 _REG (Region) ...
+2. OSPM must make Embedded Controller operation regions, accessed via
+the Embedded Controllers described in ECDT, available before executing
+any control method. These operation regions may become inaccessible
+after OSPM runs _REG(EmbeddedControl, 0)."
+
+So acpi_bus_init() calls acpi_ec_ecdt_probe(), which calls
+acpi_install_address_space_handler() to install the EC's OpRegion
+handler, early on.
+
+This not only installs the OpRegion handler, but also calls the EC's
+_REG method. The _REG method call is a problem because it may rely on
+initialization done by the _INI methods of one of the PCI / _SB root devs,
+see for example: https://bugzilla.kernel.org/show_bug.cgi?id=214899 .
+
+Generally speaking _REG methods are executed when the ACPI-device they
+are part of has a driver bound to it. Where as _INI methods must be
+executed at table load time (according to the spec). The problem here
+is that the early acpi_install_address_space_handler() call causes
+the _REG handler to run too early.
+
+To allow fixing this the ACPICA code now allows to split the OpRegion
+handler installation and the executing of _REG into 2 separate steps.
+
+This commit uses this ACPICA functionality to fix the EC probe ordering
+by delaying the executing of _REG for ECDT described ECs till the matching
+EC device in the DSDT gets parsed and acpi_ec_add() for it gets called.
+This moves the calling of _REG for the EC on devices with an ECDT to
+the same point in time where it is called on devices without an ECDT table.
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214899
+Reported-and-tested-by: Johannes Penßel <johannespenssel@posteo.net>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 28 ++++++++++++++++++----------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 4d38a00dbf50a..bbc0cfb8fc81b 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -96,6 +96,7 @@ enum {
+ EC_FLAGS_QUERY_GUARDING, /* Guard for SCI_EVT check */
+ EC_FLAGS_EVENT_HANDLER_INSTALLED, /* Event handler installed */
+ EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */
++ EC_FLAGS_EC_REG_CALLED, /* OpReg ACPI _REG method called */
+ EC_FLAGS_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */
+ EC_FLAGS_STARTED, /* Driver is started */
+ EC_FLAGS_STOPPED, /* Driver is stopped */
+@@ -1484,6 +1485,7 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+ * ec_install_handlers - Install service callbacks and register query methods.
+ * @ec: Target EC.
+ * @device: ACPI device object corresponding to @ec.
++ * @call_reg: If _REG should be called to notify OpRegion availability
+ *
+ * Install a handler for the EC address space type unless it has been installed
+ * already. If @device is not NULL, also look for EC query methods in the
+@@ -1496,7 +1498,8 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+ * -EPROBE_DEFER if GPIO IRQ acquisition needs to be deferred,
+ * or 0 (success) otherwise.
+ */
+-static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
++static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
++ bool call_reg)
+ {
+ acpi_status status;
+
+@@ -1504,10 +1507,10 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+
+ if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ acpi_ec_enter_noirq(ec);
+- status = acpi_install_address_space_handler(ec->handle,
+- ACPI_ADR_SPACE_EC,
+- &acpi_ec_space_handler,
+- NULL, ec);
++ status = acpi_install_address_space_handler_no_reg(ec->handle,
++ ACPI_ADR_SPACE_EC,
++ &acpi_ec_space_handler,
++ NULL, ec);
+ if (ACPI_FAILURE(status)) {
+ acpi_ec_stop(ec, false);
+ return -ENODEV;
+@@ -1516,6 +1519,11 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+ ec->address_space_handler_holder = ec->handle;
+ }
+
++ if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) {
++ acpi_execute_reg_methods(ec->handle, ACPI_ADR_SPACE_EC);
++ set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
++ }
++
+ if (!device)
+ return 0;
+
+@@ -1602,11 +1610,11 @@ static void ec_remove_handlers(struct acpi_ec *ec)
+ }
+ }
+
+-static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device)
++static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool call_reg)
+ {
+ int ret;
+
+- ret = ec_install_handlers(ec, device);
++ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret)
+ return ret;
+
+@@ -1668,7 +1676,7 @@ static int acpi_ec_add(struct acpi_device *device)
+ }
+ }
+
+- ret = acpi_ec_setup(ec, device);
++ ret = acpi_ec_setup(ec, device, true);
+ if (ret)
+ goto err;
+
+@@ -1788,7 +1796,7 @@ void __init acpi_ec_dsdt_probe(void)
+ * At this point, the GPE is not fully initialized, so do not to
+ * handle the events.
+ */
+- ret = acpi_ec_setup(ec, NULL);
++ ret = acpi_ec_setup(ec, NULL, true);
+ if (ret) {
+ acpi_ec_free(ec);
+ return;
+@@ -1952,7 +1960,7 @@ void __init acpi_ec_ecdt_probe(void)
+ * At this point, the namespace is not initialized, so do not find
+ * the namespace objects, or handle the events.
+ */
+- ret = acpi_ec_setup(ec, NULL);
++ ret = acpi_ec_setup(ec, NULL, false);
+ if (ret) {
+ acpi_ec_free(ec);
+ goto out;
+--
+2.53.0
+
--- /dev/null
+From 207a8573d60a18fde9dae1f9e5a21bf4a74d2012 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 May 2024 21:40:54 +0200
+Subject: ACPI: EC: Install address space handler at the namespace root
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 60fa6ae6e6d09e377fce6f8d9b6f6a4d88769f63 ]
+
+It is reported that _DSM evaluation fails in ucsi_acpi_dsm() on Lenovo
+IdeaPad Pro 5 due to a missing address space handler for the EC address
+space:
+
+ ACPI Error: No handler for Region [ECSI] (000000007b8176ee) [EmbeddedControl] (20230628/evregion-130)
+
+This happens because if there is no ECDT, the EC driver only registers
+the EC address space handler for operation regions defined in the EC
+device scope of the ACPI namespace while the operation region being
+accessed by the _DSM in question is located beyond that scope.
+
+To address this, modify the ACPI EC driver to install the EC address
+space handler at the root of the ACPI namespace for the first EC that
+can be found regardless of whether or not an ECDT is present.
+
+Note that this change is consistent with some examples in the ACPI
+specification in which EC operation regions located outside the EC
+device scope are used (for example, see Section 9.17.15 in ACPI 6.5),
+so the current behavior of the EC driver is arguably questionable.
+
+Reported-by: webcaptcha <webcapcha@gmail.com>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=218789
+Link: https://uefi.org/specs/ACPI/6.5/09_ACPI_Defined_Devices_and_Device_Specific_Objects.html#example-asl-code
+Link: https://lore.kernel.org/linux-acpi/Zi+0whTvDbAdveHq@kuha.fi.intel.com
+Suggested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 25 ++++++++++++++++---------
+ drivers/acpi/internal.h | 1 -
+ 2 files changed, 16 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index bbc0cfb8fc81b..8b54e8fe4a808 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1501,13 +1501,14 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
+ bool call_reg)
+ {
++ acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle;
+ acpi_status status;
+
+ acpi_ec_start(ec, false);
+
+ if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ acpi_ec_enter_noirq(ec);
+- status = acpi_install_address_space_handler_no_reg(ec->handle,
++ status = acpi_install_address_space_handler_no_reg(scope_handle,
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler,
+ NULL, ec);
+@@ -1516,11 +1517,10 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
+ return -ENODEV;
+ }
+ set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+- ec->address_space_handler_holder = ec->handle;
+ }
+
+ if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) {
+- acpi_execute_reg_methods(ec->handle, ACPI_ADR_SPACE_EC);
++ acpi_execute_reg_methods(scope_handle, ACPI_ADR_SPACE_EC);
+ set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
+ }
+
+@@ -1572,10 +1572,13 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
+
+ static void ec_remove_handlers(struct acpi_ec *ec)
+ {
++ acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle;
++
+ if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ if (ACPI_FAILURE(acpi_remove_address_space_handler(
+- ec->address_space_handler_holder,
+- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
++ scope_handle,
++ ACPI_ADR_SPACE_EC,
++ &acpi_ec_space_handler)))
+ pr_err("failed to remove space handler\n");
+ clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+ }
+@@ -1614,14 +1617,18 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+ {
+ int ret;
+
+- ret = ec_install_handlers(ec, device, call_reg);
+- if (ret)
+- return ret;
+-
+ /* First EC capable of handling transactions */
+ if (!first_ec)
+ first_ec = ec;
+
++ ret = ec_install_handlers(ec, device, call_reg);
++ if (ret) {
++ if (ec == first_ec)
++ first_ec = NULL;
++
++ return ret;
++ }
++
+ pr_info("EC_CMD/EC_SC=0x%lx, EC_DATA=0x%lx\n", ec->command_addr,
+ ec->data_addr);
+
+diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
+index 33cf3f38f8530..54b2be94d23dc 100644
+--- a/drivers/acpi/internal.h
++++ b/drivers/acpi/internal.h
+@@ -168,7 +168,6 @@ static inline void acpi_early_processor_osc(void) {}
+ -------------------------------------------------------------------------- */
+ struct acpi_ec {
+ acpi_handle handle;
+- acpi_handle address_space_handler_holder;
+ int gpe;
+ int irq;
+ unsigned long command_addr;
+--
+2.53.0
+
--- /dev/null
+From 6a4fdf8cc605ba316426f6e9bdc9b74412b00962 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:33 +0100
+Subject: ACPICA: Allow address_space_handler Install and _REG execution as 2
+ separate steps
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 54c516aeb8b39eeae6450b7d8076d381568dca46 ]
+
+ACPI-2.0 says that the EC op_region handler must be available immediately
+(like the standard default op_region handlers):
+
+Quoting from the ACPI spec version 6.3: "6.5.4 _REG (Region) ...
+2. OSPM must make Embedded Controller operation regions, accessed via
+the Embedded Controllers described in ECDT, available before executing
+any control method. These operation regions may become inaccessible
+after OSPM runs _REG(EmbeddedControl, 0)."
+
+So the OS must probe the ECDT described EC and install the OpRegion handler
+before calling acpi_enable_subsystem() and acpi_initialize_objects().
+
+This is a problem because calling acpi_install_address_space_handler()
+does not just install the op_region handler, it also runs the EC's _REG
+method. This _REG method may rely on initialization done by the _INI
+methods of one of the PCI / _SB root devices.
+
+For the other early/default op_region handlers the op_region handler
+install and the _REG execution is split into 2 separate steps:
+1. acpi_ev_install_region_handlers(), called early from acpi_load_tables()
+2. acpi_ev_initialize_op_regions(), called from acpi_initialize_objects()
+
+To fix the EC op_region issue, add 2 bew functions:
+1. acpi_install_address_space_handler_no_reg()
+2. acpi_execute_reg_methods()
+to allow doing things in 2 steps for other op_region handlers,
+like the EC handler, too.
+
+Note that the comment describing acpi_ev_install_region_handlers() even has
+an alinea describing this problem. Using the new methods allows users
+to avoid this problem.
+
+Link: https://github.com/acpica/acpica/pull/786
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=214899
+Reported-and-tested-by: Johannes Penßel <johannespenssel@posteo.net>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/evxfregn.c | 92 +++++++++++++++++++++++++++++++---
+ include/acpi/acpixf.h | 10 ++++
+ 2 files changed, 95 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
+index 7672d70da850d..282cd4e96e122 100644
+--- a/drivers/acpi/acpica/evxfregn.c
++++ b/drivers/acpi/acpica/evxfregn.c
+@@ -20,13 +20,14 @@ ACPI_MODULE_NAME("evxfregn")
+
+ /*******************************************************************************
+ *
+- * FUNCTION: acpi_install_address_space_handler
++ * FUNCTION: acpi_install_address_space_handler_internal
+ *
+ * PARAMETERS: device - Handle for the device
+ * space_id - The address space ID
+ * handler - Address of the handler
+ * setup - Address of the setup function
+ * context - Value passed to the handler on each access
++ * Run_reg - Run _REG methods for this address space?
+ *
+ * RETURN: Status
+ *
+@@ -37,13 +38,16 @@ ACPI_MODULE_NAME("evxfregn")
+ * are executed here, and these methods can only be safely executed after
+ * the default handlers have been installed and the hardware has been
+ * initialized (via acpi_enable_subsystem.)
++ * To avoid this problem pass FALSE for Run_Reg and later on call
++ * acpi_execute_reg_methods() to execute _REG.
+ *
+ ******************************************************************************/
+-acpi_status
+-acpi_install_address_space_handler(acpi_handle device,
+- acpi_adr_space_type space_id,
+- acpi_adr_space_handler handler,
+- acpi_adr_space_setup setup, void *context)
++static acpi_status
++acpi_install_address_space_handler_internal(acpi_handle device,
++ acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup,
++ void *context, u8 run_reg)
+ {
+ struct acpi_namespace_node *node;
+ acpi_status status;
+@@ -80,14 +84,40 @@ acpi_install_address_space_handler(acpi_handle device,
+
+ /* Run all _REG methods for this address space */
+
+- acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
++ if (run_reg) {
++ acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
++ }
+
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
+ }
+
++acpi_status
++acpi_install_address_space_handler(acpi_handle device,
++ acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup, void *context)
++{
++ return acpi_install_address_space_handler_internal(device, space_id,
++ handler, setup,
++ context, TRUE);
++}
++
+ ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
++acpi_status
++acpi_install_address_space_handler_no_reg(acpi_handle device,
++ acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup,
++ void *context)
++{
++ return acpi_install_address_space_handler_internal(device, space_id,
++ handler, setup,
++ context, FALSE);
++}
++
++ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler_no_reg)
+
+ /*******************************************************************************
+ *
+@@ -226,3 +256,51 @@ acpi_remove_address_space_handler(acpi_handle device,
+ }
+
+ ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_execute_reg_methods
++ *
++ * PARAMETERS: device - Handle for the device
++ * space_id - The address space ID
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Execute _REG for all op_regions of a given space_id.
++ *
++ ******************************************************************************/
++acpi_status
++acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id)
++{
++ struct acpi_namespace_node *node;
++ acpi_status status;
++
++ ACPI_FUNCTION_TRACE(acpi_execute_reg_methods);
++
++ /* Parameter validation */
++
++ if (!device) {
++ return_ACPI_STATUS(AE_BAD_PARAMETER);
++ }
++
++ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ /* Convert and validate the device handle */
++
++ node = acpi_ns_validate_handle(device);
++ if (node) {
++
++ /* Run all _REG methods for this address space */
++
++ acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
++ } else {
++ status = AE_BAD_PARAMETER;
++ }
++
++ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
++ return_ACPI_STATUS(status);
++}
++
++ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods)
+diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
+index 2cf4c90730d6b..27ff6bf066ef4 100644
+--- a/include/acpi/acpixf.h
++++ b/include/acpi/acpixf.h
+@@ -650,6 +650,16 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+ acpi_adr_space_setup
+ setup,
+ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_address_space_handler_no_reg
++ (acpi_handle device, acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup,
++ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_execute_reg_methods(acpi_handle device,
++ acpi_adr_space_type
++ space_id))
+ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+ acpi_remove_address_space_handler(acpi_handle
+ device,
+--
+2.53.0
+
--- /dev/null
+From c380b9b3aa0a98bc3da0289c6c0caf1a770fd732 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:32 +0100
+Subject: ACPICA: include/acpi/acpixf.h: Fix indentation
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 7a9d74e7e403cb2e60d4d00c05f2f3ab2a33d0c3 ]
+
+A bunch of the functions declared in include/acpi/acpixf.h have their
+name aligned a space after the '(' of e.g. the
+`ACPI_EXTERNAL_RETURN_STATUS(acpi_status` line above rather then being
+directly aligned after the '('.
+
+This breaks applying patches generated from the ACPICA upstream git,
+remove the extra space before the function-names and all the arguments
+to fix this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/acpi/acpixf.h | 120 +++++++++++++++++++++---------------------
+ 1 file changed, 60 insertions(+), 60 deletions(-)
+
+diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
+index 9d45a6001bc00..2cf4c90730d6b 100644
+--- a/include/acpi/acpixf.h
++++ b/include/acpi/acpixf.h
+@@ -587,82 +587,82 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+ acpi_install_initialization_handler
+ (acpi_init_handler handler, u32 function))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_sci_handler(acpi_sci_handler
+- address,
+- void *context))
+-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_remove_sci_handler(acpi_sci_handler
+- address))
++ acpi_install_sci_handler(acpi_sci_handler
++ address,
++ void *context))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_global_event_handler
+- (acpi_gbl_event_handler handler,
+- void *context))
++ acpi_remove_sci_handler(acpi_sci_handler
++ address))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_fixed_event_handler(u32
+- acpi_event,
+- acpi_event_handler
+- handler,
+- void
+- *context))
++ acpi_install_global_event_handler
++ (acpi_gbl_event_handler handler,
++ void *context))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_remove_fixed_event_handler(u32 acpi_event,
++ acpi_install_fixed_event_handler(u32
++ acpi_event,
+ acpi_event_handler
+- handler))
+-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_gpe_handler(acpi_handle
+- gpe_device,
+- u32 gpe_number,
+- u32 type,
+- acpi_gpe_handler
+- address,
+- void *context))
++ handler,
++ void
++ *context))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_gpe_raw_handler(acpi_handle
+- gpe_device,
+- u32 gpe_number,
+- u32 type,
+- acpi_gpe_handler
+- address,
+- void *context))
++ acpi_remove_fixed_event_handler(u32 acpi_event,
++ acpi_event_handler
++ handler))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_remove_gpe_handler(acpi_handle gpe_device,
++ acpi_install_gpe_handler(acpi_handle
++ gpe_device,
+ u32 gpe_number,
++ u32 type,
+ acpi_gpe_handler
+- address))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_notify_handler(acpi_handle device,
+- u32 handler_type,
+- acpi_notify_handler
+- handler,
++ address,
+ void *context))
++ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
++ acpi_install_gpe_raw_handler(acpi_handle
++ gpe_device,
++ u32 gpe_number,
++ u32 type,
++ acpi_gpe_handler
++ address,
++ void *context))
++ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
++ acpi_remove_gpe_handler(acpi_handle gpe_device,
++ u32 gpe_number,
++ acpi_gpe_handler
++ address))
+ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_remove_notify_handler(acpi_handle device,
++ acpi_install_notify_handler(acpi_handle device,
+ u32 handler_type,
+ acpi_notify_handler
+- handler))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_address_space_handler(acpi_handle
+- device,
+- acpi_adr_space_type
+- space_id,
+- acpi_adr_space_handler
+- handler,
+- acpi_adr_space_setup
+- setup,
+- void *context))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_remove_address_space_handler(acpi_handle
++ handler,
++ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_remove_notify_handler(acpi_handle device,
++ u32 handler_type,
++ acpi_notify_handler
++ handler))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_address_space_handler(acpi_handle
+ device,
+ acpi_adr_space_type
+ space_id,
+ acpi_adr_space_handler
+- handler))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_exception_handler
+- (acpi_exception_handler handler))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_interface_handler
+- (acpi_interface_handler handler))
++ handler,
++ acpi_adr_space_setup
++ setup,
++ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_remove_address_space_handler(acpi_handle
++ device,
++ acpi_adr_space_type
++ space_id,
++ acpi_adr_space_handler
++ handler))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_exception_handler
++ (acpi_exception_handler handler))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_interface_handler
++ (acpi_interface_handler handler))
+
+ /*
+ * Global Lock interfaces
+--
+2.53.0
+
--- /dev/null
+From aa16ee1d20448e04d071fabf702b5bf9e761ae1b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:04 +0100
+Subject: ASoC: adau1372: Fix clock leak on PLL lock failure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit bfe6a264effcb6fe99ad7ceaf9e8c7439fc9555b ]
+
+adau1372_enable_pll() was a void function that logged a dev_err() on
+PLL lock timeout but did not propagate the error. As a result,
+adau1372_set_power() would continue with adau1372->enabled set to true
+despite the PLL being unlocked, and the mclk left enabled with no
+corresponding disable on the error path.
+
+Convert adau1372_enable_pll() to return int, using -ETIMEDOUT on lock
+timeout and propagating regmap errors directly. In adau1372_set_power(),
+check the return value and unwind in reverse order: restore regcache to
+cache-only mode, reassert GPIO power-down, and disable the clock before
+returning the error.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index 0997d5f3e4039..e20145812f12b 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -761,7 +761,7 @@ static int adau1372_startup(struct snd_pcm_substream *substream, struct snd_soc_
+ return 0;
+ }
+
+-static void adau1372_enable_pll(struct adau1372 *adau1372)
++static int adau1372_enable_pll(struct adau1372 *adau1372)
+ {
+ unsigned int val, timeout = 0;
+ int ret;
+@@ -777,8 +777,12 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ timeout++;
+ } while (!(val & 1) && timeout < 3);
+
+- if (ret < 0 || !(val & 1))
++ if (ret < 0 || !(val & 1)) {
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
++ return ret < 0 ? ret : -ETIMEDOUT;
++ }
++
++ return 0;
+ }
+
+ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+@@ -806,7 +810,14 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ * accessed.
+ */
+ if (adau1372->use_pll) {
+- adau1372_enable_pll(adau1372);
++ ret = adau1372_enable_pll(adau1372);
++ if (ret) {
++ regcache_cache_only(adau1372->regmap, true);
++ if (adau1372->pd_gpio)
++ gpiod_set_value(adau1372->pd_gpio, 1);
++ clk_disable_unprepare(adau1372->mclk);
++ return ret;
++ }
+ clk_ctrl |= ADAU1372_CLK_CTRL_CLKSRC;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 7663f4f52c85d6992c16ea076c6f4ea1253537e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:03 +0100
+Subject: ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit 326fe8104a4020d30080d37ac8b6b43893cdebca ]
+
+adau1372_set_power() calls clk_prepare_enable() but discards the return
+value. If the clock enable fails, the driver proceeds to access registers
+on unpowered hardware, potentially causing silent corruption.
+
+Make adau1372_set_power() return int and propagate the error from
+clk_prepare_enable(). Update adau1372_set_bias_level() to return the
+error directly for the STANDBY and OFF cases.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index 6811a8b3866dd..0997d5f3e4039 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -781,15 +781,18 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
+ }
+
+-static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
++static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ {
+ if (adau1372->enabled == enable)
+- return;
++ return 0;
+
+ if (enable) {
+ unsigned int clk_ctrl = ADAU1372_CLK_CTRL_MCLK_EN;
++ int ret;
+
+- clk_prepare_enable(adau1372->mclk);
++ ret = clk_prepare_enable(adau1372->mclk);
++ if (ret)
++ return ret;
+ if (adau1372->pd_gpio)
+ gpiod_set_value(adau1372->pd_gpio, 0);
+
+@@ -828,6 +831,8 @@ static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ }
+
+ adau1372->enabled = enable;
++
++ return 0;
+ }
+
+ static int adau1372_set_bias_level(struct snd_soc_component *component,
+@@ -841,11 +846,9 @@ static int adau1372_set_bias_level(struct snd_soc_component *component,
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+- adau1372_set_power(adau1372, true);
+- break;
++ return adau1372_set_power(adau1372, true);
+ case SND_SOC_BIAS_OFF:
+- adau1372_set_power(adau1372, false);
+- break;
++ return adau1372_set_power(adau1372, false);
+ }
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 61272ad177a86639c88ccaa92b3c30610018a6fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 11:12:17 +0100
+Subject: ASoC: Intel: catpt: Fix the device initialization
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 5a184f1cb43a8e035251c635f5c47da5dc3e3049 ]
+
+The DMA mask shall be coerced before any buffer allocations for the
+device are done. At the same time explain why DMA mask of 31 bits is
+used in the first place.
+
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle")
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/catpt/device.c | 10 +++++++++-
+ sound/soc/intel/catpt/dsp.c | 3 ---
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c
+index 85a34e37316d0..68b01bdef2bfe 100644
+--- a/sound/soc/intel/catpt/device.c
++++ b/sound/soc/intel/catpt/device.c
+@@ -275,7 +275,15 @@ static int catpt_acpi_probe(struct platform_device *pdev)
+ if (IS_ERR(cdev->pci_ba))
+ return PTR_ERR(cdev->pci_ba);
+
+- /* alloc buffer for storing DRAM context during dx transitions */
++ /*
++ * As per design HOST is responsible for preserving firmware's runtime
++ * context during D0 -> D3 -> D0 transitions. Addresses used for DMA
++ * to/from HOST memory shall be outside the reserved range of 0xFFFxxxxx.
++ */
++ ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
++ if (ret)
++ return ret;
++
+ cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev),
+ &cdev->dxbuf_paddr, GFP_KERNEL);
+ if (!cdev->dxbuf_vaddr)
+diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
+index 346bec0003066..3cde6b7ae9237 100644
+--- a/sound/soc/intel/catpt/dsp.c
++++ b/sound/soc/intel/catpt/dsp.c
+@@ -125,9 +125,6 @@ int catpt_dmac_probe(struct catpt_dev *cdev)
+ dmac->dev = cdev->dev;
+ dmac->irq = cdev->irq;
+
+- ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
+- if (ret)
+- return ret;
+ /*
+ * Caller is responsible for putting device in D0 to allow
+ * for I/O and memory access before probing DW.
+--
+2.53.0
+
--- /dev/null
+From 7f822245c4b1fcdbb65ba50bbcebc85484ccb097 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 16:19:19 -0700
+Subject: drm/i915/gmbus: fix spurious timeout on 512-byte burst reads
+
+From: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+
+[ Upstream commit 08441f10f4dc09fdeb64529953ac308abc79dd38 ]
+
+When reading exactly 512 bytes with burst read enabled, the
+extra_byte_added path breaks out of the inner do-while without
+decrementing len. The outer while(len) then re-enters and gmbus_wait()
+times out since all data has been delivered. Decrement len before the
+break so the outer loop terminates correctly.
+
+Fixes: d5dc0f43f268 ("drm/i915/gmbus: Enable burst read")
+Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_gmbus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
+index ceb1bf8a8c3c2..01b046578cd15 100644
+--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
++++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
+@@ -432,8 +432,10 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
+
+ val = intel_de_read_fw(dev_priv, GMBUS3);
+ do {
+- if (extra_byte_added && len == 1)
++ if (extra_byte_added && len == 1) {
++ len--;
+ break;
++ }
+
+ *buf++ = val & 0xff;
+ val >>= 8;
+--
+2.53.0
+
--- /dev/null
+From f3ef964869a437d0514a53df407557c63a6fd168 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 05:13:06 +0000
+Subject: hwmon: (adm1177) fix sysfs ABI violation and current unit conversion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sanman Pradhan <psanman@juniper.net>
+
+[ Upstream commit bf08749a6abb6d1959bfdc0edc32c640df407558 ]
+
+The adm1177 driver exposes the current alert threshold through
+hwmon_curr_max_alarm. This violates the hwmon sysfs ABI, where
+*_alarm attributes are read-only status flags and writable thresholds
+must use currN_max.
+
+The driver also stores the threshold internally in microamps, while
+currN_max is defined in milliamps. Convert the threshold accordingly
+on both the read and write paths.
+
+Widen the cached threshold and related calculations to 64 bits so
+that small shunt resistor values do not cause truncation or overflow.
+Also use 64-bit arithmetic for the mA/uA conversions, clamp writes
+to the range the hardware can represent, and propagate failures from
+adm1177_write_alert_thr() instead of silently ignoring them.
+
+Update the hwmon documentation to reflect the attribute rename and
+the correct units returned by the driver.
+
+Fixes: 09b08ac9e8d5 ("hwmon: (adm1177) Add ADM1177 Hot Swap Controller and Digital Power Monitor driver")
+Signed-off-by: Sanman Pradhan <psanman@juniper.net>
+Acked-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/adm1177.rst | 8 ++---
+ drivers/hwmon/adm1177.c | 54 +++++++++++++++++++--------------
+ 2 files changed, 35 insertions(+), 27 deletions(-)
+
+diff --git a/Documentation/hwmon/adm1177.rst b/Documentation/hwmon/adm1177.rst
+index 1c85a2af92bf7..375f6d6e03a7d 100644
+--- a/Documentation/hwmon/adm1177.rst
++++ b/Documentation/hwmon/adm1177.rst
+@@ -27,10 +27,10 @@ for details.
+ Sysfs entries
+ -------------
+
+-The following attributes are supported. Current maxim attribute
++The following attributes are supported. Current maximum attribute
+ is read-write, all other attributes are read-only.
+
+-in0_input Measured voltage in microvolts.
++in0_input Measured voltage in millivolts.
+
+-curr1_input Measured current in microamperes.
+-curr1_max_alarm Overcurrent alarm in microamperes.
++curr1_input Measured current in milliamperes.
++curr1_max Overcurrent shutdown threshold in milliamperes.
+diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c
+index 0c5dbc5e33b46..d2ccb133b2927 100644
+--- a/drivers/hwmon/adm1177.c
++++ b/drivers/hwmon/adm1177.c
+@@ -10,6 +10,8 @@
+ #include <linux/hwmon.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
++#include <linux/math64.h>
++#include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/regulator/consumer.h>
+
+@@ -35,7 +37,7 @@ struct adm1177_state {
+ struct i2c_client *client;
+ struct regulator *reg;
+ u32 r_sense_uohm;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
+ bool vrange_high;
+ };
+
+@@ -50,7 +52,7 @@ static int adm1177_write_cmd(struct adm1177_state *st, u8 cmd)
+ }
+
+ static int adm1177_write_alert_thr(struct adm1177_state *st,
+- u32 alert_threshold_ua)
++ u64 alert_threshold_ua)
+ {
+ u64 val;
+ int ret;
+@@ -93,8 +95,8 @@ static int adm1177_read(struct device *dev, enum hwmon_sensor_types type,
+ *val = div_u64((105840000ull * dummy),
+ 4096 * st->r_sense_uohm);
+ return 0;
+- case hwmon_curr_max_alarm:
+- *val = st->alert_threshold_ua;
++ case hwmon_curr_max:
++ *val = div_u64(st->alert_threshold_ua, 1000);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+@@ -128,9 +130,10 @@ static int adm1177_write(struct device *dev, enum hwmon_sensor_types type,
+ switch (type) {
+ case hwmon_curr:
+ switch (attr) {
+- case hwmon_curr_max_alarm:
+- adm1177_write_alert_thr(st, val);
+- return 0;
++ case hwmon_curr_max:
++ val = clamp_val(val, 0,
++ div_u64(105840000ULL, st->r_sense_uohm));
++ return adm1177_write_alert_thr(st, (u64)val * 1000);
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -158,7 +161,7 @@ static umode_t adm1177_is_visible(const void *data,
+ if (st->r_sense_uohm)
+ return 0444;
+ return 0;
+- case hwmon_curr_max_alarm:
++ case hwmon_curr_max:
+ if (st->r_sense_uohm)
+ return 0644;
+ return 0;
+@@ -172,7 +175,7 @@ static umode_t adm1177_is_visible(const void *data,
+
+ static const struct hwmon_channel_info *adm1177_info[] = {
+ HWMON_CHANNEL_INFO(curr,
+- HWMON_C_INPUT | HWMON_C_MAX_ALARM),
++ HWMON_C_INPUT | HWMON_C_MAX),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT),
+ NULL
+@@ -201,7 +204,8 @@ static int adm1177_probe(struct i2c_client *client)
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct adm1177_state *st;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
++ u32 prop;
+ int ret;
+
+ st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+@@ -229,22 +233,26 @@ static int adm1177_probe(struct i2c_client *client)
+ if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
+ &st->r_sense_uohm))
+ st->r_sense_uohm = 0;
+- if (device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
+- &alert_threshold_ua)) {
+- if (st->r_sense_uohm)
+- /*
+- * set maximum default value from datasheet based on
+- * shunt-resistor
+- */
+- alert_threshold_ua = div_u64(105840000000,
+- st->r_sense_uohm);
+- else
+- alert_threshold_ua = 0;
++ if (!device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
++ &prop)) {
++ alert_threshold_ua = prop;
++ } else if (st->r_sense_uohm) {
++ /*
++ * set maximum default value from datasheet based on
++ * shunt-resistor
++ */
++ alert_threshold_ua = div_u64(105840000000ULL,
++ st->r_sense_uohm);
++ } else {
++ alert_threshold_ua = 0;
+ }
+ st->vrange_high = device_property_read_bool(dev,
+ "adi,vrange-high-enable");
+- if (alert_threshold_ua && st->r_sense_uohm)
+- adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (alert_threshold_ua && st->r_sense_uohm) {
++ ret = adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (ret)
++ return ret;
++ }
+
+ ret = adm1177_write_cmd(st, ADM1177_CMD_V_CONT |
+ ADM1177_CMD_I_CONT |
+--
+2.53.0
+
--- /dev/null
+From bc70842b0741b7262ce02b609b7402f5f7b8c61c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:43 -0500
+Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node
+
+From: Ivan Barrera <ivan.d.barrera@intel.com>
+
+[ Upstream commit b415399c9a024d574b65479636f0d4eb625b9abd ]
+
+The cm_node is available and the usage of cm_node and event->cm_node
+seems arbitrary. Clean up unnecessary dereference of event->cm_node.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Ivan Barrera <ivan.d.barrera@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index d2c6a1bcf1de9..8a99a040917f7 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -4171,21 +4171,21 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ irdma_cm_event_reset(event);
+ break;
+ case IRDMA_CM_EVENT_CONNECTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state != IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state != IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_cm_event_connected(event);
+ break;
+ case IRDMA_CM_EVENT_MPA_REJECT:
+- if (!event->cm_node->cm_id ||
++ if (!cm_node->cm_id ||
+ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_send_cm_event(cm_node, cm_node->cm_id,
+ IW_CM_EVENT_CONNECT_REPLY, -ECONNREFUSED);
+ break;
+ case IRDMA_CM_EVENT_ABORTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state == IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_event_connect_error(event);
+ break;
+@@ -4195,7 +4195,7 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ break;
+ }
+
+- irdma_rem_ref_cm_node(event->cm_node);
++ irdma_rem_ref_cm_node(cm_node);
+ kfree(event);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 8f84cd089f30733c8ef3c71e6bc9d6bd6286e10f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:45 -0500
+Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections
+
+From: Anil Samal <anil.samal@intel.com>
+
+[ Upstream commit 6f52370970ac07d352a7af4089e55e0e6425f827 ]
+
+Resolve deadlock that occurs when user executes netdev reset while RDMA
+applications (e.g., rping) are active. The netdev reset causes ice
+driver to remove irdma auxiliary driver, triggering device_delete and
+subsequent client removal. During client removal, uverbs_client waits
+for QP reference count to reach zero while cma_client holds the final
+reference, creating circular dependency and indefinite wait in iWARP
+mode. Skip QP reference count wait during device reset to prevent
+deadlock.
+
+Fixes: c8f304d75f6c ("RDMA/irdma: Prevent QP use after free")
+Signed-off-by: Anil Samal <anil.samal@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index b7186bb6a7bbc..986acd446c651 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -518,7 +518,8 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+ }
+
+ irdma_qp_rem_ref(&iwqp->ibqp);
+- wait_for_completion(&iwqp->free_qp);
++ if (!iwdev->rf->reset)
++ wait_for_completion(&iwqp->free_qp);
+ irdma_free_lsmm_rsrc(iwqp);
+ irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
+
+--
+2.53.0
+
--- /dev/null
+From 5f2016b5c37d6ba89e2a6b3758813e416b990162 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:42 -0500
+Subject: RDMA/irdma: Remove a NOP wait_event() in irdma_modify_qp_roce()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 5e8f0239731a83753473b7aa91bda67bbdff5053 ]
+
+Remove a NOP wait_event() in irdma_modify_qp_roce() which is relevant
+for iWARP and likely a copy and paste artifact for RoCEv2. The wait event
+is for sending a reset on a TCP connection, after the reset has been
+requested in irdma_modify_qp(), which occurs only in iWarp mode.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index f1924e84d2568..b7186bb6a7bbc 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1275,8 +1275,6 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ roce_info->rd_en = true;
+ }
+
+- wait_event(iwqp->mod_qp_waitq, !atomic_read(&iwqp->hw_mod_qp_pend));
+-
+ ibdev_dbg(&iwdev->ibdev,
+ "VERBS: caller: %pS qp_id=%d to_ibqpstate=%d ibqpstate=%d irdma_qpstate=%d attr_mask=0x%x\n",
+ __builtin_return_address(0), ibqp->qp_num, attr->qp_state,
+--
+2.53.0
+
--- /dev/null
+From 8a93c5b63e34b85e402b1e204d8691d2f89e14d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:44 -0500
+Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit c45c6ebd693b944f1ffe429fdfb6cc1674c237be ]
+
+During reset, irdma_modify_qp() to error should be called to disconnect
+the QP. Without this fix, if not preceded by irdma_modify_qp() to error, the
+API call irdma_destroy_qp() gets stuck waiting for the QP refcount to go
+to zero, because the cm_node associated with this QP isn't disconnected.
+
+Fixes: 915cc7ac0f8e ("RDMA/irdma: Add miscellaneous utility definitions")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/utils.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
+index 235515e8bf9b7..5a0672345cab1 100644
+--- a/drivers/infiniband/hw/irdma/utils.c
++++ b/drivers/infiniband/hw/irdma/utils.c
+@@ -2512,8 +2512,6 @@ void irdma_modify_qp_to_err(struct irdma_sc_qp *sc_qp)
+ struct irdma_qp *qp = sc_qp->qp_uk.back_qp;
+ struct ib_qp_attr attr;
+
+- if (qp->iwdev->rf->reset)
+- return;
+ attr.qp_state = IB_QPS_ERR;
+
+ if (rdma_protocol_roce(qp->ibqp.device, 1))
+--
+2.53.0
+
--- /dev/null
+From f629de500dc7130045e877bfd7b81e08fbc918e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:46 -0500
+Subject: RDMA/irdma: Return EINVAL for invalid arp index error
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 7221f581eefa79ead06e171044f393fb7ee22f87 ]
+
+When rdma_connect() fails due to an invalid arp index, user space rdma core
+reports ENOMEM which is confusing. Modify irdma_make_cm_node() to return the
+correct error code.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index 8a99a040917f7..8d671bd64f37a 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -2197,11 +2197,12 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ int oldarpindex;
+ int arpindex;
+ struct net_device *netdev = iwdev->netdev;
++ int ret;
+
+ /* create an hte and cm_node for this instance */
+ cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
+ if (!cm_node)
+- return NULL;
++ return ERR_PTR(-ENOMEM);
+
+ /* set our node specific transport info */
+ cm_node->ipv4 = cm_info->ipv4;
+@@ -2296,8 +2297,10 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ arpindex = -EINVAL;
+ }
+
+- if (arpindex < 0)
++ if (arpindex < 0) {
++ ret = -EINVAL;
+ goto err;
++ }
+
+ ether_addr_copy(cm_node->rem_mac,
+ iwdev->rf->arp_table[arpindex].mac_addr);
+@@ -2308,7 +2311,7 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ err:
+ kfree(cm_node);
+
+- return NULL;
++ return ERR_PTR(ret);
+ }
+
+ static void irdma_destroy_connection(struct irdma_cm_node *cm_node)
+@@ -2969,8 +2972,8 @@ static int irdma_create_cm_node(struct irdma_cm_core *cm_core,
+
+ /* create a CM connection node */
+ cm_node = irdma_make_cm_node(cm_core, iwdev, cm_info, NULL);
+- if (!cm_node)
+- return -ENOMEM;
++ if (IS_ERR(cm_node))
++ return PTR_ERR(cm_node);
+
+ /* set our node side to client (active) side */
+ cm_node->tcp_cntxt.client = 1;
+@@ -3167,9 +3170,9 @@ void irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf)
+ cm_info.cm_id = listener->cm_id;
+ cm_node = irdma_make_cm_node(cm_core, iwdev, &cm_info,
+ listener);
+- if (!cm_node) {
++ if (IS_ERR(cm_node)) {
+ ibdev_dbg(&cm_core->iwdev->ibdev,
+- "CM: allocate node failed\n");
++ "CM: allocate node failed ret=%ld\n", PTR_ERR(cm_node));
+ refcount_dec(&listener->refcnt);
+ return;
+ }
+--
+2.53.0
+
--- /dev/null
+From 10212fe4d8d19b1cea935f766ce3571cbf0ab4ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:41 -0500
+Subject: RDMA/irdma: Update ibqp state to error if QP is already in error
+ state
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 8c1f19a2225cf37b3f8ab0b5a8a5322291cda620 ]
+
+In irdma_modify_qp() update ibqp state to error if the irdma QP is already
+in error state, otherwise the ibqp state which is visible to the consumer
+app remains stale.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 40960f0803fbc..f1924e84d2568 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1353,6 +1353,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata) {
+ if (ib_copy_from_udata(&ureq, udata,
+@@ -1549,6 +1550,7 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata) {
+ if (ib_copy_from_udata(&ureq, udata,
+--
+2.53.0
+
--- /dev/null
+From 55a125727411c08c31885b014c6460c56650c551 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Mar 2026 15:41:58 -0400
+Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 00da250c21b074ea9494c375d0117b69e5b1d0a4 ]
+
+When IOMMU passthrough mode is active, ib_dma_map_sgtable_attrs()
+produces no coalescing: each scatterlist page maps 1:1 to a DMA
+entry, so sgt.nents equals the raw page count. A 1 MB transfer
+yields 256 DMA entries. If that count exceeds the device's
+max_sgl_rd threshold (an optimization hint from mlx5 firmware),
+rdma_rw_io_needs_mr() steers the operation into the MR
+registration path. Each such operation consumes one or more MRs
+from a pool sized at max_rdma_ctxs -- roughly one MR per
+concurrent context. Under write-intensive workloads that issue
+many concurrent RDMA READs, the pool is rapidly exhausted,
+ib_mr_pool_get() returns NULL, and rdma_rw_init_one_mr() returns
+-EAGAIN. Upper layer protocols treat this as a fatal DMA mapping
+failure and tear down the connection.
+
+The max_sgl_rd check is a performance optimization, not a
+correctness requirement: the device can handle large SGE counts
+via direct posting, just less efficiently than with MR
+registration. When the MR pool cannot satisfy a request, falling
+back to the direct SGE (map_wrs) path avoids the connection
+reset while preserving the MR optimization for the common case
+where pool resources are available.
+
+Add a fallback in rdma_rw_ctx_init() so that -EAGAIN from
+rdma_rw_init_mr_wrs() triggers direct SGE posting instead of
+propagating the error. iWARP devices, which mandate MR
+registration for RDMA READs, and force_mr debug mode continue
+to treat -EAGAIN as terminal.
+
+Fixes: 00bd1439f464 ("RDMA/rw: Support threshold for registration vs scattering to local pages")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/rw.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
+index 3b6cfa6362e04..bfa91d2ff956c 100644
+--- a/drivers/infiniband/core/rw.c
++++ b/drivers/infiniband/core/rw.c
+@@ -341,14 +341,29 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u32 port_num,
+ if (rdma_rw_io_needs_mr(qp->device, port_num, dir, sg_cnt)) {
+ ret = rdma_rw_init_mr_wrs(ctx, qp, port_num, sg, sg_cnt,
+ sg_offset, remote_addr, rkey, dir);
+- } else if (sg_cnt > 1) {
++ /*
++ * If MR init succeeded or failed for a reason other
++ * than pool exhaustion, that result is final.
++ *
++ * Pool exhaustion (-EAGAIN) from the max_sgl_rd
++ * optimization is recoverable: fall back to
++ * direct SGE posting. iWARP and force_mr require
++ * MRs unconditionally, so -EAGAIN is terminal.
++ */
++ if (ret != -EAGAIN ||
++ rdma_protocol_iwarp(qp->device, port_num) ||
++ unlikely(rdma_rw_force_mr))
++ goto out;
++ }
++
++ if (sg_cnt > 1)
+ ret = rdma_rw_init_map_wrs(ctx, qp, sg, sg_cnt, sg_offset,
+ remote_addr, rkey, dir);
+- } else {
++ else
+ ret = rdma_rw_init_single_wr(ctx, qp, sg, sg_offset,
+ remote_addr, rkey, dir);
+- }
+
++out:
+ if (ret < 0)
+ goto out_unmap_sg;
+ return ret;
+--
+2.53.0
+
--- /dev/null
+From c3da62913d21d18c2dffc8ca309b259ae6909df0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Mar 2026 19:43:31 +0100
+Subject: regmap: Synchronize cache for the page selector
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 09e70e4f119ff650d24c96161fd2f62ac7e424b0 ]
+
+If the selector register is represented in each page, its value
+according to the debugfs is stale because it gets synchronized
+only after the real page switch happens. Hence the regmap cache
+initialisation from the HW inherits outdated data in the selector
+register.
+
+Synchronize cache for the page selector just in time.
+
+Before (offset followed by hexdump, the first byte is selector):
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 05 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 01 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 02 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 03 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 04 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+After:
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 01 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 02 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 03 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 04 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+Fixes: 6863ca622759 ("regmap: Add support for register indirect addressing.")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap.c | 30 ++++++++++++++++++++++++++----
+ 1 file changed, 26 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index e1380b08685f4..b1cae7db6318a 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -1629,6 +1629,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ unsigned int val_num)
+ {
+ void *orig_work_buf;
++ unsigned int selector_reg;
+ unsigned int win_offset;
+ unsigned int win_page;
+ bool page_chg;
+@@ -1647,10 +1648,31 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ return -EINVAL;
+ }
+
+- /* It is possible to have selector register inside data window.
+- In that case, selector register is located on every page and
+- it needs no page switching, when accessed alone. */
++ /*
++ * Calculate the address of the selector register in the corresponding
++ * data window if it is located on every page.
++ */
++ page_chg = in_range(range->selector_reg, range->window_start, range->window_len);
++ if (page_chg)
++ selector_reg = range->range_min + win_page * range->window_len +
++ range->selector_reg - range->window_start;
++
++ /*
++ * It is possible to have selector register inside data window.
++ * In that case, selector register is located on every page and it
++ * needs no page switching, when accessed alone.
++ *
++ * Nevertheless we should synchronize the cache values for it.
++ * This can't be properly achieved if the selector register is
++ * the first and the only one to be read inside the data window.
++ * That's why we update it in that case as well.
++ *
++ * However, we specifically avoid updating it for the default page,
++ * when it's overlapped with the real data window, to prevent from
++ * infinite looping.
++ */
+ if (val_num > 1 ||
++ (page_chg && selector_reg != range->selector_reg) ||
+ range->window_start + win_offset != range->selector_reg) {
+ /* Use separate work_buf during page switching */
+ orig_work_buf = map->work_buf;
+@@ -1659,7 +1681,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ ret = _regmap_update_bits(map, range->selector_reg,
+ range->selector_mask,
+ win_page << range->selector_shift,
+- &page_chg, false);
++ NULL, false);
+
+ map->work_buf = orig_work_buf;
+
+--
+2.53.0
+
--- /dev/null
+From b30b2e7ed90f73bebe73ca6593333dd7c8ebeee5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 14:31:47 +0800
+Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue
+
+From: Yihang Li <liyihang9@huawei.com>
+
+[ Upstream commit d71afa9deb4d413232ba16d693f7d43b321931b4 ]
+
+After commit 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard
+and multi-channel scans"), if the device supports multiple channels (0 to
+shost->max_channel), user_scan() invokes updated sas_user_scan() to perform
+the scan behavior for a specific transfer. However, when the user
+specifies shost->max_channel, it will return -EINVAL, which is not
+expected.
+
+Fix and support specifying the scan shost->max_channel for scanning.
+
+Fixes: 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans")
+Signed-off-by: Yihang Li <liyihang9@huawei.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_sas.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index 87c5ed56e47bd..ecb2e8aed93bb 100644
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -1732,7 +1732,7 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ break;
+
+ default:
+- if (channel < shost->max_channel) {
++ if (channel <= shost->max_channel) {
+ res = scsi_scan_host_selected(shost, channel, id, lun,
+ SCSI_SCAN_MANUAL);
+ } else {
+--
+2.53.0
+
netlink-allow-be16-and-be32-types-in-all-uint-policy.patch
netfilter-ctnetlink-use-netlink-policy-range-checks.patch
net-macb-use-the-current-queue-number-for-stats.patch
+regmap-synchronize-cache-for-the-page-selector.patch
+rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch
+rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch
+rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch
+rdma-irdma-clean-up-unnecessary-dereference-of-event.patch
+rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch
+rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch
+rdma-irdma-return-einval-for-invalid-arp-index-error.patch
+scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch
+x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch
+drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch
+asoc-intel-catpt-fix-the-device-initialization.patch
+acpica-include-acpi-acpixf.h-fix-indentation.patch
+acpica-allow-address_space_handler-install-and-_reg-.patch
+acpi-ec-fix-ec-address-space-handler-unregistration.patch
+acpi-ec-fix-ecdt-probe-ordering-issues.patch
+acpi-ec-install-address-space-handler-at-the-namespa.patch
+acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch
+hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch
+sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch
+asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch
+asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch
+spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch
--- /dev/null
+From 62a49609df15f5460a7907b1ed5820740dd1a692 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 19:38:12 +0100
+Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF)
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b341c1176f2e001b3adf0b47154fc31589f7410e ]
+
+There is a teardown order issue in the driver. The SPI controller is
+registered using devm_spi_register_controller(), which delays
+unregistration of the SPI controller until after the fsl_lpspi_remove()
+function returns.
+
+As the fsl_lpspi_remove() function synchronously tears down the DMA
+channels, a running SPI transfer triggers the following NULL pointer
+dereference due to use after free:
+
+| fsl_lpspi 42550000.spi: I/O Error in DMA RX
+| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
+[...]
+| Call trace:
+| fsl_lpspi_dma_transfer+0x260/0x340 [spi_fsl_lpspi]
+| fsl_lpspi_transfer_one+0x198/0x448 [spi_fsl_lpspi]
+| spi_transfer_one_message+0x49c/0x7c8
+| __spi_pump_transfer_message+0x120/0x420
+| __spi_sync+0x2c4/0x520
+| spi_sync+0x34/0x60
+| spidev_message+0x20c/0x378 [spidev]
+| spidev_ioctl+0x398/0x750 [spidev]
+[...]
+
+Switch from devm_spi_register_controller() to spi_register_controller() in
+fsl_lpspi_probe() and add the corresponding spi_unregister_controller() in
+fsl_lpspi_remove().
+
+Fixes: 5314987de5e5 ("spi: imx: add lpspi bus driver")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-fsl-lpspi.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
+index 319cd96bd201b..540815ae49e78 100644
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -914,7 +914,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+ enable_irq(irq);
+ }
+
+- ret = devm_spi_register_controller(&pdev->dev, controller);
++ ret = spi_register_controller(controller);
+ if (ret < 0) {
+ dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
+ goto free_dma;
+@@ -943,6 +943,7 @@ static int fsl_lpspi_remove(struct platform_device *pdev)
+ struct fsl_lpspi_data *fsl_lpspi =
+ spi_controller_get_devdata(controller);
+
++ spi_unregister_controller(controller);
+ fsl_lpspi_dma_exit(controller);
+
+ pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
+--
+2.53.0
+
--- /dev/null
+From b9fe966e91706a0e50368573d912c0505f8e9141 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 23:29:50 +0100
+Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap
+
+From: Marc Buerg <buermarc@googlemail.com>
+
+[ Upstream commit f63a9df7e3f9f842945d292a19d9938924f066f9 ]
+
+proc_do_large_bitmap() does not initialize variable c, which is expected
+to be set to a trailing character by proc_get_long().
+
+However, proc_get_long() only sets c when the input buffer contains a
+trailing character after the parsed value.
+
+If c is not initialized it may happen to contain a '-'. If this is the
+case proc_do_large_bitmap() expects to be able to parse a second part of
+the input buffer. If there is no second part an unjustified -EINVAL will
+be returned.
+
+Initialize c to 0 to prevent returning -EINVAL on valid input.
+
+Fixes: 9f977fb7ae9d ("sysctl: add proc_do_large_bitmap")
+Signed-off-by: Marc Buerg <buermarc@googlemail.com>
+Reviewed-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sysctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index eaf9dd6a2f12f..ac16c3084c96c 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1528,7 +1528,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
+ unsigned long bitmap_len = table->maxlen;
+ unsigned long *bitmap = *(unsigned long **) table->data;
+ unsigned long *tmp_bitmap = NULL;
+- char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
++ char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c = 0;
+
+ if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
+ *lenp = 0;
+--
+2.53.0
+
--- /dev/null
+From b561fd2f20b43cc2e9308b8a8cf3bcf7f057e893 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 15:59:48 +0200
+Subject: x86/efi: efi_unmap_boot_services: fix calculation of ranges_to_free
+ size
+
+From: Mike Rapoport (Microsoft) <rppt@kernel.org>
+
+[ Upstream commit 217c0a5c177a3d4f7c8497950cbf5c36756e8bbb ]
+
+ranges_to_free array should have enough room to store the entire EFI
+memmap plus an extra element for NULL entry.
+The calculation of this array size wrongly adds 1 to the overall size
+instead of adding 1 to the number of elements.
+
+Add parentheses to properly size the array.
+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory")
+Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/platform/efi/quirks.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
+index e3b00f05a2532..b0d0376940ba8 100644
+--- a/arch/x86/platform/efi/quirks.c
++++ b/arch/x86/platform/efi/quirks.c
+@@ -416,7 +416,7 @@ void __init efi_unmap_boot_services(void)
+ if (efi_enabled(EFI_DBG))
+ return;
+
+- sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;
++ sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1);
+ ranges_to_free = kzalloc(sz, GFP_KERNEL);
+ if (!ranges_to_free) {
+ pr_err("Failed to allocate storage for freeable EFI regions\n");
+--
+2.53.0
+
--- /dev/null
+From caa84bd85e638f2df243d31f7c786ae32ad29ad4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 00:54:59 +0800
+Subject: ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f6484cadbcaf26b5844b51bd7307a663dda48ef6 ]
+
+When ec_install_handlers() returns -EPROBE_DEFER on reduced-hardware
+platforms, it has already started the EC and installed the address
+space handler with the struct acpi_ec pointer as handler context.
+However, acpi_ec_setup() propagates the error without any cleanup.
+
+The caller acpi_ec_add() then frees the struct acpi_ec for non-boot
+instances, leaving a dangling handler context in ACPICA.
+
+Any subsequent AML evaluation that accesses an EC OpRegion field
+dispatches into acpi_ec_space_handler() with the freed pointer,
+causing a use-after-free:
+
+ BUG: KASAN: slab-use-after-free in mutex_lock (kernel/locking/mutex.c:289)
+ Write of size 8 at addr ffff88800721de38 by task init/1
+ Call Trace:
+ <TASK>
+ mutex_lock (kernel/locking/mutex.c:289)
+ acpi_ec_space_handler (drivers/acpi/ec.c:1362)
+ acpi_ev_address_space_dispatch (drivers/acpi/acpica/evregion.c:293)
+ acpi_ex_access_region (drivers/acpi/acpica/exfldio.c:246)
+ acpi_ex_field_datum_io (drivers/acpi/acpica/exfldio.c:509)
+ acpi_ex_extract_from_field (drivers/acpi/acpica/exfldio.c:700)
+ acpi_ex_read_data_from_field (drivers/acpi/acpica/exfield.c:327)
+ acpi_ex_resolve_node_to_value (drivers/acpi/acpica/exresolv.c:392)
+ </TASK>
+
+ Allocated by task 1:
+ acpi_ec_alloc (drivers/acpi/ec.c:1424)
+ acpi_ec_add (drivers/acpi/ec.c:1692)
+
+ Freed by task 1:
+ kfree (mm/slub.c:6876)
+ acpi_ec_add (drivers/acpi/ec.c:1751)
+
+The bug triggers on reduced-hardware EC platforms (ec->gpe < 0)
+when the GPIO IRQ provider defers probing. Once the stale handler
+exists, any unprivileged sysfs read that causes AML to touch an
+EC OpRegion (battery, thermal, backlight) exercises the dangling
+pointer.
+
+Fix this by calling ec_remove_handlers() in the error path of
+acpi_ec_setup() before clearing first_ec. ec_remove_handlers()
+checks each EC_FLAGS_* bit before acting, so it is safe to call
+regardless of how far ec_install_handlers() progressed:
+
+ -ENODEV (handler not installed): only calls acpi_ec_stop()
+ -EPROBE_DEFER (handler installed): removes handler, stops EC
+
+Fixes: 03e9a0e05739 ("ACPI: EC: Consolidate event handler installation code")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 3583ce4980c32..230fe6463cc1f 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1634,6 +1634,8 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+
+ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret) {
++ ec_remove_handlers(ec);
++
+ if (ec == first_ec)
+ first_ec = NULL;
+
+--
+2.53.0
+
--- /dev/null
+From 6eb4f63c712dccb027a633d33dc1ac28aa546bbd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:34 +0100
+Subject: ACPI: EC: Fix EC address space handler unregistration
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit a5072078dbfaa9d70130805766dfa34bbb7bf2a7 ]
+
+When an ECDT table is present the EC address space handler gets registered
+on the root node. So to unregister it properly the unregister call also
+must be done on the root node.
+
+Store the ACPI handle used for the acpi_install_address_space_handler()
+call and use te same handle for the acpi_remove_address_space_handler()
+call.
+
+Reported-by: Rafael J. Wysocki <rafael@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 4 +++-
+ drivers/acpi/internal.h | 1 +
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 15148513b050d..cecc521e2d30f 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1524,6 +1524,7 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+ return -ENODEV;
+ }
+ set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
++ ec->address_space_handler_holder = ec->handle;
+ }
+
+ if (!device)
+@@ -1575,7 +1576,8 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+ static void ec_remove_handlers(struct acpi_ec *ec)
+ {
+ if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+- if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
++ if (ACPI_FAILURE(acpi_remove_address_space_handler(
++ ec->address_space_handler_holder,
+ ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
+ pr_err("failed to remove space handler\n");
+ clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
+index 219c02df9a08c..ec584442fb298 100644
+--- a/drivers/acpi/internal.h
++++ b/drivers/acpi/internal.h
+@@ -173,6 +173,7 @@ enum acpi_ec_event_state {
+
+ struct acpi_ec {
+ acpi_handle handle;
++ acpi_handle address_space_handler_holder;
+ int gpe;
+ int irq;
+ unsigned long command_addr;
+--
+2.53.0
+
--- /dev/null
+From 68fb141ac0958b643875bdd57daef3104ba9fc45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:35 +0100
+Subject: ACPI: EC: Fix ECDT probe ordering issues
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit ab4620f58d38206687b9f99d9d2cc1d5a2640985 ]
+
+ACPI-2.0 says that the EC OpRegion handler must be available immediately
+(like the standard default OpRegion handlers):
+
+Quoting from the ACPI spec version 6.3: "6.5.4 _REG (Region) ...
+2. OSPM must make Embedded Controller operation regions, accessed via
+the Embedded Controllers described in ECDT, available before executing
+any control method. These operation regions may become inaccessible
+after OSPM runs _REG(EmbeddedControl, 0)."
+
+So acpi_bus_init() calls acpi_ec_ecdt_probe(), which calls
+acpi_install_address_space_handler() to install the EC's OpRegion
+handler, early on.
+
+This not only installs the OpRegion handler, but also calls the EC's
+_REG method. The _REG method call is a problem because it may rely on
+initialization done by the _INI methods of one of the PCI / _SB root devs,
+see for example: https://bugzilla.kernel.org/show_bug.cgi?id=214899 .
+
+Generally speaking _REG methods are executed when the ACPI-device they
+are part of has a driver bound to it. Where as _INI methods must be
+executed at table load time (according to the spec). The problem here
+is that the early acpi_install_address_space_handler() call causes
+the _REG handler to run too early.
+
+To allow fixing this the ACPICA code now allows to split the OpRegion
+handler installation and the executing of _REG into 2 separate steps.
+
+This commit uses this ACPICA functionality to fix the EC probe ordering
+by delaying the executing of _REG for ECDT described ECs till the matching
+EC device in the DSDT gets parsed and acpi_ec_add() for it gets called.
+This moves the calling of _REG for the EC on devices with an ECDT to
+the same point in time where it is called on devices without an ECDT table.
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214899
+Reported-and-tested-by: Johannes Penßel <johannespenssel@posteo.net>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 28 ++++++++++++++++++----------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index cecc521e2d30f..a20b59a554414 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -94,6 +94,7 @@ enum {
+ EC_FLAGS_QUERY_ENABLED, /* Query is enabled */
+ EC_FLAGS_EVENT_HANDLER_INSTALLED, /* Event handler installed */
+ EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */
++ EC_FLAGS_EC_REG_CALLED, /* OpReg ACPI _REG method called */
+ EC_FLAGS_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */
+ EC_FLAGS_STARTED, /* Driver is started */
+ EC_FLAGS_STOPPED, /* Driver is stopped */
+@@ -1495,6 +1496,7 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+ * ec_install_handlers - Install service callbacks and register query methods.
+ * @ec: Target EC.
+ * @device: ACPI device object corresponding to @ec.
++ * @call_reg: If _REG should be called to notify OpRegion availability
+ *
+ * Install a handler for the EC address space type unless it has been installed
+ * already. If @device is not NULL, also look for EC query methods in the
+@@ -1507,7 +1509,8 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+ * -EPROBE_DEFER if GPIO IRQ acquisition needs to be deferred,
+ * or 0 (success) otherwise.
+ */
+-static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
++static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
++ bool call_reg)
+ {
+ acpi_status status;
+
+@@ -1515,10 +1518,10 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+
+ if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ acpi_ec_enter_noirq(ec);
+- status = acpi_install_address_space_handler(ec->handle,
+- ACPI_ADR_SPACE_EC,
+- &acpi_ec_space_handler,
+- NULL, ec);
++ status = acpi_install_address_space_handler_no_reg(ec->handle,
++ ACPI_ADR_SPACE_EC,
++ &acpi_ec_space_handler,
++ NULL, ec);
+ if (ACPI_FAILURE(status)) {
+ acpi_ec_stop(ec, false);
+ return -ENODEV;
+@@ -1527,6 +1530,11 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
+ ec->address_space_handler_holder = ec->handle;
+ }
+
++ if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) {
++ acpi_execute_reg_methods(ec->handle, ACPI_ADR_SPACE_EC);
++ set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
++ }
++
+ if (!device)
+ return 0;
+
+@@ -1613,11 +1621,11 @@ static void ec_remove_handlers(struct acpi_ec *ec)
+ }
+ }
+
+-static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device)
++static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool call_reg)
+ {
+ int ret;
+
+- ret = ec_install_handlers(ec, device);
++ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret)
+ return ret;
+
+@@ -1682,7 +1690,7 @@ static int acpi_ec_add(struct acpi_device *device)
+ }
+ }
+
+- ret = acpi_ec_setup(ec, device);
++ ret = acpi_ec_setup(ec, device, true);
+ if (ret)
+ goto err;
+
+@@ -1802,7 +1810,7 @@ void __init acpi_ec_dsdt_probe(void)
+ * At this point, the GPE is not fully initialized, so do not to
+ * handle the events.
+ */
+- ret = acpi_ec_setup(ec, NULL);
++ ret = acpi_ec_setup(ec, NULL, true);
+ if (ret) {
+ acpi_ec_free(ec);
+ return;
+@@ -2017,7 +2025,7 @@ void __init acpi_ec_ecdt_probe(void)
+ * At this point, the namespace is not initialized, so do not find
+ * the namespace objects, or handle the events.
+ */
+- ret = acpi_ec_setup(ec, NULL);
++ ret = acpi_ec_setup(ec, NULL, false);
+ if (ret) {
+ acpi_ec_free(ec);
+ goto out;
+--
+2.53.0
+
--- /dev/null
+From 050f7f44e7b92b43854ee228578ec940ae7d99cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 May 2024 21:40:54 +0200
+Subject: ACPI: EC: Install address space handler at the namespace root
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 60fa6ae6e6d09e377fce6f8d9b6f6a4d88769f63 ]
+
+It is reported that _DSM evaluation fails in ucsi_acpi_dsm() on Lenovo
+IdeaPad Pro 5 due to a missing address space handler for the EC address
+space:
+
+ ACPI Error: No handler for Region [ECSI] (000000007b8176ee) [EmbeddedControl] (20230628/evregion-130)
+
+This happens because if there is no ECDT, the EC driver only registers
+the EC address space handler for operation regions defined in the EC
+device scope of the ACPI namespace while the operation region being
+accessed by the _DSM in question is located beyond that scope.
+
+To address this, modify the ACPI EC driver to install the EC address
+space handler at the root of the ACPI namespace for the first EC that
+can be found regardless of whether or not an ECDT is present.
+
+Note that this change is consistent with some examples in the ACPI
+specification in which EC operation regions located outside the EC
+device scope are used (for example, see Section 9.17.15 in ACPI 6.5),
+so the current behavior of the EC driver is arguably questionable.
+
+Reported-by: webcaptcha <webcapcha@gmail.com>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=218789
+Link: https://uefi.org/specs/ACPI/6.5/09_ACPI_Defined_Devices_and_Device_Specific_Objects.html#example-asl-code
+Link: https://lore.kernel.org/linux-acpi/Zi+0whTvDbAdveHq@kuha.fi.intel.com
+Suggested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 25 ++++++++++++++++---------
+ drivers/acpi/internal.h | 1 -
+ 2 files changed, 16 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index a20b59a554414..3583ce4980c32 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1512,13 +1512,14 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
+ bool call_reg)
+ {
++ acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle;
+ acpi_status status;
+
+ acpi_ec_start(ec, false);
+
+ if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ acpi_ec_enter_noirq(ec);
+- status = acpi_install_address_space_handler_no_reg(ec->handle,
++ status = acpi_install_address_space_handler_no_reg(scope_handle,
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler,
+ NULL, ec);
+@@ -1527,11 +1528,10 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
+ return -ENODEV;
+ }
+ set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+- ec->address_space_handler_holder = ec->handle;
+ }
+
+ if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) {
+- acpi_execute_reg_methods(ec->handle, ACPI_ADR_SPACE_EC);
++ acpi_execute_reg_methods(scope_handle, ACPI_ADR_SPACE_EC);
+ set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
+ }
+
+@@ -1583,10 +1583,13 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
+
+ static void ec_remove_handlers(struct acpi_ec *ec)
+ {
++ acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle;
++
+ if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ if (ACPI_FAILURE(acpi_remove_address_space_handler(
+- ec->address_space_handler_holder,
+- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
++ scope_handle,
++ ACPI_ADR_SPACE_EC,
++ &acpi_ec_space_handler)))
+ pr_err("failed to remove space handler\n");
+ clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+ }
+@@ -1625,14 +1628,18 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+ {
+ int ret;
+
+- ret = ec_install_handlers(ec, device, call_reg);
+- if (ret)
+- return ret;
+-
+ /* First EC capable of handling transactions */
+ if (!first_ec)
+ first_ec = ec;
+
++ ret = ec_install_handlers(ec, device, call_reg);
++ if (ret) {
++ if (ec == first_ec)
++ first_ec = NULL;
++
++ return ret;
++ }
++
+ pr_info("EC_CMD/EC_SC=0x%lx, EC_DATA=0x%lx\n", ec->command_addr,
+ ec->data_addr);
+
+diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
+index ec584442fb298..219c02df9a08c 100644
+--- a/drivers/acpi/internal.h
++++ b/drivers/acpi/internal.h
+@@ -173,7 +173,6 @@ enum acpi_ec_event_state {
+
+ struct acpi_ec {
+ acpi_handle handle;
+- acpi_handle address_space_handler_holder;
+ int gpe;
+ int irq;
+ unsigned long command_addr;
+--
+2.53.0
+
--- /dev/null
+From e32848ffc654650a658ad05e8a136b273aa5885d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:33 +0100
+Subject: ACPICA: Allow address_space_handler Install and _REG execution as 2
+ separate steps
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 54c516aeb8b39eeae6450b7d8076d381568dca46 ]
+
+ACPI-2.0 says that the EC op_region handler must be available immediately
+(like the standard default op_region handlers):
+
+Quoting from the ACPI spec version 6.3: "6.5.4 _REG (Region) ...
+2. OSPM must make Embedded Controller operation regions, accessed via
+the Embedded Controllers described in ECDT, available before executing
+any control method. These operation regions may become inaccessible
+after OSPM runs _REG(EmbeddedControl, 0)."
+
+So the OS must probe the ECDT described EC and install the OpRegion handler
+before calling acpi_enable_subsystem() and acpi_initialize_objects().
+
+This is a problem because calling acpi_install_address_space_handler()
+does not just install the op_region handler, it also runs the EC's _REG
+method. This _REG method may rely on initialization done by the _INI
+methods of one of the PCI / _SB root devices.
+
+For the other early/default op_region handlers the op_region handler
+install and the _REG execution is split into 2 separate steps:
+1. acpi_ev_install_region_handlers(), called early from acpi_load_tables()
+2. acpi_ev_initialize_op_regions(), called from acpi_initialize_objects()
+
+To fix the EC op_region issue, add 2 bew functions:
+1. acpi_install_address_space_handler_no_reg()
+2. acpi_execute_reg_methods()
+to allow doing things in 2 steps for other op_region handlers,
+like the EC handler, too.
+
+Note that the comment describing acpi_ev_install_region_handlers() even has
+an alinea describing this problem. Using the new methods allows users
+to avoid this problem.
+
+Link: https://github.com/acpica/acpica/pull/786
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=214899
+Reported-and-tested-by: Johannes Penßel <johannespenssel@posteo.net>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/evxfregn.c | 92 +++++++++++++++++++++++++++++++---
+ include/acpi/acpixf.h | 10 ++++
+ 2 files changed, 95 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
+index 6fa6b485e30d5..e94e6631502c1 100644
+--- a/drivers/acpi/acpica/evxfregn.c
++++ b/drivers/acpi/acpica/evxfregn.c
+@@ -20,13 +20,14 @@ ACPI_MODULE_NAME("evxfregn")
+
+ /*******************************************************************************
+ *
+- * FUNCTION: acpi_install_address_space_handler
++ * FUNCTION: acpi_install_address_space_handler_internal
+ *
+ * PARAMETERS: device - Handle for the device
+ * space_id - The address space ID
+ * handler - Address of the handler
+ * setup - Address of the setup function
+ * context - Value passed to the handler on each access
++ * Run_reg - Run _REG methods for this address space?
+ *
+ * RETURN: Status
+ *
+@@ -37,13 +38,16 @@ ACPI_MODULE_NAME("evxfregn")
+ * are executed here, and these methods can only be safely executed after
+ * the default handlers have been installed and the hardware has been
+ * initialized (via acpi_enable_subsystem.)
++ * To avoid this problem pass FALSE for Run_Reg and later on call
++ * acpi_execute_reg_methods() to execute _REG.
+ *
+ ******************************************************************************/
+-acpi_status
+-acpi_install_address_space_handler(acpi_handle device,
+- acpi_adr_space_type space_id,
+- acpi_adr_space_handler handler,
+- acpi_adr_space_setup setup, void *context)
++static acpi_status
++acpi_install_address_space_handler_internal(acpi_handle device,
++ acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup,
++ void *context, u8 run_reg)
+ {
+ struct acpi_namespace_node *node;
+ acpi_status status;
+@@ -80,14 +84,40 @@ acpi_install_address_space_handler(acpi_handle device,
+
+ /* Run all _REG methods for this address space */
+
+- acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
++ if (run_reg) {
++ acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
++ }
+
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
+ }
+
++acpi_status
++acpi_install_address_space_handler(acpi_handle device,
++ acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup, void *context)
++{
++ return acpi_install_address_space_handler_internal(device, space_id,
++ handler, setup,
++ context, TRUE);
++}
++
+ ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
++acpi_status
++acpi_install_address_space_handler_no_reg(acpi_handle device,
++ acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup,
++ void *context)
++{
++ return acpi_install_address_space_handler_internal(device, space_id,
++ handler, setup,
++ context, FALSE);
++}
++
++ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler_no_reg)
+
+ /*******************************************************************************
+ *
+@@ -226,3 +256,51 @@ acpi_remove_address_space_handler(acpi_handle device,
+ }
+
+ ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
++/*******************************************************************************
++ *
++ * FUNCTION: acpi_execute_reg_methods
++ *
++ * PARAMETERS: device - Handle for the device
++ * space_id - The address space ID
++ *
++ * RETURN: Status
++ *
++ * DESCRIPTION: Execute _REG for all op_regions of a given space_id.
++ *
++ ******************************************************************************/
++acpi_status
++acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id)
++{
++ struct acpi_namespace_node *node;
++ acpi_status status;
++
++ ACPI_FUNCTION_TRACE(acpi_execute_reg_methods);
++
++ /* Parameter validation */
++
++ if (!device) {
++ return_ACPI_STATUS(AE_BAD_PARAMETER);
++ }
++
++ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
++ if (ACPI_FAILURE(status)) {
++ return_ACPI_STATUS(status);
++ }
++
++ /* Convert and validate the device handle */
++
++ node = acpi_ns_validate_handle(device);
++ if (node) {
++
++ /* Run all _REG methods for this address space */
++
++ acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
++ } else {
++ status = AE_BAD_PARAMETER;
++ }
++
++ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
++ return_ACPI_STATUS(status);
++}
++
++ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods)
+diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
+index 9be3151e4db59..754efb4e63307 100644
+--- a/include/acpi/acpixf.h
++++ b/include/acpi/acpixf.h
+@@ -658,6 +658,16 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+ acpi_adr_space_setup
+ setup,
+ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_address_space_handler_no_reg
++ (acpi_handle device, acpi_adr_space_type space_id,
++ acpi_adr_space_handler handler,
++ acpi_adr_space_setup setup,
++ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_execute_reg_methods(acpi_handle device,
++ acpi_adr_space_type
++ space_id))
+ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+ acpi_remove_address_space_handler(acpi_handle
+ device,
+--
+2.53.0
+
--- /dev/null
+From fcd1467987995e8d87e89fb3f1c12f9f79e0d74c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:23:32 +0100
+Subject: ACPICA: include/acpi/acpixf.h: Fix indentation
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 7a9d74e7e403cb2e60d4d00c05f2f3ab2a33d0c3 ]
+
+A bunch of the functions declared in include/acpi/acpixf.h have their
+name aligned a space after the '(' of e.g. the
+`ACPI_EXTERNAL_RETURN_STATUS(acpi_status` line above rather then being
+directly aligned after the '('.
+
+This breaks applying patches generated from the ACPICA upstream git,
+remove the extra space before the function-names and all the arguments
+to fix this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/acpi/acpixf.h | 120 +++++++++++++++++++++---------------------
+ 1 file changed, 60 insertions(+), 60 deletions(-)
+
+diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
+index 413153f3aa4fc..9be3151e4db59 100644
+--- a/include/acpi/acpixf.h
++++ b/include/acpi/acpixf.h
+@@ -595,82 +595,82 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+ acpi_install_initialization_handler
+ (acpi_init_handler handler, u32 function))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_sci_handler(acpi_sci_handler
+- address,
+- void *context))
+-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_remove_sci_handler(acpi_sci_handler
+- address))
++ acpi_install_sci_handler(acpi_sci_handler
++ address,
++ void *context))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_global_event_handler
+- (acpi_gbl_event_handler handler,
+- void *context))
++ acpi_remove_sci_handler(acpi_sci_handler
++ address))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_fixed_event_handler(u32
+- acpi_event,
+- acpi_event_handler
+- handler,
+- void
+- *context))
++ acpi_install_global_event_handler
++ (acpi_gbl_event_handler handler,
++ void *context))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_remove_fixed_event_handler(u32 acpi_event,
++ acpi_install_fixed_event_handler(u32
++ acpi_event,
+ acpi_event_handler
+- handler))
+-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_gpe_handler(acpi_handle
+- gpe_device,
+- u32 gpe_number,
+- u32 type,
+- acpi_gpe_handler
+- address,
+- void *context))
++ handler,
++ void
++ *context))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_install_gpe_raw_handler(acpi_handle
+- gpe_device,
+- u32 gpe_number,
+- u32 type,
+- acpi_gpe_handler
+- address,
+- void *context))
++ acpi_remove_fixed_event_handler(u32 acpi_event,
++ acpi_event_handler
++ handler))
+ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+- acpi_remove_gpe_handler(acpi_handle gpe_device,
++ acpi_install_gpe_handler(acpi_handle
++ gpe_device,
+ u32 gpe_number,
++ u32 type,
+ acpi_gpe_handler
+- address))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_notify_handler(acpi_handle device,
+- u32 handler_type,
+- acpi_notify_handler
+- handler,
++ address,
+ void *context))
++ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
++ acpi_install_gpe_raw_handler(acpi_handle
++ gpe_device,
++ u32 gpe_number,
++ u32 type,
++ acpi_gpe_handler
++ address,
++ void *context))
++ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
++ acpi_remove_gpe_handler(acpi_handle gpe_device,
++ u32 gpe_number,
++ acpi_gpe_handler
++ address))
+ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_remove_notify_handler(acpi_handle device,
++ acpi_install_notify_handler(acpi_handle device,
+ u32 handler_type,
+ acpi_notify_handler
+- handler))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_address_space_handler(acpi_handle
+- device,
+- acpi_adr_space_type
+- space_id,
+- acpi_adr_space_handler
+- handler,
+- acpi_adr_space_setup
+- setup,
+- void *context))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_remove_address_space_handler(acpi_handle
++ handler,
++ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_remove_notify_handler(acpi_handle device,
++ u32 handler_type,
++ acpi_notify_handler
++ handler))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_address_space_handler(acpi_handle
+ device,
+ acpi_adr_space_type
+ space_id,
+ acpi_adr_space_handler
+- handler))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_exception_handler
+- (acpi_exception_handler handler))
+-ACPI_EXTERNAL_RETURN_STATUS(acpi_status
+- acpi_install_interface_handler
+- (acpi_interface_handler handler))
++ handler,
++ acpi_adr_space_setup
++ setup,
++ void *context))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_remove_address_space_handler(acpi_handle
++ device,
++ acpi_adr_space_type
++ space_id,
++ acpi_adr_space_handler
++ handler))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_exception_handler
++ (acpi_exception_handler handler))
++ACPI_EXTERNAL_RETURN_STATUS(acpi_status
++ acpi_install_interface_handler
++ (acpi_interface_handler handler))
+
+ /*
+ * Global Lock interfaces
+--
+2.53.0
+
--- /dev/null
+From 357049b8b8b1e523535b2d3d25d31b401988802d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:04 +0100
+Subject: ASoC: adau1372: Fix clock leak on PLL lock failure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit bfe6a264effcb6fe99ad7ceaf9e8c7439fc9555b ]
+
+adau1372_enable_pll() was a void function that logged a dev_err() on
+PLL lock timeout but did not propagate the error. As a result,
+adau1372_set_power() would continue with adau1372->enabled set to true
+despite the PLL being unlocked, and the mclk left enabled with no
+corresponding disable on the error path.
+
+Convert adau1372_enable_pll() to return int, using -ETIMEDOUT on lock
+timeout and propagating regmap errors directly. In adau1372_set_power(),
+check the return value and unwind in reverse order: restore regcache to
+cache-only mode, reassert GPIO power-down, and disable the clock before
+returning the error.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index 79446c4458cc6..1a4ab7c993d28 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -761,7 +761,7 @@ static int adau1372_startup(struct snd_pcm_substream *substream, struct snd_soc_
+ return 0;
+ }
+
+-static void adau1372_enable_pll(struct adau1372 *adau1372)
++static int adau1372_enable_pll(struct adau1372 *adau1372)
+ {
+ unsigned int val, timeout = 0;
+ int ret;
+@@ -777,8 +777,12 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ timeout++;
+ } while (!(val & 1) && timeout < 3);
+
+- if (ret < 0 || !(val & 1))
++ if (ret < 0 || !(val & 1)) {
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
++ return ret < 0 ? ret : -ETIMEDOUT;
++ }
++
++ return 0;
+ }
+
+ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+@@ -806,7 +810,14 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ * accessed.
+ */
+ if (adau1372->use_pll) {
+- adau1372_enable_pll(adau1372);
++ ret = adau1372_enable_pll(adau1372);
++ if (ret) {
++ regcache_cache_only(adau1372->regmap, true);
++ if (adau1372->pd_gpio)
++ gpiod_set_value(adau1372->pd_gpio, 1);
++ clk_disable_unprepare(adau1372->mclk);
++ return ret;
++ }
+ clk_ctrl |= ADAU1372_CLK_CTRL_CLKSRC;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 8ef8a3850becd0c949d48393046604bf426d9938 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:03 +0100
+Subject: ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit 326fe8104a4020d30080d37ac8b6b43893cdebca ]
+
+adau1372_set_power() calls clk_prepare_enable() but discards the return
+value. If the clock enable fails, the driver proceeds to access registers
+on unpowered hardware, potentially causing silent corruption.
+
+Make adau1372_set_power() return int and propagate the error from
+clk_prepare_enable(). Update adau1372_set_bias_level() to return the
+error directly for the STANDBY and OFF cases.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index a9f89e8565ec6..79446c4458cc6 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -781,15 +781,18 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
+ }
+
+-static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
++static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ {
+ if (adau1372->enabled == enable)
+- return;
++ return 0;
+
+ if (enable) {
+ unsigned int clk_ctrl = ADAU1372_CLK_CTRL_MCLK_EN;
++ int ret;
+
+- clk_prepare_enable(adau1372->mclk);
++ ret = clk_prepare_enable(adau1372->mclk);
++ if (ret)
++ return ret;
+ if (adau1372->pd_gpio)
+ gpiod_set_value(adau1372->pd_gpio, 0);
+
+@@ -828,6 +831,8 @@ static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ }
+
+ adau1372->enabled = enable;
++
++ return 0;
+ }
+
+ static int adau1372_set_bias_level(struct snd_soc_component *component,
+@@ -841,11 +846,9 @@ static int adau1372_set_bias_level(struct snd_soc_component *component,
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+- adau1372_set_power(adau1372, true);
+- break;
++ return adau1372_set_power(adau1372, true);
+ case SND_SOC_BIAS_OFF:
+- adau1372_set_power(adau1372, false);
+- break;
++ return adau1372_set_power(adau1372, false);
+ }
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 84b08d9d802b38e6662cab170c3939f57caae537 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 11:12:17 +0100
+Subject: ASoC: Intel: catpt: Fix the device initialization
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 5a184f1cb43a8e035251c635f5c47da5dc3e3049 ]
+
+The DMA mask shall be coerced before any buffer allocations for the
+device are done. At the same time explain why DMA mask of 31 bits is
+used in the first place.
+
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle")
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/catpt/device.c | 10 +++++++++-
+ sound/soc/intel/catpt/dsp.c | 3 ---
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c
+index d5d08bd766c70..4783876ed56f1 100644
+--- a/sound/soc/intel/catpt/device.c
++++ b/sound/soc/intel/catpt/device.c
+@@ -271,7 +271,15 @@ static int catpt_acpi_probe(struct platform_device *pdev)
+ if (IS_ERR(cdev->pci_ba))
+ return PTR_ERR(cdev->pci_ba);
+
+- /* alloc buffer for storing DRAM context during dx transitions */
++ /*
++ * As per design HOST is responsible for preserving firmware's runtime
++ * context during D0 -> D3 -> D0 transitions. Addresses used for DMA
++ * to/from HOST memory shall be outside the reserved range of 0xFFFxxxxx.
++ */
++ ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
++ if (ret)
++ return ret;
++
+ cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev),
+ &cdev->dxbuf_paddr, GFP_KERNEL);
+ if (!cdev->dxbuf_vaddr)
+diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
+index 346bec0003066..3cde6b7ae9237 100644
+--- a/sound/soc/intel/catpt/dsp.c
++++ b/sound/soc/intel/catpt/dsp.c
+@@ -125,9 +125,6 @@ int catpt_dmac_probe(struct catpt_dev *cdev)
+ dmac->dev = cdev->dev;
+ dmac->irq = cdev->irq;
+
+- ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
+- if (ret)
+- return ret;
+ /*
+ * Caller is responsible for putting device in D0 to allow
+ * for I/O and memory access before probing DW.
+--
+2.53.0
+
--- /dev/null
+From 80bb7aaab5717b5d17e987d87e4d365b7dc0c036 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Mar 2026 13:41:18 +0530
+Subject: drm/amdgpu: Fix fence put before wait in amdgpu_amdkfd_submit_ib
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 7150850146ebfa4ca998f653f264b8df6f7f85be ]
+
+amdgpu_amdkfd_submit_ib() submits a GPU job and gets a fence
+from amdgpu_ib_schedule(). This fence is used to wait for job
+completion.
+
+Currently, the code drops the fence reference using dma_fence_put()
+before calling dma_fence_wait().
+
+If dma_fence_put() releases the last reference, the fence may be
+freed before dma_fence_wait() is called. This can lead to a
+use-after-free.
+
+Fix this by waiting on the fence first and releasing the reference
+only after dma_fence_wait() completes.
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c:697 amdgpu_amdkfd_submit_ib() warn: passing freed memory 'f' (line 696)
+
+Fixes: 9ae55f030dc5 ("drm/amdgpu: Follow up change to previous drm scheduler change.")
+Cc: Felix Kuehling <Felix.Kuehling@amd.com>
+Cc: Dan Carpenter <dan.carpenter@linaro.org>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+index 330d1404988c3..d58c8e452ca3f 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -694,9 +694,9 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
+ goto err_ib_sched;
+ }
+
+- /* Drop the initial kref_init count (see drm_sched_main as example) */
+- dma_fence_put(f);
+ ret = dma_fence_wait(f, false);
++ /* Drop the returned fence reference after the wait completes */
++ dma_fence_put(f);
+
+ err_ib_sched:
+ amdgpu_job_free(job);
+--
+2.53.0
+
--- /dev/null
+From 3ffada3b9ed899b8c2c761e2e7be4acc44dc1afe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 16:19:19 -0700
+Subject: drm/i915/gmbus: fix spurious timeout on 512-byte burst reads
+
+From: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+
+[ Upstream commit 08441f10f4dc09fdeb64529953ac308abc79dd38 ]
+
+When reading exactly 512 bytes with burst read enabled, the
+extra_byte_added path breaks out of the inner do-while without
+decrementing len. The outer while(len) then re-enters and gmbus_wait()
+times out since all data has been delivered. Decrement len before the
+break so the outer loop terminates correctly.
+
+Fixes: d5dc0f43f268 ("drm/i915/gmbus: Enable burst read")
+Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_gmbus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
+index 74443f57f62df..8595f7e7fc34c 100644
+--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
++++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
+@@ -470,8 +470,10 @@ gmbus_xfer_read_chunk(struct drm_i915_private *i915,
+
+ val = intel_de_read_fw(i915, GMBUS3(i915));
+ do {
+- if (extra_byte_added && len == 1)
++ if (extra_byte_added && len == 1) {
++ len--;
+ break;
++ }
+
+ *buf++ = val & 0xff;
+ val >>= 8;
+--
+2.53.0
+
--- /dev/null
+From 2fa7a16b99dc74214881aeee69d0480bd10fd440 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 05:13:06 +0000
+Subject: hwmon: (adm1177) fix sysfs ABI violation and current unit conversion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sanman Pradhan <psanman@juniper.net>
+
+[ Upstream commit bf08749a6abb6d1959bfdc0edc32c640df407558 ]
+
+The adm1177 driver exposes the current alert threshold through
+hwmon_curr_max_alarm. This violates the hwmon sysfs ABI, where
+*_alarm attributes are read-only status flags and writable thresholds
+must use currN_max.
+
+The driver also stores the threshold internally in microamps, while
+currN_max is defined in milliamps. Convert the threshold accordingly
+on both the read and write paths.
+
+Widen the cached threshold and related calculations to 64 bits so
+that small shunt resistor values do not cause truncation or overflow.
+Also use 64-bit arithmetic for the mA/uA conversions, clamp writes
+to the range the hardware can represent, and propagate failures from
+adm1177_write_alert_thr() instead of silently ignoring them.
+
+Update the hwmon documentation to reflect the attribute rename and
+the correct units returned by the driver.
+
+Fixes: 09b08ac9e8d5 ("hwmon: (adm1177) Add ADM1177 Hot Swap Controller and Digital Power Monitor driver")
+Signed-off-by: Sanman Pradhan <psanman@juniper.net>
+Acked-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/adm1177.rst | 8 ++---
+ drivers/hwmon/adm1177.c | 54 +++++++++++++++++++--------------
+ 2 files changed, 35 insertions(+), 27 deletions(-)
+
+diff --git a/Documentation/hwmon/adm1177.rst b/Documentation/hwmon/adm1177.rst
+index 1c85a2af92bf7..375f6d6e03a7d 100644
+--- a/Documentation/hwmon/adm1177.rst
++++ b/Documentation/hwmon/adm1177.rst
+@@ -27,10 +27,10 @@ for details.
+ Sysfs entries
+ -------------
+
+-The following attributes are supported. Current maxim attribute
++The following attributes are supported. Current maximum attribute
+ is read-write, all other attributes are read-only.
+
+-in0_input Measured voltage in microvolts.
++in0_input Measured voltage in millivolts.
+
+-curr1_input Measured current in microamperes.
+-curr1_max_alarm Overcurrent alarm in microamperes.
++curr1_input Measured current in milliamperes.
++curr1_max Overcurrent shutdown threshold in milliamperes.
+diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c
+index 0c5dbc5e33b46..d2ccb133b2927 100644
+--- a/drivers/hwmon/adm1177.c
++++ b/drivers/hwmon/adm1177.c
+@@ -10,6 +10,8 @@
+ #include <linux/hwmon.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
++#include <linux/math64.h>
++#include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/regulator/consumer.h>
+
+@@ -35,7 +37,7 @@ struct adm1177_state {
+ struct i2c_client *client;
+ struct regulator *reg;
+ u32 r_sense_uohm;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
+ bool vrange_high;
+ };
+
+@@ -50,7 +52,7 @@ static int adm1177_write_cmd(struct adm1177_state *st, u8 cmd)
+ }
+
+ static int adm1177_write_alert_thr(struct adm1177_state *st,
+- u32 alert_threshold_ua)
++ u64 alert_threshold_ua)
+ {
+ u64 val;
+ int ret;
+@@ -93,8 +95,8 @@ static int adm1177_read(struct device *dev, enum hwmon_sensor_types type,
+ *val = div_u64((105840000ull * dummy),
+ 4096 * st->r_sense_uohm);
+ return 0;
+- case hwmon_curr_max_alarm:
+- *val = st->alert_threshold_ua;
++ case hwmon_curr_max:
++ *val = div_u64(st->alert_threshold_ua, 1000);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+@@ -128,9 +130,10 @@ static int adm1177_write(struct device *dev, enum hwmon_sensor_types type,
+ switch (type) {
+ case hwmon_curr:
+ switch (attr) {
+- case hwmon_curr_max_alarm:
+- adm1177_write_alert_thr(st, val);
+- return 0;
++ case hwmon_curr_max:
++ val = clamp_val(val, 0,
++ div_u64(105840000ULL, st->r_sense_uohm));
++ return adm1177_write_alert_thr(st, (u64)val * 1000);
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -158,7 +161,7 @@ static umode_t adm1177_is_visible(const void *data,
+ if (st->r_sense_uohm)
+ return 0444;
+ return 0;
+- case hwmon_curr_max_alarm:
++ case hwmon_curr_max:
+ if (st->r_sense_uohm)
+ return 0644;
+ return 0;
+@@ -172,7 +175,7 @@ static umode_t adm1177_is_visible(const void *data,
+
+ static const struct hwmon_channel_info *adm1177_info[] = {
+ HWMON_CHANNEL_INFO(curr,
+- HWMON_C_INPUT | HWMON_C_MAX_ALARM),
++ HWMON_C_INPUT | HWMON_C_MAX),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT),
+ NULL
+@@ -201,7 +204,8 @@ static int adm1177_probe(struct i2c_client *client)
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct adm1177_state *st;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
++ u32 prop;
+ int ret;
+
+ st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+@@ -229,22 +233,26 @@ static int adm1177_probe(struct i2c_client *client)
+ if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
+ &st->r_sense_uohm))
+ st->r_sense_uohm = 0;
+- if (device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
+- &alert_threshold_ua)) {
+- if (st->r_sense_uohm)
+- /*
+- * set maximum default value from datasheet based on
+- * shunt-resistor
+- */
+- alert_threshold_ua = div_u64(105840000000,
+- st->r_sense_uohm);
+- else
+- alert_threshold_ua = 0;
++ if (!device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
++ &prop)) {
++ alert_threshold_ua = prop;
++ } else if (st->r_sense_uohm) {
++ /*
++ * set maximum default value from datasheet based on
++ * shunt-resistor
++ */
++ alert_threshold_ua = div_u64(105840000000ULL,
++ st->r_sense_uohm);
++ } else {
++ alert_threshold_ua = 0;
+ }
+ st->vrange_high = device_property_read_bool(dev,
+ "adi,vrange-high-enable");
+- if (alert_threshold_ua && st->r_sense_uohm)
+- adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (alert_threshold_ua && st->r_sense_uohm) {
++ ret = adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (ret)
++ return ret;
++ }
+
+ ret = adm1177_write_cmd(st, ADM1177_CMD_V_CONT |
+ ADM1177_CMD_I_CONT |
+--
+2.53.0
+
--- /dev/null
+From 7791d15ec206e96bab5b35d620cef319b344f517 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:43 -0500
+Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node
+
+From: Ivan Barrera <ivan.d.barrera@intel.com>
+
+[ Upstream commit b415399c9a024d574b65479636f0d4eb625b9abd ]
+
+The cm_node is available and the usage of cm_node and event->cm_node
+seems arbitrary. Clean up unnecessary dereference of event->cm_node.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Ivan Barrera <ivan.d.barrera@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index 691b9ed7f759d..b8f945576eb53 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -4181,21 +4181,21 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ irdma_cm_event_reset(event);
+ break;
+ case IRDMA_CM_EVENT_CONNECTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state != IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state != IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_cm_event_connected(event);
+ break;
+ case IRDMA_CM_EVENT_MPA_REJECT:
+- if (!event->cm_node->cm_id ||
++ if (!cm_node->cm_id ||
+ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_send_cm_event(cm_node, cm_node->cm_id,
+ IW_CM_EVENT_CONNECT_REPLY, -ECONNREFUSED);
+ break;
+ case IRDMA_CM_EVENT_ABORTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state == IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_event_connect_error(event);
+ break;
+@@ -4205,7 +4205,7 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ break;
+ }
+
+- irdma_rem_ref_cm_node(event->cm_node);
++ irdma_rem_ref_cm_node(cm_node);
+ kfree(event);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 8b320da77cab5913b6bd2d65f8151eb2637832ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:45 -0500
+Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections
+
+From: Anil Samal <anil.samal@intel.com>
+
+[ Upstream commit 6f52370970ac07d352a7af4089e55e0e6425f827 ]
+
+Resolve deadlock that occurs when user executes netdev reset while RDMA
+applications (e.g., rping) are active. The netdev reset causes ice
+driver to remove irdma auxiliary driver, triggering device_delete and
+subsequent client removal. During client removal, uverbs_client waits
+for QP reference count to reach zero while cma_client holds the final
+reference, creating circular dependency and indefinite wait in iWARP
+mode. Skip QP reference count wait during device reset to prevent
+deadlock.
+
+Fixes: c8f304d75f6c ("RDMA/irdma: Prevent QP use after free")
+Signed-off-by: Anil Samal <anil.samal@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 6d1ca8a1717c4..1eb219fa0d453 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -534,7 +534,8 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+ }
+
+ irdma_qp_rem_ref(&iwqp->ibqp);
+- wait_for_completion(&iwqp->free_qp);
++ if (!iwdev->rf->reset)
++ wait_for_completion(&iwqp->free_qp);
+ irdma_free_lsmm_rsrc(iwqp);
+ irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
+
+--
+2.53.0
+
--- /dev/null
+From 0af3430feac4dc8cf6346ae70cd94c21bc253225 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:38 -0500
+Subject: RDMA/irdma: Initialize free_qp completion before using it
+
+From: Jacob Moroni <jmoroni@google.com>
+
+[ Upstream commit 11a95521fb93c91e2d4ef9d53dc80ef0a755549b ]
+
+In irdma_create_qp, if ib_copy_to_udata fails, it will call
+irdma_destroy_qp to clean up which will attempt to wait on
+the free_qp completion, which is not initialized yet. Fix this
+by initializing the completion before the ib_copy_to_udata call.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Jacob Moroni <jmoroni@google.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index d0139a696d437..2f5299c9d9ed3 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1005,6 +1005,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ spin_lock_init(&iwqp->sc_qp.pfpdu.lock);
+ iwqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) ? 1 : 0;
+ rf->qp_table[qp_num] = iwqp;
++ init_completion(&iwqp->free_qp);
+
+ if (rdma_protocol_roce(&iwdev->ibdev, 1)) {
+ if (dev->ws_add(&iwdev->vsi, 0)) {
+@@ -1039,7 +1040,6 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ }
+ }
+
+- init_completion(&iwqp->free_qp);
+ return 0;
+
+ error:
+--
+2.53.0
+
--- /dev/null
+From bf147f829ebcc43c347ea31de9598e7f4f19d7a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:42 -0500
+Subject: RDMA/irdma: Remove a NOP wait_event() in irdma_modify_qp_roce()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 5e8f0239731a83753473b7aa91bda67bbdff5053 ]
+
+Remove a NOP wait_event() in irdma_modify_qp_roce() which is relevant
+for iWARP and likely a copy and paste artifact for RoCEv2. The wait event
+is for sending a reset on a TCP connection, after the reset has been
+requested in irdma_modify_qp(), which occurs only in iWarp mode.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 5bd4062fa82ff..6d1ca8a1717c4 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1341,8 +1341,6 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ roce_info->rd_en = true;
+ }
+
+- wait_event(iwqp->mod_qp_waitq, !atomic_read(&iwqp->hw_mod_qp_pend));
+-
+ ibdev_dbg(&iwdev->ibdev,
+ "VERBS: caller: %pS qp_id=%d to_ibqpstate=%d ibqpstate=%d irdma_qpstate=%d attr_mask=0x%x\n",
+ __builtin_return_address(0), ibqp->qp_num, attr->qp_state,
+--
+2.53.0
+
--- /dev/null
+From 8b58f082423797c9bc85e528981e8c0b8aadb480 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:44 -0500
+Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit c45c6ebd693b944f1ffe429fdfb6cc1674c237be ]
+
+During reset, irdma_modify_qp() to error should be called to disconnect
+the QP. Without this fix, if not preceded by irdma_modify_qp() to error, the
+API call irdma_destroy_qp() gets stuck waiting for the QP refcount to go
+to zero, because the cm_node associated with this QP isn't disconnected.
+
+Fixes: 915cc7ac0f8e ("RDMA/irdma: Add miscellaneous utility definitions")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/utils.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
+index d236e4a27ca92..98a3849c39bf0 100644
+--- a/drivers/infiniband/hw/irdma/utils.c
++++ b/drivers/infiniband/hw/irdma/utils.c
+@@ -2456,8 +2456,6 @@ void irdma_modify_qp_to_err(struct irdma_sc_qp *sc_qp)
+ struct irdma_qp *qp = sc_qp->qp_uk.back_qp;
+ struct ib_qp_attr attr;
+
+- if (qp->iwdev->rf->reset)
+- return;
+ attr.qp_state = IB_QPS_ERR;
+
+ if (rdma_protocol_roce(qp->ibqp.device, 1))
+--
+2.53.0
+
--- /dev/null
+From b6877084939a2be6f85efa93feb1eadfbf5a3750 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:46 -0500
+Subject: RDMA/irdma: Return EINVAL for invalid arp index error
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 7221f581eefa79ead06e171044f393fb7ee22f87 ]
+
+When rdma_connect() fails due to an invalid arp index, user space rdma core
+reports ENOMEM which is confusing. Modify irdma_make_cm_node() to return the
+correct error code.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index b8f945576eb53..f72863aefcad7 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -2196,11 +2196,12 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ int oldarpindex;
+ int arpindex;
+ struct net_device *netdev = iwdev->netdev;
++ int ret;
+
+ /* create an hte and cm_node for this instance */
+ cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
+ if (!cm_node)
+- return NULL;
++ return ERR_PTR(-ENOMEM);
+
+ /* set our node specific transport info */
+ cm_node->ipv4 = cm_info->ipv4;
+@@ -2299,8 +2300,10 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ arpindex = -EINVAL;
+ }
+
+- if (arpindex < 0)
++ if (arpindex < 0) {
++ ret = -EINVAL;
+ goto err;
++ }
+
+ ether_addr_copy(cm_node->rem_mac,
+ iwdev->rf->arp_table[arpindex].mac_addr);
+@@ -2311,7 +2314,7 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ err:
+ kfree(cm_node);
+
+- return NULL;
++ return ERR_PTR(ret);
+ }
+
+ static void irdma_destroy_connection(struct irdma_cm_node *cm_node)
+@@ -2972,8 +2975,8 @@ static int irdma_create_cm_node(struct irdma_cm_core *cm_core,
+
+ /* create a CM connection node */
+ cm_node = irdma_make_cm_node(cm_core, iwdev, cm_info, NULL);
+- if (!cm_node)
+- return -ENOMEM;
++ if (IS_ERR(cm_node))
++ return PTR_ERR(cm_node);
+
+ /* set our node side to client (active) side */
+ cm_node->tcp_cntxt.client = 1;
+@@ -3170,9 +3173,9 @@ void irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf)
+ cm_info.cm_id = listener->cm_id;
+ cm_node = irdma_make_cm_node(cm_core, iwdev, &cm_info,
+ listener);
+- if (!cm_node) {
++ if (IS_ERR(cm_node)) {
+ ibdev_dbg(&cm_core->iwdev->ibdev,
+- "CM: allocate node failed\n");
++ "CM: allocate node failed ret=%ld\n", PTR_ERR(cm_node));
+ refcount_dec(&listener->refcnt);
+ return;
+ }
+--
+2.53.0
+
--- /dev/null
+From 154227439ab96fb75ba506b9b9242be37eb62614 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:41 -0500
+Subject: RDMA/irdma: Update ibqp state to error if QP is already in error
+ state
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 8c1f19a2225cf37b3f8ab0b5a8a5322291cda620 ]
+
+In irdma_modify_qp() update ibqp state to error if the irdma QP is already
+in error state, otherwise the ibqp state which is visible to the consumer
+app remains stale.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 2f5299c9d9ed3..5bd4062fa82ff 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1419,6 +1419,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+@@ -1624,6 +1625,7 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+--
+2.53.0
+
--- /dev/null
+From 2d0bfce7d7d5e2ad52df214b6cb1d4801c540089 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Mar 2026 15:41:58 -0400
+Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 00da250c21b074ea9494c375d0117b69e5b1d0a4 ]
+
+When IOMMU passthrough mode is active, ib_dma_map_sgtable_attrs()
+produces no coalescing: each scatterlist page maps 1:1 to a DMA
+entry, so sgt.nents equals the raw page count. A 1 MB transfer
+yields 256 DMA entries. If that count exceeds the device's
+max_sgl_rd threshold (an optimization hint from mlx5 firmware),
+rdma_rw_io_needs_mr() steers the operation into the MR
+registration path. Each such operation consumes one or more MRs
+from a pool sized at max_rdma_ctxs -- roughly one MR per
+concurrent context. Under write-intensive workloads that issue
+many concurrent RDMA READs, the pool is rapidly exhausted,
+ib_mr_pool_get() returns NULL, and rdma_rw_init_one_mr() returns
+-EAGAIN. Upper layer protocols treat this as a fatal DMA mapping
+failure and tear down the connection.
+
+The max_sgl_rd check is a performance optimization, not a
+correctness requirement: the device can handle large SGE counts
+via direct posting, just less efficiently than with MR
+registration. When the MR pool cannot satisfy a request, falling
+back to the direct SGE (map_wrs) path avoids the connection
+reset while preserving the MR optimization for the common case
+where pool resources are available.
+
+Add a fallback in rdma_rw_ctx_init() so that -EAGAIN from
+rdma_rw_init_mr_wrs() triggers direct SGE posting instead of
+propagating the error. iWARP devices, which mandate MR
+registration for RDMA READs, and force_mr debug mode continue
+to treat -EAGAIN as terminal.
+
+Fixes: 00bd1439f464 ("RDMA/rw: Support threshold for registration vs scattering to local pages")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/rw.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
+index 2522ff1cc462c..49fbfe1cef689 100644
+--- a/drivers/infiniband/core/rw.c
++++ b/drivers/infiniband/core/rw.c
+@@ -326,14 +326,29 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u32 port_num,
+ if (rdma_rw_io_needs_mr(qp->device, port_num, dir, sg_cnt)) {
+ ret = rdma_rw_init_mr_wrs(ctx, qp, port_num, sg, sg_cnt,
+ sg_offset, remote_addr, rkey, dir);
+- } else if (sg_cnt > 1) {
++ /*
++ * If MR init succeeded or failed for a reason other
++ * than pool exhaustion, that result is final.
++ *
++ * Pool exhaustion (-EAGAIN) from the max_sgl_rd
++ * optimization is recoverable: fall back to
++ * direct SGE posting. iWARP and force_mr require
++ * MRs unconditionally, so -EAGAIN is terminal.
++ */
++ if (ret != -EAGAIN ||
++ rdma_protocol_iwarp(qp->device, port_num) ||
++ unlikely(rdma_rw_force_mr))
++ goto out;
++ }
++
++ if (sg_cnt > 1)
+ ret = rdma_rw_init_map_wrs(ctx, qp, sg, sg_cnt, sg_offset,
+ remote_addr, rkey, dir);
+- } else {
++ else
+ ret = rdma_rw_init_single_wr(ctx, qp, sg, sg_offset,
+ remote_addr, rkey, dir);
+- }
+
++out:
+ if (ret < 0)
+ goto out_unmap_sg;
+ return ret;
+--
+2.53.0
+
--- /dev/null
+From 9f877b4e4d05ba28137e7e2761f0a2fb768c839b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Mar 2026 19:43:31 +0100
+Subject: regmap: Synchronize cache for the page selector
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 09e70e4f119ff650d24c96161fd2f62ac7e424b0 ]
+
+If the selector register is represented in each page, its value
+according to the debugfs is stale because it gets synchronized
+only after the real page switch happens. Hence the regmap cache
+initialisation from the HW inherits outdated data in the selector
+register.
+
+Synchronize cache for the page selector just in time.
+
+Before (offset followed by hexdump, the first byte is selector):
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 05 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 01 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 02 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 03 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 04 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+After:
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 01 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 02 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 03 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 04 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+Fixes: 6863ca622759 ("regmap: Add support for register indirect addressing.")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap.c | 30 ++++++++++++++++++++++++++----
+ 1 file changed, 26 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index bc89790ff0ded..6d8ed7683a387 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -1634,6 +1634,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ unsigned int val_num)
+ {
+ void *orig_work_buf;
++ unsigned int selector_reg;
+ unsigned int win_offset;
+ unsigned int win_page;
+ bool page_chg;
+@@ -1652,10 +1653,31 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ return -EINVAL;
+ }
+
+- /* It is possible to have selector register inside data window.
+- In that case, selector register is located on every page and
+- it needs no page switching, when accessed alone. */
++ /*
++ * Calculate the address of the selector register in the corresponding
++ * data window if it is located on every page.
++ */
++ page_chg = in_range(range->selector_reg, range->window_start, range->window_len);
++ if (page_chg)
++ selector_reg = range->range_min + win_page * range->window_len +
++ range->selector_reg - range->window_start;
++
++ /*
++ * It is possible to have selector register inside data window.
++ * In that case, selector register is located on every page and it
++ * needs no page switching, when accessed alone.
++ *
++ * Nevertheless we should synchronize the cache values for it.
++ * This can't be properly achieved if the selector register is
++ * the first and the only one to be read inside the data window.
++ * That's why we update it in that case as well.
++ *
++ * However, we specifically avoid updating it for the default page,
++ * when it's overlapped with the real data window, to prevent from
++ * infinite looping.
++ */
+ if (val_num > 1 ||
++ (page_chg && selector_reg != range->selector_reg) ||
+ range->window_start + win_offset != range->selector_reg) {
+ /* Use separate work_buf during page switching */
+ orig_work_buf = map->work_buf;
+@@ -1664,7 +1686,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ ret = _regmap_update_bits(map, range->selector_reg,
+ range->selector_mask,
+ win_page << range->selector_shift,
+- &page_chg, false);
++ NULL, false);
+
+ map->work_buf = orig_work_buf;
+
+--
+2.53.0
+
--- /dev/null
+From 6fcb2256c3a1c30b68620daca0ec74b019329890 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 14:31:47 +0800
+Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue
+
+From: Yihang Li <liyihang9@huawei.com>
+
+[ Upstream commit d71afa9deb4d413232ba16d693f7d43b321931b4 ]
+
+After commit 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard
+and multi-channel scans"), if the device supports multiple channels (0 to
+shost->max_channel), user_scan() invokes updated sas_user_scan() to perform
+the scan behavior for a specific transfer. However, when the user
+specifies shost->max_channel, it will return -EINVAL, which is not
+expected.
+
+Fix and support specifying the scan shost->max_channel for scanning.
+
+Fixes: 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans")
+Signed-off-by: Yihang Li <liyihang9@huawei.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_sas.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index 5a19de2c70067..f11e74abb48c6 100644
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -1732,7 +1732,7 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ break;
+
+ default:
+- if (channel < shost->max_channel) {
++ if (channel <= shost->max_channel) {
+ res = scsi_scan_host_selected(shost, channel, id, lun,
+ SCSI_SCAN_MANUAL);
+ } else {
+--
+2.53.0
+
netlink-allow-be16-and-be32-types-in-all-uint-policy.patch
netfilter-ctnetlink-use-netlink-policy-range-checks.patch
net-macb-use-the-current-queue-number-for-stats.patch
+regmap-synchronize-cache-for-the-page-selector.patch
+rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch
+rdma-irdma-initialize-free_qp-completion-before-usin.patch
+rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch
+rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch
+rdma-irdma-clean-up-unnecessary-dereference-of-event.patch
+rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch
+rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch
+rdma-irdma-return-einval-for-invalid-arp-index-error.patch
+scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch
+x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch
+drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch
+asoc-intel-catpt-fix-the-device-initialization.patch
+acpica-include-acpi-acpixf.h-fix-indentation.patch
+acpica-allow-address_space_handler-install-and-_reg-.patch
+acpi-ec-fix-ec-address-space-handler-unregistration.patch
+acpi-ec-fix-ecdt-probe-ordering-issues.patch
+acpi-ec-install-address-space-handler-at-the-namespa.patch
+acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch
+drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch
+hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch
+sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch
+asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch
+asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch
+spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch
--- /dev/null
+From 1009aa803b44789f4ac0af4d87e93ca0186ecb5b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 19:38:12 +0100
+Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF)
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b341c1176f2e001b3adf0b47154fc31589f7410e ]
+
+There is a teardown order issue in the driver. The SPI controller is
+registered using devm_spi_register_controller(), which delays
+unregistration of the SPI controller until after the fsl_lpspi_remove()
+function returns.
+
+As the fsl_lpspi_remove() function synchronously tears down the DMA
+channels, a running SPI transfer triggers the following NULL pointer
+dereference due to use after free:
+
+| fsl_lpspi 42550000.spi: I/O Error in DMA RX
+| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
+[...]
+| Call trace:
+| fsl_lpspi_dma_transfer+0x260/0x340 [spi_fsl_lpspi]
+| fsl_lpspi_transfer_one+0x198/0x448 [spi_fsl_lpspi]
+| spi_transfer_one_message+0x49c/0x7c8
+| __spi_pump_transfer_message+0x120/0x420
+| __spi_sync+0x2c4/0x520
+| spi_sync+0x34/0x60
+| spidev_message+0x20c/0x378 [spidev]
+| spidev_ioctl+0x398/0x750 [spidev]
+[...]
+
+Switch from devm_spi_register_controller() to spi_register_controller() in
+fsl_lpspi_probe() and add the corresponding spi_unregister_controller() in
+fsl_lpspi_remove().
+
+Fixes: 5314987de5e5 ("spi: imx: add lpspi bus driver")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-fsl-lpspi.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
+index c0e15d8a913df..b3e6dcdb47f60 100644
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -913,7 +913,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+ enable_irq(irq);
+ }
+
+- ret = devm_spi_register_controller(&pdev->dev, controller);
++ ret = spi_register_controller(controller);
+ if (ret < 0) {
+ dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
+ goto free_dma;
+@@ -942,6 +942,7 @@ static int fsl_lpspi_remove(struct platform_device *pdev)
+ struct fsl_lpspi_data *fsl_lpspi =
+ spi_controller_get_devdata(controller);
+
++ spi_unregister_controller(controller);
+ fsl_lpspi_dma_exit(controller);
+
+ pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
+--
+2.53.0
+
--- /dev/null
+From 6c63508c646bc28b092adcdf76f3b67185511d65 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 23:29:50 +0100
+Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap
+
+From: Marc Buerg <buermarc@googlemail.com>
+
+[ Upstream commit f63a9df7e3f9f842945d292a19d9938924f066f9 ]
+
+proc_do_large_bitmap() does not initialize variable c, which is expected
+to be set to a trailing character by proc_get_long().
+
+However, proc_get_long() only sets c when the input buffer contains a
+trailing character after the parsed value.
+
+If c is not initialized it may happen to contain a '-'. If this is the
+case proc_do_large_bitmap() expects to be able to parse a second part of
+the input buffer. If there is no second part an unjustified -EINVAL will
+be returned.
+
+Initialize c to 0 to prevent returning -EINVAL on valid input.
+
+Fixes: 9f977fb7ae9d ("sysctl: add proc_do_large_bitmap")
+Signed-off-by: Marc Buerg <buermarc@googlemail.com>
+Reviewed-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sysctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index c6d9dec11b749..eaa2691caf492 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1391,7 +1391,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
+ unsigned long bitmap_len = table->maxlen;
+ unsigned long *bitmap = *(unsigned long **) table->data;
+ unsigned long *tmp_bitmap = NULL;
+- char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
++ char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c = 0;
+
+ if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
+ *lenp = 0;
+--
+2.53.0
+
--- /dev/null
+From c36f787f44b953f92e16fe2cccfe7aa4dd1c61ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 15:59:48 +0200
+Subject: x86/efi: efi_unmap_boot_services: fix calculation of ranges_to_free
+ size
+
+From: Mike Rapoport (Microsoft) <rppt@kernel.org>
+
+[ Upstream commit 217c0a5c177a3d4f7c8497950cbf5c36756e8bbb ]
+
+ranges_to_free array should have enough room to store the entire EFI
+memmap plus an extra element for NULL entry.
+The calculation of this array size wrongly adds 1 to the overall size
+instead of adding 1 to the number of elements.
+
+Add parentheses to properly size the array.
+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory")
+Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/platform/efi/quirks.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
+index e3b00f05a2532..b0d0376940ba8 100644
+--- a/arch/x86/platform/efi/quirks.c
++++ b/arch/x86/platform/efi/quirks.c
+@@ -416,7 +416,7 @@ void __init efi_unmap_boot_services(void)
+ if (efi_enabled(EFI_DBG))
+ return;
+
+- sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;
++ sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1);
+ ranges_to_free = kzalloc(sz, GFP_KERNEL);
+ if (!ranges_to_free) {
+ pr_err("Failed to allocate storage for freeable EFI regions\n");
+--
+2.53.0
+
--- /dev/null
+From 24b249312d66eb66330aeb459961024984bec513 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 00:54:59 +0800
+Subject: ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f6484cadbcaf26b5844b51bd7307a663dda48ef6 ]
+
+When ec_install_handlers() returns -EPROBE_DEFER on reduced-hardware
+platforms, it has already started the EC and installed the address
+space handler with the struct acpi_ec pointer as handler context.
+However, acpi_ec_setup() propagates the error without any cleanup.
+
+The caller acpi_ec_add() then frees the struct acpi_ec for non-boot
+instances, leaving a dangling handler context in ACPICA.
+
+Any subsequent AML evaluation that accesses an EC OpRegion field
+dispatches into acpi_ec_space_handler() with the freed pointer,
+causing a use-after-free:
+
+ BUG: KASAN: slab-use-after-free in mutex_lock (kernel/locking/mutex.c:289)
+ Write of size 8 at addr ffff88800721de38 by task init/1
+ Call Trace:
+ <TASK>
+ mutex_lock (kernel/locking/mutex.c:289)
+ acpi_ec_space_handler (drivers/acpi/ec.c:1362)
+ acpi_ev_address_space_dispatch (drivers/acpi/acpica/evregion.c:293)
+ acpi_ex_access_region (drivers/acpi/acpica/exfldio.c:246)
+ acpi_ex_field_datum_io (drivers/acpi/acpica/exfldio.c:509)
+ acpi_ex_extract_from_field (drivers/acpi/acpica/exfldio.c:700)
+ acpi_ex_read_data_from_field (drivers/acpi/acpica/exfield.c:327)
+ acpi_ex_resolve_node_to_value (drivers/acpi/acpica/exresolv.c:392)
+ </TASK>
+
+ Allocated by task 1:
+ acpi_ec_alloc (drivers/acpi/ec.c:1424)
+ acpi_ec_add (drivers/acpi/ec.c:1692)
+
+ Freed by task 1:
+ kfree (mm/slub.c:6876)
+ acpi_ec_add (drivers/acpi/ec.c:1751)
+
+The bug triggers on reduced-hardware EC platforms (ec->gpe < 0)
+when the GPIO IRQ provider defers probing. Once the stale handler
+exists, any unprivileged sysfs read that causes AML to touch an
+EC OpRegion (battery, thermal, backlight) exercises the dangling
+pointer.
+
+Fix this by calling ec_remove_handlers() in the error path of
+acpi_ec_setup() before clearing first_ec. ec_remove_handlers()
+checks each EC_FLAGS_* bit before acting, so it is safe to call
+regardless of how far ec_install_handlers() progressed:
+
+ -ENODEV (handler not installed): only calls acpi_ec_stop()
+ -EPROBE_DEFER (handler installed): removes handler, stops EC
+
+Fixes: 03e9a0e05739 ("ACPI: EC: Consolidate event handler installation code")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index a813bc97cf425..10bd2942c4beb 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1653,6 +1653,8 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+
+ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret) {
++ ec_remove_handlers(ec);
++
+ if (ec == first_ec)
+ first_ec = NULL;
+
+--
+2.53.0
+
--- /dev/null
+From c2c0bdb95fce22cd59979ae689fa09456bf9e8ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 15 Mar 2026 20:11:27 +0000
+Subject: ALSA: hda/realtek: Sequence GPIO2 on Star Labs StarFighter
+
+From: Sean Rhodes <sean@starlabs.systems>
+
+[ Upstream commit a6919f2a01f8fbf807b015e5b26aecae7db8117b ]
+
+The initial StarFighter quirk fixed the runtime suspend pop by muting
+speakers in the shutup callback before power-down. Further hardware
+validation showed that the speaker path is controlled directly by LINE2
+EAPD on NID 0x1b together with GPIO2 for the external amplifier.
+
+Replace the shutup-delay workaround with explicit sequencing of those
+controls at playback start and stop:
+- assert LINE2 EAPD and drive GPIO2 high on PREPARE
+- deassert LINE2 EAPD and drive GPIO2 low on CLEANUP
+
+This avoids the runtime suspend pop without a sleep, and also fixes pops
+around G3 entry and display-manager start that the original workaround
+did not cover.
+
+Fixes: 1cb3c20688fc ("ALSA: hda/realtek: Fix speaker pop on Star Labs StarFighter")
+Tested-by: Sean Rhodes <sean@starlabs.systems>
+Signed-off-by: Sean Rhodes <sean@starlabs.systems>
+Link: https://patch.msgid.link/20260315201127.33744-1-sean@starlabs.systems
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 38 +++++++++++++++++++++++++++++------
+ 1 file changed, 32 insertions(+), 6 deletions(-)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 689b5510a95e8..fad159187f445 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -4164,12 +4164,30 @@ static int alc269_resume(struct hda_codec *codec)
+ return 0;
+ }
+
+-#define STARLABS_STARFIGHTER_SHUTUP_DELAY_MS 30
++#define ALC233_STARFIGHTER_SPK_PIN 0x1b
++#define ALC233_STARFIGHTER_GPIO2 0x04
+
+-static void starlabs_starfighter_shutup(struct hda_codec *codec)
++static void alc233_starfighter_update_amp(struct hda_codec *codec, bool on)
+ {
+- if (snd_hda_gen_shutup_speakers(codec))
+- msleep(STARLABS_STARFIGHTER_SHUTUP_DELAY_MS);
++ snd_hda_codec_write(codec, ALC233_STARFIGHTER_SPK_PIN, 0,
++ AC_VERB_SET_EAPD_BTLENABLE,
++ on ? AC_EAPDBTL_EAPD : 0);
++ alc_update_gpio_data(codec, ALC233_STARFIGHTER_GPIO2, on);
++}
++
++static void alc233_starfighter_pcm_hook(struct hda_pcm_stream *hinfo,
++ struct hda_codec *codec,
++ struct snd_pcm_substream *substream,
++ int action)
++{
++ switch (action) {
++ case HDA_GEN_PCM_ACT_PREPARE:
++ alc233_starfighter_update_amp(codec, true);
++ break;
++ case HDA_GEN_PCM_ACT_CLEANUP:
++ alc233_starfighter_update_amp(codec, false);
++ break;
++ }
+ }
+
+ static void alc233_fixup_starlabs_starfighter(struct hda_codec *codec,
+@@ -4178,8 +4196,16 @@ static void alc233_fixup_starlabs_starfighter(struct hda_codec *codec,
+ {
+ struct alc_spec *spec = codec->spec;
+
+- if (action == HDA_FIXUP_ACT_PRE_PROBE)
+- spec->shutup = starlabs_starfighter_shutup;
++ switch (action) {
++ case HDA_FIXUP_ACT_PRE_PROBE:
++ spec->gpio_mask |= ALC233_STARFIGHTER_GPIO2;
++ spec->gpio_dir |= ALC233_STARFIGHTER_GPIO2;
++ spec->gpio_data &= ~ALC233_STARFIGHTER_GPIO2;
++ break;
++ case HDA_FIXUP_ACT_PROBE:
++ spec->gen.pcm_playback_hook = alc233_starfighter_pcm_hook;
++ break;
++ }
+ }
+
+ static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec,
+--
+2.53.0
+
--- /dev/null
+From c441bfce6f2a2a2c8255def521edbefff205ec48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:04 +0100
+Subject: ASoC: adau1372: Fix clock leak on PLL lock failure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit bfe6a264effcb6fe99ad7ceaf9e8c7439fc9555b ]
+
+adau1372_enable_pll() was a void function that logged a dev_err() on
+PLL lock timeout but did not propagate the error. As a result,
+adau1372_set_power() would continue with adau1372->enabled set to true
+despite the PLL being unlocked, and the mclk left enabled with no
+corresponding disable on the error path.
+
+Convert adau1372_enable_pll() to return int, using -ETIMEDOUT on lock
+timeout and propagating regmap errors directly. In adau1372_set_power(),
+check the return value and unwind in reverse order: restore regcache to
+cache-only mode, reassert GPIO power-down, and disable the clock before
+returning the error.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index f629be6c297df..25f123110b5be 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -761,7 +761,7 @@ static int adau1372_startup(struct snd_pcm_substream *substream, struct snd_soc_
+ return 0;
+ }
+
+-static void adau1372_enable_pll(struct adau1372 *adau1372)
++static int adau1372_enable_pll(struct adau1372 *adau1372)
+ {
+ unsigned int val, timeout = 0;
+ int ret;
+@@ -777,8 +777,12 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ timeout++;
+ } while (!(val & 1) && timeout < 3);
+
+- if (ret < 0 || !(val & 1))
++ if (ret < 0 || !(val & 1)) {
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
++ return ret < 0 ? ret : -ETIMEDOUT;
++ }
++
++ return 0;
+ }
+
+ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+@@ -806,7 +810,14 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ * accessed.
+ */
+ if (adau1372->use_pll) {
+- adau1372_enable_pll(adau1372);
++ ret = adau1372_enable_pll(adau1372);
++ if (ret) {
++ regcache_cache_only(adau1372->regmap, true);
++ if (adau1372->pd_gpio)
++ gpiod_set_value(adau1372->pd_gpio, 1);
++ clk_disable_unprepare(adau1372->mclk);
++ return ret;
++ }
+ clk_ctrl |= ADAU1372_CLK_CTRL_CLKSRC;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 8c5a2cfd41e42078bbdf0903d079fbd3447bd634 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:03 +0100
+Subject: ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit 326fe8104a4020d30080d37ac8b6b43893cdebca ]
+
+adau1372_set_power() calls clk_prepare_enable() but discards the return
+value. If the clock enable fails, the driver proceeds to access registers
+on unpowered hardware, potentially causing silent corruption.
+
+Make adau1372_set_power() return int and propagate the error from
+clk_prepare_enable(). Update adau1372_set_bias_level() to return the
+error directly for the STANDBY and OFF cases.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index 98380a7ce64d8..f629be6c297df 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -781,15 +781,18 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
+ }
+
+-static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
++static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ {
+ if (adau1372->enabled == enable)
+- return;
++ return 0;
+
+ if (enable) {
+ unsigned int clk_ctrl = ADAU1372_CLK_CTRL_MCLK_EN;
++ int ret;
+
+- clk_prepare_enable(adau1372->mclk);
++ ret = clk_prepare_enable(adau1372->mclk);
++ if (ret)
++ return ret;
+ if (adau1372->pd_gpio)
+ gpiod_set_value(adau1372->pd_gpio, 0);
+
+@@ -828,6 +831,8 @@ static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ }
+
+ adau1372->enabled = enable;
++
++ return 0;
+ }
+
+ static int adau1372_set_bias_level(struct snd_soc_component *component,
+@@ -841,11 +846,9 @@ static int adau1372_set_bias_level(struct snd_soc_component *component,
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+- adau1372_set_power(adau1372, true);
+- break;
++ return adau1372_set_power(adau1372, true);
+ case SND_SOC_BIAS_OFF:
+- adau1372_set_power(adau1372, false);
+- break;
++ return adau1372_set_power(adau1372, false);
+ }
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 0d3110b50e53d0d4bf9078788832930a63d34fad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 11:12:17 +0100
+Subject: ASoC: Intel: catpt: Fix the device initialization
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 5a184f1cb43a8e035251c635f5c47da5dc3e3049 ]
+
+The DMA mask shall be coerced before any buffer allocations for the
+device are done. At the same time explain why DMA mask of 31 bits is
+used in the first place.
+
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle")
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/catpt/device.c | 10 +++++++++-
+ sound/soc/intel/catpt/dsp.c | 3 ---
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c
+index 2aa637124bec6..37f4d116e6c26 100644
+--- a/sound/soc/intel/catpt/device.c
++++ b/sound/soc/intel/catpt/device.c
+@@ -271,7 +271,15 @@ static int catpt_acpi_probe(struct platform_device *pdev)
+ if (IS_ERR(cdev->pci_ba))
+ return PTR_ERR(cdev->pci_ba);
+
+- /* alloc buffer for storing DRAM context during dx transitions */
++ /*
++ * As per design HOST is responsible for preserving firmware's runtime
++ * context during D0 -> D3 -> D0 transitions. Addresses used for DMA
++ * to/from HOST memory shall be outside the reserved range of 0xFFFxxxxx.
++ */
++ ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
++ if (ret)
++ return ret;
++
+ cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev),
+ &cdev->dxbuf_paddr, GFP_KERNEL);
+ if (!cdev->dxbuf_vaddr)
+diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
+index 5993819cc58a2..8e4836605e8e1 100644
+--- a/sound/soc/intel/catpt/dsp.c
++++ b/sound/soc/intel/catpt/dsp.c
+@@ -125,9 +125,6 @@ int catpt_dmac_probe(struct catpt_dev *cdev)
+ dmac->dev = cdev->dev;
+ dmac->irq = cdev->irq;
+
+- ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
+- if (ret)
+- return ret;
+ /*
+ * Caller is responsible for putting device in D0 to allow
+ * for I/O and memory access before probing DW.
+--
+2.53.0
+
--- /dev/null
+From 605e085e6ac8e03d20477967aa71ef6de9c09ac9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Mar 2026 12:06:35 +0000
+Subject: drm/amd/display: Do not skip unrelated mode changes in DSC validation
+
+From: Yussuf Khalil <dev@pp3345.net>
+
+[ Upstream commit aed3d041ab061ec8a64f50a3edda0f4db7280025 ]
+
+Starting with commit 17ce8a6907f7 ("drm/amd/display: Add dsc pre-validation in
+atomic check"), amdgpu resets the CRTC state mode_changed flag to false when
+recomputing the DSC configuration results in no timing change for a particular
+stream.
+
+However, this is incorrect in scenarios where a change in MST/DSC configuration
+happens in the same KMS commit as another (unrelated) mode change. For example,
+the integrated panel of a laptop may be configured differently (e.g., HDR
+enabled/disabled) depending on whether external screens are attached. In this
+case, plugging in external DP-MST screens may result in the mode_changed flag
+being dropped incorrectly for the integrated panel if its DSC configuration
+did not change during precomputation in pre_validate_dsc().
+
+At this point, however, dm_update_crtc_state() has already created new streams
+for CRTCs with DSC-independent mode changes. In turn,
+amdgpu_dm_commit_streams() will never release the old stream, resulting in a
+memory leak. amdgpu_dm_atomic_commit_tail() will never acquire a reference to
+the new stream either, which manifests as a use-after-free when the stream gets
+disabled later on:
+
+BUG: KASAN: use-after-free in dc_stream_release+0x25/0x90 [amdgpu]
+Write of size 4 at addr ffff88813d836524 by task kworker/9:9/29977
+
+Workqueue: events drm_mode_rmfb_work_fn
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x6e/0xa0
+ print_address_description.constprop.0+0x88/0x320
+ ? dc_stream_release+0x25/0x90 [amdgpu]
+ print_report+0xfc/0x1ff
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? __virt_addr_valid+0x225/0x4e0
+ ? dc_stream_release+0x25/0x90 [amdgpu]
+ kasan_report+0xe1/0x180
+ ? dc_stream_release+0x25/0x90 [amdgpu]
+ kasan_check_range+0x125/0x200
+ dc_stream_release+0x25/0x90 [amdgpu]
+ dc_state_destruct+0x14d/0x5c0 [amdgpu]
+ dc_state_release.part.0+0x4e/0x130 [amdgpu]
+ dm_atomic_destroy_state+0x3f/0x70 [amdgpu]
+ drm_atomic_state_default_clear+0x8ee/0xf30
+ ? drm_mode_object_put.part.0+0xb1/0x130
+ __drm_atomic_state_free+0x15c/0x2d0
+ atomic_remove_fb+0x67e/0x980
+
+Since there is no reliable way of figuring out whether a CRTC has unrelated
+mode changes pending at the time of DSC validation, remember the value of the
+mode_changed flag from before the point where a CRTC was marked as potentially
+affected by a change in DSC configuration. Reset the mode_changed flag to this
+earlier value instead in pre_validate_dsc().
+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/5004
+Fixes: 17ce8a6907f7 ("drm/amd/display: Add dsc pre-validation in atomic check")
+Signed-off-by: Yussuf Khalil <dev@pp3345.net>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit cc7c7121ae082b7b82891baa7280f1ff2608f22b)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 +
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +++-
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index e092d2372a4e6..1ed631006e63f 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -11722,6 +11722,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
+ }
+
+ if (dc_resource_is_dsc_encoding_supported(dc)) {
++ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
++ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
++ dm_new_crtc_state->mode_changed_independent_from_dsc = new_crtc_state->mode_changed;
++ }
++
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+ if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
+ ret = add_affected_mst_dsc_crtcs(state, crtc);
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+index 2c0e1180706fa..9682c190e9524 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+@@ -881,6 +881,7 @@ struct dm_crtc_state {
+
+ bool freesync_vrr_info_changed;
+
++ bool mode_changed_independent_from_dsc;
+ bool dsc_force_changed;
+ bool vrr_supported;
+ struct mod_freesync_config freesync_config;
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+index a2a70c1e9afdc..9a3deb26149d8 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -1703,9 +1703,11 @@ int pre_validate_dsc(struct drm_atomic_state *state,
+ int ind = find_crtc_index_in_state_by_stream(state, stream);
+
+ if (ind >= 0) {
++ struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(state->crtcs[ind].new_state);
++
+ DRM_INFO_ONCE("%s:%d MST_DSC no mode changed for stream 0x%p\n",
+ __func__, __LINE__, stream);
+- state->crtcs[ind].new_state->mode_changed = 0;
++ dm_new_crtc_state->base.mode_changed = dm_new_crtc_state->mode_changed_independent_from_dsc;
+ }
+ }
+ }
+--
+2.53.0
+
--- /dev/null
+From 265e96670e47050cae6d28655c4dcc2d0c44f7b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Mar 2026 13:41:18 +0530
+Subject: drm/amdgpu: Fix fence put before wait in amdgpu_amdkfd_submit_ib
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 7150850146ebfa4ca998f653f264b8df6f7f85be ]
+
+amdgpu_amdkfd_submit_ib() submits a GPU job and gets a fence
+from amdgpu_ib_schedule(). This fence is used to wait for job
+completion.
+
+Currently, the code drops the fence reference using dma_fence_put()
+before calling dma_fence_wait().
+
+If dma_fence_put() releases the last reference, the fence may be
+freed before dma_fence_wait() is called. This can lead to a
+use-after-free.
+
+Fix this by waiting on the fence first and releasing the reference
+only after dma_fence_wait() completes.
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c:697 amdgpu_amdkfd_submit_ib() warn: passing freed memory 'f' (line 696)
+
+Fixes: 9ae55f030dc5 ("drm/amdgpu: Follow up change to previous drm scheduler change.")
+Cc: Felix Kuehling <Felix.Kuehling@amd.com>
+Cc: Dan Carpenter <dan.carpenter@linaro.org>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+index 84e5364d1f67d..a872da6324865 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -702,9 +702,9 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
+ goto err_ib_sched;
+ }
+
+- /* Drop the initial kref_init count (see drm_sched_main as example) */
+- dma_fence_put(f);
+ ret = dma_fence_wait(f, false);
++ /* Drop the returned fence reference after the wait completes */
++ dma_fence_put(f);
+
+ err_ib_sched:
+ amdgpu_job_free(job);
+--
+2.53.0
+
--- /dev/null
+From 1889b919dc635c145af349cf26b7907e7892663e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 16:19:19 -0700
+Subject: drm/i915/gmbus: fix spurious timeout on 512-byte burst reads
+
+From: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+
+[ Upstream commit 08441f10f4dc09fdeb64529953ac308abc79dd38 ]
+
+When reading exactly 512 bytes with burst read enabled, the
+extra_byte_added path breaks out of the inner do-while without
+decrementing len. The outer while(len) then re-enters and gmbus_wait()
+times out since all data has been delivered. Decrement len before the
+break so the outer loop terminates correctly.
+
+Fixes: d5dc0f43f268 ("drm/i915/gmbus: Enable burst read")
+Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_gmbus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
+index 6470f75106bd4..88b37deb5c82a 100644
+--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
++++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
+@@ -460,8 +460,10 @@ gmbus_xfer_read_chunk(struct drm_i915_private *i915,
+
+ val = intel_de_read_fw(i915, GMBUS3(i915));
+ do {
+- if (extra_byte_added && len == 1)
++ if (extra_byte_added && len == 1) {
++ len--;
+ break;
++ }
+
+ *buf++ = val & 0xff;
+ val >>= 8;
+--
+2.53.0
+
--- /dev/null
+From e4a9a151305f82ad8d8483c60f3736b2315faabd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 05:13:06 +0000
+Subject: hwmon: (adm1177) fix sysfs ABI violation and current unit conversion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sanman Pradhan <psanman@juniper.net>
+
+[ Upstream commit bf08749a6abb6d1959bfdc0edc32c640df407558 ]
+
+The adm1177 driver exposes the current alert threshold through
+hwmon_curr_max_alarm. This violates the hwmon sysfs ABI, where
+*_alarm attributes are read-only status flags and writable thresholds
+must use currN_max.
+
+The driver also stores the threshold internally in microamps, while
+currN_max is defined in milliamps. Convert the threshold accordingly
+on both the read and write paths.
+
+Widen the cached threshold and related calculations to 64 bits so
+that small shunt resistor values do not cause truncation or overflow.
+Also use 64-bit arithmetic for the mA/uA conversions, clamp writes
+to the range the hardware can represent, and propagate failures from
+adm1177_write_alert_thr() instead of silently ignoring them.
+
+Update the hwmon documentation to reflect the attribute rename and
+the correct units returned by the driver.
+
+Fixes: 09b08ac9e8d5 ("hwmon: (adm1177) Add ADM1177 Hot Swap Controller and Digital Power Monitor driver")
+Signed-off-by: Sanman Pradhan <psanman@juniper.net>
+Acked-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/adm1177.rst | 8 ++---
+ drivers/hwmon/adm1177.c | 54 +++++++++++++++++++--------------
+ 2 files changed, 35 insertions(+), 27 deletions(-)
+
+diff --git a/Documentation/hwmon/adm1177.rst b/Documentation/hwmon/adm1177.rst
+index 1c85a2af92bf7..375f6d6e03a7d 100644
+--- a/Documentation/hwmon/adm1177.rst
++++ b/Documentation/hwmon/adm1177.rst
+@@ -27,10 +27,10 @@ for details.
+ Sysfs entries
+ -------------
+
+-The following attributes are supported. Current maxim attribute
++The following attributes are supported. Current maximum attribute
+ is read-write, all other attributes are read-only.
+
+-in0_input Measured voltage in microvolts.
++in0_input Measured voltage in millivolts.
+
+-curr1_input Measured current in microamperes.
+-curr1_max_alarm Overcurrent alarm in microamperes.
++curr1_input Measured current in milliamperes.
++curr1_max Overcurrent shutdown threshold in milliamperes.
+diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c
+index 8b2c965480e3f..7888afe8dafd6 100644
+--- a/drivers/hwmon/adm1177.c
++++ b/drivers/hwmon/adm1177.c
+@@ -10,6 +10,8 @@
+ #include <linux/hwmon.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
++#include <linux/math64.h>
++#include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/regulator/consumer.h>
+
+@@ -33,7 +35,7 @@
+ struct adm1177_state {
+ struct i2c_client *client;
+ u32 r_sense_uohm;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
+ bool vrange_high;
+ };
+
+@@ -48,7 +50,7 @@ static int adm1177_write_cmd(struct adm1177_state *st, u8 cmd)
+ }
+
+ static int adm1177_write_alert_thr(struct adm1177_state *st,
+- u32 alert_threshold_ua)
++ u64 alert_threshold_ua)
+ {
+ u64 val;
+ int ret;
+@@ -91,8 +93,8 @@ static int adm1177_read(struct device *dev, enum hwmon_sensor_types type,
+ *val = div_u64((105840000ull * dummy),
+ 4096 * st->r_sense_uohm);
+ return 0;
+- case hwmon_curr_max_alarm:
+- *val = st->alert_threshold_ua;
++ case hwmon_curr_max:
++ *val = div_u64(st->alert_threshold_ua, 1000);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+@@ -126,9 +128,10 @@ static int adm1177_write(struct device *dev, enum hwmon_sensor_types type,
+ switch (type) {
+ case hwmon_curr:
+ switch (attr) {
+- case hwmon_curr_max_alarm:
+- adm1177_write_alert_thr(st, val);
+- return 0;
++ case hwmon_curr_max:
++ val = clamp_val(val, 0,
++ div_u64(105840000ULL, st->r_sense_uohm));
++ return adm1177_write_alert_thr(st, (u64)val * 1000);
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -156,7 +159,7 @@ static umode_t adm1177_is_visible(const void *data,
+ if (st->r_sense_uohm)
+ return 0444;
+ return 0;
+- case hwmon_curr_max_alarm:
++ case hwmon_curr_max:
+ if (st->r_sense_uohm)
+ return 0644;
+ return 0;
+@@ -170,7 +173,7 @@ static umode_t adm1177_is_visible(const void *data,
+
+ static const struct hwmon_channel_info * const adm1177_info[] = {
+ HWMON_CHANNEL_INFO(curr,
+- HWMON_C_INPUT | HWMON_C_MAX_ALARM),
++ HWMON_C_INPUT | HWMON_C_MAX),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT),
+ NULL
+@@ -192,7 +195,8 @@ static int adm1177_probe(struct i2c_client *client)
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct adm1177_state *st;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
++ u32 prop;
+ int ret;
+
+ st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+@@ -208,22 +212,26 @@ static int adm1177_probe(struct i2c_client *client)
+ if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
+ &st->r_sense_uohm))
+ st->r_sense_uohm = 0;
+- if (device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
+- &alert_threshold_ua)) {
+- if (st->r_sense_uohm)
+- /*
+- * set maximum default value from datasheet based on
+- * shunt-resistor
+- */
+- alert_threshold_ua = div_u64(105840000000,
+- st->r_sense_uohm);
+- else
+- alert_threshold_ua = 0;
++ if (!device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
++ &prop)) {
++ alert_threshold_ua = prop;
++ } else if (st->r_sense_uohm) {
++ /*
++ * set maximum default value from datasheet based on
++ * shunt-resistor
++ */
++ alert_threshold_ua = div_u64(105840000000ULL,
++ st->r_sense_uohm);
++ } else {
++ alert_threshold_ua = 0;
+ }
+ st->vrange_high = device_property_read_bool(dev,
+ "adi,vrange-high-enable");
+- if (alert_threshold_ua && st->r_sense_uohm)
+- adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (alert_threshold_ua && st->r_sense_uohm) {
++ ret = adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (ret)
++ return ret;
++ }
+
+ ret = adm1177_write_cmd(st, ADM1177_CMD_V_CONT |
+ ADM1177_CMD_I_CONT |
+--
+2.53.0
+
--- /dev/null
+From b0b25faa40441fae5b32504ff3526de70ab8c0e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 2 Jul 2023 13:58:19 -0700
+Subject: hwmon: (pmbus/core) Fix various coding style issues
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 649b419f918fedf7213e590dba16e2fab5ea7259 ]
+
+Checkpatch reports bad multi-line comments, bad multi-line alignments,
+missing blank lines after variable declarations, unnecessary empty lines,
+unnecessary spaces, and unnecessary braces. Fix most of the reported
+problems except for some multi-line alignment problems.
+
+Reviewed-by: Tzung-Bi Shih <tzungbi@kernel.org>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Stable-dep-of: 805a5bd1c3f3 ("hwmon: (pmbus) Mark lowest/average/highest/rated attributes as read-only")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 41 +++++++++++++-------------------
+ 1 file changed, 17 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index a68b0a98e8d4d..a8ffafc7411e3 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -41,8 +41,7 @@ struct pmbus_sensor {
+ enum pmbus_sensor_classes class; /* sensor class */
+ bool update; /* runtime sensor update needed */
+ bool convert; /* Whether or not to apply linear/vid/direct */
+- int data; /* Sensor data.
+- Negative if there was a read error */
++ int data; /* Sensor data; negative if there was a read error */
+ };
+ #define to_pmbus_sensor(_attr) \
+ container_of(_attr, struct pmbus_sensor, attribute)
+@@ -189,11 +188,10 @@ static void pmbus_update_ts(struct i2c_client *client, bool write_op)
+ struct pmbus_data *data = i2c_get_clientdata(client);
+ const struct pmbus_driver_info *info = data->info;
+
+- if (info->access_delay) {
++ if (info->access_delay)
+ data->access_time = ktime_get();
+- } else if (info->write_delay && write_op) {
++ else if (info->write_delay && write_op)
+ data->write_time = ktime_get();
+- }
+ }
+
+ int pmbus_set_page(struct i2c_client *client, int page, int phase)
+@@ -289,7 +287,6 @@ int pmbus_write_word_data(struct i2c_client *client, int page, u8 reg,
+ }
+ EXPORT_SYMBOL_NS_GPL(pmbus_write_word_data, PMBUS);
+
+-
+ static int pmbus_write_virt_reg(struct i2c_client *client, int page, int reg,
+ u16 word)
+ {
+@@ -378,14 +375,14 @@ int pmbus_update_fan(struct i2c_client *client, int page, int id,
+ u8 to;
+
+ from = _pmbus_read_byte_data(client, page,
+- pmbus_fan_config_registers[id]);
++ pmbus_fan_config_registers[id]);
+ if (from < 0)
+ return from;
+
+ to = (from & ~mask) | (config & mask);
+ if (to != from) {
+ rv = _pmbus_write_byte_data(client, page,
+- pmbus_fan_config_registers[id], to);
++ pmbus_fan_config_registers[id], to);
+ if (rv < 0)
+ return rv;
+ }
+@@ -560,7 +557,7 @@ static int pmbus_get_fan_rate(struct i2c_client *client, int page, int id,
+ }
+
+ config = _pmbus_read_byte_data(client, page,
+- pmbus_fan_config_registers[id]);
++ pmbus_fan_config_registers[id]);
+ if (config < 0)
+ return config;
+
+@@ -785,7 +782,7 @@ static s64 pmbus_reg2data_linear(struct pmbus_data *data,
+
+ if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */
+ exponent = data->exponent[sensor->page];
+- mantissa = (u16) sensor->data;
++ mantissa = (u16)sensor->data;
+ } else { /* LINEAR11 */
+ exponent = ((s16)sensor->data) >> 11;
+ mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5;
+@@ -1170,7 +1167,6 @@ static int pmbus_get_boolean(struct i2c_client *client, struct pmbus_boolean *b,
+ } else {
+ pmbus_clear_fault_page(client, page);
+ }
+-
+ }
+ if (s1 && s2) {
+ s64 v1, v2;
+@@ -1497,8 +1493,7 @@ struct pmbus_limit_attr {
+ u16 reg; /* Limit register */
+ u16 sbit; /* Alarm attribute status bit */
+ bool update; /* True if register needs updates */
+- bool low; /* True if low limit; for limits with compare
+- functions only */
++ bool low; /* True if low limit; for limits with compare functions only */
+ const char *attr; /* Attribute name */
+ const char *alarm; /* Alarm attribute name */
+ };
+@@ -2209,8 +2204,8 @@ static const u32 pmbus_fan_status_flags[] = {
+
+ /* Precondition: FAN_CONFIG_x_y and FAN_COMMAND_x must exist for the fan ID */
+ static int pmbus_add_fan_ctrl(struct i2c_client *client,
+- struct pmbus_data *data, int index, int page, int id,
+- u8 config)
++ struct pmbus_data *data, int index, int page,
++ int id, u8 config)
+ {
+ struct pmbus_sensor *sensor;
+
+@@ -2222,7 +2217,7 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
+ return -ENOMEM;
+
+ if (!((data->info->func[page] & PMBUS_HAVE_PWM12) ||
+- (data->info->func[page] & PMBUS_HAVE_PWM34)))
++ (data->info->func[page] & PMBUS_HAVE_PWM34)))
+ return 0;
+
+ sensor = pmbus_add_sensor(data, "pwm", NULL, index, page,
+@@ -2888,7 +2883,7 @@ static void pmbus_notify(struct pmbus_data *data, int page, int reg, int flags)
+ }
+
+ static int _pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *flags,
+- unsigned int *event, bool notify)
++ unsigned int *event, bool notify)
+ {
+ int i, status;
+ const struct pmbus_status_category *cat;
+@@ -2917,7 +2912,6 @@ static int _pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *flag
+
+ if (notify && status)
+ pmbus_notify(data, page, cat->reg, status);
+-
+ }
+
+ /*
+@@ -2968,7 +2962,6 @@ static int _pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *flag
+ *event |= REGULATOR_EVENT_OVER_TEMP_WARN;
+ }
+
+-
+ return 0;
+ }
+
+@@ -3181,7 +3174,7 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
+ }
+
+ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
+- unsigned int selector)
++ unsigned int selector)
+ {
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
+@@ -3296,8 +3289,8 @@ static irqreturn_t pmbus_fault_handler(int irq, void *pdata)
+ {
+ struct pmbus_data *data = pdata;
+ struct i2c_client *client = to_i2c_client(data->dev);
+-
+ int i, status, event;
++
+ mutex_lock(&data->update_lock);
+ for (i = 0; i < data->info->pages; i++) {
+ _pmbus_get_flags(data, i, &status, &event, true);
+@@ -3405,7 +3398,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(pmbus_debugfs_ops_status, pmbus_debugfs_get_status,
+ NULL, "0x%04llx\n");
+
+ static ssize_t pmbus_debugfs_mfr_read(struct file *file, char __user *buf,
+- size_t count, loff_t *ppos)
++ size_t count, loff_t *ppos)
+ {
+ int rc;
+ struct pmbus_debugfs_entry *entry = file->private_data;
+@@ -3724,8 +3717,8 @@ int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info)
+
+ data->groups[0] = &data->group;
+ memcpy(data->groups + 1, info->groups, sizeof(void *) * groups_num);
+- data->hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+- name, data, data->groups);
++ data->hwmon_dev = devm_hwmon_device_register_with_groups(dev, name,
++ data, data->groups);
+ if (IS_ERR(data->hwmon_dev)) {
+ dev_err(dev, "Failed to register hwmon device\n");
+ return PTR_ERR(data->hwmon_dev);
+--
+2.53.0
+
--- /dev/null
+From ce2772f265a4e28525ac70e0b6c0c4cfdd24b69c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 18:54:11 -0700
+Subject: hwmon: (pmbus) Introduce the concept of "write-only" attributes
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit cd658475e7694d58e1c40dabc1dacf8431ccedb2 ]
+
+Attributes intended to clear sensor history are intended to be writeable
+only. Reading those attributes today results in reporting more or less
+random values. To avoid ABI surprises, have those attributes explicitly
+return 0 when reading.
+
+Fixes: 787c095edaa9d ("hwmon: (pmbus/core) Add support for rated attributes")
+Reviewed-by: Sanman Pradhan <psanman@juniper.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 32 ++++++++++++++++++++++++--------
+ 1 file changed, 24 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index f452876287556..41c66ece5177e 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -1205,6 +1205,12 @@ static ssize_t pmbus_show_boolean(struct device *dev,
+ return sysfs_emit(buf, "%d\n", val);
+ }
+
++static ssize_t pmbus_show_zero(struct device *dev,
++ struct device_attribute *devattr, char *buf)
++{
++ return sysfs_emit(buf, "0\n");
++}
++
+ static ssize_t pmbus_show_sensor(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+ {
+@@ -1403,7 +1409,7 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+ int reg,
+ enum pmbus_sensor_classes class,
+ bool update, bool readonly,
+- bool convert)
++ bool writeonly, bool convert)
+ {
+ struct pmbus_sensor *sensor;
+ struct device_attribute *a;
+@@ -1432,7 +1438,8 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+ sensor->data = -ENODATA;
+ pmbus_dev_attr_init(a, sensor->name,
+ readonly ? 0444 : 0644,
+- pmbus_show_sensor, pmbus_set_sensor);
++ writeonly ? pmbus_show_zero : pmbus_show_sensor,
++ pmbus_set_sensor);
+
+ if (pmbus_add_attribute(data, &a->attr))
+ return NULL;
+@@ -1493,6 +1500,7 @@ struct pmbus_limit_attr {
+ u16 reg; /* Limit register */
+ u16 sbit; /* Alarm attribute status bit */
+ bool readonly:1; /* True if the attribute is read-only */
++ bool writeonly:1; /* True if the attribute is write-only */
+ bool update:1; /* True if register needs updates */
+ bool low:1; /* True if low limit; for limits with compare functions only */
+ const char *attr; /* Attribute name */
+@@ -1542,7 +1550,7 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
+ curr = pmbus_add_sensor(data, name, l->attr, index,
+ page, 0xff, l->reg, attr->class,
+ attr->update || l->update,
+- l->readonly, true);
++ l->readonly, l->writeonly, true);
+ if (!curr)
+ return -ENOMEM;
+ if (l->sbit && (info->func[page] & attr->sfunc)) {
+@@ -1582,7 +1590,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
+ return ret;
+ }
+ base = pmbus_add_sensor(data, name, "input", index, page, phase,
+- attr->reg, attr->class, true, true, true);
++ attr->reg, attr->class, true, true, false, true);
+ if (!base)
+ return -ENOMEM;
+ /* No limit and alarm attributes for phase specific sensors */
+@@ -1719,6 +1727,7 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VIN_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VIN_MIN,
+@@ -1793,6 +1802,7 @@ static const struct pmbus_limit_attr vout_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VOUT_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VOUT_MIN,
+@@ -1874,6 +1884,7 @@ static const struct pmbus_limit_attr iin_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IIN_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IIN_MAX,
+@@ -1915,6 +1926,7 @@ static const struct pmbus_limit_attr iout_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IOUT_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IOUT_MAX,
+@@ -1973,6 +1985,7 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_PIN_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_PIN_MAX,
+@@ -2014,6 +2027,7 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_POUT_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_POUT_MAX,
+@@ -2085,6 +2099,7 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_1,
+@@ -2130,6 +2145,7 @@ static const struct pmbus_limit_attr temp_limit_attrs2[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_2,
+@@ -2247,7 +2263,7 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
+
+ sensor = pmbus_add_sensor(data, "fan", "target", index, page,
+ 0xff, PMBUS_VIRT_FAN_TARGET_1 + id, PSC_FAN,
+- false, false, true);
++ false, false, false, true);
+
+ if (!sensor)
+ return -ENOMEM;
+@@ -2258,14 +2274,14 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
+
+ sensor = pmbus_add_sensor(data, "pwm", NULL, index, page,
+ 0xff, PMBUS_VIRT_PWM_1 + id, PSC_PWM,
+- false, false, true);
++ false, false, false, true);
+
+ if (!sensor)
+ return -ENOMEM;
+
+ sensor = pmbus_add_sensor(data, "pwm", "enable", index, page,
+ 0xff, PMBUS_VIRT_PWM_ENABLE_1 + id, PSC_PWM,
+- true, false, false);
++ true, false, false, false);
+
+ if (!sensor)
+ return -ENOMEM;
+@@ -2307,7 +2323,7 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
+
+ if (pmbus_add_sensor(data, "fan", "input", index,
+ page, 0xff, pmbus_fan_registers[f],
+- PSC_FAN, true, true, true) == NULL)
++ PSC_FAN, true, true, false, true) == NULL)
+ return -ENOMEM;
+
+ /* Fan control */
+--
+2.53.0
+
--- /dev/null
+From 4b62e7f1cf803713e4bc1fc734444c550da0109f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 16:41:07 -0700
+Subject: hwmon: (pmbus) Mark lowest/average/highest/rated attributes as
+ read-only
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 805a5bd1c3f307d45ae4e9cf8915ef16d585a54a ]
+
+Writing those attributes is not supported, so mark them as read-only.
+
+Prior to this change, attempts to write into these attributes returned
+an error.
+
+Mark boolean fields in struct pmbus_limit_attr and in struct
+pmbus_sensor_attr as bit fields to reduce configuration data size.
+The data is scanned only while probing, so performance is not a concern.
+
+Fixes: 6f183d33a02e6 ("hwmon: (pmbus) Add support for peak attributes")
+Reviewed-by: Sanman Pradhan <psanman@juniper.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 48 ++++++++++++++++++++++++++++----
+ 1 file changed, 42 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index a8ffafc7411e3..f452876287556 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -1492,8 +1492,9 @@ static int pmbus_add_label(struct pmbus_data *data,
+ struct pmbus_limit_attr {
+ u16 reg; /* Limit register */
+ u16 sbit; /* Alarm attribute status bit */
+- bool update; /* True if register needs updates */
+- bool low; /* True if low limit; for limits with compare functions only */
++ bool readonly:1; /* True if the attribute is read-only */
++ bool update:1; /* True if register needs updates */
++ bool low:1; /* True if low limit; for limits with compare functions only */
+ const char *attr; /* Attribute name */
+ const char *alarm; /* Alarm attribute name */
+ };
+@@ -1508,9 +1509,9 @@ struct pmbus_sensor_attr {
+ u8 nlimit; /* # of limit registers */
+ enum pmbus_sensor_classes class;/* sensor class */
+ const char *label; /* sensor label */
+- bool paged; /* true if paged sensor */
+- bool update; /* true if update needed */
+- bool compare; /* true if compare function needed */
++ bool paged:1; /* true if paged sensor */
++ bool update:1; /* true if update needed */
++ bool compare:1; /* true if compare function needed */
+ u32 func; /* sensor mask */
+ u32 sfunc; /* sensor status mask */
+ int sreg; /* status register */
+@@ -1541,7 +1542,7 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
+ curr = pmbus_add_sensor(data, name, l->attr, index,
+ page, 0xff, l->reg, attr->class,
+ attr->update || l->update,
+- false, true);
++ l->readonly, true);
+ if (!curr)
+ return -ENOMEM;
+ if (l->sbit && (info->func[page] & attr->sfunc)) {
+@@ -1704,23 +1705,28 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_VIN_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_VIN_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_VIN_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VIN_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VIN_MIN,
++ .readonly = true,
+ .attr = "rated_min",
+ }, {
+ .reg = PMBUS_MFR_VIN_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1773,23 +1779,28 @@ static const struct pmbus_limit_attr vout_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_VOUT_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_VOUT_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_VOUT_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VOUT_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VOUT_MIN,
++ .readonly = true,
+ .attr = "rated_min",
+ }, {
+ .reg = PMBUS_MFR_VOUT_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1849,20 +1860,24 @@ static const struct pmbus_limit_attr iin_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_IIN_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_IIN_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_IIN_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IIN_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IIN_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1886,20 +1901,24 @@ static const struct pmbus_limit_attr iout_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_IOUT_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_IOUT_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_IOUT_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IOUT_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IOUT_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1940,20 +1959,24 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_PIN_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_PIN_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "input_lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_PIN_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_PIN_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_PIN_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1977,20 +2000,24 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_POUT_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_POUT_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "input_lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_POUT_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_POUT_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_POUT_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -2046,18 +2073,22 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = {
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP_MIN,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP_AVG,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP_MAX,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_1,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -2087,18 +2118,22 @@ static const struct pmbus_limit_attr temp_limit_attrs2[] = {
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_MIN,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_AVG,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_MAX,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_2,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -2128,6 +2163,7 @@ static const struct pmbus_limit_attr temp_limit_attrs3[] = {
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_3,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From b6c90c1327c5d2e89ea17aeda194fbc919ce3ecc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Mar 2026 18:39:41 +0100
+Subject: PM: hibernate: Drain trailing zero pages on userspace restore
+
+From: Alberto Garcia <berto@igalia.com>
+
+[ Upstream commit 734eba62cd32cb9ceffa09e57cdc03d761528525 ]
+
+Commit 005e8dddd497 ("PM: hibernate: don't store zero pages in the
+image file") added an optimization to skip zero-filled pages in the
+hibernation image. On restore, zero pages are handled internally by
+snapshot_write_next() in a loop that processes them without returning
+to the caller.
+
+With the userspace restore interface, writing the last non-zero page
+to /dev/snapshot is followed by the SNAPSHOT_ATOMIC_RESTORE ioctl. At
+this point there are no more calls to snapshot_write_next() so any
+trailing zero pages are not processed, snapshot_image_loaded() fails
+because handle->cur is smaller than expected, the ioctl returns -EPERM
+and the image is not restored.
+
+The in-kernel restore path is not affected by this because the loop in
+load_image() in swap.c calls snapshot_write_next() until it returns 0.
+It is this final call that drains any trailing zero pages.
+
+Fixed by calling snapshot_write_next() in snapshot_write_finalize(),
+giving the kernel the chance to drain any trailing zero pages.
+
+Fixes: 005e8dddd497 ("PM: hibernate: don't store zero pages in the image file")
+Signed-off-by: Alberto Garcia <berto@igalia.com>
+Acked-by: Brian Geffon <bgeffon@google.com>
+Link: https://patch.msgid.link/ef5a7c5e3e3dbd17dcb20efaa0c53a47a23498bb.1773075892.git.berto@igalia.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/snapshot.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
+index 30894d8f0a781..c56b08121dbc5 100644
+--- a/kernel/power/snapshot.c
++++ b/kernel/power/snapshot.c
+@@ -2861,6 +2861,17 @@ int snapshot_write_finalize(struct snapshot_handle *handle)
+ {
+ int error;
+
++ /*
++ * Call snapshot_write_next() to drain any trailing zero pages,
++ * but make sure we're in the data page region first.
++ * This function can return PAGE_SIZE if the kernel was expecting
++ * another copy page. Return -ENODATA in that situation.
++ */
++ if (handle->cur > nr_meta_pages + 1) {
++ error = snapshot_write_next(handle);
++ if (error)
++ return error > 0 ? -ENODATA : error;
++ }
+ copy_last_highmem_page();
+ error = hibernate_restore_protect_page(handle->buffer);
+ /* Do that only if we have loaded the image entirely */
+--
+2.53.0
+
--- /dev/null
+From 4baf70c60ea7d85e83e89eec647830f14891ba4b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:43 -0500
+Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node
+
+From: Ivan Barrera <ivan.d.barrera@intel.com>
+
+[ Upstream commit b415399c9a024d574b65479636f0d4eb625b9abd ]
+
+The cm_node is available and the usage of cm_node and event->cm_node
+seems arbitrary. Clean up unnecessary dereference of event->cm_node.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Ivan Barrera <ivan.d.barrera@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index 7b9cba80a7f74..e7f315e102d51 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -4238,21 +4238,21 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ irdma_cm_event_reset(event);
+ break;
+ case IRDMA_CM_EVENT_CONNECTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state != IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state != IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_cm_event_connected(event);
+ break;
+ case IRDMA_CM_EVENT_MPA_REJECT:
+- if (!event->cm_node->cm_id ||
++ if (!cm_node->cm_id ||
+ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_send_cm_event(cm_node, cm_node->cm_id,
+ IW_CM_EVENT_CONNECT_REPLY, -ECONNREFUSED);
+ break;
+ case IRDMA_CM_EVENT_ABORTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state == IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_event_connect_error(event);
+ break;
+@@ -4262,7 +4262,7 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ break;
+ }
+
+- irdma_rem_ref_cm_node(event->cm_node);
++ irdma_rem_ref_cm_node(cm_node);
+ kfree(event);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From cdae41813cb0aed7ef974e925dc951279e3ef76f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:45 -0500
+Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections
+
+From: Anil Samal <anil.samal@intel.com>
+
+[ Upstream commit 6f52370970ac07d352a7af4089e55e0e6425f827 ]
+
+Resolve deadlock that occurs when user executes netdev reset while RDMA
+applications (e.g., rping) are active. The netdev reset causes ice
+driver to remove irdma auxiliary driver, triggering device_delete and
+subsequent client removal. During client removal, uverbs_client waits
+for QP reference count to reach zero while cma_client holds the final
+reference, creating circular dependency and indefinite wait in iWARP
+mode. Skip QP reference count wait during device reset to prevent
+deadlock.
+
+Fixes: c8f304d75f6c ("RDMA/irdma: Prevent QP use after free")
+Signed-off-by: Anil Samal <anil.samal@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 5db64fae45515..1f267dea6460e 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -536,7 +536,8 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+ }
+
+ irdma_qp_rem_ref(&iwqp->ibqp);
+- wait_for_completion(&iwqp->free_qp);
++ if (!iwdev->rf->reset)
++ wait_for_completion(&iwqp->free_qp);
+ irdma_free_lsmm_rsrc(iwqp);
+ irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
+
+--
+2.53.0
+
--- /dev/null
+From 2e2938b392ae4c23dadcf15a2cbdc6cb2fce73ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:38 -0500
+Subject: RDMA/irdma: Initialize free_qp completion before using it
+
+From: Jacob Moroni <jmoroni@google.com>
+
+[ Upstream commit 11a95521fb93c91e2d4ef9d53dc80ef0a755549b ]
+
+In irdma_create_qp, if ib_copy_to_udata fails, it will call
+irdma_destroy_qp to clean up which will attempt to wait on
+the free_qp completion, which is not initialized yet. Fix this
+by initializing the completion before the ib_copy_to_udata call.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Jacob Moroni <jmoroni@google.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index ac01b6c10327e..7514c5e54e026 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1008,6 +1008,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ spin_lock_init(&iwqp->sc_qp.pfpdu.lock);
+ iwqp->sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
+ rf->qp_table[qp_num] = iwqp;
++ init_completion(&iwqp->free_qp);
+
+ if (rdma_protocol_roce(&iwdev->ibdev, 1)) {
+ if (dev->ws_add(&iwdev->vsi, 0)) {
+@@ -1042,7 +1043,6 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ }
+ }
+
+- init_completion(&iwqp->free_qp);
+ return 0;
+
+ error:
+--
+2.53.0
+
--- /dev/null
+From 9722774586d7facd5d1c19b7d3b39d2c9b0fa517 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:42 -0500
+Subject: RDMA/irdma: Remove a NOP wait_event() in irdma_modify_qp_roce()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 5e8f0239731a83753473b7aa91bda67bbdff5053 ]
+
+Remove a NOP wait_event() in irdma_modify_qp_roce() which is relevant
+for iWARP and likely a copy and paste artifact for RoCEv2. The wait event
+is for sending a reset on a TCP connection, after the reset has been
+requested in irdma_modify_qp(), which occurs only in iWarp mode.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 90d2c36928c1e..5db64fae45515 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1364,8 +1364,6 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ roce_info->rd_en = true;
+ }
+
+- wait_event(iwqp->mod_qp_waitq, !atomic_read(&iwqp->hw_mod_qp_pend));
+-
+ ibdev_dbg(&iwdev->ibdev,
+ "VERBS: caller: %pS qp_id=%d to_ibqpstate=%d ibqpstate=%d irdma_qpstate=%d attr_mask=0x%x\n",
+ __builtin_return_address(0), ibqp->qp_num, attr->qp_state,
+--
+2.53.0
+
--- /dev/null
+From 9cc253528fef3f2389d1270b16bb78e54cdaa13e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:44 -0500
+Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit c45c6ebd693b944f1ffe429fdfb6cc1674c237be ]
+
+During reset, irdma_modify_qp() to error should be called to disconnect
+the QP. Without this fix, if not preceded by irdma_modify_qp() to error, the
+API call irdma_destroy_qp() gets stuck waiting for the QP refcount to go
+to zero, because the cm_node associated with this QP isn't disconnected.
+
+Fixes: 915cc7ac0f8e ("RDMA/irdma: Add miscellaneous utility definitions")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/utils.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
+index 87a6d58663ded..a88f93b961682 100644
+--- a/drivers/infiniband/hw/irdma/utils.c
++++ b/drivers/infiniband/hw/irdma/utils.c
+@@ -2340,8 +2340,6 @@ void irdma_modify_qp_to_err(struct irdma_sc_qp *sc_qp)
+ struct irdma_qp *qp = sc_qp->qp_uk.back_qp;
+ struct ib_qp_attr attr;
+
+- if (qp->iwdev->rf->reset)
+- return;
+ attr.qp_state = IB_QPS_ERR;
+
+ if (rdma_protocol_roce(qp->ibqp.device, 1))
+--
+2.53.0
+
--- /dev/null
+From 63f7bb8d63f50466922d6557ad28822eb991310e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:46 -0500
+Subject: RDMA/irdma: Return EINVAL for invalid arp index error
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 7221f581eefa79ead06e171044f393fb7ee22f87 ]
+
+When rdma_connect() fails due to an invalid arp index, user space rdma core
+reports ENOMEM which is confusing. Modify irdma_make_cm_node() to return the
+correct error code.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index e7f315e102d51..6a911f6230648 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -2240,11 +2240,12 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ int oldarpindex;
+ int arpindex;
+ struct net_device *netdev = iwdev->netdev;
++ int ret;
+
+ /* create an hte and cm_node for this instance */
+ cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
+ if (!cm_node)
+- return NULL;
++ return ERR_PTR(-ENOMEM);
+
+ /* set our node specific transport info */
+ cm_node->ipv4 = cm_info->ipv4;
+@@ -2347,8 +2348,10 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ arpindex = -EINVAL;
+ }
+
+- if (arpindex < 0)
++ if (arpindex < 0) {
++ ret = -EINVAL;
+ goto err;
++ }
+
+ ether_addr_copy(cm_node->rem_mac,
+ iwdev->rf->arp_table[arpindex].mac_addr);
+@@ -2359,7 +2362,7 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ err:
+ kfree(cm_node);
+
+- return NULL;
++ return ERR_PTR(ret);
+ }
+
+ static void irdma_destroy_connection(struct irdma_cm_node *cm_node)
+@@ -3020,8 +3023,8 @@ static int irdma_create_cm_node(struct irdma_cm_core *cm_core,
+
+ /* create a CM connection node */
+ cm_node = irdma_make_cm_node(cm_core, iwdev, cm_info, NULL);
+- if (!cm_node)
+- return -ENOMEM;
++ if (IS_ERR(cm_node))
++ return PTR_ERR(cm_node);
+
+ /* set our node side to client (active) side */
+ cm_node->tcp_cntxt.client = 1;
+@@ -3218,9 +3221,9 @@ void irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf)
+ cm_info.cm_id = listener->cm_id;
+ cm_node = irdma_make_cm_node(cm_core, iwdev, &cm_info,
+ listener);
+- if (!cm_node) {
++ if (IS_ERR(cm_node)) {
+ ibdev_dbg(&cm_core->iwdev->ibdev,
+- "CM: allocate node failed\n");
++ "CM: allocate node failed ret=%ld\n", PTR_ERR(cm_node));
+ refcount_dec(&listener->refcnt);
+ return;
+ }
+--
+2.53.0
+
--- /dev/null
+From b035951106e0ea88aff51bf933915306b60c39b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:41 -0500
+Subject: RDMA/irdma: Update ibqp state to error if QP is already in error
+ state
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 8c1f19a2225cf37b3f8ab0b5a8a5322291cda620 ]
+
+In irdma_modify_qp() update ibqp state to error if the irdma QP is already
+in error state, otherwise the ibqp state which is visible to the consumer
+app remains stale.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 7514c5e54e026..90d2c36928c1e 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1442,6 +1442,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+@@ -1647,6 +1648,7 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+--
+2.53.0
+
--- /dev/null
+From 99d8efe1f4dd5e8355f0059802323733d09e0245 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Mar 2026 15:41:58 -0400
+Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 00da250c21b074ea9494c375d0117b69e5b1d0a4 ]
+
+When IOMMU passthrough mode is active, ib_dma_map_sgtable_attrs()
+produces no coalescing: each scatterlist page maps 1:1 to a DMA
+entry, so sgt.nents equals the raw page count. A 1 MB transfer
+yields 256 DMA entries. If that count exceeds the device's
+max_sgl_rd threshold (an optimization hint from mlx5 firmware),
+rdma_rw_io_needs_mr() steers the operation into the MR
+registration path. Each such operation consumes one or more MRs
+from a pool sized at max_rdma_ctxs -- roughly one MR per
+concurrent context. Under write-intensive workloads that issue
+many concurrent RDMA READs, the pool is rapidly exhausted,
+ib_mr_pool_get() returns NULL, and rdma_rw_init_one_mr() returns
+-EAGAIN. Upper layer protocols treat this as a fatal DMA mapping
+failure and tear down the connection.
+
+The max_sgl_rd check is a performance optimization, not a
+correctness requirement: the device can handle large SGE counts
+via direct posting, just less efficiently than with MR
+registration. When the MR pool cannot satisfy a request, falling
+back to the direct SGE (map_wrs) path avoids the connection
+reset while preserving the MR optimization for the common case
+where pool resources are available.
+
+Add a fallback in rdma_rw_ctx_init() so that -EAGAIN from
+rdma_rw_init_mr_wrs() triggers direct SGE posting instead of
+propagating the error. iWARP devices, which mandate MR
+registration for RDMA READs, and force_mr debug mode continue
+to treat -EAGAIN as terminal.
+
+Fixes: 00bd1439f464 ("RDMA/rw: Support threshold for registration vs scattering to local pages")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/rw.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
+index 2522ff1cc462c..49fbfe1cef689 100644
+--- a/drivers/infiniband/core/rw.c
++++ b/drivers/infiniband/core/rw.c
+@@ -326,14 +326,29 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u32 port_num,
+ if (rdma_rw_io_needs_mr(qp->device, port_num, dir, sg_cnt)) {
+ ret = rdma_rw_init_mr_wrs(ctx, qp, port_num, sg, sg_cnt,
+ sg_offset, remote_addr, rkey, dir);
+- } else if (sg_cnt > 1) {
++ /*
++ * If MR init succeeded or failed for a reason other
++ * than pool exhaustion, that result is final.
++ *
++ * Pool exhaustion (-EAGAIN) from the max_sgl_rd
++ * optimization is recoverable: fall back to
++ * direct SGE posting. iWARP and force_mr require
++ * MRs unconditionally, so -EAGAIN is terminal.
++ */
++ if (ret != -EAGAIN ||
++ rdma_protocol_iwarp(qp->device, port_num) ||
++ unlikely(rdma_rw_force_mr))
++ goto out;
++ }
++
++ if (sg_cnt > 1)
+ ret = rdma_rw_init_map_wrs(ctx, qp, sg, sg_cnt, sg_offset,
+ remote_addr, rkey, dir);
+- } else {
++ else
+ ret = rdma_rw_init_single_wr(ctx, qp, sg, sg_offset,
+ remote_addr, rkey, dir);
+- }
+
++out:
+ if (ret < 0)
+ goto out_unmap_sg;
+ return ret;
+--
+2.53.0
+
--- /dev/null
+From 4a572989472951d8875b9909a96609450cf6779f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Mar 2026 19:43:31 +0100
+Subject: regmap: Synchronize cache for the page selector
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 09e70e4f119ff650d24c96161fd2f62ac7e424b0 ]
+
+If the selector register is represented in each page, its value
+according to the debugfs is stale because it gets synchronized
+only after the real page switch happens. Hence the regmap cache
+initialisation from the HW inherits outdated data in the selector
+register.
+
+Synchronize cache for the page selector just in time.
+
+Before (offset followed by hexdump, the first byte is selector):
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 05 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 01 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 02 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 03 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 04 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+After:
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 01 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 02 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 03 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 04 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+Fixes: 6863ca622759 ("regmap: Add support for register indirect addressing.")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap.c | 30 ++++++++++++++++++++++++++----
+ 1 file changed, 26 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index 70cde1bd04000..3b2e27af91fe6 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -1544,6 +1544,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ unsigned int val_num)
+ {
+ void *orig_work_buf;
++ unsigned int selector_reg;
+ unsigned int win_offset;
+ unsigned int win_page;
+ bool page_chg;
+@@ -1562,10 +1563,31 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ return -EINVAL;
+ }
+
+- /* It is possible to have selector register inside data window.
+- In that case, selector register is located on every page and
+- it needs no page switching, when accessed alone. */
++ /*
++ * Calculate the address of the selector register in the corresponding
++ * data window if it is located on every page.
++ */
++ page_chg = in_range(range->selector_reg, range->window_start, range->window_len);
++ if (page_chg)
++ selector_reg = range->range_min + win_page * range->window_len +
++ range->selector_reg - range->window_start;
++
++ /*
++ * It is possible to have selector register inside data window.
++ * In that case, selector register is located on every page and it
++ * needs no page switching, when accessed alone.
++ *
++ * Nevertheless we should synchronize the cache values for it.
++ * This can't be properly achieved if the selector register is
++ * the first and the only one to be read inside the data window.
++ * That's why we update it in that case as well.
++ *
++ * However, we specifically avoid updating it for the default page,
++ * when it's overlapped with the real data window, to prevent from
++ * infinite looping.
++ */
+ if (val_num > 1 ||
++ (page_chg && selector_reg != range->selector_reg) ||
+ range->window_start + win_offset != range->selector_reg) {
+ /* Use separate work_buf during page switching */
+ orig_work_buf = map->work_buf;
+@@ -1574,7 +1596,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ ret = _regmap_update_bits(map, range->selector_reg,
+ range->selector_mask,
+ win_page << range->selector_shift,
+- &page_chg, false);
++ NULL, false);
+
+ map->work_buf = orig_work_buf;
+
+--
+2.53.0
+
--- /dev/null
+From 0b00eee8d0971f1f61c21011316b2fd055aafe36 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 14:31:47 +0800
+Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue
+
+From: Yihang Li <liyihang9@huawei.com>
+
+[ Upstream commit d71afa9deb4d413232ba16d693f7d43b321931b4 ]
+
+After commit 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard
+and multi-channel scans"), if the device supports multiple channels (0 to
+shost->max_channel), user_scan() invokes updated sas_user_scan() to perform
+the scan behavior for a specific transfer. However, when the user
+specifies shost->max_channel, it will return -EINVAL, which is not
+expected.
+
+Fix and support specifying the scan shost->max_channel for scanning.
+
+Fixes: 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans")
+Signed-off-by: Yihang Li <liyihang9@huawei.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_sas.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index d322802c7790f..f21d2be7ef1b6 100644
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -1732,7 +1732,7 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ break;
+
+ default:
+- if (channel < shost->max_channel) {
++ if (channel <= shost->max_channel) {
+ res = scsi_scan_host_selected(shost, channel, id, lun,
+ SCSI_SCAN_MANUAL);
+ } else {
+--
+2.53.0
+
netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch
netfilter-ctnetlink-use-netlink-policy-range-checks.patch
net-macb-use-the-current-queue-number-for-stats.patch
+regmap-synchronize-cache-for-the-page-selector.patch
+alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch
+rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch
+rdma-irdma-initialize-free_qp-completion-before-usin.patch
+rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch
+rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch
+rdma-irdma-clean-up-unnecessary-dereference-of-event.patch
+rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch
+rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch
+rdma-irdma-return-einval-for-invalid-arp-index-error.patch
+scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch
+x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch
+drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch
+pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch
+spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch
+asoc-intel-catpt-fix-the-device-initialization.patch
+spi-meson-spicc-fix-double-put-in-remove-path.patch
+drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch
+spi-group-cs-related-fields-in-struct-spi_device.patch
+spi-use-generic-driver_override-infrastructure.patch
+acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch
+drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch
+hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch
+hwmon-pmbus-core-fix-various-coding-style-issues.patch
+hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch
+hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch
+sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch
+asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch
+asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch
+spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch
--- /dev/null
+From f22e5052f17bc7a3aa9123911026719667187537 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Mar 2025 13:35:59 +0300
+Subject: spi: Group CS related fields in struct spi_device
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit dd8a9807fa03666bff52cb28472fb227eaac36c9 ]
+
+The CS related fields are sparse in the struct spi_device. Group them.
+While at it, fix the comment style of cs_index_mask.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20250331103609.4160281-1-andriy.shevchenko@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: cc34d77dd487 ("spi: use generic driver_override infrastructure")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/spi/spi.h | 37 +++++++++++++++++++++----------------
+ 1 file changed, 21 insertions(+), 16 deletions(-)
+
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index 71ad766932d31..825c41611852a 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -134,13 +134,6 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
+ * @max_speed_hz: Maximum clock rate to be used with this chip
+ * (on this board); may be changed by the device's driver.
+ * The spi_transfer.speed_hz can override this for each transfer.
+- * @chip_select: Array of physical chipselect, spi->chipselect[i] gives
+- * the corresponding physical CS for logical CS i.
+- * @mode: The spi mode defines how data is clocked out and in.
+- * This may be changed by the device's driver.
+- * The "active low" default for chipselect mode can be overridden
+- * (by specifying SPI_CS_HIGH) as can the "MSB first" default for
+- * each word in a transfer (by specifying SPI_LSB_FIRST).
+ * @bits_per_word: Data transfers involve one or more words; word sizes
+ * like eight or 12 bits are common. In-memory wordsizes are
+ * powers of two bytes (e.g. 20 bit samples use 32 bits).
+@@ -148,6 +141,11 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
+ * default (0) indicating protocol words are eight bit bytes.
+ * The spi_transfer.bits_per_word can override this for each transfer.
+ * @rt: Make the pump thread real time priority.
++ * @mode: The spi mode defines how data is clocked out and in.
++ * This may be changed by the device's driver.
++ * The "active low" default for chipselect mode can be overridden
++ * (by specifying SPI_CS_HIGH) as can the "MSB first" default for
++ * each word in a transfer (by specifying SPI_LSB_FIRST).
+ * @irq: Negative, or the number passed to request_irq() to receive
+ * interrupts from this device.
+ * @controller_state: Controller's runtime state
+@@ -160,8 +158,7 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
+ * the device will bind to the named driver and only the named driver.
+ * Do not set directly, because core frees it; use driver_set_override() to
+ * set or clear it.
+- * @cs_gpiod: Array of GPIO descriptors of the corresponding chipselect lines
+- * (optional, NULL when not using a GPIO line)
++ * @pcpu_statistics: statistics for the spi_device
+ * @word_delay: delay to be inserted between consecutive
+ * words of a transfer
+ * @cs_setup: delay to be introduced by the controller after CS is asserted
+@@ -169,8 +166,11 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
+ * @cs_inactive: delay to be introduced by the controller after CS is
+ * deasserted. If @cs_change_delay is used from @spi_transfer, then the
+ * two delays will be added up.
+- * @pcpu_statistics: statistics for the spi_device
++ * @chip_select: Array of physical chipselect, spi->chipselect[i] gives
++ * the corresponding physical CS for logical CS i.
+ * @cs_index_mask: Bit mask of the active chipselect(s) in the chipselect array
++ * @cs_gpiod: Array of GPIO descriptors of the corresponding chipselect lines
++ * (optional, NULL when not using a GPIO line)
+ *
+ * A @spi_device is used to interchange data between an SPI slave
+ * (usually a discrete chip) and CPU memory.
+@@ -185,7 +185,6 @@ struct spi_device {
+ struct device dev;
+ struct spi_controller *controller;
+ u32 max_speed_hz;
+- u8 chip_select[SPI_CS_CNT_MAX];
+ u8 bits_per_word;
+ bool rt;
+ #define SPI_NO_TX BIT(31) /* No transmit wire */
+@@ -216,23 +215,29 @@ struct spi_device {
+ void *controller_data;
+ char modalias[SPI_NAME_SIZE];
+ const char *driver_override;
+- struct gpio_desc *cs_gpiod[SPI_CS_CNT_MAX]; /* Chip select gpio desc */
++
++ /* The statistics */
++ struct spi_statistics __percpu *pcpu_statistics;
++
+ struct spi_delay word_delay; /* Inter-word delay */
++
+ /* CS delays */
+ struct spi_delay cs_setup;
+ struct spi_delay cs_hold;
+ struct spi_delay cs_inactive;
+
+- /* The statistics */
+- struct spi_statistics __percpu *pcpu_statistics;
++ u8 chip_select[SPI_CS_CNT_MAX];
+
+- /* Bit mask of the chipselect(s) that the driver need to use from
+- * the chipselect array.When the controller is capable to handle
++ /*
++ * Bit mask of the chipselect(s) that the driver need to use from
++ * the chipselect array. When the controller is capable to handle
+ * multiple chip selects & memories are connected in parallel
+ * then more than one bit need to be set in cs_index_mask.
+ */
+ u32 cs_index_mask : SPI_CS_CNT_MAX;
+
++ struct gpio_desc *cs_gpiod[SPI_CS_CNT_MAX]; /* Chip select gpio desc */
++
+ /*
+ * Likely need more hooks for more protocol options affecting how
+ * the controller talks to each chip, like:
+--
+2.53.0
+
--- /dev/null
+From c950fc52e229d9896d340bf5ad529edad5385cfd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Mar 2026 21:29:56 +0800
+Subject: spi: meson-spicc: Fix double-put in remove path
+
+From: Felix Gu <ustc.gu@gmail.com>
+
+[ Upstream commit 63542bb402b7013171c9f621c28b609eda4dbf1f ]
+
+meson_spicc_probe() registers the controller with
+devm_spi_register_controller(), so teardown already drops the
+controller reference via devm cleanup.
+
+Calling spi_controller_put() again in meson_spicc_remove()
+causes a double-put.
+
+Fixes: 8311ee2164c5 ("spi: meson-spicc: fix memory leak in meson_spicc_remove")
+Signed-off-by: Felix Gu <ustc.gu@gmail.com>
+Reviewed-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260322-rockchip-v1-1-fac3f0c6dad8@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-meson-spicc.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
+index 1d05590a74346..4ba95b148b1f6 100644
+--- a/drivers/spi/spi-meson-spicc.c
++++ b/drivers/spi/spi-meson-spicc.c
+@@ -903,8 +903,6 @@ static void meson_spicc_remove(struct platform_device *pdev)
+
+ /* Disable SPI */
+ writel(0, spicc->base + SPICC_CONREG);
+-
+- spi_controller_put(spicc->host);
+ }
+
+ static const struct meson_spicc_data meson_spicc_gx_data = {
+--
+2.53.0
+
--- /dev/null
+From aaf3f1fc9b2ac453ef44853984263e97152f4462 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 00:12:34 +0800
+Subject: spi: sn-f-ospi: Fix resource leak in f_ospi_probe()
+
+From: Felix Gu <ustc.gu@gmail.com>
+
+[ Upstream commit ef3d549e1deb3466c61f3b01d22fc3fe3e5efb08 ]
+
+In f_ospi_probe(), when num_cs validation fails, it returns without
+calling spi_controller_put() on the SPI controller, which causes a
+resource leak.
+
+Use devm_spi_alloc_host() instead of spi_alloc_host() to ensure the
+SPI controller is properly freed when probe fails.
+
+Fixes: 1b74dd64c861 ("spi: Add Socionext F_OSPI SPI flash controller driver")
+Signed-off-by: Felix Gu <ustc.gu@gmail.com>
+Link: https://patch.msgid.link/20260319-sn-f-v1-1-33a6738d2da8@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-sn-f-ospi.c | 17 +++++------------
+ 1 file changed, 5 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c
+index fd8c8eb37d01d..2d6d50b6f4dc9 100644
+--- a/drivers/spi/spi-sn-f-ospi.c
++++ b/drivers/spi/spi-sn-f-ospi.c
+@@ -609,7 +609,7 @@ static int f_ospi_probe(struct platform_device *pdev)
+ u32 num_cs = OSPI_NUM_CS;
+ int ret;
+
+- ctlr = spi_alloc_host(dev, sizeof(*ospi));
++ ctlr = devm_spi_alloc_host(dev, sizeof(*ospi));
+ if (!ctlr)
+ return -ENOMEM;
+
+@@ -632,16 +632,12 @@ static int f_ospi_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, ospi);
+
+ ospi->base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(ospi->base)) {
+- ret = PTR_ERR(ospi->base);
+- goto err_put_ctlr;
+- }
++ if (IS_ERR(ospi->base))
++ return PTR_ERR(ospi->base);
+
+ ospi->clk = devm_clk_get_enabled(dev, NULL);
+- if (IS_ERR(ospi->clk)) {
+- ret = PTR_ERR(ospi->clk);
+- goto err_put_ctlr;
+- }
++ if (IS_ERR(ospi->clk))
++ return PTR_ERR(ospi->clk);
+
+ mutex_init(&ospi->mlock);
+
+@@ -658,9 +654,6 @@ static int f_ospi_probe(struct platform_device *pdev)
+ err_destroy_mutex:
+ mutex_destroy(&ospi->mlock);
+
+-err_put_ctlr:
+- spi_controller_put(ctlr);
+-
+ return ret;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From c8640469087c067a79c9c256986ed55136771026 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 19:38:12 +0100
+Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF)
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b341c1176f2e001b3adf0b47154fc31589f7410e ]
+
+There is a teardown order issue in the driver. The SPI controller is
+registered using devm_spi_register_controller(), which delays
+unregistration of the SPI controller until after the fsl_lpspi_remove()
+function returns.
+
+As the fsl_lpspi_remove() function synchronously tears down the DMA
+channels, a running SPI transfer triggers the following NULL pointer
+dereference due to use after free:
+
+| fsl_lpspi 42550000.spi: I/O Error in DMA RX
+| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
+[...]
+| Call trace:
+| fsl_lpspi_dma_transfer+0x260/0x340 [spi_fsl_lpspi]
+| fsl_lpspi_transfer_one+0x198/0x448 [spi_fsl_lpspi]
+| spi_transfer_one_message+0x49c/0x7c8
+| __spi_pump_transfer_message+0x120/0x420
+| __spi_sync+0x2c4/0x520
+| spi_sync+0x34/0x60
+| spidev_message+0x20c/0x378 [spidev]
+| spidev_ioctl+0x398/0x750 [spidev]
+[...]
+
+Switch from devm_spi_register_controller() to spi_register_controller() in
+fsl_lpspi_probe() and add the corresponding spi_unregister_controller() in
+fsl_lpspi_remove().
+
+Fixes: 5314987de5e5 ("spi: imx: add lpspi bus driver")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-fsl-lpspi.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
+index 5e96913fd9466..8879baab1daf3 100644
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -954,7 +954,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+ enable_irq(irq);
+ }
+
+- ret = devm_spi_register_controller(&pdev->dev, controller);
++ ret = spi_register_controller(controller);
+ if (ret < 0) {
+ dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
+ goto free_dma;
+@@ -981,6 +981,7 @@ static void fsl_lpspi_remove(struct platform_device *pdev)
+ struct fsl_lpspi_data *fsl_lpspi =
+ spi_controller_get_devdata(controller);
+
++ spi_unregister_controller(controller);
+ fsl_lpspi_dma_exit(controller);
+
+ pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
+--
+2.53.0
+
--- /dev/null
+From 0ccdbeea9951b508e07673527b9523ba9fe26e79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 01:59:15 +0100
+Subject: spi: use generic driver_override infrastructure
+
+From: Danilo Krummrich <dakr@kernel.org>
+
+[ Upstream commit cc34d77dd48708d810c12bfd6f5bf03304f6c824 ]
+
+When a driver is probed through __driver_attach(), the bus' match()
+callback is called without the device lock held, thus accessing the
+driver_override field without a lock, which can cause a UAF.
+
+Fix this by using the driver-core driver_override infrastructure taking
+care of proper locking internally.
+
+Note that calling match() from __driver_attach() without the device lock
+held is intentional. [1]
+
+Also note that we do not enable the driver_override feature of struct
+bus_type, as SPI - in contrast to most other buses - passes "" to
+sysfs_emit() when the driver_override pointer is NULL. Thus, printing
+"\n" instead of "(null)\n".
+
+Link: https://lore.kernel.org/driver-core/DGRGTIRHA62X.3RY09D9SOK77P@kernel.org/ [1]
+Reported-by: Gui-Dong Han <hanguidong02@gmail.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789
+Fixes: 5039563e7c25 ("spi: Add driver_override SPI device attribute")
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Link: https://patch.msgid.link/20260324005919.2408620-12-dakr@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi.c | 19 +++++++------------
+ include/linux/spi/spi.h | 5 -----
+ 2 files changed, 7 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 7cf37e28e4859..0c3200d08fe46 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -49,7 +49,6 @@ static void spidev_release(struct device *dev)
+ struct spi_device *spi = to_spi_device(dev);
+
+ spi_controller_put(spi->controller);
+- kfree(spi->driver_override);
+ free_percpu(spi->pcpu_statistics);
+ kfree(spi);
+ }
+@@ -72,10 +71,9 @@ static ssize_t driver_override_store(struct device *dev,
+ struct device_attribute *a,
+ const char *buf, size_t count)
+ {
+- struct spi_device *spi = to_spi_device(dev);
+ int ret;
+
+- ret = driver_set_override(dev, &spi->driver_override, buf, count);
++ ret = __device_set_driver_override(dev, buf, count);
+ if (ret)
+ return ret;
+
+@@ -85,13 +83,8 @@ static ssize_t driver_override_store(struct device *dev,
+ static ssize_t driver_override_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+ {
+- const struct spi_device *spi = to_spi_device(dev);
+- ssize_t len;
+-
+- device_lock(dev);
+- len = sysfs_emit(buf, "%s\n", spi->driver_override ? : "");
+- device_unlock(dev);
+- return len;
++ guard(spinlock)(&dev->driver_override.lock);
++ return sysfs_emit(buf, "%s\n", dev->driver_override.name ?: "");
+ }
+ static DEVICE_ATTR_RW(driver_override);
+
+@@ -375,10 +368,12 @@ static int spi_match_device(struct device *dev, const struct device_driver *drv)
+ {
+ const struct spi_device *spi = to_spi_device(dev);
+ const struct spi_driver *sdrv = to_spi_driver(drv);
++ int ret;
+
+ /* Check override first, and if set, only use the named driver */
+- if (spi->driver_override)
+- return strcmp(spi->driver_override, drv->name) == 0;
++ ret = device_match_driver_override(dev, drv);
++ if (ret >= 0)
++ return ret;
+
+ /* Attempt an OF style match */
+ if (of_driver_match_device(dev, drv))
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index 825c41611852a..8f6280bd2bf06 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -154,10 +154,6 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
+ * @modalias: Name of the driver to use with this device, or an alias
+ * for that name. This appears in the sysfs "modalias" attribute
+ * for driver coldplugging, and in uevents used for hotplugging
+- * @driver_override: If the name of a driver is written to this attribute, then
+- * the device will bind to the named driver and only the named driver.
+- * Do not set directly, because core frees it; use driver_set_override() to
+- * set or clear it.
+ * @pcpu_statistics: statistics for the spi_device
+ * @word_delay: delay to be inserted between consecutive
+ * words of a transfer
+@@ -214,7 +210,6 @@ struct spi_device {
+ void *controller_state;
+ void *controller_data;
+ char modalias[SPI_NAME_SIZE];
+- const char *driver_override;
+
+ /* The statistics */
+ struct spi_statistics __percpu *pcpu_statistics;
+--
+2.53.0
+
--- /dev/null
+From 2c3edf95e5e64a24812d617e4ff55431856e51d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 23:29:50 +0100
+Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap
+
+From: Marc Buerg <buermarc@googlemail.com>
+
+[ Upstream commit f63a9df7e3f9f842945d292a19d9938924f066f9 ]
+
+proc_do_large_bitmap() does not initialize variable c, which is expected
+to be set to a trailing character by proc_get_long().
+
+However, proc_get_long() only sets c when the input buffer contains a
+trailing character after the parsed value.
+
+If c is not initialized it may happen to contain a '-'. If this is the
+case proc_do_large_bitmap() expects to be able to parse a second part of
+the input buffer. If there is no second part an unjustified -EINVAL will
+be returned.
+
+Initialize c to 0 to prevent returning -EINVAL on valid input.
+
+Fixes: 9f977fb7ae9d ("sysctl: add proc_do_large_bitmap")
+Signed-off-by: Marc Buerg <buermarc@googlemail.com>
+Reviewed-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sysctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 79e6cb1d5c48f..de58128fa5212 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1369,7 +1369,7 @@ int proc_do_large_bitmap(const struct ctl_table *table, int write,
+ unsigned long bitmap_len = table->maxlen;
+ unsigned long *bitmap = *(unsigned long **) table->data;
+ unsigned long *tmp_bitmap = NULL;
+- char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
++ char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c = 0;
+
+ if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
+ *lenp = 0;
+--
+2.53.0
+
--- /dev/null
+From 4b4696d9c4772de37fd74733c8afbafabd03f5c2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 15:59:48 +0200
+Subject: x86/efi: efi_unmap_boot_services: fix calculation of ranges_to_free
+ size
+
+From: Mike Rapoport (Microsoft) <rppt@kernel.org>
+
+[ Upstream commit 217c0a5c177a3d4f7c8497950cbf5c36756e8bbb ]
+
+ranges_to_free array should have enough room to store the entire EFI
+memmap plus an extra element for NULL entry.
+The calculation of this array size wrongly adds 1 to the overall size
+instead of adding 1 to the number of elements.
+
+Add parentheses to properly size the array.
+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory")
+Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/platform/efi/quirks.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
+index df3b45ef1420c..a29efaf6fe411 100644
+--- a/arch/x86/platform/efi/quirks.c
++++ b/arch/x86/platform/efi/quirks.c
+@@ -424,7 +424,7 @@ void __init efi_unmap_boot_services(void)
+ if (efi_enabled(EFI_DBG))
+ return;
+
+- sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;
++ sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1);
+ ranges_to_free = kzalloc(sz, GFP_KERNEL);
+ if (!ranges_to_free) {
+ pr_err("Failed to allocate storage for freeable EFI regions\n");
+--
+2.53.0
+
--- /dev/null
+From cd325b849d14cfb51d55a4d019a3c97bcfd09d5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 00:54:59 +0800
+Subject: ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f6484cadbcaf26b5844b51bd7307a663dda48ef6 ]
+
+When ec_install_handlers() returns -EPROBE_DEFER on reduced-hardware
+platforms, it has already started the EC and installed the address
+space handler with the struct acpi_ec pointer as handler context.
+However, acpi_ec_setup() propagates the error without any cleanup.
+
+The caller acpi_ec_add() then frees the struct acpi_ec for non-boot
+instances, leaving a dangling handler context in ACPICA.
+
+Any subsequent AML evaluation that accesses an EC OpRegion field
+dispatches into acpi_ec_space_handler() with the freed pointer,
+causing a use-after-free:
+
+ BUG: KASAN: slab-use-after-free in mutex_lock (kernel/locking/mutex.c:289)
+ Write of size 8 at addr ffff88800721de38 by task init/1
+ Call Trace:
+ <TASK>
+ mutex_lock (kernel/locking/mutex.c:289)
+ acpi_ec_space_handler (drivers/acpi/ec.c:1362)
+ acpi_ev_address_space_dispatch (drivers/acpi/acpica/evregion.c:293)
+ acpi_ex_access_region (drivers/acpi/acpica/exfldio.c:246)
+ acpi_ex_field_datum_io (drivers/acpi/acpica/exfldio.c:509)
+ acpi_ex_extract_from_field (drivers/acpi/acpica/exfldio.c:700)
+ acpi_ex_read_data_from_field (drivers/acpi/acpica/exfield.c:327)
+ acpi_ex_resolve_node_to_value (drivers/acpi/acpica/exresolv.c:392)
+ </TASK>
+
+ Allocated by task 1:
+ acpi_ec_alloc (drivers/acpi/ec.c:1424)
+ acpi_ec_add (drivers/acpi/ec.c:1692)
+
+ Freed by task 1:
+ kfree (mm/slub.c:6876)
+ acpi_ec_add (drivers/acpi/ec.c:1751)
+
+The bug triggers on reduced-hardware EC platforms (ec->gpe < 0)
+when the GPIO IRQ provider defers probing. Once the stale handler
+exists, any unprivileged sysfs read that causes AML to touch an
+EC OpRegion (battery, thermal, backlight) exercises the dangling
+pointer.
+
+Fix this by calling ec_remove_handlers() in the error path of
+acpi_ec_setup() before clearing first_ec. ec_remove_handlers()
+checks each EC_FLAGS_* bit before acting, so it is safe to call
+regardless of how far ec_install_handlers() progressed:
+
+ -ENODEV (handler not installed): only calls acpi_ec_stop()
+ -EPROBE_DEFER (handler installed): removes handler, stops EC
+
+Fixes: 03e9a0e05739 ("ACPI: EC: Consolidate event handler installation code")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 7855bbf752b1e..1f4fc78a124fa 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1655,6 +1655,8 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+
+ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret) {
++ ec_remove_handlers(ec);
++
+ if (ec == first_ec)
+ first_ec = NULL;
+
+--
+2.53.0
+
--- /dev/null
+From ecacecc011f244d416e4f1e83e4186ff38048a85 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 15 Mar 2026 20:11:27 +0000
+Subject: ALSA: hda/realtek: Sequence GPIO2 on Star Labs StarFighter
+
+From: Sean Rhodes <sean@starlabs.systems>
+
+[ Upstream commit a6919f2a01f8fbf807b015e5b26aecae7db8117b ]
+
+The initial StarFighter quirk fixed the runtime suspend pop by muting
+speakers in the shutup callback before power-down. Further hardware
+validation showed that the speaker path is controlled directly by LINE2
+EAPD on NID 0x1b together with GPIO2 for the external amplifier.
+
+Replace the shutup-delay workaround with explicit sequencing of those
+controls at playback start and stop:
+- assert LINE2 EAPD and drive GPIO2 high on PREPARE
+- deassert LINE2 EAPD and drive GPIO2 low on CLEANUP
+
+This avoids the runtime suspend pop without a sleep, and also fixes pops
+around G3 entry and display-manager start that the original workaround
+did not cover.
+
+Fixes: 1cb3c20688fc ("ALSA: hda/realtek: Fix speaker pop on Star Labs StarFighter")
+Tested-by: Sean Rhodes <sean@starlabs.systems>
+Signed-off-by: Sean Rhodes <sean@starlabs.systems>
+Link: https://patch.msgid.link/20260315201127.33744-1-sean@starlabs.systems
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/hda/codecs/realtek/alc269.c | 38 ++++++++++++++++++++++++++-----
+ 1 file changed, 32 insertions(+), 6 deletions(-)
+
+diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
+index 38fe144e6238a..b7d2c6f8f73ce 100644
+--- a/sound/hda/codecs/realtek/alc269.c
++++ b/sound/hda/codecs/realtek/alc269.c
+@@ -1017,12 +1017,30 @@ static int alc269_resume(struct hda_codec *codec)
+ return 0;
+ }
+
+-#define STARLABS_STARFIGHTER_SHUTUP_DELAY_MS 30
++#define ALC233_STARFIGHTER_SPK_PIN 0x1b
++#define ALC233_STARFIGHTER_GPIO2 0x04
+
+-static void starlabs_starfighter_shutup(struct hda_codec *codec)
++static void alc233_starfighter_update_amp(struct hda_codec *codec, bool on)
+ {
+- if (snd_hda_gen_shutup_speakers(codec))
+- msleep(STARLABS_STARFIGHTER_SHUTUP_DELAY_MS);
++ snd_hda_codec_write(codec, ALC233_STARFIGHTER_SPK_PIN, 0,
++ AC_VERB_SET_EAPD_BTLENABLE,
++ on ? AC_EAPDBTL_EAPD : 0);
++ alc_update_gpio_data(codec, ALC233_STARFIGHTER_GPIO2, on);
++}
++
++static void alc233_starfighter_pcm_hook(struct hda_pcm_stream *hinfo,
++ struct hda_codec *codec,
++ struct snd_pcm_substream *substream,
++ int action)
++{
++ switch (action) {
++ case HDA_GEN_PCM_ACT_PREPARE:
++ alc233_starfighter_update_amp(codec, true);
++ break;
++ case HDA_GEN_PCM_ACT_CLEANUP:
++ alc233_starfighter_update_amp(codec, false);
++ break;
++ }
+ }
+
+ static void alc233_fixup_starlabs_starfighter(struct hda_codec *codec,
+@@ -1031,8 +1049,16 @@ static void alc233_fixup_starlabs_starfighter(struct hda_codec *codec,
+ {
+ struct alc_spec *spec = codec->spec;
+
+- if (action == HDA_FIXUP_ACT_PRE_PROBE)
+- spec->shutup = starlabs_starfighter_shutup;
++ switch (action) {
++ case HDA_FIXUP_ACT_PRE_PROBE:
++ spec->gpio_mask |= ALC233_STARFIGHTER_GPIO2;
++ spec->gpio_dir |= ALC233_STARFIGHTER_GPIO2;
++ spec->gpio_data &= ~ALC233_STARFIGHTER_GPIO2;
++ break;
++ case HDA_FIXUP_ACT_PROBE:
++ spec->gen.pcm_playback_hook = alc233_starfighter_pcm_hook;
++ break;
++ }
+ }
+
+ static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec,
+--
+2.53.0
+
--- /dev/null
+From e5cdedec3d572ff8bde318b6f83d098c7a7615ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Mar 2026 06:02:30 +1030
+Subject: ALSA: usb-audio: Exclude Scarlett 2i2 1st Gen from SKIP_IFACE_SETUP
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit 8780f561f6717dec52351251881bff79e960eb46 ]
+
+The Focusrite Scarlett 2i2 1st Gen (1235:8006) produces
+distorted/silent audio when QUIRK_FLAG_SKIP_IFACE_SETUP is active, as
+that flag causes the feedback format to be detected as 17.15 instead
+of 16.16.
+
+Add a DEVICE_FLG entry for this device before the Focusrite VENDOR_FLG
+entry so that it gets no quirk flags, overriding the vendor-wide
+SKIP_IFACE_SETUP. This device doesn't have the internal mixer, Air, or
+Safe modes that the quirk was designed to protect.
+
+Fixes: 38c322068a26 ("ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP")
+Reported-by: pairomaniac [https://github.com/geoffreybennett/linux-fcp/issues/54]
+Tested-by: pairomaniac [https://github.com/geoffreybennett/linux-fcp/issues/54]
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://patch.msgid.link/abmsTjKmQMKbhYtK@m.b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index fd50bf7c381d6..11823549900f1 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2422,6 +2422,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY),
+ VENDOR_FLG(0x07fd, /* MOTU */
+ QUIRK_FLAG_VALIDATE_RATES),
++ DEVICE_FLG(0x1235, 0x8006, 0), /* Focusrite Scarlett 2i2 1st Gen */
+ VENDOR_FLG(0x1235, /* Focusrite Novation */
+ QUIRK_FLAG_SKIP_IFACE_SETUP),
+ VENDOR_FLG(0x1511, /* AURALiC */
+--
+2.53.0
+
--- /dev/null
+From 0831b12a1f08e5728a30e4ff060f268bb4685704 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Mar 2026 21:59:21 +1030
+Subject: ALSA: usb-audio: Exclude Scarlett 2i4 1st Gen from SKIP_IFACE_SETUP
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit 990a8b0732cf899d4a0f847b0a67efeb9a384c82 ]
+
+Same issue that the Scarlett 2i2 1st Gen had:
+QUIRK_FLAG_SKIP_IFACE_SETUP causes distorted/flanging audio on the
+Scarlett 2i4 1st Gen (1235:800a).
+
+Fixes: 38c322068a26 ("ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP")
+Reported-by: dcferreira [https://github.com/geoffreybennett/linux-fcp/issues/54]
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://patch.msgid.link/acEkEbftzyNe8W7C@m.b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 11823549900f1..45d0e1364dd98 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2423,6 +2423,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ VENDOR_FLG(0x07fd, /* MOTU */
+ QUIRK_FLAG_VALIDATE_RATES),
+ DEVICE_FLG(0x1235, 0x8006, 0), /* Focusrite Scarlett 2i2 1st Gen */
++ DEVICE_FLG(0x1235, 0x800a, 0), /* Focusrite Scarlett 2i4 1st Gen */
+ VENDOR_FLG(0x1235, /* Focusrite Novation */
+ QUIRK_FLAG_SKIP_IFACE_SETUP),
+ VENDOR_FLG(0x1511, /* AURALiC */
+--
+2.53.0
+
--- /dev/null
+From 86d1b03615aeb767e1b94ceaaee894f0d612ff11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:04 +0100
+Subject: ASoC: adau1372: Fix clock leak on PLL lock failure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit bfe6a264effcb6fe99ad7ceaf9e8c7439fc9555b ]
+
+adau1372_enable_pll() was a void function that logged a dev_err() on
+PLL lock timeout but did not propagate the error. As a result,
+adau1372_set_power() would continue with adau1372->enabled set to true
+despite the PLL being unlocked, and the mclk left enabled with no
+corresponding disable on the error path.
+
+Convert adau1372_enable_pll() to return int, using -ETIMEDOUT on lock
+timeout and propagating regmap errors directly. In adau1372_set_power(),
+check the return value and unwind in reverse order: restore regcache to
+cache-only mode, reassert GPIO power-down, and disable the clock before
+returning the error.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index 6345342218d61..d7363f9d53bb3 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -762,7 +762,7 @@ static int adau1372_startup(struct snd_pcm_substream *substream, struct snd_soc_
+ return 0;
+ }
+
+-static void adau1372_enable_pll(struct adau1372 *adau1372)
++static int adau1372_enable_pll(struct adau1372 *adau1372)
+ {
+ unsigned int val, timeout = 0;
+ int ret;
+@@ -778,8 +778,12 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ timeout++;
+ } while (!(val & 1) && timeout < 3);
+
+- if (ret < 0 || !(val & 1))
++ if (ret < 0 || !(val & 1)) {
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
++ return ret < 0 ? ret : -ETIMEDOUT;
++ }
++
++ return 0;
+ }
+
+ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+@@ -807,7 +811,14 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ * accessed.
+ */
+ if (adau1372->use_pll) {
+- adau1372_enable_pll(adau1372);
++ ret = adau1372_enable_pll(adau1372);
++ if (ret) {
++ regcache_cache_only(adau1372->regmap, true);
++ if (adau1372->pd_gpio)
++ gpiod_set_value(adau1372->pd_gpio, 1);
++ clk_disable_unprepare(adau1372->mclk);
++ return ret;
++ }
+ clk_ctrl |= ADAU1372_CLK_CTRL_CLKSRC;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 264939d4b099d0a0a5a00c3a5586b8af5b5f196d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:03 +0100
+Subject: ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit 326fe8104a4020d30080d37ac8b6b43893cdebca ]
+
+adau1372_set_power() calls clk_prepare_enable() but discards the return
+value. If the clock enable fails, the driver proceeds to access registers
+on unpowered hardware, potentially causing silent corruption.
+
+Make adau1372_set_power() return int and propagate the error from
+clk_prepare_enable(). Update adau1372_set_bias_level() to return the
+error directly for the STANDBY and OFF cases.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index fdee689cae538..6345342218d61 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -782,15 +782,18 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
+ }
+
+-static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
++static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ {
+ if (adau1372->enabled == enable)
+- return;
++ return 0;
+
+ if (enable) {
+ unsigned int clk_ctrl = ADAU1372_CLK_CTRL_MCLK_EN;
++ int ret;
+
+- clk_prepare_enable(adau1372->mclk);
++ ret = clk_prepare_enable(adau1372->mclk);
++ if (ret)
++ return ret;
+ if (adau1372->pd_gpio)
+ gpiod_set_value(adau1372->pd_gpio, 0);
+
+@@ -829,6 +832,8 @@ static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ }
+
+ adau1372->enabled = enable;
++
++ return 0;
+ }
+
+ static int adau1372_set_bias_level(struct snd_soc_component *component,
+@@ -842,11 +847,9 @@ static int adau1372_set_bias_level(struct snd_soc_component *component,
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+- adau1372_set_power(adau1372, true);
+- break;
++ return adau1372_set_power(adau1372, true);
+ case SND_SOC_BIAS_OFF:
+- adau1372_set_power(adau1372, false);
+- break;
++ return adau1372_set_power(adau1372, false);
+ }
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 8544864e447157ddfb8ae126c6fb4f9e05ee81d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 21 Mar 2026 02:20:11 +0100
+Subject: ASoC: dt-bindings: stm32: Fix incorrect compatible string in
+ stm32h7-sai match
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit 91049ec2e18376ec2192e73ef7be4c7110436350 ]
+
+The conditional block that defines clock constraints for the stm32h7-sai
+variant references "st,stm32mph7-sai", which does not match any compatible
+string in the enum. As a result, clock validation for the h7 variant is
+silently skipped. Correct the compatible string to "st,stm32h7-sai".
+
+Fixes: 8509bb1f11a1f ("ASoC: dt-bindings: add stm32mp25 support for sai")
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Reviewed-by: Olivier Moysan <olivier.moysan@foss.st.com>
+Link: https://patch.msgid.link/20260321012011.125791-1-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/devicetree/bindings/sound/st,stm32-sai.yaml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
+index 4a7129d0b1574..551edf39e7663 100644
+--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
++++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
+@@ -164,7 +164,7 @@ allOf:
+ properties:
+ compatible:
+ contains:
+- const: st,stm32mph7-sai
++ const: st,stm32h7-sai
+ then:
+ properties:
+ clocks:
+--
+2.53.0
+
--- /dev/null
+From e5aa579b700d2ee556890e1b5f3952bfd8171d64 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Mar 2026 18:28:50 +0800
+Subject: ASoC: fsl: imx-card: initialize playback_only and capture_only
+
+From: Shengjiu Wang <shengjiu.wang@nxp.com>
+
+[ Upstream commit ca67bd564e94aaa898a2cbb90922ca3cccd0612b ]
+
+Fix uninitialized variable playback_only and capture_only because
+graph_util_parse_link_direction() may not write them.
+
+Fixes: 1877c3e7937f ("ASoC: imx-card: Add playback_only or capture_only support")
+Suggested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
+Link: https://patch.msgid.link/20260318102850.2794029-3-shengjiu.wang@nxp.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/fsl/imx-card.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c
+index 05b4e971a3661..a4518fefad690 100644
+--- a/sound/soc/fsl/imx-card.c
++++ b/sound/soc/fsl/imx-card.c
+@@ -710,6 +710,8 @@ static int imx_card_parse_of(struct imx_card_data *data)
+ link->ops = &imx_aif_ops;
+ }
+
++ playback_only = false;
++ capture_only = false;
+ graph_util_parse_link_direction(np, &playback_only, &capture_only);
+ link->playback_only = playback_only;
+ link->capture_only = capture_only;
+--
+2.53.0
+
--- /dev/null
+From a6056f41d5b1a060a7c4f35445ba690c5d7f8eb0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 11:12:17 +0100
+Subject: ASoC: Intel: catpt: Fix the device initialization
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 5a184f1cb43a8e035251c635f5c47da5dc3e3049 ]
+
+The DMA mask shall be coerced before any buffer allocations for the
+device are done. At the same time explain why DMA mask of 31 bits is
+used in the first place.
+
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle")
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/catpt/device.c | 10 +++++++++-
+ sound/soc/intel/catpt/dsp.c | 3 ---
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c
+index faa916f400693..00e544e043591 100644
+--- a/sound/soc/intel/catpt/device.c
++++ b/sound/soc/intel/catpt/device.c
+@@ -271,7 +271,15 @@ static int catpt_acpi_probe(struct platform_device *pdev)
+ if (IS_ERR(cdev->pci_ba))
+ return PTR_ERR(cdev->pci_ba);
+
+- /* alloc buffer for storing DRAM context during dx transitions */
++ /*
++ * As per design HOST is responsible for preserving firmware's runtime
++ * context during D0 -> D3 -> D0 transitions. Addresses used for DMA
++ * to/from HOST memory shall be outside the reserved range of 0xFFFxxxxx.
++ */
++ ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
++ if (ret)
++ return ret;
++
+ cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev),
+ &cdev->dxbuf_paddr, GFP_KERNEL);
+ if (!cdev->dxbuf_vaddr)
+diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
+index 008a20a2acbda..677f348909c8f 100644
+--- a/sound/soc/intel/catpt/dsp.c
++++ b/sound/soc/intel/catpt/dsp.c
+@@ -125,9 +125,6 @@ int catpt_dmac_probe(struct catpt_dev *cdev)
+ dmac->dev = cdev->dev;
+ dmac->irq = cdev->irq;
+
+- ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
+- if (ret)
+- return ret;
+ /*
+ * Caller is responsible for putting device in D0 to allow
+ * for I/O and memory access before probing DW.
+--
+2.53.0
+
--- /dev/null
+From 5eec14bcaf89cec7a2377d3dacd603da6eb57881 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Mar 2026 12:06:35 +0000
+Subject: drm/amd/display: Do not skip unrelated mode changes in DSC validation
+
+From: Yussuf Khalil <dev@pp3345.net>
+
+[ Upstream commit aed3d041ab061ec8a64f50a3edda0f4db7280025 ]
+
+Starting with commit 17ce8a6907f7 ("drm/amd/display: Add dsc pre-validation in
+atomic check"), amdgpu resets the CRTC state mode_changed flag to false when
+recomputing the DSC configuration results in no timing change for a particular
+stream.
+
+However, this is incorrect in scenarios where a change in MST/DSC configuration
+happens in the same KMS commit as another (unrelated) mode change. For example,
+the integrated panel of a laptop may be configured differently (e.g., HDR
+enabled/disabled) depending on whether external screens are attached. In this
+case, plugging in external DP-MST screens may result in the mode_changed flag
+being dropped incorrectly for the integrated panel if its DSC configuration
+did not change during precomputation in pre_validate_dsc().
+
+At this point, however, dm_update_crtc_state() has already created new streams
+for CRTCs with DSC-independent mode changes. In turn,
+amdgpu_dm_commit_streams() will never release the old stream, resulting in a
+memory leak. amdgpu_dm_atomic_commit_tail() will never acquire a reference to
+the new stream either, which manifests as a use-after-free when the stream gets
+disabled later on:
+
+BUG: KASAN: use-after-free in dc_stream_release+0x25/0x90 [amdgpu]
+Write of size 4 at addr ffff88813d836524 by task kworker/9:9/29977
+
+Workqueue: events drm_mode_rmfb_work_fn
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x6e/0xa0
+ print_address_description.constprop.0+0x88/0x320
+ ? dc_stream_release+0x25/0x90 [amdgpu]
+ print_report+0xfc/0x1ff
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? __virt_addr_valid+0x225/0x4e0
+ ? dc_stream_release+0x25/0x90 [amdgpu]
+ kasan_report+0xe1/0x180
+ ? dc_stream_release+0x25/0x90 [amdgpu]
+ kasan_check_range+0x125/0x200
+ dc_stream_release+0x25/0x90 [amdgpu]
+ dc_state_destruct+0x14d/0x5c0 [amdgpu]
+ dc_state_release.part.0+0x4e/0x130 [amdgpu]
+ dm_atomic_destroy_state+0x3f/0x70 [amdgpu]
+ drm_atomic_state_default_clear+0x8ee/0xf30
+ ? drm_mode_object_put.part.0+0xb1/0x130
+ __drm_atomic_state_free+0x15c/0x2d0
+ atomic_remove_fb+0x67e/0x980
+
+Since there is no reliable way of figuring out whether a CRTC has unrelated
+mode changes pending at the time of DSC validation, remember the value of the
+mode_changed flag from before the point where a CRTC was marked as potentially
+affected by a change in DSC configuration. Reset the mode_changed flag to this
+earlier value instead in pre_validate_dsc().
+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/5004
+Fixes: 17ce8a6907f7 ("drm/amd/display: Add dsc pre-validation in atomic check")
+Signed-off-by: Yussuf Khalil <dev@pp3345.net>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit cc7c7121ae082b7b82891baa7280f1ff2608f22b)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 +
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +++-
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 77840b6cb2065..82a74e2cd721d 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -12268,6 +12268,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
+ }
+
+ if (dc_resource_is_dsc_encoding_supported(dc)) {
++ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
++ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
++ dm_new_crtc_state->mode_changed_independent_from_dsc = new_crtc_state->mode_changed;
++ }
++
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+ if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
+ ret = add_affected_mst_dsc_crtcs(state, crtc);
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+index adcd7ea696719..cd362d22a2774 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+@@ -965,6 +965,7 @@ struct dm_crtc_state {
+
+ bool freesync_vrr_info_changed;
+
++ bool mode_changed_independent_from_dsc;
+ bool dsc_force_changed;
+ bool vrr_supported;
+ struct mod_freesync_config freesync_config;
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+index 5e92eaa67aa33..2e0895f4f9b10 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -1744,9 +1744,11 @@ int pre_validate_dsc(struct drm_atomic_state *state,
+ int ind = find_crtc_index_in_state_by_stream(state, stream);
+
+ if (ind >= 0) {
++ struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(state->crtcs[ind].new_state);
++
+ DRM_INFO_ONCE("%s:%d MST_DSC no mode changed for stream 0x%p\n",
+ __func__, __LINE__, stream);
+- state->crtcs[ind].new_state->mode_changed = 0;
++ dm_new_crtc_state->base.mode_changed = dm_new_crtc_state->mode_changed_independent_from_dsc;
+ }
+ }
+ }
+--
+2.53.0
+
--- /dev/null
+From 72a760ee7f86e5815039a4e01d3e2846f1e9caef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Mar 2026 13:41:18 +0530
+Subject: drm/amdgpu: Fix fence put before wait in amdgpu_amdkfd_submit_ib
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 7150850146ebfa4ca998f653f264b8df6f7f85be ]
+
+amdgpu_amdkfd_submit_ib() submits a GPU job and gets a fence
+from amdgpu_ib_schedule(). This fence is used to wait for job
+completion.
+
+Currently, the code drops the fence reference using dma_fence_put()
+before calling dma_fence_wait().
+
+If dma_fence_put() releases the last reference, the fence may be
+freed before dma_fence_wait() is called. This can lead to a
+use-after-free.
+
+Fix this by waiting on the fence first and releasing the reference
+only after dma_fence_wait() completes.
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c:697 amdgpu_amdkfd_submit_ib() warn: passing freed memory 'f' (line 696)
+
+Fixes: 9ae55f030dc5 ("drm/amdgpu: Follow up change to previous drm scheduler change.")
+Cc: Felix Kuehling <Felix.Kuehling@amd.com>
+Cc: Dan Carpenter <dan.carpenter@linaro.org>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+index a2879d2b7c8ec..1ec26be82f30e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -687,9 +687,9 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
+ goto err_ib_sched;
+ }
+
+- /* Drop the initial kref_init count (see drm_sched_main as example) */
+- dma_fence_put(f);
+ ret = dma_fence_wait(f, false);
++ /* Drop the returned fence reference after the wait completes */
++ dma_fence_put(f);
+
+ err_ib_sched:
+ amdgpu_job_free(job);
+--
+2.53.0
+
--- /dev/null
+From b7b0ae2c0a291251ac4dcbc711b021b77bb6ec0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 16:19:19 -0700
+Subject: drm/i915/gmbus: fix spurious timeout on 512-byte burst reads
+
+From: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+
+[ Upstream commit 08441f10f4dc09fdeb64529953ac308abc79dd38 ]
+
+When reading exactly 512 bytes with burst read enabled, the
+extra_byte_added path breaks out of the inner do-while without
+decrementing len. The outer while(len) then re-enters and gmbus_wait()
+times out since all data has been delivered. Decrement len before the
+break so the outer loop terminates correctly.
+
+Fixes: d5dc0f43f268 ("drm/i915/gmbus: Enable burst read")
+Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_gmbus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
+index 358210adb8f84..10b3f3969c960 100644
+--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
++++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
+@@ -497,8 +497,10 @@ gmbus_xfer_read_chunk(struct intel_display *display,
+
+ val = intel_de_read_fw(display, GMBUS3(display));
+ do {
+- if (extra_byte_added && len == 1)
++ if (extra_byte_added && len == 1) {
++ len--;
+ break;
++ }
+
+ *buf++ = val & 0xff;
+ val >>= 8;
+--
+2.53.0
+
--- /dev/null
+From e8a868e3514627052a27b89517f1b8974d40ba68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Feb 2026 09:38:41 +0000
+Subject: drm/mediatek: dsi: Store driver data before invoking
+ mipi_dsi_host_register
+
+From: Luca Leonardo Scorcia <l.scorcia@gmail.com>
+
+[ Upstream commit 4cfdfeb6ac06079f92fccd977fa742d6c5b8dd3a ]
+
+The call to mipi_dsi_host_register triggers a callback to mtk_dsi_bind,
+which uses dev_get_drvdata to retrieve the mtk_dsi struct, so this
+structure needs to be stored inside the driver data before invoking it.
+
+As drvdata is currently uninitialized it leads to a crash when
+registering the DSI DRM encoder right after acquiring
+the mode_config.idr_mutex, blocking all subsequent DRM operations.
+
+Fixes the following crash during mediatek-drm probe (tested on Xiaomi
+Smart Clock x04g):
+
+Unable to handle kernel NULL pointer dereference at virtual address
+ 0000000000000040
+[...]
+Modules linked in: mediatek_drm(+) drm_display_helper cec drm_client_lib
+ drm_dma_helper drm_kms_helper panel_simple
+[...]
+Call trace:
+ drm_mode_object_add+0x58/0x98 (P)
+ __drm_encoder_init+0x48/0x140
+ drm_encoder_init+0x6c/0xa0
+ drm_simple_encoder_init+0x20/0x34 [drm_kms_helper]
+ mtk_dsi_bind+0x34/0x13c [mediatek_drm]
+ component_bind_all+0x120/0x280
+ mtk_drm_bind+0x284/0x67c [mediatek_drm]
+ try_to_bring_up_aggregate_device+0x23c/0x320
+ __component_add+0xa4/0x198
+ component_add+0x14/0x20
+ mtk_dsi_host_attach+0x78/0x100 [mediatek_drm]
+ mipi_dsi_attach+0x2c/0x50
+ panel_simple_dsi_probe+0x4c/0x9c [panel_simple]
+ mipi_dsi_drv_probe+0x1c/0x28
+ really_probe+0xc0/0x3dc
+ __driver_probe_device+0x80/0x160
+ driver_probe_device+0x40/0x120
+ __device_attach_driver+0xbc/0x17c
+ bus_for_each_drv+0x88/0xf0
+ __device_attach+0x9c/0x1cc
+ device_initial_probe+0x54/0x60
+ bus_probe_device+0x34/0xa0
+ device_add+0x5b0/0x800
+ mipi_dsi_device_register_full+0xdc/0x16c
+ mipi_dsi_host_register+0xc4/0x17c
+ mtk_dsi_probe+0x10c/0x260 [mediatek_drm]
+ platform_probe+0x5c/0xa4
+ really_probe+0xc0/0x3dc
+ __driver_probe_device+0x80/0x160
+ driver_probe_device+0x40/0x120
+ __driver_attach+0xc8/0x1f8
+ bus_for_each_dev+0x7c/0xe0
+ driver_attach+0x24/0x30
+ bus_add_driver+0x11c/0x240
+ driver_register+0x68/0x130
+ __platform_register_drivers+0x64/0x160
+ mtk_drm_init+0x24/0x1000 [mediatek_drm]
+ do_one_initcall+0x60/0x1d0
+ do_init_module+0x54/0x240
+ load_module+0x1838/0x1dc0
+ init_module_from_file+0xd8/0xf0
+ __arm64_sys_finit_module+0x1b4/0x428
+ invoke_syscall.constprop.0+0x48/0xc8
+ do_el0_svc+0x3c/0xb8
+ el0_svc+0x34/0xe8
+ el0t_64_sync_handler+0xa0/0xe4
+ el0t_64_sync+0x198/0x19c
+Code: 52800022 941004ab 2a0003f3 37f80040 (29005a80)
+
+Fixes: e4732b590a77 ("drm/mediatek: dsi: Register DSI host after acquiring clocks and PHY")
+Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: CK Hu <ck.hu@mediatek.com>
+Link: https://patchwork.kernel.org/project/dri-devel/patch/20260225094047.76780-1-l.scorcia@gmail.com/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dsi.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index d7726091819c4..acee2227275b7 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -1232,6 +1232,11 @@ static int mtk_dsi_probe(struct platform_device *pdev)
+
+ dsi->host.ops = &mtk_dsi_ops;
+ dsi->host.dev = dev;
++
++ init_waitqueue_head(&dsi->irq_wait_queue);
++
++ platform_set_drvdata(pdev, dsi);
++
+ ret = mipi_dsi_host_register(&dsi->host);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to register DSI host\n");
+@@ -1243,10 +1248,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
+ return dev_err_probe(&pdev->dev, ret, "Failed to request DSI irq\n");
+ }
+
+- init_waitqueue_head(&dsi->irq_wait_queue);
+-
+- platform_set_drvdata(pdev, dsi);
+-
+ dsi->bridge.of_node = dev->of_node;
+ dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
+
+--
+2.53.0
+
--- /dev/null
+From a88e66f260dc5bc6ed1c7e0b5f0feeb9f66571bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 15:30:34 -0700
+Subject: drm/xe: Implement recent spec updates to Wa_16025250150
+
+From: Matt Roper <matthew.d.roper@intel.com>
+
+[ Upstream commit 56781a4597706cd25185b1dedc38841ec6c31496 ]
+
+The hardware teams noticed that the originally documented workaround
+steps for Wa_16025250150 may not be sufficient to fully avoid a hardware
+issue. The workaround documentation has been augmented to suggest
+programming one additional register; make the corresponding change in
+the driver.
+
+Fixes: 7654d51f1fd8 ("drm/xe/xe2hpg: Add Wa_16025250150")
+Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
+Link: https://patch.msgid.link/20260319-wa_16025250150_part2-v1-1-46b1de1a31b2@intel.com
+Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
+(cherry picked from commit a31566762d4075646a8a2214586158b681e94305)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/regs/xe_gt_regs.h | 1 +
+ drivers/gpu/drm/xe/xe_wa.c | 3 ++-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+index f680c8b8f2587..7d90e4dd86d0e 100644
+--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
++++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+@@ -540,6 +540,7 @@
+ #define ENABLE_SMP_LD_RENDER_SURFACE_CONTROL REG_BIT(44 - 32)
+ #define FORCE_SLM_FENCE_SCOPE_TO_TILE REG_BIT(42 - 32)
+ #define FORCE_UGM_FENCE_SCOPE_TO_TILE REG_BIT(41 - 32)
++#define L3_128B_256B_WRT_DIS REG_BIT(40 - 32)
+ #define MAXREQS_PER_BANK REG_GENMASK(39 - 32, 37 - 32)
+ #define DISABLE_128B_EVICTION_COMMAND_UDW REG_BIT(36 - 32)
+
+diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
+index fe6e6227d9216..51c5985830b17 100644
+--- a/drivers/gpu/drm/xe/xe_wa.c
++++ b/drivers/gpu/drm/xe/xe_wa.c
+@@ -261,7 +261,8 @@ static const struct xe_rtp_entry_sr gt_was[] = {
+ LSN_DIM_Z_WGT_MASK,
+ LSN_LNI_WGT(1) | LSN_LNE_WGT(1) |
+ LSN_DIM_X_WGT(1) | LSN_DIM_Y_WGT(1) |
+- LSN_DIM_Z_WGT(1)))
++ LSN_DIM_Z_WGT(1)),
++ SET(LSC_CHICKEN_BIT_0_UDW, L3_128B_256B_WRT_DIS))
+ },
+
+ /* Xe2_HPM */
+--
+2.53.0
+
--- /dev/null
+From ff380acafc889dcbe26bbb6632280488d48c214a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 05:13:06 +0000
+Subject: hwmon: (adm1177) fix sysfs ABI violation and current unit conversion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sanman Pradhan <psanman@juniper.net>
+
+[ Upstream commit bf08749a6abb6d1959bfdc0edc32c640df407558 ]
+
+The adm1177 driver exposes the current alert threshold through
+hwmon_curr_max_alarm. This violates the hwmon sysfs ABI, where
+*_alarm attributes are read-only status flags and writable thresholds
+must use currN_max.
+
+The driver also stores the threshold internally in microamps, while
+currN_max is defined in milliamps. Convert the threshold accordingly
+on both the read and write paths.
+
+Widen the cached threshold and related calculations to 64 bits so
+that small shunt resistor values do not cause truncation or overflow.
+Also use 64-bit arithmetic for the mA/uA conversions, clamp writes
+to the range the hardware can represent, and propagate failures from
+adm1177_write_alert_thr() instead of silently ignoring them.
+
+Update the hwmon documentation to reflect the attribute rename and
+the correct units returned by the driver.
+
+Fixes: 09b08ac9e8d5 ("hwmon: (adm1177) Add ADM1177 Hot Swap Controller and Digital Power Monitor driver")
+Signed-off-by: Sanman Pradhan <psanman@juniper.net>
+Acked-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/adm1177.rst | 8 ++---
+ drivers/hwmon/adm1177.c | 54 +++++++++++++++++++--------------
+ 2 files changed, 35 insertions(+), 27 deletions(-)
+
+diff --git a/Documentation/hwmon/adm1177.rst b/Documentation/hwmon/adm1177.rst
+index 1c85a2af92bf7..375f6d6e03a7d 100644
+--- a/Documentation/hwmon/adm1177.rst
++++ b/Documentation/hwmon/adm1177.rst
+@@ -27,10 +27,10 @@ for details.
+ Sysfs entries
+ -------------
+
+-The following attributes are supported. Current maxim attribute
++The following attributes are supported. Current maximum attribute
+ is read-write, all other attributes are read-only.
+
+-in0_input Measured voltage in microvolts.
++in0_input Measured voltage in millivolts.
+
+-curr1_input Measured current in microamperes.
+-curr1_max_alarm Overcurrent alarm in microamperes.
++curr1_input Measured current in milliamperes.
++curr1_max Overcurrent shutdown threshold in milliamperes.
+diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c
+index 8b2c965480e3f..7888afe8dafd6 100644
+--- a/drivers/hwmon/adm1177.c
++++ b/drivers/hwmon/adm1177.c
+@@ -10,6 +10,8 @@
+ #include <linux/hwmon.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
++#include <linux/math64.h>
++#include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/regulator/consumer.h>
+
+@@ -33,7 +35,7 @@
+ struct adm1177_state {
+ struct i2c_client *client;
+ u32 r_sense_uohm;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
+ bool vrange_high;
+ };
+
+@@ -48,7 +50,7 @@ static int adm1177_write_cmd(struct adm1177_state *st, u8 cmd)
+ }
+
+ static int adm1177_write_alert_thr(struct adm1177_state *st,
+- u32 alert_threshold_ua)
++ u64 alert_threshold_ua)
+ {
+ u64 val;
+ int ret;
+@@ -91,8 +93,8 @@ static int adm1177_read(struct device *dev, enum hwmon_sensor_types type,
+ *val = div_u64((105840000ull * dummy),
+ 4096 * st->r_sense_uohm);
+ return 0;
+- case hwmon_curr_max_alarm:
+- *val = st->alert_threshold_ua;
++ case hwmon_curr_max:
++ *val = div_u64(st->alert_threshold_ua, 1000);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+@@ -126,9 +128,10 @@ static int adm1177_write(struct device *dev, enum hwmon_sensor_types type,
+ switch (type) {
+ case hwmon_curr:
+ switch (attr) {
+- case hwmon_curr_max_alarm:
+- adm1177_write_alert_thr(st, val);
+- return 0;
++ case hwmon_curr_max:
++ val = clamp_val(val, 0,
++ div_u64(105840000ULL, st->r_sense_uohm));
++ return adm1177_write_alert_thr(st, (u64)val * 1000);
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -156,7 +159,7 @@ static umode_t adm1177_is_visible(const void *data,
+ if (st->r_sense_uohm)
+ return 0444;
+ return 0;
+- case hwmon_curr_max_alarm:
++ case hwmon_curr_max:
+ if (st->r_sense_uohm)
+ return 0644;
+ return 0;
+@@ -170,7 +173,7 @@ static umode_t adm1177_is_visible(const void *data,
+
+ static const struct hwmon_channel_info * const adm1177_info[] = {
+ HWMON_CHANNEL_INFO(curr,
+- HWMON_C_INPUT | HWMON_C_MAX_ALARM),
++ HWMON_C_INPUT | HWMON_C_MAX),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT),
+ NULL
+@@ -192,7 +195,8 @@ static int adm1177_probe(struct i2c_client *client)
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct adm1177_state *st;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
++ u32 prop;
+ int ret;
+
+ st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+@@ -208,22 +212,26 @@ static int adm1177_probe(struct i2c_client *client)
+ if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
+ &st->r_sense_uohm))
+ st->r_sense_uohm = 0;
+- if (device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
+- &alert_threshold_ua)) {
+- if (st->r_sense_uohm)
+- /*
+- * set maximum default value from datasheet based on
+- * shunt-resistor
+- */
+- alert_threshold_ua = div_u64(105840000000,
+- st->r_sense_uohm);
+- else
+- alert_threshold_ua = 0;
++ if (!device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
++ &prop)) {
++ alert_threshold_ua = prop;
++ } else if (st->r_sense_uohm) {
++ /*
++ * set maximum default value from datasheet based on
++ * shunt-resistor
++ */
++ alert_threshold_ua = div_u64(105840000000ULL,
++ st->r_sense_uohm);
++ } else {
++ alert_threshold_ua = 0;
+ }
+ st->vrange_high = device_property_read_bool(dev,
+ "adi,vrange-high-enable");
+- if (alert_threshold_ua && st->r_sense_uohm)
+- adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (alert_threshold_ua && st->r_sense_uohm) {
++ ret = adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (ret)
++ return ret;
++ }
+
+ ret = adm1177_write_cmd(st, ADM1177_CMD_V_CONT |
+ ADM1177_CMD_I_CONT |
+--
+2.53.0
+
--- /dev/null
+From 504639740691b331b9a59681fb4a43d71cb89e35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Mar 2026 09:12:33 -0700
+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: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 114 ++++++++++++++++++++++++-------
+ 1 file changed, 89 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index cbc36f0ba4bf9..572be3ebc03df 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/dcache.h>
+@@ -21,8 +22,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"
+
+ /*
+@@ -112,6 +113,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);
+
+@@ -3228,12 +3234,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,
+@@ -3250,16 +3263,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)
+@@ -3269,7 +3288,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,
+@@ -3279,6 +3301,7 @@ static int pmbus_regulator_list_voltage(struct regulator_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 (data->flags & PMBUS_VOUT_PROTECTED)
+ return 0;
+@@ -3291,18 +3314,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 = {
+@@ -3333,12 +3367,42 @@ int pmbus_regulator_init_cb(struct regulator_dev *rdev,
+ }
+ EXPORT_SYMBOL_NS_GPL(pmbus_regulator_init_cb, "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);
+@@ -3362,19 +3426,19 @@ 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 void 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;
+- }
+- }
++ atomic_or(event, &data->regulator_events[page]);
++ schedule_work(&data->regulator_notify_work);
+ }
+ #else
+ static int pmbus_regulator_register(struct pmbus_data *data)
+--
+2.53.0
+
--- /dev/null
+From ab0cf54573ff62342775cc5318cae91a32cfc1ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 18:54:11 -0700
+Subject: hwmon: (pmbus) Introduce the concept of "write-only" attributes
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit cd658475e7694d58e1c40dabc1dacf8431ccedb2 ]
+
+Attributes intended to clear sensor history are intended to be writeable
+only. Reading those attributes today results in reporting more or less
+random values. To avoid ABI surprises, have those attributes explicitly
+return 0 when reading.
+
+Fixes: 787c095edaa9d ("hwmon: (pmbus/core) Add support for rated attributes")
+Reviewed-by: Sanman Pradhan <psanman@juniper.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 32 ++++++++++++++++++++++++--------
+ 1 file changed, 24 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index ecd1dddcbe0ff..cbc36f0ba4bf9 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -1209,6 +1209,12 @@ static ssize_t pmbus_show_boolean(struct device *dev,
+ return sysfs_emit(buf, "%d\n", val);
+ }
+
++static ssize_t pmbus_show_zero(struct device *dev,
++ struct device_attribute *devattr, char *buf)
++{
++ return sysfs_emit(buf, "0\n");
++}
++
+ static ssize_t pmbus_show_sensor(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+ {
+@@ -1407,7 +1413,7 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+ int reg,
+ enum pmbus_sensor_classes class,
+ bool update, bool readonly,
+- bool convert)
++ bool writeonly, bool convert)
+ {
+ struct pmbus_sensor *sensor;
+ struct device_attribute *a;
+@@ -1436,7 +1442,8 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+ sensor->data = -ENODATA;
+ pmbus_dev_attr_init(a, sensor->name,
+ readonly ? 0444 : 0644,
+- pmbus_show_sensor, pmbus_set_sensor);
++ writeonly ? pmbus_show_zero : pmbus_show_sensor,
++ pmbus_set_sensor);
+
+ if (pmbus_add_attribute(data, &a->attr))
+ return NULL;
+@@ -1496,6 +1503,7 @@ struct pmbus_limit_attr {
+ u16 reg; /* Limit register */
+ u16 sbit; /* Alarm attribute status bit */
+ bool readonly:1; /* True if the attribute is read-only */
++ bool writeonly:1; /* True if the attribute is write-only */
+ bool update:1; /* True if register needs updates */
+ bool low:1; /* True if low limit; for limits with compare functions only */
+ const char *attr; /* Attribute name */
+@@ -1545,7 +1553,7 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
+ curr = pmbus_add_sensor(data, name, l->attr, index,
+ page, 0xff, l->reg, attr->class,
+ attr->update || l->update,
+- l->readonly, true);
++ l->readonly, l->writeonly, true);
+ if (!curr)
+ return -ENOMEM;
+ if (l->sbit && (info->func[page] & attr->sfunc)) {
+@@ -1585,7 +1593,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
+ return ret;
+ }
+ base = pmbus_add_sensor(data, name, "input", index, page, phase,
+- attr->reg, attr->class, true, true, true);
++ attr->reg, attr->class, true, true, false, true);
+ if (!base)
+ return -ENOMEM;
+ /* No limit and alarm attributes for phase specific sensors */
+@@ -1722,6 +1730,7 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VIN_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VIN_MIN,
+@@ -1796,6 +1805,7 @@ static const struct pmbus_limit_attr vout_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VOUT_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VOUT_MIN,
+@@ -1877,6 +1887,7 @@ static const struct pmbus_limit_attr iin_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IIN_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IIN_MAX,
+@@ -1918,6 +1929,7 @@ static const struct pmbus_limit_attr iout_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IOUT_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IOUT_MAX,
+@@ -1976,6 +1988,7 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_PIN_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_PIN_MAX,
+@@ -2017,6 +2030,7 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_POUT_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_POUT_MAX,
+@@ -2088,6 +2102,7 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_1,
+@@ -2133,6 +2148,7 @@ static const struct pmbus_limit_attr temp_limit_attrs2[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_2,
+@@ -2250,7 +2266,7 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
+
+ sensor = pmbus_add_sensor(data, "fan", "target", index, page,
+ 0xff, PMBUS_VIRT_FAN_TARGET_1 + id, PSC_FAN,
+- false, false, true);
++ false, false, false, true);
+
+ if (!sensor)
+ return -ENOMEM;
+@@ -2261,14 +2277,14 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
+
+ sensor = pmbus_add_sensor(data, "pwm", NULL, index, page,
+ 0xff, PMBUS_VIRT_PWM_1 + id, PSC_PWM,
+- false, false, true);
++ false, false, false, true);
+
+ if (!sensor)
+ return -ENOMEM;
+
+ sensor = pmbus_add_sensor(data, "pwm", "enable", index, page,
+ 0xff, PMBUS_VIRT_PWM_ENABLE_1 + id, PSC_PWM,
+- true, false, false);
++ true, false, false, false);
+
+ if (!sensor)
+ return -ENOMEM;
+@@ -2310,7 +2326,7 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
+
+ if (pmbus_add_sensor(data, "fan", "input", index,
+ page, 0xff, pmbus_fan_registers[f],
+- PSC_FAN, true, true, true) == NULL)
++ PSC_FAN, true, true, false, true) == NULL)
+ return -ENOMEM;
+
+ /* Fan control */
+--
+2.53.0
+
--- /dev/null
+From 1cfadeb2a9a46ff1e97ec25c03c66d5ef980eddc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 16:41:07 -0700
+Subject: hwmon: (pmbus) Mark lowest/average/highest/rated attributes as
+ read-only
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 805a5bd1c3f307d45ae4e9cf8915ef16d585a54a ]
+
+Writing those attributes is not supported, so mark them as read-only.
+
+Prior to this change, attempts to write into these attributes returned
+an error.
+
+Mark boolean fields in struct pmbus_limit_attr and in struct
+pmbus_sensor_attr as bit fields to reduce configuration data size.
+The data is scanned only while probing, so performance is not a concern.
+
+Fixes: 6f183d33a02e6 ("hwmon: (pmbus) Add support for peak attributes")
+Reviewed-by: Sanman Pradhan <psanman@juniper.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 48 ++++++++++++++++++++++++++++----
+ 1 file changed, 42 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index be6d05def1152..ecd1dddcbe0ff 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -1495,8 +1495,9 @@ static int pmbus_add_label(struct pmbus_data *data,
+ struct pmbus_limit_attr {
+ u16 reg; /* Limit register */
+ u16 sbit; /* Alarm attribute status bit */
+- bool update; /* True if register needs updates */
+- bool low; /* True if low limit; for limits with compare functions only */
++ bool readonly:1; /* True if the attribute is read-only */
++ bool update:1; /* True if register needs updates */
++ bool low:1; /* True if low limit; for limits with compare functions only */
+ const char *attr; /* Attribute name */
+ const char *alarm; /* Alarm attribute name */
+ };
+@@ -1511,9 +1512,9 @@ struct pmbus_sensor_attr {
+ u8 nlimit; /* # of limit registers */
+ enum pmbus_sensor_classes class;/* sensor class */
+ const char *label; /* sensor label */
+- bool paged; /* true if paged sensor */
+- bool update; /* true if update needed */
+- bool compare; /* true if compare function needed */
++ bool paged:1; /* true if paged sensor */
++ bool update:1; /* true if update needed */
++ bool compare:1; /* true if compare function needed */
+ u32 func; /* sensor mask */
+ u32 sfunc; /* sensor status mask */
+ int sreg; /* status register */
+@@ -1544,7 +1545,7 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
+ curr = pmbus_add_sensor(data, name, l->attr, index,
+ page, 0xff, l->reg, attr->class,
+ attr->update || l->update,
+- false, true);
++ l->readonly, true);
+ if (!curr)
+ return -ENOMEM;
+ if (l->sbit && (info->func[page] & attr->sfunc)) {
+@@ -1707,23 +1708,28 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_VIN_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_VIN_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_VIN_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VIN_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VIN_MIN,
++ .readonly = true,
+ .attr = "rated_min",
+ }, {
+ .reg = PMBUS_MFR_VIN_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1776,23 +1782,28 @@ static const struct pmbus_limit_attr vout_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_VOUT_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_VOUT_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_VOUT_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VOUT_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VOUT_MIN,
++ .readonly = true,
+ .attr = "rated_min",
+ }, {
+ .reg = PMBUS_MFR_VOUT_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1852,20 +1863,24 @@ static const struct pmbus_limit_attr iin_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_IIN_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_IIN_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_IIN_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IIN_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IIN_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1889,20 +1904,24 @@ static const struct pmbus_limit_attr iout_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_IOUT_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_IOUT_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_IOUT_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IOUT_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IOUT_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1943,20 +1962,24 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_PIN_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_PIN_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "input_lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_PIN_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_PIN_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_PIN_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1980,20 +2003,24 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_POUT_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_POUT_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "input_lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_POUT_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_POUT_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_POUT_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -2049,18 +2076,22 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = {
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP_MIN,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP_AVG,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP_MAX,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_1,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -2090,18 +2121,22 @@ static const struct pmbus_limit_attr temp_limit_attrs2[] = {
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_MIN,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_AVG,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_MAX,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_2,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -2131,6 +2166,7 @@ static const struct pmbus_limit_attr temp_limit_attrs3[] = {
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_3,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From a4af67c3972a6e62e81d6a6fa24b3cfe0e06aebb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Mar 2026 18:39:41 +0100
+Subject: PM: hibernate: Drain trailing zero pages on userspace restore
+
+From: Alberto Garcia <berto@igalia.com>
+
+[ Upstream commit 734eba62cd32cb9ceffa09e57cdc03d761528525 ]
+
+Commit 005e8dddd497 ("PM: hibernate: don't store zero pages in the
+image file") added an optimization to skip zero-filled pages in the
+hibernation image. On restore, zero pages are handled internally by
+snapshot_write_next() in a loop that processes them without returning
+to the caller.
+
+With the userspace restore interface, writing the last non-zero page
+to /dev/snapshot is followed by the SNAPSHOT_ATOMIC_RESTORE ioctl. At
+this point there are no more calls to snapshot_write_next() so any
+trailing zero pages are not processed, snapshot_image_loaded() fails
+because handle->cur is smaller than expected, the ioctl returns -EPERM
+and the image is not restored.
+
+The in-kernel restore path is not affected by this because the loop in
+load_image() in swap.c calls snapshot_write_next() until it returns 0.
+It is this final call that drains any trailing zero pages.
+
+Fixed by calling snapshot_write_next() in snapshot_write_finalize(),
+giving the kernel the chance to drain any trailing zero pages.
+
+Fixes: 005e8dddd497 ("PM: hibernate: don't store zero pages in the image file")
+Signed-off-by: Alberto Garcia <berto@igalia.com>
+Acked-by: Brian Geffon <bgeffon@google.com>
+Link: https://patch.msgid.link/ef5a7c5e3e3dbd17dcb20efaa0c53a47a23498bb.1773075892.git.berto@igalia.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/snapshot.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
+index 645f42e404789..e249e5786fbcd 100644
+--- a/kernel/power/snapshot.c
++++ b/kernel/power/snapshot.c
+@@ -2856,6 +2856,17 @@ int snapshot_write_finalize(struct snapshot_handle *handle)
+ {
+ int error;
+
++ /*
++ * Call snapshot_write_next() to drain any trailing zero pages,
++ * but make sure we're in the data page region first.
++ * This function can return PAGE_SIZE if the kernel was expecting
++ * another copy page. Return -ENODATA in that situation.
++ */
++ if (handle->cur > nr_meta_pages + 1) {
++ error = snapshot_write_next(handle);
++ if (error)
++ return error > 0 ? -ENODATA : error;
++ }
+ copy_last_highmem_page();
+ error = hibernate_restore_protect_page(handle->buffer);
+ /* Do that only if we have loaded the image entirely */
+--
+2.53.0
+
--- /dev/null
+From 3e9c79774ef393357c71da628220b3f6c8e908f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Mar 2026 21:05:28 +0900
+Subject: PM: sleep: Drop spurious WARN_ON() from pm_restore_gfp_mask()
+
+From: Youngjun Park <youngjun.park@lge.com>
+
+[ Upstream commit a8d51efb5929ae308895455a3e496b5eca2cd143 ]
+
+Commit 35e4a69b2003f ("PM: sleep: Allow pm_restrict_gfp_mask()
+stacking") introduced refcount-based GFP mask management that warns
+when pm_restore_gfp_mask() is called with saved_gfp_count == 0.
+
+Some hibernation paths call pm_restore_gfp_mask() defensively where
+the GFP mask may or may not be restricted depending on the execution
+path. For example, the uswsusp interface invokes it in
+SNAPSHOT_CREATE_IMAGE, SNAPSHOT_UNFREEZE, and snapshot_release().
+Before the stacking change this was a silent no-op; it now triggers
+a spurious WARNING.
+
+Remove the WARN_ON() wrapper from the !saved_gfp_count check while
+retaining the check itself, so that defensive calls remain harmless
+without producing false warnings.
+
+Fixes: 35e4a69b2003f ("PM: sleep: Allow pm_restrict_gfp_mask() stacking")
+Signed-off-by: Youngjun Park <youngjun.park@lge.com>
+[ rjw: Subject tweak ]
+Link: https://patch.msgid.link/20260322120528.750178-1-youngjun.park@lge.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/power/main.c b/kernel/power/main.c
+index 549f51ca3a1e6..ed7b5953d1ce0 100644
+--- a/kernel/power/main.c
++++ b/kernel/power/main.c
+@@ -38,7 +38,7 @@ void pm_restore_gfp_mask(void)
+ {
+ WARN_ON(!mutex_is_locked(&system_transition_mutex));
+
+- if (WARN_ON(!saved_gfp_count) || --saved_gfp_count)
++ if (!saved_gfp_count || --saved_gfp_count)
+ return;
+
+ gfp_allowed_mask = saved_gfp_mask;
+--
+2.53.0
+
--- /dev/null
+From 2c753458df99cdca6362a962cd73e0525bb8bd49 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Dec 2025 13:06:13 +0000
+Subject: RDMA/efa: Check stored completion CTX command ID with received one
+
+From: Yonatan Nachum <ynachum@amazon.com>
+
+[ Upstream commit 4b01ec0f133b3fe1038dc538d6bfcbd72462d2f0 ]
+
+In admin command completion, we receive a CQE with the command ID which
+is constructed from context index and entropy bits from the admin queue
+producer counter. To try to detect memory corruptions in the received
+CQE, validate the full command ID of the fetched context with the CQE
+command ID. If there is a mismatch, complete the CQE with error.
+Also use LSBs of the admin queue producer counter to better detect
+entropy mismatch between smaller number of commands.
+
+Reviewed-by: Daniel Kranzdorf <dkkranzd@amazon.com>
+Reviewed-by: Michael Margolin <mrgolin@amazon.com>
+Signed-off-by: Yonatan Nachum <ynachum@amazon.com>
+Link: https://patch.msgid.link/20251210130614.36460-2-ynachum@amazon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: ef3b06742c8a ("RDMA/efa: Fix use of completion ctx after free")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/efa/efa_com.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c
+index 0e979ca10d240..b31478f3a1212 100644
+--- a/drivers/infiniband/hw/efa/efa_com.c
++++ b/drivers/infiniband/hw/efa/efa_com.c
+@@ -3,6 +3,8 @@
+ * Copyright 2018-2025 Amazon.com, Inc. or its affiliates. All rights reserved.
+ */
+
++#include <linux/log2.h>
++
+ #include "efa_com.h"
+ #include "efa_regs_defs.h"
+
+@@ -317,7 +319,7 @@ static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queu
+
+ /* cmd_id LSBs are the ctx_id and MSBs are entropy bits from pc */
+ cmd_id = ctx_id & queue_size_mask;
+- cmd_id |= aq->sq.pc & ~queue_size_mask;
++ cmd_id |= aq->sq.pc << ilog2(aq->depth);
+ cmd_id &= EFA_ADMIN_AQ_COMMON_DESC_COMMAND_ID_MASK;
+
+ cmd->aq_common_descriptor.command_id = cmd_id;
+@@ -418,7 +420,7 @@ static int efa_com_handle_single_admin_completion(struct efa_com_admin_queue *aq
+ EFA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID);
+
+ comp_ctx = efa_com_get_comp_ctx(aq, cmd_id, false);
+- if (comp_ctx->status != EFA_CMD_SUBMITTED) {
++ if (comp_ctx->status != EFA_CMD_SUBMITTED || comp_ctx->cmd_id != cmd_id) {
+ ibdev_err(aq->efa_dev,
+ "Received completion with unexpected command id[%d], sq producer: %d, sq consumer: %d, cq consumer: %d\n",
+ cmd_id, aq->sq.pc, aq->sq.cc, aq->cq.cc);
+--
+2.53.0
+
--- /dev/null
+From fbd82c2cb1ef010c5824c22b7fa493a8429cbbae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Mar 2026 23:57:30 -0500
+Subject: RDMA/efa: Fix possible deadlock
+
+From: Ethan Tidmore <ethantidmore06@gmail.com>
+
+[ Upstream commit 0f2055db7b630559870afb40fc84490816ab8ec5 ]
+
+In the error path for efa_com_alloc_comp_ctx() the semaphore assigned to
+&aq->avail_cmds is not released.
+
+Detected by Smatch:
+drivers/infiniband/hw/efa/efa_com.c:662 efa_com_cmd_exec() warn:
+inconsistent returns '&aq->avail_cmds'
+
+Add release for &aq->avail_cmds in efa_com_alloc_comp_ctx() error path.
+
+Fixes: ef3b06742c8a2 ("RDMA/efa: Fix use of completion ctx after free")
+Signed-off-by: Ethan Tidmore <ethantidmore06@gmail.com>
+Link: https://patch.msgid.link/20260314045730.1143862-1-ethantidmore06@gmail.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/efa/efa_com.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c
+index 56caba612139f..e97b5f0d70038 100644
+--- a/drivers/infiniband/hw/efa/efa_com.c
++++ b/drivers/infiniband/hw/efa/efa_com.c
+@@ -629,6 +629,7 @@ int efa_com_cmd_exec(struct efa_com_admin_queue *aq,
+ comp_ctx = efa_com_alloc_comp_ctx(aq);
+ if (!comp_ctx) {
+ clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
++ up(&aq->avail_cmds);
+ return -EINVAL;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 07e86b997b20b88a43fb01876af251e0fb376a30 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Mar 2026 16:53:50 +0000
+Subject: RDMA/efa: Fix use of completion ctx after free
+
+From: Yonatan Nachum <ynachum@amazon.com>
+
+[ Upstream commit ef3b06742c8a201d0e83edc9a33a89a4fe3009f8 ]
+
+On admin queue completion handling, if the admin command completed with
+error we print data from the completion context. The issue is that we
+already freed the completion context in polling/interrupts handler which
+means we print data from context in an unknown state (it might be
+already used again).
+Change the admin submission flow so alloc/dealloc of the context will be
+symmetric and dealloc will be called after any potential use of the
+context.
+
+Fixes: 68fb9f3e312a ("RDMA/efa: Remove redundant NULL pointer check of CQE")
+Reviewed-by: Daniel Kranzdorf <dkkranzd@amazon.com>
+Reviewed-by: Michael Margolin <mrgolin@amazon.com>
+Signed-off-by: Yonatan Nachum <ynachum@amazon.com>
+Link: https://patch.msgid.link/20260308165350.18219-1-ynachum@amazon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/efa/efa_com.c | 87 +++++++++++++----------------
+ 1 file changed, 39 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c
+index 229b0ad3b0cbb..56caba612139f 100644
+--- a/drivers/infiniband/hw/efa/efa_com.c
++++ b/drivers/infiniband/hw/efa/efa_com.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+ /*
+- * Copyright 2018-2025 Amazon.com, Inc. or its affiliates. All rights reserved.
++ * Copyright 2018-2026 Amazon.com, Inc. or its affiliates. All rights reserved.
+ */
+
+ #include <linux/log2.h>
+@@ -310,23 +310,19 @@ static inline struct efa_comp_ctx *efa_com_get_comp_ctx_by_cmd_id(struct efa_com
+ return &aq->comp_ctx[ctx_id];
+ }
+
+-static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queue *aq,
+- struct efa_admin_aq_entry *cmd,
+- size_t cmd_size_in_bytes,
+- struct efa_admin_acq_entry *comp,
+- size_t comp_size_in_bytes)
++static void __efa_com_submit_admin_cmd(struct efa_com_admin_queue *aq,
++ struct efa_comp_ctx *comp_ctx,
++ struct efa_admin_aq_entry *cmd,
++ size_t cmd_size_in_bytes,
++ struct efa_admin_acq_entry *comp,
++ size_t comp_size_in_bytes)
+ {
+ struct efa_admin_aq_entry *aqe;
+- struct efa_comp_ctx *comp_ctx;
+ u16 queue_size_mask;
+ u16 cmd_id;
+ u16 ctx_id;
+ u16 pi;
+
+- comp_ctx = efa_com_alloc_comp_ctx(aq);
+- if (!comp_ctx)
+- return ERR_PTR(-EINVAL);
+-
+ queue_size_mask = aq->depth - 1;
+ pi = aq->sq.pc & queue_size_mask;
+ ctx_id = efa_com_get_comp_ctx_id(aq, comp_ctx);
+@@ -360,8 +356,6 @@ static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queu
+
+ /* barrier not needed in case of writel */
+ writel(aq->sq.pc, aq->sq.db_addr);
+-
+- return comp_ctx;
+ }
+
+ static inline int efa_com_init_comp_ctxt(struct efa_com_admin_queue *aq)
+@@ -394,28 +388,25 @@ static inline int efa_com_init_comp_ctxt(struct efa_com_admin_queue *aq)
+ return 0;
+ }
+
+-static struct efa_comp_ctx *efa_com_submit_admin_cmd(struct efa_com_admin_queue *aq,
+- struct efa_admin_aq_entry *cmd,
+- size_t cmd_size_in_bytes,
+- struct efa_admin_acq_entry *comp,
+- size_t comp_size_in_bytes)
++static int efa_com_submit_admin_cmd(struct efa_com_admin_queue *aq,
++ struct efa_comp_ctx *comp_ctx,
++ struct efa_admin_aq_entry *cmd,
++ size_t cmd_size_in_bytes,
++ struct efa_admin_acq_entry *comp,
++ size_t comp_size_in_bytes)
+ {
+- struct efa_comp_ctx *comp_ctx;
+-
+ spin_lock(&aq->sq.lock);
+ if (!test_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state)) {
+ ibdev_err_ratelimited(aq->efa_dev, "Admin queue is closed\n");
+ spin_unlock(&aq->sq.lock);
+- return ERR_PTR(-ENODEV);
++ return -ENODEV;
+ }
+
+- comp_ctx = __efa_com_submit_admin_cmd(aq, cmd, cmd_size_in_bytes, comp,
+- comp_size_in_bytes);
++ __efa_com_submit_admin_cmd(aq, comp_ctx, cmd, cmd_size_in_bytes, comp,
++ comp_size_in_bytes);
+ spin_unlock(&aq->sq.lock);
+- if (IS_ERR(comp_ctx))
+- clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
+
+- return comp_ctx;
++ return 0;
+ }
+
+ static int efa_com_handle_single_admin_completion(struct efa_com_admin_queue *aq,
+@@ -512,7 +503,6 @@ static int efa_com_wait_and_process_admin_cq_polling(struct efa_comp_ctx *comp_c
+ {
+ unsigned long timeout;
+ unsigned long flags;
+- int err;
+
+ timeout = jiffies + usecs_to_jiffies(aq->completion_timeout);
+
+@@ -532,24 +522,20 @@ static int efa_com_wait_and_process_admin_cq_polling(struct efa_comp_ctx *comp_c
+ atomic64_inc(&aq->stats.no_completion);
+
+ clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
+- err = -ETIME;
+- goto out;
++ return -ETIME;
+ }
+
+ msleep(aq->poll_interval);
+ }
+
+- err = efa_com_comp_status_to_errno(comp_ctx->user_cqe->acq_common_descriptor.status);
+-out:
+- efa_com_dealloc_comp_ctx(aq, comp_ctx);
+- return err;
++ return efa_com_comp_status_to_errno(
++ comp_ctx->user_cqe->acq_common_descriptor.status);
+ }
+
+ static int efa_com_wait_and_process_admin_cq_interrupts(struct efa_comp_ctx *comp_ctx,
+ struct efa_com_admin_queue *aq)
+ {
+ unsigned long flags;
+- int err;
+
+ wait_for_completion_timeout(&comp_ctx->wait_event,
+ usecs_to_jiffies(aq->completion_timeout));
+@@ -585,14 +571,11 @@ static int efa_com_wait_and_process_admin_cq_interrupts(struct efa_comp_ctx *com
+ aq->cq.cc);
+
+ clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
+- err = -ETIME;
+- goto out;
++ return -ETIME;
+ }
+
+- err = efa_com_comp_status_to_errno(comp_ctx->user_cqe->acq_common_descriptor.status);
+-out:
+- efa_com_dealloc_comp_ctx(aq, comp_ctx);
+- return err;
++ return efa_com_comp_status_to_errno(
++ comp_ctx->user_cqe->acq_common_descriptor.status);
+ }
+
+ /*
+@@ -642,30 +625,38 @@ int efa_com_cmd_exec(struct efa_com_admin_queue *aq,
+ ibdev_dbg(aq->efa_dev, "%s (opcode %d)\n",
+ efa_com_cmd_str(cmd->aq_common_descriptor.opcode),
+ cmd->aq_common_descriptor.opcode);
+- comp_ctx = efa_com_submit_admin_cmd(aq, cmd, cmd_size, comp, comp_size);
+- if (IS_ERR(comp_ctx)) {
++
++ comp_ctx = efa_com_alloc_comp_ctx(aq);
++ if (!comp_ctx) {
++ clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
++ return -EINVAL;
++ }
++
++ err = efa_com_submit_admin_cmd(aq, comp_ctx, cmd, cmd_size, comp, comp_size);
++ if (err) {
+ ibdev_err_ratelimited(
+ aq->efa_dev,
+- "Failed to submit command %s (opcode %u) err %pe\n",
++ "Failed to submit command %s (opcode %u) err %d\n",
+ efa_com_cmd_str(cmd->aq_common_descriptor.opcode),
+- cmd->aq_common_descriptor.opcode, comp_ctx);
++ cmd->aq_common_descriptor.opcode, err);
+
++ efa_com_dealloc_comp_ctx(aq, comp_ctx);
+ up(&aq->avail_cmds);
+ atomic64_inc(&aq->stats.cmd_err);
+- return PTR_ERR(comp_ctx);
++ return err;
+ }
+
+ err = efa_com_wait_and_process_admin_cq(comp_ctx, aq);
+ if (err) {
+ ibdev_err_ratelimited(
+ aq->efa_dev,
+- "Failed to process command %s (opcode %u) comp_status %d err %d\n",
++ "Failed to process command %s (opcode %u) err %d\n",
+ efa_com_cmd_str(cmd->aq_common_descriptor.opcode),
+- cmd->aq_common_descriptor.opcode,
+- comp_ctx->user_cqe->acq_common_descriptor.status, err);
++ cmd->aq_common_descriptor.opcode, err);
+ atomic64_inc(&aq->stats.cmd_err);
+ }
+
++ efa_com_dealloc_comp_ctx(aq, comp_ctx);
+ up(&aq->avail_cmds);
+
+ return err;
+--
+2.53.0
+
--- /dev/null
+From 4809ce3425c0c6e53ff45b199e37f091c882ad01 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Dec 2025 13:06:14 +0000
+Subject: RDMA/efa: Improve admin completion context state machine
+
+From: Yonatan Nachum <ynachum@amazon.com>
+
+[ Upstream commit dab5825491f7b0ea92a09390f39df0a51100f12f ]
+
+Add a new unused state to the admin completion contexts state machine
+instead of the occupied field. This improves the completion validity
+check because it now enforce the context to be in submitted state prior
+to completing it. Also add allocated state as a intermediate state
+between unused and submitted.
+
+Reviewed-by: Daniel Kranzdorf <dkkranzd@amazon.com>
+Reviewed-by: Michael Margolin <mrgolin@amazon.com>
+Signed-off-by: Yonatan Nachum <ynachum@amazon.com>
+Link: https://patch.msgid.link/20251210130614.36460-3-ynachum@amazon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: ef3b06742c8a ("RDMA/efa: Fix use of completion ctx after free")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/efa/efa_com.c | 91 ++++++++++++++++-------------
+ 1 file changed, 50 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c
+index b31478f3a1212..229b0ad3b0cbb 100644
+--- a/drivers/infiniband/hw/efa/efa_com.c
++++ b/drivers/infiniband/hw/efa/efa_com.c
+@@ -23,6 +23,8 @@
+ #define EFA_CTRL_SUB_MINOR 1
+
+ enum efa_cmd_status {
++ EFA_CMD_UNUSED,
++ EFA_CMD_ALLOCATED,
+ EFA_CMD_SUBMITTED,
+ EFA_CMD_COMPLETED,
+ };
+@@ -34,7 +36,6 @@ struct efa_comp_ctx {
+ enum efa_cmd_status status;
+ u16 cmd_id;
+ u8 cmd_opcode;
+- u8 occupied;
+ };
+
+ static const char *efa_com_cmd_str(u8 cmd)
+@@ -243,7 +244,6 @@ static int efa_com_admin_init_aenq(struct efa_com_dev *edev,
+ return 0;
+ }
+
+-/* ID to be used with efa_com_get_comp_ctx */
+ static u16 efa_com_alloc_ctx_id(struct efa_com_admin_queue *aq)
+ {
+ u16 ctx_id;
+@@ -265,36 +265,47 @@ static void efa_com_dealloc_ctx_id(struct efa_com_admin_queue *aq,
+ spin_unlock(&aq->comp_ctx_lock);
+ }
+
+-static inline void efa_com_put_comp_ctx(struct efa_com_admin_queue *aq,
+- struct efa_comp_ctx *comp_ctx)
++static struct efa_comp_ctx *efa_com_alloc_comp_ctx(struct efa_com_admin_queue *aq)
+ {
+- u16 cmd_id = EFA_GET(&comp_ctx->user_cqe->acq_common_descriptor.command,
+- EFA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID);
+- u16 ctx_id = cmd_id & (aq->depth - 1);
++ struct efa_comp_ctx *comp_ctx;
++ u16 ctx_id;
+
+- ibdev_dbg(aq->efa_dev, "Put completion command_id %#x\n", cmd_id);
+- comp_ctx->occupied = 0;
+- efa_com_dealloc_ctx_id(aq, ctx_id);
++ ctx_id = efa_com_alloc_ctx_id(aq);
++
++ comp_ctx = &aq->comp_ctx[ctx_id];
++ if (comp_ctx->status != EFA_CMD_UNUSED) {
++ efa_com_dealloc_ctx_id(aq, ctx_id);
++ ibdev_err_ratelimited(aq->efa_dev,
++ "Completion context[%u] is used[%u]\n",
++ ctx_id, comp_ctx->status);
++ return NULL;
++ }
++
++ comp_ctx->status = EFA_CMD_ALLOCATED;
++ ibdev_dbg(aq->efa_dev, "Take completion context[%u]\n", ctx_id);
++ return comp_ctx;
+ }
+
+-static struct efa_comp_ctx *efa_com_get_comp_ctx(struct efa_com_admin_queue *aq,
+- u16 cmd_id, bool capture)
++static inline u16 efa_com_get_comp_ctx_id(struct efa_com_admin_queue *aq,
++ struct efa_comp_ctx *comp_ctx)
+ {
+- u16 ctx_id = cmd_id & (aq->depth - 1);
++ return comp_ctx - aq->comp_ctx;
++}
+
+- if (aq->comp_ctx[ctx_id].occupied && capture) {
+- ibdev_err_ratelimited(
+- aq->efa_dev,
+- "Completion context for command_id %#x is occupied\n",
+- cmd_id);
+- return NULL;
+- }
++static inline void efa_com_dealloc_comp_ctx(struct efa_com_admin_queue *aq,
++ struct efa_comp_ctx *comp_ctx)
++{
++ u16 ctx_id = efa_com_get_comp_ctx_id(aq, comp_ctx);
+
+- if (capture) {
+- aq->comp_ctx[ctx_id].occupied = 1;
+- ibdev_dbg(aq->efa_dev,
+- "Take completion ctxt for command_id %#x\n", cmd_id);
+- }
++ ibdev_dbg(aq->efa_dev, "Put completion context[%u]\n", ctx_id);
++ comp_ctx->status = EFA_CMD_UNUSED;
++ efa_com_dealloc_ctx_id(aq, ctx_id);
++}
++
++static inline struct efa_comp_ctx *efa_com_get_comp_ctx_by_cmd_id(struct efa_com_admin_queue *aq,
++ u16 cmd_id)
++{
++ u16 ctx_id = cmd_id & (aq->depth - 1);
+
+ return &aq->comp_ctx[ctx_id];
+ }
+@@ -312,10 +323,13 @@ static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queu
+ u16 ctx_id;
+ u16 pi;
+
++ comp_ctx = efa_com_alloc_comp_ctx(aq);
++ if (!comp_ctx)
++ return ERR_PTR(-EINVAL);
++
+ queue_size_mask = aq->depth - 1;
+ pi = aq->sq.pc & queue_size_mask;
+-
+- ctx_id = efa_com_alloc_ctx_id(aq);
++ ctx_id = efa_com_get_comp_ctx_id(aq, comp_ctx);
+
+ /* cmd_id LSBs are the ctx_id and MSBs are entropy bits from pc */
+ cmd_id = ctx_id & queue_size_mask;
+@@ -326,12 +340,6 @@ static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queu
+ EFA_SET(&cmd->aq_common_descriptor.flags,
+ EFA_ADMIN_AQ_COMMON_DESC_PHASE, aq->sq.phase);
+
+- comp_ctx = efa_com_get_comp_ctx(aq, cmd_id, true);
+- if (!comp_ctx) {
+- efa_com_dealloc_ctx_id(aq, ctx_id);
+- return ERR_PTR(-EINVAL);
+- }
+-
+ comp_ctx->status = EFA_CMD_SUBMITTED;
+ comp_ctx->comp_size = comp_size_in_bytes;
+ comp_ctx->user_cqe = comp;
+@@ -372,9 +380,9 @@ static inline int efa_com_init_comp_ctxt(struct efa_com_admin_queue *aq)
+ }
+
+ for (i = 0; i < aq->depth; i++) {
+- comp_ctx = efa_com_get_comp_ctx(aq, i, false);
+- if (comp_ctx)
+- init_completion(&comp_ctx->wait_event);
++ comp_ctx = &aq->comp_ctx[i];
++ comp_ctx->status = EFA_CMD_UNUSED;
++ init_completion(&comp_ctx->wait_event);
+
+ aq->comp_ctx_pool[i] = i;
+ }
+@@ -419,11 +427,12 @@ static int efa_com_handle_single_admin_completion(struct efa_com_admin_queue *aq
+ cmd_id = EFA_GET(&cqe->acq_common_descriptor.command,
+ EFA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID);
+
+- comp_ctx = efa_com_get_comp_ctx(aq, cmd_id, false);
++ comp_ctx = efa_com_get_comp_ctx_by_cmd_id(aq, cmd_id);
+ if (comp_ctx->status != EFA_CMD_SUBMITTED || comp_ctx->cmd_id != cmd_id) {
+ ibdev_err(aq->efa_dev,
+- "Received completion with unexpected command id[%d], sq producer: %d, sq consumer: %d, cq consumer: %d\n",
+- cmd_id, aq->sq.pc, aq->sq.cc, aq->cq.cc);
++ "Received completion with unexpected command id[%x], status[%d] sq producer[%d], sq consumer[%d], cq consumer[%d]\n",
++ cmd_id, comp_ctx->status, aq->sq.pc, aq->sq.cc,
++ aq->cq.cc);
+ return -EINVAL;
+ }
+
+@@ -532,7 +541,7 @@ static int efa_com_wait_and_process_admin_cq_polling(struct efa_comp_ctx *comp_c
+
+ err = efa_com_comp_status_to_errno(comp_ctx->user_cqe->acq_common_descriptor.status);
+ out:
+- efa_com_put_comp_ctx(aq, comp_ctx);
++ efa_com_dealloc_comp_ctx(aq, comp_ctx);
+ return err;
+ }
+
+@@ -582,7 +591,7 @@ static int efa_com_wait_and_process_admin_cq_interrupts(struct efa_comp_ctx *com
+
+ err = efa_com_comp_status_to_errno(comp_ctx->user_cqe->acq_common_descriptor.status);
+ out:
+- efa_com_put_comp_ctx(aq, comp_ctx);
++ efa_com_dealloc_comp_ctx(aq, comp_ctx);
+ return err;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 9fcd1fb284209e26a6c8029d64e18a3b085a15ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:43 -0500
+Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node
+
+From: Ivan Barrera <ivan.d.barrera@intel.com>
+
+[ Upstream commit b415399c9a024d574b65479636f0d4eb625b9abd ]
+
+The cm_node is available and the usage of cm_node and event->cm_node
+seems arbitrary. Clean up unnecessary dereference of event->cm_node.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Ivan Barrera <ivan.d.barrera@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index f4f4f92ba63ac..128cfcf27714d 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -4239,21 +4239,21 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ irdma_cm_event_reset(event);
+ break;
+ case IRDMA_CM_EVENT_CONNECTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state != IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state != IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_cm_event_connected(event);
+ break;
+ case IRDMA_CM_EVENT_MPA_REJECT:
+- if (!event->cm_node->cm_id ||
++ if (!cm_node->cm_id ||
+ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_send_cm_event(cm_node, cm_node->cm_id,
+ IW_CM_EVENT_CONNECT_REPLY, -ECONNREFUSED);
+ break;
+ case IRDMA_CM_EVENT_ABORTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state == IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_event_connect_error(event);
+ break;
+@@ -4263,7 +4263,7 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ break;
+ }
+
+- irdma_rem_ref_cm_node(event->cm_node);
++ irdma_rem_ref_cm_node(cm_node);
+ kfree(event);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 4a85329f11f875a51d58e14876d72d6bbe124b95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:45 -0500
+Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections
+
+From: Anil Samal <anil.samal@intel.com>
+
+[ Upstream commit 6f52370970ac07d352a7af4089e55e0e6425f827 ]
+
+Resolve deadlock that occurs when user executes netdev reset while RDMA
+applications (e.g., rping) are active. The netdev reset causes ice
+driver to remove irdma auxiliary driver, triggering device_delete and
+subsequent client removal. During client removal, uverbs_client waits
+for QP reference count to reach zero while cma_client holds the final
+reference, creating circular dependency and indefinite wait in iWARP
+mode. Skip QP reference count wait during device reset to prevent
+deadlock.
+
+Fixes: c8f304d75f6c ("RDMA/irdma: Prevent QP use after free")
+Signed-off-by: Anil Samal <anil.samal@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index ed2f985a35408..c77d6d0eafdec 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -558,7 +558,8 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+ }
+
+ irdma_qp_rem_ref(&iwqp->ibqp);
+- wait_for_completion(&iwqp->free_qp);
++ if (!iwdev->rf->reset)
++ wait_for_completion(&iwqp->free_qp);
+ irdma_free_lsmm_rsrc(iwqp);
+ irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
+
+--
+2.53.0
+
--- /dev/null
+From a6411322cb7cc91593871fd50b6d5ee8c34c4c59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:47 -0500
+Subject: RDMA/irdma: Harden depth calculation functions
+
+From: Shiraz Saleem <shiraz.saleem@intel.com>
+
+[ Upstream commit e37afcb56ae070477741fe2d6e61fc0c542cce2d ]
+
+An issue was exposed where OS can pass in U32_MAX for SQ/RQ/SRQ size.
+This can cause integer overflow and truncation of SQ/RQ/SRQ depth
+returning a success when it should have failed.
+
+Harden the functions to do all depth calculations and boundary
+checking in u64 sizes.
+
+Fixes: 563e1feb5f6e ("RDMA/irdma: Add SRQ support")
+Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/uk.c | 39 ++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/uk.c b/drivers/infiniband/hw/irdma/uk.c
+index d5568584ad5e3..4cc81d61be7fa 100644
+--- a/drivers/infiniband/hw/irdma/uk.c
++++ b/drivers/infiniband/hw/irdma/uk.c
+@@ -1410,7 +1410,7 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
+ * irdma_round_up_wq - return round up qp wq depth
+ * @wqdepth: wq depth in quanta to round up
+ */
+-static int irdma_round_up_wq(u32 wqdepth)
++static u64 irdma_round_up_wq(u64 wqdepth)
+ {
+ int scount = 1;
+
+@@ -1463,15 +1463,16 @@ void irdma_get_wqe_shift(struct irdma_uk_attrs *uk_attrs, u32 sge,
+ int irdma_get_sqdepth(struct irdma_uk_attrs *uk_attrs, u32 sq_size, u8 shift,
+ u32 *sqdepth)
+ {
+- u32 min_size = (u32)uk_attrs->min_hw_wq_size << shift;
++ u32 min_hw_quanta = (u32)uk_attrs->min_hw_wq_size << shift;
++ u64 hw_quanta =
++ irdma_round_up_wq(((u64)sq_size << shift) + IRDMA_SQ_RSVD);
+
+- *sqdepth = irdma_round_up_wq((sq_size << shift) + IRDMA_SQ_RSVD);
+-
+- if (*sqdepth < min_size)
+- *sqdepth = min_size;
+- else if (*sqdepth > uk_attrs->max_hw_wq_quanta)
++ if (hw_quanta < min_hw_quanta)
++ hw_quanta = min_hw_quanta;
++ else if (hw_quanta > uk_attrs->max_hw_wq_quanta)
+ return -EINVAL;
+
++ *sqdepth = hw_quanta;
+ return 0;
+ }
+
+@@ -1485,15 +1486,16 @@ int irdma_get_sqdepth(struct irdma_uk_attrs *uk_attrs, u32 sq_size, u8 shift,
+ int irdma_get_rqdepth(struct irdma_uk_attrs *uk_attrs, u32 rq_size, u8 shift,
+ u32 *rqdepth)
+ {
+- u32 min_size = (u32)uk_attrs->min_hw_wq_size << shift;
+-
+- *rqdepth = irdma_round_up_wq((rq_size << shift) + IRDMA_RQ_RSVD);
++ u32 min_hw_quanta = (u32)uk_attrs->min_hw_wq_size << shift;
++ u64 hw_quanta =
++ irdma_round_up_wq(((u64)rq_size << shift) + IRDMA_RQ_RSVD);
+
+- if (*rqdepth < min_size)
+- *rqdepth = min_size;
+- else if (*rqdepth > uk_attrs->max_hw_rq_quanta)
++ if (hw_quanta < min_hw_quanta)
++ hw_quanta = min_hw_quanta;
++ else if (hw_quanta > uk_attrs->max_hw_rq_quanta)
+ return -EINVAL;
+
++ *rqdepth = hw_quanta;
+ return 0;
+ }
+
+@@ -1507,13 +1509,16 @@ int irdma_get_rqdepth(struct irdma_uk_attrs *uk_attrs, u32 rq_size, u8 shift,
+ int irdma_get_srqdepth(struct irdma_uk_attrs *uk_attrs, u32 srq_size, u8 shift,
+ u32 *srqdepth)
+ {
+- *srqdepth = irdma_round_up_wq((srq_size << shift) + IRDMA_RQ_RSVD);
++ u32 min_hw_quanta = (u32)uk_attrs->min_hw_wq_size << shift;
++ u64 hw_quanta =
++ irdma_round_up_wq(((u64)srq_size << shift) + IRDMA_RQ_RSVD);
+
+- if (*srqdepth < ((u32)uk_attrs->min_hw_wq_size << shift))
+- *srqdepth = uk_attrs->min_hw_wq_size << shift;
+- else if (*srqdepth > uk_attrs->max_hw_srq_quanta)
++ if (hw_quanta < min_hw_quanta)
++ hw_quanta = min_hw_quanta;
++ else if (hw_quanta > uk_attrs->max_hw_srq_quanta)
+ return -EINVAL;
+
++ *srqdepth = hw_quanta;
+ return 0;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 7791bee3e3433a01233adb3500501e780492863c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:38 -0500
+Subject: RDMA/irdma: Initialize free_qp completion before using it
+
+From: Jacob Moroni <jmoroni@google.com>
+
+[ Upstream commit 11a95521fb93c91e2d4ef9d53dc80ef0a755549b ]
+
+In irdma_create_qp, if ib_copy_to_udata fails, it will call
+irdma_destroy_qp to clean up which will attempt to wait on
+the free_qp completion, which is not initialized yet. Fix this
+by initializing the completion before the ib_copy_to_udata call.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Jacob Moroni <jmoroni@google.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 5d027c04dba6f..f53b8f0d7ca83 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1106,6 +1106,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ spin_lock_init(&iwqp->sc_qp.pfpdu.lock);
+ iwqp->sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
+ rf->qp_table[qp_num] = iwqp;
++ init_completion(&iwqp->free_qp);
+
+ if (udata) {
+ /* GEN_1 legacy support with libi40iw does not have expanded uresp struct */
+@@ -1130,7 +1131,6 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ }
+ }
+
+- init_completion(&iwqp->free_qp);
+ return 0;
+
+ error:
+--
+2.53.0
+
--- /dev/null
+From b83956e96e58f15b3f6a8b7ba8052360e2edfb8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:42 -0500
+Subject: RDMA/irdma: Remove a NOP wait_event() in irdma_modify_qp_roce()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 5e8f0239731a83753473b7aa91bda67bbdff5053 ]
+
+Remove a NOP wait_event() in irdma_modify_qp_roce() which is relevant
+for iWARP and likely a copy and paste artifact for RoCEv2. The wait event
+is for sending a reset on a TCP connection, after the reset has been
+requested in irdma_modify_qp(), which occurs only in iWarp mode.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index c2449f5721eeb..ed2f985a35408 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1463,8 +1463,6 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ ctx_info->remote_atomics_en = true;
+ }
+
+- wait_event(iwqp->mod_qp_waitq, !atomic_read(&iwqp->hw_mod_qp_pend));
+-
+ ibdev_dbg(&iwdev->ibdev,
+ "VERBS: caller: %pS qp_id=%d to_ibqpstate=%d ibqpstate=%d irdma_qpstate=%d attr_mask=0x%x\n",
+ __builtin_return_address(0), ibqp->qp_num, attr->qp_state,
+--
+2.53.0
+
--- /dev/null
+From bffcf159ae4c74fe350cdecae593602f32d9df78 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:44 -0500
+Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit c45c6ebd693b944f1ffe429fdfb6cc1674c237be ]
+
+During reset, irdma_modify_qp() to error should be called to disconnect
+the QP. Without this fix, if not preceded by irdma_modify_qp() to error, the
+API call irdma_destroy_qp() gets stuck waiting for the QP refcount to go
+to zero, because the cm_node associated with this QP isn't disconnected.
+
+Fixes: 915cc7ac0f8e ("RDMA/irdma: Add miscellaneous utility definitions")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/utils.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
+index b6c4ccf38eb78..e5e226b346211 100644
+--- a/drivers/infiniband/hw/irdma/utils.c
++++ b/drivers/infiniband/hw/irdma/utils.c
+@@ -2325,8 +2325,6 @@ void irdma_modify_qp_to_err(struct irdma_sc_qp *sc_qp)
+ struct irdma_qp *qp = sc_qp->qp_uk.back_qp;
+ struct ib_qp_attr attr;
+
+- if (qp->iwdev->rf->reset)
+- return;
+ attr.qp_state = IB_QPS_ERR;
+
+ if (rdma_protocol_roce(qp->ibqp.device, 1))
+--
+2.53.0
+
--- /dev/null
+From 33d0ea8a32f49318d2b5fbed6887f2baf4e0a8b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:46 -0500
+Subject: RDMA/irdma: Return EINVAL for invalid arp index error
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 7221f581eefa79ead06e171044f393fb7ee22f87 ]
+
+When rdma_connect() fails due to an invalid arp index, user space rdma core
+reports ENOMEM which is confusing. Modify irdma_make_cm_node() to return the
+correct error code.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index 128cfcf27714d..d14a381beb661 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -2241,11 +2241,12 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ int oldarpindex;
+ int arpindex;
+ struct net_device *netdev = iwdev->netdev;
++ int ret;
+
+ /* create an hte and cm_node for this instance */
+ cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
+ if (!cm_node)
+- return NULL;
++ return ERR_PTR(-ENOMEM);
+
+ /* set our node specific transport info */
+ cm_node->ipv4 = cm_info->ipv4;
+@@ -2348,8 +2349,10 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ arpindex = -EINVAL;
+ }
+
+- if (arpindex < 0)
++ if (arpindex < 0) {
++ ret = -EINVAL;
+ goto err;
++ }
+
+ ether_addr_copy(cm_node->rem_mac,
+ iwdev->rf->arp_table[arpindex].mac_addr);
+@@ -2360,7 +2363,7 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ err:
+ kfree(cm_node);
+
+- return NULL;
++ return ERR_PTR(ret);
+ }
+
+ static void irdma_destroy_connection(struct irdma_cm_node *cm_node)
+@@ -3021,8 +3024,8 @@ static int irdma_create_cm_node(struct irdma_cm_core *cm_core,
+
+ /* create a CM connection node */
+ cm_node = irdma_make_cm_node(cm_core, iwdev, cm_info, NULL);
+- if (!cm_node)
+- return -ENOMEM;
++ if (IS_ERR(cm_node))
++ return PTR_ERR(cm_node);
+
+ /* set our node side to client (active) side */
+ cm_node->tcp_cntxt.client = 1;
+@@ -3219,9 +3222,9 @@ void irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf)
+ cm_info.cm_id = listener->cm_id;
+ cm_node = irdma_make_cm_node(cm_core, iwdev, &cm_info,
+ listener);
+- if (!cm_node) {
++ if (IS_ERR(cm_node)) {
+ ibdev_dbg(&cm_core->iwdev->ibdev,
+- "CM: allocate node failed\n");
++ "CM: allocate node failed ret=%ld\n", PTR_ERR(cm_node));
+ refcount_dec(&listener->refcnt);
+ return;
+ }
+--
+2.53.0
+
--- /dev/null
+From eb76e4f767694bd70301af528e53eb701f270314 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:41 -0500
+Subject: RDMA/irdma: Update ibqp state to error if QP is already in error
+ state
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 8c1f19a2225cf37b3f8ab0b5a8a5322291cda620 ]
+
+In irdma_modify_qp() update ibqp state to error if the irdma QP is already
+in error state, otherwise the ibqp state which is visible to the consumer
+app remains stale.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index f53b8f0d7ca83..c2449f5721eeb 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1541,6 +1541,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+@@ -1746,6 +1747,7 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+--
+2.53.0
+
--- /dev/null
+From 38a99e6adb13fd595ab7df14aa769a49595adf57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Mar 2026 15:41:58 -0400
+Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 00da250c21b074ea9494c375d0117b69e5b1d0a4 ]
+
+When IOMMU passthrough mode is active, ib_dma_map_sgtable_attrs()
+produces no coalescing: each scatterlist page maps 1:1 to a DMA
+entry, so sgt.nents equals the raw page count. A 1 MB transfer
+yields 256 DMA entries. If that count exceeds the device's
+max_sgl_rd threshold (an optimization hint from mlx5 firmware),
+rdma_rw_io_needs_mr() steers the operation into the MR
+registration path. Each such operation consumes one or more MRs
+from a pool sized at max_rdma_ctxs -- roughly one MR per
+concurrent context. Under write-intensive workloads that issue
+many concurrent RDMA READs, the pool is rapidly exhausted,
+ib_mr_pool_get() returns NULL, and rdma_rw_init_one_mr() returns
+-EAGAIN. Upper layer protocols treat this as a fatal DMA mapping
+failure and tear down the connection.
+
+The max_sgl_rd check is a performance optimization, not a
+correctness requirement: the device can handle large SGE counts
+via direct posting, just less efficiently than with MR
+registration. When the MR pool cannot satisfy a request, falling
+back to the direct SGE (map_wrs) path avoids the connection
+reset while preserving the MR optimization for the common case
+where pool resources are available.
+
+Add a fallback in rdma_rw_ctx_init() so that -EAGAIN from
+rdma_rw_init_mr_wrs() triggers direct SGE posting instead of
+propagating the error. iWARP devices, which mandate MR
+registration for RDMA READs, and force_mr debug mode continue
+to treat -EAGAIN as terminal.
+
+Fixes: 00bd1439f464 ("RDMA/rw: Support threshold for registration vs scattering to local pages")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/rw.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
+index 2522ff1cc462c..49fbfe1cef689 100644
+--- a/drivers/infiniband/core/rw.c
++++ b/drivers/infiniband/core/rw.c
+@@ -326,14 +326,29 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u32 port_num,
+ if (rdma_rw_io_needs_mr(qp->device, port_num, dir, sg_cnt)) {
+ ret = rdma_rw_init_mr_wrs(ctx, qp, port_num, sg, sg_cnt,
+ sg_offset, remote_addr, rkey, dir);
+- } else if (sg_cnt > 1) {
++ /*
++ * If MR init succeeded or failed for a reason other
++ * than pool exhaustion, that result is final.
++ *
++ * Pool exhaustion (-EAGAIN) from the max_sgl_rd
++ * optimization is recoverable: fall back to
++ * direct SGE posting. iWARP and force_mr require
++ * MRs unconditionally, so -EAGAIN is terminal.
++ */
++ if (ret != -EAGAIN ||
++ rdma_protocol_iwarp(qp->device, port_num) ||
++ unlikely(rdma_rw_force_mr))
++ goto out;
++ }
++
++ if (sg_cnt > 1)
+ ret = rdma_rw_init_map_wrs(ctx, qp, sg, sg_cnt, sg_offset,
+ remote_addr, rkey, dir);
+- } else {
++ else
+ ret = rdma_rw_init_single_wr(ctx, qp, sg, sg_offset,
+ remote_addr, rkey, dir);
+- }
+
++out:
+ if (ret < 0)
+ goto out_unmap_sg;
+ return ret;
+--
+2.53.0
+
--- /dev/null
+From 434de1fc8025634c8f07e924f02efc9c38b383a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Mar 2026 19:43:31 +0100
+Subject: regmap: Synchronize cache for the page selector
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 09e70e4f119ff650d24c96161fd2f62ac7e424b0 ]
+
+If the selector register is represented in each page, its value
+according to the debugfs is stale because it gets synchronized
+only after the real page switch happens. Hence the regmap cache
+initialisation from the HW inherits outdated data in the selector
+register.
+
+Synchronize cache for the page selector just in time.
+
+Before (offset followed by hexdump, the first byte is selector):
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 05 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 01 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 02 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 03 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 04 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+After:
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 01 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 02 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 03 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 04 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+Fixes: 6863ca622759 ("regmap: Add support for register indirect addressing.")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap.c | 30 ++++++++++++++++++++++++++----
+ 1 file changed, 26 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index ae2215d4e61c3..a648218507236 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -1543,6 +1543,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ unsigned int val_num)
+ {
+ void *orig_work_buf;
++ unsigned int selector_reg;
+ unsigned int win_offset;
+ unsigned int win_page;
+ bool page_chg;
+@@ -1561,10 +1562,31 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ return -EINVAL;
+ }
+
+- /* It is possible to have selector register inside data window.
+- In that case, selector register is located on every page and
+- it needs no page switching, when accessed alone. */
++ /*
++ * Calculate the address of the selector register in the corresponding
++ * data window if it is located on every page.
++ */
++ page_chg = in_range(range->selector_reg, range->window_start, range->window_len);
++ if (page_chg)
++ selector_reg = range->range_min + win_page * range->window_len +
++ range->selector_reg - range->window_start;
++
++ /*
++ * It is possible to have selector register inside data window.
++ * In that case, selector register is located on every page and it
++ * needs no page switching, when accessed alone.
++ *
++ * Nevertheless we should synchronize the cache values for it.
++ * This can't be properly achieved if the selector register is
++ * the first and the only one to be read inside the data window.
++ * That's why we update it in that case as well.
++ *
++ * However, we specifically avoid updating it for the default page,
++ * when it's overlapped with the real data window, to prevent from
++ * infinite looping.
++ */
+ if (val_num > 1 ||
++ (page_chg && selector_reg != range->selector_reg) ||
+ range->window_start + win_offset != range->selector_reg) {
+ /* Use separate work_buf during page switching */
+ orig_work_buf = map->work_buf;
+@@ -1573,7 +1595,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ ret = _regmap_update_bits(map, range->selector_reg,
+ range->selector_mask,
+ win_page << range->selector_shift,
+- &page_chg, false);
++ NULL, false);
+
+ map->work_buf = orig_work_buf;
+
+--
+2.53.0
+
--- /dev/null
+From c648df1acf48a1c06e9b444803ae6826c9bbbed6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 10:49:59 +0000
+Subject: rust: regulator: do not assume that regulator_get() returns non-null
+
+From: Alice Ryhl <aliceryhl@google.com>
+
+[ Upstream commit 8121353a4bf8e38afee26299419a78ec108e14a6 ]
+
+The Rust `Regulator` abstraction uses `NonNull` to wrap the underlying
+`struct regulator` pointer. When `CONFIG_REGULATOR` is disabled, the C
+stub for `regulator_get` returns `NULL`. `from_err_ptr` does not treat
+`NULL` as an error, so it was passed to `NonNull::new_unchecked`,
+causing undefined behavior.
+
+Fix this by using a raw pointer `*mut bindings::regulator` instead of
+`NonNull`. This allows `inner` to be `NULL` when `CONFIG_REGULATOR` is
+disabled, and leverages the C stubs which are designed to handle `NULL`
+or are no-ops.
+
+Fixes: 9b614ceada7c ("rust: regulator: add a bare minimum regulator abstraction")
+Reported-by: Miguel Ojeda <ojeda@kernel.org>
+Closes: https://lore.kernel.org/r/20260322193830.89324-1-ojeda@kernel.org
+Signed-off-by: Alice Ryhl <aliceryhl@google.com>
+Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
+Link: https://patch.msgid.link/20260324-regulator-fix-v1-1-a5244afa3c15@google.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ rust/kernel/regulator.rs | 33 ++++++++++++++++++---------------
+ 1 file changed, 18 insertions(+), 15 deletions(-)
+
+diff --git a/rust/kernel/regulator.rs b/rust/kernel/regulator.rs
+index b55a201e5029f..09c8263043bc7 100644
+--- a/rust/kernel/regulator.rs
++++ b/rust/kernel/regulator.rs
+@@ -23,7 +23,10 @@ use crate::{
+ prelude::*,
+ };
+
+-use core::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull};
++use core::{
++ marker::PhantomData,
++ mem::ManuallyDrop, //
++};
+
+ mod private {
+ pub trait Sealed {}
+@@ -230,15 +233,17 @@ pub fn devm_enable_optional(dev: &Device<Bound>, name: &CStr) -> Result {
+ ///
+ /// # Invariants
+ ///
+-/// - `inner` is a non-null wrapper over a pointer to a `struct
+-/// regulator` obtained from [`regulator_get()`].
++/// - `inner` is a pointer obtained from a successful call to
++/// [`regulator_get()`]. It is treated as an opaque token that may only be
++/// accessed using C API methods (e.g., it may be `NULL` if the C API returns
++/// `NULL`).
+ ///
+ /// [`regulator_get()`]: https://docs.kernel.org/driver-api/regulator.html#c.regulator_get
+ pub struct Regulator<State>
+ where
+ State: RegulatorState,
+ {
+- inner: NonNull<bindings::regulator>,
++ inner: *mut bindings::regulator,
+ _phantom: PhantomData<State>,
+ }
+
+@@ -250,7 +255,7 @@ impl<T: RegulatorState> Regulator<T> {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+ to_result(unsafe {
+ bindings::regulator_set_voltage(
+- self.inner.as_ptr(),
++ self.inner,
+ min_voltage.as_microvolts(),
+ max_voltage.as_microvolts(),
+ )
+@@ -260,7 +265,7 @@ impl<T: RegulatorState> Regulator<T> {
+ /// Gets the current voltage of the regulator.
+ pub fn get_voltage(&self) -> Result<Voltage> {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+- let voltage = unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) };
++ let voltage = unsafe { bindings::regulator_get_voltage(self.inner) };
+
+ to_result(voltage).map(|()| Voltage::from_microvolts(voltage))
+ }
+@@ -270,10 +275,8 @@ impl<T: RegulatorState> Regulator<T> {
+ // received from the C code.
+ let inner = from_err_ptr(unsafe { bindings::regulator_get(dev.as_raw(), name.as_ptr()) })?;
+
+- // SAFETY: We can safely trust `inner` to be a pointer to a valid
+- // regulator if `ERR_PTR` was not returned.
+- let inner = unsafe { NonNull::new_unchecked(inner) };
+-
++ // INVARIANT: `inner` is a pointer obtained from `regulator_get()`, and
++ // the call was successful.
+ Ok(Self {
+ inner,
+ _phantom: PhantomData,
+@@ -282,12 +285,12 @@ impl<T: RegulatorState> Regulator<T> {
+
+ fn enable_internal(&self) -> Result {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+- to_result(unsafe { bindings::regulator_enable(self.inner.as_ptr()) })
++ to_result(unsafe { bindings::regulator_enable(self.inner) })
+ }
+
+ fn disable_internal(&self) -> Result {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+- to_result(unsafe { bindings::regulator_disable(self.inner.as_ptr()) })
++ to_result(unsafe { bindings::regulator_disable(self.inner) })
+ }
+ }
+
+@@ -349,7 +352,7 @@ impl<T: IsEnabled> Regulator<T> {
+ /// Checks if the regulator is enabled.
+ pub fn is_enabled(&self) -> bool {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+- unsafe { bindings::regulator_is_enabled(self.inner.as_ptr()) != 0 }
++ unsafe { bindings::regulator_is_enabled(self.inner) != 0 }
+ }
+ }
+
+@@ -359,11 +362,11 @@ impl<T: RegulatorState> Drop for Regulator<T> {
+ // SAFETY: By the type invariants, we know that `self` owns a
+ // reference on the enabled refcount, so it is safe to relinquish it
+ // now.
+- unsafe { bindings::regulator_disable(self.inner.as_ptr()) };
++ unsafe { bindings::regulator_disable(self.inner) };
+ }
+ // SAFETY: By the type invariants, we know that `self` owns a reference,
+ // so it is safe to relinquish it now.
+- unsafe { bindings::regulator_put(self.inner.as_ptr()) };
++ unsafe { bindings::regulator_put(self.inner) };
+ }
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 9dc42b707dacf13f1a30da16ec23012723914743 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 14:31:47 +0800
+Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue
+
+From: Yihang Li <liyihang9@huawei.com>
+
+[ Upstream commit d71afa9deb4d413232ba16d693f7d43b321931b4 ]
+
+After commit 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard
+and multi-channel scans"), if the device supports multiple channels (0 to
+shost->max_channel), user_scan() invokes updated sas_user_scan() to perform
+the scan behavior for a specific transfer. However, when the user
+specifies shost->max_channel, it will return -EINVAL, which is not
+expected.
+
+Fix and support specifying the scan shost->max_channel for scanning.
+
+Fixes: 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans")
+Signed-off-by: Yihang Li <liyihang9@huawei.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_sas.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index d69c7c444a311..081c168094374 100644
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -1734,7 +1734,7 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ break;
+
+ default:
+- if (channel < shost->max_channel) {
++ if (channel <= shost->max_channel) {
+ res = scsi_scan_host_selected(shost, channel, id, lun,
+ SCSI_SCAN_MANUAL);
+ } else {
+--
+2.53.0
+
netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch
netfilter-ctnetlink-use-netlink-policy-range-checks.patch
net-macb-use-the-current-queue-number-for-stats.patch
+rdma-efa-check-stored-completion-ctx-command-id-with.patch
+rdma-efa-improve-admin-completion-context-state-mach.patch
+rdma-efa-fix-use-of-completion-ctx-after-free.patch
+regmap-synchronize-cache-for-the-page-selector.patch
+alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch
+rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch
+rdma-efa-fix-possible-deadlock.patch
+alsa-usb-audio-exclude-scarlett-2i2-1st-gen-from-ski.patch
+rdma-irdma-initialize-free_qp-completion-before-usin.patch
+rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch
+rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch
+rdma-irdma-clean-up-unnecessary-dereference-of-event.patch
+rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch
+rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch
+rdma-irdma-return-einval-for-invalid-arp-index-error.patch
+rdma-irdma-harden-depth-calculation-functions.patch
+asoc-fsl-imx-card-initialize-playback_only-and-captu.patch
+scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch
+x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch
+drm-mediatek-dsi-store-driver-data-before-invoking-m.patch
+drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch
+pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch
+pm-sleep-drop-spurious-warn_on-from-pm_restore_gfp_m.patch
+spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch
+asoc-intel-catpt-fix-the-device-initialization.patch
+spi-meson-spicc-fix-double-put-in-remove-path.patch
+drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch
+asoc-dt-bindings-stm32-fix-incorrect-compatible-stri.patch
+rust-regulator-do-not-assume-that-regulator_get-retu.patch
+drm-xe-implement-recent-spec-updates-to-wa_160252501.patch
+spi-use-generic-driver_override-infrastructure.patch
+acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch
+drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch
+hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch
+hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch
+hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch
+hwmon-pmbus-core-protect-regulator-operations-with-m.patch
+sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch
+asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch
+asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch
+spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch
+alsa-usb-audio-exclude-scarlett-2i4-1st-gen-from-ski.patch
--- /dev/null
+From 7ad4a51ddfd09fb153afff7dedde1c5bc9b6b374 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Mar 2026 21:29:56 +0800
+Subject: spi: meson-spicc: Fix double-put in remove path
+
+From: Felix Gu <ustc.gu@gmail.com>
+
+[ Upstream commit 63542bb402b7013171c9f621c28b609eda4dbf1f ]
+
+meson_spicc_probe() registers the controller with
+devm_spi_register_controller(), so teardown already drops the
+controller reference via devm cleanup.
+
+Calling spi_controller_put() again in meson_spicc_remove()
+causes a double-put.
+
+Fixes: 8311ee2164c5 ("spi: meson-spicc: fix memory leak in meson_spicc_remove")
+Signed-off-by: Felix Gu <ustc.gu@gmail.com>
+Reviewed-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260322-rockchip-v1-1-fac3f0c6dad8@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-meson-spicc.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
+index 6b91373075334..c99fab392add1 100644
+--- a/drivers/spi/spi-meson-spicc.c
++++ b/drivers/spi/spi-meson-spicc.c
+@@ -1102,8 +1102,6 @@ static void meson_spicc_remove(struct platform_device *pdev)
+
+ /* Disable SPI */
+ writel(0, spicc->base + SPICC_CONREG);
+-
+- spi_controller_put(spicc->host);
+ }
+
+ static const struct meson_spicc_data meson_spicc_gx_data = {
+--
+2.53.0
+
--- /dev/null
+From cf898b4456788e78bdc8d1cb6a6d2e943d0cadfd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 00:12:34 +0800
+Subject: spi: sn-f-ospi: Fix resource leak in f_ospi_probe()
+
+From: Felix Gu <ustc.gu@gmail.com>
+
+[ Upstream commit ef3d549e1deb3466c61f3b01d22fc3fe3e5efb08 ]
+
+In f_ospi_probe(), when num_cs validation fails, it returns without
+calling spi_controller_put() on the SPI controller, which causes a
+resource leak.
+
+Use devm_spi_alloc_host() instead of spi_alloc_host() to ensure the
+SPI controller is properly freed when probe fails.
+
+Fixes: 1b74dd64c861 ("spi: Add Socionext F_OSPI SPI flash controller driver")
+Signed-off-by: Felix Gu <ustc.gu@gmail.com>
+Link: https://patch.msgid.link/20260319-sn-f-v1-1-33a6738d2da8@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-sn-f-ospi.c | 17 +++++------------
+ 1 file changed, 5 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c
+index c4969f66a0ba9..84a5b327022e8 100644
+--- a/drivers/spi/spi-sn-f-ospi.c
++++ b/drivers/spi/spi-sn-f-ospi.c
+@@ -612,7 +612,7 @@ static int f_ospi_probe(struct platform_device *pdev)
+ u32 num_cs = OSPI_NUM_CS;
+ int ret;
+
+- ctlr = spi_alloc_host(dev, sizeof(*ospi));
++ ctlr = devm_spi_alloc_host(dev, sizeof(*ospi));
+ if (!ctlr)
+ return -ENOMEM;
+
+@@ -636,16 +636,12 @@ static int f_ospi_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, ospi);
+
+ ospi->base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(ospi->base)) {
+- ret = PTR_ERR(ospi->base);
+- goto err_put_ctlr;
+- }
++ if (IS_ERR(ospi->base))
++ return PTR_ERR(ospi->base);
+
+ ospi->clk = devm_clk_get_enabled(dev, NULL);
+- if (IS_ERR(ospi->clk)) {
+- ret = PTR_ERR(ospi->clk);
+- goto err_put_ctlr;
+- }
++ if (IS_ERR(ospi->clk))
++ return PTR_ERR(ospi->clk);
+
+ mutex_init(&ospi->mlock);
+
+@@ -662,9 +658,6 @@ static int f_ospi_probe(struct platform_device *pdev)
+ err_destroy_mutex:
+ mutex_destroy(&ospi->mlock);
+
+-err_put_ctlr:
+- spi_controller_put(ctlr);
+-
+ return ret;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 25c293a7f9d068d8981226950de030899241803b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 19:38:12 +0100
+Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF)
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b341c1176f2e001b3adf0b47154fc31589f7410e ]
+
+There is a teardown order issue in the driver. The SPI controller is
+registered using devm_spi_register_controller(), which delays
+unregistration of the SPI controller until after the fsl_lpspi_remove()
+function returns.
+
+As the fsl_lpspi_remove() function synchronously tears down the DMA
+channels, a running SPI transfer triggers the following NULL pointer
+dereference due to use after free:
+
+| fsl_lpspi 42550000.spi: I/O Error in DMA RX
+| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
+[...]
+| Call trace:
+| fsl_lpspi_dma_transfer+0x260/0x340 [spi_fsl_lpspi]
+| fsl_lpspi_transfer_one+0x198/0x448 [spi_fsl_lpspi]
+| spi_transfer_one_message+0x49c/0x7c8
+| __spi_pump_transfer_message+0x120/0x420
+| __spi_sync+0x2c4/0x520
+| spi_sync+0x34/0x60
+| spidev_message+0x20c/0x378 [spidev]
+| spidev_ioctl+0x398/0x750 [spidev]
+[...]
+
+Switch from devm_spi_register_controller() to spi_register_controller() in
+fsl_lpspi_probe() and add the corresponding spi_unregister_controller() in
+fsl_lpspi_remove().
+
+Fixes: 5314987de5e5 ("spi: imx: add lpspi bus driver")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-fsl-lpspi.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
+index 065456aba2aea..47d372557e4f6 100644
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -972,7 +972,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+ enable_irq(irq);
+ }
+
+- ret = devm_spi_register_controller(&pdev->dev, controller);
++ ret = spi_register_controller(controller);
+ if (ret < 0) {
+ dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
+ goto free_dma;
+@@ -998,6 +998,7 @@ static void fsl_lpspi_remove(struct platform_device *pdev)
+ struct fsl_lpspi_data *fsl_lpspi =
+ spi_controller_get_devdata(controller);
+
++ spi_unregister_controller(controller);
+ fsl_lpspi_dma_exit(controller);
+
+ pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
+--
+2.53.0
+
--- /dev/null
+From a536c73898d2fb2cdeeb2af83db75af3b69d6de9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 01:59:15 +0100
+Subject: spi: use generic driver_override infrastructure
+
+From: Danilo Krummrich <dakr@kernel.org>
+
+[ Upstream commit cc34d77dd48708d810c12bfd6f5bf03304f6c824 ]
+
+When a driver is probed through __driver_attach(), the bus' match()
+callback is called without the device lock held, thus accessing the
+driver_override field without a lock, which can cause a UAF.
+
+Fix this by using the driver-core driver_override infrastructure taking
+care of proper locking internally.
+
+Note that calling match() from __driver_attach() without the device lock
+held is intentional. [1]
+
+Also note that we do not enable the driver_override feature of struct
+bus_type, as SPI - in contrast to most other buses - passes "" to
+sysfs_emit() when the driver_override pointer is NULL. Thus, printing
+"\n" instead of "(null)\n".
+
+Link: https://lore.kernel.org/driver-core/DGRGTIRHA62X.3RY09D9SOK77P@kernel.org/ [1]
+Reported-by: Gui-Dong Han <hanguidong02@gmail.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789
+Fixes: 5039563e7c25 ("spi: Add driver_override SPI device attribute")
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Link: https://patch.msgid.link/20260324005919.2408620-12-dakr@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi.c | 19 +++++++------------
+ include/linux/spi/spi.h | 5 -----
+ 2 files changed, 7 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 201b9569ce690..87d829d2a8427 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -50,7 +50,6 @@ static void spidev_release(struct device *dev)
+ struct spi_device *spi = to_spi_device(dev);
+
+ spi_controller_put(spi->controller);
+- kfree(spi->driver_override);
+ free_percpu(spi->pcpu_statistics);
+ kfree(spi);
+ }
+@@ -73,10 +72,9 @@ static ssize_t driver_override_store(struct device *dev,
+ struct device_attribute *a,
+ const char *buf, size_t count)
+ {
+- struct spi_device *spi = to_spi_device(dev);
+ int ret;
+
+- ret = driver_set_override(dev, &spi->driver_override, buf, count);
++ ret = __device_set_driver_override(dev, buf, count);
+ if (ret)
+ return ret;
+
+@@ -86,13 +84,8 @@ static ssize_t driver_override_store(struct device *dev,
+ static ssize_t driver_override_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+ {
+- const struct spi_device *spi = to_spi_device(dev);
+- ssize_t len;
+-
+- device_lock(dev);
+- len = sysfs_emit(buf, "%s\n", spi->driver_override ? : "");
+- device_unlock(dev);
+- return len;
++ guard(spinlock)(&dev->driver_override.lock);
++ return sysfs_emit(buf, "%s\n", dev->driver_override.name ?: "");
+ }
+ static DEVICE_ATTR_RW(driver_override);
+
+@@ -376,10 +369,12 @@ static int spi_match_device(struct device *dev, const struct device_driver *drv)
+ {
+ const struct spi_device *spi = to_spi_device(dev);
+ const struct spi_driver *sdrv = to_spi_driver(drv);
++ int ret;
+
+ /* Check override first, and if set, only use the named driver */
+- if (spi->driver_override)
+- return strcmp(spi->driver_override, drv->name) == 0;
++ ret = device_match_driver_override(dev, drv);
++ if (ret >= 0)
++ return ret;
+
+ /* Attempt an OF style match */
+ if (of_driver_match_device(dev, drv))
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index cb2c2df310899..fe9dd430cc03a 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -156,10 +156,6 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
+ * @modalias: Name of the driver to use with this device, or an alias
+ * for that name. This appears in the sysfs "modalias" attribute
+ * for driver coldplugging, and in uevents used for hotplugging
+- * @driver_override: If the name of a driver is written to this attribute, then
+- * the device will bind to the named driver and only the named driver.
+- * Do not set directly, because core frees it; use driver_set_override() to
+- * set or clear it.
+ * @pcpu_statistics: statistics for the spi_device
+ * @word_delay: delay to be inserted between consecutive
+ * words of a transfer
+@@ -217,7 +213,6 @@ struct spi_device {
+ void *controller_state;
+ void *controller_data;
+ char modalias[SPI_NAME_SIZE];
+- const char *driver_override;
+
+ /* The statistics */
+ struct spi_statistics __percpu *pcpu_statistics;
+--
+2.53.0
+
--- /dev/null
+From a4ebda3c7616231b3bc396ae62fb4ff21e7eb200 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 23:29:50 +0100
+Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap
+
+From: Marc Buerg <buermarc@googlemail.com>
+
+[ Upstream commit f63a9df7e3f9f842945d292a19d9938924f066f9 ]
+
+proc_do_large_bitmap() does not initialize variable c, which is expected
+to be set to a trailing character by proc_get_long().
+
+However, proc_get_long() only sets c when the input buffer contains a
+trailing character after the parsed value.
+
+If c is not initialized it may happen to contain a '-'. If this is the
+case proc_do_large_bitmap() expects to be able to parse a second part of
+the input buffer. If there is no second part an unjustified -EINVAL will
+be returned.
+
+Initialize c to 0 to prevent returning -EINVAL on valid input.
+
+Fixes: 9f977fb7ae9d ("sysctl: add proc_do_large_bitmap")
+Signed-off-by: Marc Buerg <buermarc@googlemail.com>
+Reviewed-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sysctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index cb6196e3fa993..970525e6c76c7 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1213,7 +1213,7 @@ int proc_do_large_bitmap(const struct ctl_table *table, int write,
+ unsigned long bitmap_len = table->maxlen;
+ unsigned long *bitmap = *(unsigned long **) table->data;
+ unsigned long *tmp_bitmap = NULL;
+- char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
++ char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c = 0;
+
+ if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
+ *lenp = 0;
+--
+2.53.0
+
--- /dev/null
+From 6cf7d315ace71bb2a7a8d0d99c86504fa54ce315 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 15:59:48 +0200
+Subject: x86/efi: efi_unmap_boot_services: fix calculation of ranges_to_free
+ size
+
+From: Mike Rapoport (Microsoft) <rppt@kernel.org>
+
+[ Upstream commit 217c0a5c177a3d4f7c8497950cbf5c36756e8bbb ]
+
+ranges_to_free array should have enough room to store the entire EFI
+memmap plus an extra element for NULL entry.
+The calculation of this array size wrongly adds 1 to the overall size
+instead of adding 1 to the number of elements.
+
+Add parentheses to properly size the array.
+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory")
+Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/platform/efi/quirks.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
+index 35caa5746115d..79f0818131e83 100644
+--- a/arch/x86/platform/efi/quirks.c
++++ b/arch/x86/platform/efi/quirks.c
+@@ -424,7 +424,7 @@ void __init efi_unmap_boot_services(void)
+ if (efi_enabled(EFI_DBG))
+ return;
+
+- sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;
++ sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1);
+ ranges_to_free = kzalloc(sz, GFP_KERNEL);
+ if (!ranges_to_free) {
+ pr_err("Failed to allocate storage for freeable EFI regions\n");
+--
+2.53.0
+
--- /dev/null
+From 94b23ea098caf029cedc4f2a7c0e4e56aa7398fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 00:54:59 +0800
+Subject: ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f6484cadbcaf26b5844b51bd7307a663dda48ef6 ]
+
+When ec_install_handlers() returns -EPROBE_DEFER on reduced-hardware
+platforms, it has already started the EC and installed the address
+space handler with the struct acpi_ec pointer as handler context.
+However, acpi_ec_setup() propagates the error without any cleanup.
+
+The caller acpi_ec_add() then frees the struct acpi_ec for non-boot
+instances, leaving a dangling handler context in ACPICA.
+
+Any subsequent AML evaluation that accesses an EC OpRegion field
+dispatches into acpi_ec_space_handler() with the freed pointer,
+causing a use-after-free:
+
+ BUG: KASAN: slab-use-after-free in mutex_lock (kernel/locking/mutex.c:289)
+ Write of size 8 at addr ffff88800721de38 by task init/1
+ Call Trace:
+ <TASK>
+ mutex_lock (kernel/locking/mutex.c:289)
+ acpi_ec_space_handler (drivers/acpi/ec.c:1362)
+ acpi_ev_address_space_dispatch (drivers/acpi/acpica/evregion.c:293)
+ acpi_ex_access_region (drivers/acpi/acpica/exfldio.c:246)
+ acpi_ex_field_datum_io (drivers/acpi/acpica/exfldio.c:509)
+ acpi_ex_extract_from_field (drivers/acpi/acpica/exfldio.c:700)
+ acpi_ex_read_data_from_field (drivers/acpi/acpica/exfield.c:327)
+ acpi_ex_resolve_node_to_value (drivers/acpi/acpica/exresolv.c:392)
+ </TASK>
+
+ Allocated by task 1:
+ acpi_ec_alloc (drivers/acpi/ec.c:1424)
+ acpi_ec_add (drivers/acpi/ec.c:1692)
+
+ Freed by task 1:
+ kfree (mm/slub.c:6876)
+ acpi_ec_add (drivers/acpi/ec.c:1751)
+
+The bug triggers on reduced-hardware EC platforms (ec->gpe < 0)
+when the GPIO IRQ provider defers probing. Once the stale handler
+exists, any unprivileged sysfs read that causes AML to touch an
+EC OpRegion (battery, thermal, backlight) exercises the dangling
+pointer.
+
+Fix this by calling ec_remove_handlers() in the error path of
+acpi_ec_setup() before clearing first_ec. ec_remove_handlers()
+checks each EC_FLAGS_* bit before acting, so it is safe to call
+regardless of how far ec_install_handlers() progressed:
+
+ -ENODEV (handler not installed): only calls acpi_ec_stop()
+ -EPROBE_DEFER (handler installed): removes handler, stops EC
+
+Fixes: 03e9a0e05739 ("ACPI: EC: Consolidate event handler installation code")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 59b3d50ff01ec..c981a53434edf 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1655,6 +1655,8 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+
+ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret) {
++ ec_remove_handlers(ec);
++
+ if (ec == first_ec)
+ first_ec = NULL;
+
+--
+2.53.0
+
--- /dev/null
+From 994bb193d19046fa067fb87e218c4eb1b5fbbd32 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 15 Mar 2026 20:11:27 +0000
+Subject: ALSA: hda/realtek: Sequence GPIO2 on Star Labs StarFighter
+
+From: Sean Rhodes <sean@starlabs.systems>
+
+[ Upstream commit a6919f2a01f8fbf807b015e5b26aecae7db8117b ]
+
+The initial StarFighter quirk fixed the runtime suspend pop by muting
+speakers in the shutup callback before power-down. Further hardware
+validation showed that the speaker path is controlled directly by LINE2
+EAPD on NID 0x1b together with GPIO2 for the external amplifier.
+
+Replace the shutup-delay workaround with explicit sequencing of those
+controls at playback start and stop:
+- assert LINE2 EAPD and drive GPIO2 high on PREPARE
+- deassert LINE2 EAPD and drive GPIO2 low on CLEANUP
+
+This avoids the runtime suspend pop without a sleep, and also fixes pops
+around G3 entry and display-manager start that the original workaround
+did not cover.
+
+Fixes: 1cb3c20688fc ("ALSA: hda/realtek: Fix speaker pop on Star Labs StarFighter")
+Tested-by: Sean Rhodes <sean@starlabs.systems>
+Signed-off-by: Sean Rhodes <sean@starlabs.systems>
+Link: https://patch.msgid.link/20260315201127.33744-1-sean@starlabs.systems
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/hda/codecs/realtek/alc269.c | 38 ++++++++++++++++++++++++++-----
+ 1 file changed, 32 insertions(+), 6 deletions(-)
+
+diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
+index ab4b22fcb72ed..eba7afef302f7 100644
+--- a/sound/hda/codecs/realtek/alc269.c
++++ b/sound/hda/codecs/realtek/alc269.c
+@@ -1017,12 +1017,30 @@ static int alc269_resume(struct hda_codec *codec)
+ return 0;
+ }
+
+-#define STARLABS_STARFIGHTER_SHUTUP_DELAY_MS 30
++#define ALC233_STARFIGHTER_SPK_PIN 0x1b
++#define ALC233_STARFIGHTER_GPIO2 0x04
+
+-static void starlabs_starfighter_shutup(struct hda_codec *codec)
++static void alc233_starfighter_update_amp(struct hda_codec *codec, bool on)
+ {
+- if (snd_hda_gen_shutup_speakers(codec))
+- msleep(STARLABS_STARFIGHTER_SHUTUP_DELAY_MS);
++ snd_hda_codec_write(codec, ALC233_STARFIGHTER_SPK_PIN, 0,
++ AC_VERB_SET_EAPD_BTLENABLE,
++ on ? AC_EAPDBTL_EAPD : 0);
++ alc_update_gpio_data(codec, ALC233_STARFIGHTER_GPIO2, on);
++}
++
++static void alc233_starfighter_pcm_hook(struct hda_pcm_stream *hinfo,
++ struct hda_codec *codec,
++ struct snd_pcm_substream *substream,
++ int action)
++{
++ switch (action) {
++ case HDA_GEN_PCM_ACT_PREPARE:
++ alc233_starfighter_update_amp(codec, true);
++ break;
++ case HDA_GEN_PCM_ACT_CLEANUP:
++ alc233_starfighter_update_amp(codec, false);
++ break;
++ }
+ }
+
+ static void alc233_fixup_starlabs_starfighter(struct hda_codec *codec,
+@@ -1031,8 +1049,16 @@ static void alc233_fixup_starlabs_starfighter(struct hda_codec *codec,
+ {
+ struct alc_spec *spec = codec->spec;
+
+- if (action == HDA_FIXUP_ACT_PRE_PROBE)
+- spec->shutup = starlabs_starfighter_shutup;
++ switch (action) {
++ case HDA_FIXUP_ACT_PRE_PROBE:
++ spec->gpio_mask |= ALC233_STARFIGHTER_GPIO2;
++ spec->gpio_dir |= ALC233_STARFIGHTER_GPIO2;
++ spec->gpio_data &= ~ALC233_STARFIGHTER_GPIO2;
++ break;
++ case HDA_FIXUP_ACT_PROBE:
++ spec->gen.pcm_playback_hook = alc233_starfighter_pcm_hook;
++ break;
++ }
+ }
+
+ static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec,
+--
+2.53.0
+
--- /dev/null
+From ed06a1487879e6651697140a9c07a882c5e57092 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Mar 2026 06:02:30 +1030
+Subject: ALSA: usb-audio: Exclude Scarlett 2i2 1st Gen from SKIP_IFACE_SETUP
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit 8780f561f6717dec52351251881bff79e960eb46 ]
+
+The Focusrite Scarlett 2i2 1st Gen (1235:8006) produces
+distorted/silent audio when QUIRK_FLAG_SKIP_IFACE_SETUP is active, as
+that flag causes the feedback format to be detected as 17.15 instead
+of 16.16.
+
+Add a DEVICE_FLG entry for this device before the Focusrite VENDOR_FLG
+entry so that it gets no quirk flags, overriding the vendor-wide
+SKIP_IFACE_SETUP. This device doesn't have the internal mixer, Air, or
+Safe modes that the quirk was designed to protect.
+
+Fixes: 38c322068a26 ("ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP")
+Reported-by: pairomaniac [https://github.com/geoffreybennett/linux-fcp/issues/54]
+Tested-by: pairomaniac [https://github.com/geoffreybennett/linux-fcp/issues/54]
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://patch.msgid.link/abmsTjKmQMKbhYtK@m.b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index d87b988516bbf..461d7d254e378 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2425,6 +2425,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY),
+ VENDOR_FLG(0x07fd, /* MOTU */
+ QUIRK_FLAG_VALIDATE_RATES),
++ DEVICE_FLG(0x1235, 0x8006, 0), /* Focusrite Scarlett 2i2 1st Gen */
+ VENDOR_FLG(0x1235, /* Focusrite Novation */
+ QUIRK_FLAG_SKIP_IFACE_SETUP),
+ VENDOR_FLG(0x1511, /* AURALiC */
+--
+2.53.0
+
--- /dev/null
+From 6ab6ea309c71de56e5bf49c0e1a7dcf8b8f953b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Mar 2026 21:59:21 +1030
+Subject: ALSA: usb-audio: Exclude Scarlett 2i4 1st Gen from SKIP_IFACE_SETUP
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit 990a8b0732cf899d4a0f847b0a67efeb9a384c82 ]
+
+Same issue that the Scarlett 2i2 1st Gen had:
+QUIRK_FLAG_SKIP_IFACE_SETUP causes distorted/flanging audio on the
+Scarlett 2i4 1st Gen (1235:800a).
+
+Fixes: 38c322068a26 ("ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP")
+Reported-by: dcferreira [https://github.com/geoffreybennett/linux-fcp/issues/54]
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://patch.msgid.link/acEkEbftzyNe8W7C@m.b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 461d7d254e378..09ed935107580 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2426,6 +2426,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ VENDOR_FLG(0x07fd, /* MOTU */
+ QUIRK_FLAG_VALIDATE_RATES),
+ DEVICE_FLG(0x1235, 0x8006, 0), /* Focusrite Scarlett 2i2 1st Gen */
++ DEVICE_FLG(0x1235, 0x800a, 0), /* Focusrite Scarlett 2i4 1st Gen */
+ VENDOR_FLG(0x1235, /* Focusrite Novation */
+ QUIRK_FLAG_SKIP_IFACE_SETUP),
+ VENDOR_FLG(0x1511, /* AURALiC */
+--
+2.53.0
+
--- /dev/null
+From 4386ef16c04ea6ef9dd50339a4fa762307fa3507 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:04 +0100
+Subject: ASoC: adau1372: Fix clock leak on PLL lock failure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit bfe6a264effcb6fe99ad7ceaf9e8c7439fc9555b ]
+
+adau1372_enable_pll() was a void function that logged a dev_err() on
+PLL lock timeout but did not propagate the error. As a result,
+adau1372_set_power() would continue with adau1372->enabled set to true
+despite the PLL being unlocked, and the mclk left enabled with no
+corresponding disable on the error path.
+
+Convert adau1372_enable_pll() to return int, using -ETIMEDOUT on lock
+timeout and propagating regmap errors directly. In adau1372_set_power(),
+check the return value and unwind in reverse order: restore regcache to
+cache-only mode, reassert GPIO power-down, and disable the clock before
+returning the error.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index 6345342218d61..d7363f9d53bb3 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -762,7 +762,7 @@ static int adau1372_startup(struct snd_pcm_substream *substream, struct snd_soc_
+ return 0;
+ }
+
+-static void adau1372_enable_pll(struct adau1372 *adau1372)
++static int adau1372_enable_pll(struct adau1372 *adau1372)
+ {
+ unsigned int val, timeout = 0;
+ int ret;
+@@ -778,8 +778,12 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ timeout++;
+ } while (!(val & 1) && timeout < 3);
+
+- if (ret < 0 || !(val & 1))
++ if (ret < 0 || !(val & 1)) {
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
++ return ret < 0 ? ret : -ETIMEDOUT;
++ }
++
++ return 0;
+ }
+
+ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+@@ -807,7 +811,14 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ * accessed.
+ */
+ if (adau1372->use_pll) {
+- adau1372_enable_pll(adau1372);
++ ret = adau1372_enable_pll(adau1372);
++ if (ret) {
++ regcache_cache_only(adau1372->regmap, true);
++ if (adau1372->pd_gpio)
++ gpiod_set_value(adau1372->pd_gpio, 1);
++ clk_disable_unprepare(adau1372->mclk);
++ return ret;
++ }
+ clk_ctrl |= ADAU1372_CLK_CTRL_CLKSRC;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 448049771744d9d7339a28aca03de7ad69229196 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:03 +0100
+Subject: ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit 326fe8104a4020d30080d37ac8b6b43893cdebca ]
+
+adau1372_set_power() calls clk_prepare_enable() but discards the return
+value. If the clock enable fails, the driver proceeds to access registers
+on unpowered hardware, potentially causing silent corruption.
+
+Make adau1372_set_power() return int and propagate the error from
+clk_prepare_enable(). Update adau1372_set_bias_level() to return the
+error directly for the STANDBY and OFF cases.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index fdee689cae538..6345342218d61 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -782,15 +782,18 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
+ }
+
+-static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
++static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ {
+ if (adau1372->enabled == enable)
+- return;
++ return 0;
+
+ if (enable) {
+ unsigned int clk_ctrl = ADAU1372_CLK_CTRL_MCLK_EN;
++ int ret;
+
+- clk_prepare_enable(adau1372->mclk);
++ ret = clk_prepare_enable(adau1372->mclk);
++ if (ret)
++ return ret;
+ if (adau1372->pd_gpio)
+ gpiod_set_value(adau1372->pd_gpio, 0);
+
+@@ -829,6 +832,8 @@ static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ }
+
+ adau1372->enabled = enable;
++
++ return 0;
+ }
+
+ static int adau1372_set_bias_level(struct snd_soc_component *component,
+@@ -842,11 +847,9 @@ static int adau1372_set_bias_level(struct snd_soc_component *component,
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+- adau1372_set_power(adau1372, true);
+- break;
++ return adau1372_set_power(adau1372, true);
+ case SND_SOC_BIAS_OFF:
+- adau1372_set_power(adau1372, false);
+- break;
++ return adau1372_set_power(adau1372, false);
+ }
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 8eba73b6630134e1d9abbd33679ce624ecfce0b2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 21 Mar 2026 02:20:11 +0100
+Subject: ASoC: dt-bindings: stm32: Fix incorrect compatible string in
+ stm32h7-sai match
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit 91049ec2e18376ec2192e73ef7be4c7110436350 ]
+
+The conditional block that defines clock constraints for the stm32h7-sai
+variant references "st,stm32mph7-sai", which does not match any compatible
+string in the enum. As a result, clock validation for the h7 variant is
+silently skipped. Correct the compatible string to "st,stm32h7-sai".
+
+Fixes: 8509bb1f11a1f ("ASoC: dt-bindings: add stm32mp25 support for sai")
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Reviewed-by: Olivier Moysan <olivier.moysan@foss.st.com>
+Link: https://patch.msgid.link/20260321012011.125791-1-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/devicetree/bindings/sound/st,stm32-sai.yaml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
+index 4a7129d0b1574..551edf39e7663 100644
+--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
++++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
+@@ -164,7 +164,7 @@ allOf:
+ properties:
+ compatible:
+ contains:
+- const: st,stm32mph7-sai
++ const: st,stm32h7-sai
+ then:
+ properties:
+ clocks:
+--
+2.53.0
+
--- /dev/null
+From 80c6917e379b7b2306d469993f4e0d245d7ed3ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Mar 2026 18:28:50 +0800
+Subject: ASoC: fsl: imx-card: initialize playback_only and capture_only
+
+From: Shengjiu Wang <shengjiu.wang@nxp.com>
+
+[ Upstream commit ca67bd564e94aaa898a2cbb90922ca3cccd0612b ]
+
+Fix uninitialized variable playback_only and capture_only because
+graph_util_parse_link_direction() may not write them.
+
+Fixes: 1877c3e7937f ("ASoC: imx-card: Add playback_only or capture_only support")
+Suggested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
+Link: https://patch.msgid.link/20260318102850.2794029-3-shengjiu.wang@nxp.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/fsl/imx-card.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c
+index 05b4e971a3661..a4518fefad690 100644
+--- a/sound/soc/fsl/imx-card.c
++++ b/sound/soc/fsl/imx-card.c
+@@ -710,6 +710,8 @@ static int imx_card_parse_of(struct imx_card_data *data)
+ link->ops = &imx_aif_ops;
+ }
+
++ playback_only = false;
++ capture_only = false;
+ graph_util_parse_link_direction(np, &playback_only, &capture_only);
+ link->playback_only = playback_only;
+ link->capture_only = capture_only;
+--
+2.53.0
+
--- /dev/null
+From 4ac44e0152210a8e44e3602915530ade74469832 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 11:12:17 +0100
+Subject: ASoC: Intel: catpt: Fix the device initialization
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 5a184f1cb43a8e035251c635f5c47da5dc3e3049 ]
+
+The DMA mask shall be coerced before any buffer allocations for the
+device are done. At the same time explain why DMA mask of 31 bits is
+used in the first place.
+
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle")
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/catpt/device.c | 10 +++++++++-
+ sound/soc/intel/catpt/dsp.c | 3 ---
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c
+index d13062c8e907c..fcc7a7342a4ab 100644
+--- a/sound/soc/intel/catpt/device.c
++++ b/sound/soc/intel/catpt/device.c
+@@ -281,7 +281,15 @@ static int catpt_acpi_probe(struct platform_device *pdev)
+ if (IS_ERR(cdev->pci_ba))
+ return PTR_ERR(cdev->pci_ba);
+
+- /* alloc buffer for storing DRAM context during dx transitions */
++ /*
++ * As per design HOST is responsible for preserving firmware's runtime
++ * context during D0 -> D3 -> D0 transitions. Addresses used for DMA
++ * to/from HOST memory shall be outside the reserved range of 0xFFFxxxxx.
++ */
++ ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
++ if (ret)
++ return ret;
++
+ cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev),
+ &cdev->dxbuf_paddr, GFP_KERNEL);
+ if (!cdev->dxbuf_vaddr)
+diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
+index 008a20a2acbda..677f348909c8f 100644
+--- a/sound/soc/intel/catpt/dsp.c
++++ b/sound/soc/intel/catpt/dsp.c
+@@ -125,9 +125,6 @@ int catpt_dmac_probe(struct catpt_dev *cdev)
+ dmac->dev = cdev->dev;
+ dmac->irq = cdev->irq;
+
+- ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
+- if (ret)
+- return ret;
+ /*
+ * Caller is responsible for putting device in D0 to allow
+ * for I/O and memory access before probing DW.
+--
+2.53.0
+
--- /dev/null
+From e7731b2445a3b3a46f9ddd7cbafc2fbee671e182 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 19:04:06 +0800
+Subject: ASoC: SDCA: fix finding wrong entity
+
+From: Shuming Fan <shumingf@realtek.com>
+
+[ Upstream commit c673efd5db2223c2e8b885025bcd96bca6cdb171 ]
+
+This patch fixes an issue like:
+where searching for the entity 'FU 11' could incorrectly match 'FU 113' first.
+The driver should first perform an exact match on the full string name.
+If no exact match is found, it can then fall back to a partial match.
+
+Fixes: 48fa77af2f4a ("ASoC: SDCA: Add terminal type into input/output widget name")
+Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Signed-off-by: Shuming Fan <shumingf@realtek.com>
+Link: https://patch.msgid.link/20260325110406.3232420-1-shumingf@realtek.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/sdca/sdca_functions.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
+index d2de9e81b4f9f..a1f6f931a8081 100644
+--- a/sound/soc/sdca/sdca_functions.c
++++ b/sound/soc/sdca/sdca_functions.c
+@@ -1568,10 +1568,19 @@ static int find_sdca_entities(struct device *dev, struct sdw_slave *sdw,
+ static struct sdca_entity *find_sdca_entity_by_label(struct sdca_function_data *function,
+ const char *entity_label)
+ {
++ struct sdca_entity *entity = NULL;
+ int i;
+
+ for (i = 0; i < function->num_entities; i++) {
+- struct sdca_entity *entity = &function->entities[i];
++ entity = &function->entities[i];
++
++ /* check whole string first*/
++ if (!strcmp(entity->label, entity_label))
++ return entity;
++ }
++
++ for (i = 0; i < function->num_entities; i++) {
++ entity = &function->entities[i];
+
+ if (!strncmp(entity->label, entity_label, strlen(entity_label)))
+ return entity;
+--
+2.53.0
+
--- /dev/null
+From a134ab50a7f0c8f3d29842e0668fceba6dbd74ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Mar 2026 18:28:49 +0800
+Subject: ASoC: simple-card-utils: Check value of is_playback_only and
+ is_capture_only
+
+From: Shengjiu Wang <shengjiu.wang@nxp.com>
+
+[ Upstream commit 0e9fc79132ce7ea1e48c388b864382aa38eb0ed4 ]
+
+The audio-graph-card2 gets the value of 'playback-only' and
+'capture_only' property in below sequence, if there is 'playback_only' or
+'capture_only' property in port_cpu and port_codec nodes, but no these
+properties in ep_cpu and ep_codec nodes, the value of playback_only and
+capture_only will be flushed to zero in the end.
+
+graph_util_parse_link_direction(lnk, &playback_only, &capture_only);
+graph_util_parse_link_direction(ports_cpu, &playback_only, &capture_only);
+graph_util_parse_link_direction(ports_codec, &playback_only, &capture_only);
+graph_util_parse_link_direction(port_cpu, &playback_only, &capture_only);
+graph_util_parse_link_direction(port_codec, &playback_only, &capture_only);
+graph_util_parse_link_direction(ep_cpu, &playback_only, &capture_only);
+graph_util_parse_link_direction(ep_codec, &playback_only, &capture_only);
+
+So check the value of is_playback_only and is_capture_only in
+graph_util_parse_link_direction() function, if they are true, then rewrite
+the values, and no need to check the np variable as
+of_property_read_bool() will ignore if it was NULL.
+
+Fixes: 3cc393d2232e ("ASoC: simple-card-utils: Fix pointer check in graph_util_parse_link_direction")
+Fixes: 22a507d7680f ("ASoC: simple-card-utils: Check device node before overwrite direction")
+Suggested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
+Link: https://patch.msgid.link/20260318102850.2794029-2-shengjiu.wang@nxp.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/generic/simple-card-utils.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
+index 9e5be0eaa77f3..89d694c2cbdda 100644
+--- a/sound/soc/generic/simple-card-utils.c
++++ b/sound/soc/generic/simple-card-utils.c
+@@ -1183,9 +1183,9 @@ void graph_util_parse_link_direction(struct device_node *np,
+ bool is_playback_only = of_property_read_bool(np, "playback-only");
+ bool is_capture_only = of_property_read_bool(np, "capture-only");
+
+- if (np && playback_only)
++ if (playback_only && is_playback_only)
+ *playback_only = is_playback_only;
+- if (np && capture_only)
++ if (capture_only && is_capture_only)
+ *capture_only = is_capture_only;
+ }
+ EXPORT_SYMBOL_GPL(graph_util_parse_link_direction);
+--
+2.53.0
+
--- /dev/null
+From 0f3be3c4ccf8e194bb47e0aeaedc3730cbf82557 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Mar 2026 12:06:35 +0000
+Subject: drm/amd/display: Do not skip unrelated mode changes in DSC validation
+
+From: Yussuf Khalil <dev@pp3345.net>
+
+[ Upstream commit aed3d041ab061ec8a64f50a3edda0f4db7280025 ]
+
+Starting with commit 17ce8a6907f7 ("drm/amd/display: Add dsc pre-validation in
+atomic check"), amdgpu resets the CRTC state mode_changed flag to false when
+recomputing the DSC configuration results in no timing change for a particular
+stream.
+
+However, this is incorrect in scenarios where a change in MST/DSC configuration
+happens in the same KMS commit as another (unrelated) mode change. For example,
+the integrated panel of a laptop may be configured differently (e.g., HDR
+enabled/disabled) depending on whether external screens are attached. In this
+case, plugging in external DP-MST screens may result in the mode_changed flag
+being dropped incorrectly for the integrated panel if its DSC configuration
+did not change during precomputation in pre_validate_dsc().
+
+At this point, however, dm_update_crtc_state() has already created new streams
+for CRTCs with DSC-independent mode changes. In turn,
+amdgpu_dm_commit_streams() will never release the old stream, resulting in a
+memory leak. amdgpu_dm_atomic_commit_tail() will never acquire a reference to
+the new stream either, which manifests as a use-after-free when the stream gets
+disabled later on:
+
+BUG: KASAN: use-after-free in dc_stream_release+0x25/0x90 [amdgpu]
+Write of size 4 at addr ffff88813d836524 by task kworker/9:9/29977
+
+Workqueue: events drm_mode_rmfb_work_fn
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x6e/0xa0
+ print_address_description.constprop.0+0x88/0x320
+ ? dc_stream_release+0x25/0x90 [amdgpu]
+ print_report+0xfc/0x1ff
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? __virt_addr_valid+0x225/0x4e0
+ ? dc_stream_release+0x25/0x90 [amdgpu]
+ kasan_report+0xe1/0x180
+ ? dc_stream_release+0x25/0x90 [amdgpu]
+ kasan_check_range+0x125/0x200
+ dc_stream_release+0x25/0x90 [amdgpu]
+ dc_state_destruct+0x14d/0x5c0 [amdgpu]
+ dc_state_release.part.0+0x4e/0x130 [amdgpu]
+ dm_atomic_destroy_state+0x3f/0x70 [amdgpu]
+ drm_atomic_state_default_clear+0x8ee/0xf30
+ ? drm_mode_object_put.part.0+0xb1/0x130
+ __drm_atomic_state_free+0x15c/0x2d0
+ atomic_remove_fb+0x67e/0x980
+
+Since there is no reliable way of figuring out whether a CRTC has unrelated
+mode changes pending at the time of DSC validation, remember the value of the
+mode_changed flag from before the point where a CRTC was marked as potentially
+affected by a change in DSC configuration. Reset the mode_changed flag to this
+earlier value instead in pre_validate_dsc().
+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/5004
+Fixes: 17ce8a6907f7 ("drm/amd/display: Add dsc pre-validation in atomic check")
+Signed-off-by: Yussuf Khalil <dev@pp3345.net>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit cc7c7121ae082b7b82891baa7280f1ff2608f22b)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 +
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +++-
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 5a54d3f4a3de5..1430d18ae2c9e 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -12505,6 +12505,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
+ }
+
+ if (dc_resource_is_dsc_encoding_supported(dc)) {
++ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
++ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
++ dm_new_crtc_state->mode_changed_independent_from_dsc = new_crtc_state->mode_changed;
++ }
++
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+ if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
+ ret = add_affected_mst_dsc_crtcs(state, crtc);
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+index beb0d04d3e682..dbc3db0d68292 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+@@ -965,6 +965,7 @@ struct dm_crtc_state {
+
+ bool freesync_vrr_info_changed;
+
++ bool mode_changed_independent_from_dsc;
+ bool dsc_force_changed;
+ bool vrr_supported;
+ struct mod_freesync_config freesync_config;
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+index 5e92eaa67aa33..2e0895f4f9b10 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -1744,9 +1744,11 @@ int pre_validate_dsc(struct drm_atomic_state *state,
+ int ind = find_crtc_index_in_state_by_stream(state, stream);
+
+ if (ind >= 0) {
++ struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(state->crtcs[ind].new_state);
++
+ DRM_INFO_ONCE("%s:%d MST_DSC no mode changed for stream 0x%p\n",
+ __func__, __LINE__, stream);
+- state->crtcs[ind].new_state->mode_changed = 0;
++ dm_new_crtc_state->base.mode_changed = dm_new_crtc_state->mode_changed_independent_from_dsc;
+ }
+ }
+ }
+--
+2.53.0
+
--- /dev/null
+From fadd160c4a89a13f77edbe5e609149700e44b928 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Mar 2026 13:41:18 +0530
+Subject: drm/amdgpu: Fix fence put before wait in amdgpu_amdkfd_submit_ib
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 7150850146ebfa4ca998f653f264b8df6f7f85be ]
+
+amdgpu_amdkfd_submit_ib() submits a GPU job and gets a fence
+from amdgpu_ib_schedule(). This fence is used to wait for job
+completion.
+
+Currently, the code drops the fence reference using dma_fence_put()
+before calling dma_fence_wait().
+
+If dma_fence_put() releases the last reference, the fence may be
+freed before dma_fence_wait() is called. This can lead to a
+use-after-free.
+
+Fix this by waiting on the fence first and releasing the reference
+only after dma_fence_wait() completes.
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c:697 amdgpu_amdkfd_submit_ib() warn: passing freed memory 'f' (line 696)
+
+Fixes: 9ae55f030dc5 ("drm/amdgpu: Follow up change to previous drm scheduler change.")
+Cc: Felix Kuehling <Felix.Kuehling@amd.com>
+Cc: Dan Carpenter <dan.carpenter@linaro.org>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+index a2879d2b7c8ec..1ec26be82f30e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -687,9 +687,9 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
+ goto err_ib_sched;
+ }
+
+- /* Drop the initial kref_init count (see drm_sched_main as example) */
+- dma_fence_put(f);
+ ret = dma_fence_wait(f, false);
++ /* Drop the returned fence reference after the wait completes */
++ dma_fence_put(f);
+
+ err_ib_sched:
+ amdgpu_job_free(job);
+--
+2.53.0
+
--- /dev/null
+From b862900999021e5bdb6bd086fd8d5c61c830c2bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 16:19:19 -0700
+Subject: drm/i915/gmbus: fix spurious timeout on 512-byte burst reads
+
+From: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+
+[ Upstream commit 08441f10f4dc09fdeb64529953ac308abc79dd38 ]
+
+When reading exactly 512 bytes with burst read enabled, the
+extra_byte_added path breaks out of the inner do-while without
+decrementing len. The outer while(len) then re-enters and gmbus_wait()
+times out since all data has been delivered. Decrement len before the
+break so the outer loop terminates correctly.
+
+Fixes: d5dc0f43f268 ("drm/i915/gmbus: Enable burst read")
+Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_gmbus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
+index 795012d7c24c2..5a941bea81cad 100644
+--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
++++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
+@@ -498,8 +498,10 @@ gmbus_xfer_read_chunk(struct intel_display *display,
+
+ val = intel_de_read_fw(display, GMBUS3(display));
+ do {
+- if (extra_byte_added && len == 1)
++ if (extra_byte_added && len == 1) {
++ len--;
+ break;
++ }
+
+ *buf++ = val & 0xff;
+ val >>= 8;
+--
+2.53.0
+
--- /dev/null
+From ed9ee19d9d7c20b05aa3c1aed152dabf11cc6331 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Feb 2026 09:38:41 +0000
+Subject: drm/mediatek: dsi: Store driver data before invoking
+ mipi_dsi_host_register
+
+From: Luca Leonardo Scorcia <l.scorcia@gmail.com>
+
+[ Upstream commit 4cfdfeb6ac06079f92fccd977fa742d6c5b8dd3a ]
+
+The call to mipi_dsi_host_register triggers a callback to mtk_dsi_bind,
+which uses dev_get_drvdata to retrieve the mtk_dsi struct, so this
+structure needs to be stored inside the driver data before invoking it.
+
+As drvdata is currently uninitialized it leads to a crash when
+registering the DSI DRM encoder right after acquiring
+the mode_config.idr_mutex, blocking all subsequent DRM operations.
+
+Fixes the following crash during mediatek-drm probe (tested on Xiaomi
+Smart Clock x04g):
+
+Unable to handle kernel NULL pointer dereference at virtual address
+ 0000000000000040
+[...]
+Modules linked in: mediatek_drm(+) drm_display_helper cec drm_client_lib
+ drm_dma_helper drm_kms_helper panel_simple
+[...]
+Call trace:
+ drm_mode_object_add+0x58/0x98 (P)
+ __drm_encoder_init+0x48/0x140
+ drm_encoder_init+0x6c/0xa0
+ drm_simple_encoder_init+0x20/0x34 [drm_kms_helper]
+ mtk_dsi_bind+0x34/0x13c [mediatek_drm]
+ component_bind_all+0x120/0x280
+ mtk_drm_bind+0x284/0x67c [mediatek_drm]
+ try_to_bring_up_aggregate_device+0x23c/0x320
+ __component_add+0xa4/0x198
+ component_add+0x14/0x20
+ mtk_dsi_host_attach+0x78/0x100 [mediatek_drm]
+ mipi_dsi_attach+0x2c/0x50
+ panel_simple_dsi_probe+0x4c/0x9c [panel_simple]
+ mipi_dsi_drv_probe+0x1c/0x28
+ really_probe+0xc0/0x3dc
+ __driver_probe_device+0x80/0x160
+ driver_probe_device+0x40/0x120
+ __device_attach_driver+0xbc/0x17c
+ bus_for_each_drv+0x88/0xf0
+ __device_attach+0x9c/0x1cc
+ device_initial_probe+0x54/0x60
+ bus_probe_device+0x34/0xa0
+ device_add+0x5b0/0x800
+ mipi_dsi_device_register_full+0xdc/0x16c
+ mipi_dsi_host_register+0xc4/0x17c
+ mtk_dsi_probe+0x10c/0x260 [mediatek_drm]
+ platform_probe+0x5c/0xa4
+ really_probe+0xc0/0x3dc
+ __driver_probe_device+0x80/0x160
+ driver_probe_device+0x40/0x120
+ __driver_attach+0xc8/0x1f8
+ bus_for_each_dev+0x7c/0xe0
+ driver_attach+0x24/0x30
+ bus_add_driver+0x11c/0x240
+ driver_register+0x68/0x130
+ __platform_register_drivers+0x64/0x160
+ mtk_drm_init+0x24/0x1000 [mediatek_drm]
+ do_one_initcall+0x60/0x1d0
+ do_init_module+0x54/0x240
+ load_module+0x1838/0x1dc0
+ init_module_from_file+0xd8/0xf0
+ __arm64_sys_finit_module+0x1b4/0x428
+ invoke_syscall.constprop.0+0x48/0xc8
+ do_el0_svc+0x3c/0xb8
+ el0_svc+0x34/0xe8
+ el0t_64_sync_handler+0xa0/0xe4
+ el0t_64_sync+0x198/0x19c
+Code: 52800022 941004ab 2a0003f3 37f80040 (29005a80)
+
+Fixes: e4732b590a77 ("drm/mediatek: dsi: Register DSI host after acquiring clocks and PHY")
+Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: CK Hu <ck.hu@mediatek.com>
+Link: https://patchwork.kernel.org/project/dri-devel/patch/20260225094047.76780-1-l.scorcia@gmail.com/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dsi.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index d7726091819c4..acee2227275b7 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -1232,6 +1232,11 @@ static int mtk_dsi_probe(struct platform_device *pdev)
+
+ dsi->host.ops = &mtk_dsi_ops;
+ dsi->host.dev = dev;
++
++ init_waitqueue_head(&dsi->irq_wait_queue);
++
++ platform_set_drvdata(pdev, dsi);
++
+ ret = mipi_dsi_host_register(&dsi->host);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to register DSI host\n");
+@@ -1243,10 +1248,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
+ return dev_err_probe(&pdev->dev, ret, "Failed to request DSI irq\n");
+ }
+
+- init_waitqueue_head(&dsi->irq_wait_queue);
+-
+- platform_set_drvdata(pdev, dsi);
+-
+ dsi->bridge.of_node = dev->of_node;
+ dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
+
+--
+2.53.0
+
--- /dev/null
+From 44c736fe843dbba9254ca1bc94c6f0ec3631173d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 15:30:34 -0700
+Subject: drm/xe: Implement recent spec updates to Wa_16025250150
+
+From: Matt Roper <matthew.d.roper@intel.com>
+
+[ Upstream commit 56781a4597706cd25185b1dedc38841ec6c31496 ]
+
+The hardware teams noticed that the originally documented workaround
+steps for Wa_16025250150 may not be sufficient to fully avoid a hardware
+issue. The workaround documentation has been augmented to suggest
+programming one additional register; make the corresponding change in
+the driver.
+
+Fixes: 7654d51f1fd8 ("drm/xe/xe2hpg: Add Wa_16025250150")
+Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
+Link: https://patch.msgid.link/20260319-wa_16025250150_part2-v1-1-46b1de1a31b2@intel.com
+Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
+(cherry picked from commit a31566762d4075646a8a2214586158b681e94305)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/regs/xe_gt_regs.h | 1 +
+ drivers/gpu/drm/xe/xe_wa.c | 3 ++-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+index 917a088c28f24..ec1ae2dc6cabe 100644
+--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
++++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+@@ -544,6 +544,7 @@
+ #define ENABLE_SMP_LD_RENDER_SURFACE_CONTROL REG_BIT(44 - 32)
+ #define FORCE_SLM_FENCE_SCOPE_TO_TILE REG_BIT(42 - 32)
+ #define FORCE_UGM_FENCE_SCOPE_TO_TILE REG_BIT(41 - 32)
++#define L3_128B_256B_WRT_DIS REG_BIT(40 - 32)
+ #define MAXREQS_PER_BANK REG_GENMASK(39 - 32, 37 - 32)
+ #define DISABLE_128B_EVICTION_COMMAND_UDW REG_BIT(36 - 32)
+
+diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
+index 4039a6428e6c1..c15b0288e0ff5 100644
+--- a/drivers/gpu/drm/xe/xe_wa.c
++++ b/drivers/gpu/drm/xe/xe_wa.c
+@@ -261,7 +261,8 @@ static const struct xe_rtp_entry_sr gt_was[] = {
+ LSN_DIM_Z_WGT_MASK,
+ LSN_LNI_WGT(1) | LSN_LNE_WGT(1) |
+ LSN_DIM_X_WGT(1) | LSN_DIM_Y_WGT(1) |
+- LSN_DIM_Z_WGT(1)))
++ LSN_DIM_Z_WGT(1)),
++ SET(LSC_CHICKEN_BIT_0_UDW, L3_128B_256B_WRT_DIS))
+ },
+
+ /* Xe2_HPM */
+--
+2.53.0
+
--- /dev/null
+From 1fe314c158487d5a856771e5d8f9e87f13313831 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Feb 2026 16:41:18 +0100
+Subject: drm/xe/pf: Fix use-after-free in migration restore
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michał Winiarski <michal.winiarski@intel.com>
+
+[ Upstream commit 87997b6c6516e049cbaf2fc6810b213d587a06b1 ]
+
+When an error is returned from xe_sriov_pf_migration_restore_produce(),
+the data pointer is not set to NULL, which can trigger use-after-free
+in subsequent .write() calls.
+Set the pointer to NULL upon error to fix the problem.
+
+Fixes: 1ed30397c0b92 ("drm/xe/pf: Add support for encap/decap of bitstream to/from packet")
+Reported-by: Sebastian Österlund <sebastian.osterlund@intel.com>
+Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/7230
+Reviewed-by: Shuicheng Lin <shuicheng.lin@intel.com>
+Link: https://patch.msgid.link/20260217154118.176902-1-michal.winiarski@intel.com
+Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
+(cherry picked from commit 4f53d8c6d23527d734fe3531d08e15cb170a0819)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_sriov_packet.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_sriov_packet.c b/drivers/gpu/drm/xe/xe_sriov_packet.c
+index bab9946968964..111877b6d44cf 100644
+--- a/drivers/gpu/drm/xe/xe_sriov_packet.c
++++ b/drivers/gpu/drm/xe/xe_sriov_packet.c
+@@ -342,6 +342,8 @@ ssize_t xe_sriov_packet_write_single(struct xe_device *xe, unsigned int vfid,
+ ret = xe_sriov_pf_migration_restore_produce(xe, vfid, *data);
+ if (ret) {
+ xe_sriov_packet_free(*data);
++ *data = NULL;
++
+ return ret;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From f05146f9998d4d7d400463a3d4855d9fc777ddde Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 05:13:06 +0000
+Subject: hwmon: (adm1177) fix sysfs ABI violation and current unit conversion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sanman Pradhan <psanman@juniper.net>
+
+[ Upstream commit bf08749a6abb6d1959bfdc0edc32c640df407558 ]
+
+The adm1177 driver exposes the current alert threshold through
+hwmon_curr_max_alarm. This violates the hwmon sysfs ABI, where
+*_alarm attributes are read-only status flags and writable thresholds
+must use currN_max.
+
+The driver also stores the threshold internally in microamps, while
+currN_max is defined in milliamps. Convert the threshold accordingly
+on both the read and write paths.
+
+Widen the cached threshold and related calculations to 64 bits so
+that small shunt resistor values do not cause truncation or overflow.
+Also use 64-bit arithmetic for the mA/uA conversions, clamp writes
+to the range the hardware can represent, and propagate failures from
+adm1177_write_alert_thr() instead of silently ignoring them.
+
+Update the hwmon documentation to reflect the attribute rename and
+the correct units returned by the driver.
+
+Fixes: 09b08ac9e8d5 ("hwmon: (adm1177) Add ADM1177 Hot Swap Controller and Digital Power Monitor driver")
+Signed-off-by: Sanman Pradhan <psanman@juniper.net>
+Acked-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/adm1177.rst | 8 ++---
+ drivers/hwmon/adm1177.c | 54 +++++++++++++++++++--------------
+ 2 files changed, 35 insertions(+), 27 deletions(-)
+
+diff --git a/Documentation/hwmon/adm1177.rst b/Documentation/hwmon/adm1177.rst
+index 1c85a2af92bf7..375f6d6e03a7d 100644
+--- a/Documentation/hwmon/adm1177.rst
++++ b/Documentation/hwmon/adm1177.rst
+@@ -27,10 +27,10 @@ for details.
+ Sysfs entries
+ -------------
+
+-The following attributes are supported. Current maxim attribute
++The following attributes are supported. Current maximum attribute
+ is read-write, all other attributes are read-only.
+
+-in0_input Measured voltage in microvolts.
++in0_input Measured voltage in millivolts.
+
+-curr1_input Measured current in microamperes.
+-curr1_max_alarm Overcurrent alarm in microamperes.
++curr1_input Measured current in milliamperes.
++curr1_max Overcurrent shutdown threshold in milliamperes.
+diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c
+index 8b2c965480e3f..7888afe8dafd6 100644
+--- a/drivers/hwmon/adm1177.c
++++ b/drivers/hwmon/adm1177.c
+@@ -10,6 +10,8 @@
+ #include <linux/hwmon.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
++#include <linux/math64.h>
++#include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/regulator/consumer.h>
+
+@@ -33,7 +35,7 @@
+ struct adm1177_state {
+ struct i2c_client *client;
+ u32 r_sense_uohm;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
+ bool vrange_high;
+ };
+
+@@ -48,7 +50,7 @@ static int adm1177_write_cmd(struct adm1177_state *st, u8 cmd)
+ }
+
+ static int adm1177_write_alert_thr(struct adm1177_state *st,
+- u32 alert_threshold_ua)
++ u64 alert_threshold_ua)
+ {
+ u64 val;
+ int ret;
+@@ -91,8 +93,8 @@ static int adm1177_read(struct device *dev, enum hwmon_sensor_types type,
+ *val = div_u64((105840000ull * dummy),
+ 4096 * st->r_sense_uohm);
+ return 0;
+- case hwmon_curr_max_alarm:
+- *val = st->alert_threshold_ua;
++ case hwmon_curr_max:
++ *val = div_u64(st->alert_threshold_ua, 1000);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+@@ -126,9 +128,10 @@ static int adm1177_write(struct device *dev, enum hwmon_sensor_types type,
+ switch (type) {
+ case hwmon_curr:
+ switch (attr) {
+- case hwmon_curr_max_alarm:
+- adm1177_write_alert_thr(st, val);
+- return 0;
++ case hwmon_curr_max:
++ val = clamp_val(val, 0,
++ div_u64(105840000ULL, st->r_sense_uohm));
++ return adm1177_write_alert_thr(st, (u64)val * 1000);
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -156,7 +159,7 @@ static umode_t adm1177_is_visible(const void *data,
+ if (st->r_sense_uohm)
+ return 0444;
+ return 0;
+- case hwmon_curr_max_alarm:
++ case hwmon_curr_max:
+ if (st->r_sense_uohm)
+ return 0644;
+ return 0;
+@@ -170,7 +173,7 @@ static umode_t adm1177_is_visible(const void *data,
+
+ static const struct hwmon_channel_info * const adm1177_info[] = {
+ HWMON_CHANNEL_INFO(curr,
+- HWMON_C_INPUT | HWMON_C_MAX_ALARM),
++ HWMON_C_INPUT | HWMON_C_MAX),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT),
+ NULL
+@@ -192,7 +195,8 @@ static int adm1177_probe(struct i2c_client *client)
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct adm1177_state *st;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
++ u32 prop;
+ int ret;
+
+ st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+@@ -208,22 +212,26 @@ static int adm1177_probe(struct i2c_client *client)
+ if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
+ &st->r_sense_uohm))
+ st->r_sense_uohm = 0;
+- if (device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
+- &alert_threshold_ua)) {
+- if (st->r_sense_uohm)
+- /*
+- * set maximum default value from datasheet based on
+- * shunt-resistor
+- */
+- alert_threshold_ua = div_u64(105840000000,
+- st->r_sense_uohm);
+- else
+- alert_threshold_ua = 0;
++ if (!device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
++ &prop)) {
++ alert_threshold_ua = prop;
++ } else if (st->r_sense_uohm) {
++ /*
++ * set maximum default value from datasheet based on
++ * shunt-resistor
++ */
++ alert_threshold_ua = div_u64(105840000000ULL,
++ st->r_sense_uohm);
++ } else {
++ alert_threshold_ua = 0;
+ }
+ st->vrange_high = device_property_read_bool(dev,
+ "adi,vrange-high-enable");
+- if (alert_threshold_ua && st->r_sense_uohm)
+- adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (alert_threshold_ua && st->r_sense_uohm) {
++ ret = adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (ret)
++ return ret;
++ }
+
+ ret = adm1177_write_cmd(st, ADM1177_CMD_V_CONT |
+ ADM1177_CMD_I_CONT |
+--
+2.53.0
+
--- /dev/null
+From 4bcfd0475037eee1a23bb7a05ef0dd77650204c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Mar 2026 09:12:33 -0700
+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: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 114 ++++++++++++++++++++++++-------
+ 1 file changed, 89 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index cbc36f0ba4bf9..572be3ebc03df 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/dcache.h>
+@@ -21,8 +22,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"
+
+ /*
+@@ -112,6 +113,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);
+
+@@ -3228,12 +3234,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,
+@@ -3250,16 +3263,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)
+@@ -3269,7 +3288,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,
+@@ -3279,6 +3301,7 @@ static int pmbus_regulator_list_voltage(struct regulator_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 (data->flags & PMBUS_VOUT_PROTECTED)
+ return 0;
+@@ -3291,18 +3314,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 = {
+@@ -3333,12 +3367,42 @@ int pmbus_regulator_init_cb(struct regulator_dev *rdev,
+ }
+ EXPORT_SYMBOL_NS_GPL(pmbus_regulator_init_cb, "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);
+@@ -3362,19 +3426,19 @@ 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 void 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;
+- }
+- }
++ atomic_or(event, &data->regulator_events[page]);
++ schedule_work(&data->regulator_notify_work);
+ }
+ #else
+ static int pmbus_regulator_register(struct pmbus_data *data)
+--
+2.53.0
+
--- /dev/null
+From 1703afe42e6f46eaf62b66269aabd34fd69ab140 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 18:54:11 -0700
+Subject: hwmon: (pmbus) Introduce the concept of "write-only" attributes
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit cd658475e7694d58e1c40dabc1dacf8431ccedb2 ]
+
+Attributes intended to clear sensor history are intended to be writeable
+only. Reading those attributes today results in reporting more or less
+random values. To avoid ABI surprises, have those attributes explicitly
+return 0 when reading.
+
+Fixes: 787c095edaa9d ("hwmon: (pmbus/core) Add support for rated attributes")
+Reviewed-by: Sanman Pradhan <psanman@juniper.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 32 ++++++++++++++++++++++++--------
+ 1 file changed, 24 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index ecd1dddcbe0ff..cbc36f0ba4bf9 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -1209,6 +1209,12 @@ static ssize_t pmbus_show_boolean(struct device *dev,
+ return sysfs_emit(buf, "%d\n", val);
+ }
+
++static ssize_t pmbus_show_zero(struct device *dev,
++ struct device_attribute *devattr, char *buf)
++{
++ return sysfs_emit(buf, "0\n");
++}
++
+ static ssize_t pmbus_show_sensor(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+ {
+@@ -1407,7 +1413,7 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+ int reg,
+ enum pmbus_sensor_classes class,
+ bool update, bool readonly,
+- bool convert)
++ bool writeonly, bool convert)
+ {
+ struct pmbus_sensor *sensor;
+ struct device_attribute *a;
+@@ -1436,7 +1442,8 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+ sensor->data = -ENODATA;
+ pmbus_dev_attr_init(a, sensor->name,
+ readonly ? 0444 : 0644,
+- pmbus_show_sensor, pmbus_set_sensor);
++ writeonly ? pmbus_show_zero : pmbus_show_sensor,
++ pmbus_set_sensor);
+
+ if (pmbus_add_attribute(data, &a->attr))
+ return NULL;
+@@ -1496,6 +1503,7 @@ struct pmbus_limit_attr {
+ u16 reg; /* Limit register */
+ u16 sbit; /* Alarm attribute status bit */
+ bool readonly:1; /* True if the attribute is read-only */
++ bool writeonly:1; /* True if the attribute is write-only */
+ bool update:1; /* True if register needs updates */
+ bool low:1; /* True if low limit; for limits with compare functions only */
+ const char *attr; /* Attribute name */
+@@ -1545,7 +1553,7 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
+ curr = pmbus_add_sensor(data, name, l->attr, index,
+ page, 0xff, l->reg, attr->class,
+ attr->update || l->update,
+- l->readonly, true);
++ l->readonly, l->writeonly, true);
+ if (!curr)
+ return -ENOMEM;
+ if (l->sbit && (info->func[page] & attr->sfunc)) {
+@@ -1585,7 +1593,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
+ return ret;
+ }
+ base = pmbus_add_sensor(data, name, "input", index, page, phase,
+- attr->reg, attr->class, true, true, true);
++ attr->reg, attr->class, true, true, false, true);
+ if (!base)
+ return -ENOMEM;
+ /* No limit and alarm attributes for phase specific sensors */
+@@ -1722,6 +1730,7 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VIN_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VIN_MIN,
+@@ -1796,6 +1805,7 @@ static const struct pmbus_limit_attr vout_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VOUT_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VOUT_MIN,
+@@ -1877,6 +1887,7 @@ static const struct pmbus_limit_attr iin_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IIN_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IIN_MAX,
+@@ -1918,6 +1929,7 @@ static const struct pmbus_limit_attr iout_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IOUT_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IOUT_MAX,
+@@ -1976,6 +1988,7 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_PIN_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_PIN_MAX,
+@@ -2017,6 +2030,7 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_POUT_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_POUT_MAX,
+@@ -2088,6 +2102,7 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_1,
+@@ -2133,6 +2148,7 @@ static const struct pmbus_limit_attr temp_limit_attrs2[] = {
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
++ .writeonly = true,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_2,
+@@ -2250,7 +2266,7 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
+
+ sensor = pmbus_add_sensor(data, "fan", "target", index, page,
+ 0xff, PMBUS_VIRT_FAN_TARGET_1 + id, PSC_FAN,
+- false, false, true);
++ false, false, false, true);
+
+ if (!sensor)
+ return -ENOMEM;
+@@ -2261,14 +2277,14 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
+
+ sensor = pmbus_add_sensor(data, "pwm", NULL, index, page,
+ 0xff, PMBUS_VIRT_PWM_1 + id, PSC_PWM,
+- false, false, true);
++ false, false, false, true);
+
+ if (!sensor)
+ return -ENOMEM;
+
+ sensor = pmbus_add_sensor(data, "pwm", "enable", index, page,
+ 0xff, PMBUS_VIRT_PWM_ENABLE_1 + id, PSC_PWM,
+- true, false, false);
++ true, false, false, false);
+
+ if (!sensor)
+ return -ENOMEM;
+@@ -2310,7 +2326,7 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
+
+ if (pmbus_add_sensor(data, "fan", "input", index,
+ page, 0xff, pmbus_fan_registers[f],
+- PSC_FAN, true, true, true) == NULL)
++ PSC_FAN, true, true, false, true) == NULL)
+ return -ENOMEM;
+
+ /* Fan control */
+--
+2.53.0
+
--- /dev/null
+From 0f53d77ee5ebf856c0ad62ef24fa40b33b10cf81 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 16:41:07 -0700
+Subject: hwmon: (pmbus) Mark lowest/average/highest/rated attributes as
+ read-only
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+[ Upstream commit 805a5bd1c3f307d45ae4e9cf8915ef16d585a54a ]
+
+Writing those attributes is not supported, so mark them as read-only.
+
+Prior to this change, attempts to write into these attributes returned
+an error.
+
+Mark boolean fields in struct pmbus_limit_attr and in struct
+pmbus_sensor_attr as bit fields to reduce configuration data size.
+The data is scanned only while probing, so performance is not a concern.
+
+Fixes: 6f183d33a02e6 ("hwmon: (pmbus) Add support for peak attributes")
+Reviewed-by: Sanman Pradhan <psanman@juniper.net>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/pmbus_core.c | 48 ++++++++++++++++++++++++++++----
+ 1 file changed, 42 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index be6d05def1152..ecd1dddcbe0ff 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -1495,8 +1495,9 @@ static int pmbus_add_label(struct pmbus_data *data,
+ struct pmbus_limit_attr {
+ u16 reg; /* Limit register */
+ u16 sbit; /* Alarm attribute status bit */
+- bool update; /* True if register needs updates */
+- bool low; /* True if low limit; for limits with compare functions only */
++ bool readonly:1; /* True if the attribute is read-only */
++ bool update:1; /* True if register needs updates */
++ bool low:1; /* True if low limit; for limits with compare functions only */
+ const char *attr; /* Attribute name */
+ const char *alarm; /* Alarm attribute name */
+ };
+@@ -1511,9 +1512,9 @@ struct pmbus_sensor_attr {
+ u8 nlimit; /* # of limit registers */
+ enum pmbus_sensor_classes class;/* sensor class */
+ const char *label; /* sensor label */
+- bool paged; /* true if paged sensor */
+- bool update; /* true if update needed */
+- bool compare; /* true if compare function needed */
++ bool paged:1; /* true if paged sensor */
++ bool update:1; /* true if update needed */
++ bool compare:1; /* true if compare function needed */
+ u32 func; /* sensor mask */
+ u32 sfunc; /* sensor status mask */
+ int sreg; /* status register */
+@@ -1544,7 +1545,7 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
+ curr = pmbus_add_sensor(data, name, l->attr, index,
+ page, 0xff, l->reg, attr->class,
+ attr->update || l->update,
+- false, true);
++ l->readonly, true);
+ if (!curr)
+ return -ENOMEM;
+ if (l->sbit && (info->func[page] & attr->sfunc)) {
+@@ -1707,23 +1708,28 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_VIN_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_VIN_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_VIN_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VIN_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VIN_MIN,
++ .readonly = true,
+ .attr = "rated_min",
+ }, {
+ .reg = PMBUS_MFR_VIN_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1776,23 +1782,28 @@ static const struct pmbus_limit_attr vout_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_VOUT_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_VOUT_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_VOUT_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_VOUT_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_VOUT_MIN,
++ .readonly = true,
+ .attr = "rated_min",
+ }, {
+ .reg = PMBUS_MFR_VOUT_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1852,20 +1863,24 @@ static const struct pmbus_limit_attr iin_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_IIN_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_IIN_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_IIN_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IIN_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IIN_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1889,20 +1904,24 @@ static const struct pmbus_limit_attr iout_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_IOUT_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_IOUT_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_IOUT_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_IOUT_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_IOUT_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1943,20 +1962,24 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_PIN_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_PIN_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "input_lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_PIN_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_PIN_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_PIN_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -1980,20 +2003,24 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
+ }, {
+ .reg = PMBUS_VIRT_READ_POUT_AVG,
+ .update = true,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_POUT_MIN,
+ .update = true,
++ .readonly = true,
+ .attr = "input_lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_POUT_MAX,
+ .update = true,
++ .readonly = true,
+ .attr = "input_highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_POUT_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_POUT_MAX,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -2049,18 +2076,22 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = {
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP_MIN,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP_AVG,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP_MAX,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_1,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -2090,18 +2121,22 @@ static const struct pmbus_limit_attr temp_limit_attrs2[] = {
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_MIN,
++ .readonly = true,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_AVG,
++ .readonly = true,
+ .attr = "average",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_MAX,
++ .readonly = true,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
+ .attr = "reset_history",
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_2,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+@@ -2131,6 +2166,7 @@ static const struct pmbus_limit_attr temp_limit_attrs3[] = {
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_MFR_MAX_TEMP_3,
++ .readonly = true,
+ .attr = "rated_max",
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From 1b1c50015d2683a97824ecad77afa421fef8e65b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Mar 2026 02:18:23 +0000
+Subject: io_uring/fdinfo: fix OOB read in SQE_MIXED wrap check
+
+From: Nicholas Carlini <nicholas@carlini.com>
+
+[ Upstream commit 5170efd9c344c68a8075dcb8ed38d3f8a60e7ed4 ]
+
+__io_uring_show_fdinfo() iterates over pending SQEs and, for 128-byte
+SQEs on an IORING_SETUP_SQE_MIXED ring, needs to detect when the second
+half of the SQE would be past the end of the sq_sqes array. The current
+check tests (++sq_head & sq_mask) == 0, but sq_head is only incremented
+when a 128-byte SQE is encountered, not on every iteration. The actual
+array index is sq_idx = (i + sq_head) & sq_mask, which can be sq_mask
+(the last slot) while the wrap check passes.
+
+Fix by checking sq_idx directly. Keep the sq_head increment so the loop
+still skips the second half of the 128-byte SQE on the next iteration.
+
+Fixes: 1cba30bf9fdd ("io_uring: add support for IORING_SETUP_SQE_MIXED")
+Signed-off-by: Nicholas Carlini <nicholas@carlini.com>
+Link: https://patch.msgid.link/20260327021823.3138396-1-nicholas@carlini.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ io_uring/fdinfo.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/io_uring/fdinfo.c b/io_uring/fdinfo.c
+index 25c92ace18bd1..c2d3e45544bb4 100644
+--- a/io_uring/fdinfo.c
++++ b/io_uring/fdinfo.c
+@@ -119,12 +119,13 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
+ sq_idx);
+ break;
+ }
+- if ((++sq_head & sq_mask) == 0) {
++ if (sq_idx == sq_mask) {
+ seq_printf(m,
+ "%5u: corrupted sqe, wrapping 128B entry\n",
+ sq_idx);
+ break;
+ }
++ sq_head++;
+ i++;
+ sqe128 = true;
+ }
+--
+2.53.0
+
--- /dev/null
+From 9c1db8e9e5d1f6b9c3315e1fcfca90f001ca5ead Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Mar 2026 07:02:53 -0600
+Subject: io_uring/fdinfo: fix SQE_MIXED SQE displaying
+
+From: Jens Axboe <axboe@kernel.dk>
+
+[ Upstream commit b59efde9e6c122207c16169d3d0deb623956eae9 ]
+
+When displaying pending SQEs for a MIXED ring, each 128-byte SQE
+increments sq_head to skip the second slot, but the loop counter is not
+adjusted. This can cause the loop to read past sq_tail by one entry for
+each 128-byte SQE encountered, displaying SQEs that haven't been made
+consumable yet by the application.
+
+Match the kernel's own consumption logic in io_init_req() which
+decrements what's left when consuming the extra slot.
+
+Fixes: 1cba30bf9fdd ("io_uring: add support for IORING_SETUP_SQE_MIXED")
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ io_uring/fdinfo.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/io_uring/fdinfo.c b/io_uring/fdinfo.c
+index 80178b69e05a2..25c92ace18bd1 100644
+--- a/io_uring/fdinfo.c
++++ b/io_uring/fdinfo.c
+@@ -125,6 +125,7 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
+ sq_idx);
+ break;
+ }
++ i++;
+ sqe128 = true;
+ }
+ seq_printf(m, "%5u: opcode:%s, fd:%d, flags:%x, off:%llu, "
+--
+2.53.0
+
--- /dev/null
+From 98c1740bf1f13bd0c6b8fc5592f463249a07605e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Mar 2026 18:39:41 +0100
+Subject: PM: hibernate: Drain trailing zero pages on userspace restore
+
+From: Alberto Garcia <berto@igalia.com>
+
+[ Upstream commit 734eba62cd32cb9ceffa09e57cdc03d761528525 ]
+
+Commit 005e8dddd497 ("PM: hibernate: don't store zero pages in the
+image file") added an optimization to skip zero-filled pages in the
+hibernation image. On restore, zero pages are handled internally by
+snapshot_write_next() in a loop that processes them without returning
+to the caller.
+
+With the userspace restore interface, writing the last non-zero page
+to /dev/snapshot is followed by the SNAPSHOT_ATOMIC_RESTORE ioctl. At
+this point there are no more calls to snapshot_write_next() so any
+trailing zero pages are not processed, snapshot_image_loaded() fails
+because handle->cur is smaller than expected, the ioctl returns -EPERM
+and the image is not restored.
+
+The in-kernel restore path is not affected by this because the loop in
+load_image() in swap.c calls snapshot_write_next() until it returns 0.
+It is this final call that drains any trailing zero pages.
+
+Fixed by calling snapshot_write_next() in snapshot_write_finalize(),
+giving the kernel the chance to drain any trailing zero pages.
+
+Fixes: 005e8dddd497 ("PM: hibernate: don't store zero pages in the image file")
+Signed-off-by: Alberto Garcia <berto@igalia.com>
+Acked-by: Brian Geffon <bgeffon@google.com>
+Link: https://patch.msgid.link/ef5a7c5e3e3dbd17dcb20efaa0c53a47a23498bb.1773075892.git.berto@igalia.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/snapshot.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
+index 0a946932d5c17..5706287e7230e 100644
+--- a/kernel/power/snapshot.c
++++ b/kernel/power/snapshot.c
+@@ -2855,6 +2855,17 @@ int snapshot_write_finalize(struct snapshot_handle *handle)
+ {
+ int error;
+
++ /*
++ * Call snapshot_write_next() to drain any trailing zero pages,
++ * but make sure we're in the data page region first.
++ * This function can return PAGE_SIZE if the kernel was expecting
++ * another copy page. Return -ENODATA in that situation.
++ */
++ if (handle->cur > nr_meta_pages + 1) {
++ error = snapshot_write_next(handle);
++ if (error)
++ return error > 0 ? -ENODATA : error;
++ }
+ copy_last_highmem_page();
+ error = hibernate_restore_protect_page(handle->buffer);
+ /* Do that only if we have loaded the image entirely */
+--
+2.53.0
+
--- /dev/null
+From adeb9b6c75d090ad5bc4ba16e589e6e1a8393d79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Mar 2026 21:05:28 +0900
+Subject: PM: sleep: Drop spurious WARN_ON() from pm_restore_gfp_mask()
+
+From: Youngjun Park <youngjun.park@lge.com>
+
+[ Upstream commit a8d51efb5929ae308895455a3e496b5eca2cd143 ]
+
+Commit 35e4a69b2003f ("PM: sleep: Allow pm_restrict_gfp_mask()
+stacking") introduced refcount-based GFP mask management that warns
+when pm_restore_gfp_mask() is called with saved_gfp_count == 0.
+
+Some hibernation paths call pm_restore_gfp_mask() defensively where
+the GFP mask may or may not be restricted depending on the execution
+path. For example, the uswsusp interface invokes it in
+SNAPSHOT_CREATE_IMAGE, SNAPSHOT_UNFREEZE, and snapshot_release().
+Before the stacking change this was a silent no-op; it now triggers
+a spurious WARNING.
+
+Remove the WARN_ON() wrapper from the !saved_gfp_count check while
+retaining the check itself, so that defensive calls remain harmless
+without producing false warnings.
+
+Fixes: 35e4a69b2003f ("PM: sleep: Allow pm_restrict_gfp_mask() stacking")
+Signed-off-by: Youngjun Park <youngjun.park@lge.com>
+[ rjw: Subject tweak ]
+Link: https://patch.msgid.link/20260322120528.750178-1-youngjun.park@lge.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/power/main.c b/kernel/power/main.c
+index 03b2c5495c77a..9ce75b1a23ed3 100644
+--- a/kernel/power/main.c
++++ b/kernel/power/main.c
+@@ -40,7 +40,7 @@ void pm_restore_gfp_mask(void)
+ {
+ WARN_ON(!mutex_is_locked(&system_transition_mutex));
+
+- if (WARN_ON(!saved_gfp_count) || --saved_gfp_count)
++ if (!saved_gfp_count || --saved_gfp_count)
+ return;
+
+ gfp_allowed_mask = saved_gfp_mask;
+--
+2.53.0
+
--- /dev/null
+From 23c3842e7112c12f086745efa9fdf59cac1042f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Mar 2026 23:36:45 -0500
+Subject: RDMA/bng_re: Fix silent failure in HWRM version query
+
+From: Kamal Heib <kheib@redhat.com>
+
+[ Upstream commit c242e92c9da456d361d1d4482fb6e93ee95bd8cf ]
+
+If the firmware version query fails, the driver currently ignores the
+error and continues initializing. This leaves the device in a bad state.
+
+Fix this by making bng_re_query_hwrm_version() return the error code and
+update the driver to check for this error and stop the setup process
+safely if it happens.
+
+Fixes: 745065770c2d ("RDMA/bng_re: Register and get the resources from bnge driver")
+Signed-off-by: Kamal Heib <kheib@redhat.com>
+Link: https://patch.msgid.link/20260303043645.425724-1-kheib@redhat.com
+Reviewed-by: Siva Reddy Kallam <siva.kallam@broadcom.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/bng_re/bng_dev.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/infiniband/hw/bng_re/bng_dev.c b/drivers/infiniband/hw/bng_re/bng_dev.c
+index fd0a4fe274ca6..9cf73f87070ec 100644
+--- a/drivers/infiniband/hw/bng_re/bng_dev.c
++++ b/drivers/infiniband/hw/bng_re/bng_dev.c
+@@ -210,7 +210,7 @@ static int bng_re_stats_ctx_alloc(struct bng_re_dev *rdev)
+ return rc;
+ }
+
+-static void bng_re_query_hwrm_version(struct bng_re_dev *rdev)
++static int bng_re_query_hwrm_version(struct bng_re_dev *rdev)
+ {
+ struct bnge_auxr_dev *aux_dev = rdev->aux_dev;
+ struct hwrm_ver_get_output ver_get_resp = {};
+@@ -230,7 +230,7 @@ static void bng_re_query_hwrm_version(struct bng_re_dev *rdev)
+ if (rc) {
+ ibdev_err(&rdev->ibdev, "Failed to query HW version, rc = 0x%x",
+ rc);
+- return;
++ return rc;
+ }
+
+ cctx = rdev->chip_ctx;
+@@ -244,6 +244,8 @@ static void bng_re_query_hwrm_version(struct bng_re_dev *rdev)
+
+ if (!cctx->hwrm_cmd_max_timeout)
+ cctx->hwrm_cmd_max_timeout = BNG_ROCE_FW_MAX_TIMEOUT;
++
++ return 0;
+ }
+
+ static void bng_re_dev_uninit(struct bng_re_dev *rdev)
+@@ -306,13 +308,15 @@ static int bng_re_dev_init(struct bng_re_dev *rdev)
+ goto msix_ctx_fail;
+ }
+
+- bng_re_query_hwrm_version(rdev);
++ rc = bng_re_query_hwrm_version(rdev);
++ if (rc)
++ goto destroy_chip_ctx;
+
+ rc = bng_re_alloc_fw_channel(&rdev->bng_res, &rdev->rcfw);
+ if (rc) {
+ ibdev_err(&rdev->ibdev,
+ "Failed to allocate RCFW Channel: %#x\n", rc);
+- goto alloc_fw_chl_fail;
++ goto destroy_chip_ctx;
+ }
+
+ /* Allocate nq record memory */
+@@ -391,7 +395,7 @@ static int bng_re_dev_init(struct bng_re_dev *rdev)
+ kfree(rdev->nqr);
+ nq_alloc_fail:
+ bng_re_free_rcfw_channel(&rdev->rcfw);
+-alloc_fw_chl_fail:
++destroy_chip_ctx:
+ bng_re_destroy_chip_ctx(rdev);
+ msix_ctx_fail:
+ bnge_unregister_dev(rdev->aux_dev);
+--
+2.53.0
+
--- /dev/null
+From 4dcb91da660e118a3ea75085a3495f835fce0dfc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Dec 2025 13:06:13 +0000
+Subject: RDMA/efa: Check stored completion CTX command ID with received one
+
+From: Yonatan Nachum <ynachum@amazon.com>
+
+[ Upstream commit 4b01ec0f133b3fe1038dc538d6bfcbd72462d2f0 ]
+
+In admin command completion, we receive a CQE with the command ID which
+is constructed from context index and entropy bits from the admin queue
+producer counter. To try to detect memory corruptions in the received
+CQE, validate the full command ID of the fetched context with the CQE
+command ID. If there is a mismatch, complete the CQE with error.
+Also use LSBs of the admin queue producer counter to better detect
+entropy mismatch between smaller number of commands.
+
+Reviewed-by: Daniel Kranzdorf <dkkranzd@amazon.com>
+Reviewed-by: Michael Margolin <mrgolin@amazon.com>
+Signed-off-by: Yonatan Nachum <ynachum@amazon.com>
+Link: https://patch.msgid.link/20251210130614.36460-2-ynachum@amazon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: ef3b06742c8a ("RDMA/efa: Fix use of completion ctx after free")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/efa/efa_com.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c
+index 0e979ca10d240..b31478f3a1212 100644
+--- a/drivers/infiniband/hw/efa/efa_com.c
++++ b/drivers/infiniband/hw/efa/efa_com.c
+@@ -3,6 +3,8 @@
+ * Copyright 2018-2025 Amazon.com, Inc. or its affiliates. All rights reserved.
+ */
+
++#include <linux/log2.h>
++
+ #include "efa_com.h"
+ #include "efa_regs_defs.h"
+
+@@ -317,7 +319,7 @@ static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queu
+
+ /* cmd_id LSBs are the ctx_id and MSBs are entropy bits from pc */
+ cmd_id = ctx_id & queue_size_mask;
+- cmd_id |= aq->sq.pc & ~queue_size_mask;
++ cmd_id |= aq->sq.pc << ilog2(aq->depth);
+ cmd_id &= EFA_ADMIN_AQ_COMMON_DESC_COMMAND_ID_MASK;
+
+ cmd->aq_common_descriptor.command_id = cmd_id;
+@@ -418,7 +420,7 @@ static int efa_com_handle_single_admin_completion(struct efa_com_admin_queue *aq
+ EFA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID);
+
+ comp_ctx = efa_com_get_comp_ctx(aq, cmd_id, false);
+- if (comp_ctx->status != EFA_CMD_SUBMITTED) {
++ if (comp_ctx->status != EFA_CMD_SUBMITTED || comp_ctx->cmd_id != cmd_id) {
+ ibdev_err(aq->efa_dev,
+ "Received completion with unexpected command id[%d], sq producer: %d, sq consumer: %d, cq consumer: %d\n",
+ cmd_id, aq->sq.pc, aq->sq.cc, aq->cq.cc);
+--
+2.53.0
+
--- /dev/null
+From 508dfcebd213f9e303ad79175ece6715e65a410e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Mar 2026 23:57:30 -0500
+Subject: RDMA/efa: Fix possible deadlock
+
+From: Ethan Tidmore <ethantidmore06@gmail.com>
+
+[ Upstream commit 0f2055db7b630559870afb40fc84490816ab8ec5 ]
+
+In the error path for efa_com_alloc_comp_ctx() the semaphore assigned to
+&aq->avail_cmds is not released.
+
+Detected by Smatch:
+drivers/infiniband/hw/efa/efa_com.c:662 efa_com_cmd_exec() warn:
+inconsistent returns '&aq->avail_cmds'
+
+Add release for &aq->avail_cmds in efa_com_alloc_comp_ctx() error path.
+
+Fixes: ef3b06742c8a2 ("RDMA/efa: Fix use of completion ctx after free")
+Signed-off-by: Ethan Tidmore <ethantidmore06@gmail.com>
+Link: https://patch.msgid.link/20260314045730.1143862-1-ethantidmore06@gmail.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/efa/efa_com.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c
+index 56caba612139f..e97b5f0d70038 100644
+--- a/drivers/infiniband/hw/efa/efa_com.c
++++ b/drivers/infiniband/hw/efa/efa_com.c
+@@ -629,6 +629,7 @@ int efa_com_cmd_exec(struct efa_com_admin_queue *aq,
+ comp_ctx = efa_com_alloc_comp_ctx(aq);
+ if (!comp_ctx) {
+ clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
++ up(&aq->avail_cmds);
+ return -EINVAL;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From b7081d965990257cf77d740a767274b50fded440 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Mar 2026 16:53:50 +0000
+Subject: RDMA/efa: Fix use of completion ctx after free
+
+From: Yonatan Nachum <ynachum@amazon.com>
+
+[ Upstream commit ef3b06742c8a201d0e83edc9a33a89a4fe3009f8 ]
+
+On admin queue completion handling, if the admin command completed with
+error we print data from the completion context. The issue is that we
+already freed the completion context in polling/interrupts handler which
+means we print data from context in an unknown state (it might be
+already used again).
+Change the admin submission flow so alloc/dealloc of the context will be
+symmetric and dealloc will be called after any potential use of the
+context.
+
+Fixes: 68fb9f3e312a ("RDMA/efa: Remove redundant NULL pointer check of CQE")
+Reviewed-by: Daniel Kranzdorf <dkkranzd@amazon.com>
+Reviewed-by: Michael Margolin <mrgolin@amazon.com>
+Signed-off-by: Yonatan Nachum <ynachum@amazon.com>
+Link: https://patch.msgid.link/20260308165350.18219-1-ynachum@amazon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/efa/efa_com.c | 87 +++++++++++++----------------
+ 1 file changed, 39 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c
+index 229b0ad3b0cbb..56caba612139f 100644
+--- a/drivers/infiniband/hw/efa/efa_com.c
++++ b/drivers/infiniband/hw/efa/efa_com.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+ /*
+- * Copyright 2018-2025 Amazon.com, Inc. or its affiliates. All rights reserved.
++ * Copyright 2018-2026 Amazon.com, Inc. or its affiliates. All rights reserved.
+ */
+
+ #include <linux/log2.h>
+@@ -310,23 +310,19 @@ static inline struct efa_comp_ctx *efa_com_get_comp_ctx_by_cmd_id(struct efa_com
+ return &aq->comp_ctx[ctx_id];
+ }
+
+-static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queue *aq,
+- struct efa_admin_aq_entry *cmd,
+- size_t cmd_size_in_bytes,
+- struct efa_admin_acq_entry *comp,
+- size_t comp_size_in_bytes)
++static void __efa_com_submit_admin_cmd(struct efa_com_admin_queue *aq,
++ struct efa_comp_ctx *comp_ctx,
++ struct efa_admin_aq_entry *cmd,
++ size_t cmd_size_in_bytes,
++ struct efa_admin_acq_entry *comp,
++ size_t comp_size_in_bytes)
+ {
+ struct efa_admin_aq_entry *aqe;
+- struct efa_comp_ctx *comp_ctx;
+ u16 queue_size_mask;
+ u16 cmd_id;
+ u16 ctx_id;
+ u16 pi;
+
+- comp_ctx = efa_com_alloc_comp_ctx(aq);
+- if (!comp_ctx)
+- return ERR_PTR(-EINVAL);
+-
+ queue_size_mask = aq->depth - 1;
+ pi = aq->sq.pc & queue_size_mask;
+ ctx_id = efa_com_get_comp_ctx_id(aq, comp_ctx);
+@@ -360,8 +356,6 @@ static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queu
+
+ /* barrier not needed in case of writel */
+ writel(aq->sq.pc, aq->sq.db_addr);
+-
+- return comp_ctx;
+ }
+
+ static inline int efa_com_init_comp_ctxt(struct efa_com_admin_queue *aq)
+@@ -394,28 +388,25 @@ static inline int efa_com_init_comp_ctxt(struct efa_com_admin_queue *aq)
+ return 0;
+ }
+
+-static struct efa_comp_ctx *efa_com_submit_admin_cmd(struct efa_com_admin_queue *aq,
+- struct efa_admin_aq_entry *cmd,
+- size_t cmd_size_in_bytes,
+- struct efa_admin_acq_entry *comp,
+- size_t comp_size_in_bytes)
++static int efa_com_submit_admin_cmd(struct efa_com_admin_queue *aq,
++ struct efa_comp_ctx *comp_ctx,
++ struct efa_admin_aq_entry *cmd,
++ size_t cmd_size_in_bytes,
++ struct efa_admin_acq_entry *comp,
++ size_t comp_size_in_bytes)
+ {
+- struct efa_comp_ctx *comp_ctx;
+-
+ spin_lock(&aq->sq.lock);
+ if (!test_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state)) {
+ ibdev_err_ratelimited(aq->efa_dev, "Admin queue is closed\n");
+ spin_unlock(&aq->sq.lock);
+- return ERR_PTR(-ENODEV);
++ return -ENODEV;
+ }
+
+- comp_ctx = __efa_com_submit_admin_cmd(aq, cmd, cmd_size_in_bytes, comp,
+- comp_size_in_bytes);
++ __efa_com_submit_admin_cmd(aq, comp_ctx, cmd, cmd_size_in_bytes, comp,
++ comp_size_in_bytes);
+ spin_unlock(&aq->sq.lock);
+- if (IS_ERR(comp_ctx))
+- clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
+
+- return comp_ctx;
++ return 0;
+ }
+
+ static int efa_com_handle_single_admin_completion(struct efa_com_admin_queue *aq,
+@@ -512,7 +503,6 @@ static int efa_com_wait_and_process_admin_cq_polling(struct efa_comp_ctx *comp_c
+ {
+ unsigned long timeout;
+ unsigned long flags;
+- int err;
+
+ timeout = jiffies + usecs_to_jiffies(aq->completion_timeout);
+
+@@ -532,24 +522,20 @@ static int efa_com_wait_and_process_admin_cq_polling(struct efa_comp_ctx *comp_c
+ atomic64_inc(&aq->stats.no_completion);
+
+ clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
+- err = -ETIME;
+- goto out;
++ return -ETIME;
+ }
+
+ msleep(aq->poll_interval);
+ }
+
+- err = efa_com_comp_status_to_errno(comp_ctx->user_cqe->acq_common_descriptor.status);
+-out:
+- efa_com_dealloc_comp_ctx(aq, comp_ctx);
+- return err;
++ return efa_com_comp_status_to_errno(
++ comp_ctx->user_cqe->acq_common_descriptor.status);
+ }
+
+ static int efa_com_wait_and_process_admin_cq_interrupts(struct efa_comp_ctx *comp_ctx,
+ struct efa_com_admin_queue *aq)
+ {
+ unsigned long flags;
+- int err;
+
+ wait_for_completion_timeout(&comp_ctx->wait_event,
+ usecs_to_jiffies(aq->completion_timeout));
+@@ -585,14 +571,11 @@ static int efa_com_wait_and_process_admin_cq_interrupts(struct efa_comp_ctx *com
+ aq->cq.cc);
+
+ clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
+- err = -ETIME;
+- goto out;
++ return -ETIME;
+ }
+
+- err = efa_com_comp_status_to_errno(comp_ctx->user_cqe->acq_common_descriptor.status);
+-out:
+- efa_com_dealloc_comp_ctx(aq, comp_ctx);
+- return err;
++ return efa_com_comp_status_to_errno(
++ comp_ctx->user_cqe->acq_common_descriptor.status);
+ }
+
+ /*
+@@ -642,30 +625,38 @@ int efa_com_cmd_exec(struct efa_com_admin_queue *aq,
+ ibdev_dbg(aq->efa_dev, "%s (opcode %d)\n",
+ efa_com_cmd_str(cmd->aq_common_descriptor.opcode),
+ cmd->aq_common_descriptor.opcode);
+- comp_ctx = efa_com_submit_admin_cmd(aq, cmd, cmd_size, comp, comp_size);
+- if (IS_ERR(comp_ctx)) {
++
++ comp_ctx = efa_com_alloc_comp_ctx(aq);
++ if (!comp_ctx) {
++ clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
++ return -EINVAL;
++ }
++
++ err = efa_com_submit_admin_cmd(aq, comp_ctx, cmd, cmd_size, comp, comp_size);
++ if (err) {
+ ibdev_err_ratelimited(
+ aq->efa_dev,
+- "Failed to submit command %s (opcode %u) err %pe\n",
++ "Failed to submit command %s (opcode %u) err %d\n",
+ efa_com_cmd_str(cmd->aq_common_descriptor.opcode),
+- cmd->aq_common_descriptor.opcode, comp_ctx);
++ cmd->aq_common_descriptor.opcode, err);
+
++ efa_com_dealloc_comp_ctx(aq, comp_ctx);
+ up(&aq->avail_cmds);
+ atomic64_inc(&aq->stats.cmd_err);
+- return PTR_ERR(comp_ctx);
++ return err;
+ }
+
+ err = efa_com_wait_and_process_admin_cq(comp_ctx, aq);
+ if (err) {
+ ibdev_err_ratelimited(
+ aq->efa_dev,
+- "Failed to process command %s (opcode %u) comp_status %d err %d\n",
++ "Failed to process command %s (opcode %u) err %d\n",
+ efa_com_cmd_str(cmd->aq_common_descriptor.opcode),
+- cmd->aq_common_descriptor.opcode,
+- comp_ctx->user_cqe->acq_common_descriptor.status, err);
++ cmd->aq_common_descriptor.opcode, err);
+ atomic64_inc(&aq->stats.cmd_err);
+ }
+
++ efa_com_dealloc_comp_ctx(aq, comp_ctx);
+ up(&aq->avail_cmds);
+
+ return err;
+--
+2.53.0
+
--- /dev/null
+From e12956e5377d59a5f6bd27e436a8e3580427e0a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Dec 2025 13:06:14 +0000
+Subject: RDMA/efa: Improve admin completion context state machine
+
+From: Yonatan Nachum <ynachum@amazon.com>
+
+[ Upstream commit dab5825491f7b0ea92a09390f39df0a51100f12f ]
+
+Add a new unused state to the admin completion contexts state machine
+instead of the occupied field. This improves the completion validity
+check because it now enforce the context to be in submitted state prior
+to completing it. Also add allocated state as a intermediate state
+between unused and submitted.
+
+Reviewed-by: Daniel Kranzdorf <dkkranzd@amazon.com>
+Reviewed-by: Michael Margolin <mrgolin@amazon.com>
+Signed-off-by: Yonatan Nachum <ynachum@amazon.com>
+Link: https://patch.msgid.link/20251210130614.36460-3-ynachum@amazon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: ef3b06742c8a ("RDMA/efa: Fix use of completion ctx after free")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/efa/efa_com.c | 91 ++++++++++++++++-------------
+ 1 file changed, 50 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c
+index b31478f3a1212..229b0ad3b0cbb 100644
+--- a/drivers/infiniband/hw/efa/efa_com.c
++++ b/drivers/infiniband/hw/efa/efa_com.c
+@@ -23,6 +23,8 @@
+ #define EFA_CTRL_SUB_MINOR 1
+
+ enum efa_cmd_status {
++ EFA_CMD_UNUSED,
++ EFA_CMD_ALLOCATED,
+ EFA_CMD_SUBMITTED,
+ EFA_CMD_COMPLETED,
+ };
+@@ -34,7 +36,6 @@ struct efa_comp_ctx {
+ enum efa_cmd_status status;
+ u16 cmd_id;
+ u8 cmd_opcode;
+- u8 occupied;
+ };
+
+ static const char *efa_com_cmd_str(u8 cmd)
+@@ -243,7 +244,6 @@ static int efa_com_admin_init_aenq(struct efa_com_dev *edev,
+ return 0;
+ }
+
+-/* ID to be used with efa_com_get_comp_ctx */
+ static u16 efa_com_alloc_ctx_id(struct efa_com_admin_queue *aq)
+ {
+ u16 ctx_id;
+@@ -265,36 +265,47 @@ static void efa_com_dealloc_ctx_id(struct efa_com_admin_queue *aq,
+ spin_unlock(&aq->comp_ctx_lock);
+ }
+
+-static inline void efa_com_put_comp_ctx(struct efa_com_admin_queue *aq,
+- struct efa_comp_ctx *comp_ctx)
++static struct efa_comp_ctx *efa_com_alloc_comp_ctx(struct efa_com_admin_queue *aq)
+ {
+- u16 cmd_id = EFA_GET(&comp_ctx->user_cqe->acq_common_descriptor.command,
+- EFA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID);
+- u16 ctx_id = cmd_id & (aq->depth - 1);
++ struct efa_comp_ctx *comp_ctx;
++ u16 ctx_id;
+
+- ibdev_dbg(aq->efa_dev, "Put completion command_id %#x\n", cmd_id);
+- comp_ctx->occupied = 0;
+- efa_com_dealloc_ctx_id(aq, ctx_id);
++ ctx_id = efa_com_alloc_ctx_id(aq);
++
++ comp_ctx = &aq->comp_ctx[ctx_id];
++ if (comp_ctx->status != EFA_CMD_UNUSED) {
++ efa_com_dealloc_ctx_id(aq, ctx_id);
++ ibdev_err_ratelimited(aq->efa_dev,
++ "Completion context[%u] is used[%u]\n",
++ ctx_id, comp_ctx->status);
++ return NULL;
++ }
++
++ comp_ctx->status = EFA_CMD_ALLOCATED;
++ ibdev_dbg(aq->efa_dev, "Take completion context[%u]\n", ctx_id);
++ return comp_ctx;
+ }
+
+-static struct efa_comp_ctx *efa_com_get_comp_ctx(struct efa_com_admin_queue *aq,
+- u16 cmd_id, bool capture)
++static inline u16 efa_com_get_comp_ctx_id(struct efa_com_admin_queue *aq,
++ struct efa_comp_ctx *comp_ctx)
+ {
+- u16 ctx_id = cmd_id & (aq->depth - 1);
++ return comp_ctx - aq->comp_ctx;
++}
+
+- if (aq->comp_ctx[ctx_id].occupied && capture) {
+- ibdev_err_ratelimited(
+- aq->efa_dev,
+- "Completion context for command_id %#x is occupied\n",
+- cmd_id);
+- return NULL;
+- }
++static inline void efa_com_dealloc_comp_ctx(struct efa_com_admin_queue *aq,
++ struct efa_comp_ctx *comp_ctx)
++{
++ u16 ctx_id = efa_com_get_comp_ctx_id(aq, comp_ctx);
+
+- if (capture) {
+- aq->comp_ctx[ctx_id].occupied = 1;
+- ibdev_dbg(aq->efa_dev,
+- "Take completion ctxt for command_id %#x\n", cmd_id);
+- }
++ ibdev_dbg(aq->efa_dev, "Put completion context[%u]\n", ctx_id);
++ comp_ctx->status = EFA_CMD_UNUSED;
++ efa_com_dealloc_ctx_id(aq, ctx_id);
++}
++
++static inline struct efa_comp_ctx *efa_com_get_comp_ctx_by_cmd_id(struct efa_com_admin_queue *aq,
++ u16 cmd_id)
++{
++ u16 ctx_id = cmd_id & (aq->depth - 1);
+
+ return &aq->comp_ctx[ctx_id];
+ }
+@@ -312,10 +323,13 @@ static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queu
+ u16 ctx_id;
+ u16 pi;
+
++ comp_ctx = efa_com_alloc_comp_ctx(aq);
++ if (!comp_ctx)
++ return ERR_PTR(-EINVAL);
++
+ queue_size_mask = aq->depth - 1;
+ pi = aq->sq.pc & queue_size_mask;
+-
+- ctx_id = efa_com_alloc_ctx_id(aq);
++ ctx_id = efa_com_get_comp_ctx_id(aq, comp_ctx);
+
+ /* cmd_id LSBs are the ctx_id and MSBs are entropy bits from pc */
+ cmd_id = ctx_id & queue_size_mask;
+@@ -326,12 +340,6 @@ static struct efa_comp_ctx *__efa_com_submit_admin_cmd(struct efa_com_admin_queu
+ EFA_SET(&cmd->aq_common_descriptor.flags,
+ EFA_ADMIN_AQ_COMMON_DESC_PHASE, aq->sq.phase);
+
+- comp_ctx = efa_com_get_comp_ctx(aq, cmd_id, true);
+- if (!comp_ctx) {
+- efa_com_dealloc_ctx_id(aq, ctx_id);
+- return ERR_PTR(-EINVAL);
+- }
+-
+ comp_ctx->status = EFA_CMD_SUBMITTED;
+ comp_ctx->comp_size = comp_size_in_bytes;
+ comp_ctx->user_cqe = comp;
+@@ -372,9 +380,9 @@ static inline int efa_com_init_comp_ctxt(struct efa_com_admin_queue *aq)
+ }
+
+ for (i = 0; i < aq->depth; i++) {
+- comp_ctx = efa_com_get_comp_ctx(aq, i, false);
+- if (comp_ctx)
+- init_completion(&comp_ctx->wait_event);
++ comp_ctx = &aq->comp_ctx[i];
++ comp_ctx->status = EFA_CMD_UNUSED;
++ init_completion(&comp_ctx->wait_event);
+
+ aq->comp_ctx_pool[i] = i;
+ }
+@@ -419,11 +427,12 @@ static int efa_com_handle_single_admin_completion(struct efa_com_admin_queue *aq
+ cmd_id = EFA_GET(&cqe->acq_common_descriptor.command,
+ EFA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID);
+
+- comp_ctx = efa_com_get_comp_ctx(aq, cmd_id, false);
++ comp_ctx = efa_com_get_comp_ctx_by_cmd_id(aq, cmd_id);
+ if (comp_ctx->status != EFA_CMD_SUBMITTED || comp_ctx->cmd_id != cmd_id) {
+ ibdev_err(aq->efa_dev,
+- "Received completion with unexpected command id[%d], sq producer: %d, sq consumer: %d, cq consumer: %d\n",
+- cmd_id, aq->sq.pc, aq->sq.cc, aq->cq.cc);
++ "Received completion with unexpected command id[%x], status[%d] sq producer[%d], sq consumer[%d], cq consumer[%d]\n",
++ cmd_id, comp_ctx->status, aq->sq.pc, aq->sq.cc,
++ aq->cq.cc);
+ return -EINVAL;
+ }
+
+@@ -532,7 +541,7 @@ static int efa_com_wait_and_process_admin_cq_polling(struct efa_comp_ctx *comp_c
+
+ err = efa_com_comp_status_to_errno(comp_ctx->user_cqe->acq_common_descriptor.status);
+ out:
+- efa_com_put_comp_ctx(aq, comp_ctx);
++ efa_com_dealloc_comp_ctx(aq, comp_ctx);
+ return err;
+ }
+
+@@ -582,7 +591,7 @@ static int efa_com_wait_and_process_admin_cq_interrupts(struct efa_comp_ctx *com
+
+ err = efa_com_comp_status_to_errno(comp_ctx->user_cqe->acq_common_descriptor.status);
+ out:
+- efa_com_put_comp_ctx(aq, comp_ctx);
++ efa_com_dealloc_comp_ctx(aq, comp_ctx);
+ return err;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 8a5b22010ef99beac37bb20f305d9ed157ce5693 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:43 -0500
+Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node
+
+From: Ivan Barrera <ivan.d.barrera@intel.com>
+
+[ Upstream commit b415399c9a024d574b65479636f0d4eb625b9abd ]
+
+The cm_node is available and the usage of cm_node and event->cm_node
+seems arbitrary. Clean up unnecessary dereference of event->cm_node.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Ivan Barrera <ivan.d.barrera@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index f4f4f92ba63ac..128cfcf27714d 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -4239,21 +4239,21 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ irdma_cm_event_reset(event);
+ break;
+ case IRDMA_CM_EVENT_CONNECTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state != IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state != IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_cm_event_connected(event);
+ break;
+ case IRDMA_CM_EVENT_MPA_REJECT:
+- if (!event->cm_node->cm_id ||
++ if (!cm_node->cm_id ||
+ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_send_cm_event(cm_node, cm_node->cm_id,
+ IW_CM_EVENT_CONNECT_REPLY, -ECONNREFUSED);
+ break;
+ case IRDMA_CM_EVENT_ABORTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state == IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_event_connect_error(event);
+ break;
+@@ -4263,7 +4263,7 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ break;
+ }
+
+- irdma_rem_ref_cm_node(event->cm_node);
++ irdma_rem_ref_cm_node(cm_node);
+ kfree(event);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From d372db3290fe5044c708df2dd7ea2545c1d632ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:45 -0500
+Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections
+
+From: Anil Samal <anil.samal@intel.com>
+
+[ Upstream commit 6f52370970ac07d352a7af4089e55e0e6425f827 ]
+
+Resolve deadlock that occurs when user executes netdev reset while RDMA
+applications (e.g., rping) are active. The netdev reset causes ice
+driver to remove irdma auxiliary driver, triggering device_delete and
+subsequent client removal. During client removal, uverbs_client waits
+for QP reference count to reach zero while cma_client holds the final
+reference, creating circular dependency and indefinite wait in iWARP
+mode. Skip QP reference count wait during device reset to prevent
+deadlock.
+
+Fixes: c8f304d75f6c ("RDMA/irdma: Prevent QP use after free")
+Signed-off-by: Anil Samal <anil.samal@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index ac3a8f3f95b7f..c454a006c78e0 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -558,7 +558,8 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+ }
+
+ irdma_qp_rem_ref(&iwqp->ibqp);
+- wait_for_completion(&iwqp->free_qp);
++ if (!iwdev->rf->reset)
++ wait_for_completion(&iwqp->free_qp);
+ irdma_free_lsmm_rsrc(iwqp);
+ irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
+
+--
+2.53.0
+
--- /dev/null
+From c0a7b402956772256553cc5d99e505ad457d3d8e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:47 -0500
+Subject: RDMA/irdma: Harden depth calculation functions
+
+From: Shiraz Saleem <shiraz.saleem@intel.com>
+
+[ Upstream commit e37afcb56ae070477741fe2d6e61fc0c542cce2d ]
+
+An issue was exposed where OS can pass in U32_MAX for SQ/RQ/SRQ size.
+This can cause integer overflow and truncation of SQ/RQ/SRQ depth
+returning a success when it should have failed.
+
+Harden the functions to do all depth calculations and boundary
+checking in u64 sizes.
+
+Fixes: 563e1feb5f6e ("RDMA/irdma: Add SRQ support")
+Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/uk.c | 39 ++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/uk.c b/drivers/infiniband/hw/irdma/uk.c
+index f0846b800913d..3d6d0ee57c4c1 100644
+--- a/drivers/infiniband/hw/irdma/uk.c
++++ b/drivers/infiniband/hw/irdma/uk.c
+@@ -1442,7 +1442,7 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
+ * irdma_round_up_wq - return round up qp wq depth
+ * @wqdepth: wq depth in quanta to round up
+ */
+-static int irdma_round_up_wq(u32 wqdepth)
++static u64 irdma_round_up_wq(u64 wqdepth)
+ {
+ int scount = 1;
+
+@@ -1495,15 +1495,16 @@ void irdma_get_wqe_shift(struct irdma_uk_attrs *uk_attrs, u32 sge,
+ int irdma_get_sqdepth(struct irdma_uk_attrs *uk_attrs, u32 sq_size, u8 shift,
+ u32 *sqdepth)
+ {
+- u32 min_size = (u32)uk_attrs->min_hw_wq_size << shift;
++ u32 min_hw_quanta = (u32)uk_attrs->min_hw_wq_size << shift;
++ u64 hw_quanta =
++ irdma_round_up_wq(((u64)sq_size << shift) + IRDMA_SQ_RSVD);
+
+- *sqdepth = irdma_round_up_wq((sq_size << shift) + IRDMA_SQ_RSVD);
+-
+- if (*sqdepth < min_size)
+- *sqdepth = min_size;
+- else if (*sqdepth > uk_attrs->max_hw_wq_quanta)
++ if (hw_quanta < min_hw_quanta)
++ hw_quanta = min_hw_quanta;
++ else if (hw_quanta > uk_attrs->max_hw_wq_quanta)
+ return -EINVAL;
+
++ *sqdepth = hw_quanta;
+ return 0;
+ }
+
+@@ -1517,15 +1518,16 @@ int irdma_get_sqdepth(struct irdma_uk_attrs *uk_attrs, u32 sq_size, u8 shift,
+ int irdma_get_rqdepth(struct irdma_uk_attrs *uk_attrs, u32 rq_size, u8 shift,
+ u32 *rqdepth)
+ {
+- u32 min_size = (u32)uk_attrs->min_hw_wq_size << shift;
+-
+- *rqdepth = irdma_round_up_wq((rq_size << shift) + IRDMA_RQ_RSVD);
++ u32 min_hw_quanta = (u32)uk_attrs->min_hw_wq_size << shift;
++ u64 hw_quanta =
++ irdma_round_up_wq(((u64)rq_size << shift) + IRDMA_RQ_RSVD);
+
+- if (*rqdepth < min_size)
+- *rqdepth = min_size;
+- else if (*rqdepth > uk_attrs->max_hw_rq_quanta)
++ if (hw_quanta < min_hw_quanta)
++ hw_quanta = min_hw_quanta;
++ else if (hw_quanta > uk_attrs->max_hw_rq_quanta)
+ return -EINVAL;
+
++ *rqdepth = hw_quanta;
+ return 0;
+ }
+
+@@ -1539,13 +1541,16 @@ int irdma_get_rqdepth(struct irdma_uk_attrs *uk_attrs, u32 rq_size, u8 shift,
+ int irdma_get_srqdepth(struct irdma_uk_attrs *uk_attrs, u32 srq_size, u8 shift,
+ u32 *srqdepth)
+ {
+- *srqdepth = irdma_round_up_wq((srq_size << shift) + IRDMA_RQ_RSVD);
++ u32 min_hw_quanta = (u32)uk_attrs->min_hw_wq_size << shift;
++ u64 hw_quanta =
++ irdma_round_up_wq(((u64)srq_size << shift) + IRDMA_RQ_RSVD);
+
+- if (*srqdepth < ((u32)uk_attrs->min_hw_wq_size << shift))
+- *srqdepth = uk_attrs->min_hw_wq_size << shift;
+- else if (*srqdepth > uk_attrs->max_hw_srq_quanta)
++ if (hw_quanta < min_hw_quanta)
++ hw_quanta = min_hw_quanta;
++ else if (hw_quanta > uk_attrs->max_hw_srq_quanta)
+ return -EINVAL;
+
++ *srqdepth = hw_quanta;
+ return 0;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 70810559a7684d0a79a8b5de3ad67968c394859f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:38 -0500
+Subject: RDMA/irdma: Initialize free_qp completion before using it
+
+From: Jacob Moroni <jmoroni@google.com>
+
+[ Upstream commit 11a95521fb93c91e2d4ef9d53dc80ef0a755549b ]
+
+In irdma_create_qp, if ib_copy_to_udata fails, it will call
+irdma_destroy_qp to clean up which will attempt to wait on
+the free_qp completion, which is not initialized yet. Fix this
+by initializing the completion before the ib_copy_to_udata call.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Jacob Moroni <jmoroni@google.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 68fb81b7bd221..d279a015094be 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1105,6 +1105,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ spin_lock_init(&iwqp->sc_qp.pfpdu.lock);
+ iwqp->sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
+ rf->qp_table[qp_num] = iwqp;
++ init_completion(&iwqp->free_qp);
+
+ if (udata) {
+ /* GEN_1 legacy support with libi40iw does not have expanded uresp struct */
+@@ -1129,7 +1130,6 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ }
+ }
+
+- init_completion(&iwqp->free_qp);
+ return 0;
+
+ error:
+--
+2.53.0
+
--- /dev/null
+From 0e98508882991a6c822580e549720a7fded9ad39 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:42 -0500
+Subject: RDMA/irdma: Remove a NOP wait_event() in irdma_modify_qp_roce()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 5e8f0239731a83753473b7aa91bda67bbdff5053 ]
+
+Remove a NOP wait_event() in irdma_modify_qp_roce() which is relevant
+for iWARP and likely a copy and paste artifact for RoCEv2. The wait event
+is for sending a reset on a TCP connection, after the reset has been
+requested in irdma_modify_qp(), which occurs only in iWarp mode.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index c34188e322085..ac3a8f3f95b7f 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1462,8 +1462,6 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ ctx_info->remote_atomics_en = true;
+ }
+
+- wait_event(iwqp->mod_qp_waitq, !atomic_read(&iwqp->hw_mod_qp_pend));
+-
+ ibdev_dbg(&iwdev->ibdev,
+ "VERBS: caller: %pS qp_id=%d to_ibqpstate=%d ibqpstate=%d irdma_qpstate=%d attr_mask=0x%x\n",
+ __builtin_return_address(0), ibqp->qp_num, attr->qp_state,
+--
+2.53.0
+
--- /dev/null
+From ce51eba4625af547346d57fa36f84709542988bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:44 -0500
+Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit c45c6ebd693b944f1ffe429fdfb6cc1674c237be ]
+
+During reset, irdma_modify_qp() to error should be called to disconnect
+the QP. Without this fix, if not preceded by irdma_modify_qp() to error, the
+API call irdma_destroy_qp() gets stuck waiting for the QP refcount to go
+to zero, because the cm_node associated with this QP isn't disconnected.
+
+Fixes: 915cc7ac0f8e ("RDMA/irdma: Add miscellaneous utility definitions")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/utils.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
+index 13d7499131d48..89c4fe05763e4 100644
+--- a/drivers/infiniband/hw/irdma/utils.c
++++ b/drivers/infiniband/hw/irdma/utils.c
+@@ -2321,8 +2321,6 @@ void irdma_modify_qp_to_err(struct irdma_sc_qp *sc_qp)
+ struct irdma_qp *qp = sc_qp->qp_uk.back_qp;
+ struct ib_qp_attr attr;
+
+- if (qp->iwdev->rf->reset)
+- return;
+ attr.qp_state = IB_QPS_ERR;
+
+ if (rdma_protocol_roce(qp->ibqp.device, 1))
+--
+2.53.0
+
--- /dev/null
+From bef5b70468c4fae0fdd85eea73df09fdf9e661c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:46 -0500
+Subject: RDMA/irdma: Return EINVAL for invalid arp index error
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 7221f581eefa79ead06e171044f393fb7ee22f87 ]
+
+When rdma_connect() fails due to an invalid arp index, user space rdma core
+reports ENOMEM which is confusing. Modify irdma_make_cm_node() to return the
+correct error code.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index 128cfcf27714d..d14a381beb661 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -2241,11 +2241,12 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ int oldarpindex;
+ int arpindex;
+ struct net_device *netdev = iwdev->netdev;
++ int ret;
+
+ /* create an hte and cm_node for this instance */
+ cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
+ if (!cm_node)
+- return NULL;
++ return ERR_PTR(-ENOMEM);
+
+ /* set our node specific transport info */
+ cm_node->ipv4 = cm_info->ipv4;
+@@ -2348,8 +2349,10 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ arpindex = -EINVAL;
+ }
+
+- if (arpindex < 0)
++ if (arpindex < 0) {
++ ret = -EINVAL;
+ goto err;
++ }
+
+ ether_addr_copy(cm_node->rem_mac,
+ iwdev->rf->arp_table[arpindex].mac_addr);
+@@ -2360,7 +2363,7 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ err:
+ kfree(cm_node);
+
+- return NULL;
++ return ERR_PTR(ret);
+ }
+
+ static void irdma_destroy_connection(struct irdma_cm_node *cm_node)
+@@ -3021,8 +3024,8 @@ static int irdma_create_cm_node(struct irdma_cm_core *cm_core,
+
+ /* create a CM connection node */
+ cm_node = irdma_make_cm_node(cm_core, iwdev, cm_info, NULL);
+- if (!cm_node)
+- return -ENOMEM;
++ if (IS_ERR(cm_node))
++ return PTR_ERR(cm_node);
+
+ /* set our node side to client (active) side */
+ cm_node->tcp_cntxt.client = 1;
+@@ -3219,9 +3222,9 @@ void irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf)
+ cm_info.cm_id = listener->cm_id;
+ cm_node = irdma_make_cm_node(cm_core, iwdev, &cm_info,
+ listener);
+- if (!cm_node) {
++ if (IS_ERR(cm_node)) {
+ ibdev_dbg(&cm_core->iwdev->ibdev,
+- "CM: allocate node failed\n");
++ "CM: allocate node failed ret=%ld\n", PTR_ERR(cm_node));
+ refcount_dec(&listener->refcnt);
+ return;
+ }
+--
+2.53.0
+
--- /dev/null
+From f689fcde0a5bac19fdd7306bcfa8cbb769b642ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:41 -0500
+Subject: RDMA/irdma: Update ibqp state to error if QP is already in error
+ state
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 8c1f19a2225cf37b3f8ab0b5a8a5322291cda620 ]
+
+In irdma_modify_qp() update ibqp state to error if the irdma QP is already
+in error state, otherwise the ibqp state which is visible to the consumer
+app remains stale.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index d279a015094be..c34188e322085 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1540,6 +1540,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+@@ -1745,6 +1746,7 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+--
+2.53.0
+
--- /dev/null
+From 16cd84d58ee16b36aed602334055686da9448fc0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Mar 2026 15:41:58 -0400
+Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 00da250c21b074ea9494c375d0117b69e5b1d0a4 ]
+
+When IOMMU passthrough mode is active, ib_dma_map_sgtable_attrs()
+produces no coalescing: each scatterlist page maps 1:1 to a DMA
+entry, so sgt.nents equals the raw page count. A 1 MB transfer
+yields 256 DMA entries. If that count exceeds the device's
+max_sgl_rd threshold (an optimization hint from mlx5 firmware),
+rdma_rw_io_needs_mr() steers the operation into the MR
+registration path. Each such operation consumes one or more MRs
+from a pool sized at max_rdma_ctxs -- roughly one MR per
+concurrent context. Under write-intensive workloads that issue
+many concurrent RDMA READs, the pool is rapidly exhausted,
+ib_mr_pool_get() returns NULL, and rdma_rw_init_one_mr() returns
+-EAGAIN. Upper layer protocols treat this as a fatal DMA mapping
+failure and tear down the connection.
+
+The max_sgl_rd check is a performance optimization, not a
+correctness requirement: the device can handle large SGE counts
+via direct posting, just less efficiently than with MR
+registration. When the MR pool cannot satisfy a request, falling
+back to the direct SGE (map_wrs) path avoids the connection
+reset while preserving the MR optimization for the common case
+where pool resources are available.
+
+Add a fallback in rdma_rw_ctx_init() so that -EAGAIN from
+rdma_rw_init_mr_wrs() triggers direct SGE posting instead of
+propagating the error. iWARP devices, which mandate MR
+registration for RDMA READs, and force_mr debug mode continue
+to treat -EAGAIN as terminal.
+
+Fixes: 00bd1439f464 ("RDMA/rw: Support threshold for registration vs scattering to local pages")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/rw.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
+index 2522ff1cc462c..49fbfe1cef689 100644
+--- a/drivers/infiniband/core/rw.c
++++ b/drivers/infiniband/core/rw.c
+@@ -326,14 +326,29 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u32 port_num,
+ if (rdma_rw_io_needs_mr(qp->device, port_num, dir, sg_cnt)) {
+ ret = rdma_rw_init_mr_wrs(ctx, qp, port_num, sg, sg_cnt,
+ sg_offset, remote_addr, rkey, dir);
+- } else if (sg_cnt > 1) {
++ /*
++ * If MR init succeeded or failed for a reason other
++ * than pool exhaustion, that result is final.
++ *
++ * Pool exhaustion (-EAGAIN) from the max_sgl_rd
++ * optimization is recoverable: fall back to
++ * direct SGE posting. iWARP and force_mr require
++ * MRs unconditionally, so -EAGAIN is terminal.
++ */
++ if (ret != -EAGAIN ||
++ rdma_protocol_iwarp(qp->device, port_num) ||
++ unlikely(rdma_rw_force_mr))
++ goto out;
++ }
++
++ if (sg_cnt > 1)
+ ret = rdma_rw_init_map_wrs(ctx, qp, sg, sg_cnt, sg_offset,
+ remote_addr, rkey, dir);
+- } else {
++ else
+ ret = rdma_rw_init_single_wr(ctx, qp, sg, sg_offset,
+ remote_addr, rkey, dir);
+- }
+
++out:
+ if (ret < 0)
+ goto out_unmap_sg;
+ return ret;
+--
+2.53.0
+
--- /dev/null
+From 7285ada4166f6e095d36c63b7915c2ef2057317d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Mar 2026 19:43:31 +0100
+Subject: regmap: Synchronize cache for the page selector
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 09e70e4f119ff650d24c96161fd2f62ac7e424b0 ]
+
+If the selector register is represented in each page, its value
+according to the debugfs is stale because it gets synchronized
+only after the real page switch happens. Hence the regmap cache
+initialisation from the HW inherits outdated data in the selector
+register.
+
+Synchronize cache for the page selector just in time.
+
+Before (offset followed by hexdump, the first byte is selector):
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 05 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 01 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 02 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 03 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 04 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+After:
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 01 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 02 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 03 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 04 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+Fixes: 6863ca622759 ("regmap: Add support for register indirect addressing.")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap.c | 30 ++++++++++++++++++++++++++----
+ 1 file changed, 26 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index ae2215d4e61c3..a648218507236 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -1543,6 +1543,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ unsigned int val_num)
+ {
+ void *orig_work_buf;
++ unsigned int selector_reg;
+ unsigned int win_offset;
+ unsigned int win_page;
+ bool page_chg;
+@@ -1561,10 +1562,31 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ return -EINVAL;
+ }
+
+- /* It is possible to have selector register inside data window.
+- In that case, selector register is located on every page and
+- it needs no page switching, when accessed alone. */
++ /*
++ * Calculate the address of the selector register in the corresponding
++ * data window if it is located on every page.
++ */
++ page_chg = in_range(range->selector_reg, range->window_start, range->window_len);
++ if (page_chg)
++ selector_reg = range->range_min + win_page * range->window_len +
++ range->selector_reg - range->window_start;
++
++ /*
++ * It is possible to have selector register inside data window.
++ * In that case, selector register is located on every page and it
++ * needs no page switching, when accessed alone.
++ *
++ * Nevertheless we should synchronize the cache values for it.
++ * This can't be properly achieved if the selector register is
++ * the first and the only one to be read inside the data window.
++ * That's why we update it in that case as well.
++ *
++ * However, we specifically avoid updating it for the default page,
++ * when it's overlapped with the real data window, to prevent from
++ * infinite looping.
++ */
+ if (val_num > 1 ||
++ (page_chg && selector_reg != range->selector_reg) ||
+ range->window_start + win_offset != range->selector_reg) {
+ /* Use separate work_buf during page switching */
+ orig_work_buf = map->work_buf;
+@@ -1573,7 +1595,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ ret = _regmap_update_bits(map, range->selector_reg,
+ range->selector_mask,
+ win_page << range->selector_shift,
+- &page_chg, false);
++ NULL, false);
+
+ map->work_buf = orig_work_buf;
+
+--
+2.53.0
+
--- /dev/null
+From 01fe336cdb6288a5829e92c8e18a96113e009af9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 10:49:59 +0000
+Subject: rust: regulator: do not assume that regulator_get() returns non-null
+
+From: Alice Ryhl <aliceryhl@google.com>
+
+[ Upstream commit 8121353a4bf8e38afee26299419a78ec108e14a6 ]
+
+The Rust `Regulator` abstraction uses `NonNull` to wrap the underlying
+`struct regulator` pointer. When `CONFIG_REGULATOR` is disabled, the C
+stub for `regulator_get` returns `NULL`. `from_err_ptr` does not treat
+`NULL` as an error, so it was passed to `NonNull::new_unchecked`,
+causing undefined behavior.
+
+Fix this by using a raw pointer `*mut bindings::regulator` instead of
+`NonNull`. This allows `inner` to be `NULL` when `CONFIG_REGULATOR` is
+disabled, and leverages the C stubs which are designed to handle `NULL`
+or are no-ops.
+
+Fixes: 9b614ceada7c ("rust: regulator: add a bare minimum regulator abstraction")
+Reported-by: Miguel Ojeda <ojeda@kernel.org>
+Closes: https://lore.kernel.org/r/20260322193830.89324-1-ojeda@kernel.org
+Signed-off-by: Alice Ryhl <aliceryhl@google.com>
+Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
+Link: https://patch.msgid.link/20260324-regulator-fix-v1-1-a5244afa3c15@google.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ rust/kernel/regulator.rs | 33 ++++++++++++++++++---------------
+ 1 file changed, 18 insertions(+), 15 deletions(-)
+
+diff --git a/rust/kernel/regulator.rs b/rust/kernel/regulator.rs
+index 2c44827ad0b7e..40c7f2209867d 100644
+--- a/rust/kernel/regulator.rs
++++ b/rust/kernel/regulator.rs
+@@ -23,7 +23,10 @@ use crate::{
+ prelude::*,
+ };
+
+-use core::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull};
++use core::{
++ marker::PhantomData,
++ mem::ManuallyDrop, //
++};
+
+ mod private {
+ pub trait Sealed {}
+@@ -232,15 +235,17 @@ pub fn devm_enable_optional(dev: &Device<Bound>, name: &CStr) -> Result {
+ ///
+ /// # Invariants
+ ///
+-/// - `inner` is a non-null wrapper over a pointer to a `struct
+-/// regulator` obtained from [`regulator_get()`].
++/// - `inner` is a pointer obtained from a successful call to
++/// [`regulator_get()`]. It is treated as an opaque token that may only be
++/// accessed using C API methods (e.g., it may be `NULL` if the C API returns
++/// `NULL`).
+ ///
+ /// [`regulator_get()`]: https://docs.kernel.org/driver-api/regulator.html#c.regulator_get
+ pub struct Regulator<State>
+ where
+ State: RegulatorState,
+ {
+- inner: NonNull<bindings::regulator>,
++ inner: *mut bindings::regulator,
+ _phantom: PhantomData<State>,
+ }
+
+@@ -252,7 +257,7 @@ impl<T: RegulatorState> Regulator<T> {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+ to_result(unsafe {
+ bindings::regulator_set_voltage(
+- self.inner.as_ptr(),
++ self.inner,
+ min_voltage.as_microvolts(),
+ max_voltage.as_microvolts(),
+ )
+@@ -262,7 +267,7 @@ impl<T: RegulatorState> Regulator<T> {
+ /// Gets the current voltage of the regulator.
+ pub fn get_voltage(&self) -> Result<Voltage> {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+- let voltage = unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) };
++ let voltage = unsafe { bindings::regulator_get_voltage(self.inner) };
+
+ to_result(voltage).map(|()| Voltage::from_microvolts(voltage))
+ }
+@@ -273,10 +278,8 @@ impl<T: RegulatorState> Regulator<T> {
+ // received from the C code.
+ from_err_ptr(unsafe { bindings::regulator_get(dev.as_raw(), name.as_char_ptr()) })?;
+
+- // SAFETY: We can safely trust `inner` to be a pointer to a valid
+- // regulator if `ERR_PTR` was not returned.
+- let inner = unsafe { NonNull::new_unchecked(inner) };
+-
++ // INVARIANT: `inner` is a pointer obtained from `regulator_get()`, and
++ // the call was successful.
+ Ok(Self {
+ inner,
+ _phantom: PhantomData,
+@@ -285,12 +288,12 @@ impl<T: RegulatorState> Regulator<T> {
+
+ fn enable_internal(&self) -> Result {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+- to_result(unsafe { bindings::regulator_enable(self.inner.as_ptr()) })
++ to_result(unsafe { bindings::regulator_enable(self.inner) })
+ }
+
+ fn disable_internal(&self) -> Result {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+- to_result(unsafe { bindings::regulator_disable(self.inner.as_ptr()) })
++ to_result(unsafe { bindings::regulator_disable(self.inner) })
+ }
+ }
+
+@@ -352,7 +355,7 @@ impl<T: IsEnabled> Regulator<T> {
+ /// Checks if the regulator is enabled.
+ pub fn is_enabled(&self) -> bool {
+ // SAFETY: Safe as per the type invariants of `Regulator`.
+- unsafe { bindings::regulator_is_enabled(self.inner.as_ptr()) != 0 }
++ unsafe { bindings::regulator_is_enabled(self.inner) != 0 }
+ }
+ }
+
+@@ -362,11 +365,11 @@ impl<T: RegulatorState> Drop for Regulator<T> {
+ // SAFETY: By the type invariants, we know that `self` owns a
+ // reference on the enabled refcount, so it is safe to relinquish it
+ // now.
+- unsafe { bindings::regulator_disable(self.inner.as_ptr()) };
++ unsafe { bindings::regulator_disable(self.inner) };
+ }
+ // SAFETY: By the type invariants, we know that `self` owns a reference,
+ // so it is safe to relinquish it now.
+- unsafe { bindings::regulator_put(self.inner.as_ptr()) };
++ unsafe { bindings::regulator_put(self.inner) };
+ }
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 6d07a464c5b5f6e6b2f338fda873e4ba301d0d1d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 14:31:47 +0800
+Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue
+
+From: Yihang Li <liyihang9@huawei.com>
+
+[ Upstream commit d71afa9deb4d413232ba16d693f7d43b321931b4 ]
+
+After commit 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard
+and multi-channel scans"), if the device supports multiple channels (0 to
+shost->max_channel), user_scan() invokes updated sas_user_scan() to perform
+the scan behavior for a specific transfer. However, when the user
+specifies shost->max_channel, it will return -EINVAL, which is not
+expected.
+
+Fix and support specifying the scan shost->max_channel for scanning.
+
+Fixes: 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans")
+Signed-off-by: Yihang Li <liyihang9@huawei.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_sas.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index d69c7c444a311..081c168094374 100644
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -1734,7 +1734,7 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ break;
+
+ default:
+- if (channel < shost->max_channel) {
++ if (channel <= shost->max_channel) {
+ res = scsi_scan_host_selected(shost, channel, id, lun,
+ SCSI_SCAN_MANUAL);
+ } else {
+--
+2.53.0
+
netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch
netfilter-ctnetlink-use-netlink-policy-range-checks.patch
net-macb-use-the-current-queue-number-for-stats.patch
+rdma-bng_re-fix-silent-failure-in-hwrm-version-query.patch
+rdma-efa-check-stored-completion-ctx-command-id-with.patch
+rdma-efa-improve-admin-completion-context-state-mach.patch
+rdma-efa-fix-use-of-completion-ctx-after-free.patch
+regmap-synchronize-cache-for-the-page-selector.patch
+alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch
+rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch
+rdma-efa-fix-possible-deadlock.patch
+alsa-usb-audio-exclude-scarlett-2i2-1st-gen-from-ski.patch
+rdma-irdma-initialize-free_qp-completion-before-usin.patch
+rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch
+rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch
+rdma-irdma-clean-up-unnecessary-dereference-of-event.patch
+rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch
+rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch
+rdma-irdma-return-einval-for-invalid-arp-index-error.patch
+rdma-irdma-harden-depth-calculation-functions.patch
+asoc-simple-card-utils-check-value-of-is_playback_on.patch
+asoc-fsl-imx-card-initialize-playback_only-and-captu.patch
+scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch
+x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch
+drm-mediatek-dsi-store-driver-data-before-invoking-m.patch
+drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch
+pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch
+pm-sleep-drop-spurious-warn_on-from-pm_restore_gfp_m.patch
+drm-xe-pf-fix-use-after-free-in-migration-restore.patch
+spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch
+asoc-intel-catpt-fix-the-device-initialization.patch
+spi-meson-spicc-fix-double-put-in-remove-path.patch
+drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch
+asoc-dt-bindings-stm32-fix-incorrect-compatible-stri.patch
+rust-regulator-do-not-assume-that-regulator_get-retu.patch
+drm-xe-implement-recent-spec-updates-to-wa_160252501.patch
+spi-use-generic-driver_override-infrastructure.patch
+acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch
+drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch
+hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch
+asoc-sdca-fix-finding-wrong-entity.patch
+hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch
+hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch
+hwmon-pmbus-core-protect-regulator-operations-with-m.patch
+sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch
+asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch
+asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch
+spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch
+io_uring-fdinfo-fix-sqe_mixed-sqe-displaying.patch
+io_uring-fdinfo-fix-oob-read-in-sqe_mixed-wrap-check.patch
+alsa-usb-audio-exclude-scarlett-2i4-1st-gen-from-ski.patch
--- /dev/null
+From 9824e5a8697f4e9d6d8181c3bfe2044e059c2d58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Mar 2026 21:29:56 +0800
+Subject: spi: meson-spicc: Fix double-put in remove path
+
+From: Felix Gu <ustc.gu@gmail.com>
+
+[ Upstream commit 63542bb402b7013171c9f621c28b609eda4dbf1f ]
+
+meson_spicc_probe() registers the controller with
+devm_spi_register_controller(), so teardown already drops the
+controller reference via devm cleanup.
+
+Calling spi_controller_put() again in meson_spicc_remove()
+causes a double-put.
+
+Fixes: 8311ee2164c5 ("spi: meson-spicc: fix memory leak in meson_spicc_remove")
+Signed-off-by: Felix Gu <ustc.gu@gmail.com>
+Reviewed-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260322-rockchip-v1-1-fac3f0c6dad8@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-meson-spicc.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
+index 6b91373075334..c99fab392add1 100644
+--- a/drivers/spi/spi-meson-spicc.c
++++ b/drivers/spi/spi-meson-spicc.c
+@@ -1102,8 +1102,6 @@ static void meson_spicc_remove(struct platform_device *pdev)
+
+ /* Disable SPI */
+ writel(0, spicc->base + SPICC_CONREG);
+-
+- spi_controller_put(spicc->host);
+ }
+
+ static const struct meson_spicc_data meson_spicc_gx_data = {
+--
+2.53.0
+
--- /dev/null
+From d8e6ba973581dddd07ffdbc4f8a8eec758a9a18d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 00:12:34 +0800
+Subject: spi: sn-f-ospi: Fix resource leak in f_ospi_probe()
+
+From: Felix Gu <ustc.gu@gmail.com>
+
+[ Upstream commit ef3d549e1deb3466c61f3b01d22fc3fe3e5efb08 ]
+
+In f_ospi_probe(), when num_cs validation fails, it returns without
+calling spi_controller_put() on the SPI controller, which causes a
+resource leak.
+
+Use devm_spi_alloc_host() instead of spi_alloc_host() to ensure the
+SPI controller is properly freed when probe fails.
+
+Fixes: 1b74dd64c861 ("spi: Add Socionext F_OSPI SPI flash controller driver")
+Signed-off-by: Felix Gu <ustc.gu@gmail.com>
+Link: https://patch.msgid.link/20260319-sn-f-v1-1-33a6738d2da8@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-sn-f-ospi.c | 17 +++++------------
+ 1 file changed, 5 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c
+index c4969f66a0ba9..84a5b327022e8 100644
+--- a/drivers/spi/spi-sn-f-ospi.c
++++ b/drivers/spi/spi-sn-f-ospi.c
+@@ -612,7 +612,7 @@ static int f_ospi_probe(struct platform_device *pdev)
+ u32 num_cs = OSPI_NUM_CS;
+ int ret;
+
+- ctlr = spi_alloc_host(dev, sizeof(*ospi));
++ ctlr = devm_spi_alloc_host(dev, sizeof(*ospi));
+ if (!ctlr)
+ return -ENOMEM;
+
+@@ -636,16 +636,12 @@ static int f_ospi_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, ospi);
+
+ ospi->base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(ospi->base)) {
+- ret = PTR_ERR(ospi->base);
+- goto err_put_ctlr;
+- }
++ if (IS_ERR(ospi->base))
++ return PTR_ERR(ospi->base);
+
+ ospi->clk = devm_clk_get_enabled(dev, NULL);
+- if (IS_ERR(ospi->clk)) {
+- ret = PTR_ERR(ospi->clk);
+- goto err_put_ctlr;
+- }
++ if (IS_ERR(ospi->clk))
++ return PTR_ERR(ospi->clk);
+
+ mutex_init(&ospi->mlock);
+
+@@ -662,9 +658,6 @@ static int f_ospi_probe(struct platform_device *pdev)
+ err_destroy_mutex:
+ mutex_destroy(&ospi->mlock);
+
+-err_put_ctlr:
+- spi_controller_put(ctlr);
+-
+ return ret;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 0bb280c7240e5d245da2c9752a8c0e7fa48e3f4c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 19:38:12 +0100
+Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF)
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b341c1176f2e001b3adf0b47154fc31589f7410e ]
+
+There is a teardown order issue in the driver. The SPI controller is
+registered using devm_spi_register_controller(), which delays
+unregistration of the SPI controller until after the fsl_lpspi_remove()
+function returns.
+
+As the fsl_lpspi_remove() function synchronously tears down the DMA
+channels, a running SPI transfer triggers the following NULL pointer
+dereference due to use after free:
+
+| fsl_lpspi 42550000.spi: I/O Error in DMA RX
+| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
+[...]
+| Call trace:
+| fsl_lpspi_dma_transfer+0x260/0x340 [spi_fsl_lpspi]
+| fsl_lpspi_transfer_one+0x198/0x448 [spi_fsl_lpspi]
+| spi_transfer_one_message+0x49c/0x7c8
+| __spi_pump_transfer_message+0x120/0x420
+| __spi_sync+0x2c4/0x520
+| spi_sync+0x34/0x60
+| spidev_message+0x20c/0x378 [spidev]
+| spidev_ioctl+0x398/0x750 [spidev]
+[...]
+
+Switch from devm_spi_register_controller() to spi_register_controller() in
+fsl_lpspi_probe() and add the corresponding spi_unregister_controller() in
+fsl_lpspi_remove().
+
+Fixes: 5314987de5e5 ("spi: imx: add lpspi bus driver")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-fsl-lpspi.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
+index 065456aba2aea..47d372557e4f6 100644
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -972,7 +972,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+ enable_irq(irq);
+ }
+
+- ret = devm_spi_register_controller(&pdev->dev, controller);
++ ret = spi_register_controller(controller);
+ if (ret < 0) {
+ dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
+ goto free_dma;
+@@ -998,6 +998,7 @@ static void fsl_lpspi_remove(struct platform_device *pdev)
+ struct fsl_lpspi_data *fsl_lpspi =
+ spi_controller_get_devdata(controller);
+
++ spi_unregister_controller(controller);
+ fsl_lpspi_dma_exit(controller);
+
+ pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
+--
+2.53.0
+
--- /dev/null
+From d8b8f102c6eba7eefe472b1fb39f1e9f85939ce6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Mar 2026 01:59:15 +0100
+Subject: spi: use generic driver_override infrastructure
+
+From: Danilo Krummrich <dakr@kernel.org>
+
+[ Upstream commit cc34d77dd48708d810c12bfd6f5bf03304f6c824 ]
+
+When a driver is probed through __driver_attach(), the bus' match()
+callback is called without the device lock held, thus accessing the
+driver_override field without a lock, which can cause a UAF.
+
+Fix this by using the driver-core driver_override infrastructure taking
+care of proper locking internally.
+
+Note that calling match() from __driver_attach() without the device lock
+held is intentional. [1]
+
+Also note that we do not enable the driver_override feature of struct
+bus_type, as SPI - in contrast to most other buses - passes "" to
+sysfs_emit() when the driver_override pointer is NULL. Thus, printing
+"\n" instead of "(null)\n".
+
+Link: https://lore.kernel.org/driver-core/DGRGTIRHA62X.3RY09D9SOK77P@kernel.org/ [1]
+Reported-by: Gui-Dong Han <hanguidong02@gmail.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789
+Fixes: 5039563e7c25 ("spi: Add driver_override SPI device attribute")
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Link: https://patch.msgid.link/20260324005919.2408620-12-dakr@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi.c | 19 +++++++------------
+ include/linux/spi/spi.h | 5 -----
+ 2 files changed, 7 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 201b9569ce690..87d829d2a8427 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -50,7 +50,6 @@ static void spidev_release(struct device *dev)
+ struct spi_device *spi = to_spi_device(dev);
+
+ spi_controller_put(spi->controller);
+- kfree(spi->driver_override);
+ free_percpu(spi->pcpu_statistics);
+ kfree(spi);
+ }
+@@ -73,10 +72,9 @@ static ssize_t driver_override_store(struct device *dev,
+ struct device_attribute *a,
+ const char *buf, size_t count)
+ {
+- struct spi_device *spi = to_spi_device(dev);
+ int ret;
+
+- ret = driver_set_override(dev, &spi->driver_override, buf, count);
++ ret = __device_set_driver_override(dev, buf, count);
+ if (ret)
+ return ret;
+
+@@ -86,13 +84,8 @@ static ssize_t driver_override_store(struct device *dev,
+ static ssize_t driver_override_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+ {
+- const struct spi_device *spi = to_spi_device(dev);
+- ssize_t len;
+-
+- device_lock(dev);
+- len = sysfs_emit(buf, "%s\n", spi->driver_override ? : "");
+- device_unlock(dev);
+- return len;
++ guard(spinlock)(&dev->driver_override.lock);
++ return sysfs_emit(buf, "%s\n", dev->driver_override.name ?: "");
+ }
+ static DEVICE_ATTR_RW(driver_override);
+
+@@ -376,10 +369,12 @@ static int spi_match_device(struct device *dev, const struct device_driver *drv)
+ {
+ const struct spi_device *spi = to_spi_device(dev);
+ const struct spi_driver *sdrv = to_spi_driver(drv);
++ int ret;
+
+ /* Check override first, and if set, only use the named driver */
+- if (spi->driver_override)
+- return strcmp(spi->driver_override, drv->name) == 0;
++ ret = device_match_driver_override(dev, drv);
++ if (ret >= 0)
++ return ret;
+
+ /* Attempt an OF style match */
+ if (of_driver_match_device(dev, drv))
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index cb2c2df310899..fe9dd430cc03a 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -156,10 +156,6 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
+ * @modalias: Name of the driver to use with this device, or an alias
+ * for that name. This appears in the sysfs "modalias" attribute
+ * for driver coldplugging, and in uevents used for hotplugging
+- * @driver_override: If the name of a driver is written to this attribute, then
+- * the device will bind to the named driver and only the named driver.
+- * Do not set directly, because core frees it; use driver_set_override() to
+- * set or clear it.
+ * @pcpu_statistics: statistics for the spi_device
+ * @word_delay: delay to be inserted between consecutive
+ * words of a transfer
+@@ -217,7 +213,6 @@ struct spi_device {
+ void *controller_state;
+ void *controller_data;
+ char modalias[SPI_NAME_SIZE];
+- const char *driver_override;
+
+ /* The statistics */
+ struct spi_statistics __percpu *pcpu_statistics;
+--
+2.53.0
+
--- /dev/null
+From 23c0eeb5a026d57ededd4ccebd3f1b034c077938 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 23:29:50 +0100
+Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap
+
+From: Marc Buerg <buermarc@googlemail.com>
+
+[ Upstream commit f63a9df7e3f9f842945d292a19d9938924f066f9 ]
+
+proc_do_large_bitmap() does not initialize variable c, which is expected
+to be set to a trailing character by proc_get_long().
+
+However, proc_get_long() only sets c when the input buffer contains a
+trailing character after the parsed value.
+
+If c is not initialized it may happen to contain a '-'. If this is the
+case proc_do_large_bitmap() expects to be able to parse a second part of
+the input buffer. If there is no second part an unjustified -EINVAL will
+be returned.
+
+Initialize c to 0 to prevent returning -EINVAL on valid input.
+
+Fixes: 9f977fb7ae9d ("sysctl: add proc_do_large_bitmap")
+Signed-off-by: Marc Buerg <buermarc@googlemail.com>
+Reviewed-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sysctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 2cd767b9680eb..c9389b50b8264 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -895,7 +895,7 @@ int proc_do_large_bitmap(const struct ctl_table *table, int dir,
+ unsigned long bitmap_len = table->maxlen;
+ unsigned long *bitmap = *(unsigned long **) table->data;
+ unsigned long *tmp_bitmap = NULL;
+- char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
++ char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c = 0;
+
+ if (!bitmap || !bitmap_len || !left || (*ppos && SYSCTL_KERN_TO_USER(dir))) {
+ *lenp = 0;
+--
+2.53.0
+
--- /dev/null
+From d82931e7a0f4049af540abf1a544d380aa02ce09 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 15:59:48 +0200
+Subject: x86/efi: efi_unmap_boot_services: fix calculation of ranges_to_free
+ size
+
+From: Mike Rapoport (Microsoft) <rppt@kernel.org>
+
+[ Upstream commit 217c0a5c177a3d4f7c8497950cbf5c36756e8bbb ]
+
+ranges_to_free array should have enough room to store the entire EFI
+memmap plus an extra element for NULL entry.
+The calculation of this array size wrongly adds 1 to the overall size
+instead of adding 1 to the number of elements.
+
+Add parentheses to properly size the array.
+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory")
+Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/platform/efi/quirks.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
+index 35caa5746115d..79f0818131e83 100644
+--- a/arch/x86/platform/efi/quirks.c
++++ b/arch/x86/platform/efi/quirks.c
+@@ -424,7 +424,7 @@ void __init efi_unmap_boot_services(void)
+ if (efi_enabled(EFI_DBG))
+ return;
+
+- sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;
++ sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1);
+ ranges_to_free = kzalloc(sz, GFP_KERNEL);
+ if (!ranges_to_free) {
+ pr_err("Failed to allocate storage for freeable EFI regions\n");
+--
+2.53.0
+
--- /dev/null
+From 869398f2264485a19fa6197e026dbcba1ca2ac19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 00:54:59 +0800
+Subject: ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f6484cadbcaf26b5844b51bd7307a663dda48ef6 ]
+
+When ec_install_handlers() returns -EPROBE_DEFER on reduced-hardware
+platforms, it has already started the EC and installed the address
+space handler with the struct acpi_ec pointer as handler context.
+However, acpi_ec_setup() propagates the error without any cleanup.
+
+The caller acpi_ec_add() then frees the struct acpi_ec for non-boot
+instances, leaving a dangling handler context in ACPICA.
+
+Any subsequent AML evaluation that accesses an EC OpRegion field
+dispatches into acpi_ec_space_handler() with the freed pointer,
+causing a use-after-free:
+
+ BUG: KASAN: slab-use-after-free in mutex_lock (kernel/locking/mutex.c:289)
+ Write of size 8 at addr ffff88800721de38 by task init/1
+ Call Trace:
+ <TASK>
+ mutex_lock (kernel/locking/mutex.c:289)
+ acpi_ec_space_handler (drivers/acpi/ec.c:1362)
+ acpi_ev_address_space_dispatch (drivers/acpi/acpica/evregion.c:293)
+ acpi_ex_access_region (drivers/acpi/acpica/exfldio.c:246)
+ acpi_ex_field_datum_io (drivers/acpi/acpica/exfldio.c:509)
+ acpi_ex_extract_from_field (drivers/acpi/acpica/exfldio.c:700)
+ acpi_ex_read_data_from_field (drivers/acpi/acpica/exfield.c:327)
+ acpi_ex_resolve_node_to_value (drivers/acpi/acpica/exresolv.c:392)
+ </TASK>
+
+ Allocated by task 1:
+ acpi_ec_alloc (drivers/acpi/ec.c:1424)
+ acpi_ec_add (drivers/acpi/ec.c:1692)
+
+ Freed by task 1:
+ kfree (mm/slub.c:6876)
+ acpi_ec_add (drivers/acpi/ec.c:1751)
+
+The bug triggers on reduced-hardware EC platforms (ec->gpe < 0)
+when the GPIO IRQ provider defers probing. Once the stale handler
+exists, any unprivileged sysfs read that causes AML to touch an
+EC OpRegion (battery, thermal, backlight) exercises the dangling
+pointer.
+
+Fix this by calling ec_remove_handlers() in the error path of
+acpi_ec_setup() before clearing first_ec. ec_remove_handlers()
+checks each EC_FLAGS_* bit before acting, so it is safe to call
+regardless of how far ec_install_handlers() progressed:
+
+ -ENODEV (handler not installed): only calls acpi_ec_stop()
+ -EPROBE_DEFER (handler installed): removes handler, stops EC
+
+Fixes: 03e9a0e05739 ("ACPI: EC: Consolidate event handler installation code")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 8e304efde3429..f94cddbbb55ac 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1653,6 +1653,8 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca
+
+ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret) {
++ ec_remove_handlers(ec);
++
+ if (ec == first_ec)
+ first_ec = NULL;
+
+--
+2.53.0
+
--- /dev/null
+From 880b53b0621e36da10b89cedc6dc8e505e59a660 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:04 +0100
+Subject: ASoC: adau1372: Fix clock leak on PLL lock failure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit bfe6a264effcb6fe99ad7ceaf9e8c7439fc9555b ]
+
+adau1372_enable_pll() was a void function that logged a dev_err() on
+PLL lock timeout but did not propagate the error. As a result,
+adau1372_set_power() would continue with adau1372->enabled set to true
+despite the PLL being unlocked, and the mclk left enabled with no
+corresponding disable on the error path.
+
+Convert adau1372_enable_pll() to return int, using -ETIMEDOUT on lock
+timeout and propagating regmap errors directly. In adau1372_set_power(),
+check the return value and unwind in reverse order: restore regcache to
+cache-only mode, reassert GPIO power-down, and disable the clock before
+returning the error.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index f629be6c297df..25f123110b5be 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -761,7 +761,7 @@ static int adau1372_startup(struct snd_pcm_substream *substream, struct snd_soc_
+ return 0;
+ }
+
+-static void adau1372_enable_pll(struct adau1372 *adau1372)
++static int adau1372_enable_pll(struct adau1372 *adau1372)
+ {
+ unsigned int val, timeout = 0;
+ int ret;
+@@ -777,8 +777,12 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ timeout++;
+ } while (!(val & 1) && timeout < 3);
+
+- if (ret < 0 || !(val & 1))
++ if (ret < 0 || !(val & 1)) {
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
++ return ret < 0 ? ret : -ETIMEDOUT;
++ }
++
++ return 0;
+ }
+
+ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+@@ -806,7 +810,14 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ * accessed.
+ */
+ if (adau1372->use_pll) {
+- adau1372_enable_pll(adau1372);
++ ret = adau1372_enable_pll(adau1372);
++ if (ret) {
++ regcache_cache_only(adau1372->regmap, true);
++ if (adau1372->pd_gpio)
++ gpiod_set_value(adau1372->pd_gpio, 1);
++ clk_disable_unprepare(adau1372->mclk);
++ return ret;
++ }
+ clk_ctrl |= ADAU1372_CLK_CTRL_CLKSRC;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 9fe74a6c41ef3257b8b937a21f617f7d7098ae66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 22:07:03 +0100
+Subject: ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+
+[ Upstream commit 326fe8104a4020d30080d37ac8b6b43893cdebca ]
+
+adau1372_set_power() calls clk_prepare_enable() but discards the return
+value. If the clock enable fails, the driver proceeds to access registers
+on unpowered hardware, potentially causing silent corruption.
+
+Make adau1372_set_power() return int and propagate the error from
+clk_prepare_enable(). Update adau1372_set_bias_level() to return the
+error directly for the STANDBY and OFF cases.
+
+Signed-off-by: Jihed Chaibi <jihed.chaibi.dev@gmail.com>
+Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support")
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/adau1372.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
+index 98380a7ce64d8..f629be6c297df 100644
+--- a/sound/soc/codecs/adau1372.c
++++ b/sound/soc/codecs/adau1372.c
+@@ -781,15 +781,18 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)
+ dev_err(adau1372->dev, "Failed to lock PLL\n");
+ }
+
+-static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
++static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ {
+ if (adau1372->enabled == enable)
+- return;
++ return 0;
+
+ if (enable) {
+ unsigned int clk_ctrl = ADAU1372_CLK_CTRL_MCLK_EN;
++ int ret;
+
+- clk_prepare_enable(adau1372->mclk);
++ ret = clk_prepare_enable(adau1372->mclk);
++ if (ret)
++ return ret;
+ if (adau1372->pd_gpio)
+ gpiod_set_value(adau1372->pd_gpio, 0);
+
+@@ -828,6 +831,8 @@ static void adau1372_set_power(struct adau1372 *adau1372, bool enable)
+ }
+
+ adau1372->enabled = enable;
++
++ return 0;
+ }
+
+ static int adau1372_set_bias_level(struct snd_soc_component *component,
+@@ -841,11 +846,9 @@ static int adau1372_set_bias_level(struct snd_soc_component *component,
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+- adau1372_set_power(adau1372, true);
+- break;
++ return adau1372_set_power(adau1372, true);
+ case SND_SOC_BIAS_OFF:
+- adau1372_set_power(adau1372, false);
+- break;
++ return adau1372_set_power(adau1372, false);
+ }
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 4561724fa699a96aa12a318b0bed5b8c702a2293 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 11:12:17 +0100
+Subject: ASoC: Intel: catpt: Fix the device initialization
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 5a184f1cb43a8e035251c635f5c47da5dc3e3049 ]
+
+The DMA mask shall be coerced before any buffer allocations for the
+device are done. At the same time explain why DMA mask of 31 bits is
+used in the first place.
+
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle")
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/catpt/device.c | 10 +++++++++-
+ sound/soc/intel/catpt/dsp.c | 3 ---
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c
+index cac3dffbd0d9f..6cc8b241f743e 100644
+--- a/sound/soc/intel/catpt/device.c
++++ b/sound/soc/intel/catpt/device.c
+@@ -271,7 +271,15 @@ static int catpt_acpi_probe(struct platform_device *pdev)
+ if (IS_ERR(cdev->pci_ba))
+ return PTR_ERR(cdev->pci_ba);
+
+- /* alloc buffer for storing DRAM context during dx transitions */
++ /*
++ * As per design HOST is responsible for preserving firmware's runtime
++ * context during D0 -> D3 -> D0 transitions. Addresses used for DMA
++ * to/from HOST memory shall be outside the reserved range of 0xFFFxxxxx.
++ */
++ ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
++ if (ret)
++ return ret;
++
+ cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev),
+ &cdev->dxbuf_paddr, GFP_KERNEL);
+ if (!cdev->dxbuf_vaddr)
+diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
+index 346bec0003066..3cde6b7ae9237 100644
+--- a/sound/soc/intel/catpt/dsp.c
++++ b/sound/soc/intel/catpt/dsp.c
+@@ -125,9 +125,6 @@ int catpt_dmac_probe(struct catpt_dev *cdev)
+ dmac->dev = cdev->dev;
+ dmac->irq = cdev->irq;
+
+- ret = dma_coerce_mask_and_coherent(cdev->dev, DMA_BIT_MASK(31));
+- if (ret)
+- return ret;
+ /*
+ * Caller is responsible for putting device in D0 to allow
+ * for I/O and memory access before probing DW.
+--
+2.53.0
+
--- /dev/null
+From f20fc83a996f7d715d29998cb149091508189016 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Mar 2026 13:41:18 +0530
+Subject: drm/amdgpu: Fix fence put before wait in amdgpu_amdkfd_submit_ib
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 7150850146ebfa4ca998f653f264b8df6f7f85be ]
+
+amdgpu_amdkfd_submit_ib() submits a GPU job and gets a fence
+from amdgpu_ib_schedule(). This fence is used to wait for job
+completion.
+
+Currently, the code drops the fence reference using dma_fence_put()
+before calling dma_fence_wait().
+
+If dma_fence_put() releases the last reference, the fence may be
+freed before dma_fence_wait() is called. This can lead to a
+use-after-free.
+
+Fix this by waiting on the fence first and releasing the reference
+only after dma_fence_wait() completes.
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c:697 amdgpu_amdkfd_submit_ib() warn: passing freed memory 'f' (line 696)
+
+Fixes: 9ae55f030dc5 ("drm/amdgpu: Follow up change to previous drm scheduler change.")
+Cc: Felix Kuehling <Felix.Kuehling@amd.com>
+Cc: Dan Carpenter <dan.carpenter@linaro.org>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+index fbee10927bfb6..946264a87d0e8 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -670,9 +670,9 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
+ goto err_ib_sched;
+ }
+
+- /* Drop the initial kref_init count (see drm_sched_main as example) */
+- dma_fence_put(f);
+ ret = dma_fence_wait(f, false);
++ /* Drop the returned fence reference after the wait completes */
++ dma_fence_put(f);
+
+ err_ib_sched:
+ amdgpu_job_free(job);
+--
+2.53.0
+
--- /dev/null
+From 44ce78b389b3bd1d6dfe3eaa95a094d6a1bfed96 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 16:19:19 -0700
+Subject: drm/i915/gmbus: fix spurious timeout on 512-byte burst reads
+
+From: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+
+[ Upstream commit 08441f10f4dc09fdeb64529953ac308abc79dd38 ]
+
+When reading exactly 512 bytes with burst read enabled, the
+extra_byte_added path breaks out of the inner do-while without
+decrementing len. The outer while(len) then re-enters and gmbus_wait()
+times out since all data has been delivered. Decrement len before the
+break so the outer loop terminates correctly.
+
+Fixes: d5dc0f43f268 ("drm/i915/gmbus: Enable burst read")
+Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_gmbus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
+index e95ddb580ef6c..a01e655c24ff3 100644
+--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
++++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
+@@ -460,8 +460,10 @@ gmbus_xfer_read_chunk(struct drm_i915_private *i915,
+
+ val = intel_de_read_fw(i915, GMBUS3(i915));
+ do {
+- if (extra_byte_added && len == 1)
++ if (extra_byte_added && len == 1) {
++ len--;
+ break;
++ }
+
+ *buf++ = val & 0xff;
+ val >>= 8;
+--
+2.53.0
+
--- /dev/null
+From 74d99f394f94208dbffd9dee9572025adbc374e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 05:13:06 +0000
+Subject: hwmon: (adm1177) fix sysfs ABI violation and current unit conversion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sanman Pradhan <psanman@juniper.net>
+
+[ Upstream commit bf08749a6abb6d1959bfdc0edc32c640df407558 ]
+
+The adm1177 driver exposes the current alert threshold through
+hwmon_curr_max_alarm. This violates the hwmon sysfs ABI, where
+*_alarm attributes are read-only status flags and writable thresholds
+must use currN_max.
+
+The driver also stores the threshold internally in microamps, while
+currN_max is defined in milliamps. Convert the threshold accordingly
+on both the read and write paths.
+
+Widen the cached threshold and related calculations to 64 bits so
+that small shunt resistor values do not cause truncation or overflow.
+Also use 64-bit arithmetic for the mA/uA conversions, clamp writes
+to the range the hardware can represent, and propagate failures from
+adm1177_write_alert_thr() instead of silently ignoring them.
+
+Update the hwmon documentation to reflect the attribute rename and
+the correct units returned by the driver.
+
+Fixes: 09b08ac9e8d5 ("hwmon: (adm1177) Add ADM1177 Hot Swap Controller and Digital Power Monitor driver")
+Signed-off-by: Sanman Pradhan <psanman@juniper.net>
+Acked-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/adm1177.rst | 8 ++---
+ drivers/hwmon/adm1177.c | 54 +++++++++++++++++++--------------
+ 2 files changed, 35 insertions(+), 27 deletions(-)
+
+diff --git a/Documentation/hwmon/adm1177.rst b/Documentation/hwmon/adm1177.rst
+index 1c85a2af92bf7..375f6d6e03a7d 100644
+--- a/Documentation/hwmon/adm1177.rst
++++ b/Documentation/hwmon/adm1177.rst
+@@ -27,10 +27,10 @@ for details.
+ Sysfs entries
+ -------------
+
+-The following attributes are supported. Current maxim attribute
++The following attributes are supported. Current maximum attribute
+ is read-write, all other attributes are read-only.
+
+-in0_input Measured voltage in microvolts.
++in0_input Measured voltage in millivolts.
+
+-curr1_input Measured current in microamperes.
+-curr1_max_alarm Overcurrent alarm in microamperes.
++curr1_input Measured current in milliamperes.
++curr1_max Overcurrent shutdown threshold in milliamperes.
+diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c
+index 60a893f271597..7581fd2456f9b 100644
+--- a/drivers/hwmon/adm1177.c
++++ b/drivers/hwmon/adm1177.c
+@@ -10,6 +10,8 @@
+ #include <linux/hwmon.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
++#include <linux/math64.h>
++#include <linux/minmax.h>
+ #include <linux/module.h>
+ #include <linux/regulator/consumer.h>
+
+@@ -33,7 +35,7 @@
+ struct adm1177_state {
+ struct i2c_client *client;
+ u32 r_sense_uohm;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
+ bool vrange_high;
+ };
+
+@@ -48,7 +50,7 @@ static int adm1177_write_cmd(struct adm1177_state *st, u8 cmd)
+ }
+
+ static int adm1177_write_alert_thr(struct adm1177_state *st,
+- u32 alert_threshold_ua)
++ u64 alert_threshold_ua)
+ {
+ u64 val;
+ int ret;
+@@ -91,8 +93,8 @@ static int adm1177_read(struct device *dev, enum hwmon_sensor_types type,
+ *val = div_u64((105840000ull * dummy),
+ 4096 * st->r_sense_uohm);
+ return 0;
+- case hwmon_curr_max_alarm:
+- *val = st->alert_threshold_ua;
++ case hwmon_curr_max:
++ *val = div_u64(st->alert_threshold_ua, 1000);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+@@ -126,9 +128,10 @@ static int adm1177_write(struct device *dev, enum hwmon_sensor_types type,
+ switch (type) {
+ case hwmon_curr:
+ switch (attr) {
+- case hwmon_curr_max_alarm:
+- adm1177_write_alert_thr(st, val);
+- return 0;
++ case hwmon_curr_max:
++ val = clamp_val(val, 0,
++ div_u64(105840000ULL, st->r_sense_uohm));
++ return adm1177_write_alert_thr(st, (u64)val * 1000);
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -156,7 +159,7 @@ static umode_t adm1177_is_visible(const void *data,
+ if (st->r_sense_uohm)
+ return 0444;
+ return 0;
+- case hwmon_curr_max_alarm:
++ case hwmon_curr_max:
+ if (st->r_sense_uohm)
+ return 0644;
+ return 0;
+@@ -170,7 +173,7 @@ static umode_t adm1177_is_visible(const void *data,
+
+ static const struct hwmon_channel_info * const adm1177_info[] = {
+ HWMON_CHANNEL_INFO(curr,
+- HWMON_C_INPUT | HWMON_C_MAX_ALARM),
++ HWMON_C_INPUT | HWMON_C_MAX),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT),
+ NULL
+@@ -192,7 +195,8 @@ static int adm1177_probe(struct i2c_client *client)
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct adm1177_state *st;
+- u32 alert_threshold_ua;
++ u64 alert_threshold_ua;
++ u32 prop;
+ int ret;
+
+ st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+@@ -208,22 +212,26 @@ static int adm1177_probe(struct i2c_client *client)
+ if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
+ &st->r_sense_uohm))
+ st->r_sense_uohm = 0;
+- if (device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
+- &alert_threshold_ua)) {
+- if (st->r_sense_uohm)
+- /*
+- * set maximum default value from datasheet based on
+- * shunt-resistor
+- */
+- alert_threshold_ua = div_u64(105840000000,
+- st->r_sense_uohm);
+- else
+- alert_threshold_ua = 0;
++ if (!device_property_read_u32(dev, "adi,shutdown-threshold-microamp",
++ &prop)) {
++ alert_threshold_ua = prop;
++ } else if (st->r_sense_uohm) {
++ /*
++ * set maximum default value from datasheet based on
++ * shunt-resistor
++ */
++ alert_threshold_ua = div_u64(105840000000ULL,
++ st->r_sense_uohm);
++ } else {
++ alert_threshold_ua = 0;
+ }
+ st->vrange_high = device_property_read_bool(dev,
+ "adi,vrange-high-enable");
+- if (alert_threshold_ua && st->r_sense_uohm)
+- adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (alert_threshold_ua && st->r_sense_uohm) {
++ ret = adm1177_write_alert_thr(st, alert_threshold_ua);
++ if (ret)
++ return ret;
++ }
+
+ ret = adm1177_write_cmd(st, ADM1177_CMD_V_CONT |
+ ADM1177_CMD_I_CONT |
+--
+2.53.0
+
--- /dev/null
+From 7a7e214dac87db2a051586edd332f54a2ab2885f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Feb 2024 09:40:58 +0100
+Subject: PM: hibernate: Don't ignore return from set_memory_ro()
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+[ Upstream commit f4311756a83fb01c28a9bf841cbb7eb2b318eebf ]
+
+set_memory_ro() and set_memory_rw() can fail, leaving memory
+unprotected.
+
+Take the returned value into account and abort in case of
+failure.
+
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 734eba62cd32 ("PM: hibernate: Drain trailing zero pages on userspace restore")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/power.h | 2 +-
+ kernel/power/snapshot.c | 25 ++++++++++++++++---------
+ kernel/power/swap.c | 8 ++++----
+ kernel/power/user.c | 4 +++-
+ 4 files changed, 24 insertions(+), 15 deletions(-)
+
+diff --git a/kernel/power/power.h b/kernel/power/power.h
+index 62a7cb452a4be..3ea663f1ad1e2 100644
+--- a/kernel/power/power.h
++++ b/kernel/power/power.h
+@@ -152,7 +152,7 @@ extern unsigned int snapshot_additional_pages(struct zone *zone);
+ extern unsigned long snapshot_get_image_size(void);
+ extern int snapshot_read_next(struct snapshot_handle *handle);
+ extern int snapshot_write_next(struct snapshot_handle *handle);
+-extern void snapshot_write_finalize(struct snapshot_handle *handle);
++int snapshot_write_finalize(struct snapshot_handle *handle);
+ extern int snapshot_image_loaded(struct snapshot_handle *handle);
+
+ extern bool hibernate_acquire(void);
+diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
+index 50a15408c3fca..ea52417375a4e 100644
+--- a/kernel/power/snapshot.c
++++ b/kernel/power/snapshot.c
+@@ -58,22 +58,24 @@ static inline void hibernate_restore_protection_end(void)
+ hibernate_restore_protection_active = false;
+ }
+
+-static inline void hibernate_restore_protect_page(void *page_address)
++static inline int __must_check hibernate_restore_protect_page(void *page_address)
+ {
+ if (hibernate_restore_protection_active)
+- set_memory_ro((unsigned long)page_address, 1);
++ return set_memory_ro((unsigned long)page_address, 1);
++ return 0;
+ }
+
+-static inline void hibernate_restore_unprotect_page(void *page_address)
++static inline int hibernate_restore_unprotect_page(void *page_address)
+ {
+ if (hibernate_restore_protection_active)
+- set_memory_rw((unsigned long)page_address, 1);
++ return set_memory_rw((unsigned long)page_address, 1);
++ return 0;
+ }
+ #else
+ static inline void hibernate_restore_protection_begin(void) {}
+ static inline void hibernate_restore_protection_end(void) {}
+-static inline void hibernate_restore_protect_page(void *page_address) {}
+-static inline void hibernate_restore_unprotect_page(void *page_address) {}
++static inline int __must_check hibernate_restore_protect_page(void *page_address) {return 0; }
++static inline int hibernate_restore_unprotect_page(void *page_address) {return 0; }
+ #endif /* CONFIG_STRICT_KERNEL_RWX && CONFIG_ARCH_HAS_SET_MEMORY */
+
+
+@@ -2832,7 +2834,9 @@ int snapshot_write_next(struct snapshot_handle *handle)
+ }
+ } else {
+ copy_last_highmem_page();
+- hibernate_restore_protect_page(handle->buffer);
++ error = hibernate_restore_protect_page(handle->buffer);
++ if (error)
++ return error;
+ handle->buffer = get_buffer(&orig_bm, &ca);
+ if (IS_ERR(handle->buffer))
+ return PTR_ERR(handle->buffer);
+@@ -2858,15 +2862,18 @@ int snapshot_write_next(struct snapshot_handle *handle)
+ * stored in highmem. Additionally, it recycles bitmap memory that's not
+ * necessary any more.
+ */
+-void snapshot_write_finalize(struct snapshot_handle *handle)
++int snapshot_write_finalize(struct snapshot_handle *handle)
+ {
++ int error;
++
+ copy_last_highmem_page();
+- hibernate_restore_protect_page(handle->buffer);
++ error = hibernate_restore_protect_page(handle->buffer);
+ /* Do that only if we have loaded the image entirely */
+ if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages + nr_zero_pages) {
+ memory_bm_recycle(&orig_bm);
+ free_highmem_data();
+ }
++ return error;
+ }
+
+ int snapshot_image_loaded(struct snapshot_handle *handle)
+diff --git a/kernel/power/swap.c b/kernel/power/swap.c
+index d71c590550d28..8c162e18e1645 100644
+--- a/kernel/power/swap.c
++++ b/kernel/power/swap.c
+@@ -1099,8 +1099,8 @@ static int load_image(struct swap_map_handle *handle,
+ ret = err2;
+ if (!ret) {
+ pr_info("Image loading done\n");
+- snapshot_write_finalize(snapshot);
+- if (!snapshot_image_loaded(snapshot))
++ ret = snapshot_write_finalize(snapshot);
++ if (!ret && !snapshot_image_loaded(snapshot))
+ ret = -ENODATA;
+ }
+ swsusp_show_speed(start, stop, nr_to_read, "Read");
+@@ -1440,8 +1440,8 @@ static int load_image_lzo(struct swap_map_handle *handle,
+ stop = ktime_get();
+ if (!ret) {
+ pr_info("Image loading done\n");
+- snapshot_write_finalize(snapshot);
+- if (!snapshot_image_loaded(snapshot))
++ ret = snapshot_write_finalize(snapshot);
++ if (!ret && !snapshot_image_loaded(snapshot))
+ ret = -ENODATA;
+ if (!ret) {
+ if (swsusp_header->flags & SF_CRC32_MODE) {
+diff --git a/kernel/power/user.c b/kernel/power/user.c
+index 3a4e70366f354..3aa41ba22129d 100644
+--- a/kernel/power/user.c
++++ b/kernel/power/user.c
+@@ -317,7 +317,9 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
+ break;
+
+ case SNAPSHOT_ATOMIC_RESTORE:
+- snapshot_write_finalize(&data->handle);
++ error = snapshot_write_finalize(&data->handle);
++ if (error)
++ break;
+ if (data->mode != O_WRONLY || !data->frozen ||
+ !snapshot_image_loaded(&data->handle)) {
+ error = -EPERM;
+--
+2.53.0
+
--- /dev/null
+From 0d142af4db0aa8153694c6ee65a364c6ba09d56b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Mar 2026 18:39:41 +0100
+Subject: PM: hibernate: Drain trailing zero pages on userspace restore
+
+From: Alberto Garcia <berto@igalia.com>
+
+[ Upstream commit 734eba62cd32cb9ceffa09e57cdc03d761528525 ]
+
+Commit 005e8dddd497 ("PM: hibernate: don't store zero pages in the
+image file") added an optimization to skip zero-filled pages in the
+hibernation image. On restore, zero pages are handled internally by
+snapshot_write_next() in a loop that processes them without returning
+to the caller.
+
+With the userspace restore interface, writing the last non-zero page
+to /dev/snapshot is followed by the SNAPSHOT_ATOMIC_RESTORE ioctl. At
+this point there are no more calls to snapshot_write_next() so any
+trailing zero pages are not processed, snapshot_image_loaded() fails
+because handle->cur is smaller than expected, the ioctl returns -EPERM
+and the image is not restored.
+
+The in-kernel restore path is not affected by this because the loop in
+load_image() in swap.c calls snapshot_write_next() until it returns 0.
+It is this final call that drains any trailing zero pages.
+
+Fixed by calling snapshot_write_next() in snapshot_write_finalize(),
+giving the kernel the chance to drain any trailing zero pages.
+
+Fixes: 005e8dddd497 ("PM: hibernate: don't store zero pages in the image file")
+Signed-off-by: Alberto Garcia <berto@igalia.com>
+Acked-by: Brian Geffon <bgeffon@google.com>
+Link: https://patch.msgid.link/ef5a7c5e3e3dbd17dcb20efaa0c53a47a23498bb.1773075892.git.berto@igalia.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/snapshot.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
+index ea52417375a4e..c3ad93fc24e64 100644
+--- a/kernel/power/snapshot.c
++++ b/kernel/power/snapshot.c
+@@ -2866,6 +2866,17 @@ int snapshot_write_finalize(struct snapshot_handle *handle)
+ {
+ int error;
+
++ /*
++ * Call snapshot_write_next() to drain any trailing zero pages,
++ * but make sure we're in the data page region first.
++ * This function can return PAGE_SIZE if the kernel was expecting
++ * another copy page. Return -ENODATA in that situation.
++ */
++ if (handle->cur > nr_meta_pages + 1) {
++ error = snapshot_write_next(handle);
++ if (error)
++ return error > 0 ? -ENODATA : error;
++ }
+ copy_last_highmem_page();
+ error = hibernate_restore_protect_page(handle->buffer);
+ /* Do that only if we have loaded the image entirely */
+--
+2.53.0
+
--- /dev/null
+From 7a8619ff60a34415206ff6a72a10508e1c285534 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:43 -0500
+Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node
+
+From: Ivan Barrera <ivan.d.barrera@intel.com>
+
+[ Upstream commit b415399c9a024d574b65479636f0d4eb625b9abd ]
+
+The cm_node is available and the usage of cm_node and event->cm_node
+seems arbitrary. Clean up unnecessary dereference of event->cm_node.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Ivan Barrera <ivan.d.barrera@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index b3f14816251b4..00e63a46a50ee 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -4237,21 +4237,21 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ irdma_cm_event_reset(event);
+ break;
+ case IRDMA_CM_EVENT_CONNECTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state != IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state != IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_cm_event_connected(event);
+ break;
+ case IRDMA_CM_EVENT_MPA_REJECT:
+- if (!event->cm_node->cm_id ||
++ if (!cm_node->cm_id ||
+ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_send_cm_event(cm_node, cm_node->cm_id,
+ IW_CM_EVENT_CONNECT_REPLY, -ECONNREFUSED);
+ break;
+ case IRDMA_CM_EVENT_ABORTED:
+- if (!event->cm_node->cm_id ||
+- event->cm_node->state == IRDMA_CM_STATE_OFFLOADED)
++ if (!cm_node->cm_id ||
++ cm_node->state == IRDMA_CM_STATE_OFFLOADED)
+ break;
+ irdma_event_connect_error(event);
+ break;
+@@ -4261,7 +4261,7 @@ static void irdma_cm_event_handler(struct work_struct *work)
+ break;
+ }
+
+- irdma_rem_ref_cm_node(event->cm_node);
++ irdma_rem_ref_cm_node(cm_node);
+ kfree(event);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 255d9f023900d5cabda9e360f8cd0e56d8f9d52e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:45 -0500
+Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections
+
+From: Anil Samal <anil.samal@intel.com>
+
+[ Upstream commit 6f52370970ac07d352a7af4089e55e0e6425f827 ]
+
+Resolve deadlock that occurs when user executes netdev reset while RDMA
+applications (e.g., rping) are active. The netdev reset causes ice
+driver to remove irdma auxiliary driver, triggering device_delete and
+subsequent client removal. During client removal, uverbs_client waits
+for QP reference count to reach zero while cma_client holds the final
+reference, creating circular dependency and indefinite wait in iWARP
+mode. Skip QP reference count wait during device reset to prevent
+deadlock.
+
+Fixes: c8f304d75f6c ("RDMA/irdma: Prevent QP use after free")
+Signed-off-by: Anil Samal <anil.samal@intel.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index cc8c6e8586252..532b36b25e919 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -536,7 +536,8 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+ }
+
+ irdma_qp_rem_ref(&iwqp->ibqp);
+- wait_for_completion(&iwqp->free_qp);
++ if (!iwdev->rf->reset)
++ wait_for_completion(&iwqp->free_qp);
+ irdma_free_lsmm_rsrc(iwqp);
+ irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
+
+--
+2.53.0
+
--- /dev/null
+From 1e5af1726fd84ca5ddb777f4907f5186db90b7fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:38 -0500
+Subject: RDMA/irdma: Initialize free_qp completion before using it
+
+From: Jacob Moroni <jmoroni@google.com>
+
+[ Upstream commit 11a95521fb93c91e2d4ef9d53dc80ef0a755549b ]
+
+In irdma_create_qp, if ib_copy_to_udata fails, it will call
+irdma_destroy_qp to clean up which will attempt to wait on
+the free_qp completion, which is not initialized yet. Fix this
+by initializing the completion before the ib_copy_to_udata call.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Jacob Moroni <jmoroni@google.com>
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 3b0050e594fdf..a2a6910113e62 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1008,6 +1008,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ spin_lock_init(&iwqp->sc_qp.pfpdu.lock);
+ iwqp->sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
+ rf->qp_table[qp_num] = iwqp;
++ init_completion(&iwqp->free_qp);
+
+ if (rdma_protocol_roce(&iwdev->ibdev, 1)) {
+ if (dev->ws_add(&iwdev->vsi, 0)) {
+@@ -1042,7 +1043,6 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ }
+ }
+
+- init_completion(&iwqp->free_qp);
+ return 0;
+
+ error:
+--
+2.53.0
+
--- /dev/null
+From 3f127b494303d4c0faebae77710d5445c85ffdb8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:42 -0500
+Subject: RDMA/irdma: Remove a NOP wait_event() in irdma_modify_qp_roce()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 5e8f0239731a83753473b7aa91bda67bbdff5053 ]
+
+Remove a NOP wait_event() in irdma_modify_qp_roce() which is relevant
+for iWARP and likely a copy and paste artifact for RoCEv2. The wait event
+is for sending a reset on a TCP connection, after the reset has been
+requested in irdma_modify_qp(), which occurs only in iWarp mode.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index b9996d36358b1..cc8c6e8586252 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1364,8 +1364,6 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ roce_info->rd_en = true;
+ }
+
+- wait_event(iwqp->mod_qp_waitq, !atomic_read(&iwqp->hw_mod_qp_pend));
+-
+ ibdev_dbg(&iwdev->ibdev,
+ "VERBS: caller: %pS qp_id=%d to_ibqpstate=%d ibqpstate=%d irdma_qpstate=%d attr_mask=0x%x\n",
+ __builtin_return_address(0), ibqp->qp_num, attr->qp_state,
+--
+2.53.0
+
--- /dev/null
+From 443b85cb5759390c82b6b8635446645107846b46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:44 -0500
+Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err()
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit c45c6ebd693b944f1ffe429fdfb6cc1674c237be ]
+
+During reset, irdma_modify_qp() to error should be called to disconnect
+the QP. Without this fix, if not preceded by irdma_modify_qp() to error, the
+API call irdma_destroy_qp() gets stuck waiting for the QP refcount to go
+to zero, because the cm_node associated with this QP isn't disconnected.
+
+Fixes: 915cc7ac0f8e ("RDMA/irdma: Add miscellaneous utility definitions")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/utils.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
+index 91ed7edcd788b..0571544e045e8 100644
+--- a/drivers/infiniband/hw/irdma/utils.c
++++ b/drivers/infiniband/hw/irdma/utils.c
+@@ -2345,8 +2345,6 @@ void irdma_modify_qp_to_err(struct irdma_sc_qp *sc_qp)
+ struct irdma_qp *qp = sc_qp->qp_uk.back_qp;
+ struct ib_qp_attr attr;
+
+- if (qp->iwdev->rf->reset)
+- return;
+ attr.qp_state = IB_QPS_ERR;
+
+ if (rdma_protocol_roce(qp->ibqp.device, 1))
+--
+2.53.0
+
--- /dev/null
+From 98239aeeb2b09f3d54349158de797f449297fd72 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:46 -0500
+Subject: RDMA/irdma: Return EINVAL for invalid arp index error
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 7221f581eefa79ead06e171044f393fb7ee22f87 ]
+
+When rdma_connect() fails due to an invalid arp index, user space rdma core
+reports ENOMEM which is confusing. Modify irdma_make_cm_node() to return the
+correct error code.
+
+Fixes: 146b9756f14c ("RDMA/irdma: Add connection manager")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/cm.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index 00e63a46a50ee..122b4cffc8dc7 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -2239,11 +2239,12 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ int oldarpindex;
+ int arpindex;
+ struct net_device *netdev = iwdev->netdev;
++ int ret;
+
+ /* create an hte and cm_node for this instance */
+ cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
+ if (!cm_node)
+- return NULL;
++ return ERR_PTR(-ENOMEM);
+
+ /* set our node specific transport info */
+ cm_node->ipv4 = cm_info->ipv4;
+@@ -2346,8 +2347,10 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ arpindex = -EINVAL;
+ }
+
+- if (arpindex < 0)
++ if (arpindex < 0) {
++ ret = -EINVAL;
+ goto err;
++ }
+
+ ether_addr_copy(cm_node->rem_mac,
+ iwdev->rf->arp_table[arpindex].mac_addr);
+@@ -2358,7 +2361,7 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
+ err:
+ kfree(cm_node);
+
+- return NULL;
++ return ERR_PTR(ret);
+ }
+
+ static void irdma_destroy_connection(struct irdma_cm_node *cm_node)
+@@ -3019,8 +3022,8 @@ static int irdma_create_cm_node(struct irdma_cm_core *cm_core,
+
+ /* create a CM connection node */
+ cm_node = irdma_make_cm_node(cm_core, iwdev, cm_info, NULL);
+- if (!cm_node)
+- return -ENOMEM;
++ if (IS_ERR(cm_node))
++ return PTR_ERR(cm_node);
+
+ /* set our node side to client (active) side */
+ cm_node->tcp_cntxt.client = 1;
+@@ -3217,9 +3220,9 @@ void irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf)
+ cm_info.cm_id = listener->cm_id;
+ cm_node = irdma_make_cm_node(cm_core, iwdev, &cm_info,
+ listener);
+- if (!cm_node) {
++ if (IS_ERR(cm_node)) {
+ ibdev_dbg(&cm_core->iwdev->ibdev,
+- "CM: allocate node failed\n");
++ "CM: allocate node failed ret=%ld\n", PTR_ERR(cm_node));
+ refcount_dec(&listener->refcnt);
+ return;
+ }
+--
+2.53.0
+
--- /dev/null
+From 2c5069bc65bfd81d21aad1bf2f68d41e145021f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 13:39:41 -0500
+Subject: RDMA/irdma: Update ibqp state to error if QP is already in error
+ state
+
+From: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+
+[ Upstream commit 8c1f19a2225cf37b3f8ab0b5a8a5322291cda620 ]
+
+In irdma_modify_qp() update ibqp state to error if the irdma QP is already
+in error state, otherwise the ibqp state which is visible to the consumer
+app remains stale.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index a2a6910113e62..b9996d36358b1 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -1442,6 +1442,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+@@ -1647,6 +1648,7 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ case IB_QPS_ERR:
+ case IB_QPS_RESET:
+ if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) {
++ iwqp->ibqp_state = attr->qp_state;
+ spin_unlock_irqrestore(&iwqp->lock, flags);
+ if (udata && udata->inlen) {
+ if (ib_copy_from_udata(&ureq, udata,
+--
+2.53.0
+
--- /dev/null
+From bba8437fb676f802e54e19cc42aa58c6f1bca6f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Mar 2026 15:41:58 -0400
+Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 00da250c21b074ea9494c375d0117b69e5b1d0a4 ]
+
+When IOMMU passthrough mode is active, ib_dma_map_sgtable_attrs()
+produces no coalescing: each scatterlist page maps 1:1 to a DMA
+entry, so sgt.nents equals the raw page count. A 1 MB transfer
+yields 256 DMA entries. If that count exceeds the device's
+max_sgl_rd threshold (an optimization hint from mlx5 firmware),
+rdma_rw_io_needs_mr() steers the operation into the MR
+registration path. Each such operation consumes one or more MRs
+from a pool sized at max_rdma_ctxs -- roughly one MR per
+concurrent context. Under write-intensive workloads that issue
+many concurrent RDMA READs, the pool is rapidly exhausted,
+ib_mr_pool_get() returns NULL, and rdma_rw_init_one_mr() returns
+-EAGAIN. Upper layer protocols treat this as a fatal DMA mapping
+failure and tear down the connection.
+
+The max_sgl_rd check is a performance optimization, not a
+correctness requirement: the device can handle large SGE counts
+via direct posting, just less efficiently than with MR
+registration. When the MR pool cannot satisfy a request, falling
+back to the direct SGE (map_wrs) path avoids the connection
+reset while preserving the MR optimization for the common case
+where pool resources are available.
+
+Add a fallback in rdma_rw_ctx_init() so that -EAGAIN from
+rdma_rw_init_mr_wrs() triggers direct SGE posting instead of
+propagating the error. iWARP devices, which mandate MR
+registration for RDMA READs, and force_mr debug mode continue
+to treat -EAGAIN as terminal.
+
+Fixes: 00bd1439f464 ("RDMA/rw: Support threshold for registration vs scattering to local pages")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/rw.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
+index 2522ff1cc462c..49fbfe1cef689 100644
+--- a/drivers/infiniband/core/rw.c
++++ b/drivers/infiniband/core/rw.c
+@@ -326,14 +326,29 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u32 port_num,
+ if (rdma_rw_io_needs_mr(qp->device, port_num, dir, sg_cnt)) {
+ ret = rdma_rw_init_mr_wrs(ctx, qp, port_num, sg, sg_cnt,
+ sg_offset, remote_addr, rkey, dir);
+- } else if (sg_cnt > 1) {
++ /*
++ * If MR init succeeded or failed for a reason other
++ * than pool exhaustion, that result is final.
++ *
++ * Pool exhaustion (-EAGAIN) from the max_sgl_rd
++ * optimization is recoverable: fall back to
++ * direct SGE posting. iWARP and force_mr require
++ * MRs unconditionally, so -EAGAIN is terminal.
++ */
++ if (ret != -EAGAIN ||
++ rdma_protocol_iwarp(qp->device, port_num) ||
++ unlikely(rdma_rw_force_mr))
++ goto out;
++ }
++
++ if (sg_cnt > 1)
+ ret = rdma_rw_init_map_wrs(ctx, qp, sg, sg_cnt, sg_offset,
+ remote_addr, rkey, dir);
+- } else {
++ else
+ ret = rdma_rw_init_single_wr(ctx, qp, sg, sg_offset,
+ remote_addr, rkey, dir);
+- }
+
++out:
+ if (ret < 0)
+ goto out_unmap_sg;
+ return ret;
+--
+2.53.0
+
--- /dev/null
+From 2832d624117b05842d2c25502a7e6cf5bfe88550 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Mar 2026 19:43:31 +0100
+Subject: regmap: Synchronize cache for the page selector
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 09e70e4f119ff650d24c96161fd2f62ac7e424b0 ]
+
+If the selector register is represented in each page, its value
+according to the debugfs is stale because it gets synchronized
+only after the real page switch happens. Hence the regmap cache
+initialisation from the HW inherits outdated data in the selector
+register.
+
+Synchronize cache for the page selector just in time.
+
+Before (offset followed by hexdump, the first byte is selector):
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 05 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 01 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 02 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 03 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 04 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+After:
+
+ // Real registers
+ 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+ ...
+ // Virtual (per port)
+ 40: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 50: 01 ff 00 00 e0 e0 00 00 00 00 00 1f
+ 60: 02 ff 00 00 ff ff 00 00 00 00 00 00
+ 70: 03 ff 00 00 cf f3 00 00 00 00 00 0c
+ 80: 04 ff 00 00 00 00 00 00 00 00 00 ff
+ 90: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
+
+Fixes: 6863ca622759 ("regmap: Add support for register indirect addressing.")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap.c | 30 ++++++++++++++++++++++++++----
+ 1 file changed, 26 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index 48860beff95c9..3b84755c2e54d 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -1541,6 +1541,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ unsigned int val_num)
+ {
+ void *orig_work_buf;
++ unsigned int selector_reg;
+ unsigned int win_offset;
+ unsigned int win_page;
+ bool page_chg;
+@@ -1559,10 +1560,31 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ return -EINVAL;
+ }
+
+- /* It is possible to have selector register inside data window.
+- In that case, selector register is located on every page and
+- it needs no page switching, when accessed alone. */
++ /*
++ * Calculate the address of the selector register in the corresponding
++ * data window if it is located on every page.
++ */
++ page_chg = in_range(range->selector_reg, range->window_start, range->window_len);
++ if (page_chg)
++ selector_reg = range->range_min + win_page * range->window_len +
++ range->selector_reg - range->window_start;
++
++ /*
++ * It is possible to have selector register inside data window.
++ * In that case, selector register is located on every page and it
++ * needs no page switching, when accessed alone.
++ *
++ * Nevertheless we should synchronize the cache values for it.
++ * This can't be properly achieved if the selector register is
++ * the first and the only one to be read inside the data window.
++ * That's why we update it in that case as well.
++ *
++ * However, we specifically avoid updating it for the default page,
++ * when it's overlapped with the real data window, to prevent from
++ * infinite looping.
++ */
+ if (val_num > 1 ||
++ (page_chg && selector_reg != range->selector_reg) ||
+ range->window_start + win_offset != range->selector_reg) {
+ /* Use separate work_buf during page switching */
+ orig_work_buf = map->work_buf;
+@@ -1571,7 +1593,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+ ret = _regmap_update_bits(map, range->selector_reg,
+ range->selector_mask,
+ win_page << range->selector_shift,
+- &page_chg, false);
++ NULL, false);
+
+ map->work_buf = orig_work_buf;
+
+--
+2.53.0
+
--- /dev/null
+From a0fdf6651e5b95e326674d2390c866a8454fee0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 14:31:47 +0800
+Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue
+
+From: Yihang Li <liyihang9@huawei.com>
+
+[ Upstream commit d71afa9deb4d413232ba16d693f7d43b321931b4 ]
+
+After commit 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard
+and multi-channel scans"), if the device supports multiple channels (0 to
+shost->max_channel), user_scan() invokes updated sas_user_scan() to perform
+the scan behavior for a specific transfer. However, when the user
+specifies shost->max_channel, it will return -EINVAL, which is not
+expected.
+
+Fix and support specifying the scan shost->max_channel for scanning.
+
+Fixes: 37c4e72b0651 ("scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans")
+Signed-off-by: Yihang Li <liyihang9@huawei.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_sas.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index 7b4c4752e2160..a9eb548c0de9f 100644
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -1732,7 +1732,7 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ break;
+
+ default:
+- if (channel < shost->max_channel) {
++ if (channel <= shost->max_channel) {
+ res = scsi_scan_host_selected(shost, channel, id, lun,
+ SCSI_SCAN_MANUAL);
+ } else {
+--
+2.53.0
+
netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch
netfilter-ctnetlink-use-netlink-policy-range-checks.patch
net-macb-use-the-current-queue-number-for-stats.patch
+regmap-synchronize-cache-for-the-page-selector.patch
+rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch
+rdma-irdma-initialize-free_qp-completion-before-usin.patch
+rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch
+rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch
+rdma-irdma-clean-up-unnecessary-dereference-of-event.patch
+rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch
+rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch
+rdma-irdma-return-einval-for-invalid-arp-index-error.patch
+scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch
+x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch
+drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch
+pm-hibernate-don-t-ignore-return-from-set_memory_ro.patch
+pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch
+spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch
+asoc-intel-catpt-fix-the-device-initialization.patch
+acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch
+drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch
+hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch
+sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch
+asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch
+asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch
+spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch
--- /dev/null
+From 9632f0926107b472e493edab1ae36e1d9e89bd2c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 00:12:34 +0800
+Subject: spi: sn-f-ospi: Fix resource leak in f_ospi_probe()
+
+From: Felix Gu <ustc.gu@gmail.com>
+
+[ Upstream commit ef3d549e1deb3466c61f3b01d22fc3fe3e5efb08 ]
+
+In f_ospi_probe(), when num_cs validation fails, it returns without
+calling spi_controller_put() on the SPI controller, which causes a
+resource leak.
+
+Use devm_spi_alloc_host() instead of spi_alloc_host() to ensure the
+SPI controller is properly freed when probe fails.
+
+Fixes: 1b74dd64c861 ("spi: Add Socionext F_OSPI SPI flash controller driver")
+Signed-off-by: Felix Gu <ustc.gu@gmail.com>
+Link: https://patch.msgid.link/20260319-sn-f-v1-1-33a6738d2da8@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-sn-f-ospi.c | 17 +++++------------
+ 1 file changed, 5 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c
+index fd8c8eb37d01d..2d6d50b6f4dc9 100644
+--- a/drivers/spi/spi-sn-f-ospi.c
++++ b/drivers/spi/spi-sn-f-ospi.c
+@@ -609,7 +609,7 @@ static int f_ospi_probe(struct platform_device *pdev)
+ u32 num_cs = OSPI_NUM_CS;
+ int ret;
+
+- ctlr = spi_alloc_host(dev, sizeof(*ospi));
++ ctlr = devm_spi_alloc_host(dev, sizeof(*ospi));
+ if (!ctlr)
+ return -ENOMEM;
+
+@@ -632,16 +632,12 @@ static int f_ospi_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, ospi);
+
+ ospi->base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(ospi->base)) {
+- ret = PTR_ERR(ospi->base);
+- goto err_put_ctlr;
+- }
++ if (IS_ERR(ospi->base))
++ return PTR_ERR(ospi->base);
+
+ ospi->clk = devm_clk_get_enabled(dev, NULL);
+- if (IS_ERR(ospi->clk)) {
+- ret = PTR_ERR(ospi->clk);
+- goto err_put_ctlr;
+- }
++ if (IS_ERR(ospi->clk))
++ return PTR_ERR(ospi->clk);
+
+ mutex_init(&ospi->mlock);
+
+@@ -658,9 +654,6 @@ static int f_ospi_probe(struct platform_device *pdev)
+ err_destroy_mutex:
+ mutex_destroy(&ospi->mlock);
+
+-err_put_ctlr:
+- spi_controller_put(ctlr);
+-
+ return ret;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 0baae967e5810053b40a05d5d07d5692c63125b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 19:38:12 +0100
+Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF)
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b341c1176f2e001b3adf0b47154fc31589f7410e ]
+
+There is a teardown order issue in the driver. The SPI controller is
+registered using devm_spi_register_controller(), which delays
+unregistration of the SPI controller until after the fsl_lpspi_remove()
+function returns.
+
+As the fsl_lpspi_remove() function synchronously tears down the DMA
+channels, a running SPI transfer triggers the following NULL pointer
+dereference due to use after free:
+
+| fsl_lpspi 42550000.spi: I/O Error in DMA RX
+| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
+[...]
+| Call trace:
+| fsl_lpspi_dma_transfer+0x260/0x340 [spi_fsl_lpspi]
+| fsl_lpspi_transfer_one+0x198/0x448 [spi_fsl_lpspi]
+| spi_transfer_one_message+0x49c/0x7c8
+| __spi_pump_transfer_message+0x120/0x420
+| __spi_sync+0x2c4/0x520
+| spi_sync+0x34/0x60
+| spidev_message+0x20c/0x378 [spidev]
+| spidev_ioctl+0x398/0x750 [spidev]
+[...]
+
+Switch from devm_spi_register_controller() to spi_register_controller() in
+fsl_lpspi_probe() and add the corresponding spi_unregister_controller() in
+fsl_lpspi_remove().
+
+Fixes: 5314987de5e5 ("spi: imx: add lpspi bus driver")
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-fsl-lpspi.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
+index 8ef82a11ebb0f..6b66b0e62db4f 100644
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -954,7 +954,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+ enable_irq(irq);
+ }
+
+- ret = devm_spi_register_controller(&pdev->dev, controller);
++ ret = spi_register_controller(controller);
+ if (ret < 0) {
+ dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
+ goto free_dma;
+@@ -981,6 +981,7 @@ static void fsl_lpspi_remove(struct platform_device *pdev)
+ struct fsl_lpspi_data *fsl_lpspi =
+ spi_controller_get_devdata(controller);
+
++ spi_unregister_controller(controller);
+ fsl_lpspi_dma_exit(controller);
+
+ pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
+--
+2.53.0
+
--- /dev/null
+From be11ed34db52463c852415963b7749000291fda5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Mar 2026 23:29:50 +0100
+Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap
+
+From: Marc Buerg <buermarc@googlemail.com>
+
+[ Upstream commit f63a9df7e3f9f842945d292a19d9938924f066f9 ]
+
+proc_do_large_bitmap() does not initialize variable c, which is expected
+to be set to a trailing character by proc_get_long().
+
+However, proc_get_long() only sets c when the input buffer contains a
+trailing character after the parsed value.
+
+If c is not initialized it may happen to contain a '-'. If this is the
+case proc_do_large_bitmap() expects to be able to parse a second part of
+the input buffer. If there is no second part an unjustified -EINVAL will
+be returned.
+
+Initialize c to 0 to prevent returning -EINVAL on valid input.
+
+Fixes: 9f977fb7ae9d ("sysctl: add proc_do_large_bitmap")
+Signed-off-by: Marc Buerg <buermarc@googlemail.com>
+Reviewed-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Joel Granados <joel.granados@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sysctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 354a2d294f526..f8f07c0492388 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1374,7 +1374,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
+ unsigned long bitmap_len = table->maxlen;
+ unsigned long *bitmap = *(unsigned long **) table->data;
+ unsigned long *tmp_bitmap = NULL;
+- char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
++ char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c = 0;
+
+ if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
+ *lenp = 0;
+--
+2.53.0
+
--- /dev/null
+From e40ba7fd402170a62dcacb24ef3e1ce0a7bffcce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Mar 2026 15:59:48 +0200
+Subject: x86/efi: efi_unmap_boot_services: fix calculation of ranges_to_free
+ size
+
+From: Mike Rapoport (Microsoft) <rppt@kernel.org>
+
+[ Upstream commit 217c0a5c177a3d4f7c8497950cbf5c36756e8bbb ]
+
+ranges_to_free array should have enough room to store the entire EFI
+memmap plus an extra element for NULL entry.
+The calculation of this array size wrongly adds 1 to the overall size
+instead of adding 1 to the number of elements.
+
+Add parentheses to properly size the array.
+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory")
+Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/platform/efi/quirks.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
+index df3b45ef1420c..a29efaf6fe411 100644
+--- a/arch/x86/platform/efi/quirks.c
++++ b/arch/x86/platform/efi/quirks.c
+@@ -424,7 +424,7 @@ void __init efi_unmap_boot_services(void)
+ if (efi_enabled(EFI_DBG))
+ return;
+
+- sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1;
++ sz = sizeof(*ranges_to_free) * (efi.memmap.nr_map + 1);
+ ranges_to_free = kzalloc(sz, GFP_KERNEL);
+ if (!ranges_to_free) {
+ pr_err("Failed to allocate storage for freeable EFI regions\n");
+--
+2.53.0
+