]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Apr 2026 14:43:27 +0000 (16:43 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Apr 2026 14:43:27 +0000 (16:43 +0200)
added patches:
batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch
bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch
cpufreq-governor-fix-double-free-in-cpufreq_dbs_governor_init-error-path.patch
cpufreq-governor-free-dbs_data-directly-when-gov-init-fails.patch
device-property-add-fwnode_is_ancestor_of-and-fwnode_get_next_parent_dev.patch
device-property-allow-error-pointer-to-be-passed-to-fwnode-apis.patch
device-property-allow-secondary-lookup-in-fwnode_get_next_child_node.patch
device-property-check-fwnode-secondary-in-fwnode_graph_get_next_endpoint.patch
device-property-check-fwnode-secondary-when-finding-properties.patch
device-property-retrieve-fwnode-from-of_node-via-accessor.patch
device-property-unify-access-to-of_node.patch
drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch
ext4-fix-iloc.bh-leak-in-ext4_fc_replay_inode-error-paths.patch
ext4-fix-the-might_sleep-warnings-in-kvfree.patch
ext4-publish-jinode-after-initialization.patch
media-device-property-return-true-in-fwnode_device_is_available-for-null-ops.patch
mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch
mmc-core-avoid-bitfield-rmw-for-claim-retune-flags.patch
mmc-core-drop-redundant-member-in-struct-mmc-host.patch
mmc-core-drop-reference-counting-of-the-bus_ops.patch
mmc-core-drop-superfluous-validations-in-mmc_hw-sw_reset.patch
net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch
net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch
nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch
revert-nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch
s390-syscalls-add-spectre-boundary-for-syscall-dispatch-table.patch
seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch
usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch
usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch
usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch
xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch
xfs-stop-reclaim-before-pushing-ail-during-unmount.patch

33 files changed:
queue-5.10/batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch [new file with mode: 0644]
queue-5.10/bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch [new file with mode: 0644]
queue-5.10/cpufreq-governor-fix-double-free-in-cpufreq_dbs_governor_init-error-path.patch [new file with mode: 0644]
queue-5.10/cpufreq-governor-free-dbs_data-directly-when-gov-init-fails.patch [new file with mode: 0644]
queue-5.10/device-property-add-fwnode_is_ancestor_of-and-fwnode_get_next_parent_dev.patch [new file with mode: 0644]
queue-5.10/device-property-allow-error-pointer-to-be-passed-to-fwnode-apis.patch [new file with mode: 0644]
queue-5.10/device-property-allow-secondary-lookup-in-fwnode_get_next_child_node.patch [new file with mode: 0644]
queue-5.10/device-property-check-fwnode-secondary-in-fwnode_graph_get_next_endpoint.patch [new file with mode: 0644]
queue-5.10/device-property-check-fwnode-secondary-when-finding-properties.patch [new file with mode: 0644]
queue-5.10/device-property-retrieve-fwnode-from-of_node-via-accessor.patch [new file with mode: 0644]
queue-5.10/device-property-unify-access-to-of_node.patch [new file with mode: 0644]
queue-5.10/drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch [new file with mode: 0644]
queue-5.10/ext4-fix-iloc.bh-leak-in-ext4_fc_replay_inode-error-paths.patch [new file with mode: 0644]
queue-5.10/ext4-fix-the-might_sleep-warnings-in-kvfree.patch [new file with mode: 0644]
queue-5.10/ext4-publish-jinode-after-initialization.patch [new file with mode: 0644]
queue-5.10/media-device-property-return-true-in-fwnode_device_is_available-for-null-ops.patch [new file with mode: 0644]
queue-5.10/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch [new file with mode: 0644]
queue-5.10/mmc-core-avoid-bitfield-rmw-for-claim-retune-flags.patch [new file with mode: 0644]
queue-5.10/mmc-core-drop-redundant-member-in-struct-mmc-host.patch [new file with mode: 0644]
queue-5.10/mmc-core-drop-reference-counting-of-the-bus_ops.patch [new file with mode: 0644]
queue-5.10/mmc-core-drop-superfluous-validations-in-mmc_hw-sw_reset.patch [new file with mode: 0644]
queue-5.10/net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch [new file with mode: 0644]
queue-5.10/net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch [new file with mode: 0644]
queue-5.10/nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch [new file with mode: 0644]
queue-5.10/revert-nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch [new file with mode: 0644]
queue-5.10/s390-syscalls-add-spectre-boundary-for-syscall-dispatch-table.patch [new file with mode: 0644]
queue-5.10/seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch [new file with mode: 0644]
queue-5.10/usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch [new file with mode: 0644]
queue-5.10/usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch [new file with mode: 0644]
queue-5.10/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch [new file with mode: 0644]
queue-5.10/xfs-stop-reclaim-before-pushing-ail-during-unmount.patch [new file with mode: 0644]

diff --git a/queue-5.10/batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch b/queue-5.10/batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch
new file mode 100644 (file)
index 0000000..d036710
--- /dev/null
@@ -0,0 +1,50 @@
+From stable+bounces-227509-greg=kroah.com@vger.kernel.org Fri Mar 20 11:18:34 2026
+From: Sven Eckelmann <sven@narfation.org>
+Date: Fri, 20 Mar 2026 11:12:23 +0100
+Subject: batman-adv: avoid OGM aggregation when skb tailroom is insufficient
+To: stable@vger.kernel.org
+Cc: Yang Yang <n05ec@lzu.edu.cn>, Yifan Wu <yifanwucs@gmail.com>, Juefei Pu <tomapufckgml@gmail.com>, Yuan Tan <tanyuan98@outlook.com>, Xin Liu <bird@lzu.edu.cn>, Sven Eckelmann <sven@narfation.org>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20260320101223.1554036-1-sven@narfation.org>
+
+From: Yang Yang <n05ec@lzu.edu.cn>
+
+commit 0d4aef630be9d5f9c1227d07669c26c4383b5ad0 upstream.
+
+When OGM aggregation state is toggled at runtime, an existing forwarded
+packet may have been allocated with only packet_len bytes, while a later
+packet can still be selected for aggregation. Appending in this case can
+hit skb_put overflow conditions.
+
+Reject aggregation when the target skb tailroom cannot accommodate the new
+packet. The caller then falls back to creating a new forward packet
+instead of appending.
+
+Fixes: c6c8fea29769 ("net: Add batman-adv meshing protocol")
+Cc: stable@vger.kernel.org
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Signed-off-by: Yuan Tan <tanyuan98@outlook.com>
+Signed-off-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Ao Zhou <n05ec@lzu.edu.cn>
+Signed-off-by: Yang Yang <n05ec@lzu.edu.cn>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+[ Adjust context ]
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_iv_ogm.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -466,6 +466,9 @@ batadv_iv_ogm_can_aggregate(const struct
+           !time_after_eq(aggregation_end_time, forw_packet->send_time))
+               return false;
++      if (skb_tailroom(forw_packet->skb) < packet_len)
++              return false;
++
+       if (aggregated_bytes > BATADV_MAX_AGGREGATION_BYTES)
+               return false;
diff --git a/queue-5.10/bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch b/queue-5.10/bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch
new file mode 100644 (file)
index 0000000..13176d3
--- /dev/null
@@ -0,0 +1,64 @@
+From stable+bounces-227805-greg=kroah.com@vger.kernel.org Sun Mar 22 02:30:47 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 21 Mar 2026 21:30:42 -0400
+Subject: Bluetooth: L2CAP: Fix accepting multiple L2CAP_ECRED_CONN_REQ
+To: stable@vger.kernel.org
+Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>, Yiming Qian <yimingqian591@gmail.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260322013042.677010-1-sashal@kernel.org>
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 5b3e2052334f2ff6d5200e952f4aa66994d09899 ]
+
+Currently the code attempts to accept requests regardless of the
+command identifier which may cause multiple requests to be marked
+as pending (FLAG_DEFER_SETUP) which can cause more than
+L2CAP_ECRED_MAX_CID(5) to be allocated in l2cap_ecred_rsp_defer
+causing an overflow.
+
+The spec is quite clear that the same identifier shall not be used on
+subsequent requests:
+
+'Within each signaling channel a different Identifier shall be used
+for each successive request or indication.'
+https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-62/out/en/host/logical-link-control-and-adaptation-protocol-specification.html#UUID-32a25a06-4aa4-c6c7-77c5-dcfe3682355d
+
+So this attempts to check if there are any channels pending with the
+same identifier and rejects if any are found.
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+[ adapted variable names ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/l2cap_core.c |   10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6053,7 +6053,7 @@ static inline int l2cap_ecred_conn_req(s
+       u16 mtu, mps;
+       __le16 psm;
+       u8 result, len = 0;
+-      int i, num_scid;
++      int i, num_scid = 0;
+       bool defer = false;
+       if (!enable_ecred)
+@@ -6063,6 +6063,14 @@ static inline int l2cap_ecred_conn_req(s
+               result = L2CAP_CR_LE_INVALID_PARAMS;
+               goto response;
+       }
++
++      /* Check if there are no pending channels with the same ident */
++      __l2cap_chan_list_id(conn, cmd->ident, l2cap_ecred_list_defer,
++                           &num_scid);
++      if (num_scid) {
++              result = L2CAP_CR_LE_INVALID_PARAMS;
++              goto response;
++      }
+       cmd_len -= sizeof(*req);
+       num_scid = cmd_len / sizeof(u16);
diff --git a/queue-5.10/cpufreq-governor-fix-double-free-in-cpufreq_dbs_governor_init-error-path.patch b/queue-5.10/cpufreq-governor-fix-double-free-in-cpufreq_dbs_governor_init-error-path.patch
new file mode 100644 (file)
index 0000000..e773287
--- /dev/null
@@ -0,0 +1,56 @@
+From stable+bounces-233898-greg=kroah.com@vger.kernel.org Wed Apr  8 15:02:11 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  8 Apr 2026 09:02:02 -0400
+Subject: cpufreq: governor: fix double free in cpufreq_dbs_governor_init() error path
+To: stable@vger.kernel.org
+Cc: Guangshuo Li <lgs201920130244@gmail.com>, Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>, Viresh Kumar <viresh.kumar@linaro.org>, "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260408130202.1050557-2-sashal@kernel.org>
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+[ Upstream commit 6dcf9d0064ce2f3e3dfe5755f98b93abe6a98e1e ]
+
+When kobject_init_and_add() fails, cpufreq_dbs_governor_init() calls
+kobject_put(&dbs_data->attr_set.kobj).
+
+The kobject release callback cpufreq_dbs_data_release() calls
+gov->exit(dbs_data) and kfree(dbs_data), but the current error path
+then calls gov->exit(dbs_data) and kfree(dbs_data) again, causing a
+double free.
+
+Keep the direct kfree(dbs_data) for the gov->init() failure path, but
+after kobject_init_and_add() has been called, let kobject_put() handle
+the cleanup through cpufreq_dbs_data_release().
+
+Fixes: 4ebe36c94aed ("cpufreq: Fix kobject memleak")
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Cc: All applicable <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20260401024535.1395801-1-lgs201920130244@gmail.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/cpufreq_governor.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/cpufreq/cpufreq_governor.c
++++ b/drivers/cpufreq/cpufreq_governor.c
+@@ -457,13 +457,13 @@ int cpufreq_dbs_governor_init(struct cpu
+       /* Failure, so roll back. */
+       pr_err("initialization failed (dbs_data kobject init error %d)\n", ret);
+-      kobject_put(&dbs_data->attr_set.kobj);
+-
+       policy->governor_data = NULL;
+       if (!have_governor_per_policy())
+               gov->gdbs_data = NULL;
+-      gov->exit(dbs_data);
++
++      kobject_put(&dbs_data->attr_set.kobj);
++      goto free_policy_dbs_info;
+ free_dbs_data:
+       kfree(dbs_data);
diff --git a/queue-5.10/cpufreq-governor-free-dbs_data-directly-when-gov-init-fails.patch b/queue-5.10/cpufreq-governor-free-dbs_data-directly-when-gov-init-fails.patch
new file mode 100644 (file)
index 0000000..ae78a29
--- /dev/null
@@ -0,0 +1,46 @@
+From stable+bounces-233897-greg=kroah.com@vger.kernel.org Wed Apr  8 15:02:09 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  8 Apr 2026 09:02:01 -0400
+Subject: cpufreq: governor: Free dbs_data directly when gov->init() fails
+To: stable@vger.kernel.org
+Cc: Liao Chang <liaochang1@huawei.com>, Viresh Kumar <viresh.kumar@linaro.org>, "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260408130202.1050557-1-sashal@kernel.org>
+
+From: Liao Chang <liaochang1@huawei.com>
+
+[ Upstream commit 916f13884042f615cfbfc0b42cc68dadee826f2a ]
+
+Due to the kobject embedded in the dbs_data doest not has a release()
+method yet, it needs to use kfree() to free dbs_data directly when
+governor fails to allocate the tunner field of dbs_data.
+
+Signed-off-by: Liao Chang <liaochang1@huawei.com>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 6dcf9d0064ce ("cpufreq: governor: fix double free in cpufreq_dbs_governor_init() error path")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/cpufreq_governor.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/cpufreq/cpufreq_governor.c
++++ b/drivers/cpufreq/cpufreq_governor.c
+@@ -430,7 +430,7 @@ int cpufreq_dbs_governor_init(struct cpu
+       ret = gov->init(dbs_data);
+       if (ret)
+-              goto free_policy_dbs_info;
++              goto free_dbs_data;
+       /*
+        * The sampling interval should not be less than the transition latency
+@@ -464,6 +464,8 @@ int cpufreq_dbs_governor_init(struct cpu
+       if (!have_governor_per_policy())
+               gov->gdbs_data = NULL;
+       gov->exit(dbs_data);
++
++free_dbs_data:
+       kfree(dbs_data);
+ free_policy_dbs_info:
diff --git a/queue-5.10/device-property-add-fwnode_is_ancestor_of-and-fwnode_get_next_parent_dev.patch b/queue-5.10/device-property-add-fwnode_is_ancestor_of-and-fwnode_get_next_parent_dev.patch
new file mode 100644 (file)
index 0000000..eb9b974
--- /dev/null
@@ -0,0 +1,113 @@
+From sashal@kernel.org Tue Mar 17 18:19:58 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 13:19:47 -0400
+Subject: device property: Add fwnode_is_ancestor_of() and fwnode_get_next_parent_dev()
+To: stable@vger.kernel.org
+Cc: Saravana Kannan <saravanak@google.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317171954.238398-1-sashal@kernel.org>
+
+From: Saravana Kannan <saravanak@google.com>
+
+[ Upstream commit b5d3e2fbcb10957521af14c4256cd0e5f68b9234 ]
+
+Add fwnode_is_ancestor_of() helper function to check if a fwnode is an
+ancestor of another fwnode.
+
+Add fwnode_get_next_parent_dev() helper function that take as input a
+fwnode and finds the closest ancestor fwnode that has a corresponding
+struct device and returns that struct device.
+
+Signed-off-by: Saravana Kannan <saravanak@google.com>
+Link: https://lore.kernel.org/r/20201121020232.908850-11-saravanak@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/property.c  |   52 +++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/property.h |    3 ++
+ 2 files changed, 55 insertions(+)
+
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -615,6 +615,31 @@ struct fwnode_handle *fwnode_get_next_pa
+ EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
+ /**
++ * fwnode_get_next_parent_dev - Find device of closest ancestor fwnode
++ * @fwnode: firmware node
++ *
++ * Given a firmware node (@fwnode), this function finds its closest ancestor
++ * firmware node that has a corresponding struct device and returns that struct
++ * device.
++ *
++ * The caller of this function is expected to call put_device() on the returned
++ * device when they are done.
++ */
++struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode)
++{
++      struct device *dev = NULL;
++
++      fwnode_handle_get(fwnode);
++      do {
++              fwnode = fwnode_get_next_parent(fwnode);
++              if (fwnode)
++                      dev = get_dev_from_fwnode(fwnode);
++      } while (fwnode && !dev);
++      fwnode_handle_put(fwnode);
++      return dev;
++}
++
++/**
+  * fwnode_count_parents - Return the number of parents a node has
+  * @fwnode: The node the parents of which are to be counted
+  *
+@@ -661,6 +686,33 @@ struct fwnode_handle *fwnode_get_nth_par
+ EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
+ /**
++ * fwnode_is_ancestor_of - Test if @test_ancestor is ancestor of @test_child
++ * @test_ancestor: Firmware which is tested for being an ancestor
++ * @test_child: Firmware which is tested for being the child
++ *
++ * A node is considered an ancestor of itself too.
++ *
++ * Returns true if @test_ancestor is an ancestor of @test_child.
++ * Otherwise, returns false.
++ */
++bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor,
++                                struct fwnode_handle *test_child)
++{
++      if (!test_ancestor)
++              return false;
++
++      fwnode_handle_get(test_child);
++      while (test_child) {
++              if (test_child == test_ancestor) {
++                      fwnode_handle_put(test_child);
++                      return true;
++              }
++              test_child = fwnode_get_next_parent(test_child);
++      }
++      return false;
++}
++
++/**
+  * fwnode_get_next_child_node - Return the next child node handle for a node
+  * @fwnode: Firmware node to find the next child node for.
+  * @child: Handle to one of the node's child nodes or a %NULL handle.
+--- a/include/linux/property.h
++++ b/include/linux/property.h
+@@ -85,9 +85,12 @@ const char *fwnode_get_name_prefix(const
+ struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode);
+ struct fwnode_handle *fwnode_get_next_parent(
+       struct fwnode_handle *fwnode);
++struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode);
+ unsigned int fwnode_count_parents(const struct fwnode_handle *fwn);
+ struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwn,
+                                           unsigned int depth);
++bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor,
++                                struct fwnode_handle *test_child);
+ struct fwnode_handle *fwnode_get_next_child_node(
+       const struct fwnode_handle *fwnode, struct fwnode_handle *child);
+ struct fwnode_handle *fwnode_get_next_available_child_node(
diff --git a/queue-5.10/device-property-allow-error-pointer-to-be-passed-to-fwnode-apis.patch b/queue-5.10/device-property-allow-error-pointer-to-be-passed-to-fwnode-apis.patch
new file mode 100644 (file)
index 0000000..b07b73c
--- /dev/null
@@ -0,0 +1,256 @@
+From stable+bounces-226740-greg=kroah.com@vger.kernel.org Tue Mar 17 18:23:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 13:19:53 -0400
+Subject: device property: Allow error pointer to be passed to fwnode APIs
+To: stable@vger.kernel.org
+Cc: "Andy Shevchenko" <andriy.shevchenko@linux.intel.com>, "Nuno Sá" <nuno.sa@analog.com>, "Sakari Ailus" <sakari.ailus@linux.intel.com>, "Heikki Krogerus" <heikki.krogerus@linux.intel.com>, "Michael Walle" <michael@walle.cc>, "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260317171954.238398-7-sashal@kernel.org>
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 002752af7b89b74c64fe6bec8c5fde3d3a7810d8 ]
+
+Some of the fwnode APIs might return an error pointer instead of NULL
+or valid fwnode handle. The result of such API call may be considered
+optional and hence the test for it is usually done in a form of
+
+       fwnode = fwnode_find_reference(...);
+       if (IS_ERR(fwnode))
+               ...error handling...
+
+Nevertheless the resulting fwnode may have bumped the reference count
+and hence caller of the above API is obliged to call fwnode_handle_put().
+Since fwnode may be not valid either as NULL or error pointer the check
+has to be performed there. This approach uglifies the code and adds
+a point of making a mistake, i.e. forgetting about error point case.
+
+To prevent this, allow an error pointer to be passed to the fwnode APIs.
+
+Fixes: 83b34afb6b79 ("device property: Introduce fwnode_find_reference()")
+Reported-by: Nuno Sá <nuno.sa@analog.com>
+Tested-by: Nuno Sá <nuno.sa@analog.com>
+Acked-by: Nuno Sá <nuno.sa@analog.com>
+Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Tested-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/property.c |   89 +++++++++++++++++++++++++++---------------------
+ include/linux/fwnode.h  |   10 ++---
+ 2 files changed, 56 insertions(+), 43 deletions(-)
+
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -48,12 +48,14 @@ bool fwnode_property_present(const struc
+ {
+       bool ret;
++      if (IS_ERR_OR_NULL(fwnode))
++              return false;
++
+       ret = fwnode_call_bool_op(fwnode, property_present, propname);
+-      if (ret == false && !IS_ERR_OR_NULL(fwnode) &&
+-          !IS_ERR_OR_NULL(fwnode->secondary))
+-              ret = fwnode_call_bool_op(fwnode->secondary, property_present,
+-                                       propname);
+-      return ret;
++      if (ret)
++              return ret;
++
++      return fwnode_call_bool_op(fwnode->secondary, property_present, propname);
+ }
+ EXPORT_SYMBOL_GPL(fwnode_property_present);
+@@ -233,15 +235,16 @@ static int fwnode_property_read_int_arra
+ {
+       int ret;
++      if (IS_ERR_OR_NULL(fwnode))
++              return -EINVAL;
++
+       ret = fwnode_call_int_op(fwnode, property_read_int_array, propname,
+                                elem_size, val, nval);
+-      if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
+-          !IS_ERR_OR_NULL(fwnode->secondary))
+-              ret = fwnode_call_int_op(
+-                      fwnode->secondary, property_read_int_array, propname,
+-                      elem_size, val, nval);
++      if (ret != -EINVAL)
++              return ret;
+-      return ret;
++      return fwnode_call_int_op(fwnode->secondary, property_read_int_array, propname,
++                                elem_size, val, nval);
+ }
+ /**
+@@ -372,14 +375,16 @@ int fwnode_property_read_string_array(co
+ {
+       int ret;
++      if (IS_ERR_OR_NULL(fwnode))
++              return -EINVAL;
++
+       ret = fwnode_call_int_op(fwnode, property_read_string_array, propname,
+                                val, nval);
+-      if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
+-          !IS_ERR_OR_NULL(fwnode->secondary))
+-              ret = fwnode_call_int_op(fwnode->secondary,
+-                                       property_read_string_array, propname,
+-                                       val, nval);
+-      return ret;
++      if (ret != -EINVAL)
++              return ret;
++
++      return fwnode_call_int_op(fwnode->secondary, property_read_string_array, propname,
++                                val, nval);
+ }
+ EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
+@@ -481,15 +486,19 @@ int fwnode_property_get_reference_args(c
+ {
+       int ret;
++      if (IS_ERR_OR_NULL(fwnode))
++              return -ENOENT;
++
+       ret = fwnode_call_int_op(fwnode, get_reference_args, prop, nargs_prop,
+                                nargs, index, args);
++      if (ret == 0)
++              return ret;
+-      if (ret < 0 && !IS_ERR_OR_NULL(fwnode) &&
+-          !IS_ERR_OR_NULL(fwnode->secondary))
+-              ret = fwnode_call_int_op(fwnode->secondary, get_reference_args,
+-                                       prop, nargs_prop, nargs, index, args);
++      if (IS_ERR_OR_NULL(fwnode->secondary))
++              return ret;
+-      return ret;
++      return fwnode_call_int_op(fwnode->secondary, get_reference_args, prop, nargs_prop,
++                                nargs, index, args);
+ }
+ EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args);
+@@ -683,12 +692,13 @@ EXPORT_SYMBOL_GPL(fwnode_count_parents);
+ struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode,
+                                           unsigned int depth)
+ {
+-      unsigned int i;
+-
+       fwnode_handle_get(fwnode);
+-      for (i = 0; i < depth && fwnode; i++)
++      do {
++              if (depth-- == 0)
++                      break;
+               fwnode = fwnode_get_next_parent(fwnode);
++      } while (fwnode);
+       return fwnode;
+ }
+@@ -707,17 +717,17 @@ EXPORT_SYMBOL_GPL(fwnode_get_nth_parent)
+ bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor,
+                                 struct fwnode_handle *test_child)
+ {
+-      if (!test_ancestor)
++      if (IS_ERR_OR_NULL(test_ancestor))
+               return false;
+       fwnode_handle_get(test_child);
+-      while (test_child) {
++      do {
+               if (test_child == test_ancestor) {
+                       fwnode_handle_put(test_child);
+                       return true;
+               }
+               test_child = fwnode_get_next_parent(test_child);
+-      }
++      } while (test_child);
+       return false;
+ }
+@@ -746,7 +756,7 @@ fwnode_get_next_available_child_node(con
+ {
+       struct fwnode_handle *next_child = child;
+-      if (!fwnode)
++      if (IS_ERR_OR_NULL(fwnode))
+               return NULL;
+       do {
+@@ -771,16 +781,16 @@ struct fwnode_handle *device_get_next_ch
+       const struct fwnode_handle *fwnode = dev_fwnode(dev);
+       struct fwnode_handle *next;
++      if (IS_ERR_OR_NULL(fwnode))
++              return NULL;
++
+       /* Try to find a child in primary fwnode */
+       next = fwnode_get_next_child_node(fwnode, child);
+       if (next)
+               return next;
+       /* When no more children in primary, continue with secondary */
+-      if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
+-              next = fwnode_get_next_child_node(fwnode->secondary, child);
+-
+-      return next;
++      return fwnode_get_next_child_node(fwnode->secondary, child);
+ }
+ EXPORT_SYMBOL_GPL(device_get_next_child_node);
+@@ -847,6 +857,9 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
+  */
+ bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
+ {
++      if (IS_ERR_OR_NULL(fwnode))
++              return false;
++
+       if (!fwnode_has_op(fwnode, device_is_available))
+               return true;
+@@ -1054,14 +1067,14 @@ fwnode_graph_get_next_endpoint(const str
+               parent = fwnode_graph_get_port_parent(prev);
+       else
+               parent = fwnode;
++      if (IS_ERR_OR_NULL(parent))
++              return NULL;
+       ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev);
++      if (ep)
++              return ep;
+-      if (IS_ERR_OR_NULL(ep) &&
+-          !IS_ERR_OR_NULL(parent) && !IS_ERR_OR_NULL(parent->secondary))
+-              ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL);
+-
+-      return ep;
++      return fwnode_graph_get_next_endpoint(parent->secondary, NULL);
+ }
+ EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
+--- a/include/linux/fwnode.h
++++ b/include/linux/fwnode.h
+@@ -149,12 +149,12 @@ struct fwnode_operations {
+                        struct device *dev);
+ };
+-#define fwnode_has_op(fwnode, op)                             \
+-      ((fwnode) && (fwnode)->ops && (fwnode)->ops->op)
++#define fwnode_has_op(fwnode, op)                                     \
++      (!IS_ERR_OR_NULL(fwnode) && (fwnode)->ops && (fwnode)->ops->op)
++
+ #define fwnode_call_int_op(fwnode, op, ...)                           \
+-      (fwnode ? (fwnode_has_op(fwnode, op) ?                          \
+-                 (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : \
+-       -EINVAL)
++      (fwnode_has_op(fwnode, op) ?                                    \
++       (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : (IS_ERR_OR_NULL(fwnode) ? -EINVAL : -ENXIO))
+ #define fwnode_call_bool_op(fwnode, op, ...)          \
+       (fwnode_has_op(fwnode, op) ?                    \
diff --git a/queue-5.10/device-property-allow-secondary-lookup-in-fwnode_get_next_child_node.patch b/queue-5.10/device-property-allow-secondary-lookup-in-fwnode_get_next_child_node.patch
new file mode 100644 (file)
index 0000000..e064837
--- /dev/null
@@ -0,0 +1,79 @@
+From stable+bounces-226741-greg=kroah.com@vger.kernel.org Tue Mar 17 18:23:31 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 13:19:54 -0400
+Subject: device property: Allow secondary lookup in fwnode_get_next_child_node()
+To: stable@vger.kernel.org
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>, "Rafael J. Wysocki (Intel)" <rafael@kernel.org>, Sakari Ailus <sakari.ailus@linux.intel.com>, Danilo Krummrich <dakr@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317171954.238398-8-sashal@kernel.org>
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 2692c614f8f05929d692b3dbfd3faef1f00fbaf0 ]
+
+When device_get_child_node_count() got split to the fwnode and device
+respective APIs, the fwnode didn't inherit the ability to traverse over
+the secondary fwnode. Hence any user, that switches from device to fwnode
+API misses this feature. In particular, this was revealed by the commit
+1490cbb9dbfd ("device property: Split fwnode_get_child_node_count()")
+that effectively broke the GPIO enumeration on Intel Galileo boards.
+Fix this by moving the secondary lookup from device to fwnode API.
+
+Note, in general no device_*() API should go into the depth of the fwnode
+implementation.
+
+Fixes: 114dbb4fa7c4 ("drivers property: When no children in primary, try secondary")
+Cc: stable@vger.kernel.org
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
+Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Link: https://patch.msgid.link/20260210135822.47335-1-andriy.shevchenko@linux.intel.com
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/property.c |   27 +++++++++++++--------------
+ 1 file changed, 13 insertions(+), 14 deletions(-)
+
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -740,7 +740,18 @@ struct fwnode_handle *
+ fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
+                          struct fwnode_handle *child)
+ {
+-      return fwnode_call_ptr_op(fwnode, get_next_child_node, child);
++      struct fwnode_handle *next;
++
++      if (IS_ERR_OR_NULL(fwnode))
++              return NULL;
++
++      /* Try to find a child in primary fwnode */
++      next = fwnode_call_ptr_op(fwnode, get_next_child_node, child);
++      if (next)
++              return next;
++
++      /* When no more children in primary, continue with secondary */
++      return fwnode_call_ptr_op(fwnode->secondary, get_next_child_node, child);
+ }
+ EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
+@@ -778,19 +789,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_availa
+ struct fwnode_handle *device_get_next_child_node(struct device *dev,
+                                                struct fwnode_handle *child)
+ {
+-      const struct fwnode_handle *fwnode = dev_fwnode(dev);
+-      struct fwnode_handle *next;
+-
+-      if (IS_ERR_OR_NULL(fwnode))
+-              return NULL;
+-
+-      /* Try to find a child in primary fwnode */
+-      next = fwnode_get_next_child_node(fwnode, child);
+-      if (next)
+-              return next;
+-
+-      /* When no more children in primary, continue with secondary */
+-      return fwnode_get_next_child_node(fwnode->secondary, child);
++      return fwnode_get_next_child_node(dev_fwnode(dev), child);
+ }
+ EXPORT_SYMBOL_GPL(device_get_next_child_node);
diff --git a/queue-5.10/device-property-check-fwnode-secondary-in-fwnode_graph_get_next_endpoint.patch b/queue-5.10/device-property-check-fwnode-secondary-in-fwnode_graph_get_next_endpoint.patch
new file mode 100644 (file)
index 0000000..f24a9ae
--- /dev/null
@@ -0,0 +1,59 @@
+From stable+bounces-226737-greg=kroah.com@vger.kernel.org Tue Mar 17 18:51:06 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 13:19:51 -0400
+Subject: device property: Check fwnode->secondary in fwnode_graph_get_next_endpoint()
+To: stable@vger.kernel.org
+Cc: Daniel Scally <djrscally@gmail.com>, Andy Shevchenko <andriy.shevchenko@linux.intel.com>, "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317171954.238398-5-sashal@kernel.org>
+
+From: Daniel Scally <djrscally@gmail.com>
+
+[ Upstream commit b5b41ab6b0c1bb70fe37a0d193006c969e3b5909 ]
+
+Sensor drivers often check for an endpoint to make sure that they're
+connected to a consuming device like a CIO2 during .probe(). Some of
+those endpoints might be in the form of software_nodes assigned as
+a secondary to the device's fwnode_handle. Account for this possibility
+in fwnode_graph_get_next_endpoint() to avoid having to do it in the
+sensor drivers themselves.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/property.c |   21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -1033,7 +1033,26 @@ struct fwnode_handle *
+ fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
+                              struct fwnode_handle *prev)
+ {
+-      return fwnode_call_ptr_op(fwnode, graph_get_next_endpoint, prev);
++      const struct fwnode_handle *parent;
++      struct fwnode_handle *ep;
++
++      /*
++       * If this function is in a loop and the previous iteration returned
++       * an endpoint from fwnode->secondary, then we need to use the secondary
++       * as parent rather than @fwnode.
++       */
++      if (prev)
++              parent = fwnode_graph_get_port_parent(prev);
++      else
++              parent = fwnode;
++
++      ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev);
++
++      if (IS_ERR_OR_NULL(ep) &&
++          !IS_ERR_OR_NULL(parent) && !IS_ERR_OR_NULL(parent->secondary))
++              ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL);
++
++      return ep;
+ }
+ EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
diff --git a/queue-5.10/device-property-check-fwnode-secondary-when-finding-properties.patch b/queue-5.10/device-property-check-fwnode-secondary-when-finding-properties.patch
new file mode 100644 (file)
index 0000000..4298afa
--- /dev/null
@@ -0,0 +1,51 @@
+From sashal@kernel.org Tue Mar 17 18:20:03 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 13:19:52 -0400
+Subject: device property: Check fwnode->secondary when finding properties
+To: stable@vger.kernel.org
+Cc: Daniel Scally <djrscally@gmail.com>, Andy Shevchenko <andriy.shevchenko@linux.intel.com>, Hans de Goede <hdegoede@redhat.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317171954.238398-6-sashal@kernel.org>
+
+From: Daniel Scally <djrscally@gmail.com>
+
+[ Upstream commit c097af1d0a8483b44fa30e86b311991d76b6ae67 ]
+
+fwnode_property_get_reference_args() searches for named properties
+against a fwnode_handle, but these could instead be against the fwnode's
+secondary. If the property isn't found against the primary, check the
+secondary to see if it's there instead.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Link: https://lore.kernel.org/r/20211128232455.39332-1-djrscally@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/property.c |   13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -479,8 +479,17 @@ int fwnode_property_get_reference_args(c
+                                      unsigned int nargs, unsigned int index,
+                                      struct fwnode_reference_args *args)
+ {
+-      return fwnode_call_int_op(fwnode, get_reference_args, prop, nargs_prop,
+-                                nargs, index, args);
++      int ret;
++
++      ret = fwnode_call_int_op(fwnode, get_reference_args, prop, nargs_prop,
++                               nargs, index, args);
++
++      if (ret < 0 && !IS_ERR_OR_NULL(fwnode) &&
++          !IS_ERR_OR_NULL(fwnode->secondary))
++              ret = fwnode_call_int_op(fwnode->secondary, get_reference_args,
++                                       prop, nargs_prop, nargs, index, args);
++
++      return ret;
+ }
+ EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args);
diff --git a/queue-5.10/device-property-retrieve-fwnode-from-of_node-via-accessor.patch b/queue-5.10/device-property-retrieve-fwnode-from-of_node-via-accessor.patch
new file mode 100644 (file)
index 0000000..aa11b53
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-226735-greg=kroah.com@vger.kernel.org Tue Mar 17 18:51:05 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 13:19:49 -0400
+Subject: device property: Retrieve fwnode from of_node via accessor
+To: stable@vger.kernel.org
+Cc: Andy Shevchenko <andy.shevchenko@gmail.com>, "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317171954.238398-3-sashal@kernel.org>
+
+From: Andy Shevchenko <andy.shevchenko@gmail.com>
+
+[ Upstream commit 3cd8015040d7537a6b88e26f36768a90d9247829 ]
+
+OF provides a specific accessor to retrieve fwnode handle.
+Use it instead of direct dereferencing.
+
+Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/property.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -21,7 +21,7 @@
+ struct fwnode_handle *dev_fwnode(const struct device *dev)
+ {
+       return IS_ENABLED(CONFIG_OF) && dev->of_node ?
+-              &dev->of_node->fwnode : dev->fwnode;
++              of_fwnode_handle(dev->of_node) : dev->fwnode;
+ }
+ EXPORT_SYMBOL_GPL(dev_fwnode);
+@@ -763,7 +763,7 @@ struct fwnode_handle *device_get_next_ch
+       struct fwnode_handle *fwnode = NULL, *next;
+       if (dev->of_node)
+-              fwnode = &dev->of_node->fwnode;
++              fwnode = of_fwnode_handle(dev->of_node);
+       else if (adev)
+               fwnode = acpi_fwnode_handle(adev);
diff --git a/queue-5.10/device-property-unify-access-to-of_node.patch b/queue-5.10/device-property-unify-access-to-of_node.patch
new file mode 100644 (file)
index 0000000..33f517e
--- /dev/null
@@ -0,0 +1,111 @@
+From stable+bounces-226736-greg=kroah.com@vger.kernel.org Tue Mar 17 18:50:50 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 13:19:50 -0400
+Subject: device property: Unify access to of_node
+To: stable@vger.kernel.org
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>, "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317171954.238398-4-sashal@kernel.org>
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit fb38f314fbd173e2e9f9f0f2e720a5f4889562da ]
+
+Historically we have a few variants how we access dev->fwnode
+and dev->of_node. Some of the functions during development
+gained different versions of the getters. Unify access to of_node
+and as a side change slightly refactor ACPI specific branches.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/property.c  |   29 +++++++++++++----------------
+ include/linux/property.h |    2 +-
+ 2 files changed, 14 insertions(+), 17 deletions(-)
+
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -759,13 +759,8 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_availa
+ struct fwnode_handle *device_get_next_child_node(struct device *dev,
+                                                struct fwnode_handle *child)
+ {
+-      struct acpi_device *adev = ACPI_COMPANION(dev);
+-      struct fwnode_handle *fwnode = NULL, *next;
+-
+-      if (dev->of_node)
+-              fwnode = of_fwnode_handle(dev->of_node);
+-      else if (adev)
+-              fwnode = acpi_fwnode_handle(adev);
++      const struct fwnode_handle *fwnode = dev_fwnode(dev);
++      struct fwnode_handle *next;
+       /* Try to find a child in primary fwnode */
+       next = fwnode_get_next_child_node(fwnode, child);
+@@ -868,28 +863,31 @@ EXPORT_SYMBOL_GPL(device_get_child_node_
+ bool device_dma_supported(struct device *dev)
+ {
++      const struct fwnode_handle *fwnode = dev_fwnode(dev);
++
+       /* For DT, this is always supported.
+        * For ACPI, this depends on CCA, which
+        * is determined by the acpi_dma_supported().
+        */
+-      if (IS_ENABLED(CONFIG_OF) && dev->of_node)
++      if (is_of_node(fwnode))
+               return true;
+-      return acpi_dma_supported(ACPI_COMPANION(dev));
++      return acpi_dma_supported(to_acpi_device_node(fwnode));
+ }
+ EXPORT_SYMBOL_GPL(device_dma_supported);
+ enum dev_dma_attr device_get_dma_attr(struct device *dev)
+ {
++      const struct fwnode_handle *fwnode = dev_fwnode(dev);
+       enum dev_dma_attr attr = DEV_DMA_NOT_SUPPORTED;
+-      if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+-              if (of_dma_is_coherent(dev->of_node))
++      if (is_of_node(fwnode)) {
++              if (of_dma_is_coherent(to_of_node(fwnode)))
+                       attr = DEV_DMA_COHERENT;
+               else
+                       attr = DEV_DMA_NON_COHERENT;
+       } else
+-              attr = acpi_get_dma_attr(ACPI_COMPANION(dev));
++              attr = acpi_get_dma_attr(to_acpi_device_node(fwnode));
+       return attr;
+ }
+@@ -1007,14 +1005,13 @@ EXPORT_SYMBOL(device_get_mac_address);
+  * Returns Linux IRQ number on success. Other values are determined
+  * accordingly to acpi_/of_ irq_get() operation.
+  */
+-int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index)
++int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index)
+ {
+-      struct device_node *of_node = to_of_node(fwnode);
+       struct resource res;
+       int ret;
+-      if (IS_ENABLED(CONFIG_OF) && of_node)
+-              return of_irq_get(of_node, index);
++      if (is_of_node(fwnode))
++              return of_irq_get(to_of_node(fwnode), index);
+       ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, &res);
+       if (ret)
+--- a/include/linux/property.h
++++ b/include/linux/property.h
+@@ -119,7 +119,7 @@ struct fwnode_handle *device_get_named_c
+ struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode);
+ void fwnode_handle_put(struct fwnode_handle *fwnode);
+-int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index);
++int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index);
+ unsigned int device_get_child_node_count(struct device *dev);
diff --git a/queue-5.10/drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch b/queue-5.10/drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch
new file mode 100644 (file)
index 0000000..b11e023
--- /dev/null
@@ -0,0 +1,237 @@
+From stable+bounces-227793-greg=kroah.com@vger.kernel.org Sat Mar 21 21:50:04 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 21 Mar 2026 16:49:57 -0400
+Subject: drm: Fix use-after-free on framebuffers and property blobs when calling drm_dev_unplug
+To: stable@vger.kernel.org
+Cc: "Maarten Lankhorst" <dev@lankhorst.se>, "Thomas Hellström" <thomas.hellstrom@linux.intel.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260321204957.594424-1-sashal@kernel.org>
+
+From: Maarten Lankhorst <dev@lankhorst.se>
+
+[ Upstream commit 6bee098b91417654703e17eb5c1822c6dfd0c01d ]
+
+When trying to do a rather aggressive test of igt's "xe_module_load
+--r reload" with a full desktop environment and game running I noticed
+a few OOPSes when dereferencing freed pointers, related to
+framebuffers and property blobs after the compositor exits.
+
+Solve this by guarding the freeing in drm_file with drm_dev_enter/exit,
+and immediately put the references from struct drm_file objects during
+drm_dev_unplug().
+
+Related warnings for framebuffers on the subtest:
+[  739.713076] ------------[ cut here ]------------
+               WARN_ON(!list_empty(&dev->mode_config.fb_list))
+[  739.713079] WARNING: drivers/gpu/drm/drm_mode_config.c:584 at drm_mode_config_cleanup+0x30b/0x320 [drm], CPU#12: xe_module_load/13145
+....
+[  739.713328] Call Trace:
+[  739.713330]  <TASK>
+[  739.713335]  ? intel_pmdemand_destroy_state+0x11/0x20 [xe]
+[  739.713574]  ? intel_atomic_global_obj_cleanup+0xe4/0x1a0 [xe]
+[  739.713794]  intel_display_driver_remove_noirq+0x51/0xb0 [xe]
+[  739.714041]  xe_display_fini_early+0x33/0x50 [xe]
+[  739.714284]  devm_action_release+0xf/0x20
+[  739.714294]  devres_release_all+0xad/0xf0
+[  739.714301]  device_unbind_cleanup+0x12/0xa0
+[  739.714305]  device_release_driver_internal+0x1b7/0x210
+[  739.714311]  device_driver_detach+0x14/0x20
+[  739.714315]  unbind_store+0xa6/0xb0
+[  739.714319]  drv_attr_store+0x21/0x30
+[  739.714322]  sysfs_kf_write+0x48/0x60
+[  739.714328]  kernfs_fop_write_iter+0x16b/0x240
+[  739.714333]  vfs_write+0x266/0x520
+[  739.714341]  ksys_write+0x72/0xe0
+[  739.714345]  __x64_sys_write+0x19/0x20
+[  739.714347]  x64_sys_call+0xa15/0xa30
+[  739.714355]  do_syscall_64+0xd8/0xab0
+[  739.714361]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+
+and
+
+[  739.714459] ------------[ cut here ]------------
+[  739.714461] xe 0000:67:00.0: [drm] drm_WARN_ON(!list_empty(&fb->filp_head))
+[  739.714464] WARNING: drivers/gpu/drm/drm_framebuffer.c:833 at drm_framebuffer_free+0x6c/0x90 [drm], CPU#12: xe_module_load/13145
+[  739.714715] RIP: 0010:drm_framebuffer_free+0x7a/0x90 [drm]
+...
+[  739.714869] Call Trace:
+[  739.714871]  <TASK>
+[  739.714876]  drm_mode_config_cleanup+0x26a/0x320 [drm]
+[  739.714998]  ? __drm_printfn_seq_file+0x20/0x20 [drm]
+[  739.715115]  ? drm_mode_config_cleanup+0x207/0x320 [drm]
+[  739.715235]  intel_display_driver_remove_noirq+0x51/0xb0 [xe]
+[  739.715576]  xe_display_fini_early+0x33/0x50 [xe]
+[  739.715821]  devm_action_release+0xf/0x20
+[  739.715828]  devres_release_all+0xad/0xf0
+[  739.715843]  device_unbind_cleanup+0x12/0xa0
+[  739.715850]  device_release_driver_internal+0x1b7/0x210
+[  739.715856]  device_driver_detach+0x14/0x20
+[  739.715860]  unbind_store+0xa6/0xb0
+[  739.715865]  drv_attr_store+0x21/0x30
+[  739.715868]  sysfs_kf_write+0x48/0x60
+[  739.715873]  kernfs_fop_write_iter+0x16b/0x240
+[  739.715878]  vfs_write+0x266/0x520
+[  739.715886]  ksys_write+0x72/0xe0
+[  739.715890]  __x64_sys_write+0x19/0x20
+[  739.715893]  x64_sys_call+0xa15/0xa30
+[  739.715900]  do_syscall_64+0xd8/0xab0
+[  739.715905]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+
+and then finally file close blows up:
+
+[  743.186530] Oops: general protection fault, probably for non-canonical address 0xdead000000000122: 0000 [#1] SMP
+[  743.186535] CPU: 3 UID: 1000 PID: 3453 Comm: kwin_wayland Tainted: G        W           7.0.0-rc1-valkyria+ #110 PREEMPT_{RT,(lazy)}
+[  743.186537] Tainted: [W]=WARN
+[  743.186538] Hardware name: Gigabyte Technology Co., Ltd. X299 AORUS Gaming 3/X299 AORUS Gaming 3-CF, BIOS F8n 12/06/2021
+[  743.186539] RIP: 0010:drm_framebuffer_cleanup+0x55/0xc0 [drm]
+[  743.186588] Code: d8 72 73 0f b6 42 05 ff c3 39 c3 72 e8 49 8d bd 50 07 00 00 31 f6 e8 3a 80 d3 e1 49 8b 44 24 10 49 8d 7c 24 08 49 8b 54 24 08 <48> 3b 38 0f 85 95 7f 02 00 48 3b 7a 08 0f 85 8b 7f 02 00 48 89 42
+[  743.186589] RSP: 0018:ffffc900085e3cf8 EFLAGS: 00010202
+[  743.186591] RAX: dead000000000122 RBX: 0000000000000001 RCX: ffffffff8217ed03
+[  743.186592] RDX: dead000000000100 RSI: 0000000000000000 RDI: ffff88814675ba08
+[  743.186593] RBP: ffffc900085e3d10 R08: 0000000000000000 R09: 0000000000000000
+[  743.186593] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88814675ba00
+[  743.186594] R13: ffff88810d778000 R14: ffff888119f6dca0 R15: ffff88810c660bb0
+[  743.186595] FS:  00007ff377d21280(0000) GS:ffff888cec3f8000(0000) knlGS:0000000000000000
+[  743.186596] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[  743.186596] CR2: 000055690b55e000 CR3: 0000000113586003 CR4: 00000000003706f0
+[  743.186597] Call Trace:
+[  743.186598]  <TASK>
+[  743.186603]  intel_user_framebuffer_destroy+0x12/0x90 [xe]
+[  743.186722]  drm_framebuffer_free+0x3a/0x90 [drm]
+[  743.186750]  ? trace_hardirqs_on+0x5f/0x120
+[  743.186754]  drm_mode_object_put+0x51/0x70 [drm]
+[  743.186786]  drm_fb_release+0x105/0x190 [drm]
+[  743.186812]  ? rt_mutex_slowunlock+0x3aa/0x410
+[  743.186817]  ? rt_spin_lock+0xea/0x1b0
+[  743.186819]  drm_file_free+0x1e0/0x2c0 [drm]
+[  743.186843]  drm_release_noglobal+0x91/0xf0 [drm]
+[  743.186865]  __fput+0x100/0x2e0
+[  743.186869]  fput_close_sync+0x40/0xa0
+[  743.186870]  __x64_sys_close+0x3e/0x80
+[  743.186873]  x64_sys_call+0xa07/0xa30
+[  743.186879]  do_syscall_64+0xd8/0xab0
+[  743.186881]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+[  743.186882] RIP: 0033:0x7ff37e567732
+[  743.186884] Code: 08 0f 85 a1 38 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 55 bf 01 00
+[  743.186885] RSP: 002b:00007ffc818169a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
+[  743.186886] RAX: ffffffffffffffda RBX: 00007ffc81816a30 RCX: 00007ff37e567732
+[  743.186887] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000012
+[  743.186888] RBP: 00007ffc818169d0 R08: 0000000000000000 R09: 0000000000000000
+[  743.186889] R10: 0000000000000000 R11: 0000000000000246 R12: 000055d60a7996e0
+[  743.186889] R13: 00007ffc81816a90 R14: 00007ffc81816a90 R15: 000055d60a782a30
+[  743.186892]  </TASK>
+[  743.186893] Modules linked in: rfcomm snd_hrtimer xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp xt_addrtype nft_compat x_tables nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables overlay cfg80211 bnep mtd_intel_dg snd_hda_codec_intelhdmi mtd snd_hda_codec_hdmi nls_utf8 mxm_wmi intel_wmi_thunderbolt gigabyte_wmi wmi_bmof xe drm_gpuvm drm_gpusvm_helper i2c_algo_bit drm_buddy drm_ttm_helper ttm video drm_suballoc_helper gpu_sched drm_client_lib drm_exec drm_display_helper cec drm_kunit_helpers drm_kms_helper kunit x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_alc882 snd_hda_codec_realtek_lib snd_hda_codec_generic snd_hda_intel snd_soc_avs snd_soc_hda_codec snd_hda_ext_core snd_hda_codec snd_hwdep snd_hda_core snd_intel_dspcfg snd_soc_core snd_compress ac97_bus snd_pcm snd_seq snd_seq_device snd_timer i2c_i801 i2c_mux snd i2c_smbus btusb btrtl btbcm btmtk btintel bluetooth ecdh_generic rfkill ecc mei_me mei ioatdma dca wmi nfsd drm i2c_dev fuse nfnetlink
+[  743.186938] ---[ end trace 0000000000000000 ]---
+
+And for property blobs:
+
+void drm_mode_config_cleanup(struct drm_device *dev)
+{
+...
+       list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
+                                head_global) {
+               drm_property_blob_put(blob);
+       }
+
+Resulting in:
+
+[  371.072940] BUG: unable to handle page fault for address: 000001ffffffffff
+[  371.072944] #PF: supervisor read access in kernel mode
+[  371.072945] #PF: error_code(0x0000) - not-present page
+[  371.072947] PGD 0 P4D 0
+[  371.072950] Oops: Oops: 0000 [#1] SMP
+[  371.072953] CPU: 0 UID: 1000 PID: 3693 Comm: kwin_wayland Not tainted 7.0.0-rc1-valkyria+ #111 PREEMPT_{RT,(lazy)}
+[  371.072956] Hardware name: Gigabyte Technology Co., Ltd. X299 AORUS Gaming 3/X299 AORUS Gaming 3-CF, BIOS F8n 12/06/2021
+[  371.072957] RIP: 0010:drm_property_destroy_user_blobs+0x3b/0x90 [drm]
+[  371.073019] Code: 00 00 48 83 ec 10 48 8b 86 30 01 00 00 48 39 c3 74 59 48 89 c2 48 8d 48 c8 48 8b 00 4c 8d 60 c8 eb 04 4c 8d 60 c8 48 8b 71 40 <48> 39 16 0f 85 39 32 01 00 48 3b 50 08 0f 85 2f 32 01 00 48 89 70
+[  371.073021] RSP: 0018:ffffc90006a73de8 EFLAGS: 00010293
+[  371.073022] RAX: 000001ffffffffff RBX: ffff888118a1a930 RCX: ffff8881b92355c0
+[  371.073024] RDX: ffff8881b92355f8 RSI: 000001ffffffffff RDI: ffff888118be4000
+[  371.073025] RBP: ffffc90006a73e08 R08: ffff8881009b7300 R09: ffff888cecc5b000
+[  371.073026] R10: ffffc90006a73e90 R11: 0000000000000002 R12: 000001ffffffffc7
+[  371.073027] R13: ffff888118a1a980 R14: ffff88810b366d20 R15: ffff888118a1a970
+[  371.073028] FS:  00007f1faccbb280(0000) GS:ffff888cec2db000(0000) knlGS:0000000000000000
+[  371.073029] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[  371.073030] CR2: 000001ffffffffff CR3: 000000010655c001 CR4: 00000000003706f0
+[  371.073031] Call Trace:
+[  371.073033]  <TASK>
+[  371.073036]  drm_file_free+0x1df/0x2a0 [drm]
+[  371.073077]  drm_release_noglobal+0x7a/0xe0 [drm]
+[  371.073113]  __fput+0xe2/0x2b0
+[  371.073118]  fput_close_sync+0x40/0xa0
+[  371.073119]  __x64_sys_close+0x3e/0x80
+[  371.073122]  x64_sys_call+0xa07/0xa30
+[  371.073126]  do_syscall_64+0xc0/0x840
+[  371.073130]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+[  371.073132] RIP: 0033:0x7f1fb3501732
+[  371.073133] Code: 08 0f 85 a1 38 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 55 bf 01 00
+[  371.073135] RSP: 002b:00007ffe8e6f0278 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
+[  371.073136] RAX: ffffffffffffffda RBX: 00007ffe8e6f0300 RCX: 00007f1fb3501732
+[  371.073137] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000012
+[  371.073138] RBP: 00007ffe8e6f02a0 R08: 0000000000000000 R09: 0000000000000000
+[  371.073139] R10: 0000000000000000 R11: 0000000000000246 R12: 00005585ba46eea0
+[  371.073140] R13: 00007ffe8e6f0360 R14: 00007ffe8e6f0360 R15: 00005585ba458a30
+[  371.073143]  </TASK>
+[  371.073144] Modules linked in: rfcomm snd_hrtimer xt_addrtype xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp nft_compat x_tables nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables overlay cfg80211 bnep snd_hda_codec_intelhdmi snd_hda_codec_hdmi mtd_intel_dg mtd nls_utf8 wmi_bmof mxm_wmi gigabyte_wmi intel_wmi_thunderbolt xe drm_gpuvm drm_gpusvm_helper i2c_algo_bit drm_buddy drm_ttm_helper ttm video drm_suballoc_helper gpu_sched drm_client_lib drm_exec drm_display_helper cec drm_kunit_helpers drm_kms_helper kunit x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_alc882 snd_hda_codec_realtek_lib snd_hda_codec_generic snd_hda_intel snd_soc_avs snd_soc_hda_codec snd_hda_ext_core snd_hda_codec snd_hwdep snd_hda_core snd_intel_dspcfg snd_soc_core snd_compress ac97_bus snd_pcm snd_seq snd_seq_device snd_timer i2c_i801 btusb i2c_mux i2c_smbus btrtl snd btbcm btmtk btintel bluetooth ecdh_generic rfkill ecc mei_me mei ioatdma dca wmi nfsd drm i2c_dev fuse nfnetlink
+[  371.073198] CR2: 000001ffffffffff
+[  371.073199] ---[ end trace 0000000000000000 ]---
+
+Add a guard around file close, and ensure the warnings from drm_mode_config
+do not trigger. Fix those by allowing an open reference to the file descriptor
+and cleaning up the file linked list entry in drm_mode_config_cleanup().
+
+Cc: <stable@vger.kernel.org> # v4.18+
+Fixes: bee330f3d672 ("drm: Use srcu to protect drm_device.unplugged")
+Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Link: https://patch.msgid.link/20260313151728.14990-4-dev@lankhorst.se
+Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
+[ adapted drm_dbg_printer(dev, DRM_UT_KMS, ...) call to older drm_debug_printer(...) API ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_file.c        |    5 ++++-
+ drivers/gpu/drm/drm_mode_config.c |    9 ++++++---
+ 2 files changed, 10 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/drm_file.c
++++ b/drivers/gpu/drm/drm_file.c
+@@ -248,6 +248,7 @@ static void drm_events_release(struct dr
+ void drm_file_free(struct drm_file *file)
+ {
+       struct drm_device *dev;
++      int idx;
+       if (!file)
+               return;
+@@ -271,9 +272,11 @@ void drm_file_free(struct drm_file *file
+       drm_events_release(file);
+-      if (drm_core_check_feature(dev, DRIVER_MODESET)) {
++      if (drm_core_check_feature(dev, DRIVER_MODESET) &&
++          drm_dev_enter(dev, &idx)) {
+               drm_fb_release(file);
+               drm_property_destroy_user_blobs(dev, file);
++              drm_dev_exit(idx);
+       }
+       if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
+--- a/drivers/gpu/drm/drm_mode_config.c
++++ b/drivers/gpu/drm/drm_mode_config.c
+@@ -543,10 +543,13 @@ void drm_mode_config_cleanup(struct drm_
+        */
+       WARN_ON(!list_empty(&dev->mode_config.fb_list));
+       list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
+-              struct drm_printer p = drm_debug_printer("[leaked fb]");
++              if (list_empty(&fb->filp_head) || drm_framebuffer_read_refcount(fb) > 1) {
++                      struct drm_printer p = drm_debug_printer("[leaked fb]");
+-              drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
+-              drm_framebuffer_print_info(&p, 1, fb);
++                      drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
++                      drm_framebuffer_print_info(&p, 1, fb);
++              }
++              list_del_init(&fb->filp_head);
+               drm_framebuffer_free(&fb->base.refcount);
+       }
diff --git a/queue-5.10/ext4-fix-iloc.bh-leak-in-ext4_fc_replay_inode-error-paths.patch b/queue-5.10/ext4-fix-iloc.bh-leak-in-ext4_fc_replay_inode-error-paths.patch
new file mode 100644 (file)
index 0000000..11e4b3d
--- /dev/null
@@ -0,0 +1,88 @@
+From stable+bounces-233181-greg=kroah.com@vger.kernel.org Fri Apr  3 13:58:38 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Apr 2026 07:58:31 -0400
+Subject: ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths
+To: stable@vger.kernel.org
+Cc: Baokun Li <libaokun@linux.alibaba.com>, Joseph Qi <joseph.qi@linux.alibaba.com>, Zhang Yi <yi.zhang@huawei.com>, Jan Kara <jack@suse.cz>, Theodore Ts'o <tytso@mit.edu>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260403115831.2109038-1-sashal@kernel.org>
+
+From: Baokun Li <libaokun@linux.alibaba.com>
+
+[ Upstream commit ec0a7500d8eace5b4f305fa0c594dd148f0e8d29 ]
+
+During code review, Joseph found that ext4_fc_replay_inode() calls
+ext4_get_fc_inode_loc() to get the inode location, which holds a
+reference to iloc.bh that must be released via brelse().
+
+However, several error paths jump to the 'out' label without
+releasing iloc.bh:
+
+ - ext4_handle_dirty_metadata() failure
+ - sync_dirty_buffer() failure
+ - ext4_mark_inode_used() failure
+ - ext4_iget() failure
+
+Fix this by introducing an 'out_brelse' label placed just before
+the existing 'out' label to ensure iloc.bh is always released.
+
+Additionally, make ext4_fc_replay_inode() propagate errors
+properly instead of always returning 0.
+
+Reported-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Fixes: 8016e29f4362 ("ext4: fast commit recovery path")
+Signed-off-by: Baokun Li <libaokun@linux.alibaba.com>
+Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20260323060836.3452660-1-libaokun@linux.alibaba.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c |   13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -1480,19 +1480,21 @@ static int ext4_fc_replay_inode(struct s
+       /* Immediately update the inode on disk. */
+       ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
+       if (ret)
+-              goto out;
++              goto out_brelse;
+       ret = sync_dirty_buffer(iloc.bh);
+       if (ret)
+-              goto out;
++              goto out_brelse;
+       ret = ext4_mark_inode_used(sb, ino);
+       if (ret)
+-              goto out;
++              goto out_brelse;
+       /* Given that we just wrote the inode on disk, this SHOULD succeed. */
+       inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
+       if (IS_ERR(inode)) {
+               jbd_debug(1, "Inode not found.");
+-              return -EFSCORRUPTED;
++              inode = NULL;
++              ret = -EFSCORRUPTED;
++              goto out_brelse;
+       }
+       /*
+@@ -1508,13 +1510,14 @@ static int ext4_fc_replay_inode(struct s
+       ext4_inode_csum_set(inode, ext4_raw_inode(&iloc), EXT4_I(inode));
+       ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
+       sync_dirty_buffer(iloc.bh);
++out_brelse:
+       brelse(iloc.bh);
+ out:
+       iput(inode);
+       if (!ret)
+               blkdev_issue_flush(sb->s_bdev, GFP_KERNEL);
+-      return 0;
++      return ret;
+ }
+ /*
diff --git a/queue-5.10/ext4-fix-the-might_sleep-warnings-in-kvfree.patch b/queue-5.10/ext4-fix-the-might_sleep-warnings-in-kvfree.patch
new file mode 100644 (file)
index 0000000..4196d1a
--- /dev/null
@@ -0,0 +1,164 @@
+From stable+bounces-233084-greg=kroah.com@vger.kernel.org Thu Apr  2 19:46:55 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  2 Apr 2026 13:40:37 -0400
+Subject: ext4: fix the might_sleep() warnings in kvfree()
+To: stable@vger.kernel.org
+Cc: Zqiang <qiang.zhang@linux.dev>, Baokun Li <libaokun@linux.alibaba.com>, Theodore Ts'o <tytso@mit.edu>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260402174037.1571365-1-sashal@kernel.org>
+
+From: Zqiang <qiang.zhang@linux.dev>
+
+[ Upstream commit 496bb99b7e66f48b178126626f47e9ba79e2d0fa ]
+
+Use the kvfree() in the RCU read critical section can trigger
+the following warnings:
+
+EXT4-fs (vdb): unmounting filesystem cd983e5b-3c83-4f5a-a136-17b00eb9d018.
+
+WARNING: suspicious RCU usage
+
+./include/linux/rcupdate.h:409 Illegal context switch in RCU read-side critical section!
+
+other info that might help us debug this:
+
+rcu_scheduler_active = 2, debug_locks = 1
+
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xbb/0xd0
+ dump_stack+0x14/0x20
+ lockdep_rcu_suspicious+0x15a/0x1b0
+ __might_resched+0x375/0x4d0
+ ? put_object.part.0+0x2c/0x50
+ __might_sleep+0x108/0x160
+ vfree+0x58/0x910
+ ? ext4_group_desc_free+0x27/0x270
+ kvfree+0x23/0x40
+ ext4_group_desc_free+0x111/0x270
+ ext4_put_super+0x3c8/0xd40
+ generic_shutdown_super+0x14c/0x4a0
+ ? __pfx_shrinker_free+0x10/0x10
+ kill_block_super+0x40/0x90
+ ext4_kill_sb+0x6d/0xb0
+ deactivate_locked_super+0xb4/0x180
+ deactivate_super+0x7e/0xa0
+ cleanup_mnt+0x296/0x3e0
+ __cleanup_mnt+0x16/0x20
+ task_work_run+0x157/0x250
+ ? __pfx_task_work_run+0x10/0x10
+ ? exit_to_user_mode_loop+0x6a/0x550
+ exit_to_user_mode_loop+0x102/0x550
+ do_syscall_64+0x44a/0x500
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+ </TASK>
+
+BUG: sleeping function called from invalid context at mm/vmalloc.c:3441
+in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 556, name: umount
+preempt_count: 1, expected: 0
+CPU: 3 UID: 0 PID: 556 Comm: umount
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xbb/0xd0
+ dump_stack+0x14/0x20
+ __might_resched+0x275/0x4d0
+ ? put_object.part.0+0x2c/0x50
+ __might_sleep+0x108/0x160
+ vfree+0x58/0x910
+ ? ext4_group_desc_free+0x27/0x270
+ kvfree+0x23/0x40
+ ext4_group_desc_free+0x111/0x270
+ ext4_put_super+0x3c8/0xd40
+ generic_shutdown_super+0x14c/0x4a0
+ ? __pfx_shrinker_free+0x10/0x10
+ kill_block_super+0x40/0x90
+ ext4_kill_sb+0x6d/0xb0
+ deactivate_locked_super+0xb4/0x180
+ deactivate_super+0x7e/0xa0
+ cleanup_mnt+0x296/0x3e0
+ __cleanup_mnt+0x16/0x20
+ task_work_run+0x157/0x250
+ ? __pfx_task_work_run+0x10/0x10
+ ? exit_to_user_mode_loop+0x6a/0x550
+ exit_to_user_mode_loop+0x102/0x550
+ do_syscall_64+0x44a/0x500
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+The above scenarios occur in initialization failures and teardown
+paths, there are no parallel operations on the resources released
+by kvfree(), this commit therefore remove rcu_read_lock/unlock() and
+use rcu_access_pointer() instead of rcu_dereference() operations.
+
+Fixes: 7c990728b99e ("ext4: fix potential race between s_flex_groups online resizing and access")
+Fixes: df3da4ea5a0f ("ext4: fix potential race between s_group_info online resizing and access")
+Signed-off-by: Zqiang <qiang.zhang@linux.dev>
+Reviewed-by: Baokun Li <libaokun@linux.alibaba.com>
+Link: https://patch.msgid.link/20260319094545.19291-1-qiang.zhang@linux.dev
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+[ adapted inline rcu_read_lock/rcu_dereference/rcu_read_unlock removal ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/mballoc.c |   10 +++-------
+ fs/ext4/super.c   |    6 ++----
+ 2 files changed, 5 insertions(+), 11 deletions(-)
+
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2894,9 +2894,7 @@ err_freebuddy:
+       rcu_read_unlock();
+       iput(sbi->s_buddy_cache);
+ err_freesgi:
+-      rcu_read_lock();
+-      kvfree(rcu_dereference(sbi->s_group_info));
+-      rcu_read_unlock();
++      kvfree(rcu_access_pointer(sbi->s_group_info));
+       return -ENOMEM;
+ }
+@@ -3088,7 +3086,8 @@ int ext4_mb_release(struct super_block *
+       struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits);
+       int count;
+-      if (sbi->s_group_info) {
++      group_info = rcu_access_pointer(sbi->s_group_info);
++      if (group_info) {
+               for (i = 0; i < ngroups; i++) {
+                       cond_resched();
+                       grinfo = ext4_get_group_info(sb, i);
+@@ -3106,12 +3105,9 @@ int ext4_mb_release(struct super_block *
+               num_meta_group_infos = (ngroups +
+                               EXT4_DESC_PER_BLOCK(sb) - 1) >>
+                       EXT4_DESC_PER_BLOCK_BITS(sb);
+-              rcu_read_lock();
+-              group_info = rcu_dereference(sbi->s_group_info);
+               for (i = 0; i < num_meta_group_infos; i++)
+                       kfree(group_info[i]);
+               kvfree(group_info);
+-              rcu_read_unlock();
+       }
+       kfree(sbi->s_mb_offsets);
+       kfree(sbi->s_mb_maxs);
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1207,18 +1207,16 @@ static void ext4_put_super(struct super_
+       if (!sb_rdonly(sb))
+               ext4_commit_super(sb, 1);
+-      rcu_read_lock();
+-      group_desc = rcu_dereference(sbi->s_group_desc);
++      group_desc = rcu_access_pointer(sbi->s_group_desc);
+       for (i = 0; i < sbi->s_gdb_count; i++)
+               brelse(group_desc[i]);
+       kvfree(group_desc);
+-      flex_groups = rcu_dereference(sbi->s_flex_groups);
++      flex_groups = rcu_access_pointer(sbi->s_flex_groups);
+       if (flex_groups) {
+               for (i = 0; i < sbi->s_flex_groups_allocated; i++)
+                       kvfree(flex_groups[i]);
+               kvfree(flex_groups);
+       }
+-      rcu_read_unlock();
+       percpu_counter_destroy(&sbi->s_freeclusters_counter);
+       percpu_counter_destroy(&sbi->s_freeinodes_counter);
+       percpu_counter_destroy(&sbi->s_dirs_counter);
diff --git a/queue-5.10/ext4-publish-jinode-after-initialization.patch b/queue-5.10/ext4-publish-jinode-after-initialization.patch
new file mode 100644 (file)
index 0000000..456de0c
--- /dev/null
@@ -0,0 +1,152 @@
+From stable+bounces-233178-greg=kroah.com@vger.kernel.org Fri Apr  3 13:49:14 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Apr 2026 07:49:07 -0400
+Subject: ext4: publish jinode after initialization
+To: stable@vger.kernel.org
+Cc: Li Chen <me@linux.beauty>, Jan Kara <jack@suse.cz>, Theodore Ts'o <tytso@mit.edu>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260403114907.2051129-1-sashal@kernel.org>
+
+From: Li Chen <me@linux.beauty>
+
+[ Upstream commit 1aec30021edd410b986c156f195f3d23959a9d11 ]
+
+ext4_inode_attach_jinode() publishes ei->jinode to concurrent users.
+It used to set ei->jinode before jbd2_journal_init_jbd_inode(),
+allowing a reader to observe a non-NULL jinode with i_vfs_inode
+still unset.
+
+The fast commit flush path can then pass this jinode to
+jbd2_wait_inode_data(), which dereferences i_vfs_inode->i_mapping and
+may crash.
+
+Below is the crash I observe:
+```
+BUG: unable to handle page fault for address: 000000010beb47f4
+PGD 110e51067 P4D 110e51067 PUD 0
+Oops: Oops: 0000 [#1] SMP NOPTI
+CPU: 1 UID: 0 PID: 4850 Comm: fc_fsync_bench_ Not tainted 6.18.0-00764-g795a690c06a5 #1 PREEMPT(voluntary)
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.17.0-2-2 04/01/2014
+RIP: 0010:xas_find_marked+0x3d/0x2e0
+Code: e0 03 48 83 f8 02 0f 84 f0 01 00 00 48 8b 47 08 48 89 c3 48 39 c6 0f 82 fd 01 00 00 48 85 c9 74 3d 48 83 f9 03 77 63 4c 8b 0f <49> 8b 71 08 48 c7 47 18 00 00 00 00 48 89 f1 83 e1 03 48 83 f9 02
+RSP: 0018:ffffbbee806e7bf0 EFLAGS: 00010246
+RAX: 000000000010beb4 RBX: 000000000010beb4 RCX: 0000000000000003
+RDX: 0000000000000001 RSI: 0000002000300000 RDI: ffffbbee806e7c10
+RBP: 0000000000000001 R08: 0000002000300000 R09: 000000010beb47ec
+R10: ffff9ea494590090 R11: 0000000000000000 R12: 0000002000300000
+R13: ffffbbee806e7c90 R14: ffff9ea494513788 R15: ffffbbee806e7c88
+FS: 00007fc2f9e3e6c0(0000) GS:ffff9ea6b1444000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 000000010beb47f4 CR3: 0000000119ac5000 CR4: 0000000000750ef0
+PKRU: 55555554
+Call Trace:
+<TASK>
+filemap_get_folios_tag+0x87/0x2a0
+__filemap_fdatawait_range+0x5f/0xd0
+? srso_alias_return_thunk+0x5/0xfbef5
+? __schedule+0x3e7/0x10c0
+? srso_alias_return_thunk+0x5/0xfbef5
+? srso_alias_return_thunk+0x5/0xfbef5
+? srso_alias_return_thunk+0x5/0xfbef5
+? preempt_count_sub+0x5f/0x80
+? srso_alias_return_thunk+0x5/0xfbef5
+? cap_safe_nice+0x37/0x70
+? srso_alias_return_thunk+0x5/0xfbef5
+? preempt_count_sub+0x5f/0x80
+? srso_alias_return_thunk+0x5/0xfbef5
+filemap_fdatawait_range_keep_errors+0x12/0x40
+ext4_fc_commit+0x697/0x8b0
+? ext4_file_write_iter+0x64b/0x950
+? srso_alias_return_thunk+0x5/0xfbef5
+? preempt_count_sub+0x5f/0x80
+? srso_alias_return_thunk+0x5/0xfbef5
+? vfs_write+0x356/0x480
+? srso_alias_return_thunk+0x5/0xfbef5
+? preempt_count_sub+0x5f/0x80
+ext4_sync_file+0xf7/0x370
+do_fsync+0x3b/0x80
+? syscall_trace_enter+0x108/0x1d0
+__x64_sys_fdatasync+0x16/0x20
+do_syscall_64+0x62/0x2c0
+entry_SYSCALL_64_after_hwframe+0x76/0x7e
+...
+```
+
+Fix this by initializing the jbd2_inode first.
+Use smp_wmb() and WRITE_ONCE() to publish ei->jinode after
+initialization. Readers use READ_ONCE() to fetch the pointer.
+
+Fixes: a361293f5fede ("jbd2: Fix oops in jbd2_journal_file_inode()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Li Chen <me@linux.beauty>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20260225082617.147957-1-me@linux.beauty
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+[ adapted READ_ONCE(jinode) wrapping to split ext4_fc_submit_inode_data_all() and ext4_fc_wait_inode_data_all() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c |    4 ++--
+ fs/ext4/inode.c       |   15 +++++++++++----
+ 2 files changed, 13 insertions(+), 6 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -902,7 +902,7 @@ static int ext4_fc_submit_inode_data_all
+                       finish_wait(&ei->i_fc_wait, &wait);
+               }
+               spin_unlock(&sbi->s_fc_lock);
+-              ret = jbd2_submit_inode_data(ei->jinode);
++              ret = jbd2_submit_inode_data(READ_ONCE(ei->jinode));
+               if (ret)
+                       return ret;
+               spin_lock(&sbi->s_fc_lock);
+@@ -927,7 +927,7 @@ static int ext4_fc_wait_inode_data_all(j
+                       continue;
+               spin_unlock(&sbi->s_fc_lock);
+-              ret = jbd2_wait_inode_data(journal, pos->jinode);
++              ret = jbd2_wait_inode_data(journal, READ_ONCE(pos->jinode));
+               if (ret)
+                       return ret;
+               spin_lock(&sbi->s_fc_lock);
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -121,6 +121,8 @@ void ext4_inode_csum_set(struct inode *i
+ static inline int ext4_begin_ordered_truncate(struct inode *inode,
+                                             loff_t new_size)
+ {
++      struct jbd2_inode *jinode = READ_ONCE(EXT4_I(inode)->jinode);
++
+       trace_ext4_begin_ordered_truncate(inode, new_size);
+       /*
+        * If jinode is zero, then we never opened the file for
+@@ -128,10 +130,10 @@ static inline int ext4_begin_ordered_tru
+        * jbd2_journal_begin_ordered_truncate() since there's no
+        * outstanding writes we need to flush.
+        */
+-      if (!EXT4_I(inode)->jinode)
++      if (!jinode)
+               return 0;
+       return jbd2_journal_begin_ordered_truncate(EXT4_JOURNAL(inode),
+-                                                 EXT4_I(inode)->jinode,
++                                                 jinode,
+                                                  new_size);
+ }
+@@ -4231,8 +4233,13 @@ int ext4_inode_attach_jinode(struct inod
+                       spin_unlock(&inode->i_lock);
+                       return -ENOMEM;
+               }
+-              ei->jinode = jinode;
+-              jbd2_journal_init_jbd_inode(ei->jinode, inode);
++              jbd2_journal_init_jbd_inode(jinode, inode);
++              /*
++               * Publish ->jinode only after it is fully initialized so that
++               * readers never observe a partially initialized jbd2_inode.
++               */
++              smp_wmb();
++              WRITE_ONCE(ei->jinode, jinode);
+               jinode = NULL;
+       }
+       spin_unlock(&inode->i_lock);
diff --git a/queue-5.10/media-device-property-return-true-in-fwnode_device_is_available-for-null-ops.patch b/queue-5.10/media-device-property-return-true-in-fwnode_device_is_available-for-null-ops.patch
new file mode 100644 (file)
index 0000000..569e45a
--- /dev/null
@@ -0,0 +1,52 @@
+From sashal@kernel.org Tue Mar 17 18:19:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 13:19:48 -0400
+Subject: media: device property: Return true in fwnode_device_is_available for NULL ops
+To: stable@vger.kernel.org
+Cc: Daniel Scally <djrscally@gmail.com>, Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Andy Shevchenko <andriy.shevchenko@linux.intel.com>, Heikki Krogerus <heikki.krogerus@linux.intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, Mauro Carvalho Chehab <mchehab+huawei@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317171954.238398-2-sashal@kernel.org>
+
+From: Daniel Scally <djrscally@gmail.com>
+
+[ Upstream commit 5273382d03763277aaf8c6a2d6088e2afaee0cf0 ]
+
+Some types of fwnode_handle do not implement the device_is_available()
+check, such as those created by software_nodes. There isn't really a
+meaningful way to check for the availability of a device that doesn't
+actually exist, so if the check isn't implemented just assume that the
+"device" is present.
+
+Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/property.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -837,9 +837,15 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
+ /**
+  * fwnode_device_is_available - check if a device is available for use
+  * @fwnode: Pointer to the fwnode of the device.
++ *
++ * For fwnode node types that don't implement the .device_is_available()
++ * operation, this function returns true.
+  */
+ bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
+ {
++      if (!fwnode_has_op(fwnode, device_is_available))
++              return true;
++
+       return fwnode_call_bool_op(fwnode, device_is_available);
+ }
+ EXPORT_SYMBOL_GPL(fwnode_device_is_available);
diff --git a/queue-5.10/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch b/queue-5.10/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch
new file mode 100644 (file)
index 0000000..94c4626
--- /dev/null
@@ -0,0 +1,87 @@
+From stable+bounces-231440-greg=kroah.com@vger.kernel.org Tue Mar 31 16:45:17 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Mar 2026 10:43:42 -0400
+Subject: mm/huge_memory: fix folio isn't locked in softleaf_to_folio()
+To: stable@vger.kernel.org
+Cc: Jinjiang Tu <tujinjiang@huawei.com>, "David Hildenbrand (Arm)" <david@kernel.org>, "Lorenzo Stoakes (Oracle)" <ljs@kernel.org>, Barry Song <baohua@kernel.org>, Kefeng Wang <wangkefeng.wang@huawei.com>, Liam Howlett <liam.howlett@oracle.com>, Michal Hocko <mhocko@suse.com>, Mike Rapoport <rppt@kernel.org>, Nanyong Sun <sunnanyong@huawei.com>, Ryan Roberts <ryan.roberts@arm.com>, Suren Baghdasaryan <surenb@google.com>, Vlastimil Babka <vbabka@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260331144342.2532713-1-sashal@kernel.org>
+
+From: Jinjiang Tu <tujinjiang@huawei.com>
+
+[ Upstream commit 4c5e7f0fcd592801c9cc18f29f80fbee84eb8669 ]
+
+On arm64 server, we found folio that get from migration entry isn't locked
+in softleaf_to_folio().  This issue triggers when mTHP splitting and
+zap_nonpresent_ptes() races, and the root cause is lack of memory barrier
+in softleaf_to_folio().  The race is as follows:
+
+       CPU0                                             CPU1
+
+deferred_split_scan()                              zap_nonpresent_ptes()
+  lock folio
+  split_folio()
+    unmap_folio()
+      change ptes to migration entries
+    __split_folio_to_order()                         softleaf_to_folio()
+      set flags(including PG_locked) for tail pages    folio = pfn_folio(softleaf_to_pfn(entry))
+      smp_wmb()                                        VM_WARN_ON_ONCE(!folio_test_locked(folio))
+      prep_compound_page() for tail pages
+
+In __split_folio_to_order(), smp_wmb() guarantees page flags of tail pages
+are visible before the tail page becomes non-compound.  smp_wmb() should
+be paired with smp_rmb() in softleaf_to_folio(), which is missed.  As a
+result, if zap_nonpresent_ptes() accesses migration entry that stores tail
+pfn, softleaf_to_folio() may see the updated compound_head of tail page
+before page->flags.
+
+This issue will trigger VM_WARN_ON_ONCE() in pfn_swap_entry_folio()
+because of the race between folio split and zap_nonpresent_ptes()
+leading to a folio incorrectly undergoing modification without a folio
+lock being held.
+
+This is a BUG_ON() before commit 93976a20345b ("mm: eliminate further
+swapops predicates"), which in merged in v6.19-rc1.
+
+To fix it, add missing smp_rmb() if the softleaf entry is migration entry
+in softleaf_to_folio() and softleaf_to_page().
+
+[tujinjiang@huawei.com: update function name and comments]
+  Link: https://lkml.kernel.org/r/20260321075214.3305564-1-tujinjiang@huawei.com
+Link: https://lkml.kernel.org/r/20260319012541.4158561-1-tujinjiang@huawei.com
+Fixes: e9b61f19858a ("thp: reintroduce split_huge_page()")
+Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Barry Song <baohua@kernel.org>
+Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Nanyong Sun <sunnanyong@huawei.com>
+Cc: Ryan Roberts <ryan.roberts@arm.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ adapted upstream leafops.h changes to swapops.h ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/swapops.h |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/include/linux/swapops.h
++++ b/include/linux/swapops.h
+@@ -198,6 +198,12 @@ static inline struct page *migration_ent
+ {
+       struct page *p = pfn_to_page(swp_offset(entry));
+       /*
++       * Ensure we do not race with split, which might alter tail pages
++       * into new folios and thus result in observing an unlocked page.
++       * This matches the write barrier in __split_huge_page_tail().
++       */
++      smp_rmb();
++      /*
+        * Any use of migration entries may only occur while the
+        * corresponding page is locked
+        */
diff --git a/queue-5.10/mmc-core-avoid-bitfield-rmw-for-claim-retune-flags.patch b/queue-5.10/mmc-core-avoid-bitfield-rmw-for-claim-retune-flags.patch
new file mode 100644 (file)
index 0000000..8958d01
--- /dev/null
@@ -0,0 +1,63 @@
+From stable+bounces-225857-greg=kroah.com@vger.kernel.org Tue Mar 17 12:54:12 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 07:49:49 -0400
+Subject: mmc: core: Avoid bitfield RMW for claim/retune flags
+To: stable@vger.kernel.org
+Cc: Penghe Geng <pgeng@nvidia.com>, Adrian Hunter <adrian.hunter@intel.com>, Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317114949.126875-4-sashal@kernel.org>
+
+From: Penghe Geng <pgeng@nvidia.com>
+
+[ Upstream commit 901084c51a0a8fb42a3f37d2e9c62083c495f824 ]
+
+Move claimed and retune control flags out of the bitfield word to
+avoid unrelated RMW side effects in asynchronous contexts.
+
+The host->claimed bit shared a word with retune flags. Writes to claimed
+in __mmc_claim_host() or retune_now in mmc_mq_queue_rq() can overwrite
+other bits when concurrent updates happen in other contexts, triggering
+spurious WARN_ON(!host->claimed). Convert claimed, can_retune,
+retune_now and retune_paused to bool to remove shared-word coupling.
+
+Fixes: 6c0cedd1ef952 ("mmc: core: Introduce host claiming by context")
+Fixes: 1e8e55b67030c ("mmc: block: Add CQE support")
+Cc: stable@vger.kernel.org
+Suggested-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Penghe Geng <pgeng@nvidia.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/mmc/host.h |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/include/linux/mmc/host.h
++++ b/include/linux/mmc/host.h
+@@ -400,14 +400,12 @@ struct mmc_host {
+       struct mmc_ios          ios;            /* current io bus settings */
++      bool                    claimed;        /* host exclusively claimed */
++
+       /* group bitfields together to minimize padding */
+       unsigned int            use_spi_crc:1;
+-      unsigned int            claimed:1;      /* host exclusively claimed */
+       unsigned int            doing_init_tune:1; /* initial tuning in progress */
+-      unsigned int            can_retune:1;   /* re-tuning can be used */
+       unsigned int            doing_retune:1; /* re-tuning in progress */
+-      unsigned int            retune_now:1;   /* do re-tuning at next req */
+-      unsigned int            retune_paused:1; /* re-tuning is temporarily disabled */
+       unsigned int            retune_crc_disable:1; /* don't trigger retune upon crc */
+       unsigned int            can_dma_map_merge:1; /* merging can be used */
+       unsigned int            vqmmc_enabled:1; /* vqmmc regulator is enabled */
+@@ -415,6 +413,9 @@ struct mmc_host {
+       int                     rescan_disable; /* disable card detection */
+       int                     rescan_entered; /* used with nonremovable devices */
++      bool                    can_retune;     /* re-tuning can be used */
++      bool                    retune_now;     /* do re-tuning at next req */
++      bool                    retune_paused;  /* re-tuning is temporarily disabled */
+       int                     need_retune;    /* re-tuning is needed */
+       int                     hold_retune;    /* hold off re-tuning */
+       unsigned int            retune_period;  /* re-tuning period in secs */
diff --git a/queue-5.10/mmc-core-drop-redundant-member-in-struct-mmc-host.patch b/queue-5.10/mmc-core-drop-redundant-member-in-struct-mmc-host.patch
new file mode 100644 (file)
index 0000000..47c3b95
--- /dev/null
@@ -0,0 +1,35 @@
+From stable+bounces-225854-greg=kroah.com@vger.kernel.org Tue Mar 17 12:54:00 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 07:49:46 -0400
+Subject: mmc: core: Drop redundant member in struct mmc host
+To: stable@vger.kernel.org
+Cc: Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317114949.126875-1-sashal@kernel.org>
+
+From: Ulf Hansson <ulf.hansson@linaro.org>
+
+[ Upstream commit 951f6ccfcbb7e4a18bf5fef1fb373d21e5831957 ]
+
+The Kconfig option to use the blk-mq support was removed in commit
+1bec43a3b181 ("mmc: core: Remove option not to use blk-mq"), but forgot to
+remove the use_blk_mq member in the struct mmc_host, let's fix it.
+
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Link: https://lore.kernel.org/r/20210202101924.69970-1-ulf.hansson@linaro.org
+Stable-dep-of: 901084c51a0a ("mmc: core: Avoid bitfield RMW for claim/retune flags")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/mmc/host.h |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/include/linux/mmc/host.h
++++ b/include/linux/mmc/host.h
+@@ -409,7 +409,6 @@ struct mmc_host {
+       unsigned int            doing_retune:1; /* re-tuning in progress */
+       unsigned int            retune_now:1;   /* do re-tuning at next req */
+       unsigned int            retune_paused:1; /* re-tuning is temporarily disabled */
+-      unsigned int            use_blk_mq:1;   /* use blk-mq */
+       unsigned int            retune_crc_disable:1; /* don't trigger retune upon crc */
+       unsigned int            can_dma_map_merge:1; /* merging can be used */
+       unsigned int            vqmmc_enabled:1; /* vqmmc regulator is enabled */
diff --git a/queue-5.10/mmc-core-drop-reference-counting-of-the-bus_ops.patch b/queue-5.10/mmc-core-drop-reference-counting-of-the-bus_ops.patch
new file mode 100644 (file)
index 0000000..7e715ea
--- /dev/null
@@ -0,0 +1,214 @@
+From stable+bounces-225856-greg=kroah.com@vger.kernel.org Tue Mar 17 12:49:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 07:49:48 -0400
+Subject: mmc: core: Drop reference counting of the bus_ops
+To: stable@vger.kernel.org
+Cc: Ulf Hansson <ulf.hansson@linaro.org>, Pierre Ossman <pierre@ossman.eu>, Russell King <linux@armlinux.org.uk>, Adrian Hunter <adrian.hunter@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317114949.126875-3-sashal@kernel.org>
+
+From: Ulf Hansson <ulf.hansson@linaro.org>
+
+[ Upstream commit e9ce2ce17da626d930812199568bd426b2832f57 ]
+
+When the mmc_rescan work is enabled for execution (host->rescan_disable),
+it's the only instance per mmc host that is allowed to set/clear the
+host->bus_ops pointer.
+
+Besides the mmc_rescan work, there are a couple of scenarios when the
+host->bus_ops pointer may be accessed. Typically, those can be described as
+as below:
+
+*)
+Upper mmc driver layers (like the mmc block device driver or an SDIO
+functional driver) needs to execute a host->bus_ops callback. This can be
+considered as safe without having to use some special locking mechanism,
+because they operate on top of the struct mmc_card. As long as there is a
+card to operate upon, the mmc core guarantees that there is a host->bus_ops
+assigned as well. Note that, upper layer mmc drivers are of course
+responsible to clean up from themselves from their ->remove() callbacks,
+otherwise things would fall apart anyways.
+
+**)
+Via the mmc host instance, we may need to force a removal of an inserted
+mmc card. This happens when a mmc host driver gets unbind, for example. In
+this case, we protect the host->bus_ops pointer from concurrent accesses,
+by disabling the mmc_rescan work upfront (host->rescan_disable). See
+mmc_stop_host() for example.
+
+This said, it seems like the reference counting of the host->bus_ops
+pointer at some point have become superfluous. As this is an old mechanism
+of the mmc core, it a bit difficult to digest the history of when that
+could have happened. However, let's drop the reference counting to avoid
+unnecessary code-paths and lockings.
+
+Cc: Pierre Ossman <pierre@ossman.eu>
+Cc: Russell King <linux@armlinux.org.uk>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20210212131610.236843-1-ulf.hansson@linaro.org
+Stable-dep-of: 901084c51a0a ("mmc: core: Avoid bitfield RMW for claim/retune flags")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/core/core.c  |   89 ++---------------------------------------------
+ include/linux/mmc/host.h |    2 -
+ 2 files changed, 4 insertions(+), 87 deletions(-)
+
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -1389,62 +1389,12 @@ void mmc_power_cycle(struct mmc_host *ho
+ }
+ /*
+- * Cleanup when the last reference to the bus operator is dropped.
+- */
+-static void __mmc_release_bus(struct mmc_host *host)
+-{
+-      WARN_ON(!host->bus_dead);
+-
+-      host->bus_ops = NULL;
+-}
+-
+-/*
+- * Increase reference count of bus operator
+- */
+-static inline void mmc_bus_get(struct mmc_host *host)
+-{
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&host->lock, flags);
+-      host->bus_refs++;
+-      spin_unlock_irqrestore(&host->lock, flags);
+-}
+-
+-/*
+- * Decrease reference count of bus operator and free it if
+- * it is the last reference.
+- */
+-static inline void mmc_bus_put(struct mmc_host *host)
+-{
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&host->lock, flags);
+-      host->bus_refs--;
+-      if ((host->bus_refs == 0) && host->bus_ops)
+-              __mmc_release_bus(host);
+-      spin_unlock_irqrestore(&host->lock, flags);
+-}
+-
+-/*
+  * Assign a mmc bus handler to a host. Only one bus handler may control a
+  * host at any given time.
+  */
+ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
+ {
+-      unsigned long flags;
+-
+-      WARN_ON(!host->claimed);
+-
+-      spin_lock_irqsave(&host->lock, flags);
+-
+-      WARN_ON(host->bus_ops);
+-      WARN_ON(host->bus_refs);
+-
+       host->bus_ops = ops;
+-      host->bus_refs = 1;
+-      host->bus_dead = 0;
+-
+-      spin_unlock_irqrestore(&host->lock, flags);
+ }
+ /*
+@@ -1452,18 +1402,7 @@ void mmc_attach_bus(struct mmc_host *hos
+  */
+ void mmc_detach_bus(struct mmc_host *host)
+ {
+-      unsigned long flags;
+-
+-      WARN_ON(!host->claimed);
+-      WARN_ON(!host->bus_ops);
+-
+-      spin_lock_irqsave(&host->lock, flags);
+-
+-      host->bus_dead = 1;
+-
+-      spin_unlock_irqrestore(&host->lock, flags);
+-
+-      mmc_bus_put(host);
++      host->bus_ops = NULL;
+ }
+ void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq)
+@@ -2260,32 +2199,15 @@ void mmc_rescan(struct work_struct *work
+               host->trigger_card_event = false;
+       }
+-      mmc_bus_get(host);
+-
+       /* Verify a registered card to be functional, else remove it. */
+-      if (host->bus_ops && !host->bus_dead)
++      if (host->bus_ops)
+               host->bus_ops->detect(host);
+       host->detect_change = 0;
+-      /*
+-       * Let mmc_bus_put() free the bus/bus_ops if we've found that
+-       * the card is no longer present.
+-       */
+-      mmc_bus_put(host);
+-      mmc_bus_get(host);
+-
+       /* if there still is a card present, stop here */
+-      if (host->bus_ops != NULL) {
+-              mmc_bus_put(host);
++      if (host->bus_ops != NULL)
+               goto out;
+-      }
+-
+-      /*
+-       * Only we can add a new handler, so it's safe to
+-       * release the lock here.
+-       */
+-      mmc_bus_put(host);
+       mmc_claim_host(host);
+       if (mmc_card_is_removable(host) && host->ops->get_cd &&
+@@ -2356,18 +2278,15 @@ void mmc_stop_host(struct mmc_host *host
+       /* clear pm flags now and let card drivers set them as needed */
+       host->pm_flags = 0;
+-      mmc_bus_get(host);
+-      if (host->bus_ops && !host->bus_dead) {
++      if (host->bus_ops) {
+               /* Calling bus_ops->remove() with a claimed host can deadlock */
+               host->bus_ops->remove(host);
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
+               mmc_power_off(host);
+               mmc_release_host(host);
+-              mmc_bus_put(host);
+               return;
+       }
+-      mmc_bus_put(host);
+       mmc_claim_host(host);
+       mmc_power_off(host);
+--- a/include/linux/mmc/host.h
++++ b/include/linux/mmc/host.h
+@@ -403,7 +403,6 @@ struct mmc_host {
+       /* group bitfields together to minimize padding */
+       unsigned int            use_spi_crc:1;
+       unsigned int            claimed:1;      /* host exclusively claimed */
+-      unsigned int            bus_dead:1;     /* bus has been released */
+       unsigned int            doing_init_tune:1; /* initial tuning in progress */
+       unsigned int            can_retune:1;   /* re-tuning can be used */
+       unsigned int            doing_retune:1; /* re-tuning in progress */
+@@ -435,7 +434,6 @@ struct mmc_host {
+       struct mmc_slot         slot;
+       const struct mmc_bus_ops *bus_ops;      /* current bus driver */
+-      unsigned int            bus_refs;       /* reference counter */
+       unsigned int            sdio_irqs;
+       struct task_struct      *sdio_irq_thread;
diff --git a/queue-5.10/mmc-core-drop-superfluous-validations-in-mmc_hw-sw_reset.patch b/queue-5.10/mmc-core-drop-superfluous-validations-in-mmc_hw-sw_reset.patch
new file mode 100644 (file)
index 0000000..78e27e9
--- /dev/null
@@ -0,0 +1,86 @@
+From stable+bounces-225855-greg=kroah.com@vger.kernel.org Tue Mar 17 12:49:58 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Mar 2026 07:49:47 -0400
+Subject: mmc: core: Drop superfluous validations in mmc_hw|sw_reset()
+To: stable@vger.kernel.org
+Cc: Ulf Hansson <ulf.hansson@linaro.org>, Adrian Hunter <adrian.hunter@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260317114949.126875-2-sashal@kernel.org>
+
+From: Ulf Hansson <ulf.hansson@linaro.org>
+
+[ Upstream commit fefdd3c91e0a7b3cbb3f25925d93a57c45cb0f31 ]
+
+The mmc_hw|sw_reset() APIs are designed to be called solely from upper
+layers, which means drivers that operates on top of the struct mmc_card,
+like the mmc block device driver and an SDIO functional driver.
+
+Additionally, as long as the struct mmc_host has a valid pointer to a
+struct mmc_card, the corresponding host->bus_ops pointer stays valid and
+assigned.
+
+For these reasons, let's drop the superfluous reference counting and the
+redundant validations in mmc_hw|sw_reset().
+
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20210212131532.236775-1-ulf.hansson@linaro.org
+Stable-dep-of: 901084c51a0a ("mmc: core: Avoid bitfield RMW for claim/retune flags")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/core/block.c |    2 +-
+ drivers/mmc/core/core.c  |   21 +--------------------
+ 2 files changed, 2 insertions(+), 21 deletions(-)
+
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -987,7 +987,7 @@ static int mmc_blk_reset(struct mmc_blk_
+       md->reset_done |= type;
+       err = mmc_hw_reset(host);
+       /* Ensure we switch back to the correct partition */
+-      if (err != -EOPNOTSUPP) {
++      if (err) {
+               struct mmc_blk_data *main_md =
+                       dev_get_drvdata(&host->card->dev);
+               int part_err;
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -2096,18 +2096,7 @@ int mmc_hw_reset(struct mmc_host *host)
+ {
+       int ret;
+-      if (!host->card)
+-              return -EINVAL;
+-
+-      mmc_bus_get(host);
+-      if (!host->bus_ops || host->bus_dead || !host->bus_ops->hw_reset) {
+-              mmc_bus_put(host);
+-              return -EOPNOTSUPP;
+-      }
+-
+       ret = host->bus_ops->hw_reset(host);
+-      mmc_bus_put(host);
+-
+       if (ret < 0)
+               pr_warn("%s: tried to HW reset card, got error %d\n",
+                       mmc_hostname(host), ret);
+@@ -2120,18 +2109,10 @@ int mmc_sw_reset(struct mmc_host *host)
+ {
+       int ret;
+-      if (!host->card)
+-              return -EINVAL;
+-
+-      mmc_bus_get(host);
+-      if (!host->bus_ops || host->bus_dead || !host->bus_ops->sw_reset) {
+-              mmc_bus_put(host);
++      if (!host->bus_ops->sw_reset)
+               return -EOPNOTSUPP;
+-      }
+       ret = host->bus_ops->sw_reset(host);
+-      mmc_bus_put(host);
+-
+       if (ret)
+               pr_warn("%s: tried to SW reset card, got error %d\n",
+                       mmc_hostname(host), ret);
diff --git a/queue-5.10/net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch b/queue-5.10/net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch
new file mode 100644 (file)
index 0000000..fe10fb6
--- /dev/null
@@ -0,0 +1,147 @@
+From stable+bounces-232615-greg=kroah.com@vger.kernel.org Wed Apr  1 02:18:53 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Mar 2026 20:18:48 -0400
+Subject: net: macb: Move devm_{free,request}_irq() out of spin lock area
+To: stable@vger.kernel.org
+Cc: "Kevin Hao" <haokexin@gmail.com>, "Théo Lebrun" <theo.lebrun@bootlin.com>, "Jakub Kicinski" <kuba@kernel.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260401001848.3982933-1-sashal@kernel.org>
+
+From: Kevin Hao <haokexin@gmail.com>
+
+[ Upstream commit 317e49358ebbf6390fa439ef3c142f9239dd25fb ]
+
+The devm_free_irq() and devm_request_irq() functions should not be
+executed in an atomic context.
+
+During device suspend, all userspace processes and most kernel threads
+are frozen. Additionally, we flush all tx/rx status, disable all macb
+interrupts, and halt rx operations. Therefore, it is safe to split the
+region protected by bp->lock into two independent sections, allowing
+devm_free_irq() and devm_request_irq() to run in a non-atomic context.
+This modification resolves the following lockdep warning:
+  BUG: sleeping function called from invalid context at kernel/locking/mutex.c:591
+  in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 501, name: rtcwake
+  preempt_count: 1, expected: 0
+  RCU nest depth: 1, expected: 0
+  7 locks held by rtcwake/501:
+   #0: ffff0008038c3408 (sb_writers#5){.+.+}-{0:0}, at: vfs_write+0xf8/0x368
+   #1: ffff0008049a5e88 (&of->mutex#2){+.+.}-{4:4}, at: kernfs_fop_write_iter+0xbc/0x1c8
+   #2: ffff00080098d588 (kn->active#70){.+.+}-{0:0}, at: kernfs_fop_write_iter+0xcc/0x1c8
+   #3: ffff800081c84888 (system_transition_mutex){+.+.}-{4:4}, at: pm_suspend+0x1ec/0x290
+   #4: ffff0008009ba0f8 (&dev->mutex){....}-{4:4}, at: device_suspend+0x118/0x4f0
+   #5: ffff800081d00458 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire+0x4/0x48
+   #6: ffff0008031fb9e0 (&bp->lock){-.-.}-{3:3}, at: macb_suspend+0x144/0x558
+  irq event stamp: 8682
+  hardirqs last  enabled at (8681): [<ffff8000813c7d7c>] _raw_spin_unlock_irqrestore+0x44/0x88
+  hardirqs last disabled at (8682): [<ffff8000813c7b58>] _raw_spin_lock_irqsave+0x38/0x98
+  softirqs last  enabled at (7322): [<ffff8000800f1b4c>] handle_softirqs+0x52c/0x588
+  softirqs last disabled at (7317): [<ffff800080010310>] __do_softirq+0x20/0x2c
+  CPU: 1 UID: 0 PID: 501 Comm: rtcwake Not tainted 7.0.0-rc3-next-20260310-yocto-standard+ #125 PREEMPT
+  Hardware name: ZynqMP ZCU102 Rev1.1 (DT)
+  Call trace:
+   show_stack+0x24/0x38 (C)
+   __dump_stack+0x28/0x38
+   dump_stack_lvl+0x64/0x88
+   dump_stack+0x18/0x24
+   __might_resched+0x200/0x218
+   __might_sleep+0x38/0x98
+   __mutex_lock_common+0x7c/0x1378
+   mutex_lock_nested+0x38/0x50
+   free_irq+0x68/0x2b0
+   devm_irq_release+0x24/0x38
+   devres_release+0x40/0x80
+   devm_free_irq+0x48/0x88
+   macb_suspend+0x298/0x558
+   device_suspend+0x218/0x4f0
+   dpm_suspend+0x244/0x3a0
+   dpm_suspend_start+0x50/0x78
+   suspend_devices_and_enter+0xec/0x560
+   pm_suspend+0x194/0x290
+   state_store+0x110/0x158
+   kobj_attr_store+0x1c/0x30
+   sysfs_kf_write+0xa8/0xd0
+   kernfs_fop_write_iter+0x11c/0x1c8
+   vfs_write+0x248/0x368
+   ksys_write+0x7c/0xf8
+   __arm64_sys_write+0x28/0x40
+   invoke_syscall+0x4c/0xe8
+   el0_svc_common+0x98/0xf0
+   do_el0_svc+0x28/0x40
+   el0_svc+0x54/0x1e0
+   el0t_64_sync_handler+0x84/0x130
+   el0t_64_sync+0x198/0x1a0
+
+Fixes: 558e35ccfe95 ("net: macb: WoL support for GEM type of Ethernet controller")
+Cc: stable@vger.kernel.org
+Reviewed-by: Théo Lebrun <theo.lebrun@bootlin.com>
+Signed-off-by: Kevin Hao <haokexin@gmail.com>
+Link: https://patch.msgid.link/20260318-macb-irq-v2-1-f1179768ab24@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ adapted WoL register writes to use MACB_BIT(MAG) instead of tmp variable ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/cadence/macb_main.c |   13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/cadence/macb_main.c
++++ b/drivers/net/ethernet/cadence/macb_main.c
+@@ -4734,6 +4734,8 @@ static int __maybe_unused macb_suspend(s
+                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+                               queue_writel(queue, ISR, -1);
+               }
++              spin_unlock_irqrestore(&bp->lock, flags);
++
+               /* Change interrupt handler and
+                * Enable WoL IRQ on queue 0
+                */
+@@ -4745,11 +4747,12 @@ static int __maybe_unused macb_suspend(s
+                               dev_err(dev,
+                                       "Unable to request IRQ %d (error %d)\n",
+                                       bp->queues[0].irq, err);
+-                              spin_unlock_irqrestore(&bp->lock, flags);
+                               return err;
+                       }
++                      spin_lock_irqsave(&bp->lock, flags);
+                       queue_writel(bp->queues, IER, GEM_BIT(WOL));
+                       gem_writel(bp, WOL, MACB_BIT(MAG));
++                      spin_unlock_irqrestore(&bp->lock, flags);
+               } else {
+                       err = devm_request_irq(dev, bp->queues[0].irq, macb_wol_interrupt,
+                                              IRQF_SHARED, netdev->name, bp->queues);
+@@ -4757,13 +4760,13 @@ static int __maybe_unused macb_suspend(s
+                               dev_err(dev,
+                                       "Unable to request IRQ %d (error %d)\n",
+                                       bp->queues[0].irq, err);
+-                              spin_unlock_irqrestore(&bp->lock, flags);
+                               return err;
+                       }
++                      spin_lock_irqsave(&bp->lock, flags);
+                       queue_writel(bp->queues, IER, MACB_BIT(WOL));
+                       macb_writel(bp, WOL, MACB_BIT(MAG));
++                      spin_unlock_irqrestore(&bp->lock, flags);
+               }
+-              spin_unlock_irqrestore(&bp->lock, flags);
+               enable_irq_wake(bp->queues[0].irq);
+       }
+@@ -4825,6 +4828,8 @@ static int __maybe_unused macb_resume(st
+               queue_readl(bp->queues, ISR);
+               if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+                       queue_writel(bp->queues, ISR, -1);
++              spin_unlock_irqrestore(&bp->lock, flags);
++
+               /* Replace interrupt handler on queue 0 */
+               devm_free_irq(dev, bp->queues[0].irq, bp->queues);
+               err = devm_request_irq(dev, bp->queues[0].irq, macb_interrupt,
+@@ -4833,10 +4838,8 @@ static int __maybe_unused macb_resume(st
+                       dev_err(dev,
+                               "Unable to request IRQ %d (error %d)\n",
+                               bp->queues[0].irq, err);
+-                      spin_unlock_irqrestore(&bp->lock, flags);
+                       return err;
+               }
+-              spin_unlock_irqrestore(&bp->lock, flags);
+               disable_irq_wake(bp->queues[0].irq);
diff --git a/queue-5.10/net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch b/queue-5.10/net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch
new file mode 100644 (file)
index 0000000..51f7d40
--- /dev/null
@@ -0,0 +1,140 @@
+From stable+bounces-235850-greg=kroah.com@vger.kernel.org Sun Apr 12 22:03:15 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 12 Apr 2026 16:03:08 -0400
+Subject: net: rfkill: prevent unlimited numbers of rfkill events from being created
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Johannes Berg <johannes@sipsolutions.net>, Yuan Tan <yuantan098@gmail.com>, Yifan Wu <yifanwucs@gmail.com>, Juefei Pu <tomapufckgml@gmail.com>, Xin Liu <bird@lzu.edu.cn>, stable <stable@kernel.org>, Johannes Berg <johannes.berg@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260412200308.2406071-1-sashal@kernel.org>
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+[ Upstream commit ea245d78dec594372e27d8c79616baf49e98a4a1 ]
+
+Userspace can create an unlimited number of rfkill events if the system
+is so configured, while not consuming them from the rfkill file
+descriptor, causing a potential out of memory situation.  Prevent this
+from bounding the number of pending rfkill events at a "large" number
+(i.e. 1000) to prevent abuses like this.
+
+Cc: Johannes Berg <johannes@sipsolutions.net>
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://patch.msgid.link/2026033013-disfigure-scroll-e25e@gregkh
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+[ replaced `rfkill_event_ext` with `rfkill_event`, `scoped_guard` with explicit mutex calls, and removed outer `data->mtx` lock in `rfkill_fop_open` to avoid deadlock with new internal locking ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/rfkill/core.c |   40 +++++++++++++++++++++++++++-------------
+ 1 file changed, 27 insertions(+), 13 deletions(-)
+
+--- a/net/rfkill/core.c
++++ b/net/rfkill/core.c
+@@ -71,11 +71,14 @@ struct rfkill_int_event {
+       struct rfkill_event     ev;
+ };
++/* Max rfkill events that can be "in-flight" for one data source */
++#define MAX_RFKILL_EVENT      1000
+ struct rfkill_data {
+       struct list_head        list;
+       struct list_head        events;
+       struct mutex            mtx;
+       wait_queue_head_t       read_wait;
++      u32                     event_count;
+       bool                    input_handler;
+ };
+@@ -252,9 +255,12 @@ static void rfkill_global_led_trigger_un
+ }
+ #endif /* CONFIG_RFKILL_LEDS */
+-static void rfkill_fill_event(struct rfkill_event *ev, struct rfkill *rfkill,
+-                            enum rfkill_operation op)
++static int rfkill_fill_event(struct rfkill_int_event *int_ev,
++                           struct rfkill *rfkill,
++                           struct rfkill_data *data,
++                           enum rfkill_operation op)
+ {
++      struct rfkill_event *ev = &int_ev->ev;
+       unsigned long flags;
+       ev->idx = rfkill->idx;
+@@ -266,6 +272,16 @@ static void rfkill_fill_event(struct rfk
+       ev->soft = !!(rfkill->state & (RFKILL_BLOCK_SW |
+                                       RFKILL_BLOCK_SW_PREV));
+       spin_unlock_irqrestore(&rfkill->lock, flags);
++
++      mutex_lock(&data->mtx);
++      if (data->event_count++ > MAX_RFKILL_EVENT) {
++              data->event_count--;
++              mutex_unlock(&data->mtx);
++              return -ENOSPC;
++      }
++      list_add_tail(&int_ev->list, &data->events);
++      mutex_unlock(&data->mtx);
++      return 0;
+ }
+ static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op)
+@@ -277,10 +293,10 @@ static void rfkill_send_events(struct rf
+               ev = kzalloc(sizeof(*ev), GFP_KERNEL);
+               if (!ev)
+                       continue;
+-              rfkill_fill_event(&ev->ev, rfkill, op);
+-              mutex_lock(&data->mtx);
+-              list_add_tail(&ev->list, &data->events);
+-              mutex_unlock(&data->mtx);
++              if (rfkill_fill_event(ev, rfkill, data, op)) {
++                      kfree(ev);
++                      continue;
++              }
+               wake_up_interruptible(&data->read_wait);
+       }
+ }
+@@ -1118,21 +1134,19 @@ static int rfkill_fop_open(struct inode
+       init_waitqueue_head(&data->read_wait);
+       mutex_lock(&rfkill_global_mutex);
+-      mutex_lock(&data->mtx);
+       /*
+-       * start getting events from elsewhere but hold mtx to get
+-       * startup events added first
++       * start getting events from elsewhere but hold rfkill_global_mutex
++       * to get startup events added first
+        */
+       list_for_each_entry(rfkill, &rfkill_list, node) {
+               ev = kzalloc(sizeof(*ev), GFP_KERNEL);
+               if (!ev)
+                       goto free;
+-              rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD);
+-              list_add_tail(&ev->list, &data->events);
++              if (rfkill_fill_event(ev, rfkill, data, RFKILL_OP_ADD))
++                      kfree(ev);
+       }
+       list_add(&data->list, &rfkill_fds);
+-      mutex_unlock(&data->mtx);
+       mutex_unlock(&rfkill_global_mutex);
+       file->private_data = data;
+@@ -1140,7 +1154,6 @@ static int rfkill_fop_open(struct inode
+       return stream_open(inode, file);
+  free:
+-      mutex_unlock(&data->mtx);
+       mutex_unlock(&rfkill_global_mutex);
+       mutex_destroy(&data->mtx);
+       list_for_each_entry_safe(ev, tmp, &data->events, list)
+@@ -1200,6 +1213,7 @@ static ssize_t rfkill_fop_read(struct fi
+               ret = -EFAULT;
+       list_del(&ev->list);
++      data->event_count--;
+       kfree(ev);
+  out:
+       mutex_unlock(&data->mtx);
diff --git a/queue-5.10/nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch b/queue-5.10/nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch
new file mode 100644 (file)
index 0000000..7f2f3c6
--- /dev/null
@@ -0,0 +1,94 @@
+From stable+bounces-217799-greg=kroah.com@vger.kernel.org Mon Feb 23 18:23:57 2026
+From: Jaskaran Singh <jsingh@cloudlinux.com>
+Date: Mon, 23 Feb 2026 22:52:41 +0530
+Subject: nvme: nvme-fc: Ensure ->ioerr_work is cancelled in nvme_fc_delete_ctrl()
+To: stable@vger.kernel.org, james.smart@broadcom.com, kbusch@kernel.org, axboe@fb.com, hch@lst.de, sagi@grimberg.me
+Cc: linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, gregkh@linuxfoundation.org, Jaskaran Singh <jsingh@cloudlinux.com>, Marco Patalano <mpatalan@redhat.com>, Justin Tee <justin.tee@broadcom.com>, "Ewan D . Milne" <emilne@redhat.com>
+Message-ID: <20260223172241.291649-3-jsingh@cloudlinux.com>
+
+From: Jaskaran Singh <jsingh@cloudlinux.com>
+
+commit 0a2c5495b6d1ecb0fa18ef6631450f391a888256 upstream.
+
+nvme_fc_delete_assocation() waits for pending I/O to complete before
+returning, and an error can cause ->ioerr_work to be queued after
+cancel_work_sync() had been called.  Move the call to cancel_work_sync() to
+be after nvme_fc_delete_association() to ensure ->ioerr_work is not running
+when the nvme_fc_ctrl object is freed.  Otherwise the following can occur:
+
+[ 1135.911754] list_del corruption, ff2d24c8093f31f8->next is NULL
+[ 1135.917705] ------------[ cut here ]------------
+[ 1135.922336] kernel BUG at lib/list_debug.c:52!
+[ 1135.926784] Oops: invalid opcode: 0000 [#1] SMP NOPTI
+[ 1135.931851] CPU: 48 UID: 0 PID: 726 Comm: kworker/u449:23 Kdump: loaded Not tainted 6.12.0 #1 PREEMPT(voluntary)
+[ 1135.943490] Hardware name: Dell Inc. PowerEdge R660/0HGTK9, BIOS 2.5.4 01/16/2025
+[ 1135.950969] Workqueue:  0x0 (nvme-wq)
+[ 1135.954673] RIP: 0010:__list_del_entry_valid_or_report.cold+0xf/0x6f
+[ 1135.961041] Code: c7 c7 98 68 72 94 e8 26 45 fe ff 0f 0b 48 c7 c7 70 68 72 94 e8 18 45 fe ff 0f 0b 48 89 fe 48 c7 c7 80 69 72 94 e8 07 45 fe ff <0f> 0b 48 89 d1 48 c7 c7 a0 6a 72 94 48 89 c2 e8 f3 44 fe ff 0f 0b
+[ 1135.979788] RSP: 0018:ff579b19482d3e50 EFLAGS: 00010046
+[ 1135.985015] RAX: 0000000000000033 RBX: ff2d24c8093f31f0 RCX: 0000000000000000
+[ 1135.992148] RDX: 0000000000000000 RSI: ff2d24d6bfa1d0c0 RDI: ff2d24d6bfa1d0c0
+[ 1135.999278] RBP: ff2d24c8093f31f8 R08: 0000000000000000 R09: ffffffff951e2b08
+[ 1136.006413] R10: ffffffff95122ac8 R11: 0000000000000003 R12: ff2d24c78697c100
+[ 1136.013546] R13: fffffffffffffff8 R14: 0000000000000000 R15: ff2d24c78697c0c0
+[ 1136.020677] FS:  0000000000000000(0000) GS:ff2d24d6bfa00000(0000) knlGS:0000000000000000
+[ 1136.028765] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 1136.034510] CR2: 00007fd207f90b80 CR3: 000000163ea22003 CR4: 0000000000f73ef0
+[ 1136.041641] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 1136.048776] DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400
+[ 1136.055910] PKRU: 55555554
+[ 1136.058623] Call Trace:
+[ 1136.061074]  <TASK>
+[ 1136.063179]  ? show_trace_log_lvl+0x1b0/0x2f0
+[ 1136.067540]  ? show_trace_log_lvl+0x1b0/0x2f0
+[ 1136.071898]  ? move_linked_works+0x4a/0xa0
+[ 1136.075998]  ? __list_del_entry_valid_or_report.cold+0xf/0x6f
+[ 1136.081744]  ? __die_body.cold+0x8/0x12
+[ 1136.085584]  ? die+0x2e/0x50
+[ 1136.088469]  ? do_trap+0xca/0x110
+[ 1136.091789]  ? do_error_trap+0x65/0x80
+[ 1136.095543]  ? __list_del_entry_valid_or_report.cold+0xf/0x6f
+[ 1136.101289]  ? exc_invalid_op+0x50/0x70
+[ 1136.105127]  ? __list_del_entry_valid_or_report.cold+0xf/0x6f
+[ 1136.110874]  ? asm_exc_invalid_op+0x1a/0x20
+[ 1136.115059]  ? __list_del_entry_valid_or_report.cold+0xf/0x6f
+[ 1136.120806]  move_linked_works+0x4a/0xa0
+[ 1136.124733]  worker_thread+0x216/0x3a0
+[ 1136.128485]  ? __pfx_worker_thread+0x10/0x10
+[ 1136.132758]  kthread+0xfa/0x240
+[ 1136.135904]  ? __pfx_kthread+0x10/0x10
+[ 1136.139657]  ret_from_fork+0x31/0x50
+[ 1136.143236]  ? __pfx_kthread+0x10/0x10
+[ 1136.146988]  ret_from_fork_asm+0x1a/0x30
+[ 1136.150915]  </TASK>
+
+Fixes: 19fce0470f05 ("nvme-fc: avoid calling _nvme_fc_abort_outstanding_ios from interrupt context")
+Cc: stable@vger.kernel.org
+Tested-by: Marco Patalano <mpatalan@redhat.com>
+Reviewed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Ewan D. Milne <emilne@redhat.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jaskaran Singh <jsingh@cloudlinux.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/fc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvme/host/fc.c
++++ b/drivers/nvme/host/fc.c
+@@ -3259,13 +3259,13 @@ nvme_fc_delete_ctrl(struct nvme_ctrl *nc
+ {
+       struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
+-      cancel_work_sync(&ctrl->ioerr_work);
+       cancel_delayed_work_sync(&ctrl->connect_work);
+       /*
+        * kill the association on the link side.  this will block
+        * waiting for io to terminate
+        */
+       nvme_fc_delete_association(ctrl);
++      cancel_work_sync(&ctrl->ioerr_work);
+ }
+ static void
diff --git a/queue-5.10/revert-nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch b/queue-5.10/revert-nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch
new file mode 100644 (file)
index 0000000..7cb2bf9
--- /dev/null
@@ -0,0 +1,42 @@
+From stable+bounces-217798-greg=kroah.com@vger.kernel.org Mon Feb 23 18:23:34 2026
+From: Jaskaran Singh <jsingh@cloudlinux.com>
+Date: Mon, 23 Feb 2026 22:52:40 +0530
+Subject: Revert "nvme: nvme-fc: Ensure ->ioerr_work is cancelled in nvme_fc_delete_ctrl()"
+To: stable@vger.kernel.org, james.smart@broadcom.com, kbusch@kernel.org, axboe@fb.com, hch@lst.de, sagi@grimberg.me
+Cc: linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, gregkh@linuxfoundation.org, Jaskaran Singh <jsingh@cloudlinux.com>
+Message-ID: <20260223172241.291649-2-jsingh@cloudlinux.com>
+
+From: Jaskaran Singh <jsingh@cloudlinux.com>
+
+This reverts commit 3d78e8e01251da032a5f7cbc9728e4ab1a5a5464.
+
+The backport of upstream commit 0a2c5495b6d1 was incorrectly applied.
+The cancel_work_sync() call for ->ioerr_work was added to
+nvme_fc_reset_ctrl_work() instead of nvme_fc_delete_ctrl().
+
+Revert this commit so the correct fix can be applied.
+
+Signed-off-by: Jaskaran Singh <jsingh@cloudlinux.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/fc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/nvme/host/fc.c
++++ b/drivers/nvme/host/fc.c
+@@ -3259,6 +3259,7 @@ nvme_fc_delete_ctrl(struct nvme_ctrl *nc
+ {
+       struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
++      cancel_work_sync(&ctrl->ioerr_work);
+       cancel_delayed_work_sync(&ctrl->connect_work);
+       /*
+        * kill the association on the link side.  this will block
+@@ -3322,7 +3323,6 @@ nvme_fc_reset_ctrl_work(struct work_stru
+       /* will block will waiting for io to terminate */
+       nvme_fc_delete_association(ctrl);
+-      cancel_work_sync(&ctrl->ioerr_work);
+       if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
+               dev_err(ctrl->ctrl.device,
diff --git a/queue-5.10/s390-syscalls-add-spectre-boundary-for-syscall-dispatch-table.patch b/queue-5.10/s390-syscalls-add-spectre-boundary-for-syscall-dispatch-table.patch
new file mode 100644 (file)
index 0000000..41f337a
--- /dev/null
@@ -0,0 +1,71 @@
+From stable+bounces-231418-greg=kroah.com@vger.kernel.org Tue Mar 31 14:25:10 2026
+From: Vasily Gorbik <gor@linux.ibm.com>
+Date: Tue, 31 Mar 2026 14:23:42 +0200
+Subject: s390/syscalls: Add spectre boundary for syscall dispatch table
+To: stable@vger.kernel.org
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Ilya Leoshkevich <iii@linux.ibm.com>, Sven Schnelle <svens@linux.ibm.com>
+Message-ID: <p01.g4865e9641758.ttcrjn3@ub.hpns>
+Content-Disposition: inline
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+[ Upstream commit 48b8814e25d073dd84daf990a879a820bad2bcbd ]
+
+The s390 syscall number is directly controlled by userspace, but does
+not have an array_index_nospec() boundary to prevent access past the
+syscall function pointer tables.
+
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
+Cc: Sven Schnelle <svens@linux.ibm.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Fixes: 56e62a737028 ("s390: convert to generic entry")
+Cc: stable@kernel.org
+Assisted-by: gkh_clanker_2000
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Vasily Gorbik <gor@linux.ibm.com>
+Link: https://lore.kernel.org/r/2026032404-sterling-swoosh-43e6@gregkh
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+[ gor: 5.10 backport. In 5.10, commit 56e62a737028 ("s390: convert to
+  generic entry") has not been applied â€” syscall dispatch is in
+  assembly (entry.S), not in C (syscall.c). The equivalent to
+  array_index_nospec() is implemented using the same clgr/slbgr/ngr.
+
+  SVC 0 path: the user-controlled syscall number in r1 is clamped via
+  a single unsigned compare (clgr) followed by slbgr/ngr. The original
+  cghi/jnl bounds check branch is replaced â€” the clamp handles both
+  cases: in-bounds values pass through, out-of-bounds values are zeroed
+  (producing the same r8=0 dispatch to table[0] as the original branch).
+
+  SVC 1-255 path: syscall number from the 8-bit instruction immediate
+  is always in bounds. ]
+Reviewed-by: Sven Schnelle <svens@linux.ibm.com>
+Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kernel/entry.S |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -420,12 +420,15 @@ ENTRY(system_call)
+       # svc 0: system call number in %r1
+       llgfr   %r1,%r1                         # clear high word in r1
+       sth     %r1,__PT_INT_CODE+2(%r11)
+-      cghi    %r1,NR_syscalls
+-      jnl     .Lsysc_nr_ok
++      lghi    %r0,NR_syscalls-1
++      clgr    %r1,%r0                         # CC0/1 if r1 in bounds
++      slbgr   %r0,%r0                         # mask = -1 in bounds, 0 out of bounds
++      ngr     %r1,%r0                         # clamp r1
+       slag    %r8,%r1,3
+ .Lsysc_nr_ok:
+       stg     %r2,__PT_ORIG_GPR2(%r11)
+       stg     %r7,STACK_FRAME_OVERHEAD(%r15)
++      xgr     %r1,%r1                         # scrub r1, unclamped user value for svc 1-255
+       lg      %r9,0(%r8,%r10)                 # get system call add.
+       TSTMSK  __TI_flags(%r12),_TIF_TRACE
+       jnz     .Lsysc_tracesys
diff --git a/queue-5.10/seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch b/queue-5.10/seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch
new file mode 100644 (file)
index 0000000..0ad9973
--- /dev/null
@@ -0,0 +1,125 @@
+From stable+bounces-235865-greg=kroah.com@vger.kernel.org Mon Apr 13 00:51:51 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 12 Apr 2026 18:51:40 -0400
+Subject: seg6: separate dst_cache for input and output paths in seg6 lwtunnel
+To: stable@vger.kernel.org
+Cc: Andrea Mayer <andrea.mayer@uniroma2.it>, Nicolas Dichtel <nicolas.dichtel@6wind.com>, Justin Iurman <justin.iurman@gmail.com>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260412225140.2461891-1-sashal@kernel.org>
+
+From: Andrea Mayer <andrea.mayer@uniroma2.it>
+
+[ Upstream commit c3812651b522fe8437ebb7063b75ddb95b571643 ]
+
+The seg6 lwtunnel uses a single dst_cache per encap route, shared
+between seg6_input_core() and seg6_output_core(). These two paths
+can perform the post-encap SID lookup in different routing contexts
+(e.g., ip rules matching on the ingress interface, or VRF table
+separation). Whichever path runs first populates the cache, and the
+other reuses it blindly, bypassing its own lookup.
+
+Fix this by splitting the cache into cache_input and cache_output,
+so each path maintains its own cached dst independently.
+
+Fixes: 6c8702c60b88 ("ipv6: sr: add support for SRH encapsulation and injection with lwtunnels")
+Cc: stable@vger.kernel.org
+Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
+Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Reviewed-by: Justin Iurman <justin.iurman@gmail.com>
+Link: https://patch.msgid.link/20260404004405.4057-2-andrea.mayer@uniroma2.it
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ adapted cache field references ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/seg6_iptunnel.c |   34 +++++++++++++++++++++++-----------
+ 1 file changed, 23 insertions(+), 11 deletions(-)
+
+--- a/net/ipv6/seg6_iptunnel.c
++++ b/net/ipv6/seg6_iptunnel.c
+@@ -45,7 +45,8 @@ static size_t seg6_lwt_headroom(struct s
+ }
+ struct seg6_lwt {
+-      struct dst_cache cache;
++      struct dst_cache cache_input;
++      struct dst_cache cache_output;
+       struct seg6_iptunnel_encap tuninfo[];
+ };
+@@ -326,7 +327,7 @@ static int seg6_input(struct sk_buff *sk
+       slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
+       local_bh_disable();
+-      dst = dst_cache_get(&slwt->cache);
++      dst = dst_cache_get(&slwt->cache_input);
+       skb_dst_drop(skb);
+@@ -334,7 +335,7 @@ static int seg6_input(struct sk_buff *sk
+               ip6_route_input(skb);
+               dst = skb_dst(skb);
+               if (!dst->error) {
+-                      dst_cache_set_ip6(&slwt->cache, dst,
++                      dst_cache_set_ip6(&slwt->cache_input, dst,
+                                         &ipv6_hdr(skb)->saddr);
+               }
+       } else {
+@@ -363,7 +364,7 @@ static int seg6_output(struct net *net,
+       slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
+       local_bh_disable();
+-      dst = dst_cache_get(&slwt->cache);
++      dst = dst_cache_get(&slwt->cache_output);
+       local_bh_enable();
+       if (unlikely(!dst)) {
+@@ -384,7 +385,7 @@ static int seg6_output(struct net *net,
+               }
+               local_bh_disable();
+-              dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
++              dst_cache_set_ip6(&slwt->cache_output, dst, &fl6.saddr);
+               local_bh_enable();
+       }
+@@ -461,11 +462,13 @@ static int seg6_build_state(struct net *
+       slwt = seg6_lwt_lwtunnel(newts);
+-      err = dst_cache_init(&slwt->cache, GFP_ATOMIC);
+-      if (err) {
+-              kfree(newts);
+-              return err;
+-      }
++      err = dst_cache_init(&slwt->cache_input, GFP_ATOMIC);
++      if (err)
++              goto err_free_newts;
++
++      err = dst_cache_init(&slwt->cache_output, GFP_ATOMIC);
++      if (err)
++              goto err_destroy_input;
+       memcpy(&slwt->tuninfo, tuninfo, tuninfo_len);
+@@ -480,11 +483,20 @@ static int seg6_build_state(struct net *
+       *ts = newts;
+       return 0;
++
++err_destroy_input:
++      dst_cache_destroy(&slwt->cache_input);
++err_free_newts:
++      kfree(newts);
++      return err;
+ }
+ static void seg6_destroy_state(struct lwtunnel_state *lwt)
+ {
+-      dst_cache_destroy(&seg6_lwt_lwtunnel(lwt)->cache);
++      struct seg6_lwt *slwt = seg6_lwt_lwtunnel(lwt);
++
++      dst_cache_destroy(&slwt->cache_input);
++      dst_cache_destroy(&slwt->cache_output);
+ }
+ static int seg6_fill_encap_info(struct sk_buff *skb,
index ef32c85e161527aa588a9d71dfd13a3757bd31a2..fe0b6aec3b0285a65f4b3a8d617d67fe0331220b 100644 (file)
@@ -458,3 +458,35 @@ xen-privcmd-unregister-xenstore-notifier-on-module-exit.patch
 asoc-soc-core-don-t-use-discriminatory-terms-on-snd_soc_runtime_get_dai_fmt.patch
 asoc-tegra-fix-master-volume-control.patch
 netlink-add-nla-be16-32-types-to-minlen-array.patch
+cpufreq-governor-free-dbs_data-directly-when-gov-init-fails.patch
+cpufreq-governor-fix-double-free-in-cpufreq_dbs_governor_init-error-path.patch
+seg6-separate-dst_cache-for-input-and-output-paths-in-seg6-lwtunnel.patch
+net-rfkill-prevent-unlimited-numbers-of-rfkill-events-from-being-created.patch
+usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch
+usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch
+usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch
+net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch
+mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch
+ext4-fix-the-might_sleep-warnings-in-kvfree.patch
+xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch
+xfs-stop-reclaim-before-pushing-ail-during-unmount.patch
+ext4-fix-iloc.bh-leak-in-ext4_fc_replay_inode-error-paths.patch
+ext4-publish-jinode-after-initialization.patch
+bluetooth-l2cap-fix-accepting-multiple-l2cap_ecred_conn_req.patch
+drm-fix-use-after-free-on-framebuffers-and-property-blobs-when-calling-drm_dev_unplug.patch
+mmc-core-drop-redundant-member-in-struct-mmc-host.patch
+mmc-core-drop-superfluous-validations-in-mmc_hw-sw_reset.patch
+mmc-core-drop-reference-counting-of-the-bus_ops.patch
+mmc-core-avoid-bitfield-rmw-for-claim-retune-flags.patch
+revert-nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch
+nvme-nvme-fc-ensure-ioerr_work-is-cancelled-in-nvme_fc_delete_ctrl.patch
+device-property-add-fwnode_is_ancestor_of-and-fwnode_get_next_parent_dev.patch
+media-device-property-return-true-in-fwnode_device_is_available-for-null-ops.patch
+device-property-retrieve-fwnode-from-of_node-via-accessor.patch
+device-property-unify-access-to-of_node.patch
+device-property-check-fwnode-secondary-in-fwnode_graph_get_next_endpoint.patch
+device-property-check-fwnode-secondary-when-finding-properties.patch
+device-property-allow-error-pointer-to-be-passed-to-fwnode-apis.patch
+device-property-allow-secondary-lookup-in-fwnode_get_next_child_node.patch
+batman-adv-avoid-ogm-aggregation-when-skb-tailroom-is-insufficient.patch
+s390-syscalls-add-spectre-boundary-for-syscall-dispatch-table.patch
diff --git a/queue-5.10/usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch b/queue-5.10/usb-gadget-f_hid-move-list-and-spinlock-inits-from-bind-to-alloc.patch
new file mode 100644 (file)
index 0000000..adecd7e
--- /dev/null
@@ -0,0 +1,72 @@
+From stable+bounces-235809-greg=kroah.com@vger.kernel.org Sun Apr 12 14:11:25 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 12 Apr 2026 08:11:18 -0400
+Subject: usb: gadget: f_hid: move list and spinlock inits from bind to alloc
+To: stable@vger.kernel.org
+Cc: Michael Zimmermann <sigmaepsilon92@gmail.com>, stable <stable@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260412121118.2103786-1-sashal@kernel.org>
+
+From: Michael Zimmermann <sigmaepsilon92@gmail.com>
+
+[ Upstream commit 4e0a88254ad59f6c53a34bf5fa241884ec09e8b2 ]
+
+There was an issue when you did the following:
+- setup and bind an hid gadget
+- open /dev/hidg0
+- use the resulting fd in EPOLL_CTL_ADD
+- unbind the UDC
+- bind the UDC
+- use the fd in EPOLL_CTL_DEL
+
+When CONFIG_DEBUG_LIST was enabled, a list_del corruption was reported
+within remove_wait_queue (via ep_remove_wait_queue). After some
+debugging I found out that the queues, which f_hid registers via
+poll_wait were the problem. These were initialized using
+init_waitqueue_head inside hidg_bind. So effectively, the bind function
+re-initialized the queues while there were still items in them.
+
+The solution is to move the initialization from hidg_bind to hidg_alloc
+to extend their lifetimes to the lifetime of the function instance.
+
+Additionally, I found many other possibly problematic init calls in the
+bind function, which I moved as well.
+
+Signed-off-by: Michael Zimmermann <sigmaepsilon92@gmail.com>
+Cc: stable <stable@kernel.org>
+Link: https://patch.msgid.link/20260331184844.2388761-1-sigmaepsilon92@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_hid.c |   11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -996,13 +996,8 @@ static int hidg_bind(struct usb_configur
+       if (status)
+               goto fail;
+-      spin_lock_init(&hidg->write_spinlock);
+       hidg->write_pending = 1;
+       hidg->req = NULL;
+-      spin_lock_init(&hidg->read_spinlock);
+-      init_waitqueue_head(&hidg->write_queue);
+-      init_waitqueue_head(&hidg->read_queue);
+-      INIT_LIST_HEAD(&hidg->completed_out_req);
+       /* create char device */
+       cdev_init(&hidg->cdev, &f_hidg_fops);
+@@ -1272,6 +1267,12 @@ static struct usb_function *hidg_alloc(s
+       mutex_lock(&opts->lock);
+       ++opts->refcnt;
++      spin_lock_init(&hidg->write_spinlock);
++      spin_lock_init(&hidg->read_spinlock);
++      init_waitqueue_head(&hidg->write_queue);
++      init_waitqueue_head(&hidg->read_queue);
++      INIT_LIST_HEAD(&hidg->completed_out_req);
++
+       device_initialize(&hidg->dev);
+       hidg->dev.release = hidg_release;
+       hidg->dev.class = hidg_class;
diff --git a/queue-5.10/usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch b/queue-5.10/usb-gadget-u_ether-fix-race-between-gether_disconnect-and-eth_stop.patch
new file mode 100644 (file)
index 0000000..b75b525
--- /dev/null
@@ -0,0 +1,80 @@
+From stable+bounces-235759-greg=kroah.com@vger.kernel.org Sat Apr 11 20:15:50 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Apr 2026 14:14:06 -0400
+Subject: usb: gadget: u_ether: Fix race between gether_disconnect and eth_stop
+To: stable@vger.kernel.org
+Cc: Kuen-Han Tsai <khtsai@google.com>, stable <stable@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260411181406.842742-1-sashal@kernel.org>
+
+From: Kuen-Han Tsai <khtsai@google.com>
+
+[ Upstream commit e1eabb072c75681f78312c484ccfffb7430f206e ]
+
+A race condition between gether_disconnect() and eth_stop() leads to a
+NULL pointer dereference. Specifically, if eth_stop() is triggered
+concurrently while gether_disconnect() is tearing down the endpoints,
+eth_stop() attempts to access the cleared endpoint descriptor, causing
+the following NPE:
+
+  Unable to handle kernel NULL pointer dereference
+  Call trace:
+   __dwc3_gadget_ep_enable+0x60/0x788
+   dwc3_gadget_ep_enable+0x70/0xe4
+   usb_ep_enable+0x60/0x15c
+   eth_stop+0xb8/0x108
+
+Because eth_stop() crashes while holding the dev->lock, the thread
+running gether_disconnect() fails to acquire the same lock and spins
+forever, resulting in a hardlockup:
+
+  Core - Debugging Information for Hardlockup core(7)
+  Call trace:
+   queued_spin_lock_slowpath+0x94/0x488
+   _raw_spin_lock+0x64/0x6c
+   gether_disconnect+0x19c/0x1e8
+   ncm_set_alt+0x68/0x1a0
+   composite_setup+0x6a0/0xc50
+
+The root cause is that the clearing of dev->port_usb in
+gether_disconnect() is delayed until the end of the function.
+
+Move the clearing of dev->port_usb to the very beginning of
+gether_disconnect() while holding dev->lock. This cuts off the link
+immediately, ensuring eth_stop() will see dev->port_usb as NULL and
+safely bail out.
+
+Fixes: 2b3d942c4878 ("usb ethernet gadget: split out network core")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
+Link: https://patch.msgid.link/20260311-gether-disconnect-npe-v1-1-454966adf7c7@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/u_ether.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/gadget/function/u_ether.c
++++ b/drivers/usb/gadget/function/u_ether.c
+@@ -1141,6 +1141,10 @@ void gether_disconnect(struct gether *li
+       DBG(dev, "%s\n", __func__);
++      spin_lock(&dev->lock);
++      dev->port_usb = NULL;
++      spin_unlock(&dev->lock);
++
+       netif_stop_queue(dev->net);
+       netif_carrier_off(dev->net);
+@@ -1178,10 +1182,6 @@ void gether_disconnect(struct gether *li
+       dev->header_len = 0;
+       dev->unwrap = NULL;
+       dev->wrap = NULL;
+-
+-      spin_lock(&dev->lock);
+-      dev->port_usb = NULL;
+-      spin_unlock(&dev->lock);
+ }
+ EXPORT_SYMBOL_GPL(gether_disconnect);
diff --git a/queue-5.10/usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch b/queue-5.10/usb-gadget-uvc-fix-null-pointer-dereference-during-unbind-race.patch
new file mode 100644 (file)
index 0000000..24e5544
--- /dev/null
@@ -0,0 +1,244 @@
+From stable+bounces-235748-greg=kroah.com@vger.kernel.org Sat Apr 11 18:31:44 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Apr 2026 12:31:15 -0400
+Subject: usb: gadget: uvc: fix NULL pointer dereference during unbind race
+To: stable@vger.kernel.org
+Cc: Jimmy Hu <hhhuuu@google.com>, stable <stable@kernel.org>, Alan Stern <stern@rowland.harvard.edu>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260411163115.807395-1-sashal@kernel.org>
+
+From: Jimmy Hu <hhhuuu@google.com>
+
+[ Upstream commit eba2936bbe6b752a31725a9eb5c674ecbf21ee7d ]
+
+Commit b81ac4395bbe ("usb: gadget: uvc: allow for application to cleanly
+shutdown") introduced two stages of synchronization waits totaling 1500ms
+in uvc_function_unbind() to prevent several types of kernel panics.
+However, this timing-based approach is insufficient during power
+management (PM) transitions.
+
+When the PM subsystem starts freezing user space processes, the
+wait_event_interruptible_timeout() is aborted early, which allows the
+unbind thread to proceed and nullify the gadget pointer
+(cdev->gadget = NULL):
+
+[  814.123447][  T947] configfs-gadget.g1 gadget.0: uvc: uvc_function_unbind()
+[  814.178583][ T3173] PM: suspend entry (deep)
+[  814.192487][ T3173] Freezing user space processes
+[  814.197668][  T947] configfs-gadget.g1 gadget.0: uvc: uvc_function_unbind no clean disconnect, wait for release
+
+When the PM subsystem resumes or aborts the suspend and tasks are
+restarted, the V4L2 release path is executed and attempts to access the
+already nullified gadget pointer, triggering a kernel panic:
+
+[  814.292597][    C0] PM: pm_system_irq_wakeup: 479 triggered dhdpcie_host_wake
+[  814.386727][ T3173] Restarting tasks ...
+[  814.403522][ T4558] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000030
+[  814.404021][ T4558] pc : usb_gadget_deactivate+0x14/0xf4
+[  814.404031][ T4558] lr : usb_function_deactivate+0x54/0x94
+[  814.404078][ T4558] Call trace:
+[  814.404080][ T4558]  usb_gadget_deactivate+0x14/0xf4
+[  814.404083][ T4558]  usb_function_deactivate+0x54/0x94
+[  814.404087][ T4558]  uvc_function_disconnect+0x1c/0x5c
+[  814.404092][ T4558]  uvc_v4l2_release+0x44/0xac
+[  814.404095][ T4558]  v4l2_release+0xcc/0x130
+
+Address the race condition and NULL pointer dereference by:
+
+1. State Synchronization (flag + mutex)
+Introduce a 'func_unbound' flag in struct uvc_device. This allows
+uvc_function_disconnect() to safely skip accessing the nullified
+cdev->gadget pointer. As suggested by Alan Stern, this flag is protected
+by a new mutex (uvc->lock) to ensure proper memory ordering and prevent
+instruction reordering or speculative loads. This mutex is also used to
+protect 'func_connected' for consistent state management.
+
+2. Explicit Synchronization (completion)
+Use a completion to synchronize uvc_function_unbind() with the
+uvc_vdev_release() callback. This prevents Use-After-Free (UAF) by
+ensuring struct uvc_device is freed after all video device resources
+are released.
+
+Fixes: b81ac4395bbe ("usb: gadget: uvc: allow for application to cleanly shutdown")
+Cc: stable <stable@kernel.org>
+Suggested-by: Alan Stern <stern@rowland.harvard.edu>
+Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jimmy Hu <hhhuuu@google.com>
+Link: https://patch.msgid.link/20260320065427.1374555-1-hhhuuu@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ replaced guard()/scoped_guard() macros ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_uvc.c    |   46 ++++++++++++++++++++++++++++++---
+ drivers/usb/gadget/function/uvc.h      |    3 ++
+ drivers/usb/gadget/function/uvc_v4l2.c |   13 +++++++--
+ 3 files changed, 56 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_uvc.c
++++ b/drivers/usb/gadget/function/f_uvc.c
+@@ -393,6 +393,14 @@ uvc_function_disconnect(struct uvc_devic
+ {
+       int ret;
++      mutex_lock(&uvc->lock);
++      if (uvc->func_unbound) {
++              dev_dbg(&uvc->vdev.dev, "skipping function deactivate (unbound)\n");
++              mutex_unlock(&uvc->lock);
++              return;
++      }
++      mutex_unlock(&uvc->lock);
++
+       if ((ret = usb_function_deactivate(&uvc->func)) < 0)
+               uvcg_info(&uvc->func, "UVC disconnect failed with %d\n", ret);
+ }
+@@ -411,6 +419,15 @@ static ssize_t function_name_show(struct
+ static DEVICE_ATTR_RO(function_name);
++static void uvc_vdev_release(struct video_device *vdev)
++{
++      struct uvc_device *uvc = video_get_drvdata(vdev);
++
++      /* Signal uvc_function_unbind() that the video device has been released */
++      if (uvc->vdev_release_done)
++              complete(uvc->vdev_release_done);
++}
++
+ static int
+ uvc_register_video(struct uvc_device *uvc)
+ {
+@@ -421,7 +438,7 @@ uvc_register_video(struct uvc_device *uv
+       uvc->vdev.v4l2_dev = &uvc->v4l2_dev;
+       uvc->vdev.fops = &uvc_v4l2_fops;
+       uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops;
+-      uvc->vdev.release = video_device_release_empty;
++      uvc->vdev.release = uvc_vdev_release;
+       uvc->vdev.vfl_dir = VFL_DIR_TX;
+       uvc->vdev.lock = &uvc->video.mutex;
+       uvc->vdev.device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+@@ -595,6 +612,9 @@ uvc_function_bind(struct usb_configurati
+       int ret = -EINVAL;
+       uvcg_info(f, "%s()\n", __func__);
++      mutex_lock(&uvc->lock);
++      uvc->func_unbound = false;
++      mutex_unlock(&uvc->lock);
+       opts = fi_to_f_uvc_opts(f->fi);
+       /* Sanity check the streaming endpoint module parameters.
+@@ -887,18 +907,25 @@ static void uvc_free(struct usb_function
+ static void uvc_function_unbind(struct usb_configuration *c,
+                               struct usb_function *f)
+ {
++      DECLARE_COMPLETION_ONSTACK(vdev_release_done);
+       struct usb_composite_dev *cdev = c->cdev;
+       struct uvc_device *uvc = to_uvc(f);
+       long wait_ret = 1;
++      bool connected;
+       uvcg_info(f, "%s()\n", __func__);
++      mutex_lock(&uvc->lock);
++      uvc->func_unbound = true;
++      uvc->vdev_release_done = &vdev_release_done;
++      connected = uvc->func_connected;
++      mutex_unlock(&uvc->lock);
+       /* If we know we're connected via v4l2, then there should be a cleanup
+        * of the device from userspace either via UVC_EVENT_DISCONNECT or
+        * though the video device removal uevent. Allow some time for the
+        * application to close out before things get deleted.
+        */
+-      if (uvc->func_connected) {
++      if (connected) {
+               uvcg_dbg(f, "waiting for clean disconnect\n");
+               wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue,
+                               uvc->func_connected == false, msecs_to_jiffies(500));
+@@ -909,8 +936,13 @@ static void uvc_function_unbind(struct u
+       video_unregister_device(&uvc->vdev);
+       v4l2_device_unregister(&uvc->v4l2_dev);
+-      if (uvc->func_connected) {
+-              /* Wait for the release to occur to ensure there are no longer any
++      mutex_lock(&uvc->lock);
++      connected = uvc->func_connected;
++      mutex_unlock(&uvc->lock);
++
++      if (connected) {
++              /*
++               * Wait for the release to occur to ensure there are no longer any
+                * pending operations that may cause panics when resources are cleaned
+                * up.
+                */
+@@ -920,6 +952,10 @@ static void uvc_function_unbind(struct u
+               uvcg_dbg(f, "done waiting for release with ret: %ld\n", wait_ret);
+       }
++      /* Wait for the video device to be released */
++      wait_for_completion(&vdev_release_done);
++      uvc->vdev_release_done = NULL;
++
+       usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
+       kfree(uvc->control_buf);
+@@ -937,6 +973,8 @@ static struct usb_function *uvc_alloc(st
+               return ERR_PTR(-ENOMEM);
+       mutex_init(&uvc->video.mutex);
++      mutex_init(&uvc->lock);
++      uvc->func_unbound = true;
+       uvc->state = UVC_STATE_DISCONNECTED;
+       init_waitqueue_head(&uvc->func_connected_queue);
+       opts = fi_to_f_uvc_opts(fi);
+--- a/drivers/usb/gadget/function/uvc.h
++++ b/drivers/usb/gadget/function/uvc.h
+@@ -118,6 +118,9 @@ struct uvc_device {
+       enum uvc_state state;
+       struct usb_function func;
+       struct uvc_video video;
++      struct completion *vdev_release_done;
++      struct mutex lock;      /* protects func_unbound and func_connected */
++      bool func_unbound;
+       bool func_connected;
+       wait_queue_head_t func_connected_queue;
+--- a/drivers/usb/gadget/function/uvc_v4l2.c
++++ b/drivers/usb/gadget/function/uvc_v4l2.c
+@@ -234,12 +234,18 @@ uvc_v4l2_subscribe_event(struct v4l2_fh
+       if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST)
+               return -EINVAL;
+-      if (sub->type == UVC_EVENT_SETUP && uvc->func_connected)
++      mutex_lock(&uvc->lock);
++
++      if (sub->type == UVC_EVENT_SETUP && uvc->func_connected) {
++              mutex_unlock(&uvc->lock);
+               return -EBUSY;
++      }
+       ret = v4l2_event_subscribe(fh, sub, 2, NULL);
+-      if (ret < 0)
++      if (ret < 0) {
++              mutex_unlock(&uvc->lock);
+               return ret;
++      }
+       if (sub->type == UVC_EVENT_SETUP) {
+               uvc->func_connected = true;
+@@ -247,6 +253,7 @@ uvc_v4l2_subscribe_event(struct v4l2_fh
+               uvc_function_connect(uvc);
+       }
++      mutex_unlock(&uvc->lock);
+       return 0;
+ }
+@@ -255,7 +262,9 @@ static void uvc_v4l2_disable(struct uvc_
+       uvc_function_disconnect(uvc);
+       uvcg_video_enable(&uvc->video, 0);
+       uvcg_free_buffers(&uvc->video.queue);
++      mutex_lock(&uvc->lock);
+       uvc->func_connected = false;
++      mutex_unlock(&uvc->lock);
+       wake_up_interruptible(&uvc->func_connected_queue);
+ }
diff --git a/queue-5.10/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch b/queue-5.10/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch
new file mode 100644 (file)
index 0000000..5b89864
--- /dev/null
@@ -0,0 +1,100 @@
+From stable+bounces-232961-greg=kroah.com@vger.kernel.org Thu Apr  2 11:44:42 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  2 Apr 2026 05:44:17 -0400
+Subject: xfs: save ailp before dropping the AIL lock in push callbacks
+To: stable@vger.kernel.org
+Cc: Yuto Ohnuki <ytohnuki@amazon.com>, syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com, "Darrick J. Wong" <djwong@kernel.org>, Dave Chinner <dchinner@redhat.com>, Carlos Maiolino <cem@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260402094417.718088-1-sashal@kernel.org>
+
+From: Yuto Ohnuki <ytohnuki@amazon.com>
+
+[ Upstream commit 394d70b86fae9fe865e7e6d9540b7696f73aa9b6 ]
+
+In xfs_inode_item_push() and xfs_qm_dquot_logitem_push(), the AIL lock
+is dropped to perform buffer IO. Once the cluster buffer no longer
+protects the log item from reclaim, the log item may be freed by
+background reclaim or the dquot shrinker. The subsequent spin_lock()
+call dereferences lip->li_ailp, which is a use-after-free.
+
+Fix this by saving the ailp pointer in a local variable while the AIL
+lock is held and the log item is guaranteed to be valid.
+
+Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c
+Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary")
+Cc: stable@vger.kernel.org # v5.9
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Dave Chinner <dchinner@redhat.com>
+Signed-off-by: Yuto Ohnuki <ytohnuki@amazon.com>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_dquot_item.c |    9 +++++++--
+ fs/xfs/xfs_inode_item.c |    9 +++++++--
+ 2 files changed, 14 insertions(+), 4 deletions(-)
+
+--- a/fs/xfs/xfs_dquot_item.c
++++ b/fs/xfs/xfs_dquot_item.c
+@@ -124,6 +124,7 @@ xfs_qm_dquot_logitem_push(
+ {
+       struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
+       struct xfs_buf          *bp = lip->li_buf;
++      struct xfs_ail          *ailp = lip->li_ailp;
+       uint                    rval = XFS_ITEM_SUCCESS;
+       int                     error;
+@@ -152,7 +153,7 @@ xfs_qm_dquot_logitem_push(
+               goto out_unlock;
+       }
+-      spin_unlock(&lip->li_ailp->ail_lock);
++      spin_unlock(&ailp->ail_lock);
+       error = xfs_qm_dqflush(dqp, &bp);
+       if (!error) {
+@@ -162,7 +163,11 @@ xfs_qm_dquot_logitem_push(
+       } else if (error == -EAGAIN)
+               rval = XFS_ITEM_LOCKED;
+-      spin_lock(&lip->li_ailp->ail_lock);
++      /*
++       * The buffer no longer protects the log item from reclaim, so
++       * do not reference lip after this point.
++       */
++      spin_lock(&ailp->ail_lock);
+ out_unlock:
+       xfs_dqunlock(dqp);
+       return rval;
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -514,6 +514,7 @@ xfs_inode_item_push(
+       struct xfs_inode_log_item *iip = INODE_ITEM(lip);
+       struct xfs_inode        *ip = iip->ili_inode;
+       struct xfs_buf          *bp = lip->li_buf;
++      struct xfs_ail          *ailp = lip->li_ailp;
+       uint                    rval = XFS_ITEM_SUCCESS;
+       int                     error;
+@@ -529,7 +530,7 @@ xfs_inode_item_push(
+       if (!xfs_buf_trylock(bp))
+               return XFS_ITEM_LOCKED;
+-      spin_unlock(&lip->li_ailp->ail_lock);
++      spin_unlock(&ailp->ail_lock);
+       /*
+        * We need to hold a reference for flushing the cluster buffer as it may
+@@ -553,7 +554,11 @@ xfs_inode_item_push(
+               rval = XFS_ITEM_LOCKED;
+       }
+-      spin_lock(&lip->li_ailp->ail_lock);
++      /*
++       * The buffer no longer protects the log item from reclaim, so
++       * do not reference lip after this point.
++       */
++      spin_lock(&ailp->ail_lock);
+       return rval;
+ }
diff --git a/queue-5.10/xfs-stop-reclaim-before-pushing-ail-during-unmount.patch b/queue-5.10/xfs-stop-reclaim-before-pushing-ail-during-unmount.patch
new file mode 100644 (file)
index 0000000..b1feb02
--- /dev/null
@@ -0,0 +1,62 @@
+From stable+bounces-232938-greg=kroah.com@vger.kernel.org Thu Apr  2 10:34:53 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  2 Apr 2026 04:32:18 -0400
+Subject: xfs: stop reclaim before pushing AIL during unmount
+To: stable@vger.kernel.org
+Cc: Yuto Ohnuki <ytohnuki@amazon.com>, syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com, "Darrick J. Wong" <djwong@kernel.org>, Carlos Maiolino <cem@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260402083218.458355-1-sashal@kernel.org>
+
+From: Yuto Ohnuki <ytohnuki@amazon.com>
+
+[ Upstream commit 4f24a767e3d64a5f58c595b5c29b6063a201f1e3 ]
+
+The unmount sequence in xfs_unmount_flush_inodes() pushed the AIL while
+background reclaim and inodegc are still running. This is broken
+independently of any use-after-free issues - background reclaim and
+inodegc should not be running while the AIL is being pushed during
+unmount, as inodegc can dirty and insert inodes into the AIL during the
+flush, and background reclaim can race to abort and free dirty inodes.
+
+Reorder xfs_unmount_flush_inodes() to stop inodegc and cancel background
+reclaim before pushing the AIL. Stop inodegc before cancelling
+m_reclaim_work because the inodegc worker can re-queue m_reclaim_work
+via xfs_inodegc_set_reclaimable.
+
+Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c
+Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary")
+Cc: stable@vger.kernel.org # v5.9
+Signed-off-by: Yuto Ohnuki <ytohnuki@amazon.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+[ dropped xfs_inodegc_stop() call ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_mount.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/fs/xfs/xfs_mount.c
++++ b/fs/xfs/xfs_mount.c
+@@ -652,8 +652,9 @@ xfs_check_summary_counts(
+  * have been retrying in the background.  This will prevent never-ending
+  * retries in AIL pushing from hanging the unmount.
+  *
+- * Finally, we can push the AIL to clean all the remaining dirty objects, then
+- * reclaim the remaining inodes that are still in memory at this point in time.
++ * Stop inodegc and background reclaim before pushing the AIL so that they
++ * are not running while the AIL is being flushed. Then push the AIL to
++ * clean all the remaining dirty objects and reclaim the remaining inodes.
+  */
+ static void
+ xfs_unmount_flush_inodes(
+@@ -665,8 +666,8 @@ xfs_unmount_flush_inodes(
+       mp->m_flags |= XFS_MOUNT_UNMOUNTING;
+-      xfs_ail_push_all_sync(mp->m_ail);
+       cancel_delayed_work_sync(&mp->m_reclaim_work);
++      xfs_ail_push_all_sync(mp->m_ail);
+       xfs_reclaim_inodes(mp);
+       xfs_health_unmount(mp);
+ }