From: Sasha Levin Date: Sat, 28 Mar 2026 20:50:37 +0000 (-0400) Subject: Fixes for all trees X-Git-Tag: v6.6.131~64 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43fb3f3f2ff4d92f09548324fea242f77967baa7;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch b/queue-5.10/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch new file mode 100644 index 0000000000..4b76e1bfe4 --- /dev/null +++ b/queue-5.10/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch @@ -0,0 +1,83 @@ +From 7a3b884834625ff8d0d4e7a8cdf105920ba6fc16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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) + + + 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 +Signed-off-by: Weiming Shi +Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/acpi-ec-fix-ec-address-space-handler-unregistration.patch b/queue-5.10/acpi-ec-fix-ec-address-space-handler-unregistration.patch new file mode 100644 index 0000000000..90d2cf8f6b --- /dev/null +++ b/queue-5.10/acpi-ec-fix-ec-address-space-handler-unregistration.patch @@ -0,0 +1,64 @@ +From b48ce2fd05d2c29e570b3b53dda6f2a7e9680e09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 15:23:34 +0100 +Subject: ACPI: EC: Fix EC address space handler unregistration + +From: Hans de Goede + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/acpi-ec-fix-ecdt-probe-ordering-issues.patch b/queue-5.10/acpi-ec-fix-ecdt-probe-ordering-issues.patch new file mode 100644 index 0000000000..afd60bb36e --- /dev/null +++ b/queue-5.10/acpi-ec-fix-ecdt-probe-ordering-issues.patch @@ -0,0 +1,156 @@ +From 1cb9837a706fe6a86a1c26f82604f7f852259ff6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/acpi-ec-install-address-space-handler-at-the-namespa.patch b/queue-5.10/acpi-ec-install-address-space-handler-at-the-namespa.patch new file mode 100644 index 0000000000..b175a40ce2 --- /dev/null +++ b/queue-5.10/acpi-ec-install-address-space-handler-at-the-namespa.patch @@ -0,0 +1,132 @@ +From 514c9d3959d766ac3a578cd1b42e88a3293fc078 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 May 2024 21:40:54 +0200 +Subject: ACPI: EC: Install address space handler at the namespace root + +From: Rafael J. Wysocki + +[ 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 +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 +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Hans de Goede +Reviewed-by: Mario Limonciello +Reviewed-by: Andy Shevchenko +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/acpica-allow-address_space_handler-install-and-_reg-.patch b/queue-5.10/acpica-allow-address_space_handler-install-and-_reg-.patch new file mode 100644 index 0000000000..897cc9b3a0 --- /dev/null +++ b/queue-5.10/acpica-allow-address_space_handler-install-and-_reg-.patch @@ -0,0 +1,217 @@ +From e2a118c9fd0e0ff62fc8dc7ba053271aa71fa2b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/acpica-include-acpi-acpixf.h-fix-indentation.patch b/queue-5.10/acpica-include-acpi-acpixf.h-fix-indentation.patch new file mode 100644 index 0000000000..2b9f299bcb --- /dev/null +++ b/queue-5.10/acpica-include-acpi-acpixf.h-fix-indentation.patch @@ -0,0 +1,176 @@ +From d8344b851905753191ed1dea37b9150f2c90d8fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 15:23:32 +0100 +Subject: ACPICA: include/acpi/acpixf.h: Fix indentation + +From: Hans de Goede + +[ 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 +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/asoc-intel-catpt-fix-the-device-initialization.patch b/queue-5.10/asoc-intel-catpt-fix-the-device-initialization.patch new file mode 100644 index 0000000000..9960eaab78 --- /dev/null +++ b/queue-5.10/asoc-intel-catpt-fix-the-device-initialization.patch @@ -0,0 +1,63 @@ +From 743e62c56e1b53e8655125cd977217778b4a4c88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 11:12:17 +0100 +Subject: ASoC: Intel: catpt: Fix the device initialization + +From: Cezary Rojewski + +[ 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 +Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle") +Signed-off-by: Cezary Rojewski +Reviewed-by: Andy Shevchenko +Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch b/queue-5.10/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch new file mode 100644 index 0000000000..6a0e744fcf --- /dev/null +++ b/queue-5.10/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch @@ -0,0 +1,46 @@ +From 7634ce3e3b63738496bff0621ed1abf9309dd70f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jani Nikula +Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com +Signed-off-by: Jani Nikula +(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch b/queue-5.10/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch new file mode 100644 index 0000000000..e0666beab2 --- /dev/null +++ b/queue-5.10/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch @@ -0,0 +1,187 @@ +From 9d1cc7f8e4563cad6be52f99ca89a6e1a85abf3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Nuno Sá +Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include + #include + #include + +@@ -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 + diff --git a/queue-5.10/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch b/queue-5.10/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch new file mode 100644 index 0000000000..c9a267742c --- /dev/null +++ b/queue-5.10/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch @@ -0,0 +1,87 @@ +From 7e1d2c706bc57ed164f74bba342d133707516f00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 15:41:58 -0400 +Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion + +From: Chuck Lever + +[ 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 +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/regmap-synchronize-cache-for-the-page-selector.patch b/queue-5.10/regmap-synchronize-cache-for-the-page-selector.patch new file mode 100644 index 0000000000..cceb8eb9e1 --- /dev/null +++ b/queue-5.10/regmap-synchronize-cache-for-the-page-selector.patch @@ -0,0 +1,112 @@ +From 1e205e91476c1b853d7b34e12c6450a722e27db2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Mar 2026 19:43:31 +0100 +Subject: regmap: Synchronize cache for the page selector + +From: Andy Shevchenko + +[ 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 +Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com +Tested-by: Marek Szyprowski +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch b/queue-5.10/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch new file mode 100644 index 0000000000..2f7f78434c --- /dev/null +++ b/queue-5.10/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch @@ -0,0 +1,44 @@ +From 54d07630f11aa9f92913e1582bf2a3910895447a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 14:31:47 +0800 +Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue + +From: Yihang Li + +[ 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 +Reviewed-by: John Garry +Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/series b/queue-5.10/series index 31c7947db6..9db532de42 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -277,3 +277,20 @@ netlink-introduce-bigendian-integer-types.patch 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 diff --git a/queue-5.10/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch b/queue-5.10/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch new file mode 100644 index 0000000000..457a3393f7 --- /dev/null +++ b/queue-5.10/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch @@ -0,0 +1,69 @@ +From 01279e4ff57e85e52d339fabc017b437b82cc29f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 19:38:12 +0100 +Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF) + +From: Marc Kleine-Budde + +[ 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 +Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch b/queue-5.10/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch new file mode 100644 index 0000000000..f9ddc9df91 --- /dev/null +++ b/queue-5.10/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch @@ -0,0 +1,47 @@ +From 18dc92903f7332335280cfd29af42f4f20641804 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 23:29:50 +0100 +Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap + +From: Marc Buerg + +[ 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 +Reviewed-by: Joel Granados +Signed-off-by: Joel Granados +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch b/queue-5.10/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch new file mode 100644 index 0000000000..c099f42cba --- /dev/null +++ b/queue-5.10/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch @@ -0,0 +1,42 @@ +From da08823759800b90213f8eac02e48c74193e9877 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory") +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/x86-fault-fold-mm_fault_error-into-do_user_addr_faul.patch b/queue-5.10/x86-fault-fold-mm_fault_error-into-do_user_addr_faul.patch new file mode 100644 index 0000000000..d01c42168e --- /dev/null +++ b/queue-5.10/x86-fault-fold-mm_fault_error-into-do_user_addr_faul.patch @@ -0,0 +1,230 @@ +From 0a9ba85121b34742a0391d446ea993f8b476c1b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Feb 2021 18:33:35 -0800 +Subject: x86/fault: Fold mm_fault_error() into do_user_addr_fault() + +From: Andy Lutomirski + +[ 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 +Signed-off-by: Borislav Petkov +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 +--- + 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 + diff --git a/queue-5.10/x86-fault-improve-kernel-executing-user-memory-handl.patch b/queue-5.10/x86-fault-improve-kernel-executing-user-memory-handl.patch new file mode 100644 index 0000000000..cce0b8dfb0 --- /dev/null +++ b/queue-5.10/x86-fault-improve-kernel-executing-user-memory-handl.patch @@ -0,0 +1,79 @@ +From e07087dc03b5f0b000aa858aebc21cb370f60c03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Feb 2021 18:33:39 -0800 +Subject: x86/fault: Improve kernel-executing-user-memory handling + +From: Andy Lutomirski + +[ 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 +Signed-off-by: Borislav Petkov +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 +--- + 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 + diff --git a/queue-5.15/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch b/queue-5.15/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch new file mode 100644 index 0000000000..cd6cfff88f --- /dev/null +++ b/queue-5.15/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch @@ -0,0 +1,83 @@ +From 5df19c7f7af6a069de3b21efa641659f5ef42837 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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) + + + 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 +Signed-off-by: Weiming Shi +Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/acpi-ec-fix-ec-address-space-handler-unregistration.patch b/queue-5.15/acpi-ec-fix-ec-address-space-handler-unregistration.patch new file mode 100644 index 0000000000..f44b885ba3 --- /dev/null +++ b/queue-5.15/acpi-ec-fix-ec-address-space-handler-unregistration.patch @@ -0,0 +1,64 @@ +From 2acbeae2f50fec974ff68aa318c97df22503686d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 15:23:34 +0100 +Subject: ACPI: EC: Fix EC address space handler unregistration + +From: Hans de Goede + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/acpi-ec-fix-ecdt-probe-ordering-issues.patch b/queue-5.15/acpi-ec-fix-ecdt-probe-ordering-issues.patch new file mode 100644 index 0000000000..9073a96e50 --- /dev/null +++ b/queue-5.15/acpi-ec-fix-ecdt-probe-ordering-issues.patch @@ -0,0 +1,156 @@ +From 04c4bd15565b6d4714dcd19f69323a883043f00c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/acpi-ec-install-address-space-handler-at-the-namespa.patch b/queue-5.15/acpi-ec-install-address-space-handler-at-the-namespa.patch new file mode 100644 index 0000000000..ca5245849b --- /dev/null +++ b/queue-5.15/acpi-ec-install-address-space-handler-at-the-namespa.patch @@ -0,0 +1,132 @@ +From 207a8573d60a18fde9dae1f9e5a21bf4a74d2012 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 May 2024 21:40:54 +0200 +Subject: ACPI: EC: Install address space handler at the namespace root + +From: Rafael J. Wysocki + +[ 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 +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 +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Hans de Goede +Reviewed-by: Mario Limonciello +Reviewed-by: Andy Shevchenko +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/acpica-allow-address_space_handler-install-and-_reg-.patch b/queue-5.15/acpica-allow-address_space_handler-install-and-_reg-.patch new file mode 100644 index 0000000000..c27d4f098f --- /dev/null +++ b/queue-5.15/acpica-allow-address_space_handler-install-and-_reg-.patch @@ -0,0 +1,217 @@ +From 6a4fdf8cc605ba316426f6e9bdc9b74412b00962 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/acpica-include-acpi-acpixf.h-fix-indentation.patch b/queue-5.15/acpica-include-acpi-acpixf.h-fix-indentation.patch new file mode 100644 index 0000000000..855ff42888 --- /dev/null +++ b/queue-5.15/acpica-include-acpi-acpixf.h-fix-indentation.patch @@ -0,0 +1,176 @@ +From c380b9b3aa0a98bc3da0289c6c0caf1a770fd732 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 15:23:32 +0100 +Subject: ACPICA: include/acpi/acpixf.h: Fix indentation + +From: Hans de Goede + +[ 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 +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch b/queue-5.15/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch new file mode 100644 index 0000000000..570624313e --- /dev/null +++ b/queue-5.15/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch @@ -0,0 +1,80 @@ +From aa16ee1d20448e04d071fabf702b5bf9e761ae1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch b/queue-5.15/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch new file mode 100644 index 0000000000..8d30833436 --- /dev/null +++ b/queue-5.15/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch @@ -0,0 +1,82 @@ +From 7663f4f52c85d6992c16ea076c6f4ea1253537e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/asoc-intel-catpt-fix-the-device-initialization.patch b/queue-5.15/asoc-intel-catpt-fix-the-device-initialization.patch new file mode 100644 index 0000000000..74d177c0a9 --- /dev/null +++ b/queue-5.15/asoc-intel-catpt-fix-the-device-initialization.patch @@ -0,0 +1,63 @@ +From 61272ad177a86639c88ccaa92b3c30610018a6fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 11:12:17 +0100 +Subject: ASoC: Intel: catpt: Fix the device initialization + +From: Cezary Rojewski + +[ 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 +Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle") +Signed-off-by: Cezary Rojewski +Reviewed-by: Andy Shevchenko +Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch b/queue-5.15/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch new file mode 100644 index 0000000000..b35d68653e --- /dev/null +++ b/queue-5.15/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch @@ -0,0 +1,46 @@ +From 7f822245c4b1fcdbb65ba50bbcebc85484ccb097 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jani Nikula +Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com +Signed-off-by: Jani Nikula +(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch b/queue-5.15/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch new file mode 100644 index 0000000000..bf3a557a87 --- /dev/null +++ b/queue-5.15/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch @@ -0,0 +1,187 @@ +From f3ef964869a437d0514a53df407557c63a6fd168 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Nuno Sá +Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include + #include + #include + +@@ -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 + diff --git a/queue-5.15/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch b/queue-5.15/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch new file mode 100644 index 0000000000..a344470483 --- /dev/null +++ b/queue-5.15/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch @@ -0,0 +1,64 @@ +From bc70842b0741b7262ce02b609b7402f5f7b8c61c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:43 -0500 +Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node + +From: Ivan Barrera + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch b/queue-5.15/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch new file mode 100644 index 0000000000..179c0e4517 --- /dev/null +++ b/queue-5.15/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch @@ -0,0 +1,44 @@ +From 8f84cd089f30733c8ef3c71e6bc9d6bd6286e10f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:45 -0500 +Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections + +From: Anil Samal + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch b/queue-5.15/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch new file mode 100644 index 0000000000..f643d2ae60 --- /dev/null +++ b/queue-5.15/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch @@ -0,0 +1,38 @@ +From 5f2016b5c37d6ba89e2a6b3758813e416b990162 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch b/queue-5.15/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch new file mode 100644 index 0000000000..a0e9a0d1ba --- /dev/null +++ b/queue-5.15/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch @@ -0,0 +1,38 @@ +From 8a93c5b63e34b85e402b1e204d8691d2f89e14d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:44 -0500 +Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err() + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-irdma-return-einval-for-invalid-arp-index-error.patch b/queue-5.15/rdma-irdma-return-einval-for-invalid-arp-index-error.patch new file mode 100644 index 0000000000..b36f5fe475 --- /dev/null +++ b/queue-5.15/rdma-irdma-return-einval-for-invalid-arp-index-error.patch @@ -0,0 +1,86 @@ +From f629de500dc7130045e877bfd7b81e08fbc918e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:46 -0500 +Subject: RDMA/irdma: Return EINVAL for invalid arp index error + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch b/queue-5.15/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch new file mode 100644 index 0000000000..4239e3b582 --- /dev/null +++ b/queue-5.15/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch @@ -0,0 +1,45 @@ +From 10212fe4d8d19b1cea935f766ce3571cbf0ab4ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch b/queue-5.15/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch new file mode 100644 index 0000000000..1f6a352adb --- /dev/null +++ b/queue-5.15/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch @@ -0,0 +1,87 @@ +From 55a125727411c08c31885b014c6460c56650c551 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 15:41:58 -0400 +Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion + +From: Chuck Lever + +[ 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 +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/regmap-synchronize-cache-for-the-page-selector.patch b/queue-5.15/regmap-synchronize-cache-for-the-page-selector.patch new file mode 100644 index 0000000000..07c94501c5 --- /dev/null +++ b/queue-5.15/regmap-synchronize-cache-for-the-page-selector.patch @@ -0,0 +1,112 @@ +From c3da62913d21d18c2dffc8ca309b259ae6909df0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Mar 2026 19:43:31 +0100 +Subject: regmap: Synchronize cache for the page selector + +From: Andy Shevchenko + +[ 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 +Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com +Tested-by: Marek Szyprowski +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch b/queue-5.15/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch new file mode 100644 index 0000000000..644a6dbecb --- /dev/null +++ b/queue-5.15/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch @@ -0,0 +1,44 @@ +From b30b2e7ed90f73bebe73ca6593333dd7c8ebeee5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 14:31:47 +0800 +Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue + +From: Yihang Li + +[ 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 +Reviewed-by: John Garry +Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series index 331395156b..61f0b09b60 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -342,3 +342,26 @@ netlink-introduce-bigendian-integer-types.patch 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 diff --git a/queue-5.15/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch b/queue-5.15/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch new file mode 100644 index 0000000000..9f993a1884 --- /dev/null +++ b/queue-5.15/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch @@ -0,0 +1,69 @@ +From 62a49609df15f5460a7907b1ed5820740dd1a692 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 19:38:12 +0100 +Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF) + +From: Marc Kleine-Budde + +[ 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 +Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch b/queue-5.15/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch new file mode 100644 index 0000000000..5fb2576228 --- /dev/null +++ b/queue-5.15/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch @@ -0,0 +1,47 @@ +From b9fe966e91706a0e50368573d912c0505f8e9141 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 23:29:50 +0100 +Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap + +From: Marc Buerg + +[ 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 +Reviewed-by: Joel Granados +Signed-off-by: Joel Granados +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch b/queue-5.15/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch new file mode 100644 index 0000000000..6e460ff0ad --- /dev/null +++ b/queue-5.15/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch @@ -0,0 +1,42 @@ +From b561fd2f20b43cc2e9308b8a8cf3bcf7f057e893 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory") +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch b/queue-6.1/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch new file mode 100644 index 0000000000..1fe2f300b6 --- /dev/null +++ b/queue-6.1/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch @@ -0,0 +1,83 @@ +From caa84bd85e638f2df243d31f7c786ae32ad29ad4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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) + + + 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 +Signed-off-by: Weiming Shi +Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/acpi-ec-fix-ec-address-space-handler-unregistration.patch b/queue-6.1/acpi-ec-fix-ec-address-space-handler-unregistration.patch new file mode 100644 index 0000000000..7553747b48 --- /dev/null +++ b/queue-6.1/acpi-ec-fix-ec-address-space-handler-unregistration.patch @@ -0,0 +1,64 @@ +From 6eb4f63c712dccb027a633d33dc1ac28aa546bbd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 15:23:34 +0100 +Subject: ACPI: EC: Fix EC address space handler unregistration + +From: Hans de Goede + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/acpi-ec-fix-ecdt-probe-ordering-issues.patch b/queue-6.1/acpi-ec-fix-ecdt-probe-ordering-issues.patch new file mode 100644 index 0000000000..fb507926ec --- /dev/null +++ b/queue-6.1/acpi-ec-fix-ecdt-probe-ordering-issues.patch @@ -0,0 +1,156 @@ +From 68fb141ac0958b643875bdd57daef3104ba9fc45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/acpi-ec-install-address-space-handler-at-the-namespa.patch b/queue-6.1/acpi-ec-install-address-space-handler-at-the-namespa.patch new file mode 100644 index 0000000000..79adac8070 --- /dev/null +++ b/queue-6.1/acpi-ec-install-address-space-handler-at-the-namespa.patch @@ -0,0 +1,132 @@ +From 050f7f44e7b92b43854ee228578ec940ae7d99cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 May 2024 21:40:54 +0200 +Subject: ACPI: EC: Install address space handler at the namespace root + +From: Rafael J. Wysocki + +[ 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 +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 +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Hans de Goede +Reviewed-by: Mario Limonciello +Reviewed-by: Andy Shevchenko +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/acpica-allow-address_space_handler-install-and-_reg-.patch b/queue-6.1/acpica-allow-address_space_handler-install-and-_reg-.patch new file mode 100644 index 0000000000..db76383cbb --- /dev/null +++ b/queue-6.1/acpica-allow-address_space_handler-install-and-_reg-.patch @@ -0,0 +1,217 @@ +From e32848ffc654650a658ad05e8a136b273aa5885d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/acpica-include-acpi-acpixf.h-fix-indentation.patch b/queue-6.1/acpica-include-acpi-acpixf.h-fix-indentation.patch new file mode 100644 index 0000000000..fe3f4c2100 --- /dev/null +++ b/queue-6.1/acpica-include-acpi-acpixf.h-fix-indentation.patch @@ -0,0 +1,176 @@ +From fcd1467987995e8d87e89fb3f1c12f9f79e0d74c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 15:23:32 +0100 +Subject: ACPICA: include/acpi/acpixf.h: Fix indentation + +From: Hans de Goede + +[ 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 +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch b/queue-6.1/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch new file mode 100644 index 0000000000..e38a1e8339 --- /dev/null +++ b/queue-6.1/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch @@ -0,0 +1,80 @@ +From 357049b8b8b1e523535b2d3d25d31b401988802d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch b/queue-6.1/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch new file mode 100644 index 0000000000..84513e8e15 --- /dev/null +++ b/queue-6.1/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch @@ -0,0 +1,82 @@ +From 8ef8a3850becd0c949d48393046604bf426d9938 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/asoc-intel-catpt-fix-the-device-initialization.patch b/queue-6.1/asoc-intel-catpt-fix-the-device-initialization.patch new file mode 100644 index 0000000000..712f27111a --- /dev/null +++ b/queue-6.1/asoc-intel-catpt-fix-the-device-initialization.patch @@ -0,0 +1,63 @@ +From 84b08d9d802b38e6662cab170c3939f57caae537 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 11:12:17 +0100 +Subject: ASoC: Intel: catpt: Fix the device initialization + +From: Cezary Rojewski + +[ 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 +Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle") +Signed-off-by: Cezary Rojewski +Reviewed-by: Andy Shevchenko +Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch b/queue-6.1/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch new file mode 100644 index 0000000000..6681103004 --- /dev/null +++ b/queue-6.1/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch @@ -0,0 +1,62 @@ +From 80bb7aaab5717b5d17e987d87e4d365b7dc0c036 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Dan Carpenter +Cc: Christian König +Cc: Alex Deucher +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch b/queue-6.1/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch new file mode 100644 index 0000000000..c147217181 --- /dev/null +++ b/queue-6.1/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch @@ -0,0 +1,46 @@ +From 3ffada3b9ed899b8c2c761e2e7be4acc44dc1afe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jani Nikula +Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com +Signed-off-by: Jani Nikula +(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch b/queue-6.1/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch new file mode 100644 index 0000000000..963a567bd9 --- /dev/null +++ b/queue-6.1/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch @@ -0,0 +1,187 @@ +From 2fa7a16b99dc74214881aeee69d0480bd10fd440 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Nuno Sá +Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include + #include + #include + +@@ -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 + diff --git a/queue-6.1/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch b/queue-6.1/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch new file mode 100644 index 0000000000..e092632fdc --- /dev/null +++ b/queue-6.1/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch @@ -0,0 +1,64 @@ +From 7791d15ec206e96bab5b35d620cef319b344f517 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:43 -0500 +Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node + +From: Ivan Barrera + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch b/queue-6.1/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch new file mode 100644 index 0000000000..3aa9120cce --- /dev/null +++ b/queue-6.1/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch @@ -0,0 +1,44 @@ +From 8b320da77cab5913b6bd2d65f8151eb2637832ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:45 -0500 +Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections + +From: Anil Samal + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/rdma-irdma-initialize-free_qp-completion-before-usin.patch b/queue-6.1/rdma-irdma-initialize-free_qp-completion-before-usin.patch new file mode 100644 index 0000000000..2c2e900159 --- /dev/null +++ b/queue-6.1/rdma-irdma-initialize-free_qp-completion-before-usin.patch @@ -0,0 +1,46 @@ +From 0af3430feac4dc8cf6346ae70cd94c21bc253225 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:38 -0500 +Subject: RDMA/irdma: Initialize free_qp completion before using it + +From: Jacob Moroni + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch b/queue-6.1/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch new file mode 100644 index 0000000000..e3ba99ed10 --- /dev/null +++ b/queue-6.1/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch @@ -0,0 +1,38 @@ +From bf147f829ebcc43c347ea31de9598e7f4f19d7a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch b/queue-6.1/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch new file mode 100644 index 0000000000..67604edd42 --- /dev/null +++ b/queue-6.1/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch @@ -0,0 +1,38 @@ +From 8b58f082423797c9bc85e528981e8c0b8aadb480 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:44 -0500 +Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err() + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/rdma-irdma-return-einval-for-invalid-arp-index-error.patch b/queue-6.1/rdma-irdma-return-einval-for-invalid-arp-index-error.patch new file mode 100644 index 0000000000..4e87f9c213 --- /dev/null +++ b/queue-6.1/rdma-irdma-return-einval-for-invalid-arp-index-error.patch @@ -0,0 +1,86 @@ +From b6877084939a2be6f85efa93feb1eadfbf5a3750 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:46 -0500 +Subject: RDMA/irdma: Return EINVAL for invalid arp index error + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch b/queue-6.1/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch new file mode 100644 index 0000000000..3b572256eb --- /dev/null +++ b/queue-6.1/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch @@ -0,0 +1,45 @@ +From 154227439ab96fb75ba506b9b9242be37eb62614 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch b/queue-6.1/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch new file mode 100644 index 0000000000..a5ae501905 --- /dev/null +++ b/queue-6.1/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch @@ -0,0 +1,87 @@ +From 2d0bfce7d7d5e2ad52df214b6cb1d4801c540089 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 15:41:58 -0400 +Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion + +From: Chuck Lever + +[ 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 +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/regmap-synchronize-cache-for-the-page-selector.patch b/queue-6.1/regmap-synchronize-cache-for-the-page-selector.patch new file mode 100644 index 0000000000..65ed40e745 --- /dev/null +++ b/queue-6.1/regmap-synchronize-cache-for-the-page-selector.patch @@ -0,0 +1,112 @@ +From 9f877b4e4d05ba28137e7e2761f0a2fb768c839b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Mar 2026 19:43:31 +0100 +Subject: regmap: Synchronize cache for the page selector + +From: Andy Shevchenko + +[ 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 +Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com +Tested-by: Marek Szyprowski +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch b/queue-6.1/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch new file mode 100644 index 0000000000..cfcc034c86 --- /dev/null +++ b/queue-6.1/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch @@ -0,0 +1,44 @@ +From 6fcb2256c3a1c30b68620daca0ec74b019329890 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 14:31:47 +0800 +Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue + +From: Yihang Li + +[ 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 +Reviewed-by: John Garry +Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/series b/queue-6.1/series index 3b54c695ec..c68980eed6 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -61,3 +61,28 @@ netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch 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 diff --git a/queue-6.1/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch b/queue-6.1/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch new file mode 100644 index 0000000000..1a577f3fb9 --- /dev/null +++ b/queue-6.1/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch @@ -0,0 +1,69 @@ +From 1009aa803b44789f4ac0af4d87e93ca0186ecb5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 19:38:12 +0100 +Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF) + +From: Marc Kleine-Budde + +[ 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 +Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch b/queue-6.1/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch new file mode 100644 index 0000000000..249b230aa1 --- /dev/null +++ b/queue-6.1/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch @@ -0,0 +1,47 @@ +From 6c63508c646bc28b092adcdf76f3b67185511d65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 23:29:50 +0100 +Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap + +From: Marc Buerg + +[ 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 +Reviewed-by: Joel Granados +Signed-off-by: Joel Granados +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch b/queue-6.1/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch new file mode 100644 index 0000000000..0e1c719720 --- /dev/null +++ b/queue-6.1/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch @@ -0,0 +1,42 @@ +From c36f787f44b953f92e16fe2cccfe7aa4dd1c61ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory") +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch b/queue-6.12/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch new file mode 100644 index 0000000000..9f924d4c1d --- /dev/null +++ b/queue-6.12/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch @@ -0,0 +1,83 @@ +From 24b249312d66eb66330aeb459961024984bec513 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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) + + + 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 +Signed-off-by: Weiming Shi +Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch b/queue-6.12/alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch new file mode 100644 index 0000000000..42a44e189b --- /dev/null +++ b/queue-6.12/alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch @@ -0,0 +1,94 @@ +From c2c0bdb95fce22cd59979ae689fa09456bf9e8ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 20:11:27 +0000 +Subject: ALSA: hda/realtek: Sequence GPIO2 on Star Labs StarFighter + +From: Sean Rhodes + +[ 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 +Signed-off-by: Sean Rhodes +Link: https://patch.msgid.link/20260315201127.33744-1-sean@starlabs.systems +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch b/queue-6.12/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch new file mode 100644 index 0000000000..bf0383847f --- /dev/null +++ b/queue-6.12/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch @@ -0,0 +1,80 @@ +From c441bfce6f2a2a2c8255def521edbefff205ec48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch b/queue-6.12/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch new file mode 100644 index 0000000000..a3c53aa06f --- /dev/null +++ b/queue-6.12/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch @@ -0,0 +1,82 @@ +From 8c5a2cfd41e42078bbdf0903d079fbd3447bd634 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/asoc-intel-catpt-fix-the-device-initialization.patch b/queue-6.12/asoc-intel-catpt-fix-the-device-initialization.patch new file mode 100644 index 0000000000..17f7994cf5 --- /dev/null +++ b/queue-6.12/asoc-intel-catpt-fix-the-device-initialization.patch @@ -0,0 +1,63 @@ +From 0d3110b50e53d0d4bf9078788832930a63d34fad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 11:12:17 +0100 +Subject: ASoC: Intel: catpt: Fix the device initialization + +From: Cezary Rojewski + +[ 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 +Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle") +Signed-off-by: Cezary Rojewski +Reviewed-by: Andy Shevchenko +Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch b/queue-6.12/drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch new file mode 100644 index 0000000000..62d7ec03e7 --- /dev/null +++ b/queue-6.12/drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch @@ -0,0 +1,121 @@ +From 605e085e6ac8e03d20477967aa71ef6de9c09ac9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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 +Reviewed-by: Harry Wentland +Signed-off-by: Alex Deucher +(cherry picked from commit cc7c7121ae082b7b82891baa7280f1ff2608f22b) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch b/queue-6.12/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch new file mode 100644 index 0000000000..3d31543a27 --- /dev/null +++ b/queue-6.12/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch @@ -0,0 +1,62 @@ +From 265e96670e47050cae6d28655c4dcc2d0c44f7b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Dan Carpenter +Cc: Christian König +Cc: Alex Deucher +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch b/queue-6.12/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch new file mode 100644 index 0000000000..e2791c22fd --- /dev/null +++ b/queue-6.12/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch @@ -0,0 +1,46 @@ +From 1889b919dc635c145af349cf26b7907e7892663e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jani Nikula +Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com +Signed-off-by: Jani Nikula +(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch b/queue-6.12/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch new file mode 100644 index 0000000000..aa674cfcb6 --- /dev/null +++ b/queue-6.12/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch @@ -0,0 +1,187 @@ +From e4a9a151305f82ad8d8483c60f3736b2315faabd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Nuno Sá +Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include + #include + #include + +@@ -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 + diff --git a/queue-6.12/hwmon-pmbus-core-fix-various-coding-style-issues.patch b/queue-6.12/hwmon-pmbus-core-fix-various-coding-style-issues.patch new file mode 100644 index 0000000000..4d0475983f --- /dev/null +++ b/queue-6.12/hwmon-pmbus-core-fix-various-coding-style-issues.patch @@ -0,0 +1,198 @@ +From b0b25faa40441fae5b32504ff3526de70ab8c0e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Jul 2023 13:58:19 -0700 +Subject: hwmon: (pmbus/core) Fix various coding style issues + +From: Guenter Roeck + +[ 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 +Signed-off-by: Guenter Roeck +Stable-dep-of: 805a5bd1c3f3 ("hwmon: (pmbus) Mark lowest/average/highest/rated attributes as read-only") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch b/queue-6.12/hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch new file mode 100644 index 0000000000..d214e1d4b9 --- /dev/null +++ b/queue-6.12/hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch @@ -0,0 +1,186 @@ +From ce2772f265a4e28525ac70e0b6c0c4cfdd24b69c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 18:54:11 -0700 +Subject: hwmon: (pmbus) Introduce the concept of "write-only" attributes + +From: Guenter Roeck + +[ 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 +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch b/queue-6.12/hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch new file mode 100644 index 0000000000..3aa80408a8 --- /dev/null +++ b/queue-6.12/hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch @@ -0,0 +1,280 @@ +From 4b62e7f1cf803713e4bc1fc734444c550da0109f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 16:41:07 -0700 +Subject: hwmon: (pmbus) Mark lowest/average/highest/rated attributes as + read-only + +From: Guenter Roeck + +[ 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 +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch b/queue-6.12/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch new file mode 100644 index 0000000000..263337f7df --- /dev/null +++ b/queue-6.12/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch @@ -0,0 +1,64 @@ +From b6c90c1327c5d2e89ea17aeda194fbc919ce3ecc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Mar 2026 18:39:41 +0100 +Subject: PM: hibernate: Drain trailing zero pages on userspace restore + +From: Alberto Garcia + +[ 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 +Acked-by: Brian Geffon +Link: https://patch.msgid.link/ef5a7c5e3e3dbd17dcb20efaa0c53a47a23498bb.1773075892.git.berto@igalia.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch b/queue-6.12/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch new file mode 100644 index 0000000000..19e6087f3b --- /dev/null +++ b/queue-6.12/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch @@ -0,0 +1,64 @@ +From 4baf70c60ea7d85e83e89eec647830f14891ba4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:43 -0500 +Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node + +From: Ivan Barrera + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch b/queue-6.12/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch new file mode 100644 index 0000000000..13a6ab2a1a --- /dev/null +++ b/queue-6.12/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch @@ -0,0 +1,44 @@ +From cdae41813cb0aed7ef974e925dc951279e3ef76f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:45 -0500 +Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections + +From: Anil Samal + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/rdma-irdma-initialize-free_qp-completion-before-usin.patch b/queue-6.12/rdma-irdma-initialize-free_qp-completion-before-usin.patch new file mode 100644 index 0000000000..d22c3f70aa --- /dev/null +++ b/queue-6.12/rdma-irdma-initialize-free_qp-completion-before-usin.patch @@ -0,0 +1,46 @@ +From 2e2938b392ae4c23dadcf15a2cbdc6cb2fce73ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:38 -0500 +Subject: RDMA/irdma: Initialize free_qp completion before using it + +From: Jacob Moroni + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch b/queue-6.12/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch new file mode 100644 index 0000000000..ff3e255843 --- /dev/null +++ b/queue-6.12/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch @@ -0,0 +1,38 @@ +From 9722774586d7facd5d1c19b7d3b39d2c9b0fa517 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch b/queue-6.12/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch new file mode 100644 index 0000000000..6f5f1b0426 --- /dev/null +++ b/queue-6.12/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch @@ -0,0 +1,38 @@ +From 9cc253528fef3f2389d1270b16bb78e54cdaa13e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:44 -0500 +Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err() + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/rdma-irdma-return-einval-for-invalid-arp-index-error.patch b/queue-6.12/rdma-irdma-return-einval-for-invalid-arp-index-error.patch new file mode 100644 index 0000000000..1aaed460c6 --- /dev/null +++ b/queue-6.12/rdma-irdma-return-einval-for-invalid-arp-index-error.patch @@ -0,0 +1,86 @@ +From 63f7bb8d63f50466922d6557ad28822eb991310e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:46 -0500 +Subject: RDMA/irdma: Return EINVAL for invalid arp index error + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch b/queue-6.12/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch new file mode 100644 index 0000000000..7ab6c0025a --- /dev/null +++ b/queue-6.12/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch @@ -0,0 +1,45 @@ +From b035951106e0ea88aff51bf933915306b60c39b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch b/queue-6.12/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch new file mode 100644 index 0000000000..5c27ece01e --- /dev/null +++ b/queue-6.12/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch @@ -0,0 +1,87 @@ +From 99d8efe1f4dd5e8355f0059802323733d09e0245 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 15:41:58 -0400 +Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion + +From: Chuck Lever + +[ 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 +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/regmap-synchronize-cache-for-the-page-selector.patch b/queue-6.12/regmap-synchronize-cache-for-the-page-selector.patch new file mode 100644 index 0000000000..542b662f70 --- /dev/null +++ b/queue-6.12/regmap-synchronize-cache-for-the-page-selector.patch @@ -0,0 +1,112 @@ +From 4a572989472951d8875b9909a96609450cf6779f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Mar 2026 19:43:31 +0100 +Subject: regmap: Synchronize cache for the page selector + +From: Andy Shevchenko + +[ 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 +Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com +Tested-by: Marek Szyprowski +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch b/queue-6.12/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch new file mode 100644 index 0000000000..3bf0010e32 --- /dev/null +++ b/queue-6.12/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch @@ -0,0 +1,44 @@ +From 0b00eee8d0971f1f61c21011316b2fd055aafe36 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 14:31:47 +0800 +Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue + +From: Yihang Li + +[ 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 +Reviewed-by: John Garry +Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/series b/queue-6.12/series index 3defca1f83..83ce794576 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -102,3 +102,33 @@ netfilter-nf_conntrack_expect-skip-expectations-in-o.patch 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 diff --git a/queue-6.12/spi-group-cs-related-fields-in-struct-spi_device.patch b/queue-6.12/spi-group-cs-related-fields-in-struct-spi_device.patch new file mode 100644 index 0000000000..4638247d14 --- /dev/null +++ b/queue-6.12/spi-group-cs-related-fields-in-struct-spi_device.patch @@ -0,0 +1,120 @@ +From f22e5052f17bc7a3aa9123911026719667187537 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 13:35:59 +0300 +Subject: spi: Group CS related fields in struct spi_device + +From: Andy Shevchenko + +[ 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 +Link: https://patch.msgid.link/20250331103609.4160281-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Mark Brown +Stable-dep-of: cc34d77dd487 ("spi: use generic driver_override infrastructure") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/spi-meson-spicc-fix-double-put-in-remove-path.patch b/queue-6.12/spi-meson-spicc-fix-double-put-in-remove-path.patch new file mode 100644 index 0000000000..3b1c6934c9 --- /dev/null +++ b/queue-6.12/spi-meson-spicc-fix-double-put-in-remove-path.patch @@ -0,0 +1,42 @@ +From c950fc52e229d9896d340bf5ad529edad5385cfd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 Mar 2026 21:29:56 +0800 +Subject: spi: meson-spicc: Fix double-put in remove path + +From: Felix Gu + +[ 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 +Reviewed-by: Johan Hovold +Link: https://patch.msgid.link/20260322-rockchip-v1-1-fac3f0c6dad8@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch b/queue-6.12/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch new file mode 100644 index 0000000000..00a6aaf7ed --- /dev/null +++ b/queue-6.12/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch @@ -0,0 +1,72 @@ +From aaf3f1fc9b2ac453ef44853984263e97152f4462 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 00:12:34 +0800 +Subject: spi: sn-f-ospi: Fix resource leak in f_ospi_probe() + +From: Felix Gu + +[ 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 +Link: https://patch.msgid.link/20260319-sn-f-v1-1-33a6738d2da8@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch b/queue-6.12/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch new file mode 100644 index 0000000000..27844bd517 --- /dev/null +++ b/queue-6.12/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch @@ -0,0 +1,69 @@ +From c8640469087c067a79c9c256986ed55136771026 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 19:38:12 +0100 +Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF) + +From: Marc Kleine-Budde + +[ 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 +Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/spi-use-generic-driver_override-infrastructure.patch b/queue-6.12/spi-use-generic-driver_override-infrastructure.patch new file mode 100644 index 0000000000..56e4da74b3 --- /dev/null +++ b/queue-6.12/spi-use-generic-driver_override-infrastructure.patch @@ -0,0 +1,118 @@ +From 0ccdbeea9951b508e07673527b9523ba9fe26e79 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 01:59:15 +0100 +Subject: spi: use generic driver_override infrastructure + +From: Danilo Krummrich + +[ 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 +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789 +Fixes: 5039563e7c25 ("spi: Add driver_override SPI device attribute") +Signed-off-by: Danilo Krummrich +Link: https://patch.msgid.link/20260324005919.2408620-12-dakr@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch b/queue-6.12/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch new file mode 100644 index 0000000000..551bae8643 --- /dev/null +++ b/queue-6.12/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch @@ -0,0 +1,47 @@ +From 2c3edf95e5e64a24812d617e4ff55431856e51d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 23:29:50 +0100 +Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap + +From: Marc Buerg + +[ 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 +Reviewed-by: Joel Granados +Signed-off-by: Joel Granados +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.12/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch b/queue-6.12/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch new file mode 100644 index 0000000000..14e0087604 --- /dev/null +++ b/queue-6.12/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch @@ -0,0 +1,42 @@ +From 4b4696d9c4772de37fd74733c8afbafabd03f5c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory") +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch b/queue-6.18/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch new file mode 100644 index 0000000000..5ac9fa0b98 --- /dev/null +++ b/queue-6.18/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch @@ -0,0 +1,83 @@ +From cd325b849d14cfb51d55a4d019a3c97bcfd09d5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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) + + + 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 +Signed-off-by: Weiming Shi +Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch b/queue-6.18/alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch new file mode 100644 index 0000000000..b668db829c --- /dev/null +++ b/queue-6.18/alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch @@ -0,0 +1,94 @@ +From ecacecc011f244d416e4f1e83e4186ff38048a85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 20:11:27 +0000 +Subject: ALSA: hda/realtek: Sequence GPIO2 on Star Labs StarFighter + +From: Sean Rhodes + +[ 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 +Signed-off-by: Sean Rhodes +Link: https://patch.msgid.link/20260315201127.33744-1-sean@starlabs.systems +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/alsa-usb-audio-exclude-scarlett-2i2-1st-gen-from-ski.patch b/queue-6.18/alsa-usb-audio-exclude-scarlett-2i2-1st-gen-from-ski.patch new file mode 100644 index 0000000000..c234ba59f6 --- /dev/null +++ b/queue-6.18/alsa-usb-audio-exclude-scarlett-2i2-1st-gen-from-ski.patch @@ -0,0 +1,45 @@ +From e5cdedec3d572ff8bde318b6f83d098c7a7615ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://patch.msgid.link/abmsTjKmQMKbhYtK@m.b4.vu +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/alsa-usb-audio-exclude-scarlett-2i4-1st-gen-from-ski.patch b/queue-6.18/alsa-usb-audio-exclude-scarlett-2i4-1st-gen-from-ski.patch new file mode 100644 index 0000000000..c058c4be94 --- /dev/null +++ b/queue-6.18/alsa-usb-audio-exclude-scarlett-2i4-1st-gen-from-ski.patch @@ -0,0 +1,38 @@ +From 0831b12a1f08e5728a30e4ff060f268bb4685704 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://patch.msgid.link/acEkEbftzyNe8W7C@m.b4.vu +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch b/queue-6.18/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch new file mode 100644 index 0000000000..5348964d90 --- /dev/null +++ b/queue-6.18/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch @@ -0,0 +1,80 @@ +From 86d1b03615aeb767e1b94ceaaee894f0d612ff11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch b/queue-6.18/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch new file mode 100644 index 0000000000..eadc10e15c --- /dev/null +++ b/queue-6.18/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch @@ -0,0 +1,82 @@ +From 264939d4b099d0a0a5a00c3a5586b8af5b5f196d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/asoc-dt-bindings-stm32-fix-incorrect-compatible-stri.patch b/queue-6.18/asoc-dt-bindings-stm32-fix-incorrect-compatible-stri.patch new file mode 100644 index 0000000000..1dc87be76c --- /dev/null +++ b/queue-6.18/asoc-dt-bindings-stm32-fix-incorrect-compatible-stri.patch @@ -0,0 +1,41 @@ +From 8544864e447157ddfb8ae126c6fb4f9e05ee81d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Olivier Moysan +Link: https://patch.msgid.link/20260321012011.125791-1-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/asoc-fsl-imx-card-initialize-playback_only-and-captu.patch b/queue-6.18/asoc-fsl-imx-card-initialize-playback_only-and-captu.patch new file mode 100644 index 0000000000..bcf737f8b3 --- /dev/null +++ b/queue-6.18/asoc-fsl-imx-card-initialize-playback_only-and-captu.patch @@ -0,0 +1,39 @@ +From e5aa579b700d2ee556890e1b5f3952bfd8171d64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 18:28:50 +0800 +Subject: ASoC: fsl: imx-card: initialize playback_only and capture_only + +From: Shengjiu Wang + +[ 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 +Acked-by: Kuninori Morimoto +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260318102850.2794029-3-shengjiu.wang@nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/asoc-intel-catpt-fix-the-device-initialization.patch b/queue-6.18/asoc-intel-catpt-fix-the-device-initialization.patch new file mode 100644 index 0000000000..fac3daab84 --- /dev/null +++ b/queue-6.18/asoc-intel-catpt-fix-the-device-initialization.patch @@ -0,0 +1,63 @@ +From a6056f41d5b1a060a7c4f35445ba690c5d7f8eb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 11:12:17 +0100 +Subject: ASoC: Intel: catpt: Fix the device initialization + +From: Cezary Rojewski + +[ 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 +Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle") +Signed-off-by: Cezary Rojewski +Reviewed-by: Andy Shevchenko +Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch b/queue-6.18/drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch new file mode 100644 index 0000000000..e440cb7944 --- /dev/null +++ b/queue-6.18/drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch @@ -0,0 +1,121 @@ +From 5eec14bcaf89cec7a2377d3dacd603da6eb57881 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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 +Reviewed-by: Harry Wentland +Signed-off-by: Alex Deucher +(cherry picked from commit cc7c7121ae082b7b82891baa7280f1ff2608f22b) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch b/queue-6.18/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch new file mode 100644 index 0000000000..a2c5573c38 --- /dev/null +++ b/queue-6.18/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch @@ -0,0 +1,62 @@ +From 72a760ee7f86e5815039a4e01d3e2846f1e9caef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Dan Carpenter +Cc: Christian König +Cc: Alex Deucher +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch b/queue-6.18/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch new file mode 100644 index 0000000000..3f625c7931 --- /dev/null +++ b/queue-6.18/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch @@ -0,0 +1,46 @@ +From b7b0ae2c0a291251ac4dcbc711b021b77bb6ec0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jani Nikula +Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com +Signed-off-by: Jani Nikula +(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/drm-mediatek-dsi-store-driver-data-before-invoking-m.patch b/queue-6.18/drm-mediatek-dsi-store-driver-data-before-invoking-m.patch new file mode 100644 index 0000000000..560437cef2 --- /dev/null +++ b/queue-6.18/drm-mediatek-dsi-store-driver-data-before-invoking-m.patch @@ -0,0 +1,118 @@ +From e8a868e3514627052a27b89517f1b8974d40ba68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/dri-devel/patch/20260225094047.76780-1-l.scorcia@gmail.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/drm-xe-implement-recent-spec-updates-to-wa_160252501.patch b/queue-6.18/drm-xe-implement-recent-spec-updates-to-wa_160252501.patch new file mode 100644 index 0000000000..8622bead7d --- /dev/null +++ b/queue-6.18/drm-xe-implement-recent-spec-updates-to-wa_160252501.patch @@ -0,0 +1,56 @@ +From a88e66f260dc5bc6ed1c7e0b5f0feeb9f66571bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 15:30:34 -0700 +Subject: drm/xe: Implement recent spec updates to Wa_16025250150 + +From: Matt Roper + +[ 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 +Link: https://patch.msgid.link/20260319-wa_16025250150_part2-v1-1-46b1de1a31b2@intel.com +Signed-off-by: Matt Roper +(cherry picked from commit a31566762d4075646a8a2214586158b681e94305) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch b/queue-6.18/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch new file mode 100644 index 0000000000..32c0b11e45 --- /dev/null +++ b/queue-6.18/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch @@ -0,0 +1,187 @@ +From ff380acafc889dcbe26bbb6632280488d48c214a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Nuno Sá +Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include + #include + #include + +@@ -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 + diff --git a/queue-6.18/hwmon-pmbus-core-protect-regulator-operations-with-m.patch b/queue-6.18/hwmon-pmbus-core-protect-regulator-operations-with-m.patch new file mode 100644 index 0000000000..336eba00d9 --- /dev/null +++ b/queue-6.18/hwmon-pmbus-core-protect-regulator-operations-with-m.patch @@ -0,0 +1,256 @@ +From 504639740691b331b9a59681fb4a43d71cb89e35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 Mar 2026 09:12:33 -0700 +Subject: hwmon: (pmbus/core) Protect regulator operations with mutex + +From: Guenter Roeck + +[ 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 +Fixes: ddbb4db4ced1b ("hwmon: (pmbus) Add regulator support") +Reviewed-by: Sanman Pradhan +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + #include + #include + #include +@@ -21,8 +22,8 @@ + #include + #include + #include +-#include + #include ++#include + #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 + diff --git a/queue-6.18/hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch b/queue-6.18/hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch new file mode 100644 index 0000000000..5649ac1a8e --- /dev/null +++ b/queue-6.18/hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch @@ -0,0 +1,186 @@ +From ab0cf54573ff62342775cc5318cae91a32cfc1ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 18:54:11 -0700 +Subject: hwmon: (pmbus) Introduce the concept of "write-only" attributes + +From: Guenter Roeck + +[ 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 +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch b/queue-6.18/hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch new file mode 100644 index 0000000000..f105562392 --- /dev/null +++ b/queue-6.18/hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch @@ -0,0 +1,280 @@ +From 1cfadeb2a9a46ff1e97ec25c03c66d5ef980eddc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 16:41:07 -0700 +Subject: hwmon: (pmbus) Mark lowest/average/highest/rated attributes as + read-only + +From: Guenter Roeck + +[ 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 +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch b/queue-6.18/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch new file mode 100644 index 0000000000..fcc70000ec --- /dev/null +++ b/queue-6.18/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch @@ -0,0 +1,64 @@ +From a4af67c3972a6e62e81d6a6fa24b3cfe0e06aebb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Mar 2026 18:39:41 +0100 +Subject: PM: hibernate: Drain trailing zero pages on userspace restore + +From: Alberto Garcia + +[ 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 +Acked-by: Brian Geffon +Link: https://patch.msgid.link/ef5a7c5e3e3dbd17dcb20efaa0c53a47a23498bb.1773075892.git.berto@igalia.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/pm-sleep-drop-spurious-warn_on-from-pm_restore_gfp_m.patch b/queue-6.18/pm-sleep-drop-spurious-warn_on-from-pm_restore_gfp_m.patch new file mode 100644 index 0000000000..361c0a4e23 --- /dev/null +++ b/queue-6.18/pm-sleep-drop-spurious-warn_on-from-pm_restore_gfp_m.patch @@ -0,0 +1,50 @@ +From 3e9c79774ef393357c71da628220b3f6c8e908f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 Mar 2026 21:05:28 +0900 +Subject: PM: sleep: Drop spurious WARN_ON() from pm_restore_gfp_mask() + +From: Youngjun Park + +[ 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 +[ rjw: Subject tweak ] +Link: https://patch.msgid.link/20260322120528.750178-1-youngjun.park@lge.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-efa-check-stored-completion-ctx-command-id-with.patch b/queue-6.18/rdma-efa-check-stored-completion-ctx-command-id-with.patch new file mode 100644 index 0000000000..0a22194337 --- /dev/null +++ b/queue-6.18/rdma-efa-check-stored-completion-ctx-command-id-with.patch @@ -0,0 +1,62 @@ +From 2c753458df99cdca6362a962cd73e0525bb8bd49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Dec 2025 13:06:13 +0000 +Subject: RDMA/efa: Check stored completion CTX command ID with received one + +From: Yonatan Nachum + +[ 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 +Reviewed-by: Michael Margolin +Signed-off-by: Yonatan Nachum +Link: https://patch.msgid.link/20251210130614.36460-2-ynachum@amazon.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: ef3b06742c8a ("RDMA/efa: Fix use of completion ctx after free") +Signed-off-by: Sasha Levin +--- + 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 ++ + #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 + diff --git a/queue-6.18/rdma-efa-fix-possible-deadlock.patch b/queue-6.18/rdma-efa-fix-possible-deadlock.patch new file mode 100644 index 0000000000..c48f713722 --- /dev/null +++ b/queue-6.18/rdma-efa-fix-possible-deadlock.patch @@ -0,0 +1,42 @@ +From fbd82c2cb1ef010c5824c22b7fa493a8429cbbae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 23:57:30 -0500 +Subject: RDMA/efa: Fix possible deadlock + +From: Ethan Tidmore + +[ 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 +Link: https://patch.msgid.link/20260314045730.1143862-1-ethantidmore06@gmail.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-efa-fix-use-of-completion-ctx-after-free.patch b/queue-6.18/rdma-efa-fix-use-of-completion-ctx-after-free.patch new file mode 100644 index 0000000000..c404104935 --- /dev/null +++ b/queue-6.18/rdma-efa-fix-use-of-completion-ctx-after-free.patch @@ -0,0 +1,223 @@ +From 07e86b997b20b88a43fb01876af251e0fb376a30 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 8 Mar 2026 16:53:50 +0000 +Subject: RDMA/efa: Fix use of completion ctx after free + +From: Yonatan Nachum + +[ 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 +Reviewed-by: Michael Margolin +Signed-off-by: Yonatan Nachum +Link: https://patch.msgid.link/20260308165350.18219-1-ynachum@amazon.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 +@@ -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 + diff --git a/queue-6.18/rdma-efa-improve-admin-completion-context-state-mach.patch b/queue-6.18/rdma-efa-improve-admin-completion-context-state-mach.patch new file mode 100644 index 0000000000..2c33cfdc11 --- /dev/null +++ b/queue-6.18/rdma-efa-improve-admin-completion-context-state-mach.patch @@ -0,0 +1,205 @@ +From 4809ce3425c0c6e53ff45b199e37f091c882ad01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Dec 2025 13:06:14 +0000 +Subject: RDMA/efa: Improve admin completion context state machine + +From: Yonatan Nachum + +[ 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 +Reviewed-by: Michael Margolin +Signed-off-by: Yonatan Nachum +Link: https://patch.msgid.link/20251210130614.36460-3-ynachum@amazon.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: ef3b06742c8a ("RDMA/efa: Fix use of completion ctx after free") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch b/queue-6.18/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch new file mode 100644 index 0000000000..a873d6daaf --- /dev/null +++ b/queue-6.18/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch @@ -0,0 +1,64 @@ +From 9fcd1fb284209e26a6c8029d64e18a3b085a15ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:43 -0500 +Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node + +From: Ivan Barrera + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch b/queue-6.18/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch new file mode 100644 index 0000000000..c4071a13bc --- /dev/null +++ b/queue-6.18/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch @@ -0,0 +1,44 @@ +From 4a85329f11f875a51d58e14876d72d6bbe124b95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:45 -0500 +Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections + +From: Anil Samal + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-irdma-harden-depth-calculation-functions.patch b/queue-6.18/rdma-irdma-harden-depth-calculation-functions.patch new file mode 100644 index 0000000000..1e90a72fac --- /dev/null +++ b/queue-6.18/rdma-irdma-harden-depth-calculation-functions.patch @@ -0,0 +1,108 @@ +From a6411322cb7cc91593871fd50b6d5ee8c34c4c59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:47 -0500 +Subject: RDMA/irdma: Harden depth calculation functions + +From: Shiraz Saleem + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-irdma-initialize-free_qp-completion-before-usin.patch b/queue-6.18/rdma-irdma-initialize-free_qp-completion-before-usin.patch new file mode 100644 index 0000000000..88771bbb78 --- /dev/null +++ b/queue-6.18/rdma-irdma-initialize-free_qp-completion-before-usin.patch @@ -0,0 +1,46 @@ +From 7791bee3e3433a01233adb3500501e780492863c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:38 -0500 +Subject: RDMA/irdma: Initialize free_qp completion before using it + +From: Jacob Moroni + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch b/queue-6.18/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch new file mode 100644 index 0000000000..441dd9befb --- /dev/null +++ b/queue-6.18/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch @@ -0,0 +1,38 @@ +From b83956e96e58f15b3f6a8b7ba8052360e2edfb8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch b/queue-6.18/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch new file mode 100644 index 0000000000..6c21476d2c --- /dev/null +++ b/queue-6.18/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch @@ -0,0 +1,38 @@ +From bffcf159ae4c74fe350cdecae593602f32d9df78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:44 -0500 +Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err() + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-irdma-return-einval-for-invalid-arp-index-error.patch b/queue-6.18/rdma-irdma-return-einval-for-invalid-arp-index-error.patch new file mode 100644 index 0000000000..f7b33bfe99 --- /dev/null +++ b/queue-6.18/rdma-irdma-return-einval-for-invalid-arp-index-error.patch @@ -0,0 +1,86 @@ +From 33d0ea8a32f49318d2b5fbed6887f2baf4e0a8b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:46 -0500 +Subject: RDMA/irdma: Return EINVAL for invalid arp index error + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch b/queue-6.18/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch new file mode 100644 index 0000000000..539369a1c2 --- /dev/null +++ b/queue-6.18/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch @@ -0,0 +1,45 @@ +From eb76e4f767694bd70301af528e53eb701f270314 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch b/queue-6.18/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch new file mode 100644 index 0000000000..bda3456d45 --- /dev/null +++ b/queue-6.18/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch @@ -0,0 +1,87 @@ +From 38a99e6adb13fd595ab7df14aa769a49595adf57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 15:41:58 -0400 +Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion + +From: Chuck Lever + +[ 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 +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/regmap-synchronize-cache-for-the-page-selector.patch b/queue-6.18/regmap-synchronize-cache-for-the-page-selector.patch new file mode 100644 index 0000000000..b419cd0a46 --- /dev/null +++ b/queue-6.18/regmap-synchronize-cache-for-the-page-selector.patch @@ -0,0 +1,112 @@ +From 434de1fc8025634c8f07e924f02efc9c38b383a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Mar 2026 19:43:31 +0100 +Subject: regmap: Synchronize cache for the page selector + +From: Andy Shevchenko + +[ 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 +Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com +Tested-by: Marek Szyprowski +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/rust-regulator-do-not-assume-that-regulator_get-retu.patch b/queue-6.18/rust-regulator-do-not-assume-that-regulator_get-retu.patch new file mode 100644 index 0000000000..95f6791c13 --- /dev/null +++ b/queue-6.18/rust-regulator-do-not-assume-that-regulator_get-retu.patch @@ -0,0 +1,141 @@ +From c648df1acf48a1c06e9b444803ae6826c9bbbed6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 10:49:59 +0000 +Subject: rust: regulator: do not assume that regulator_get() returns non-null + +From: Alice Ryhl + +[ 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 +Closes: https://lore.kernel.org/r/20260322193830.89324-1-ojeda@kernel.org +Signed-off-by: Alice Ryhl +Reviewed-by: Daniel Almeida +Link: https://patch.msgid.link/20260324-regulator-fix-v1-1-a5244afa3c15@google.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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, 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 + where + State: RegulatorState, + { +- inner: NonNull, ++ inner: *mut bindings::regulator, + _phantom: PhantomData, + } + +@@ -250,7 +255,7 @@ impl Regulator { + // 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 Regulator { + /// Gets the current voltage of the regulator. + pub fn get_voltage(&self) -> Result { + // 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 Regulator { + // 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 Regulator { + + 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 Regulator { + /// 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 Drop for Regulator { + // 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 + diff --git a/queue-6.18/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch b/queue-6.18/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch new file mode 100644 index 0000000000..9e3b9f5499 --- /dev/null +++ b/queue-6.18/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch @@ -0,0 +1,44 @@ +From 9dc42b707dacf13f1a30da16ec23012723914743 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 14:31:47 +0800 +Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue + +From: Yihang Li + +[ 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 +Reviewed-by: John Garry +Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/series b/queue-6.18/series index 2fd48fd242..4eef47c2dd 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -130,3 +130,45 @@ netfilter-nf_conntrack_expect-skip-expectations-in-o.patch 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 diff --git a/queue-6.18/spi-meson-spicc-fix-double-put-in-remove-path.patch b/queue-6.18/spi-meson-spicc-fix-double-put-in-remove-path.patch new file mode 100644 index 0000000000..18a0065495 --- /dev/null +++ b/queue-6.18/spi-meson-spicc-fix-double-put-in-remove-path.patch @@ -0,0 +1,42 @@ +From 7ad4a51ddfd09fb153afff7dedde1c5bc9b6b374 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 Mar 2026 21:29:56 +0800 +Subject: spi: meson-spicc: Fix double-put in remove path + +From: Felix Gu + +[ 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 +Reviewed-by: Johan Hovold +Link: https://patch.msgid.link/20260322-rockchip-v1-1-fac3f0c6dad8@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch b/queue-6.18/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch new file mode 100644 index 0000000000..6110873d92 --- /dev/null +++ b/queue-6.18/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch @@ -0,0 +1,72 @@ +From cf898b4456788e78bdc8d1cb6a6d2e943d0cadfd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 00:12:34 +0800 +Subject: spi: sn-f-ospi: Fix resource leak in f_ospi_probe() + +From: Felix Gu + +[ 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 +Link: https://patch.msgid.link/20260319-sn-f-v1-1-33a6738d2da8@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch b/queue-6.18/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch new file mode 100644 index 0000000000..b010043594 --- /dev/null +++ b/queue-6.18/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch @@ -0,0 +1,69 @@ +From 25c293a7f9d068d8981226950de030899241803b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 19:38:12 +0100 +Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF) + +From: Marc Kleine-Budde + +[ 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 +Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/spi-use-generic-driver_override-infrastructure.patch b/queue-6.18/spi-use-generic-driver_override-infrastructure.patch new file mode 100644 index 0000000000..7c23ee0a6b --- /dev/null +++ b/queue-6.18/spi-use-generic-driver_override-infrastructure.patch @@ -0,0 +1,118 @@ +From a536c73898d2fb2cdeeb2af83db75af3b69d6de9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 01:59:15 +0100 +Subject: spi: use generic driver_override infrastructure + +From: Danilo Krummrich + +[ 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 +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789 +Fixes: 5039563e7c25 ("spi: Add driver_override SPI device attribute") +Signed-off-by: Danilo Krummrich +Link: https://patch.msgid.link/20260324005919.2408620-12-dakr@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch b/queue-6.18/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch new file mode 100644 index 0000000000..6d9ece297b --- /dev/null +++ b/queue-6.18/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch @@ -0,0 +1,47 @@ +From a4ebda3c7616231b3bc396ae62fb4ff21e7eb200 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 23:29:50 +0100 +Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap + +From: Marc Buerg + +[ 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 +Reviewed-by: Joel Granados +Signed-off-by: Joel Granados +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.18/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch b/queue-6.18/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch new file mode 100644 index 0000000000..4f8dd26070 --- /dev/null +++ b/queue-6.18/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch @@ -0,0 +1,42 @@ +From 6cf7d315ace71bb2a7a8d0d99c86504fa54ce315 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory") +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch b/queue-6.19/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch new file mode 100644 index 0000000000..4b483cd435 --- /dev/null +++ b/queue-6.19/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch @@ -0,0 +1,83 @@ +From 94b23ea098caf029cedc4f2a7c0e4e56aa7398fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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) + + + 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 +Signed-off-by: Weiming Shi +Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch b/queue-6.19/alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch new file mode 100644 index 0000000000..94bf2ddb3b --- /dev/null +++ b/queue-6.19/alsa-hda-realtek-sequence-gpio2-on-star-labs-starfig.patch @@ -0,0 +1,94 @@ +From 994bb193d19046fa067fb87e218c4eb1b5fbbd32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 20:11:27 +0000 +Subject: ALSA: hda/realtek: Sequence GPIO2 on Star Labs StarFighter + +From: Sean Rhodes + +[ 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 +Signed-off-by: Sean Rhodes +Link: https://patch.msgid.link/20260315201127.33744-1-sean@starlabs.systems +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/alsa-usb-audio-exclude-scarlett-2i2-1st-gen-from-ski.patch b/queue-6.19/alsa-usb-audio-exclude-scarlett-2i2-1st-gen-from-ski.patch new file mode 100644 index 0000000000..b7cfd58633 --- /dev/null +++ b/queue-6.19/alsa-usb-audio-exclude-scarlett-2i2-1st-gen-from-ski.patch @@ -0,0 +1,45 @@ +From ed06a1487879e6651697140a9c07a882c5e57092 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://patch.msgid.link/abmsTjKmQMKbhYtK@m.b4.vu +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/alsa-usb-audio-exclude-scarlett-2i4-1st-gen-from-ski.patch b/queue-6.19/alsa-usb-audio-exclude-scarlett-2i4-1st-gen-from-ski.patch new file mode 100644 index 0000000000..a151d23bf6 --- /dev/null +++ b/queue-6.19/alsa-usb-audio-exclude-scarlett-2i4-1st-gen-from-ski.patch @@ -0,0 +1,38 @@ +From 6ab6ea309c71de56e5bf49c0e1a7dcf8b8f953b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://patch.msgid.link/acEkEbftzyNe8W7C@m.b4.vu +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch b/queue-6.19/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch new file mode 100644 index 0000000000..956701af17 --- /dev/null +++ b/queue-6.19/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch @@ -0,0 +1,80 @@ +From 4386ef16c04ea6ef9dd50339a4fa762307fa3507 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch b/queue-6.19/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch new file mode 100644 index 0000000000..e10ef5e53d --- /dev/null +++ b/queue-6.19/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch @@ -0,0 +1,82 @@ +From 448049771744d9d7339a28aca03de7ad69229196 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/asoc-dt-bindings-stm32-fix-incorrect-compatible-stri.patch b/queue-6.19/asoc-dt-bindings-stm32-fix-incorrect-compatible-stri.patch new file mode 100644 index 0000000000..0b3e950d5e --- /dev/null +++ b/queue-6.19/asoc-dt-bindings-stm32-fix-incorrect-compatible-stri.patch @@ -0,0 +1,41 @@ +From 8eba73b6630134e1d9abbd33679ce624ecfce0b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Olivier Moysan +Link: https://patch.msgid.link/20260321012011.125791-1-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/asoc-fsl-imx-card-initialize-playback_only-and-captu.patch b/queue-6.19/asoc-fsl-imx-card-initialize-playback_only-and-captu.patch new file mode 100644 index 0000000000..2e9e5674ba --- /dev/null +++ b/queue-6.19/asoc-fsl-imx-card-initialize-playback_only-and-captu.patch @@ -0,0 +1,39 @@ +From 80c6917e379b7b2306d469993f4e0d245d7ed3ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 18:28:50 +0800 +Subject: ASoC: fsl: imx-card: initialize playback_only and capture_only + +From: Shengjiu Wang + +[ 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 +Acked-by: Kuninori Morimoto +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260318102850.2794029-3-shengjiu.wang@nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/asoc-intel-catpt-fix-the-device-initialization.patch b/queue-6.19/asoc-intel-catpt-fix-the-device-initialization.patch new file mode 100644 index 0000000000..be77d5a3c8 --- /dev/null +++ b/queue-6.19/asoc-intel-catpt-fix-the-device-initialization.patch @@ -0,0 +1,63 @@ +From 4ac44e0152210a8e44e3602915530ade74469832 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 11:12:17 +0100 +Subject: ASoC: Intel: catpt: Fix the device initialization + +From: Cezary Rojewski + +[ 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 +Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle") +Signed-off-by: Cezary Rojewski +Reviewed-by: Andy Shevchenko +Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/asoc-sdca-fix-finding-wrong-entity.patch b/queue-6.19/asoc-sdca-fix-finding-wrong-entity.patch new file mode 100644 index 0000000000..718a9b478d --- /dev/null +++ b/queue-6.19/asoc-sdca-fix-finding-wrong-entity.patch @@ -0,0 +1,52 @@ +From e7731b2445a3b3a46f9ddd7cbafc2fbee671e182 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 19:04:06 +0800 +Subject: ASoC: SDCA: fix finding wrong entity + +From: Shuming Fan + +[ 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 +Signed-off-by: Shuming Fan +Link: https://patch.msgid.link/20260325110406.3232420-1-shumingf@realtek.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/asoc-simple-card-utils-check-value-of-is_playback_on.patch b/queue-6.19/asoc-simple-card-utils-check-value-of-is_playback_on.patch new file mode 100644 index 0000000000..00641116d2 --- /dev/null +++ b/queue-6.19/asoc-simple-card-utils-check-value-of-is_playback_on.patch @@ -0,0 +1,60 @@ +From a134ab50a7f0c8f3d29842e0668fceba6dbd74ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Kuninori Morimoto +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260318102850.2794029-2-shengjiu.wang@nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch b/queue-6.19/drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch new file mode 100644 index 0000000000..7d6fe4ebb8 --- /dev/null +++ b/queue-6.19/drm-amd-display-do-not-skip-unrelated-mode-changes-i.patch @@ -0,0 +1,121 @@ +From 0f3be3c4ccf8e194bb47e0aeaedc3730cbf82557 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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 +Reviewed-by: Harry Wentland +Signed-off-by: Alex Deucher +(cherry picked from commit cc7c7121ae082b7b82891baa7280f1ff2608f22b) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch b/queue-6.19/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch new file mode 100644 index 0000000000..11d5f2e54f --- /dev/null +++ b/queue-6.19/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch @@ -0,0 +1,62 @@ +From fadd160c4a89a13f77edbe5e609149700e44b928 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Dan Carpenter +Cc: Christian König +Cc: Alex Deucher +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch b/queue-6.19/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch new file mode 100644 index 0000000000..9dc0cc8932 --- /dev/null +++ b/queue-6.19/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch @@ -0,0 +1,46 @@ +From b862900999021e5bdb6bd086fd8d5c61c830c2bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jani Nikula +Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com +Signed-off-by: Jani Nikula +(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/drm-mediatek-dsi-store-driver-data-before-invoking-m.patch b/queue-6.19/drm-mediatek-dsi-store-driver-data-before-invoking-m.patch new file mode 100644 index 0000000000..f1afeb2f0e --- /dev/null +++ b/queue-6.19/drm-mediatek-dsi-store-driver-data-before-invoking-m.patch @@ -0,0 +1,118 @@ +From ed9ee19d9d7c20b05aa3c1aed152dabf11cc6331 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/dri-devel/patch/20260225094047.76780-1-l.scorcia@gmail.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/drm-xe-implement-recent-spec-updates-to-wa_160252501.patch b/queue-6.19/drm-xe-implement-recent-spec-updates-to-wa_160252501.patch new file mode 100644 index 0000000000..fd2fee0f37 --- /dev/null +++ b/queue-6.19/drm-xe-implement-recent-spec-updates-to-wa_160252501.patch @@ -0,0 +1,56 @@ +From 44c736fe843dbba9254ca1bc94c6f0ec3631173d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 15:30:34 -0700 +Subject: drm/xe: Implement recent spec updates to Wa_16025250150 + +From: Matt Roper + +[ 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 +Link: https://patch.msgid.link/20260319-wa_16025250150_part2-v1-1-46b1de1a31b2@intel.com +Signed-off-by: Matt Roper +(cherry picked from commit a31566762d4075646a8a2214586158b681e94305) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/drm-xe-pf-fix-use-after-free-in-migration-restore.patch b/queue-6.19/drm-xe-pf-fix-use-after-free-in-migration-restore.patch new file mode 100644 index 0000000000..81f19fb30a --- /dev/null +++ b/queue-6.19/drm-xe-pf-fix-use-after-free-in-migration-restore.patch @@ -0,0 +1,46 @@ +From 1fe314c158487d5a856771e5d8f9e87f13313831 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/7230 +Reviewed-by: Shuicheng Lin +Link: https://patch.msgid.link/20260217154118.176902-1-michal.winiarski@intel.com +Signed-off-by: Michał Winiarski +(cherry picked from commit 4f53d8c6d23527d734fe3531d08e15cb170a0819) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch b/queue-6.19/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch new file mode 100644 index 0000000000..e0aa3937c0 --- /dev/null +++ b/queue-6.19/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch @@ -0,0 +1,187 @@ +From f05146f9998d4d7d400463a3d4855d9fc777ddde Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Nuno Sá +Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include + #include + #include + +@@ -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 + diff --git a/queue-6.19/hwmon-pmbus-core-protect-regulator-operations-with-m.patch b/queue-6.19/hwmon-pmbus-core-protect-regulator-operations-with-m.patch new file mode 100644 index 0000000000..d9df5b4a7b --- /dev/null +++ b/queue-6.19/hwmon-pmbus-core-protect-regulator-operations-with-m.patch @@ -0,0 +1,256 @@ +From 4bcfd0475037eee1a23bb7a05ef0dd77650204c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 Mar 2026 09:12:33 -0700 +Subject: hwmon: (pmbus/core) Protect regulator operations with mutex + +From: Guenter Roeck + +[ 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 +Fixes: ddbb4db4ced1b ("hwmon: (pmbus) Add regulator support") +Reviewed-by: Sanman Pradhan +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + #include + #include + #include +@@ -21,8 +22,8 @@ + #include + #include + #include +-#include + #include ++#include + #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 + diff --git a/queue-6.19/hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch b/queue-6.19/hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch new file mode 100644 index 0000000000..a8f558f9ff --- /dev/null +++ b/queue-6.19/hwmon-pmbus-introduce-the-concept-of-write-only-attr.patch @@ -0,0 +1,186 @@ +From 1703afe42e6f46eaf62b66269aabd34fd69ab140 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 18:54:11 -0700 +Subject: hwmon: (pmbus) Introduce the concept of "write-only" attributes + +From: Guenter Roeck + +[ 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 +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch b/queue-6.19/hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch new file mode 100644 index 0000000000..2844c1dd4a --- /dev/null +++ b/queue-6.19/hwmon-pmbus-mark-lowest-average-highest-rated-attrib.patch @@ -0,0 +1,280 @@ +From 0f53d77ee5ebf856c0ad62ef24fa40b33b10cf81 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 16:41:07 -0700 +Subject: hwmon: (pmbus) Mark lowest/average/highest/rated attributes as + read-only + +From: Guenter Roeck + +[ 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 +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/io_uring-fdinfo-fix-oob-read-in-sqe_mixed-wrap-check.patch b/queue-6.19/io_uring-fdinfo-fix-oob-read-in-sqe_mixed-wrap-check.patch new file mode 100644 index 0000000000..f316403e84 --- /dev/null +++ b/queue-6.19/io_uring-fdinfo-fix-oob-read-in-sqe_mixed-wrap-check.patch @@ -0,0 +1,51 @@ +From 1b1c50015d2683a97824ecad77afa421fef8e65b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Mar 2026 02:18:23 +0000 +Subject: io_uring/fdinfo: fix OOB read in SQE_MIXED wrap check + +From: Nicholas Carlini + +[ 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 +Link: https://patch.msgid.link/20260327021823.3138396-1-nicholas@carlini.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/io_uring-fdinfo-fix-sqe_mixed-sqe-displaying.patch b/queue-6.19/io_uring-fdinfo-fix-sqe_mixed-sqe-displaying.patch new file mode 100644 index 0000000000..843f7df5b2 --- /dev/null +++ b/queue-6.19/io_uring-fdinfo-fix-sqe_mixed-sqe-displaying.patch @@ -0,0 +1,40 @@ +From 9c1db8e9e5d1f6b9c3315e1fcfca90f001ca5ead Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 26 Mar 2026 07:02:53 -0600 +Subject: io_uring/fdinfo: fix SQE_MIXED SQE displaying + +From: Jens Axboe + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch b/queue-6.19/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch new file mode 100644 index 0000000000..537701eea6 --- /dev/null +++ b/queue-6.19/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch @@ -0,0 +1,64 @@ +From 98c1740bf1f13bd0c6b8fc5592f463249a07605e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Mar 2026 18:39:41 +0100 +Subject: PM: hibernate: Drain trailing zero pages on userspace restore + +From: Alberto Garcia + +[ 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 +Acked-by: Brian Geffon +Link: https://patch.msgid.link/ef5a7c5e3e3dbd17dcb20efaa0c53a47a23498bb.1773075892.git.berto@igalia.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/pm-sleep-drop-spurious-warn_on-from-pm_restore_gfp_m.patch b/queue-6.19/pm-sleep-drop-spurious-warn_on-from-pm_restore_gfp_m.patch new file mode 100644 index 0000000000..cf6f813f13 --- /dev/null +++ b/queue-6.19/pm-sleep-drop-spurious-warn_on-from-pm_restore_gfp_m.patch @@ -0,0 +1,50 @@ +From adeb9b6c75d090ad5bc4ba16e589e6e1a8393d79 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 Mar 2026 21:05:28 +0900 +Subject: PM: sleep: Drop spurious WARN_ON() from pm_restore_gfp_mask() + +From: Youngjun Park + +[ 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 +[ rjw: Subject tweak ] +Link: https://patch.msgid.link/20260322120528.750178-1-youngjun.park@lge.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-bng_re-fix-silent-failure-in-hwrm-version-query.patch b/queue-6.19/rdma-bng_re-fix-silent-failure-in-hwrm-version-query.patch new file mode 100644 index 0000000000..aca986a959 --- /dev/null +++ b/queue-6.19/rdma-bng_re-fix-silent-failure-in-hwrm-version-query.patch @@ -0,0 +1,87 @@ +From 23c3842e7112c12f086745efa9fdf59cac1042f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Mar 2026 23:36:45 -0500 +Subject: RDMA/bng_re: Fix silent failure in HWRM version query + +From: Kamal Heib + +[ 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 +Link: https://patch.msgid.link/20260303043645.425724-1-kheib@redhat.com +Reviewed-by: Siva Reddy Kallam +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-efa-check-stored-completion-ctx-command-id-with.patch b/queue-6.19/rdma-efa-check-stored-completion-ctx-command-id-with.patch new file mode 100644 index 0000000000..c3db41c68a --- /dev/null +++ b/queue-6.19/rdma-efa-check-stored-completion-ctx-command-id-with.patch @@ -0,0 +1,62 @@ +From 4dcb91da660e118a3ea75085a3495f835fce0dfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Dec 2025 13:06:13 +0000 +Subject: RDMA/efa: Check stored completion CTX command ID with received one + +From: Yonatan Nachum + +[ 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 +Reviewed-by: Michael Margolin +Signed-off-by: Yonatan Nachum +Link: https://patch.msgid.link/20251210130614.36460-2-ynachum@amazon.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: ef3b06742c8a ("RDMA/efa: Fix use of completion ctx after free") +Signed-off-by: Sasha Levin +--- + 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 ++ + #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 + diff --git a/queue-6.19/rdma-efa-fix-possible-deadlock.patch b/queue-6.19/rdma-efa-fix-possible-deadlock.patch new file mode 100644 index 0000000000..a8c4a6b52a --- /dev/null +++ b/queue-6.19/rdma-efa-fix-possible-deadlock.patch @@ -0,0 +1,42 @@ +From 508dfcebd213f9e303ad79175ece6715e65a410e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 23:57:30 -0500 +Subject: RDMA/efa: Fix possible deadlock + +From: Ethan Tidmore + +[ 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 +Link: https://patch.msgid.link/20260314045730.1143862-1-ethantidmore06@gmail.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-efa-fix-use-of-completion-ctx-after-free.patch b/queue-6.19/rdma-efa-fix-use-of-completion-ctx-after-free.patch new file mode 100644 index 0000000000..96d8c6b73b --- /dev/null +++ b/queue-6.19/rdma-efa-fix-use-of-completion-ctx-after-free.patch @@ -0,0 +1,223 @@ +From b7081d965990257cf77d740a767274b50fded440 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 8 Mar 2026 16:53:50 +0000 +Subject: RDMA/efa: Fix use of completion ctx after free + +From: Yonatan Nachum + +[ 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 +Reviewed-by: Michael Margolin +Signed-off-by: Yonatan Nachum +Link: https://patch.msgid.link/20260308165350.18219-1-ynachum@amazon.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 +@@ -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 + diff --git a/queue-6.19/rdma-efa-improve-admin-completion-context-state-mach.patch b/queue-6.19/rdma-efa-improve-admin-completion-context-state-mach.patch new file mode 100644 index 0000000000..b05b6dc26a --- /dev/null +++ b/queue-6.19/rdma-efa-improve-admin-completion-context-state-mach.patch @@ -0,0 +1,205 @@ +From e12956e5377d59a5f6bd27e436a8e3580427e0a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Dec 2025 13:06:14 +0000 +Subject: RDMA/efa: Improve admin completion context state machine + +From: Yonatan Nachum + +[ 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 +Reviewed-by: Michael Margolin +Signed-off-by: Yonatan Nachum +Link: https://patch.msgid.link/20251210130614.36460-3-ynachum@amazon.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: ef3b06742c8a ("RDMA/efa: Fix use of completion ctx after free") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch b/queue-6.19/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch new file mode 100644 index 0000000000..6718f376ae --- /dev/null +++ b/queue-6.19/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch @@ -0,0 +1,64 @@ +From 8a5b22010ef99beac37bb20f305d9ed157ce5693 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:43 -0500 +Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node + +From: Ivan Barrera + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch b/queue-6.19/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch new file mode 100644 index 0000000000..0de9c6cbda --- /dev/null +++ b/queue-6.19/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch @@ -0,0 +1,44 @@ +From d372db3290fe5044c708df2dd7ea2545c1d632ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:45 -0500 +Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections + +From: Anil Samal + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-irdma-harden-depth-calculation-functions.patch b/queue-6.19/rdma-irdma-harden-depth-calculation-functions.patch new file mode 100644 index 0000000000..37cf5fa5a5 --- /dev/null +++ b/queue-6.19/rdma-irdma-harden-depth-calculation-functions.patch @@ -0,0 +1,108 @@ +From c0a7b402956772256553cc5d99e505ad457d3d8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:47 -0500 +Subject: RDMA/irdma: Harden depth calculation functions + +From: Shiraz Saleem + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-irdma-initialize-free_qp-completion-before-usin.patch b/queue-6.19/rdma-irdma-initialize-free_qp-completion-before-usin.patch new file mode 100644 index 0000000000..81b83fdcbe --- /dev/null +++ b/queue-6.19/rdma-irdma-initialize-free_qp-completion-before-usin.patch @@ -0,0 +1,46 @@ +From 70810559a7684d0a79a8b5de3ad67968c394859f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:38 -0500 +Subject: RDMA/irdma: Initialize free_qp completion before using it + +From: Jacob Moroni + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch b/queue-6.19/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch new file mode 100644 index 0000000000..2828714e40 --- /dev/null +++ b/queue-6.19/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch @@ -0,0 +1,38 @@ +From 0e98508882991a6c822580e549720a7fded9ad39 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch b/queue-6.19/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch new file mode 100644 index 0000000000..5ead3fa212 --- /dev/null +++ b/queue-6.19/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch @@ -0,0 +1,38 @@ +From ce51eba4625af547346d57fa36f84709542988bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:44 -0500 +Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err() + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-irdma-return-einval-for-invalid-arp-index-error.patch b/queue-6.19/rdma-irdma-return-einval-for-invalid-arp-index-error.patch new file mode 100644 index 0000000000..8824cfdf1f --- /dev/null +++ b/queue-6.19/rdma-irdma-return-einval-for-invalid-arp-index-error.patch @@ -0,0 +1,86 @@ +From bef5b70468c4fae0fdd85eea73df09fdf9e661c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:46 -0500 +Subject: RDMA/irdma: Return EINVAL for invalid arp index error + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch b/queue-6.19/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch new file mode 100644 index 0000000000..946f8441e2 --- /dev/null +++ b/queue-6.19/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch @@ -0,0 +1,45 @@ +From f689fcde0a5bac19fdd7306bcfa8cbb769b642ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch b/queue-6.19/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch new file mode 100644 index 0000000000..ecf54378b2 --- /dev/null +++ b/queue-6.19/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch @@ -0,0 +1,87 @@ +From 16cd84d58ee16b36aed602334055686da9448fc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 15:41:58 -0400 +Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion + +From: Chuck Lever + +[ 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 +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/regmap-synchronize-cache-for-the-page-selector.patch b/queue-6.19/regmap-synchronize-cache-for-the-page-selector.patch new file mode 100644 index 0000000000..69394d7921 --- /dev/null +++ b/queue-6.19/regmap-synchronize-cache-for-the-page-selector.patch @@ -0,0 +1,112 @@ +From 7285ada4166f6e095d36c63b7915c2ef2057317d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Mar 2026 19:43:31 +0100 +Subject: regmap: Synchronize cache for the page selector + +From: Andy Shevchenko + +[ 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 +Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com +Tested-by: Marek Szyprowski +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/rust-regulator-do-not-assume-that-regulator_get-retu.patch b/queue-6.19/rust-regulator-do-not-assume-that-regulator_get-retu.patch new file mode 100644 index 0000000000..22e0a34ae0 --- /dev/null +++ b/queue-6.19/rust-regulator-do-not-assume-that-regulator_get-retu.patch @@ -0,0 +1,141 @@ +From 01fe336cdb6288a5829e92c8e18a96113e009af9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 10:49:59 +0000 +Subject: rust: regulator: do not assume that regulator_get() returns non-null + +From: Alice Ryhl + +[ 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 +Closes: https://lore.kernel.org/r/20260322193830.89324-1-ojeda@kernel.org +Signed-off-by: Alice Ryhl +Reviewed-by: Daniel Almeida +Link: https://patch.msgid.link/20260324-regulator-fix-v1-1-a5244afa3c15@google.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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, 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 + where + State: RegulatorState, + { +- inner: NonNull, ++ inner: *mut bindings::regulator, + _phantom: PhantomData, + } + +@@ -252,7 +257,7 @@ impl Regulator { + // 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 Regulator { + /// Gets the current voltage of the regulator. + pub fn get_voltage(&self) -> Result { + // 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 Regulator { + // 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 Regulator { + + 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 Regulator { + /// 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 Drop for Regulator { + // 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 + diff --git a/queue-6.19/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch b/queue-6.19/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch new file mode 100644 index 0000000000..93b8751ecb --- /dev/null +++ b/queue-6.19/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch @@ -0,0 +1,44 @@ +From 6d07a464c5b5f6e6b2f338fda873e4ba301d0d1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 14:31:47 +0800 +Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue + +From: Yihang Li + +[ 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 +Reviewed-by: John Garry +Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/series b/queue-6.19/series index f90e913c16..59faf0078f 100644 --- a/queue-6.19/series +++ b/queue-6.19/series @@ -144,3 +144,51 @@ netfilter-nf_conntrack_expect-skip-expectations-in-o.patch 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 diff --git a/queue-6.19/spi-meson-spicc-fix-double-put-in-remove-path.patch b/queue-6.19/spi-meson-spicc-fix-double-put-in-remove-path.patch new file mode 100644 index 0000000000..ea2acb05b6 --- /dev/null +++ b/queue-6.19/spi-meson-spicc-fix-double-put-in-remove-path.patch @@ -0,0 +1,42 @@ +From 9824e5a8697f4e9d6d8181c3bfe2044e059c2d58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 Mar 2026 21:29:56 +0800 +Subject: spi: meson-spicc: Fix double-put in remove path + +From: Felix Gu + +[ 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 +Reviewed-by: Johan Hovold +Link: https://patch.msgid.link/20260322-rockchip-v1-1-fac3f0c6dad8@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch b/queue-6.19/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch new file mode 100644 index 0000000000..681643e2e0 --- /dev/null +++ b/queue-6.19/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch @@ -0,0 +1,72 @@ +From d8e6ba973581dddd07ffdbc4f8a8eec758a9a18d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 00:12:34 +0800 +Subject: spi: sn-f-ospi: Fix resource leak in f_ospi_probe() + +From: Felix Gu + +[ 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 +Link: https://patch.msgid.link/20260319-sn-f-v1-1-33a6738d2da8@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch b/queue-6.19/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch new file mode 100644 index 0000000000..28feb42730 --- /dev/null +++ b/queue-6.19/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch @@ -0,0 +1,69 @@ +From 0bb280c7240e5d245da2c9752a8c0e7fa48e3f4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 19:38:12 +0100 +Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF) + +From: Marc Kleine-Budde + +[ 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 +Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/spi-use-generic-driver_override-infrastructure.patch b/queue-6.19/spi-use-generic-driver_override-infrastructure.patch new file mode 100644 index 0000000000..fc0ea1b05c --- /dev/null +++ b/queue-6.19/spi-use-generic-driver_override-infrastructure.patch @@ -0,0 +1,118 @@ +From d8b8f102c6eba7eefe472b1fb39f1e9f85939ce6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 01:59:15 +0100 +Subject: spi: use generic driver_override infrastructure + +From: Danilo Krummrich + +[ 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 +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789 +Fixes: 5039563e7c25 ("spi: Add driver_override SPI device attribute") +Signed-off-by: Danilo Krummrich +Link: https://patch.msgid.link/20260324005919.2408620-12-dakr@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch b/queue-6.19/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch new file mode 100644 index 0000000000..6cf70891a1 --- /dev/null +++ b/queue-6.19/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch @@ -0,0 +1,47 @@ +From 23c0eeb5a026d57ededd4ccebd3f1b034c077938 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 23:29:50 +0100 +Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap + +From: Marc Buerg + +[ 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 +Reviewed-by: Joel Granados +Signed-off-by: Joel Granados +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.19/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch b/queue-6.19/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch new file mode 100644 index 0000000000..f68c8369c0 --- /dev/null +++ b/queue-6.19/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch @@ -0,0 +1,42 @@ +From d82931e7a0f4049af540abf1a544d380aa02ce09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory") +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch b/queue-6.6/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch new file mode 100644 index 0000000000..9e1db32b57 --- /dev/null +++ b/queue-6.6/acpi-ec-clean-up-handlers-on-probe-failure-in-acpi_e.patch @@ -0,0 +1,83 @@ +From 869398f2264485a19fa6197e026dbcba1ca2ac19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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) + + + 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 +Signed-off-by: Weiming Shi +Link: https://patch.msgid.link/20260324165458.1337233-2-bestswngs@gmail.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch b/queue-6.6/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch new file mode 100644 index 0000000000..7e3f03308b --- /dev/null +++ b/queue-6.6/asoc-adau1372-fix-clock-leak-on-pll-lock-failure.patch @@ -0,0 +1,80 @@ +From 880b53b0621e36da10b89cedc6dc8e505e59a660 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-3-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch b/queue-6.6/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch new file mode 100644 index 0000000000..ab7aea8584 --- /dev/null +++ b/queue-6.6/asoc-adau1372-fix-unchecked-clk_prepare_enable-retur.patch @@ -0,0 +1,82 @@ +From 9fe74a6c41ef3257b8b937a21f617f7d7098ae66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 6cd4c6459e47 ("ASoC: Add ADAU1372 audio CODEC support") +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20260325210704.76847-2-jihed.chaibi.dev@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/asoc-intel-catpt-fix-the-device-initialization.patch b/queue-6.6/asoc-intel-catpt-fix-the-device-initialization.patch new file mode 100644 index 0000000000..78291154cb --- /dev/null +++ b/queue-6.6/asoc-intel-catpt-fix-the-device-initialization.patch @@ -0,0 +1,63 @@ +From 4561724fa699a96aa12a318b0bed5b8c702a2293 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 11:12:17 +0100 +Subject: ASoC: Intel: catpt: Fix the device initialization + +From: Cezary Rojewski + +[ 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 +Fixes: 7a10b66a5df9 ("ASoC: Intel: catpt: Device driver lifecycle") +Signed-off-by: Cezary Rojewski +Reviewed-by: Andy Shevchenko +Link: https://patch.msgid.link/20260320101217.1243688-1-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch b/queue-6.6/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch new file mode 100644 index 0000000000..1c13019e79 --- /dev/null +++ b/queue-6.6/drm-amdgpu-fix-fence-put-before-wait-in-amdgpu_amdkf.patch @@ -0,0 +1,62 @@ +From f20fc83a996f7d715d29998cb149091508189016 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Dan Carpenter +Cc: Christian König +Cc: Alex Deucher +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit 8b9e5259adc385b61a6590a13b82ae0ac2bd3482) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch b/queue-6.6/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch new file mode 100644 index 0000000000..46a117d85b --- /dev/null +++ b/queue-6.6/drm-i915-gmbus-fix-spurious-timeout-on-512-byte-burs.patch @@ -0,0 +1,46 @@ +From 44ce78b389b3bd1d6dfe3eaa95a094d6a1bfed96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jani Nikula +Link: https://patch.msgid.link/20260316231920.135438-2-samasth.norway.ananda@oracle.com +Signed-off-by: Jani Nikula +(cherry picked from commit 4ab0f09ee73fc853d00466682635f67c531f909c) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch b/queue-6.6/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch new file mode 100644 index 0000000000..08b57f0dfb --- /dev/null +++ b/queue-6.6/hwmon-adm1177-fix-sysfs-abi-violation-and-current-un.patch @@ -0,0 +1,187 @@ +From 74d99f394f94208dbffd9dee9572025adbc374e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Nuno Sá +Link: https://lore.kernel.org/r/20260325051246.28262-1-sanman.pradhan@hpe.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include + #include + #include + +@@ -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 + diff --git a/queue-6.6/pm-hibernate-don-t-ignore-return-from-set_memory_ro.patch b/queue-6.6/pm-hibernate-don-t-ignore-return-from-set_memory_ro.patch new file mode 100644 index 0000000000..88e1fa8d53 --- /dev/null +++ b/queue-6.6/pm-hibernate-don-t-ignore-return-from-set_memory_ro.patch @@ -0,0 +1,151 @@ +From 7a7e214dac87db2a051586edd332f54a2ab2885f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 Feb 2024 09:40:58 +0100 +Subject: PM: hibernate: Don't ignore return from set_memory_ro() + +From: Christophe Leroy + +[ 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 +Reviewed-by: Kees Cook +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: 734eba62cd32 ("PM: hibernate: Drain trailing zero pages on userspace restore") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch b/queue-6.6/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch new file mode 100644 index 0000000000..1aa31fe12b --- /dev/null +++ b/queue-6.6/pm-hibernate-drain-trailing-zero-pages-on-userspace-.patch @@ -0,0 +1,64 @@ +From 0d142af4db0aa8153694c6ee65a364c6ba09d56b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Mar 2026 18:39:41 +0100 +Subject: PM: hibernate: Drain trailing zero pages on userspace restore + +From: Alberto Garcia + +[ 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 +Acked-by: Brian Geffon +Link: https://patch.msgid.link/ef5a7c5e3e3dbd17dcb20efaa0c53a47a23498bb.1773075892.git.berto@igalia.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch b/queue-6.6/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch new file mode 100644 index 0000000000..2939ab0714 --- /dev/null +++ b/queue-6.6/rdma-irdma-clean-up-unnecessary-dereference-of-event.patch @@ -0,0 +1,64 @@ +From 7a8619ff60a34415206ff6a72a10508e1c285534 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:43 -0500 +Subject: RDMA/irdma: Clean up unnecessary dereference of event->cm_node + +From: Ivan Barrera + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch b/queue-6.6/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch new file mode 100644 index 0000000000..64071e9b62 --- /dev/null +++ b/queue-6.6/rdma-irdma-fix-deadlock-during-netdev-reset-with-act.patch @@ -0,0 +1,44 @@ +From 255d9f023900d5cabda9e360f8cd0e56d8f9d52e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:45 -0500 +Subject: RDMA/irdma: Fix deadlock during netdev reset with active connections + +From: Anil Samal + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/rdma-irdma-initialize-free_qp-completion-before-usin.patch b/queue-6.6/rdma-irdma-initialize-free_qp-completion-before-usin.patch new file mode 100644 index 0000000000..116e492b48 --- /dev/null +++ b/queue-6.6/rdma-irdma-initialize-free_qp-completion-before-usin.patch @@ -0,0 +1,46 @@ +From 1e5af1726fd84ca5ddb777f4907f5186db90b7fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:38 -0500 +Subject: RDMA/irdma: Initialize free_qp completion before using it + +From: Jacob Moroni + +[ 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 +Signed-off-by: Tatyana Nikolova +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch b/queue-6.6/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch new file mode 100644 index 0000000000..ba67927658 --- /dev/null +++ b/queue-6.6/rdma-irdma-remove-a-nop-wait_event-in-irdma_modify_q.patch @@ -0,0 +1,38 @@ +From 3f127b494303d4c0faebae77710d5445c85ffdb8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch b/queue-6.6/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch new file mode 100644 index 0000000000..020ba3e96e --- /dev/null +++ b/queue-6.6/rdma-irdma-remove-reset-check-from-irdma_modify_qp_t.patch @@ -0,0 +1,38 @@ +From 443b85cb5759390c82b6b8635446645107846b46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:44 -0500 +Subject: RDMA/irdma: Remove reset check from irdma_modify_qp_to_err() + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/rdma-irdma-return-einval-for-invalid-arp-index-error.patch b/queue-6.6/rdma-irdma-return-einval-for-invalid-arp-index-error.patch new file mode 100644 index 0000000000..8c59c77ee3 --- /dev/null +++ b/queue-6.6/rdma-irdma-return-einval-for-invalid-arp-index-error.patch @@ -0,0 +1,86 @@ +From 98239aeeb2b09f3d54349158de797f449297fd72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 13:39:46 -0500 +Subject: RDMA/irdma: Return EINVAL for invalid arp index error + +From: Tatyana Nikolova + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch b/queue-6.6/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch new file mode 100644 index 0000000000..bff560f9c8 --- /dev/null +++ b/queue-6.6/rdma-irdma-update-ibqp-state-to-error-if-qp-is-alrea.patch @@ -0,0 +1,45 @@ +From 2c5069bc65bfd81d21aad1bf2f68d41e145021f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch b/queue-6.6/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch new file mode 100644 index 0000000000..ed412a1f1a --- /dev/null +++ b/queue-6.6/rdma-rw-fall-back-to-direct-sge-on-mr-pool-exhaustio.patch @@ -0,0 +1,87 @@ +From bba8437fb676f802e54e19cc42aa58c6f1bca6f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 15:41:58 -0400 +Subject: RDMA/rw: Fall back to direct SGE on MR pool exhaustion + +From: Chuck Lever + +[ 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 +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260313194201.5818-2-cel@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/regmap-synchronize-cache-for-the-page-selector.patch b/queue-6.6/regmap-synchronize-cache-for-the-page-selector.patch new file mode 100644 index 0000000000..a76a258bb6 --- /dev/null +++ b/queue-6.6/regmap-synchronize-cache-for-the-page-selector.patch @@ -0,0 +1,112 @@ +From 2832d624117b05842d2c25502a7e6cf5bfe88550 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Mar 2026 19:43:31 +0100 +Subject: regmap: Synchronize cache for the page selector + +From: Andy Shevchenko + +[ 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 +Link: https://patch.msgid.link/20260302184753.2693803-1-andriy.shevchenko@linux.intel.com +Tested-by: Marek Szyprowski +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch b/queue-6.6/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch new file mode 100644 index 0000000000..7207127252 --- /dev/null +++ b/queue-6.6/scsi-scsi_transport_sas-fix-the-maximum-channel-scan.patch @@ -0,0 +1,44 @@ +From a0fdf6651e5b95e326674d2390c866a8454fee0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 14:31:47 +0800 +Subject: scsi: scsi_transport_sas: Fix the maximum channel scanning issue + +From: Yihang Li + +[ 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 +Reviewed-by: John Garry +Link: https://patch.msgid.link/20260317063147.2182562-1-liyihang9@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/series b/queue-6.6/series index 0718966fba..5345c35738 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -72,3 +72,26 @@ netfilter-nf_conntrack_expect-skip-expectations-in-o.patch 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 diff --git a/queue-6.6/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch b/queue-6.6/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch new file mode 100644 index 0000000000..aa946c397e --- /dev/null +++ b/queue-6.6/spi-sn-f-ospi-fix-resource-leak-in-f_ospi_probe.patch @@ -0,0 +1,72 @@ +From 9632f0926107b472e493edab1ae36e1d9e89bd2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 00:12:34 +0800 +Subject: spi: sn-f-ospi: Fix resource leak in f_ospi_probe() + +From: Felix Gu + +[ 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 +Link: https://patch.msgid.link/20260319-sn-f-v1-1-33a6738d2da8@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch b/queue-6.6/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch new file mode 100644 index 0000000000..d3268c5a57 --- /dev/null +++ b/queue-6.6/spi-spi-fsl-lpspi-fix-teardown-order-issue-uaf.patch @@ -0,0 +1,69 @@ +From 0baae967e5810053b40a05d5d07d5692c63125b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 19:38:12 +0100 +Subject: spi: spi-fsl-lpspi: fix teardown order issue (UAF) + +From: Marc Kleine-Budde + +[ 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 +Link: https://patch.msgid.link/20260319-spi-fsl-lpspi-fixes-v1-1-b433e435b2d8@pengutronix.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch b/queue-6.6/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch new file mode 100644 index 0000000000..10791c6a6a --- /dev/null +++ b/queue-6.6/sysctl-fix-uninitialized-variable-in-proc_do_large_b.patch @@ -0,0 +1,47 @@ +From be11ed34db52463c852415963b7749000291fda5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 23:29:50 +0100 +Subject: sysctl: fix uninitialized variable in proc_do_large_bitmap + +From: Marc Buerg + +[ 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 +Reviewed-by: Joel Granados +Signed-off-by: Joel Granados +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch b/queue-6.6/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch new file mode 100644 index 0000000000..c59c7049a9 --- /dev/null +++ b/queue-6.6/x86-efi-efi_unmap_boot_services-fix-calculation-of-r.patch @@ -0,0 +1,42 @@ +From e40ba7fd402170a62dcacb24ef3e1ce0a7bffcce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Fixes: a4b0bf6a40f3 ("x86/efi: defer freeing of boot services memory") +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Ard Biesheuvel +Signed-off-by: Sasha Levin +--- + 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 +