]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.10
authorSasha Levin <sashal@kernel.org>
Sun, 11 Aug 2024 12:55:08 +0000 (08:55 -0400)
committerSasha Levin <sashal@kernel.org>
Sun, 11 Aug 2024 12:55:08 +0000 (08:55 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
123 files changed:
queue-6.10/acpi-battery-create-alarm-sysfs-attribute-atomically.patch [new file with mode: 0644]
queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch [new file with mode: 0644]
queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch-7833 [new file with mode: 0644]
queue-6.10/acpi-sbs-manage-alarm-sysfs-attribute-through-psy-co.patch [new file with mode: 0644]
queue-6.10/af_unix-don-t-retry-after-unix_state_lock_nested-in-.patch [new file with mode: 0644]
queue-6.10/block-change-rq_integrity_vec-to-respect-the-iterato.patch [new file with mode: 0644]
queue-6.10/bluetooth-btnxpuart-shutdown-timer-and-prevent-rearm.patch [new file with mode: 0644]
queue-6.10/bluetooth-hci_sync-avoid-dup-filtering-when-passive-.patch [new file with mode: 0644]
queue-6.10/bluetooth-l2cap-always-unlock-channel-in-l2cap_conle.patch [new file with mode: 0644]
queue-6.10/bnxt_en-fix-memory-out-of-bounds-in-bnxt_fill_hw_rss.patch [new file with mode: 0644]
queue-6.10/bpf-add-missing-check_func_arg_reg_off-to-prevent-ou.patch [new file with mode: 0644]
queue-6.10/btrfs-do-not-bug_on-when-freeing-tree-block-after-er.patch [new file with mode: 0644]
queue-6.10/btrfs-do-not-clear-page-dirty-inside-extent_write_lo.patch [new file with mode: 0644]
queue-6.10/btrfs-fix-bitmap-leak-when-loading-free-space-cache-.patch [new file with mode: 0644]
queue-6.10/btrfs-fix-data-race-when-accessing-the-last_trans-fi.patch [new file with mode: 0644]
queue-6.10/btrfs-reduce-nesting-for-extent-processing-at-btrfs_.patch [new file with mode: 0644]
queue-6.10/can-mcp251xfd-tef-prepare-to-workaround-broken-tef-f.patch [new file with mode: 0644]
queue-6.10/can-mcp251xfd-tef-update-workaround-for-erratum-ds80.patch [new file with mode: 0644]
queue-6.10/clocksource-drivers-sh_cmt-address-race-condition-fo.patch [new file with mode: 0644]
queue-6.10/cpufreq-amd-pstate-allow-users-to-write-default-epp-.patch [new file with mode: 0644]
queue-6.10/cpufreq-amd-pstate-auto-load-pstate-driver-by-defaul.patch [new file with mode: 0644]
queue-6.10/debugobjects-annotate-racy-debug-variables.patch [new file with mode: 0644]
queue-6.10/drm-admgpu-fix-dereferencing-null-pointer-context.patch [new file with mode: 0644]
queue-6.10/drm-amd-amdkfd-fix-a-resource-leak-in-svm_range_vali.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-add-delay-to-improve-lttpr-uhbr-inte.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-add-null-check-for-afb-before-derefe.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-add-null-checker-before-passing-vari.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-add-null-checks-for-stream-and-plane.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-don-t-refer-to-dc_sink-in-is_dsc_nee.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-fix-null-pointer-deref-in-dcn20_reso.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-fix-null-pointer-dereference-for-dtn.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-handle-hpd_irq-for-internal-link.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-reduce-odm-slice-count-to-initial-ne.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-remove-dpp-pipes-on-failure-to-updat.patch [new file with mode: 0644]
queue-6.10/drm-amd-display-wake-dmcub-before-sending-a-command-.patch [new file with mode: 0644]
queue-6.10/drm-amd-pm-fix-the-null-pointer-dereference-for-vega.patch [new file with mode: 0644]
queue-6.10/drm-amdgpu-add-lock-around-vf-rlcg-interface.patch [new file with mode: 0644]
queue-6.10/drm-amdgpu-fix-potential-resource-leak-warning.patch [new file with mode: 0644]
queue-6.10/drm-amdgpu-fix-the-null-pointer-dereference-to-ras_m.patch [new file with mode: 0644]
queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-for-s.patch [new file with mode: 0644]
queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-in-ap.patch [new file with mode: 0644]
queue-6.10/drm-amdgpu-pm-fix-the-param-type-of-set_power_profil.patch [new file with mode: 0644]
queue-6.10/drm-xe-preempt_fence-enlarge-the-fence-critical-sect.patch [new file with mode: 0644]
queue-6.10/drm-xe-xe_guc_submit-fix-exec-queue-stop-race-condit.patch [new file with mode: 0644]
queue-6.10/ext4-fix-uninitialized-variable-in-ext4_inlinedir_to.patch [new file with mode: 0644]
queue-6.10/ext4-sanity-check-for-null-pointer-after-ext4_force_.patch [new file with mode: 0644]
queue-6.10/gpio-prevent-potential-speculation-leaks-in-gpio_dev.patch [new file with mode: 0644]
queue-6.10/gve-fix-use-of-netif_carrier_ok.patch [new file with mode: 0644]
queue-6.10/hwmon-corsair-psu-add-usb-id-of-hx1200i-series-2023-.patch [new file with mode: 0644]
queue-6.10/ice-fix-reset-handler.patch [new file with mode: 0644]
queue-6.10/idpf-fix-memory-leaks-and-crashes-while-performing-a.patch [new file with mode: 0644]
queue-6.10/idpf-fix-uafs-when-destroying-the-queues.patch [new file with mode: 0644]
queue-6.10/irqchip-gic-v3-don-t-return-errors-from-gic_acpi_mat.patch [new file with mode: 0644]
queue-6.10/irqchip-mbigen-fix-mbigen-node-address-layout.patch [new file with mode: 0644]
queue-6.10/jbd2-avoid-memleak-in-jbd2_journal_write_metadata_bu.patch [new file with mode: 0644]
queue-6.10/jump_label-fix-the-fix-brown-paper-bags-galore.patch [new file with mode: 0644]
queue-6.10/l2tp-fix-lockdep-splat.patch [new file with mode: 0644]
queue-6.10/locking-pvqspinlock-correct-the-type-of-old-variable.patch [new file with mode: 0644]
queue-6.10/md-change-the-return-value-type-of-md_write_start-to.patch [new file with mode: 0644]
queue-6.10/md-do-not-delete-safemode_timer-in-mddev_suspend.patch [new file with mode: 0644]
queue-6.10/md-raid5-avoid-bug_on-while-continue-reshape-after-r.patch [new file with mode: 0644]
queue-6.10/media-amphion-remove-lock-in-s_ctrl-callback.patch [new file with mode: 0644]
queue-6.10/media-i2c-ov5647-replacing-of_node_put-with-__free-d.patch [new file with mode: 0644]
queue-6.10/media-uvcvideo-fix-the-bandwdith-quirk-on-usb-3.x.patch [new file with mode: 0644]
queue-6.10/media-uvcvideo-ignore-empty-ts-packets.patch [new file with mode: 0644]
queue-6.10/media-xc2028-avoid-use-after-free-in-load_firmware_c.patch [new file with mode: 0644]
queue-6.10/mlxsw-pci-lock-configuration-space-of-upstream-bridg.patch [new file with mode: 0644]
queue-6.10/net-bcmgenet-properly-overlay-phy-and-mac-wake-on-la.patch [new file with mode: 0644]
queue-6.10/net-bridge-mcast-wait-for-previous-gc-cycles-when-re.patch [new file with mode: 0644]
queue-6.10/net-dsa-bcm_sf2-fix-a-possible-memory-leak-in-bcm_sf.patch [new file with mode: 0644]
queue-6.10/net-dsa-microchip-disable-eee-for-ksz8567-ksz9567-ks.patch [new file with mode: 0644]
queue-6.10/net-dsa-microchip-fix-wake-on-lan-check-to-not-retur.patch [new file with mode: 0644]
queue-6.10/net-fec-stop-pps-on-driver-remove.patch [new file with mode: 0644]
queue-6.10/net-linkwatch-use-system_unbound_wq.patch [new file with mode: 0644]
queue-6.10/net-mlx5e-shampo-fix-invalid-wq-linked-list-unlink.patch [new file with mode: 0644]
queue-6.10/net-pse-pd-tps23881-fix-the-device-id-check.patch [new file with mode: 0644]
queue-6.10/net-pse-pd-tps23881-include-missing-bitfield.h-heade.patch [new file with mode: 0644]
queue-6.10/net-reference-bpf_redirect_info-via-task_struct-on-p.patch [new file with mode: 0644]
queue-6.10/net-smc-add-the-max-value-of-fallback-reason-count.patch [new file with mode: 0644]
queue-6.10/net-stmmac-qcom-ethqos-enable-sgmii-loopback-during-.patch [new file with mode: 0644]
queue-6.10/net-usb-qmi_wwan-fix-memory-leak-for-not-ip-packets.patch [new file with mode: 0644]
queue-6.10/nvme-apple-fix-device-reference-counting.patch [new file with mode: 0644]
queue-6.10/pci-add-edimax-vendor-id-to-pci_ids.h.patch [new file with mode: 0644]
queue-6.10/perf-x86-amd-use-try_cmpxchg-in-events-amd-un-core.c.patch [new file with mode: 0644]
queue-6.10/perf-x86-fix-smp_processor_id-in-preemptible-warning.patch [new file with mode: 0644]
queue-6.10/perf-x86-intel-cstate-add-arrowlake-support.patch [new file with mode: 0644]
queue-6.10/perf-x86-intel-cstate-add-lunarlake-support.patch [new file with mode: 0644]
queue-6.10/perf-x86-intel-cstate-add-pkg-c2-residency-counter-f.patch [new file with mode: 0644]
queue-6.10/perf-x86-intel-support-the-pebs-event-mask.patch [new file with mode: 0644]
queue-6.10/perf-x86-support-counter-mask.patch [new file with mode: 0644]
queue-6.10/platform-chrome-cros_ec_lpc-add-a-new-quirk-for-acpi.patch [new file with mode: 0644]
queue-6.10/platform-x86-intel-ifs-initialize-union-ifs_status-t.patch [new file with mode: 0644]
queue-6.10/platform-x86-intel-vbtn-protect-acpi-notify-handler-.patch [new file with mode: 0644]
queue-6.10/power-supply-rt5033-bring-back-i2c_set_clientdata.patch [new file with mode: 0644]
queue-6.10/r8169-remove-detection-of-chip-version-11-early-rtl8.patch [new file with mode: 0644]
queue-6.10/rcu-fix-rcu_barrier-vs-post-cpuhp_teardown_cpu-invoc.patch [new file with mode: 0644]
queue-6.10/rcutorture-fix-rcu_torture_fwd_cb_cr-data-race.patch [new file with mode: 0644]
queue-6.10/regmap-kunit-fix-memory-leaks-in-gen_regmap-and-gen_.patch [new file with mode: 0644]
queue-6.10/revert-rcu-tasks-fix-synchronize_rcu_tasks-vs-zap_pi.patch [new file with mode: 0644]
queue-6.10/rtnetlink-move-rtnl_lock-handling-out-of-af_netlink.patch [new file with mode: 0644]
queue-6.10/s390-sclp-prevent-release-of-buffer-in-i-o.patch [new file with mode: 0644]
queue-6.10/sctp-fix-null-ptr-deref-in-reuseport_add_sock.patch [new file with mode: 0644]
queue-6.10/selftests-bpf-fix-send_signal-test-with-nested-confi.patch [new file with mode: 0644]
queue-6.10/selftests-ksft-fix-finished-helper-exit-code-on-skip.patch [new file with mode: 0644]
queue-6.10/selftests-mptcp-join-ability-to-invert-add_addr-chec.patch [new file with mode: 0644]
queue-6.10/selftests-mptcp-join-test-both-signal-subflow.patch [new file with mode: 0644]
queue-6.10/series
queue-6.10/smb-client-handle-lack-of-fsctl_get_reparse_point-su.patch [new file with mode: 0644]
queue-6.10/soc-qcom-icc-bwmon-allow-for-interrupts-to-be-shared.patch [new file with mode: 0644]
queue-6.10/sunrpc-fix-a-race-to-wake-a-sync-task.patch [new file with mode: 0644]
queue-6.10/thermal-intel-hfi-give-hfi-instances-package-scope.patch [new file with mode: 0644]
queue-6.10/udf-prevent-integer-overflow-in-udf_bitmap_free_bloc.patch [new file with mode: 0644]
queue-6.10/virtio-net-unbreak-vq-resizing-when-coalescing-is-no.patch [new file with mode: 0644]
queue-6.10/wifi-ath12k-fix-memory-leak-in-ath12k_dp_rx_peer_fra.patch [new file with mode: 0644]
queue-6.10/wifi-ath12k-fix-race-due-to-setting-ath12k_flag_ext_.patch [new file with mode: 0644]
queue-6.10/wifi-mac80211-fix-null-dereference-at-band-check-in-.patch [new file with mode: 0644]
queue-6.10/wifi-nl80211-disallow-setting-special-ap-channel-wid.patch [new file with mode: 0644]
queue-6.10/wifi-nl80211-don-t-give-key-data-to-userspace.patch [new file with mode: 0644]
queue-6.10/wifi-rtlwifi-handle-return-value-of-usb-init-tx-rx.patch [new file with mode: 0644]
queue-6.10/wifi-rtw89-pci-fix-rx-tag-race-condition-resulting-i.patch [new file with mode: 0644]
queue-6.10/x86-mm-fix-pti_clone_entry_text-for-i386.patch [new file with mode: 0644]
queue-6.10/x86-mm-fix-pti_clone_pgtable-alignment-assumption.patch [new file with mode: 0644]
queue-6.10/xen-privcmd-switch-from-mutex-to-spinlock-for-irqfds.patch [new file with mode: 0644]

diff --git a/queue-6.10/acpi-battery-create-alarm-sysfs-attribute-atomically.patch b/queue-6.10/acpi-battery-create-alarm-sysfs-attribute-atomically.patch
new file mode 100644 (file)
index 0000000..620a72a
--- /dev/null
@@ -0,0 +1,79 @@
+From 9839095f50202ea752d4ed6d18e4b358ba2c952e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Jun 2024 09:27:16 +0200
+Subject: ACPI: battery: create alarm sysfs attribute atomically
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit a231eed10ed5a290129fda36ad7bcc263c53ff7d ]
+
+Let the power supply core register the attribute.
+This ensures that the attribute is created before the device is
+announced to userspace, avoid a race condition.
+
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/battery.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
+index b379401ff1c20..44ca989f16466 100644
+--- a/drivers/acpi/battery.c
++++ b/drivers/acpi/battery.c
+@@ -678,12 +678,18 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
+       return count;
+ }
+-static const struct device_attribute alarm_attr = {
++static struct device_attribute alarm_attr = {
+       .attr = {.name = "alarm", .mode = 0644},
+       .show = acpi_battery_alarm_show,
+       .store = acpi_battery_alarm_store,
+ };
++static struct attribute *acpi_battery_attrs[] = {
++      &alarm_attr.attr,
++      NULL
++};
++ATTRIBUTE_GROUPS(acpi_battery);
++
+ /*
+  * The Battery Hooking API
+  *
+@@ -823,7 +829,10 @@ static void __exit battery_hook_exit(void)
+ static int sysfs_add_battery(struct acpi_battery *battery)
+ {
+-      struct power_supply_config psy_cfg = { .drv_data = battery, };
++      struct power_supply_config psy_cfg = {
++              .drv_data = battery,
++              .attr_grp = acpi_battery_groups,
++      };
+       bool full_cap_broken = false;
+       if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
+@@ -868,7 +877,7 @@ static int sysfs_add_battery(struct acpi_battery *battery)
+               return result;
+       }
+       battery_hook_add_battery(battery);
+-      return device_create_file(&battery->bat->dev, &alarm_attr);
++      return 0;
+ }
+ static void sysfs_remove_battery(struct acpi_battery *battery)
+@@ -879,7 +888,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
+               return;
+       }
+       battery_hook_remove_battery(battery);
+-      device_remove_file(&battery->bat->dev, &alarm_attr);
+       power_supply_unregister(battery->bat);
+       battery->bat = NULL;
+       mutex_unlock(&battery->sysfs_lock);
+-- 
+2.43.0
+
diff --git a/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch b/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch
new file mode 100644 (file)
index 0000000..b4c0518
--- /dev/null
@@ -0,0 +1,46 @@
+From 523d65eb01f501ea407c1d38b8916cb31d08ce72 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jul 2024 08:58:06 -0400
+Subject: ACPI: resource: Skip IRQ override on Asus Vivobook Pro N6506MU
+
+From: Tamim Khan <tamim@fusetak.com>
+
+[ Upstream commit dc41751f9e07889d078e3f06adb6e892c80b7c10 ]
+
+Like various other Asus laptops, the Asus Vivobook Pro N6506MV has a
+DSDT table that describes IRQ 1 as ActiveLow while the kernel is overriding
+it to Edge_High. This prevents the internal keyboard from working. This patch
+prevents this issue by adding this laptop to the override table that prevents
+the kernel from overriding this IRQ
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=218954
+Tested-by: Lefteris <eleftherios.giapitzakis@gmail.com>
+Signed-off-by: Tamim Khan <tamim@fusetak.com>
+Link: https://patch.msgid.link/20240702125918.34683-1-tamim@fusetak.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/resource.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+index b5bf8b81a050a..b3ae5f9ac5510 100644
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -524,6 +524,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
+                       DMI_MATCH(DMI_BOARD_NAME, "N6506MV"),
+               },
+       },
++      {
++              /* Asus Vivobook Pro N6506MU */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_BOARD_NAME, "N6506MU"),
++              },
++      },
+       {
+               /* LG Electronics 17U70P */
+               .matches = {
+-- 
+2.43.0
+
diff --git a/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch-7833 b/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch-7833
new file mode 100644 (file)
index 0000000..2fff75e
--- /dev/null
@@ -0,0 +1,46 @@
+From 441a4585d061c956fa28eaa5862b4992960abc6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 7 Jul 2024 20:05:50 -0400
+Subject: ACPI: resource: Skip IRQ override on Asus Vivobook Pro N6506MJ
+
+From: Tamim Khan <tamim@fusetak.com>
+
+[ Upstream commit e2e7f037b400aebbb3892d8010fb3d9cae6f426e ]
+
+Similar to other Asus Vivobooks, the Asus Vivobook Pro N6506MJ has a DSDT table
+that describes IRQ 1 as ActiveLow, whereas the kernel overrides it to Edge_High.
+This discrepancy prevents the internal keyboard from functioning properly. This
+patch resolves this issue by adding this laptop to the override table that prevents
+the kernel from overriding this IRQ.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=218929
+Tested-by: Amber Connelly <amb3r.dev@gmail.com>
+Signed-off-by: Tamim Khan <tamim@fusetak.com>
+Link: https://patch.msgid.link/20240708000557.83539-1-tamim@fusetak.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/resource.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+index b3ae5f9ac5510..df5d5a554b388 100644
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -531,6 +531,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
+                       DMI_MATCH(DMI_BOARD_NAME, "N6506MU"),
+               },
+       },
++      {
++              /* Asus Vivobook Pro N6506MJ */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_BOARD_NAME, "N6506MJ"),
++              },
++      },
+       {
+               /* LG Electronics 17U70P */
+               .matches = {
+-- 
+2.43.0
+
diff --git a/queue-6.10/acpi-sbs-manage-alarm-sysfs-attribute-through-psy-co.patch b/queue-6.10/acpi-sbs-manage-alarm-sysfs-attribute-through-psy-co.patch
new file mode 100644 (file)
index 0000000..dc21b32
--- /dev/null
@@ -0,0 +1,95 @@
+From 33ae8199c3dc00979ee1548fc374e2da87180c68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Jun 2024 13:13:28 +0200
+Subject: ACPI: SBS: manage alarm sysfs attribute through psy core
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 6bad28cfc30988a845fb3f59a99f4b8a4ce8fe95 ]
+
+Let the power supply core register the attribute.
+
+This ensures that the attribute is created before the device is
+announced to userspace, avoiding a race condition.
+
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/sbs.c | 23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
+index dc8164b182dcc..442c5905d43be 100644
+--- a/drivers/acpi/sbs.c
++++ b/drivers/acpi/sbs.c
+@@ -77,7 +77,6 @@ struct acpi_battery {
+       u16 spec;
+       u8 id;
+       u8 present:1;
+-      u8 have_sysfs_alarm:1;
+ };
+ #define to_acpi_battery(x) power_supply_get_drvdata(x)
+@@ -462,12 +461,18 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
+       return count;
+ }
+-static const struct device_attribute alarm_attr = {
++static struct device_attribute alarm_attr = {
+       .attr = {.name = "alarm", .mode = 0644},
+       .show = acpi_battery_alarm_show,
+       .store = acpi_battery_alarm_store,
+ };
++static struct attribute *acpi_battery_attrs[] = {
++      &alarm_attr.attr,
++      NULL
++};
++ATTRIBUTE_GROUPS(acpi_battery);
++
+ /* --------------------------------------------------------------------------
+                                  Driver Interface
+    -------------------------------------------------------------------------- */
+@@ -518,7 +523,10 @@ static int acpi_battery_read(struct acpi_battery *battery)
+ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
+ {
+       struct acpi_battery *battery = &sbs->battery[id];
+-      struct power_supply_config psy_cfg = { .drv_data = battery, };
++      struct power_supply_config psy_cfg = {
++              .drv_data = battery,
++              .attr_grp = acpi_battery_groups,
++      };
+       int result;
+       battery->id = id;
+@@ -548,10 +556,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
+               goto end;
+       }
+-      result = device_create_file(&battery->bat->dev, &alarm_attr);
+-      if (result)
+-              goto end;
+-      battery->have_sysfs_alarm = 1;
+       end:
+       pr_info("%s [%s]: Battery Slot [%s] (battery %s)\n",
+              ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
+@@ -563,11 +567,8 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
+ {
+       struct acpi_battery *battery = &sbs->battery[id];
+-      if (battery->bat) {
+-              if (battery->have_sysfs_alarm)
+-                      device_remove_file(&battery->bat->dev, &alarm_attr);
++      if (battery->bat)
+               power_supply_unregister(battery->bat);
+-      }
+ }
+ static int acpi_charger_add(struct acpi_sbs *sbs)
+-- 
+2.43.0
+
diff --git a/queue-6.10/af_unix-don-t-retry-after-unix_state_lock_nested-in-.patch b/queue-6.10/af_unix-don-t-retry-after-unix_state_lock_nested-in-.patch
new file mode 100644 (file)
index 0000000..7263ce7
--- /dev/null
@@ -0,0 +1,139 @@
+From ba95fd74d89f45c1ec46ec9e17e76c1b97f8f778 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jun 2024 13:56:15 -0700
+Subject: af_unix: Don't retry after unix_state_lock_nested() in
+ unix_stream_connect().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 1ca27e0c8c13ac50a4acf9cdf77069e2d94a547d ]
+
+When a SOCK_(STREAM|SEQPACKET) socket connect()s to another one, we need
+to lock the two sockets to check their states in unix_stream_connect().
+
+We use unix_state_lock() for the server and unix_state_lock_nested() for
+client with tricky sk->sk_state check to avoid deadlock.
+
+The possible deadlock scenario are the following:
+
+  1) Self connect()
+  2) Simultaneous connect()
+
+The former is simple, attempt to grab the same lock, and the latter is
+AB-BA deadlock.
+
+After the server's unix_state_lock(), we check the server socket's state,
+and if it's not TCP_LISTEN, connect() fails with -EINVAL.
+
+Then, we avoid the former deadlock by checking the client's state before
+unix_state_lock_nested().  If its state is not TCP_LISTEN, we can make
+sure that the client and the server are not identical based on the state.
+
+Also, the latter deadlock can be avoided in the same way.  Due to the
+server sk->sk_state requirement, AB-BA deadlock could happen only with
+TCP_LISTEN sockets.  So, if the client's state is TCP_LISTEN, we can
+give up the second lock to avoid the deadlock.
+
+  CPU 1                 CPU 2                  CPU 3
+  connect(A -> B)       connect(B -> A)        listen(A)
+  ---                   ---                    ---
+  unix_state_lock(B)
+  B->sk_state == TCP_LISTEN
+  READ_ONCE(A->sk_state) == TCP_CLOSE
+                            ^^^^^^^^^
+                            ok, will lock A    unix_state_lock(A)
+             .--------------'                  WRITE_ONCE(A->sk_state, TCP_LISTEN)
+             |                                 unix_state_unlock(A)
+             |
+             |          unix_state_lock(A)
+             |          A->sk_sk_state == TCP_LISTEN
+             |          READ_ONCE(B->sk_state) == TCP_LISTEN
+             v                                    ^^^^^^^^^^
+  unix_state_lock_nested(A)                       Don't lock B !!
+
+Currently, while checking the client's state, we also check if it's
+TCP_ESTABLISHED, but this is unlikely and can be checked after we know
+the state is not TCP_CLOSE.
+
+Moreover, if it happens after the second lock, we now jump to the restart
+label, but it's unlikely that the server is not found during the retry,
+so the jump is mostly to revist the client state check.
+
+Let's remove the retry logic and check the state against TCP_CLOSE first.
+
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/af_unix.c | 34 +++++++++-------------------------
+ 1 file changed, 9 insertions(+), 25 deletions(-)
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 11cb5badafb6d..be5266007b489 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1473,6 +1473,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+       struct unix_sock *u = unix_sk(sk), *newu, *otheru;
+       struct net *net = sock_net(sk);
+       struct sk_buff *skb = NULL;
++      unsigned char state;
+       long timeo;
+       int err;
+@@ -1523,7 +1524,6 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+               goto out;
+       }
+-      /* Latch state of peer */
+       unix_state_lock(other);
+       /* Apparently VFS overslept socket death. Retry. */
+@@ -1553,37 +1553,21 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+               goto restart;
+       }
+-      /* Latch our state.
+-
+-         It is tricky place. We need to grab our state lock and cannot
+-         drop lock on peer. It is dangerous because deadlock is
+-         possible. Connect to self case and simultaneous
+-         attempt to connect are eliminated by checking socket
+-         state. other is TCP_LISTEN, if sk is TCP_LISTEN we
+-         check this before attempt to grab lock.
+-
+-         Well, and we have to recheck the state after socket locked.
++      /* self connect and simultaneous connect are eliminated
++       * by rejecting TCP_LISTEN socket to avoid deadlock.
+        */
+-      switch (READ_ONCE(sk->sk_state)) {
+-      case TCP_CLOSE:
+-              /* This is ok... continue with connect */
+-              break;
+-      case TCP_ESTABLISHED:
+-              /* Socket is already connected */
+-              err = -EISCONN;
+-              goto out_unlock;
+-      default:
+-              err = -EINVAL;
++      state = READ_ONCE(sk->sk_state);
++      if (unlikely(state != TCP_CLOSE)) {
++              err = state == TCP_ESTABLISHED ? -EISCONN : -EINVAL;
+               goto out_unlock;
+       }
+       unix_state_lock_nested(sk, U_LOCK_SECOND);
+-      if (sk->sk_state != TCP_CLOSE) {
++      if (unlikely(sk->sk_state != TCP_CLOSE)) {
++              err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EINVAL;
+               unix_state_unlock(sk);
+-              unix_state_unlock(other);
+-              sock_put(other);
+-              goto restart;
++              goto out_unlock;
+       }
+       err = security_unix_stream_connect(sk, other, newsk);
+-- 
+2.43.0
+
diff --git a/queue-6.10/block-change-rq_integrity_vec-to-respect-the-iterato.patch b/queue-6.10/block-change-rq_integrity_vec-to-respect-the-iterato.patch
new file mode 100644 (file)
index 0000000..27f5faa
--- /dev/null
@@ -0,0 +1,106 @@
+From 4925f571ef20bb3170a2c62cef6c8f55573d1fe8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 17:40:10 +0200
+Subject: block: change rq_integrity_vec to respect the iterator
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+[ Upstream commit cf546dd289e0f6d2594c25e2fb4e19ee67c6d988 ]
+
+If we allocate a bio that is larger than NVMe maximum request size,
+attach integrity metadata to it and send it to the NVMe subsystem, the
+integrity metadata will be corrupted.
+
+Splitting the bio works correctly. The function bio_split will clone the
+bio, trim the iterator of the first bio and advance the iterator of the
+second bio.
+
+However, the function rq_integrity_vec has a bug - it returns the first
+vector of the bio's metadata and completely disregards the metadata
+iterator that was advanced when the bio was split. Thus, the second bio
+uses the same metadata as the first bio and this leads to metadata
+corruption.
+
+This commit changes rq_integrity_vec, so that it calls mp_bvec_iter_bvec
+instead of returning the first vector. mp_bvec_iter_bvec reads the
+iterator and uses it to build a bvec for the current position in the
+iterator.
+
+The "queue_max_integrity_segments(rq->q) > 1" check was removed, because
+the updated rq_integrity_vec function works correctly with multiple
+segments.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Reviewed-by: Anuj Gupta <anuj20.g@samsung.com>
+Reviewed-by: Kanchan Joshi <joshi.k@samsung.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/49d1afaa-f934-6ed2-a678-e0d428c63a65@redhat.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c       |  6 +++---
+ include/linux/blk-integrity.h | 14 +++++++-------
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 5a93f021ca4f1..7168ff4cc62bb 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -826,9 +826,9 @@ static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req,
+               struct nvme_command *cmnd)
+ {
+       struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
++      struct bio_vec bv = rq_integrity_vec(req);
+-      iod->meta_dma = dma_map_bvec(dev->dev, rq_integrity_vec(req),
+-                      rq_dma_dir(req), 0);
++      iod->meta_dma = dma_map_bvec(dev->dev, &bv, rq_dma_dir(req), 0);
+       if (dma_mapping_error(dev->dev, iod->meta_dma))
+               return BLK_STS_IOERR;
+       cmnd->rw.metadata = cpu_to_le64(iod->meta_dma);
+@@ -968,7 +968,7 @@ static __always_inline void nvme_pci_unmap_rq(struct request *req)
+               struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+               dma_unmap_page(dev->dev, iod->meta_dma,
+-                             rq_integrity_vec(req)->bv_len, rq_dma_dir(req));
++                             rq_integrity_vec(req).bv_len, rq_dma_dir(req));
+       }
+       if (blk_rq_nr_phys_segments(req))
+diff --git a/include/linux/blk-integrity.h b/include/linux/blk-integrity.h
+index 7428cb43952da..d16dd24719841 100644
+--- a/include/linux/blk-integrity.h
++++ b/include/linux/blk-integrity.h
+@@ -100,14 +100,13 @@ static inline bool blk_integrity_rq(struct request *rq)
+ }
+ /*
+- * Return the first bvec that contains integrity data.  Only drivers that are
+- * limited to a single integrity segment should use this helper.
++ * Return the current bvec that contains the integrity data. bip_iter may be
++ * advanced to iterate over the integrity data.
+  */
+-static inline struct bio_vec *rq_integrity_vec(struct request *rq)
++static inline struct bio_vec rq_integrity_vec(struct request *rq)
+ {
+-      if (WARN_ON_ONCE(queue_max_integrity_segments(rq->q) > 1))
+-              return NULL;
+-      return rq->bio->bi_integrity->bip_vec;
++      return mp_bvec_iter_bvec(rq->bio->bi_integrity->bip_vec,
++                               rq->bio->bi_integrity->bip_iter);
+ }
+ #else /* CONFIG_BLK_DEV_INTEGRITY */
+ static inline int blk_rq_count_integrity_sg(struct request_queue *q,
+@@ -169,7 +168,8 @@ static inline int blk_integrity_rq(struct request *rq)
+ static inline struct bio_vec *rq_integrity_vec(struct request *rq)
+ {
+-      return NULL;
++      /* the optimizer will remove all calls to this function */
++      return (struct bio_vec){ };
+ }
+ #endif /* CONFIG_BLK_DEV_INTEGRITY */
+ #endif /* _LINUX_BLK_INTEGRITY_H */
+-- 
+2.43.0
+
diff --git a/queue-6.10/bluetooth-btnxpuart-shutdown-timer-and-prevent-rearm.patch b/queue-6.10/bluetooth-btnxpuart-shutdown-timer-and-prevent-rearm.patch
new file mode 100644 (file)
index 0000000..5b90be7
--- /dev/null
@@ -0,0 +1,70 @@
+From d48078439a68d507c4b74415591eb46c8a316afa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 May 2024 19:15:35 +0800
+Subject: Bluetooth: btnxpuart: Shutdown timer and prevent rearming when driver
+ unloading
+
+From: Luke Wang <ziniu.wang_1@nxp.com>
+
+[ Upstream commit 0d0df1e750bac0fdaa77940e711c1625cff08d33 ]
+
+When unload the btnxpuart driver, its associated timer will be deleted.
+If the timer happens to be modified at this moment, it leads to the
+kernel call this timer even after the driver unloaded, resulting in
+kernel panic.
+Use timer_shutdown_sync() instead of del_timer_sync() to prevent rearming.
+
+panic log:
+  Internal error: Oops: 0000000086000007 [#1] PREEMPT SMP
+  Modules linked in: algif_hash algif_skcipher af_alg moal(O) mlan(O) crct10dif_ce polyval_ce polyval_generic   snd_soc_imx_card snd_soc_fsl_asoc_card snd_soc_imx_audmux mxc_jpeg_encdec v4l2_jpeg snd_soc_wm8962 snd_soc_fsl_micfil   snd_soc_fsl_sai flexcan snd_soc_fsl_utils ap130x rpmsg_ctrl imx_pcm_dma can_dev rpmsg_char pwm_fan fuse [last unloaded:   btnxpuart]
+  CPU: 5 PID: 723 Comm: memtester Tainted: G           O       6.6.23-lts-next-06207-g4aef2658ac28 #1
+  Hardware name: NXP i.MX95 19X19 board (DT)
+  pstate: 20400009 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+  pc : 0xffff80007a2cf464
+  lr : call_timer_fn.isra.0+0x24/0x80
+...
+  Call trace:
+   0xffff80007a2cf464
+   __run_timers+0x234/0x280
+   run_timer_softirq+0x20/0x40
+   __do_softirq+0x100/0x26c
+   ____do_softirq+0x10/0x1c
+   call_on_irq_stack+0x24/0x4c
+   do_softirq_own_stack+0x1c/0x2c
+   irq_exit_rcu+0xc0/0xdc
+   el0_interrupt+0x54/0xd8
+   __el0_irq_handler_common+0x18/0x24
+   el0t_64_irq_handler+0x10/0x1c
+   el0t_64_irq+0x190/0x194
+  Code: ???????? ???????? ???????? ???????? (????????)
+  ---[ end trace 0000000000000000 ]---
+  Kernel panic - not syncing: Oops: Fatal exception in interrupt
+  SMP: stopping secondary CPUs
+  Kernel Offset: disabled
+  CPU features: 0x0,c0000000,40028143,1000721b
+  Memory Limit: none
+  ---[ end Kernel panic - not syncing: Oops: Fatal exception in interrupt ]---
+
+Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btnxpuart.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
+index 6a863328b8053..d310b525fbf00 100644
+--- a/drivers/bluetooth/btnxpuart.c
++++ b/drivers/bluetooth/btnxpuart.c
+@@ -344,7 +344,7 @@ static void ps_cancel_timer(struct btnxpuart_dev *nxpdev)
+       struct ps_data *psdata = &nxpdev->psdata;
+       flush_work(&psdata->work);
+-      del_timer_sync(&psdata->ps_timer);
++      timer_shutdown_sync(&psdata->ps_timer);
+ }
+ static void ps_control(struct hci_dev *hdev, u8 ps_state)
+-- 
+2.43.0
+
diff --git a/queue-6.10/bluetooth-hci_sync-avoid-dup-filtering-when-passive-.patch b/queue-6.10/bluetooth-hci_sync-avoid-dup-filtering-when-passive-.patch
new file mode 100644 (file)
index 0000000..dfc4316
--- /dev/null
@@ -0,0 +1,53 @@
+From 87f2a3176664f2cd87893bd0384841827205f52f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 21:58:10 +0200
+Subject: Bluetooth: hci_sync: avoid dup filtering when passive scanning with
+ adv monitor
+
+From: Anton Khirnov <anton@khirnov.net>
+
+[ Upstream commit b5431dc2803ac159d6d4645ae237d15c3cb252db ]
+
+This restores behaviour (including the comment) from now-removed
+hci_request.c, and also matches existing code for active scanning.
+
+Without this, the duplicates filter is always active when passive
+scanning, which makes it impossible to work with devices that send
+nontrivial dynamic data in their advertisement reports.
+
+Fixes: abfeea476c68 ("Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY")
+Signed-off-by: Anton Khirnov <anton@khirnov.net>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sync.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 2f26147fdf3c9..4e90bd722e7b5 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -2972,6 +2972,20 @@ static int hci_passive_scan_sync(struct hci_dev *hdev)
+       } else if (hci_is_adv_monitoring(hdev)) {
+               window = hdev->le_scan_window_adv_monitor;
+               interval = hdev->le_scan_int_adv_monitor;
++
++              /* Disable duplicates filter when scanning for advertisement
++               * monitor for the following reasons.
++               *
++               * For HW pattern filtering (ex. MSFT), Realtek and Qualcomm
++               * controllers ignore RSSI_Sampling_Period when the duplicates
++               * filter is enabled.
++               *
++               * For SW pattern filtering, when we're not doing interleaved
++               * scanning, it is necessary to disable duplicates filter,
++               * otherwise hosts can only receive one advertisement and it's
++               * impossible to know if a peer is still in range.
++               */
++              filter_dups = LE_SCAN_FILTER_DUP_DISABLE;
+       } else {
+               window = hdev->le_scan_window;
+               interval = hdev->le_scan_interval;
+-- 
+2.43.0
+
diff --git a/queue-6.10/bluetooth-l2cap-always-unlock-channel-in-l2cap_conle.patch b/queue-6.10/bluetooth-l2cap-always-unlock-channel-in-l2cap_conle.patch
new file mode 100644 (file)
index 0000000..d1cd4fe
--- /dev/null
@@ -0,0 +1,37 @@
+From 96cd656b241ef33c9bdbc9d4621d6c92ceb9c111 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 12:19:36 +0300
+Subject: Bluetooth: l2cap: always unlock channel in l2cap_conless_channel()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit c531e63871c0b50c8c4e62c048535a08886fba3e ]
+
+Add missing call to 'l2cap_chan_unlock()' on receive error handling
+path in 'l2cap_conless_channel()'.
+
+Fixes: a24cce144b98 ("Bluetooth: Fix reference counting of global L2CAP channels")
+Reported-by: syzbot+45ac74737e866894acb0@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=45ac74737e866894acb0
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index c3c26bbb5ddae..9988ba382b686 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6774,6 +6774,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
+       bt_cb(skb)->l2cap.psm = psm;
+       if (!chan->ops->recv(chan, skb)) {
++              l2cap_chan_unlock(chan);
+               l2cap_chan_put(chan);
+               return;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/bnxt_en-fix-memory-out-of-bounds-in-bnxt_fill_hw_rss.patch b/queue-6.10/bnxt_en-fix-memory-out-of-bounds-in-bnxt_fill_hw_rss.patch
new file mode 100644 (file)
index 0000000..371f302
--- /dev/null
@@ -0,0 +1,97 @@
+From 6168307f0f39543f5d6cc0a0674beacb2d78a82b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 22:37:42 -0700
+Subject: bnxt_en : Fix memory out-of-bounds in bnxt_fill_hw_rss_tbl()
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit da03f5d1b2c319a2b74fe76edeadcd8fa5f44376 ]
+
+A recent commit has modified the code in __bnxt_reserve_rings() to
+set the default RSS indirection table to default only when the number
+of RX rings is changing.  While this works for newer firmware that
+requires RX ring reservations, it causes the regression on older
+firmware not requiring RX ring resrvations (BNXT_NEW_RM() returns
+false).
+
+With older firmware, RX ring reservations are not required and so
+hw_resc->resv_rx_rings is not always set to the proper value.  The
+comparison:
+
+if (old_rx_rings != bp->hw_resc.resv_rx_rings)
+
+in __bnxt_reserve_rings() may be false even when the RX rings are
+changing.  This will cause __bnxt_reserve_rings() to skip setting
+the default RSS indirection table to default to match the current
+number of RX rings.  This may later cause bnxt_fill_hw_rss_tbl() to
+use an out-of-range index.
+
+We already have bnxt_check_rss_tbl_no_rmgr() to handle exactly this
+scenario.  We just need to move it up in bnxt_need_reserve_rings()
+to be called unconditionally when using older firmware.  Without the
+fix, if the TX rings are changing, we'll skip the
+bnxt_check_rss_tbl_no_rmgr() call and __bnxt_reserve_rings() may also
+skip the bnxt_set_dflt_rss_indir_tbl() call for the reason explained
+in the last paragraph.  Without setting the default RSS indirection
+table to default, it causes the regression:
+
+BUG: KASAN: slab-out-of-bounds in __bnxt_hwrm_vnic_set_rss+0xb79/0xe40
+Read of size 2 at addr ffff8881c5809618 by task ethtool/31525
+Call Trace:
+__bnxt_hwrm_vnic_set_rss+0xb79/0xe40
+ bnxt_hwrm_vnic_rss_cfg_p5+0xf7/0x460
+ __bnxt_setup_vnic_p5+0x12e/0x270
+ __bnxt_open_nic+0x2262/0x2f30
+ bnxt_open_nic+0x5d/0xf0
+ ethnl_set_channels+0x5d4/0xb30
+ ethnl_default_set_doit+0x2f1/0x620
+
+Reported-by: Breno Leitao <leitao@debian.org>
+Closes: https://lore.kernel.org/netdev/ZrC6jpghA3PWVWSB@gmail.com/
+Fixes: 98ba1d931f61 ("bnxt_en: Fix RSS logic in __bnxt_reserve_rings()")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Tested-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20240806053742.140304-1-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 23627c973e40f..a2d672a698e35 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -7433,19 +7433,20 @@ static bool bnxt_need_reserve_rings(struct bnxt *bp)
+       int rx = bp->rx_nr_rings, stat;
+       int vnic, grp = rx;
+-      if (hw_resc->resv_tx_rings != bp->tx_nr_rings &&
+-          bp->hwrm_spec_code >= 0x10601)
+-              return true;
+-
+       /* Old firmware does not need RX ring reservations but we still
+        * need to setup a default RSS map when needed.  With new firmware
+        * we go through RX ring reservations first and then set up the
+        * RSS map for the successfully reserved RX rings when needed.
+        */
+-      if (!BNXT_NEW_RM(bp)) {
++      if (!BNXT_NEW_RM(bp))
+               bnxt_check_rss_tbl_no_rmgr(bp);
++
++      if (hw_resc->resv_tx_rings != bp->tx_nr_rings &&
++          bp->hwrm_spec_code >= 0x10601)
++              return true;
++
++      if (!BNXT_NEW_RM(bp))
+               return false;
+-      }
+       vnic = bnxt_get_total_vnics(bp, rx);
+-- 
+2.43.0
+
diff --git a/queue-6.10/bpf-add-missing-check_func_arg_reg_off-to-prevent-ou.patch b/queue-6.10/bpf-add-missing-check_func_arg_reg_off-to-prevent-ou.patch
new file mode 100644 (file)
index 0000000..66e3192
--- /dev/null
@@ -0,0 +1,113 @@
+From 48ece36104ccd87af1864d784b95b920e99a6b3a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jun 2024 06:28:56 +0000
+Subject: bpf: add missing check_func_arg_reg_off() to prevent out-of-bounds
+ memory accesses
+
+From: Matt Bobrowski <mattbobrowski@google.com>
+
+[ Upstream commit ec2b9a5e11e51fea1bb04c1e7e471952e887e874 ]
+
+Currently, it's possible to pass in a modified CONST_PTR_TO_DYNPTR to
+a global function as an argument. The adverse effects of this is that
+BPF helpers can continue to make use of this modified
+CONST_PTR_TO_DYNPTR from within the context of the global function,
+which can unintentionally result in out-of-bounds memory accesses and
+therefore compromise overall system stability i.e.
+
+[  244.157771] BUG: KASAN: slab-out-of-bounds in bpf_dynptr_data+0x137/0x140
+[  244.161345] Read of size 8 at addr ffff88810914be68 by task test_progs/302
+[  244.167151] CPU: 0 PID: 302 Comm: test_progs Tainted: G O E 6.10.0-rc3-00131-g66b586715063 #533
+[  244.174318] Call Trace:
+[  244.175787]  <TASK>
+[  244.177356]  dump_stack_lvl+0x66/0xa0
+[  244.179531]  print_report+0xce/0x670
+[  244.182314]  ? __virt_addr_valid+0x200/0x3e0
+[  244.184908]  kasan_report+0xd7/0x110
+[  244.187408]  ? bpf_dynptr_data+0x137/0x140
+[  244.189714]  ? bpf_dynptr_data+0x137/0x140
+[  244.192020]  bpf_dynptr_data+0x137/0x140
+[  244.194264]  bpf_prog_b02a02fdd2bdc5fa_global_call_bpf_dynptr_data+0x22/0x26
+[  244.198044]  bpf_prog_b0fe7b9d7dc3abde_callback_adjust_bpf_dynptr_reg_off+0x1f/0x23
+[  244.202136]  bpf_user_ringbuf_drain+0x2c7/0x570
+[  244.204744]  ? 0xffffffffc0009e58
+[  244.206593]  ? __pfx_bpf_user_ringbuf_drain+0x10/0x10
+[  244.209795]  bpf_prog_33ab33f6a804ba2d_user_ringbuf_callback_const_ptr_to_dynptr_reg_off+0x47/0x4b
+[  244.215922]  bpf_trampoline_6442502480+0x43/0xe3
+[  244.218691]  __x64_sys_prlimit64+0x9/0xf0
+[  244.220912]  do_syscall_64+0xc1/0x1d0
+[  244.223043]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
+[  244.226458] RIP: 0033:0x7ffa3eb8f059
+[  244.228582] Code: 08 89 e8 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 8f 1d 0d 00 f7 d8 64 89 01 48
+[  244.241307] RSP: 002b:00007ffa3e9c6eb8 EFLAGS: 00000206 ORIG_RAX: 000000000000012e
+[  244.246474] RAX: ffffffffffffffda RBX: 00007ffa3e9c7cdc RCX: 00007ffa3eb8f059
+[  244.250478] RDX: 00007ffa3eb162b4 RSI: 0000000000000000 RDI: 00007ffa3e9c7fb0
+[  244.255396] RBP: 00007ffa3e9c6ed0 R08: 00007ffa3e9c76c0 R09: 0000000000000000
+[  244.260195] R10: 0000000000000000 R11: 0000000000000206 R12: ffffffffffffff80
+[  244.264201] R13: 000000000000001c R14: 00007ffc5d6b4260 R15: 00007ffa3e1c7000
+[  244.268303]  </TASK>
+
+Add a check_func_arg_reg_off() to the path in which the BPF verifier
+verifies the arguments of global function arguments, specifically
+those which take an argument of type ARG_PTR_TO_DYNPTR |
+MEM_RDONLY. Also, process_dynptr_func() doesn't appear to perform any
+explicit and strict type matching on the supplied register type, so
+let's also enforce that a register either type PTR_TO_STACK or
+CONST_PTR_TO_DYNPTR is by the caller.
+
+Reported-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>
+Link: https://lore.kernel.org/r/20240625062857.92760-1-mattbobrowski@google.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 6b422c275f78c..a8845cc299fec 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -7716,6 +7716,13 @@ static int process_dynptr_func(struct bpf_verifier_env *env, int regno, int insn
+       struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
+       int err;
++      if (reg->type != PTR_TO_STACK && reg->type != CONST_PTR_TO_DYNPTR) {
++              verbose(env,
++                      "arg#%d expected pointer to stack or const struct bpf_dynptr\n",
++                      regno);
++              return -EINVAL;
++      }
++
+       /* MEM_UNINIT and MEM_RDONLY are exclusive, when applied to an
+        * ARG_PTR_TO_DYNPTR (or ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_*):
+        */
+@@ -9465,6 +9472,10 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
+                               return -EINVAL;
+                       }
+               } else if (arg->arg_type == (ARG_PTR_TO_DYNPTR | MEM_RDONLY)) {
++                      ret = check_func_arg_reg_off(env, reg, regno, ARG_PTR_TO_DYNPTR);
++                      if (ret)
++                              return ret;
++
+                       ret = process_dynptr_func(env, regno, -1, arg->arg_type, 0);
+                       if (ret)
+                               return ret;
+@@ -11958,12 +11969,6 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
+                       enum bpf_arg_type dynptr_arg_type = ARG_PTR_TO_DYNPTR;
+                       int clone_ref_obj_id = 0;
+-                      if (reg->type != PTR_TO_STACK &&
+-                          reg->type != CONST_PTR_TO_DYNPTR) {
+-                              verbose(env, "arg#%d expected pointer to stack or dynptr_ptr\n", i);
+-                              return -EINVAL;
+-                      }
+-
+                       if (reg->type == CONST_PTR_TO_DYNPTR)
+                               dynptr_arg_type |= MEM_RDONLY;
+-- 
+2.43.0
+
diff --git a/queue-6.10/btrfs-do-not-bug_on-when-freeing-tree-block-after-er.patch b/queue-6.10/btrfs-do-not-bug_on-when-freeing-tree-block-after-er.patch
new file mode 100644 (file)
index 0000000..9b90d62
--- /dev/null
@@ -0,0 +1,308 @@
+From f209ea9ea6d1f8a2351aa30d4b7b23d4a98486ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 14:50:47 +0100
+Subject: btrfs: do not BUG_ON() when freeing tree block after error
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit bb3868033a4cccff7be57e9145f2117cbdc91c11 ]
+
+When freeing a tree block, at btrfs_free_tree_block(), if we fail to
+create a delayed reference we don't deal with the error and just do a
+BUG_ON(). The error most likely to happen is -ENOMEM, and we have a
+comment mentioning that only -ENOMEM can happen, but that is not true,
+because in case qgroups are enabled any error returned from
+btrfs_qgroup_trace_extent_post() (can be -EUCLEAN or anything returned
+from btrfs_search_slot() for example) can be propagated back to
+btrfs_free_tree_block().
+
+So stop doing a BUG_ON() and return the error to the callers and make
+them abort the transaction to prevent leaking space. Syzbot was
+triggering this, likely due to memory allocation failure injection.
+
+Reported-by: syzbot+a306f914b4d01b3958fe@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/linux-btrfs/000000000000fcba1e05e998263c@google.com/
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/ctree.c           | 53 ++++++++++++++++++++++++++++++--------
+ fs/btrfs/extent-tree.c     | 24 ++++++++++-------
+ fs/btrfs/extent-tree.h     |  8 +++---
+ fs/btrfs/free-space-tree.c | 10 ++++---
+ fs/btrfs/ioctl.c           |  6 ++++-
+ fs/btrfs/qgroup.c          |  6 +++--
+ 6 files changed, 76 insertions(+), 31 deletions(-)
+
+diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
+index 1a49b92329908..ca372068226d5 100644
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -620,10 +620,16 @@ int btrfs_force_cow_block(struct btrfs_trans_handle *trans,
+               atomic_inc(&cow->refs);
+               rcu_assign_pointer(root->node, cow);
+-              btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
+-                                    parent_start, last_ref);
++              ret = btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
++                                          parent_start, last_ref);
+               free_extent_buffer(buf);
+               add_root_to_dirty_list(root);
++              if (ret < 0) {
++                      btrfs_tree_unlock(cow);
++                      free_extent_buffer(cow);
++                      btrfs_abort_transaction(trans, ret);
++                      return ret;
++              }
+       } else {
+               WARN_ON(trans->transid != btrfs_header_generation(parent));
+               ret = btrfs_tree_mod_log_insert_key(parent, parent_slot,
+@@ -648,8 +654,14 @@ int btrfs_force_cow_block(struct btrfs_trans_handle *trans,
+                               return ret;
+                       }
+               }
+-              btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
+-                                    parent_start, last_ref);
++              ret = btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
++                                          parent_start, last_ref);
++              if (ret < 0) {
++                      btrfs_tree_unlock(cow);
++                      free_extent_buffer(cow);
++                      btrfs_abort_transaction(trans, ret);
++                      return ret;
++              }
+       }
+       if (unlock_orig)
+               btrfs_tree_unlock(buf);
+@@ -983,9 +995,13 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
+               free_extent_buffer(mid);
+               root_sub_used_bytes(root);
+-              btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
++              ret = btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
+               /* once for the root ptr */
+               free_extent_buffer_stale(mid);
++              if (ret < 0) {
++                      btrfs_abort_transaction(trans, ret);
++                      goto out;
++              }
+               return 0;
+       }
+       if (btrfs_header_nritems(mid) >
+@@ -1053,10 +1069,14 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
+                               goto out;
+                       }
+                       root_sub_used_bytes(root);
+-                      btrfs_free_tree_block(trans, btrfs_root_id(root), right,
+-                                            0, 1);
++                      ret = btrfs_free_tree_block(trans, btrfs_root_id(root),
++                                                  right, 0, 1);
+                       free_extent_buffer_stale(right);
+                       right = NULL;
++                      if (ret < 0) {
++                              btrfs_abort_transaction(trans, ret);
++                              goto out;
++                      }
+               } else {
+                       struct btrfs_disk_key right_key;
+                       btrfs_node_key(right, &right_key, 0);
+@@ -1111,9 +1131,13 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
+                       goto out;
+               }
+               root_sub_used_bytes(root);
+-              btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
++              ret = btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
+               free_extent_buffer_stale(mid);
+               mid = NULL;
++              if (ret < 0) {
++                      btrfs_abort_transaction(trans, ret);
++                      goto out;
++              }
+       } else {
+               /* update the parent key to reflect our changes */
+               struct btrfs_disk_key mid_key;
+@@ -2883,7 +2907,11 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
+       old = root->node;
+       ret = btrfs_tree_mod_log_insert_root(root->node, c, false);
+       if (ret < 0) {
+-              btrfs_free_tree_block(trans, btrfs_root_id(root), c, 0, 1);
++              int ret2;
++
++              ret2 = btrfs_free_tree_block(trans, btrfs_root_id(root), c, 0, 1);
++              if (ret2 < 0)
++                      btrfs_abort_transaction(trans, ret2);
+               btrfs_tree_unlock(c);
+               free_extent_buffer(c);
+               return ret;
+@@ -4452,9 +4480,12 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
+       root_sub_used_bytes(root);
+       atomic_inc(&leaf->refs);
+-      btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1);
++      ret = btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1);
+       free_extent_buffer_stale(leaf);
+-      return 0;
++      if (ret < 0)
++              btrfs_abort_transaction(trans, ret);
++
++      return ret;
+ }
+ /*
+  * delete the item at the leaf level in path.  If that empties
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index b75e14f399a01..153297cb97a4a 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -3420,10 +3420,10 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
+       return 0;
+ }
+-void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+-                         u64 root_id,
+-                         struct extent_buffer *buf,
+-                         u64 parent, int last_ref)
++int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
++                        u64 root_id,
++                        struct extent_buffer *buf,
++                        u64 parent, int last_ref)
+ {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
+       struct btrfs_block_group *bg;
+@@ -3450,11 +3450,12 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+               btrfs_init_tree_ref(&generic_ref, btrfs_header_level(buf), 0, false);
+               btrfs_ref_tree_mod(fs_info, &generic_ref);
+               ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, NULL);
+-              BUG_ON(ret); /* -ENOMEM */
++              if (ret < 0)
++                      return ret;
+       }
+       if (!last_ref)
+-              return;
++              return 0;
+       if (btrfs_header_generation(buf) != trans->transid)
+               goto out;
+@@ -3511,6 +3512,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+        * matter anymore.
+        */
+       clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags);
++      return 0;
+ }
+ /* Can return -ENOMEM */
+@@ -5644,7 +5646,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
+                                struct walk_control *wc)
+ {
+       struct btrfs_fs_info *fs_info = root->fs_info;
+-      int ret;
++      int ret = 0;
+       int level = wc->level;
+       struct extent_buffer *eb = path->nodes[level];
+       u64 parent = 0;
+@@ -5731,12 +5733,14 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
+                       goto owner_mismatch;
+       }
+-      btrfs_free_tree_block(trans, btrfs_root_id(root), eb, parent,
+-                            wc->refs[level] == 1);
++      ret = btrfs_free_tree_block(trans, btrfs_root_id(root), eb, parent,
++                                  wc->refs[level] == 1);
++      if (ret < 0)
++              btrfs_abort_transaction(trans, ret);
+ out:
+       wc->refs[level] = 0;
+       wc->flags[level] = 0;
+-      return 0;
++      return ret;
+ owner_mismatch:
+       btrfs_err_rl(fs_info, "unexpected tree owner, have %llu expect %llu",
+diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h
+index af9f8800d5aca..2ad51130c037e 100644
+--- a/fs/btrfs/extent-tree.h
++++ b/fs/btrfs/extent-tree.h
+@@ -127,10 +127,10 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
+                                            u64 empty_size,
+                                            u64 reloc_src_root,
+                                            enum btrfs_lock_nesting nest);
+-void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+-                         u64 root_id,
+-                         struct extent_buffer *buf,
+-                         u64 parent, int last_ref);
++int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
++                        u64 root_id,
++                        struct extent_buffer *buf,
++                        u64 parent, int last_ref);
+ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
+                                    struct btrfs_root *root, u64 owner,
+                                    u64 offset, u64 ram_bytes,
+diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
+index 90f2938bd743d..7ba50e133921a 100644
+--- a/fs/btrfs/free-space-tree.c
++++ b/fs/btrfs/free-space-tree.c
+@@ -1300,10 +1300,14 @@ int btrfs_delete_free_space_tree(struct btrfs_fs_info *fs_info)
+       btrfs_tree_lock(free_space_root->node);
+       btrfs_clear_buffer_dirty(trans, free_space_root->node);
+       btrfs_tree_unlock(free_space_root->node);
+-      btrfs_free_tree_block(trans, btrfs_root_id(free_space_root),
+-                            free_space_root->node, 0, 1);
+-
++      ret = btrfs_free_tree_block(trans, btrfs_root_id(free_space_root),
++                                  free_space_root->node, 0, 1);
+       btrfs_put_root(free_space_root);
++      if (ret < 0) {
++              btrfs_abort_transaction(trans, ret);
++              btrfs_end_transaction(trans);
++              return ret;
++      }
+       return btrfs_commit_transaction(trans);
+ }
+diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
+index efd5d6e9589e0..c1b0556e40368 100644
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -719,6 +719,8 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+       ret = btrfs_insert_root(trans, fs_info->tree_root, &key,
+                               root_item);
+       if (ret) {
++              int ret2;
++
+               /*
+                * Since we don't abort the transaction in this case, free the
+                * tree block so that we don't leak space and leave the
+@@ -729,7 +731,9 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+               btrfs_tree_lock(leaf);
+               btrfs_clear_buffer_dirty(trans, leaf);
+               btrfs_tree_unlock(leaf);
+-              btrfs_free_tree_block(trans, objectid, leaf, 0, 1);
++              ret2 = btrfs_free_tree_block(trans, objectid, leaf, 0, 1);
++              if (ret2 < 0)
++                      btrfs_abort_transaction(trans, ret2);
+               free_extent_buffer(leaf);
+               goto out;
+       }
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index 39a15cca58ca9..29d6ca3b874ec 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -1446,9 +1446,11 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
+       btrfs_tree_lock(quota_root->node);
+       btrfs_clear_buffer_dirty(trans, quota_root->node);
+       btrfs_tree_unlock(quota_root->node);
+-      btrfs_free_tree_block(trans, btrfs_root_id(quota_root),
+-                            quota_root->node, 0, 1);
++      ret = btrfs_free_tree_block(trans, btrfs_root_id(quota_root),
++                                  quota_root->node, 0, 1);
++      if (ret < 0)
++              btrfs_abort_transaction(trans, ret);
+ out:
+       btrfs_put_root(quota_root);
+-- 
+2.43.0
+
diff --git a/queue-6.10/btrfs-do-not-clear-page-dirty-inside-extent_write_lo.patch b/queue-6.10/btrfs-do-not-clear-page-dirty-inside-extent_write_lo.patch
new file mode 100644 (file)
index 0000000..e079a66
--- /dev/null
@@ -0,0 +1,201 @@
+From b324b0d12a6f5cfb3dd5c6bec6171e73782ebf03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Mar 2024 08:21:54 +1030
+Subject: btrfs: do not clear page dirty inside extent_write_locked_range()
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 97713b1a2ced1e4a2a6c40045903797ebd44d7e0 ]
+
+[BUG]
+For subpage + zoned case, the following workload can lead to rsv data
+leak at unmount time:
+
+  # mkfs.btrfs -f -s 4k $dev
+  # mount $dev $mnt
+  # fsstress -w -n 8 -d $mnt -s 1709539240
+  0/0: fiemap - no filename
+  0/1: copyrange read - no filename
+  0/2: write - no filename
+  0/3: rename - no source filename
+  0/4: creat f0 x:0 0 0
+  0/4: creat add id=0,parent=-1
+  0/5: writev f0[259 1 0 0 0 0] [778052,113,965] 0
+  0/6: ioctl(FIEMAP) f0[259 1 0 0 224 887097] [1294220,2291618343991484791,0x10000] -1
+  0/7: dwrite - xfsctl(XFS_IOC_DIOINFO) f0[259 1 0 0 224 887097] return 25, fallback to stat()
+  0/7: dwrite f0[259 1 0 0 224 887097] [696320,102400] 0
+  # umount $mnt
+
+The dmesg includes the following rsv leak detection warning (all call
+trace skipped):
+
+  ------------[ cut here ]------------
+  WARNING: CPU: 2 PID: 4528 at fs/btrfs/inode.c:8653 btrfs_destroy_inode+0x1e0/0x200 [btrfs]
+  ---[ end trace 0000000000000000 ]---
+  ------------[ cut here ]------------
+  WARNING: CPU: 2 PID: 4528 at fs/btrfs/inode.c:8654 btrfs_destroy_inode+0x1a8/0x200 [btrfs]
+  ---[ end trace 0000000000000000 ]---
+  ------------[ cut here ]------------
+  WARNING: CPU: 2 PID: 4528 at fs/btrfs/inode.c:8660 btrfs_destroy_inode+0x1a0/0x200 [btrfs]
+  ---[ end trace 0000000000000000 ]---
+  BTRFS info (device sda): last unmount of filesystem 1b4abba9-de34-4f07-9e7f-157cf12a18d6
+  ------------[ cut here ]------------
+  WARNING: CPU: 3 PID: 4528 at fs/btrfs/block-group.c:4434 btrfs_free_block_groups+0x338/0x500 [btrfs]
+  ---[ end trace 0000000000000000 ]---
+  BTRFS info (device sda): space_info DATA has 268218368 free, is not full
+  BTRFS info (device sda): space_info total=268435456, used=204800, pinned=0, reserved=0, may_use=12288, readonly=0 zone_unusable=0
+  BTRFS info (device sda): global_block_rsv: size 0 reserved 0
+  BTRFS info (device sda): trans_block_rsv: size 0 reserved 0
+  BTRFS info (device sda): chunk_block_rsv: size 0 reserved 0
+  BTRFS info (device sda): delayed_block_rsv: size 0 reserved 0
+  BTRFS info (device sda): delayed_refs_rsv: size 0 reserved 0
+  ------------[ cut here ]------------
+  WARNING: CPU: 3 PID: 4528 at fs/btrfs/block-group.c:4434 btrfs_free_block_groups+0x338/0x500 [btrfs]
+  ---[ end trace 0000000000000000 ]---
+  BTRFS info (device sda): space_info METADATA has 267796480 free, is not full
+  BTRFS info (device sda): space_info total=268435456, used=131072, pinned=0, reserved=0, may_use=262144, readonly=0 zone_unusable=245760
+  BTRFS info (device sda): global_block_rsv: size 0 reserved 0
+  BTRFS info (device sda): trans_block_rsv: size 0 reserved 0
+  BTRFS info (device sda): chunk_block_rsv: size 0 reserved 0
+  BTRFS info (device sda): delayed_block_rsv: size 0 reserved 0
+  BTRFS info (device sda): delayed_refs_rsv: size 0 reserved 0
+
+Above $dev is a tcmu-runner emulated zoned HDD, which has a max zone
+append size of 64K, and the system has 64K page size.
+
+[CAUSE]
+I have added several trace_printk() to show the events (header skipped):
+
+  > btrfs_dirty_pages: r/i=5/259 dirty start=774144 len=114688
+  > btrfs_dirty_pages: r/i=5/259 dirty part of page=720896 off_in_page=53248 len_in_page=12288
+  > btrfs_dirty_pages: r/i=5/259 dirty part of page=786432 off_in_page=0 len_in_page=65536
+  > btrfs_dirty_pages: r/i=5/259 dirty part of page=851968 off_in_page=0 len_in_page=36864
+
+The above lines show our buffered write has dirtied 3 pages of inode
+259 of root 5:
+
+  704K             768K              832K              896K
+  I           |////I/////////////////I///////////|     I
+              756K                               868K
+
+  |///| is the dirtied range using subpage bitmaps. and 'I' is the page
+  boundary.
+
+  Meanwhile all three pages (704K, 768K, 832K) have their PageDirty
+  flag set.
+
+  > btrfs_direct_write: r/i=5/259 start dio filepos=696320 len=102400
+
+Then direct IO write starts, since the range [680K, 780K) covers the
+beginning part of the above dirty range, we need to writeback the
+two pages at 704K and 768K.
+
+  > cow_file_range: r/i=5/259 add ordered extent filepos=774144 len=65536
+  > extent_write_locked_range: r/i=5/259 locked page=720896 start=774144 len=65536
+
+Now the above 2 lines show that we're writing back for dirty range
+[756K, 756K + 64K).
+We only writeback 64K because the zoned device has max zone append size
+as 64K.
+
+  > extent_write_locked_range: r/i=5/259 clear dirty for page=786432
+
+!!! The above line shows the root cause. !!!
+
+We're calling clear_page_dirty_for_io() inside extent_write_locked_range(),
+for the page 768K.
+This is because extent_write_locked_range() can go beyond the current
+locked page, here we hit the page at 768K and clear its page dirt.
+
+In fact this would lead to the desync between subpage dirty and page
+dirty flags.  We have the page dirty flag cleared, but the subpage range
+[820K, 832K) is still dirty.
+
+After the writeback of range [756K, 820K), the dirty flags look like
+this, as page 768K no longer has dirty flag set.
+
+  704K             768K              832K              896K
+  I                I      |          I/////////////|   I
+                          820K                     868K
+
+This means we will no longer writeback range [820K, 832K), thus the
+reserved data/metadata space would never be properly released.
+
+  > extent_write_cache_pages: r/i=5/259 skip non-dirty folio=786432
+
+Now even though we try to start writeback for page 768K, since the
+page is not dirty, we completely skip it at extent_write_cache_pages()
+time.
+
+  > btrfs_direct_write: r/i=5/259 dio done filepos=696320 len=0
+
+Now the direct IO finished.
+
+  > cow_file_range: r/i=5/259 add ordered extent filepos=851968 len=36864
+  > extent_write_locked_range: r/i=5/259 locked page=851968 start=851968 len=36864
+
+Now we writeback the remaining dirty range, which is [832K, 868K).
+Causing the range [820K, 832K) never to be submitted, thus leaking the
+reserved space.
+
+This bug only affects subpage and zoned case.  For non-subpage and zoned
+case, we have exactly one sector for each page, thus no such partial dirty
+cases.
+
+For subpage and non-zoned case, we never go into run_delalloc_cow(), and
+normally all the dirty subpage ranges would be properly submitted inside
+__extent_writepage_io().
+
+[FIX]
+Just do not clear the page dirty at all inside extent_write_locked_range().
+As __extent_writepage_io() would do a more accurate, subpage compatible
+clear for page and subpage dirty flags anyway.
+
+Now the correct trace would look like this:
+
+  > btrfs_dirty_pages: r/i=5/259 dirty start=774144 len=114688
+  > btrfs_dirty_pages: r/i=5/259 dirty part of page=720896 off_in_page=53248 len_in_page=12288
+  > btrfs_dirty_pages: r/i=5/259 dirty part of page=786432 off_in_page=0 len_in_page=65536
+  > btrfs_dirty_pages: r/i=5/259 dirty part of page=851968 off_in_page=0 len_in_page=36864
+
+The page dirty part is still the same 3 pages.
+
+  > btrfs_direct_write: r/i=5/259 start dio filepos=696320 len=102400
+  > cow_file_range: r/i=5/259 add ordered extent filepos=774144 len=65536
+  > extent_write_locked_range: r/i=5/259 locked page=720896 start=774144 len=65536
+
+And the writeback for the first 64K is still correct.
+
+  > cow_file_range: r/i=5/259 add ordered extent filepos=839680 len=49152
+  > extent_write_locked_range: r/i=5/259 locked page=786432 start=839680 len=49152
+
+Now with the fix, we can properly writeback the range [820K, 832K), and
+properly release the reserved data/metadata space.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 958155cc43a81..0486b1f911248 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -2246,10 +2246,8 @@ void extent_write_locked_range(struct inode *inode, struct page *locked_page,
+               page = find_get_page(mapping, cur >> PAGE_SHIFT);
+               ASSERT(PageLocked(page));
+-              if (pages_dirty && page != locked_page) {
++              if (pages_dirty && page != locked_page)
+                       ASSERT(PageDirty(page));
+-                      clear_page_dirty_for_io(page);
+-              }
+               ret = __extent_writepage_io(BTRFS_I(inode), page, &bio_ctrl,
+                                           i_size, &nr);
+-- 
+2.43.0
+
diff --git a/queue-6.10/btrfs-fix-bitmap-leak-when-loading-free-space-cache-.patch b/queue-6.10/btrfs-fix-bitmap-leak-when-loading-free-space-cache-.patch
new file mode 100644 (file)
index 0000000..bcf104c
--- /dev/null
@@ -0,0 +1,39 @@
+From 88797b3ae2188e7c474bbf49ff51949478a26db2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jul 2024 15:40:59 +0100
+Subject: btrfs: fix bitmap leak when loading free space cache on duplicate
+ entry
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit 320d8dc612660da84c3b70a28658bb38069e5a9a ]
+
+If we failed to link a free space entry because there's already a
+conflicting entry for the same offset, we free the free space entry but
+we don't free the associated bitmap that we had just allocated before.
+Fix that by freeing the bitmap before freeing the entry.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/free-space-cache.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
+index d674f2106593a..62c3dea9572ab 100644
+--- a/fs/btrfs/free-space-cache.c
++++ b/fs/btrfs/free-space-cache.c
+@@ -858,6 +858,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
+                               spin_unlock(&ctl->tree_lock);
+                               btrfs_err(fs_info,
+                                       "Duplicate entries in free space cache, dumping");
++                              kmem_cache_free(btrfs_free_space_bitmap_cachep, e->bitmap);
+                               kmem_cache_free(btrfs_free_space_cachep, e);
+                               goto free_cache;
+                       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/btrfs-fix-data-race-when-accessing-the-last_trans-fi.patch b/queue-6.10/btrfs-fix-data-race-when-accessing-the-last_trans-fi.patch
new file mode 100644 (file)
index 0000000..67e354d
--- /dev/null
@@ -0,0 +1,228 @@
+From eecc72d6ce5b65bd37c4112bb1e9a401c51fac93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jul 2024 10:51:28 +0100
+Subject: btrfs: fix data race when accessing the last_trans field of a root
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit ca84529a842f3a15a5f17beac6252aa11955923f ]
+
+KCSAN complains about a data race when accessing the last_trans field of a
+root:
+
+  [  199.553628] BUG: KCSAN: data-race in btrfs_record_root_in_trans [btrfs] / record_root_in_trans [btrfs]
+
+  [  199.555186] read to 0x000000008801e308 of 8 bytes by task 2812 on cpu 1:
+  [  199.555210]  btrfs_record_root_in_trans+0x9a/0x128 [btrfs]
+  [  199.555999]  start_transaction+0x154/0xcd8 [btrfs]
+  [  199.556780]  btrfs_join_transaction+0x44/0x60 [btrfs]
+  [  199.557559]  btrfs_dirty_inode+0x9c/0x140 [btrfs]
+  [  199.558339]  btrfs_update_time+0x8c/0xb0 [btrfs]
+  [  199.559123]  touch_atime+0x16c/0x1e0
+  [  199.559151]  pipe_read+0x6a8/0x7d0
+  [  199.559179]  vfs_read+0x466/0x498
+  [  199.559204]  ksys_read+0x108/0x150
+  [  199.559230]  __s390x_sys_read+0x68/0x88
+  [  199.559257]  do_syscall+0x1c6/0x210
+  [  199.559286]  __do_syscall+0xc8/0xf0
+  [  199.559318]  system_call+0x70/0x98
+
+  [  199.559431] write to 0x000000008801e308 of 8 bytes by task 2808 on cpu 0:
+  [  199.559464]  record_root_in_trans+0x196/0x228 [btrfs]
+  [  199.560236]  btrfs_record_root_in_trans+0xfe/0x128 [btrfs]
+  [  199.561097]  start_transaction+0x154/0xcd8 [btrfs]
+  [  199.561927]  btrfs_join_transaction+0x44/0x60 [btrfs]
+  [  199.562700]  btrfs_dirty_inode+0x9c/0x140 [btrfs]
+  [  199.563493]  btrfs_update_time+0x8c/0xb0 [btrfs]
+  [  199.564277]  file_update_time+0xb8/0xf0
+  [  199.564301]  pipe_write+0x8ac/0xab8
+  [  199.564326]  vfs_write+0x33c/0x588
+  [  199.564349]  ksys_write+0x108/0x150
+  [  199.564372]  __s390x_sys_write+0x68/0x88
+  [  199.564397]  do_syscall+0x1c6/0x210
+  [  199.564424]  __do_syscall+0xc8/0xf0
+  [  199.564452]  system_call+0x70/0x98
+
+This is because we update and read last_trans concurrently without any
+type of synchronization. This should be generally harmless and in the
+worst case it can make us do extra locking (btrfs_record_root_in_trans())
+trigger some warnings at ctree.c or do extra work during relocation - this
+would probably only happen in case of load or store tearing.
+
+So fix this by always reading and updating the field using READ_ONCE()
+and WRITE_ONCE(), this silences KCSAN and prevents load and store tearing.
+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/ctree.c       |  4 ++--
+ fs/btrfs/ctree.h       | 10 ++++++++++
+ fs/btrfs/defrag.c      |  2 +-
+ fs/btrfs/disk-io.c     |  4 ++--
+ fs/btrfs/relocation.c  |  8 ++++----
+ fs/btrfs/transaction.c |  8 ++++----
+ 6 files changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
+index ca372068226d5..8a791b648ac53 100644
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -321,7 +321,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
+       WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+               trans->transid != fs_info->running_transaction->transid);
+       WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+-              trans->transid != root->last_trans);
++              trans->transid != btrfs_get_root_last_trans(root));
+       level = btrfs_header_level(buf);
+       if (level == 0)
+@@ -551,7 +551,7 @@ int btrfs_force_cow_block(struct btrfs_trans_handle *trans,
+       WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+               trans->transid != fs_info->running_transaction->transid);
+       WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+-              trans->transid != root->last_trans);
++              trans->transid != btrfs_get_root_last_trans(root));
+       level = btrfs_header_level(buf);
+diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
+index c03c58246033b..b2e4b30b8fae9 100644
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -354,6 +354,16 @@ static inline void btrfs_set_root_last_log_commit(struct btrfs_root *root, int c
+       WRITE_ONCE(root->last_log_commit, commit_id);
+ }
++static inline u64 btrfs_get_root_last_trans(const struct btrfs_root *root)
++{
++      return READ_ONCE(root->last_trans);
++}
++
++static inline void btrfs_set_root_last_trans(struct btrfs_root *root, u64 transid)
++{
++      WRITE_ONCE(root->last_trans, transid);
++}
++
+ /*
+  * Structure that conveys information about an extent that is going to replace
+  * all the extents in a file range.
+diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c
+index 407ccec3e57ed..f664678c71d15 100644
+--- a/fs/btrfs/defrag.c
++++ b/fs/btrfs/defrag.c
+@@ -139,7 +139,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
+       if (trans)
+               transid = trans->transid;
+       else
+-              transid = inode->root->last_trans;
++              transid = btrfs_get_root_last_trans(root);
+       defrag = kmem_cache_zalloc(btrfs_inode_defrag_cachep, GFP_NOFS);
+       if (!defrag)
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index cabb558dbdaa8..3791813dc7b62 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -658,7 +658,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
+       root->state = 0;
+       RB_CLEAR_NODE(&root->rb_node);
+-      root->last_trans = 0;
++      btrfs_set_root_last_trans(root, 0);
+       root->free_objectid = 0;
+       root->nr_delalloc_inodes = 0;
+       root->nr_ordered_extents = 0;
+@@ -1010,7 +1010,7 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
+               return ret;
+       }
+-      log_root->last_trans = trans->transid;
++      btrfs_set_root_last_trans(log_root, trans->transid);
+       log_root->root_key.offset = btrfs_root_id(root);
+       inode_item = &log_root->root_item.inode;
+diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
+index 8b24bb5a0aa18..f2935252b981a 100644
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -817,7 +817,7 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
+               goto abort;
+       }
+       set_bit(BTRFS_ROOT_SHAREABLE, &reloc_root->state);
+-      reloc_root->last_trans = trans->transid;
++      btrfs_set_root_last_trans(reloc_root, trans->transid);
+       return reloc_root;
+ fail:
+       kfree(root_item);
+@@ -864,7 +864,7 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
+        */
+       if (root->reloc_root) {
+               reloc_root = root->reloc_root;
+-              reloc_root->last_trans = trans->transid;
++              btrfs_set_root_last_trans(reloc_root, trans->transid);
+               return 0;
+       }
+@@ -1739,7 +1739,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
+                * btrfs_update_reloc_root() and update our root item
+                * appropriately.
+                */
+-              reloc_root->last_trans = trans->transid;
++              btrfs_set_root_last_trans(reloc_root, trans->transid);
+               trans->block_rsv = rc->block_rsv;
+               replaced = 0;
+@@ -2082,7 +2082,7 @@ static int record_reloc_root_in_trans(struct btrfs_trans_handle *trans,
+       struct btrfs_root *root;
+       int ret;
+-      if (reloc_root->last_trans == trans->transid)
++      if (btrfs_get_root_last_trans(reloc_root) == trans->transid)
+               return 0;
+       root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset, false);
+diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
+index 3388c836b9a56..76117bb2c726c 100644
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -405,7 +405,7 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
+       int ret = 0;
+       if ((test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+-          root->last_trans < trans->transid) || force) {
++          btrfs_get_root_last_trans(root) < trans->transid) || force) {
+               WARN_ON(!force && root->commit_root != root->node);
+               /*
+@@ -421,7 +421,7 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
+               smp_wmb();
+               spin_lock(&fs_info->fs_roots_radix_lock);
+-              if (root->last_trans == trans->transid && !force) {
++              if (btrfs_get_root_last_trans(root) == trans->transid && !force) {
+                       spin_unlock(&fs_info->fs_roots_radix_lock);
+                       return 0;
+               }
+@@ -429,7 +429,7 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
+                                  (unsigned long)btrfs_root_id(root),
+                                  BTRFS_ROOT_TRANS_TAG);
+               spin_unlock(&fs_info->fs_roots_radix_lock);
+-              root->last_trans = trans->transid;
++              btrfs_set_root_last_trans(root, trans->transid);
+               /* this is pretty tricky.  We don't want to
+                * take the relocation lock in btrfs_record_root_in_trans
+@@ -491,7 +491,7 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
+        * and barriers
+        */
+       smp_rmb();
+-      if (root->last_trans == trans->transid &&
++      if (btrfs_get_root_last_trans(root) == trans->transid &&
+           !test_bit(BTRFS_ROOT_IN_TRANS_SETUP, &root->state))
+               return 0;
+-- 
+2.43.0
+
diff --git a/queue-6.10/btrfs-reduce-nesting-for-extent-processing-at-btrfs_.patch b/queue-6.10/btrfs-reduce-nesting-for-extent-processing-at-btrfs_.patch
new file mode 100644 (file)
index 0000000..f125576
--- /dev/null
@@ -0,0 +1,77 @@
+From 5a0873e18421183cf695cc5f2c851aac4e1d832c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jun 2024 11:52:19 +0100
+Subject: btrfs: reduce nesting for extent processing at
+ btrfs_lookup_extent_info()
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit 5c83b3beaee06aa88d4015408ac2d8bb35380b06 ]
+
+Instead of using an if-else statement when processing the extent item at
+btrfs_lookup_extent_info(), use a single if statement for the error case
+since it does a goto at the end and leave the success (expected) case
+following the if statement, reducing indentation and making the logic a
+bit easier to follow. Also make the if statement's condition as unlikely
+since it's not expected to ever happen, as it signals some corruption,
+making it clear and hint the compiler to generate more efficient code.
+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent-tree.c | 22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index 153297cb97a4a..844b677d054ec 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -104,10 +104,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
+       struct btrfs_delayed_ref_head *head;
+       struct btrfs_delayed_ref_root *delayed_refs;
+       struct btrfs_path *path;
+-      struct btrfs_extent_item *ei;
+-      struct extent_buffer *leaf;
+       struct btrfs_key key;
+-      u32 item_size;
+       u64 num_refs;
+       u64 extent_flags;
+       u64 owner = 0;
+@@ -157,16 +154,11 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
+       }
+       if (ret == 0) {
+-              leaf = path->nodes[0];
+-              item_size = btrfs_item_size(leaf, path->slots[0]);
+-              if (item_size >= sizeof(*ei)) {
+-                      ei = btrfs_item_ptr(leaf, path->slots[0],
+-                                          struct btrfs_extent_item);
+-                      num_refs = btrfs_extent_refs(leaf, ei);
+-                      extent_flags = btrfs_extent_flags(leaf, ei);
+-                      owner = btrfs_get_extent_owner_root(fs_info, leaf,
+-                                                          path->slots[0]);
+-              } else {
++              struct extent_buffer *leaf = path->nodes[0];
++              struct btrfs_extent_item *ei;
++              const u32 item_size = btrfs_item_size(leaf, path->slots[0]);
++
++              if (unlikely(item_size < sizeof(*ei))) {
+                       ret = -EUCLEAN;
+                       btrfs_err(fs_info,
+                       "unexpected extent item size, has %u expect >= %zu",
+@@ -179,6 +171,10 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
+                       goto out_free;
+               }
++              ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
++              num_refs = btrfs_extent_refs(leaf, ei);
++              extent_flags = btrfs_extent_flags(leaf, ei);
++              owner = btrfs_get_extent_owner_root(fs_info, leaf, path->slots[0]);
+               BUG_ON(num_refs == 0);
+       } else {
+               num_refs = 0;
+-- 
+2.43.0
+
diff --git a/queue-6.10/can-mcp251xfd-tef-prepare-to-workaround-broken-tef-f.patch b/queue-6.10/can-mcp251xfd-tef-prepare-to-workaround-broken-tef-f.patch
new file mode 100644 (file)
index 0000000..4f28036
--- /dev/null
@@ -0,0 +1,211 @@
+From 55b694b7967c21c8bf443c4a0eecf4136161a8fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Jan 2023 21:30:41 +0100
+Subject: can: mcp251xfd: tef: prepare to workaround broken TEF FIFO tail index
+ erratum
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b8e0ddd36ce9536ad7478dd27df06c9ae92370ba ]
+
+This is a preparatory patch to work around a problem similar to
+erratum DS80000789E 6 of the mcp2518fd, the other variants of the chip
+family (mcp2517fd and mcp251863) are probably also affected.
+
+Erratum DS80000789E 6 says "reading of the FIFOCI bits in the FIFOSTA
+register for an RX FIFO may be corrupted". However observation shows
+that this problem is not limited to RX FIFOs but also effects the TEF
+FIFO.
+
+When handling the TEF interrupt, the driver reads the FIFO header
+index from the TEF FIFO STA register of the chip.
+
+In the bad case, the driver reads a too large head index. In the
+original code, the driver always trusted the read value, which caused
+old CAN transmit complete events that were already processed to be
+re-processed.
+
+Instead of reading and trusting the head index, read the head index
+and calculate the number of CAN frames that were supposedly received -
+replace mcp251xfd_tef_ring_update() with mcp251xfd_get_tef_len().
+
+The mcp251xfd_handle_tefif() function reads the CAN transmit complete
+events from the chip, iterates over them and pushes them into the
+network stack. The original driver already contains code to detect old
+CAN transmit complete events, that will be updated in the next patch.
+
+Cc: Stefan Althöfer <Stefan.Althoefer@janztec.com>
+Cc: Thomas Kopp <thomas.kopp@microchip.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    |  2 +
+ drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c | 54 +++++++++++++------
+ drivers/net/can/spi/mcp251xfd/mcp251xfd.h     | 13 ++---
+ 3 files changed, 43 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+index bfe4caa0c99d4..4cb79a4f24612 100644
+--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+@@ -485,6 +485,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
+               clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
+       }
++      tx_ring->obj_num_shift_to_u8 = BITS_PER_TYPE(tx_ring->obj_num) -
++              ilog2(tx_ring->obj_num);
+       tx_ring->obj_size = tx_obj_size;
+       rem = priv->rx_obj_num;
+diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+index e5bd57b65aafe..b41fad3b37c06 100644
+--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+@@ -2,7 +2,7 @@
+ //
+ // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
+ //
+-// Copyright (c) 2019, 2020, 2021 Pengutronix,
++// Copyright (c) 2019, 2020, 2021, 2023 Pengutronix,
+ //               Marc Kleine-Budde <kernel@pengutronix.de>
+ //
+ // Based on:
+@@ -16,6 +16,11 @@
+ #include "mcp251xfd.h"
++static inline bool mcp251xfd_tx_fifo_sta_full(u32 fifo_sta)
++{
++      return !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF);
++}
++
+ static inline int
+ mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
+                                u8 *tef_tail)
+@@ -120,28 +125,44 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
+       return 0;
+ }
+-static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv)
++static int
++mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
+ {
+       const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
+-      unsigned int new_head;
+-      u8 chip_tx_tail;
++      const u8 shift = tx_ring->obj_num_shift_to_u8;
++      u8 chip_tx_tail, tail, len;
++      u32 fifo_sta;
+       int err;
+-      err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail);
++      err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(priv->tx->fifo_nr),
++                        &fifo_sta);
+       if (err)
+               return err;
+-      /* chip_tx_tail, is the next TX-Object send by the HW.
+-       * The new TEF head must be >= the old head, ...
++      if (mcp251xfd_tx_fifo_sta_full(fifo_sta)) {
++              *len_p = tx_ring->obj_num;
++              return 0;
++      }
++
++      chip_tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
++
++      err =  mcp251xfd_check_tef_tail(priv);
++      if (err)
++              return err;
++      tail = mcp251xfd_get_tef_tail(priv);
++
++      /* First shift to full u8. The subtraction works on signed
++       * values, that keeps the difference steady around the u8
++       * overflow. The right shift acts on len, which is an u8.
+        */
+-      new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail;
+-      if (new_head <= priv->tef->head)
+-              new_head += tx_ring->obj_num;
++      BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(chip_tx_tail));
++      BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(tail));
++      BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len));
+-      /* ... but it cannot exceed the TX head. */
+-      priv->tef->head = min(new_head, tx_ring->head);
++      len = (chip_tx_tail << shift) - (tail << shift);
++      *len_p = len >> shift;
+-      return mcp251xfd_check_tef_tail(priv);
++      return 0;
+ }
+ static inline int
+@@ -182,13 +203,12 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
+       u8 tef_tail, len, l;
+       int err, i;
+-      err = mcp251xfd_tef_ring_update(priv);
++      err = mcp251xfd_get_tef_len(priv, &len);
+       if (err)
+               return err;
+       tef_tail = mcp251xfd_get_tef_tail(priv);
+-      len = mcp251xfd_get_tef_len(priv);
+-      l = mcp251xfd_get_tef_linear_len(priv);
++      l = mcp251xfd_get_tef_linear_len(priv, len);
+       err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l);
+       if (err)
+               return err;
+@@ -223,6 +243,8 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
+               struct mcp251xfd_tx_ring *tx_ring = priv->tx;
+               int offset;
++              ring->head += len;
++
+               /* Increment the TEF FIFO tail pointer 'len' times in
+                * a single SPI message.
+                *
+diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+index b35bfebd23f29..4628bf847bc9b 100644
+--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+@@ -524,6 +524,7 @@ struct mcp251xfd_tef_ring {
+       /* u8 obj_num equals tx_ring->obj_num */
+       /* u8 obj_size equals sizeof(struct mcp251xfd_hw_tef_obj) */
++      /* u8 obj_num_shift_to_u8 equals tx_ring->obj_num_shift_to_u8 */
+       union mcp251xfd_write_reg_buf irq_enable_buf;
+       struct spi_transfer irq_enable_xfer;
+@@ -542,6 +543,7 @@ struct mcp251xfd_tx_ring {
+       u8 nr;
+       u8 fifo_nr;
+       u8 obj_num;
++      u8 obj_num_shift_to_u8;
+       u8 obj_size;
+       struct mcp251xfd_tx_obj obj[MCP251XFD_TX_OBJ_NUM_MAX];
+@@ -861,17 +863,8 @@ static inline u8 mcp251xfd_get_tef_tail(const struct mcp251xfd_priv *priv)
+       return priv->tef->tail & (priv->tx->obj_num - 1);
+ }
+-static inline u8 mcp251xfd_get_tef_len(const struct mcp251xfd_priv *priv)
++static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv, u8 len)
+ {
+-      return priv->tef->head - priv->tef->tail;
+-}
+-
+-static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv)
+-{
+-      u8 len;
+-
+-      len = mcp251xfd_get_tef_len(priv);
+-
+       return min_t(u8, len, priv->tx->obj_num - mcp251xfd_get_tef_tail(priv));
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/can-mcp251xfd-tef-update-workaround-for-erratum-ds80.patch b/queue-6.10/can-mcp251xfd-tef-update-workaround-for-erratum-ds80.patch
new file mode 100644 (file)
index 0000000..f1c06ae
--- /dev/null
@@ -0,0 +1,151 @@
+From 1809c96bd0c5a7fe492d4a8e60840da50642ecc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Jan 2023 22:35:03 +0100
+Subject: can: mcp251xfd: tef: update workaround for erratum DS80000789E 6 of
+ mcp2518fd
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 3a0a88fcbaf9e027ecca3fe8775be9700b4d6460 ]
+
+This patch updates the workaround for a problem similar to erratum
+DS80000789E 6 of the mcp2518fd, the other variants of the chip
+family (mcp2517fd and mcp251863) are probably also affected.
+
+Erratum DS80000789E 6 says "reading of the FIFOCI bits in the FIFOSTA
+register for an RX FIFO may be corrupted". However observation shows
+that this problem is not limited to RX FIFOs but also effects the TEF
+FIFO.
+
+In the bad case, the driver reads a too large head index. As the FIFO
+is implemented as a ring buffer, this results in re-handling old CAN
+transmit complete events.
+
+Every transmit complete event contains with a sequence number that
+equals to the sequence number of the corresponding TX request. This
+way old TX complete events can be detected.
+
+If the original driver detects a non matching sequence number, it
+prints an info message and tries again later. As wrong sequence
+numbers can be explained by the erratum DS80000789E 6, demote the info
+message to debug level, streamline the code and update the comments.
+
+Keep the behavior: If an old CAN TX complete event is detected, abort
+the iteration and mark the number of valid CAN TX complete events as
+processed in the chip by incrementing the FIFO's tail index.
+
+Cc: Stefan Althöfer <Stefan.Althoefer@janztec.com>
+Cc: Thomas Kopp <thomas.kopp@microchip.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c | 71 +++++++------------
+ 1 file changed, 27 insertions(+), 44 deletions(-)
+
+diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+index b41fad3b37c06..5b0c7890d4b44 100644
+--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+@@ -60,56 +60,39 @@ static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv)
+       return 0;
+ }
+-static int
+-mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
+-{
+-      const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
+-      u32 tef_sta;
+-      int err;
+-
+-      err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta);
+-      if (err)
+-              return err;
+-
+-      if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) {
+-              netdev_err(priv->ndev,
+-                         "Transmit Event FIFO buffer overflow.\n");
+-              return -ENOBUFS;
+-      }
+-
+-      netdev_info(priv->ndev,
+-                  "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x).\n",
+-                  tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ?
+-                  "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ?
+-                  "not empty" : "empty",
+-                  seq, priv->tef->tail, priv->tef->head, tx_ring->head);
+-
+-      /* The Sequence Number in the TEF doesn't match our tef_tail. */
+-      return -EAGAIN;
+-}
+-
+ static int
+ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
+                          const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
+                          unsigned int *frame_len_ptr)
+ {
+       struct net_device_stats *stats = &priv->ndev->stats;
++      u32 seq, tef_tail_masked, tef_tail;
+       struct sk_buff *skb;
+-      u32 seq, seq_masked, tef_tail_masked, tef_tail;
+-      seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK,
++       /* Use the MCP2517FD mask on the MCP2518FD, too. We only
++        * compare 7 bits, this is enough to detect old TEF objects.
++        */
++      seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK,
+                       hw_tef_obj->flags);
+-
+-      /* Use the MCP2517FD mask on the MCP2518FD, too. We only
+-       * compare 7 bits, this should be enough to detect
+-       * net-yet-completed, i.e. old TEF objects.
+-       */
+-      seq_masked = seq &
+-              field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
+       tef_tail_masked = priv->tef->tail &
+               field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
+-      if (seq_masked != tef_tail_masked)
+-              return mcp251xfd_handle_tefif_recover(priv, seq);
++
++      /* According to mcp2518fd erratum DS80000789E 6. the FIFOCI
++       * bits of a FIFOSTA register, here the TX FIFO tail index
++       * might be corrupted and we might process past the TEF FIFO's
++       * head into old CAN frames.
++       *
++       * Compare the sequence number of the currently processed CAN
++       * frame with the expected sequence number. Abort with
++       * -EBADMSG if an old CAN frame is detected.
++       */
++      if (seq != tef_tail_masked) {
++              netdev_dbg(priv->ndev, "%s: chip=0x%02x ring=0x%02x\n", __func__,
++                         seq, tef_tail_masked);
++              stats->tx_fifo_errors++;
++
++              return -EBADMSG;
++      }
+       tef_tail = mcp251xfd_get_tef_tail(priv);
+       skb = priv->can.echo_skb[tef_tail];
+@@ -223,12 +206,12 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
+               unsigned int frame_len = 0;
+               err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
+-              /* -EAGAIN means the Sequence Number in the TEF
+-               * doesn't match our tef_tail. This can happen if we
+-               * read the TEF objects too early. Leave loop let the
+-               * interrupt handler call us again.
++              /* -EBADMSG means we're affected by mcp2518fd erratum
++               * DS80000789E 6., i.e. the Sequence Number in the TEF
++               * doesn't match our tef_tail. Don't process any
++               * further and mark processed frames as good.
+                */
+-              if (err == -EAGAIN)
++              if (err == -EBADMSG)
+                       goto out_netif_wake_queue;
+               if (err)
+                       return err;
+-- 
+2.43.0
+
diff --git a/queue-6.10/clocksource-drivers-sh_cmt-address-race-condition-fo.patch b/queue-6.10/clocksource-drivers-sh_cmt-address-race-condition-fo.patch
new file mode 100644 (file)
index 0000000..b3f447a
--- /dev/null
@@ -0,0 +1,144 @@
+From 0952ac7e4caa804c44d3e373719c10c5e566a0b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jul 2024 21:02:30 +0200
+Subject: clocksource/drivers/sh_cmt: Address race condition for clock events
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+[ Upstream commit db19d3aa77612983a02bd223b3f273f896b243cf ]
+
+There is a race condition in the CMT interrupt handler. In the interrupt
+handler the driver sets a driver private flag, FLAG_IRQCONTEXT. This
+flag is used to indicate any call to set_next_event() should not be
+directly propagated to the device, but instead cached. This is done as
+the interrupt handler itself reprograms the device when needed before it
+completes and this avoids this operation to take place twice.
+
+It is unclear why this design was chosen, my suspicion is to allow the
+struct clock_event_device.event_handler callback, which is called while
+the FLAG_IRQCONTEXT is set, can update the next event without having to
+write to the device twice.
+
+Unfortunately there is a race between when the FLAG_IRQCONTEXT flag is
+set and later cleared where the interrupt handler have already started to
+write the next event to the device. If set_next_event() is called in
+this window the value is only cached in the driver but not written. This
+leads to the board to misbehave, or worse lockup and produce a splat.
+
+   rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
+   rcu:     0-...!: (0 ticks this GP) idle=f5e0/0/0x0 softirq=519/519 fqs=0 (false positive?)
+   rcu:     (detected by 1, t=6502 jiffies, g=-595, q=77 ncpus=2)
+   Sending NMI from CPU 1 to CPUs 0:
+   NMI backtrace for cpu 0
+   CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.10.0-rc5-arm64-renesas-00019-g74a6f86eaf1c-dirty #20
+   Hardware name: Renesas Salvator-X 2nd version board based on r8a77965 (DT)
+   pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+   pc : tick_check_broadcast_expired+0xc/0x40
+   lr : cpu_idle_poll.isra.0+0x8c/0x168
+   sp : ffff800081c63d70
+   x29: ffff800081c63d70 x28: 00000000580000c8 x27: 00000000bfee5610
+   x26: 0000000000000027 x25: 0000000000000000 x24: 0000000000000000
+   x23: ffff00007fbb9100 x22: ffff8000818f1008 x21: ffff8000800ef07c
+   x20: ffff800081c79ec0 x19: ffff800081c70c28 x18: 0000000000000000
+   x17: 0000000000000000 x16: 0000000000000000 x15: 0000ffffc2c717d8
+   x14: 0000000000000000 x13: ffff000009c18080 x12: ffff8000825f7fc0
+   x11: 0000000000000000 x10: ffff8000818f3cd4 x9 : 0000000000000028
+   x8 : ffff800081c79ec0 x7 : ffff800081c73000 x6 : 0000000000000000
+   x5 : 0000000000000000 x4 : ffff7ffffe286000 x3 : 0000000000000000
+   x2 : ffff7ffffe286000 x1 : ffff800082972900 x0 : ffff8000818f1008
+   Call trace:
+    tick_check_broadcast_expired+0xc/0x40
+    do_idle+0x9c/0x280
+    cpu_startup_entry+0x34/0x40
+    kernel_init+0x0/0x11c
+    do_one_initcall+0x0/0x260
+    __primary_switched+0x80/0x88
+   rcu: rcu_preempt kthread timer wakeup didn't happen for 6501 jiffies! g-595 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402
+   rcu:     Possible timer handling issue on cpu=0 timer-softirq=262
+   rcu: rcu_preempt kthread starved for 6502 jiffies! g-595 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402 ->cpu=0
+   rcu:     Unless rcu_preempt kthread gets sufficient CPU time, OOM is now expected behavior.
+   rcu: RCU grace-period kthread stack dump:
+   task:rcu_preempt     state:I stack:0     pid:15    tgid:15    ppid:2      flags:0x00000008
+   Call trace:
+    __switch_to+0xbc/0x100
+    __schedule+0x358/0xbe0
+    schedule+0x48/0x148
+    schedule_timeout+0xc4/0x138
+    rcu_gp_fqs_loop+0x12c/0x764
+    rcu_gp_kthread+0x208/0x298
+    kthread+0x10c/0x110
+    ret_from_fork+0x10/0x20
+
+The design have been part of the driver since it was first merged in
+early 2009. It becomes increasingly harder to trigger the issue the
+older kernel version one tries. It only takes a few boots on v6.10-rc5,
+while hundreds of boots are needed to trigger it on v5.10.
+
+Close the race condition by using the CMT channel lock for the two
+competing sections. The channel lock was added to the driver after its
+initial design.
+
+Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Link: https://lore.kernel.org/r/20240702190230.3825292-1-niklas.soderlund+renesas@ragnatech.se
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clocksource/sh_cmt.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
+index 26919556ef5f0..b72b36e0abed8 100644
+--- a/drivers/clocksource/sh_cmt.c
++++ b/drivers/clocksource/sh_cmt.c
+@@ -528,6 +528,7 @@ static void sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
+ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
+ {
+       struct sh_cmt_channel *ch = dev_id;
++      unsigned long flags;
+       /* clear flags */
+       sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) &
+@@ -558,6 +559,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
+       ch->flags &= ~FLAG_SKIPEVENT;
++      raw_spin_lock_irqsave(&ch->lock, flags);
++
+       if (ch->flags & FLAG_REPROGRAM) {
+               ch->flags &= ~FLAG_REPROGRAM;
+               sh_cmt_clock_event_program_verify(ch, 1);
+@@ -570,6 +573,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
+       ch->flags &= ~FLAG_IRQCONTEXT;
++      raw_spin_unlock_irqrestore(&ch->lock, flags);
++
+       return IRQ_HANDLED;
+ }
+@@ -780,12 +785,18 @@ static int sh_cmt_clock_event_next(unsigned long delta,
+                                  struct clock_event_device *ced)
+ {
+       struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
++      unsigned long flags;
+       BUG_ON(!clockevent_state_oneshot(ced));
++
++      raw_spin_lock_irqsave(&ch->lock, flags);
++
+       if (likely(ch->flags & FLAG_IRQCONTEXT))
+               ch->next_match_value = delta - 1;
+       else
+-              sh_cmt_set_next(ch, delta - 1);
++              __sh_cmt_set_next(ch, delta - 1);
++
++      raw_spin_unlock_irqrestore(&ch->lock, flags);
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/cpufreq-amd-pstate-allow-users-to-write-default-epp-.patch b/queue-6.10/cpufreq-amd-pstate-allow-users-to-write-default-epp-.patch
new file mode 100644 (file)
index 0000000..67c1f4d
--- /dev/null
@@ -0,0 +1,67 @@
+From b949cff9e9a86ae2343320d9045a38da5fbae431 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jun 2024 09:20:49 -0500
+Subject: cpufreq: amd-pstate: Allow users to write 'default' EPP string
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit fc6e0837264a8b2504b6160e63ec92eb012540f3 ]
+
+The EPP string for 'default' represents what the firmware had configured
+as the default EPP value but once a user changes EPP to another string
+they can't reset it back to 'default'.
+
+Cache the firmware EPP value and allow the user to write 'default' using
+this value.
+
+Reported-by: Artem S. Tashkinov <aros@gmx.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217931#c61
+Reviewed-by: Perry Yuan <perry.yuan@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/amd-pstate.c | 8 +++-----
+ drivers/cpufreq/amd-pstate.h | 1 +
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
+index a092b13ffbc2f..874ee90b1cf10 100644
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -304,10 +304,8 @@ static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata,
+       int epp = -EINVAL;
+       int ret;
+-      if (!pref_index) {
+-              pr_debug("EPP pref_index is invalid\n");
+-              return -EINVAL;
+-      }
++      if (!pref_index)
++              epp = cpudata->epp_default;
+       if (epp == -EINVAL)
+               epp = epp_values[pref_index];
+@@ -1439,7 +1437,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
+       policy->driver_data = cpudata;
+-      cpudata->epp_cached = amd_pstate_get_epp(cpudata, 0);
++      cpudata->epp_cached = cpudata->epp_default = amd_pstate_get_epp(cpudata, 0);
+       policy->min = policy->cpuinfo.min_freq;
+       policy->max = policy->cpuinfo.max_freq;
+diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
+index e6a28e7f4dbf1..f80b33fa5d43a 100644
+--- a/drivers/cpufreq/amd-pstate.h
++++ b/drivers/cpufreq/amd-pstate.h
+@@ -99,6 +99,7 @@ struct amd_cpudata {
+       u32     policy;
+       u64     cppc_cap1_cached;
+       bool    suspended;
++      s16     epp_default;
+ };
+ #endif /* _LINUX_AMD_PSTATE_H */
+-- 
+2.43.0
+
diff --git a/queue-6.10/cpufreq-amd-pstate-auto-load-pstate-driver-by-defaul.patch b/queue-6.10/cpufreq-amd-pstate-auto-load-pstate-driver-by-defaul.patch
new file mode 100644 (file)
index 0000000..d6e1caa
--- /dev/null
@@ -0,0 +1,92 @@
+From 6b48e8f74e1ba147eb68634476b85012f1386776 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Jun 2024 23:40:19 +0800
+Subject: cpufreq: amd-pstate: auto-load pstate driver by default
+
+From: Perry Yuan <perry.yuan@amd.com>
+
+[ Upstream commit 4e4f600ee750facedf6a5dc97e8ae0b627ab4573 ]
+
+If the `amd-pstate` driver is not loaded automatically by default,
+it is because the kernel command line parameter has not been added.
+To resolve this issue, it is necessary to call the `amd_pstate_set_driver()`
+function to enable the desired mode (passive/active/guided) before registering
+the driver instance.
+
+This ensures that the driver is loaded correctly without relying on the kernel
+command line parameter.
+
+When there is no parameter added to command line, Kernel config will
+provide the default mode to load.
+
+Meanwhile, user can add driver mode in command line which will override
+the kernel config default option.
+
+Reported-by: Andrei Amuraritei <andamu@posteo.net>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218705
+Signed-off-by: Perry Yuan <perry.yuan@amd.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Link: https://lore.kernel.org/r/83301c4cea4f92fb19e14b23f2bac7facfd8bdbb.1718811234.git.perry.yuan@amd.com
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/amd-pstate.c | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
+index 874ee90b1cf10..67c4a6a0ef124 100644
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -1764,8 +1764,13 @@ static int __init amd_pstate_init(void)
+       /* check if this machine need CPPC quirks */
+       dmi_check_system(amd_pstate_quirks_table);
+-      switch (cppc_state) {
+-      case AMD_PSTATE_UNDEFINED:
++      /*
++      * determine the driver mode from the command line or kernel config.
++      * If no command line input is provided, cppc_state will be AMD_PSTATE_UNDEFINED.
++      * command line options will override the kernel config settings.
++      */
++
++      if (cppc_state == AMD_PSTATE_UNDEFINED) {
+               /* Disable on the following configs by default:
+                * 1. Undefined platforms
+                * 2. Server platforms
+@@ -1777,15 +1782,20 @@ static int __init amd_pstate_init(void)
+                       pr_info("driver load is disabled, boot with specific mode to enable this\n");
+                       return -ENODEV;
+               }
+-              ret = amd_pstate_set_driver(CONFIG_X86_AMD_PSTATE_DEFAULT_MODE);
+-              if (ret)
+-                      return ret;
+-              break;
++              /* get driver mode from kernel config option [1:4] */
++              cppc_state = CONFIG_X86_AMD_PSTATE_DEFAULT_MODE;
++      }
++
++      switch (cppc_state) {
+       case AMD_PSTATE_DISABLE:
++              pr_info("driver load is disabled, boot with specific mode to enable this\n");
+               return -ENODEV;
+       case AMD_PSTATE_PASSIVE:
+       case AMD_PSTATE_ACTIVE:
+       case AMD_PSTATE_GUIDED:
++              ret = amd_pstate_set_driver(cppc_state);
++              if (ret)
++                      return ret;
+               break;
+       default:
+               return -EINVAL;
+@@ -1806,7 +1816,7 @@ static int __init amd_pstate_init(void)
+       /* enable amd pstate feature */
+       ret = amd_pstate_enable(true);
+       if (ret) {
+-              pr_err("failed to enable with return %d\n", ret);
++              pr_err("failed to enable driver mode(%d)\n", cppc_state);
+               return ret;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/debugobjects-annotate-racy-debug-variables.patch b/queue-6.10/debugobjects-annotate-racy-debug-variables.patch
new file mode 100644 (file)
index 0000000..809b652
--- /dev/null
@@ -0,0 +1,79 @@
+From 2914c33c3aba36a09f17f7d6d1b0305db31c2e7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jun 2024 02:18:12 -0700
+Subject: debugobjects: Annotate racy debug variables
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 5b5baba6222255d29626f63c41f101379ec5400b ]
+
+KCSAN has identified a potential data race in debugobjects, where the
+global variable debug_objects_maxchain is accessed for both reading and
+writing simultaneously in separate and parallel data paths. This results in
+the following splat printed by KCSAN:
+
+  BUG: KCSAN: data-race in debug_check_no_obj_freed / debug_object_activate
+
+  write to 0xffffffff847ccfc8 of 4 bytes by task 734 on cpu 41:
+  debug_object_activate (lib/debugobjects.c:199 lib/debugobjects.c:564 lib/debugobjects.c:710)
+  call_rcu (kernel/rcu/rcu.h:227 kernel/rcu/tree.c:2719 kernel/rcu/tree.c:2838)
+  security_inode_free (security/security.c:1626)
+  __destroy_inode (./include/linux/fsnotify.h:222 fs/inode.c:287)
+  ...
+  read to 0xffffffff847ccfc8 of 4 bytes by task 384 on cpu 31:
+  debug_check_no_obj_freed (lib/debugobjects.c:1000 lib/debugobjects.c:1019)
+  kfree (mm/slub.c:2081 mm/slub.c:4280 mm/slub.c:4390)
+  percpu_ref_exit (lib/percpu-refcount.c:147)
+  css_free_rwork_fn (kernel/cgroup/cgroup.c:5357)
+  ...
+  value changed: 0x00000070 -> 0x00000071
+
+The data race is actually harmless as this is just used for debugfs
+statistics, as all other debug variables.
+
+Annotate all debug variables as racy explicitly, since these variables
+are known to be racy and harmless.
+
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20240611091813.1189860-1-leitao@debian.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/debugobjects.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/lib/debugobjects.c b/lib/debugobjects.c
+index fb12a9bacd2fa..7cea91e193a8f 100644
+--- a/lib/debugobjects.c
++++ b/lib/debugobjects.c
+@@ -78,16 +78,17 @@ static bool                        obj_freeing;
+ /* The number of objs on the global free list */
+ static int                    obj_nr_tofree;
+-static int                    debug_objects_maxchain __read_mostly;
+-static int __maybe_unused     debug_objects_maxchecked __read_mostly;
+-static int                    debug_objects_fixups __read_mostly;
+-static int                    debug_objects_warnings __read_mostly;
+-static int                    debug_objects_enabled __read_mostly
+-                              = CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT;
+-static int                    debug_objects_pool_size __read_mostly
+-                              = ODEBUG_POOL_SIZE;
+-static int                    debug_objects_pool_min_level __read_mostly
+-                              = ODEBUG_POOL_MIN_LEVEL;
++static int __data_racy                        debug_objects_maxchain __read_mostly;
++static int __data_racy __maybe_unused debug_objects_maxchecked __read_mostly;
++static int __data_racy                        debug_objects_fixups __read_mostly;
++static int __data_racy                        debug_objects_warnings __read_mostly;
++static int __data_racy                        debug_objects_enabled __read_mostly
++                                      = CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT;
++static int __data_racy                        debug_objects_pool_size __read_mostly
++                                      = ODEBUG_POOL_SIZE;
++static int __data_racy                        debug_objects_pool_min_level __read_mostly
++                                      = ODEBUG_POOL_MIN_LEVEL;
++
+ static const struct debug_obj_descr *descr_test  __read_mostly;
+ static struct kmem_cache      *obj_cache __ro_after_init;
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-admgpu-fix-dereferencing-null-pointer-context.patch b/queue-6.10/drm-admgpu-fix-dereferencing-null-pointer-context.patch
new file mode 100644 (file)
index 0000000..137ba09
--- /dev/null
@@ -0,0 +1,37 @@
+From 964d2008dd63f9d6bb493c452c4663fc96447d5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 May 2024 10:57:04 +0800
+Subject: drm/admgpu: fix dereferencing null pointer context
+
+From: Jesse Zhang <jesse.zhang@amd.com>
+
+[ Upstream commit 030ffd4d43b433bc6671d9ec34fc12c59220b95d ]
+
+When user space sets an invalid ta type, the pointer context will be empty.
+So it need to check the pointer context before using it
+
+Signed-off-by: Jesse Zhang <Jesse.Zhang@amd.com>
+Suggested-by: Tim Huang <Tim.Huang@amd.com>
+Reviewed-by: Tim Huang <Tim.Huang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
+index ca5c86e5f7cd6..8e8afbd237bcd 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
+@@ -334,7 +334,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
+       set_ta_context_funcs(psp, ta_type, &context);
+-      if (!context->initialized) {
++      if (!context || !context->initialized) {
+               dev_err(adev->dev, "TA is not initialized\n");
+               ret = -EINVAL;
+               goto err_free_shared_buf;
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-amdkfd-fix-a-resource-leak-in-svm_range_vali.patch b/queue-6.10/drm-amd-amdkfd-fix-a-resource-leak-in-svm_range_vali.patch
new file mode 100644 (file)
index 0000000..87faa6a
--- /dev/null
@@ -0,0 +1,51 @@
+From aba2f0eef21c63e0287c2047a788e849cc57ded2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Apr 2024 15:24:46 -0500
+Subject: drm/amd/amdkfd: Fix a resource leak in svm_range_validate_and_map()
+
+From: Ramesh Errabolu <Ramesh.Errabolu@amd.com>
+
+[ Upstream commit d2d3a44008fea01ec7d5a9d9ca527286be2e0257 ]
+
+Analysis of code by Coverity, a static code analyser, has identified
+a resource leak in the symbol hmm_range. This leak occurs when one of
+the prior steps before it is released encounters an error.
+
+Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu@amd.com>
+Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+index 31e500859ab01..92485251247a0 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+@@ -1658,7 +1658,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
+       start = map_start << PAGE_SHIFT;
+       end = (map_last + 1) << PAGE_SHIFT;
+       for (addr = start; !r && addr < end; ) {
+-              struct hmm_range *hmm_range;
++              struct hmm_range *hmm_range = NULL;
+               unsigned long map_start_vma;
+               unsigned long map_last_vma;
+               struct vm_area_struct *vma;
+@@ -1696,7 +1696,12 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
+               }
+               svm_range_lock(prange);
+-              if (!r && amdgpu_hmm_range_get_pages_done(hmm_range)) {
++
++              /* Free backing memory of hmm_range if it was initialized
++               * Overrride return value to TRY AGAIN only if prior returns
++               * were successful
++               */
++              if (hmm_range && amdgpu_hmm_range_get_pages_done(hmm_range) && !r) {
+                       pr_debug("hmm update the range, need validate again\n");
+                       r = -EAGAIN;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-add-delay-to-improve-lttpr-uhbr-inte.patch b/queue-6.10/drm-amd-display-add-delay-to-improve-lttpr-uhbr-inte.patch
new file mode 100644 (file)
index 0000000..1da870e
--- /dev/null
@@ -0,0 +1,45 @@
+From dd0e44e843b878e839f6ae5379f413c37bf30a44 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Apr 2024 12:00:34 -0400
+Subject: drm/amd/display: Add delay to improve LTTPR UHBR interop
+
+From: Michael Strauss <michael.strauss@amd.com>
+
+[ Upstream commit 10839ee6a977ed1f7d0f4deb29f2d7e5d1f2a9dd ]
+
+[WHY]
+Avoid race condition which puts LTTPR into bad state during UHBR LT.
+
+[HOW]
+Delay 30ms between starting UHBR TPS1 PHY output and sending TPS1 via DPCD.
+
+Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
+Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Michael Strauss <michael.strauss@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c      | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
+index 3e6c7be7e2786..5302d2c9c7607 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
++++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
+@@ -165,7 +165,12 @@ static void set_hpo_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *lin
+               link_res->hpo_dp_link_enc->funcs->set_link_test_pattern(
+                               link_res->hpo_dp_link_enc, tp_params);
+       }
++
+       link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
++
++      // Give retimer extra time to lock before updating DP_TRAINING_PATTERN_SET to TPS1
++      if (tp_params->dp_phy_pattern == DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE)
++              msleep(30);
+ }
+ static void set_hpo_fixed_vs_pe_retimer_dp_lane_settings(struct dc_link *link,
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-add-null-check-for-afb-before-derefe.patch b/queue-6.10/drm-amd-display-add-null-check-for-afb-before-derefe.patch
new file mode 100644 (file)
index 0000000..43fd440
--- /dev/null
@@ -0,0 +1,67 @@
+From 2a26e9c9acd06183ee0c1c13acce22ec926243ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 21:13:40 +0530
+Subject: drm/amd/display: Add NULL check for 'afb' before dereferencing in
+ amdgpu_dm_plane_handle_cursor_update
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 38e6f715b02b572f74677eb2f29d3b4bc6f1ddff ]
+
+This commit adds a null check for the 'afb' variable in the
+amdgpu_dm_plane_handle_cursor_update function. Previously, 'afb' was
+assumed to be null, but was used later in the code without a null check.
+This could potentially lead to a null pointer dereference.
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm_plane.c:1298 amdgpu_dm_plane_handle_cursor_update() error: we previously assumed 'afb' could be null (see line 1252)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Hersen Wu <hersenxs.wu@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c  | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+index 8a4c40b4c27e4..918c880739a2a 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+@@ -1231,14 +1231,22 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
+ {
+       struct amdgpu_device *adev = drm_to_adev(plane->dev);
+       struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb);
+-      struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc;
+-      struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL;
+-      struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+-      uint64_t address = afb ? afb->address : 0;
++      struct drm_crtc *crtc;
++      struct dm_crtc_state *crtc_state;
++      struct amdgpu_crtc *amdgpu_crtc;
++      u64 address;
+       struct dc_cursor_position position = {0};
+       struct dc_cursor_attributes attributes;
+       int ret;
++      if (!afb)
++              return;
++
++      crtc = plane->state->crtc ? plane->state->crtc : old_plane_state->crtc;
++      crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL;
++      amdgpu_crtc = to_amdgpu_crtc(crtc);
++      address = afb->address;
++
+       if (!plane->state->fb && !old_plane_state->fb)
+               return;
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-add-null-checker-before-passing-vari.patch b/queue-6.10/drm-amd-display-add-null-checker-before-passing-vari.patch
new file mode 100644 (file)
index 0000000..191bbae
--- /dev/null
@@ -0,0 +1,59 @@
+From 579cb49b6beebcd3b45775f9848614e7110d888d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 16:33:18 -0600
+Subject: drm/amd/display: Add null checker before passing variables
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 8092aa3ab8f7b737a34b71f91492c676a843043a ]
+
+Checks null pointer before passing variables to functions.
+
+This fixes 3 NULL_RETURNS issues reported by Coverity.
+
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 3cdcadd41be1a..964bb6d0a3833 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -2701,7 +2701,8 @@ static int dm_suspend(void *handle)
+               dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state);
+-              dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);
++              if (dm->cached_dc_state)
++                      dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);
+               amdgpu_dm_commit_zero_streams(dm->dc);
+@@ -6788,7 +6789,8 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
+               aconnector->dc_sink = aconnector->dc_link->local_sink ?
+               aconnector->dc_link->local_sink :
+               aconnector->dc_em_sink;
+-              dc_sink_retain(aconnector->dc_sink);
++              if (aconnector->dc_sink)
++                      dc_sink_retain(aconnector->dc_sink);
+       }
+ }
+@@ -7615,7 +7617,8 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
+                               drm_add_modes_noedid(connector, 1920, 1080);
+       } else {
+               amdgpu_dm_connector_ddc_get_modes(connector, edid);
+-              amdgpu_dm_connector_add_common_modes(encoder, connector);
++              if (encoder)
++                      amdgpu_dm_connector_add_common_modes(encoder, connector);
+               amdgpu_dm_connector_add_freesync_modes(connector, edid);
+       }
+       amdgpu_dm_fbc_init(connector);
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-add-null-checks-for-stream-and-plane.patch b/queue-6.10/drm-amd-display-add-null-checks-for-stream-and-plane.patch
new file mode 100644 (file)
index 0000000..1ae879a
--- /dev/null
@@ -0,0 +1,57 @@
+From 867f093dea3e42437521b9dd2c3c9dddf17d07de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 20:15:21 +0530
+Subject: drm/amd/display: Add null checks for 'stream' and 'plane' before
+ dereferencing
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 15c2990e0f0108b9c3752d7072a97d45d4283aea ]
+
+This commit adds null checks for the 'stream' and 'plane' variables in
+the dcn30_apply_idle_power_optimizations function. These variables were
+previously assumed to be null at line 922, but they were used later in
+the code without checking if they were null. This could potentially lead
+to a null pointer dereference, which would cause a crash.
+
+The null checks ensure that 'stream' and 'plane' are not null before
+they are used, preventing potential crashes.
+
+Fixes the below static smatch checker:
+drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c:938 dcn30_apply_idle_power_optimizations() error: we previously assumed 'stream' could be null (see line 922)
+drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c:940 dcn30_apply_idle_power_optimizations() error: we previously assumed 'plane' could be null (see line 922)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Cc: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Hersen Wu <hersenxs.wu@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+index ed9141a67db37..5b09d95cc5b8f 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+@@ -919,6 +919,9 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
+                       stream = dc->current_state->streams[0];
+                       plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL);
++                      if (!stream || !plane)
++                              return false;
++
+                       if (stream && plane) {
+                               cursor_cache_enable = stream->cursor_position.enable &&
+                                               plane->address.grph.cursor_cache_addr.quad_part;
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-don-t-refer-to-dc_sink-in-is_dsc_nee.patch b/queue-6.10/drm-amd-display-don-t-refer-to-dc_sink-in-is_dsc_nee.patch
new file mode 100644 (file)
index 0000000..aacebaa
--- /dev/null
@@ -0,0 +1,70 @@
+From cb0c1a81dfd1ac47ece50a420d61e102df1eac95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 May 2024 11:54:26 +0800
+Subject: drm/amd/display: Don't refer to dc_sink in is_dsc_need_re_compute
+
+From: Wayne Lin <wayne.lin@amd.com>
+
+[ Upstream commit fcf6a49d79923a234844b8efe830a61f3f0584e4 ]
+
+[Why]
+When unplug one of monitors connected after mst hub, encounter null pointer dereference.
+
+It's due to dc_sink get released immediately in early_unregister() or detect_ctx(). When
+commit new state which directly referring to info stored in dc_sink will cause null pointer
+dereference.
+
+[how]
+Remove redundant checking condition. Relevant condition should already be covered by checking
+if dsc_aux is null or not. Also reset dsc_aux to NULL when the connector is disconnected.
+
+Reviewed-by: Jerry Zuo <jerry.zuo@amd.com>
+Acked-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c  | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+index e90f9d6975111..7c405ffae1a3d 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -182,6 +182,8 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
+               dc_sink_release(dc_sink);
+               aconnector->dc_sink = NULL;
+               aconnector->edid = NULL;
++              aconnector->dsc_aux = NULL;
++              port->passthrough_aux = NULL;
+       }
+       aconnector->mst_status = MST_STATUS_DEFAULT;
+@@ -494,6 +496,8 @@ dm_dp_mst_detect(struct drm_connector *connector,
+               dc_sink_release(aconnector->dc_sink);
+               aconnector->dc_sink = NULL;
+               aconnector->edid = NULL;
++              aconnector->dsc_aux = NULL;
++              port->passthrough_aux = NULL;
+               amdgpu_dm_set_mst_status(&aconnector->mst_status,
+                       MST_REMOTE_EDID | MST_ALLOCATE_NEW_PAYLOAD | MST_CLEAR_ALLOCATED_PAYLOAD,
+@@ -1233,14 +1237,6 @@ static bool is_dsc_need_re_compute(
+               if (!aconnector || !aconnector->dsc_aux)
+                       continue;
+-              /*
+-               *      check if cached virtual MST DSC caps are available and DSC is supported
+-               *      as per specifications in their Virtual DPCD registers.
+-              */
+-              if (!(aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported ||
+-                      aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT))
+-                      continue;
+-
+               stream_on_link[new_stream_on_link_num] = aconnector;
+               new_stream_on_link_num++;
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-fix-null-pointer-deref-in-dcn20_reso.patch b/queue-6.10/drm-amd-display-fix-null-pointer-deref-in-dcn20_reso.patch
new file mode 100644 (file)
index 0000000..91f454f
--- /dev/null
@@ -0,0 +1,83 @@
+From 379467002e520422ebc323a6a68552741ad8b0f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jun 2024 13:13:57 -0400
+Subject: drm/amd/display: Fix null pointer deref in dcn20_resource.c
+
+From: Aurabindo Pillai <aurabindo.pillai@amd.com>
+
+[ Upstream commit ecbf60782662f0a388493685b85a645a0ba1613c ]
+
+Fixes a hang thats triggered when MPV is run on a DCN401 dGPU:
+
+mpv --hwdec=vaapi --vo=gpu --hwdec-codecs=all
+
+and then enabling fullscreen playback (double click on the video)
+
+The following calltrace will be seen:
+
+[  181.843989] BUG: kernel NULL pointer dereference, address: 0000000000000000
+[  181.843997] #PF: supervisor instruction fetch in kernel mode
+[  181.844003] #PF: error_code(0x0010) - not-present page
+[  181.844009] PGD 0 P4D 0
+[  181.844020] Oops: 0010 [#1] PREEMPT SMP NOPTI
+[  181.844028] CPU: 6 PID: 1892 Comm: gnome-shell Tainted: G        W  OE      6.5.0-41-generic #41~22.04.2-Ubuntu
+[  181.844038] Hardware name: System manufacturer System Product Name/CROSSHAIR VI HERO, BIOS 6302 10/23/2018
+[  181.844044] RIP: 0010:0x0
+[  181.844079] Code: Unable to access opcode bytes at 0xffffffffffffffd6.
+[  181.844084] RSP: 0018:ffffb593c2b8f7b0 EFLAGS: 00010246
+[  181.844093] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000004
+[  181.844099] RDX: ffffb593c2b8f804 RSI: ffffb593c2b8f7e0 RDI: ffff9e3c8e758400
+[  181.844105] RBP: ffffb593c2b8f7b8 R08: ffffb593c2b8f9c8 R09: ffffb593c2b8f96c
+[  181.844110] R10: 0000000000000000 R11: 0000000000000000 R12: ffffb593c2b8f9c8
+[  181.844115] R13: 0000000000000001 R14: ffff9e3c88000000 R15: 0000000000000005
+[  181.844121] FS:  00007c6e323bb5c0(0000) GS:ffff9e3f85f80000(0000) knlGS:0000000000000000
+[  181.844128] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[  181.844134] CR2: ffffffffffffffd6 CR3: 0000000140fbe000 CR4: 00000000003506e0
+[  181.844141] Call Trace:
+[  181.844146]  <TASK>
+[  181.844153]  ? show_regs+0x6d/0x80
+[  181.844167]  ? __die+0x24/0x80
+[  181.844179]  ? page_fault_oops+0x99/0x1b0
+[  181.844192]  ? do_user_addr_fault+0x31d/0x6b0
+[  181.844204]  ? exc_page_fault+0x83/0x1b0
+[  181.844216]  ? asm_exc_page_fault+0x27/0x30
+[  181.844237]  dcn20_get_dcc_compression_cap+0x23/0x30 [amdgpu]
+[  181.845115]  amdgpu_dm_plane_validate_dcc.constprop.0+0xe5/0x180 [amdgpu]
+[  181.845985]  amdgpu_dm_plane_fill_plane_buffer_attributes+0x300/0x580 [amdgpu]
+[  181.846848]  fill_dc_plane_info_and_addr+0x258/0x350 [amdgpu]
+[  181.847734]  fill_dc_plane_attributes+0x162/0x350 [amdgpu]
+[  181.848748]  dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu]
+[  181.849791]  ? dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu]
+[  181.850840]  amdgpu_dm_atomic_check+0xdfe/0x1760 [amdgpu]
+
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/dc/resource/dcn20/dcn20_resource.c   | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+index 0a939437e19f1..6b380e037e3f8 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+@@ -2193,10 +2193,11 @@ bool dcn20_get_dcc_compression_cap(const struct dc *dc,
+               const struct dc_dcc_surface_param *input,
+               struct dc_surface_dcc_cap *output)
+ {
+-      return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
+-                      dc->res_pool->hubbub,
+-                      input,
+-                      output);
++      if (dc->res_pool->hubbub->funcs->get_dcc_compression_cap)
++              return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
++                      dc->res_pool->hubbub, input, output);
++
++      return false;
+ }
+ static void dcn20_destroy_resource_pool(struct resource_pool **pool)
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-fix-null-pointer-dereference-for-dtn.patch b/queue-6.10/drm-amd-display-fix-null-pointer-dereference-for-dtn.patch
new file mode 100644 (file)
index 0000000..cf3421e
--- /dev/null
@@ -0,0 +1,157 @@
+From 81599e460038b57347811bc8d3d5a8879c8acf61 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Jun 2024 15:31:15 -0600
+Subject: drm/amd/display: Fix NULL pointer dereference for DTN log in DCN401
+
+From: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+
+[ Upstream commit 5af757124792817f8eb1bd0c80ad60fab519586b ]
+
+When users run the command:
+
+cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
+
+The following NULL pointer dereference happens:
+
+[  +0.000003] BUG: kernel NULL pointer dereference, address: NULL
+[  +0.000005] #PF: supervisor instruction fetch in kernel mode
+[  +0.000002] #PF: error_code(0x0010) - not-present page
+[  +0.000002] PGD 0 P4D 0
+[  +0.000004] Oops: 0010 [#1] PREEMPT SMP NOPTI
+[  +0.000003] RIP: 0010:0x0
+[  +0.000008] Code: Unable to access opcode bytes at 0xffffffffffffffd6.
+[...]
+[  +0.000002] PKRU: 55555554
+[  +0.000002] Call Trace:
+[  +0.000002]  <TASK>
+[  +0.000003]  ? show_regs+0x65/0x70
+[  +0.000006]  ? __die+0x24/0x70
+[  +0.000004]  ? page_fault_oops+0x160/0x470
+[  +0.000006]  ? do_user_addr_fault+0x2b5/0x690
+[  +0.000003]  ? prb_read_valid+0x1c/0x30
+[  +0.000005]  ? exc_page_fault+0x8c/0x1a0
+[  +0.000005]  ? asm_exc_page_fault+0x27/0x30
+[  +0.000012]  dcn10_log_color_state+0xf9/0x510 [amdgpu]
+[  +0.000306]  ? srso_alias_return_thunk+0x5/0xfbef5
+[  +0.000003]  ? vsnprintf+0x2fb/0x600
+[  +0.000009]  dcn10_log_hw_state+0xfd0/0xfe0 [amdgpu]
+[  +0.000218]  ? __mod_memcg_lruvec_state+0xe8/0x170
+[  +0.000008]  ? srso_alias_return_thunk+0x5/0xfbef5
+[  +0.000002]  ? debug_smp_processor_id+0x17/0x20
+[  +0.000003]  ? srso_alias_return_thunk+0x5/0xfbef5
+[  +0.000002]  ? srso_alias_return_thunk+0x5/0xfbef5
+[  +0.000002]  ? set_ptes.isra.0+0x2b/0x90
+[  +0.000004]  ? srso_alias_return_thunk+0x5/0xfbef5
+[  +0.000002]  ? _raw_spin_unlock+0x19/0x40
+[  +0.000004]  ? srso_alias_return_thunk+0x5/0xfbef5
+[  +0.000002]  ? do_anonymous_page+0x337/0x700
+[  +0.000004]  dtn_log_read+0x82/0x120 [amdgpu]
+[  +0.000207]  full_proxy_read+0x66/0x90
+[  +0.000007]  vfs_read+0xb0/0x340
+[  +0.000005]  ? __count_memcg_events+0x79/0xe0
+[  +0.000002]  ? srso_alias_return_thunk+0x5/0xfbef5
+[  +0.000003]  ? count_memcg_events.constprop.0+0x1e/0x40
+[  +0.000003]  ? handle_mm_fault+0xb2/0x370
+[  +0.000003]  ksys_read+0x6b/0xf0
+[  +0.000004]  __x64_sys_read+0x19/0x20
+[  +0.000003]  do_syscall_64+0x60/0x130
+[  +0.000004]  entry_SYSCALL_64_after_hwframe+0x6e/0x76
+[  +0.000003] RIP: 0033:0x7fdf32f147e2
+[...]
+
+This error happens when the color log tries to read the gamut remap
+information from DCN401 which is not initialized in the dcn401_dpp_funcs
+which leads to a null pointer dereference. This commit addresses this
+issue by adding a proper guard to access the gamut_remap callback in
+case the specific ASIC did not implement this function.
+
+Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c   | 49 ++++++++++---------
+ 1 file changed, 27 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+index 0c4aef8ffe2c5..3306684e805ac 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+@@ -288,6 +288,7 @@ static void dcn10_log_color_state(struct dc *dc,
+ {
+       struct dc_context *dc_ctx = dc->ctx;
+       struct resource_pool *pool = dc->res_pool;
++      bool is_gamut_remap_available = false;
+       int i;
+       DTN_INFO("DPP:    IGAM format    IGAM mode    DGAM mode    RGAM mode"
+@@ -300,16 +301,15 @@ static void dcn10_log_color_state(struct dc *dc,
+               struct dcn_dpp_state s = {0};
+               dpp->funcs->dpp_read_state(dpp, &s);
+-              dpp->funcs->dpp_get_gamut_remap(dpp, &s.gamut_remap);
++              if (dpp->funcs->dpp_get_gamut_remap) {
++                      dpp->funcs->dpp_get_gamut_remap(dpp, &s.gamut_remap);
++                      is_gamut_remap_available = true;
++              }
+               if (!s.is_enabled)
+                       continue;
+-              DTN_INFO("[%2d]:  %11xh  %11s    %9s    %9s"
+-                       "  %12s  "
+-                       "%010lld %010lld %010lld %010lld "
+-                       "%010lld %010lld %010lld %010lld "
+-                       "%010lld %010lld %010lld %010lld",
++              DTN_INFO("[%2d]:  %11xh  %11s    %9s    %9s",
+                               dpp->inst,
+                               s.igam_input_format,
+                               (s.igam_lut_mode == 0) ? "BypassFixed" :
+@@ -328,22 +328,27 @@ static void dcn10_log_color_state(struct dc *dc,
+                                       ((s.rgam_lut_mode == 2) ? "Ycc" :
+                                       ((s.rgam_lut_mode == 3) ? "RAM" :
+                                       ((s.rgam_lut_mode == 4) ? "RAM" :
+-                                                               "Unknown")))),
+-                              (s.gamut_remap.gamut_adjust_type == 0) ? "Bypass" :
+-                                      ((s.gamut_remap.gamut_adjust_type == 1) ? "HW" :
+-                                                                                "SW"),
+-                              s.gamut_remap.temperature_matrix[0].value,
+-                              s.gamut_remap.temperature_matrix[1].value,
+-                              s.gamut_remap.temperature_matrix[2].value,
+-                              s.gamut_remap.temperature_matrix[3].value,
+-                              s.gamut_remap.temperature_matrix[4].value,
+-                              s.gamut_remap.temperature_matrix[5].value,
+-                              s.gamut_remap.temperature_matrix[6].value,
+-                              s.gamut_remap.temperature_matrix[7].value,
+-                              s.gamut_remap.temperature_matrix[8].value,
+-                              s.gamut_remap.temperature_matrix[9].value,
+-                              s.gamut_remap.temperature_matrix[10].value,
+-                              s.gamut_remap.temperature_matrix[11].value);
++                                                               "Unknown")))));
++              if (is_gamut_remap_available)
++                      DTN_INFO("  %12s  "
++                               "%010lld %010lld %010lld %010lld "
++                               "%010lld %010lld %010lld %010lld "
++                               "%010lld %010lld %010lld %010lld",
++                               (s.gamut_remap.gamut_adjust_type == 0) ? "Bypass" :
++                                      ((s.gamut_remap.gamut_adjust_type == 1) ? "HW" : "SW"),
++                               s.gamut_remap.temperature_matrix[0].value,
++                               s.gamut_remap.temperature_matrix[1].value,
++                               s.gamut_remap.temperature_matrix[2].value,
++                               s.gamut_remap.temperature_matrix[3].value,
++                               s.gamut_remap.temperature_matrix[4].value,
++                               s.gamut_remap.temperature_matrix[5].value,
++                               s.gamut_remap.temperature_matrix[6].value,
++                               s.gamut_remap.temperature_matrix[7].value,
++                               s.gamut_remap.temperature_matrix[8].value,
++                               s.gamut_remap.temperature_matrix[9].value,
++                               s.gamut_remap.temperature_matrix[10].value,
++                               s.gamut_remap.temperature_matrix[11].value);
++
+               DTN_INFO("\n");
+       }
+       DTN_INFO("\n");
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-handle-hpd_irq-for-internal-link.patch b/queue-6.10/drm-amd-display-handle-hpd_irq-for-internal-link.patch
new file mode 100644 (file)
index 0000000..41267cc
--- /dev/null
@@ -0,0 +1,94 @@
+From ccc1ac5cd979220dd3625dcdf773aec5e68997c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Apr 2024 14:40:32 +0800
+Subject: drm/amd/display: Handle HPD_IRQ for internal link
+
+From: Sung-huai Wang <danny.wang@amd.com>
+
+[ Upstream commit 239b31bd5c3fef3698440bf6436b2068c6bb08a3 ]
+
+[Why]
+TCON data is corrupted after electro static discharge test.
+Once the TCON data get corrupted, they will get themselves
+reset and send HPD_IRQ to source side.
+
+[How]
+Support HPD_IRQ for internal link, and restore the PSR/Replay setup.
+
+Reviewed-by: Robin Chen <robin.chen@amd.com>
+Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Sung-huai Wang <danny.wang@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dc/link/protocols/link_dp_irq_handler.c   | 25 ++++++++++++-------
+ 1 file changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+index 0fcf0b8530acf..659b8064d3618 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+@@ -373,6 +373,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+       union device_service_irq device_service_clear = {0};
+       enum dc_status result;
+       bool status = false;
++      bool allow_active = false;
+       if (out_link_loss)
+               *out_link_loss = false;
+@@ -427,12 +428,6 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+               return false;
+       }
+-      if (handle_hpd_irq_psr_sink(link))
+-              /* PSR-related error was detected and handled */
+-              return true;
+-
+-      handle_hpd_irq_replay_sink(link);
+-
+       /* If PSR-related error handled, Main link may be off,
+        * so do not handle as a normal sink status change interrupt.
+        */
+@@ -454,9 +449,8 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+        * If we got sink count changed it means
+        * Downstream port status changed,
+        * then DM should call DC to do the detection.
+-       * NOTE: Do not handle link loss on eDP since it is internal link*/
+-      if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
+-                      dp_parse_link_loss_status(
++       */
++      if (dp_parse_link_loss_status(
+                                       link,
+                                       &hpd_irq_dpcd_data)) {
+               /* Connectivity log: link loss */
+@@ -465,6 +459,11 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+                                       sizeof(hpd_irq_dpcd_data),
+                                       "Status: ");
++              if (link->psr_settings.psr_feature_enabled)
++                      edp_set_psr_allow_active(link, &allow_active, true, false, NULL);
++              else if (link->replay_settings.replay_allow_active)
++                      edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
++
+               if (defer_handling && has_left_work)
+                       *has_left_work = true;
+               else
+@@ -477,6 +476,14 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+               dp_trace_link_loss_increment(link);
+       }
++      if (*out_link_loss == false) {
++              if (handle_hpd_irq_psr_sink(link))
++                      /* PSR-related error was detected and handled */
++                      return true;
++
++              handle_hpd_irq_replay_sink(link);
++      }
++
+       if (link->type == dc_connection_sst_branch &&
+               hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
+                       != link->dpcd_sink_count)
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-reduce-odm-slice-count-to-initial-ne.patch b/queue-6.10/drm-amd-display-reduce-odm-slice-count-to-initial-ne.patch
new file mode 100644 (file)
index 0000000..c632983
--- /dev/null
@@ -0,0 +1,235 @@
+From 757d529cb7d14863eea92bc0754ace8f1e0626c6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 May 2024 17:05:41 -0400
+Subject: drm/amd/display: reduce ODM slice count to initial new dc state only
+ when needed
+
+From: Wenjing Liu <wenjing.liu@amd.com>
+
+[ Upstream commit 9a29c4adb0997be6ba3dd92dfba14ea75a8c6ce4 ]
+
+[why]
+We need to decrease ODM slice when adding or removing planes because MPO
+support takes precedence over dynamic ODM combine. However there is a case where
+we remove ODM combine even for ODM combine required timing in the initial new
+dc state. This is normally okay because ODM will be added back after we pass DML
+bandwidth validation. However since we remove ODM combine in the initial new
+state, the previous ODM pipe allocation is lost. This may cause the new plane to
+take away the original secondary OPP head pipe that is still required in the new
+state.
+
+For a timing that requires ODM 2:1 but optimized with ODM 4:1, if we add an MPO
+plane, we will not have enough pipe to preserve ODM 4:1. In this case we should
+reduce ODM slice count then try to add the MPO plane again. By reducing, we are
+gradually remove 1 ODM slice from right most side one at a time until we have
+enough free pipes for the new plane. If we remove ODM combine entirely, we could
+use the pipe at ODM slice index 1 as a DPP pipe for the new plane. But ODM slice
+1 is still needed as the timing requires ODM 2:1. This transition is not
+seamless and user will see corruption on the screen.
+
+[how]
+Remove single ODM slice one at time until we have enough pipes for a new plane.
+Remove previous logic to always remove ODM combine entirely.
+
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Acked-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/core/dc_resource.c | 45 +++++++------
+ .../gpu/drm/amd/display/dc/core/dc_state.c    | 67 +++++++++++++------
+ 2 files changed, 71 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index 15819416a2f36..a2ca66a268c2d 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -2508,6 +2508,17 @@ static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx,
+       }
+ }
++static int get_num_of_free_pipes(const struct resource_pool *pool, const struct dc_state *context)
++{
++      int i;
++      int count = 0;
++
++      for (i = 0; i < pool->pipe_count; i++)
++              if (resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], FREE_PIPE))
++                      count++;
++      return count;
++}
++
+ enum dc_status resource_add_otg_master_for_stream_output(struct dc_state *new_ctx,
+               const struct resource_pool *pool,
+               struct dc_stream_state *stream)
+@@ -2641,37 +2652,33 @@ static bool acquire_secondary_dpp_pipes_and_add_plane(
+               struct dc_state *cur_ctx,
+               struct resource_pool *pool)
+ {
+-      struct pipe_ctx *opp_head_pipe, *sec_pipe, *tail_pipe;
++      struct pipe_ctx *sec_pipe, *tail_pipe;
++      struct pipe_ctx *opp_heads[MAX_PIPES];
++      int opp_head_count;
++      int i;
+       if (!pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe) {
+               ASSERT(0);
+               return false;
+       }
+-      opp_head_pipe = otg_master_pipe;
+-      while (opp_head_pipe) {
++      opp_head_count = resource_get_opp_heads_for_otg_master(otg_master_pipe,
++                      &new_ctx->res_ctx, opp_heads);
++      if (get_num_of_free_pipes(pool, new_ctx) < opp_head_count)
++              /* not enough free pipes */
++              return false;
++
++      for (i = 0; i < opp_head_count; i++) {
+               sec_pipe = pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe(
+                               cur_ctx,
+                               new_ctx,
+                               pool,
+-                              opp_head_pipe);
+-              if (!sec_pipe) {
+-                      /* try tearing down MPCC combine */
+-                      int pipe_idx = acquire_first_split_pipe(
+-                                      &new_ctx->res_ctx, pool,
+-                                      otg_master_pipe->stream);
+-
+-                      if (pipe_idx >= 0)
+-                              sec_pipe = &new_ctx->res_ctx.pipe_ctx[pipe_idx];
+-              }
+-
+-              if (!sec_pipe)
+-                      return false;
+-
++                              opp_heads[i]);
++              ASSERT(sec_pipe);
+               sec_pipe->plane_state = plane_state;
+               /* establish pipe relationship */
+-              tail_pipe = get_tail_pipe(opp_head_pipe);
++              tail_pipe = get_tail_pipe(opp_heads[i]);
+               tail_pipe->bottom_pipe = sec_pipe;
+               sec_pipe->top_pipe = tail_pipe;
+               sec_pipe->bottom_pipe = NULL;
+@@ -2682,8 +2689,6 @@ static bool acquire_secondary_dpp_pipes_and_add_plane(
+               } else {
+                       sec_pipe->prev_odm_pipe = NULL;
+               }
+-
+-              opp_head_pipe = opp_head_pipe->next_odm_pipe;
+       }
+       return true;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+index 76bb05f4d6bf3..52a1cfc5feed8 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+@@ -437,6 +437,19 @@ enum dc_status dc_state_remove_stream(
+       return DC_OK;
+ }
++static void remove_mpc_combine_for_stream(const struct dc *dc,
++              struct dc_state *new_ctx,
++              const struct dc_state *cur_ctx,
++              struct dc_stream_status *status)
++{
++      int i;
++
++      for (i = 0; i < status->plane_count; i++)
++              resource_update_pipes_for_plane_with_slice_count(
++                              new_ctx, cur_ctx, dc->res_pool,
++                              status->plane_states[i], 1);
++}
++
+ bool dc_state_add_plane(
+               const struct dc *dc,
+               struct dc_stream_state *stream,
+@@ -447,8 +460,12 @@ bool dc_state_add_plane(
+       struct pipe_ctx *otg_master_pipe;
+       struct dc_stream_status *stream_status = NULL;
+       bool added = false;
++      int odm_slice_count;
++      int i;
+       stream_status = dc_state_get_stream_status(state, stream);
++      otg_master_pipe = resource_get_otg_master_for_stream(
++                      &state->res_ctx, stream);
+       if (stream_status == NULL) {
+               dm_error("Existing stream not found; failed to attach surface!\n");
+               goto out;
+@@ -456,22 +473,39 @@ bool dc_state_add_plane(
+               dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
+                               plane_state, MAX_SURFACE_NUM);
+               goto out;
++      } else if (!otg_master_pipe) {
++              goto out;
+       }
+-      if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
+-              /* ODM combine could prevent us from supporting more planes
+-               * we will reset ODM slice count back to 1 when all planes have
+-               * been removed to maximize the amount of planes supported when
+-               * new planes are added.
+-               */
+-              resource_update_pipes_for_stream_with_slice_count(
+-                              state, dc->current_state, dc->res_pool, stream, 1);
++      added = resource_append_dpp_pipes_for_plane_composition(state,
++                      dc->current_state, pool, otg_master_pipe, plane_state);
+-      otg_master_pipe = resource_get_otg_master_for_stream(
+-                      &state->res_ctx, stream);
+-      if (otg_master_pipe)
++      if (!added) {
++              /* try to remove MPC combine to free up pipes */
++              for (i = 0; i < state->stream_count; i++)
++                      remove_mpc_combine_for_stream(dc, state,
++                                      dc->current_state,
++                                      &state->stream_status[i]);
+               added = resource_append_dpp_pipes_for_plane_composition(state,
+-                              dc->current_state, pool, otg_master_pipe, plane_state);
++                                      dc->current_state, pool,
++                                      otg_master_pipe, plane_state);
++      }
++
++      if (!added) {
++              /* try to decrease ODM slice count gradually to free up pipes */
++              odm_slice_count = resource_get_odm_slice_count(otg_master_pipe);
++              for (i = odm_slice_count - 1; i > 0; i--) {
++                      resource_update_pipes_for_stream_with_slice_count(state,
++                                      dc->current_state, dc->res_pool, stream,
++                                      i);
++                      added = resource_append_dpp_pipes_for_plane_composition(
++                                      state,
++                                      dc->current_state, pool,
++                                      otg_master_pipe, plane_state);
++                      if (added)
++                              break;
++              }
++      }
+       if (added) {
+               stream_status->plane_states[stream_status->plane_count] =
+@@ -531,15 +565,6 @@ bool dc_state_remove_plane(
+       stream_status->plane_states[stream_status->plane_count] = NULL;
+-      if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
+-              /* ODM combine could prevent us from supporting more planes
+-               * we will reset ODM slice count back to 1 when all planes have
+-               * been removed to maximize the amount of planes supported when
+-               * new planes are added.
+-               */
+-              resource_update_pipes_for_stream_with_slice_count(
+-                              state, dc->current_state, dc->res_pool, stream, 1);
+-
+       return true;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-remove-dpp-pipes-on-failure-to-updat.patch b/queue-6.10/drm-amd-display-remove-dpp-pipes-on-failure-to-updat.patch
new file mode 100644 (file)
index 0000000..f3571a5
--- /dev/null
@@ -0,0 +1,66 @@
+From c023cd7163dd6984148c259b8048d987cd6fa8d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 May 2024 14:17:34 -0400
+Subject: drm/amd/display: remove dpp pipes on failure to update pipe params
+
+From: Wenjing Liu <wenjing.liu@amd.com>
+
+[ Upstream commit 3ddd9c83ff7ac0ead38188425b14d03dc2f2c133 ]
+
+[why]
+There are cases where update pipe params could fail but dpp pipes are already
+added to the state. In this case, we should remove dpp pipes so dc state is
+restored back. If it is not restored, dc state is corrupted after calling this
+function, so if we call the same interface with the corrupted state again, we
+may end up programming pipe topology based on a corrupted dc state.
+
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Acked-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index a2ca66a268c2d..a51e5de6554ee 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -2701,6 +2701,7 @@ bool resource_append_dpp_pipes_for_plane_composition(
+               struct dc_plane_state *plane_state)
+ {
+       bool success;
++
+       if (otg_master_pipe->plane_state == NULL)
+               success = add_plane_to_opp_head_pipes(otg_master_pipe,
+                               plane_state, new_ctx);
+@@ -2708,10 +2709,15 @@ bool resource_append_dpp_pipes_for_plane_composition(
+               success = acquire_secondary_dpp_pipes_and_add_plane(
+                               otg_master_pipe, plane_state, new_ctx,
+                               cur_ctx, pool);
+-      if (success)
++      if (success) {
+               /* when appending a plane mpc slice count changes from 0 to 1 */
+               success = update_pipe_params_after_mpc_slice_count_change(
+                               plane_state, new_ctx, pool);
++              if (!success)
++                      resource_remove_dpp_pipes_for_plane_composition(new_ctx,
++                                      pool, plane_state);
++      }
++
+       return success;
+ }
+@@ -2721,6 +2727,7 @@ void resource_remove_dpp_pipes_for_plane_composition(
+               const struct dc_plane_state *plane_state)
+ {
+       int i;
++
+       for (i = pool->pipe_count - 1; i >= 0; i--) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-display-wake-dmcub-before-sending-a-command-.patch b/queue-6.10/drm-amd-display-wake-dmcub-before-sending-a-command-.patch
new file mode 100644 (file)
index 0000000..7e6d30a
--- /dev/null
@@ -0,0 +1,69 @@
+From 7df4a098a4fe0480fd292647816550d4d176cfd9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Dec 2023 16:35:04 -0500
+Subject: drm/amd/display: Wake DMCUB before sending a command for replay
+ feature
+
+From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+
+[ Upstream commit 3601a35a2e9d640233f4bc3496f7603b93f9c143 ]
+
+[Why]
+We can hang in place trying to send commands when the DMCUB isn't
+powered on.
+
+[How]
+For functions that execute within a DC context or DC lock we can wrap
+the direct calls to dm_execute_dmub_cmd/list with code that exits idle
+power optimizations and reallows once we're done with the command
+submission on success.
+
+For DM direct submissions the DM will need to manage the enter/exit
+sequencing manually.
+
+We cannot invoke a DMCUB command directly within the DM execution helper
+or we can deadlock.
+
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+index 4f559a025cf00..f820647443d16 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+@@ -84,7 +84,7 @@ static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait,
+       cmd.replay_enable.header.payload_bytes = sizeof(struct dmub_rb_cmd_replay_enable_data);
+-      dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
++      dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+       /* Below loops 1000 x 500us = 500 ms.
+        *  Exit REPLAY may need to wait 1-2 frames to power up. Timeout after at
+@@ -127,7 +127,7 @@ static void dmub_replay_set_power_opt(struct dmub_replay *dmub, unsigned int pow
+       cmd.replay_set_power_opt.replay_set_power_opt_data.power_opt = power_opt;
+       cmd.replay_set_power_opt.replay_set_power_opt_data.panel_inst = panel_inst;
+-      dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
++      dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ }
+ /*
+@@ -231,7 +231,7 @@ static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub,
+       cmd.replay_set_coasting_vtotal.header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data);
+       cmd.replay_set_coasting_vtotal.replay_set_coasting_vtotal_data.coasting_vtotal = coasting_vtotal;
+-      dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
++      dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amd-pm-fix-the-null-pointer-dereference-for-vega.patch b/queue-6.10/drm-amd-pm-fix-the-null-pointer-dereference-for-vega.patch
new file mode 100644 (file)
index 0000000..dba204d
--- /dev/null
@@ -0,0 +1,114 @@
+From 3debc8183b07e5eb1494d60687490d81b00e42fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 May 2024 15:01:22 +0800
+Subject: drm/amd/pm: Fix the null pointer dereference for vega10_hwmgr
+
+From: Bob Zhou <bob.zhou@amd.com>
+
+[ Upstream commit 50151b7f1c79a09117837eb95b76c2de76841dab ]
+
+Check return value and conduct null pointer handling to avoid null pointer dereference.
+
+Signed-off-by: Bob Zhou <bob.zhou@amd.com>
+Reviewed-by: Tim Huang <Tim.Huang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 29 ++++++++++++++++---
+ 1 file changed, 25 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+index 8d7dc0e5417ed..f4acdb2267416 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+@@ -3418,13 +3418,17 @@ static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, co
+       const struct vega10_power_state *vega10_ps =
+                       cast_const_phw_vega10_power_state(states->pnew_state);
+       struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
+-      uint32_t sclk = vega10_ps->performance_levels
+-                      [vega10_ps->performance_level_count - 1].gfx_clock;
+       struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
+-      uint32_t mclk = vega10_ps->performance_levels
+-                      [vega10_ps->performance_level_count - 1].mem_clock;
++      uint32_t sclk, mclk;
+       uint32_t i;
++      if (vega10_ps == NULL)
++              return -EINVAL;
++      sclk = vega10_ps->performance_levels
++                      [vega10_ps->performance_level_count - 1].gfx_clock;
++      mclk = vega10_ps->performance_levels
++                      [vega10_ps->performance_level_count - 1].mem_clock;
++
+       for (i = 0; i < sclk_table->count; i++) {
+               if (sclk == sclk_table->dpm_levels[i].value)
+                       break;
+@@ -3731,6 +3735,9 @@ static int vega10_generate_dpm_level_enable_mask(
+                       cast_const_phw_vega10_power_state(states->pnew_state);
+       int i;
++      if (vega10_ps == NULL)
++              return -EINVAL;
++
+       PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps),
+                       "Attempt to Trim DPM States Failed!",
+                       return -1);
+@@ -4998,6 +5005,8 @@ static int vega10_check_states_equal(struct pp_hwmgr *hwmgr,
+       vega10_psa = cast_const_phw_vega10_power_state(pstate1);
+       vega10_psb = cast_const_phw_vega10_power_state(pstate2);
++      if (vega10_psa == NULL || vega10_psb == NULL)
++              return -EINVAL;
+       /* If the two states don't even have the same number of performance levels
+        * they cannot be the same state.
+@@ -5131,6 +5140,8 @@ static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
+               return -EINVAL;
+       vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
++      if (vega10_ps == NULL)
++              return -EINVAL;
+       vega10_ps->performance_levels
+       [vega10_ps->performance_level_count - 1].gfx_clock =
+@@ -5182,6 +5193,8 @@ static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
+               return -EINVAL;
+       vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
++      if (vega10_ps == NULL)
++              return -EINVAL;
+       vega10_ps->performance_levels
+       [vega10_ps->performance_level_count - 1].mem_clock =
+@@ -5423,6 +5436,9 @@ static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr)
+               return;
+       vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
++      if (vega10_ps == NULL)
++              return;
++
+       max_level = vega10_ps->performance_level_count - 1;
+       if (vega10_ps->performance_levels[max_level].gfx_clock !=
+@@ -5445,6 +5461,9 @@ static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr)
+       ps = (struct pp_power_state *)((unsigned long)(hwmgr->ps) + hwmgr->ps_size * (hwmgr->num_ps - 1));
+       vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
++      if (vega10_ps == NULL)
++              return;
++
+       max_level = vega10_ps->performance_level_count - 1;
+       if (vega10_ps->performance_levels[max_level].gfx_clock !=
+@@ -5635,6 +5654,8 @@ static int vega10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_
+               return -EINVAL;
+       vega10_ps = cast_const_phw_vega10_power_state(state);
++      if (vega10_ps == NULL)
++              return -EINVAL;
+       i = index > vega10_ps->performance_level_count - 1 ?
+                       vega10_ps->performance_level_count - 1 : index;
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amdgpu-add-lock-around-vf-rlcg-interface.patch b/queue-6.10/drm-amdgpu-add-lock-around-vf-rlcg-interface.patch
new file mode 100644 (file)
index 0000000..996b7e5
--- /dev/null
@@ -0,0 +1,78 @@
+From cc1128f2104fda9f2e9e1ed13407fa7017242ff9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 16:10:43 -0400
+Subject: drm/amdgpu: Add lock around VF RLCG interface
+
+From: Victor Skvortsov <victor.skvortsov@amd.com>
+
+[ Upstream commit e864180ee49b4d30e640fd1e1d852b86411420c9 ]
+
+flush_gpu_tlb may be called from another thread while
+device_gpu_recover is running.
+
+Both of these threads access registers through the VF
+RLCG interface during VF Full Access. Add a lock around this interface
+to prevent race conditions between these threads.
+
+Signed-off-by: Victor Skvortsov <victor.skvortsov@amd.com>
+Reviewed-by: Zhigang Luo <zhigang.luo@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 +
+ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c   | 6 ++++++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h   | 2 ++
+ 3 files changed, 9 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index ee7df1d84e028..89cf9ac6da174 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -4048,6 +4048,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
+       mutex_init(&adev->grbm_idx_mutex);
+       mutex_init(&adev->mn_lock);
+       mutex_init(&adev->virt.vf_errors.lock);
++      mutex_init(&adev->virt.rlcg_reg_lock);
+       hash_init(adev->mn_hash);
+       mutex_init(&adev->psp.mutex);
+       mutex_init(&adev->notifier_lock);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+index 54ab51a4ada77..972a58f0f4924 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+@@ -980,6 +980,9 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f
+       scratch_reg1 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg1;
+       scratch_reg2 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg2;
+       scratch_reg3 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg3;
++
++      mutex_lock(&adev->virt.rlcg_reg_lock);
++
+       if (reg_access_ctrl->spare_int)
+               spare_int = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->spare_int;
+@@ -1036,6 +1039,9 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f
+       }
+       ret = readl(scratch_reg0);
++
++      mutex_unlock(&adev->virt.rlcg_reg_lock);
++
+       return ret;
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+index 642f1fd287d83..0ec246c74570c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+@@ -272,6 +272,8 @@ struct amdgpu_virt {
+       /* the ucode id to signal the autoload */
+       uint32_t autoload_ucode_id;
++
++      struct mutex rlcg_reg_lock;
+ };
+ struct amdgpu_video_codec_info;
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amdgpu-fix-potential-resource-leak-warning.patch b/queue-6.10/drm-amdgpu-fix-potential-resource-leak-warning.patch
new file mode 100644 (file)
index 0000000..42187e8
--- /dev/null
@@ -0,0 +1,42 @@
+From 257f1201243d672e09b0728c33db390a06232c81 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 11:09:00 +0800
+Subject: drm/amdgpu: fix potential resource leak warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tim Huang <Tim.Huang@amd.com>
+
+[ Upstream commit 22a5daaec0660dd19740c4c6608b78f38760d1e6 ]
+
+Clear resource leak warning that when the prepare fails,
+the allocated amdgpu job object will never be released.
+
+Signed-off-by: Tim Huang <Tim.Huang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
+index 66e8a016126b8..9b748d7058b5c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
+@@ -102,6 +102,11 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p,
+       if (!r)
+               r = amdgpu_sync_push_to_job(&sync, p->job);
+       amdgpu_sync_free(&sync);
++
++      if (r) {
++              p->num_dw_left = 0;
++              amdgpu_job_free(p->job);
++      }
+       return r;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amdgpu-fix-the-null-pointer-dereference-to-ras_m.patch b/queue-6.10/drm-amdgpu-fix-the-null-pointer-dereference-to-ras_m.patch
new file mode 100644 (file)
index 0000000..f8143f1
--- /dev/null
@@ -0,0 +1,44 @@
+From ac585cb8a2f143e114b9deeb29b8030200d36b76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 May 2024 15:48:02 +0800
+Subject: drm/amdgpu: Fix the null pointer dereference to ras_manager
+
+From: Ma Jun <Jun.Ma2@amd.com>
+
+[ Upstream commit 4c11d30c95576937c6c35e6f29884761f2dddb43 ]
+
+Check ras_manager before using it
+
+Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+index 1adc81a55734d..0c4ee06451e9c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+@@ -2172,12 +2172,15 @@ static void amdgpu_ras_interrupt_process_handler(struct work_struct *work)
+ int amdgpu_ras_interrupt_dispatch(struct amdgpu_device *adev,
+               struct ras_dispatch_if *info)
+ {
+-      struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
+-      struct ras_ih_data *data = &obj->ih_data;
++      struct ras_manager *obj;
++      struct ras_ih_data *data;
++      obj = amdgpu_ras_find_obj(adev, &info->head);
+       if (!obj)
+               return -EINVAL;
++      data = &obj->ih_data;
++
+       if (data->inuse == 0)
+               return 0;
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-for-s.patch b/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-for-s.patch
new file mode 100644 (file)
index 0000000..aee43a0
--- /dev/null
@@ -0,0 +1,99 @@
+From ab9b20b8a7b373daa083ef37d79c719d918552a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 15:01:59 +0800
+Subject: drm/amdgpu/pm: Fix the null pointer dereference for smu7
+
+From: Ma Jun <Jun.Ma2@amd.com>
+
+[ Upstream commit c02c1960c93eede587576625a1221205a68a904f ]
+
+optimize the code to avoid pass a null pointer (hwmgr->backend)
+to function smu7_update_edc_leakage_table.
+
+Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
+Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c   | 50 +++++++++----------
+ 1 file changed, 24 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+index 1fcd4451001fa..5d0c281f2378c 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+@@ -2957,6 +2957,7 @@ static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr)
+ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+ {
++      struct amdgpu_device *adev = hwmgr->adev;
+       struct smu7_hwmgr *data;
+       int result = 0;
+@@ -2993,40 +2994,37 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+       /* Initalize Dynamic State Adjustment Rule Settings */
+       result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
+-      if (0 == result) {
+-              struct amdgpu_device *adev = hwmgr->adev;
++      if (result)
++              goto fail;
+-              data->is_tlu_enabled = false;
++      data->is_tlu_enabled = false;
+-              hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
++      hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
+                                                       SMU7_MAX_HARDWARE_POWERLEVELS;
+-              hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
+-              hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
++      hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
++      hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
+-              data->pcie_gen_cap = adev->pm.pcie_gen_mask;
+-              if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
+-                      data->pcie_spc_cap = 20;
+-              else
+-                      data->pcie_spc_cap = 16;
+-              data->pcie_lane_cap = adev->pm.pcie_mlw_mask;
+-
+-              hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
+-/* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
+-              hwmgr->platform_descriptor.clockStep.engineClock = 500;
+-              hwmgr->platform_descriptor.clockStep.memoryClock = 500;
+-              smu7_thermal_parameter_init(hwmgr);
+-      } else {
+-              /* Ignore return value in here, we are cleaning up a mess. */
+-              smu7_hwmgr_backend_fini(hwmgr);
+-      }
++      data->pcie_gen_cap = adev->pm.pcie_gen_mask;
++      if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
++              data->pcie_spc_cap = 20;
++      else
++              data->pcie_spc_cap = 16;
++      data->pcie_lane_cap = adev->pm.pcie_mlw_mask;
++
++      hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
++      /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
++      hwmgr->platform_descriptor.clockStep.engineClock = 500;
++      hwmgr->platform_descriptor.clockStep.memoryClock = 500;
++      smu7_thermal_parameter_init(hwmgr);
+       result = smu7_update_edc_leakage_table(hwmgr);
+-      if (result) {
+-              smu7_hwmgr_backend_fini(hwmgr);
+-              return result;
+-      }
++      if (result)
++              goto fail;
+       return 0;
++fail:
++      smu7_hwmgr_backend_fini(hwmgr);
++      return result;
+ }
+ static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr)
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-in-ap.patch b/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-in-ap.patch
new file mode 100644 (file)
index 0000000..0b823a6
--- /dev/null
@@ -0,0 +1,105 @@
+From e27959baf16e47ed93ddbfb86cb622554af866cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 May 2024 15:51:35 +0800
+Subject: drm/amdgpu/pm: Fix the null pointer dereference in
+ apply_state_adjust_rules
+
+From: Ma Jun <Jun.Ma2@amd.com>
+
+[ Upstream commit d19fb10085a49b77578314f69fff21562f7cd054 ]
+
+Check the pointer value to fix potential null pointer
+dereference
+
+Acked-by: Yang Wang<kevinyang.wang@amd.com>
+Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c    |  7 +++++--
+ .../gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c    | 14 ++++++++------
+ .../gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c  |  7 +++++--
+ 3 files changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+index 5d0c281f2378c..f1c369945ac5d 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+@@ -3314,8 +3314,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+                       const struct pp_power_state *current_ps)
+ {
+       struct amdgpu_device *adev = hwmgr->adev;
+-      struct smu7_power_state *smu7_ps =
+-                              cast_phw_smu7_power_state(&request_ps->hardware);
++      struct smu7_power_state *smu7_ps;
+       uint32_t sclk;
+       uint32_t mclk;
+       struct PP_Clocks minimum_clocks = {0};
+@@ -3332,6 +3331,10 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+       uint32_t latency;
+       bool latency_allowed = false;
++      smu7_ps = cast_phw_smu7_power_state(&request_ps->hardware);
++      if (!smu7_ps)
++              return -EINVAL;
++
+       data->battery_state = (PP_StateUILabel_Battery ==
+                       request_ps->classification.ui_label);
+       data->mclk_ignore_signal = false;
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c
+index b015a601b385a..eb744401e0567 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c
+@@ -1065,16 +1065,18 @@ static int smu8_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+                               struct pp_power_state  *prequest_ps,
+                       const struct pp_power_state *pcurrent_ps)
+ {
+-      struct smu8_power_state *smu8_ps =
+-                              cast_smu8_power_state(&prequest_ps->hardware);
+-
+-      const struct smu8_power_state *smu8_current_ps =
+-                              cast_const_smu8_power_state(&pcurrent_ps->hardware);
+-
++      struct smu8_power_state *smu8_ps;
++      const struct smu8_power_state *smu8_current_ps;
+       struct smu8_hwmgr *data = hwmgr->backend;
+       struct PP_Clocks clocks = {0, 0, 0, 0};
+       bool force_high;
++      smu8_ps = cast_smu8_power_state(&prequest_ps->hardware);
++      smu8_current_ps = cast_const_smu8_power_state(&pcurrent_ps->hardware);
++
++      if (!smu8_ps || !smu8_current_ps)
++              return -EINVAL;
++
+       smu8_ps->need_dfs_bypass = true;
+       data->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label);
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+index 9f5bd998c6bff..8d7dc0e5417ed 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+@@ -3259,8 +3259,7 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+                       const struct pp_power_state *current_ps)
+ {
+       struct amdgpu_device *adev = hwmgr->adev;
+-      struct vega10_power_state *vega10_ps =
+-                              cast_phw_vega10_power_state(&request_ps->hardware);
++      struct vega10_power_state *vega10_ps;
+       uint32_t sclk;
+       uint32_t mclk;
+       struct PP_Clocks minimum_clocks = {0};
+@@ -3278,6 +3277,10 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+       uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
+       uint32_t latency;
++      vega10_ps = cast_phw_vega10_power_state(&request_ps->hardware);
++      if (!vega10_ps)
++              return -EINVAL;
++
+       data->battery_state = (PP_StateUILabel_Battery ==
+                       request_ps->classification.ui_label);
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-amdgpu-pm-fix-the-param-type-of-set_power_profil.patch b/queue-6.10/drm-amdgpu-pm-fix-the-param-type-of-set_power_profil.patch
new file mode 100644 (file)
index 0000000..dcf4511
--- /dev/null
@@ -0,0 +1,151 @@
+From d6949fe3402e882edaff83a660883e4d83c296ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 28 Apr 2024 15:58:10 +0800
+Subject: drm/amdgpu/pm: Fix the param type of set_power_profile_mode
+
+From: Ma Jun <Jun.Ma2@amd.com>
+
+[ Upstream commit f683f24093dd94a831085fe0ea8e9dc4c6c1a2d1 ]
+
+Function .set_power_profile_mode need an array as input
+parameter. So define variable workload as an array to fix
+the below coverity warning.
+
+"Passing &workload to function hwmgr->hwmgr_func->set_power_profile_mode
+which uses it as an array. This might corrupt or misinterpret adjacent
+memory locations"
+
+Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c |  8 ++++----
+ drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c  |  8 ++++----
+ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c        | 16 ++++++++--------
+ 3 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+index 5fb21a0508cd9..f531ce1d2b1dc 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+@@ -929,7 +929,7 @@ static int pp_dpm_switch_power_profile(void *handle,
+               enum PP_SMC_POWER_PROFILE type, bool en)
+ {
+       struct pp_hwmgr *hwmgr = handle;
+-      long workload;
++      long workload[1];
+       uint32_t index;
+       if (!hwmgr || !hwmgr->pm_en)
+@@ -947,12 +947,12 @@ static int pp_dpm_switch_power_profile(void *handle,
+               hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);
+               index = fls(hwmgr->workload_mask);
+               index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
+-              workload = hwmgr->workload_setting[index];
++              workload[0] = hwmgr->workload_setting[index];
+       } else {
+               hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);
+               index = fls(hwmgr->workload_mask);
+               index = index <= Workload_Policy_Max ? index - 1 : 0;
+-              workload = hwmgr->workload_setting[index];
++              workload[0] = hwmgr->workload_setting[index];
+       }
+       if (type == PP_SMC_POWER_PROFILE_COMPUTE &&
+@@ -962,7 +962,7 @@ static int pp_dpm_switch_power_profile(void *handle,
+       }
+       if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+-              hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
++              hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, workload, 0);
+       return 0;
+ }
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c
+index 1d829402cd2e2..f4bd8e9357e22 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c
+@@ -269,7 +269,7 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_set
+                                               struct pp_power_state *new_ps)
+ {
+       uint32_t index;
+-      long workload;
++      long workload[1];
+       if (hwmgr->not_vf) {
+               if (!skip_display_settings)
+@@ -294,10 +294,10 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_set
+       if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
+               index = fls(hwmgr->workload_mask);
+               index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
+-              workload = hwmgr->workload_setting[index];
++              workload[0] = hwmgr->workload_setting[index];
+-              if (hwmgr->power_profile_mode != workload && hwmgr->hwmgr_func->set_power_profile_mode)
+-                      hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
++              if (hwmgr->power_profile_mode != workload[0] && hwmgr->hwmgr_func->set_power_profile_mode)
++                      hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, workload, 0);
+       }
+       return 0;
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+index e1796ecf9c05c..06409133b09b1 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+@@ -2220,7 +2220,7 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu,
+ {
+       int ret = 0;
+       int index = 0;
+-      long workload;
++      long workload[1];
+       struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
+       if (!skip_display_settings) {
+@@ -2260,10 +2260,10 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu,
+               smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
+               index = fls(smu->workload_mask);
+               index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+-              workload = smu->workload_setting[index];
++              workload[0] = smu->workload_setting[index];
+-              if (smu->power_profile_mode != workload)
+-                      smu_bump_power_profile_mode(smu, &workload, 0);
++              if (smu->power_profile_mode != workload[0])
++                      smu_bump_power_profile_mode(smu, workload, 0);
+       }
+       return ret;
+@@ -2313,7 +2313,7 @@ static int smu_switch_power_profile(void *handle,
+ {
+       struct smu_context *smu = handle;
+       struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
+-      long workload;
++      long workload[1];
+       uint32_t index;
+       if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
+@@ -2326,17 +2326,17 @@ static int smu_switch_power_profile(void *handle,
+               smu->workload_mask &= ~(1 << smu->workload_prority[type]);
+               index = fls(smu->workload_mask);
+               index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+-              workload = smu->workload_setting[index];
++              workload[0] = smu->workload_setting[index];
+       } else {
+               smu->workload_mask |= (1 << smu->workload_prority[type]);
+               index = fls(smu->workload_mask);
+               index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+-              workload = smu->workload_setting[index];
++              workload[0] = smu->workload_setting[index];
+       }
+       if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
+               smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
+-              smu_bump_power_profile_mode(smu, &workload, 0);
++              smu_bump_power_profile_mode(smu, workload, 0);
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-xe-preempt_fence-enlarge-the-fence-critical-sect.patch b/queue-6.10/drm-xe-preempt_fence-enlarge-the-fence-critical-sect.patch
new file mode 100644 (file)
index 0000000..0d025ba
--- /dev/null
@@ -0,0 +1,58 @@
+From 01d5e852b29741df41afd95b2a1e478f1003046b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Apr 2024 15:46:31 +0100
+Subject: drm/xe/preempt_fence: enlarge the fence critical section
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+[ Upstream commit 3cd1585e57908b6efcd967465ef7685f40b2a294 ]
+
+It is really easy to introduce subtle deadlocks in
+preempt_fence_work_func() since we operate on single global ordered-wq
+for signalling our preempt fences behind the scenes, so even though we
+signal a particular fence, everything in the callback should be in the
+fence critical section, since blocking in the callback will prevent
+other published fences from signalling. If we enlarge the fence critical
+section to cover the entire callback, then lockdep should be able to
+understand this better, and complain if we grab a sensitive lock like
+vm->lock, which is also held when waiting on preempt fences.
+
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Cc: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240418144630.299531-2-matthew.auld@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_preempt_fence.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_preempt_fence.c b/drivers/gpu/drm/xe/xe_preempt_fence.c
+index 7d50c6e89d8e7..5b243b7feb59d 100644
+--- a/drivers/gpu/drm/xe/xe_preempt_fence.c
++++ b/drivers/gpu/drm/xe/xe_preempt_fence.c
+@@ -23,11 +23,19 @@ static void preempt_fence_work_func(struct work_struct *w)
+               q->ops->suspend_wait(q);
+       dma_fence_signal(&pfence->base);
+-      dma_fence_end_signalling(cookie);
+-
++      /*
++       * Opt for keep everything in the fence critical section. This looks really strange since we
++       * have just signalled the fence, however the preempt fences are all signalled via single
++       * global ordered-wq, therefore anything that happens in this callback can easily block
++       * progress on the entire wq, which itself may prevent other published preempt fences from
++       * ever signalling.  Therefore try to keep everything here in the callback in the fence
++       * critical section. For example if something below grabs a scary lock like vm->lock,
++       * lockdep should complain since we also hold that lock whilst waiting on preempt fences to
++       * complete.
++       */
+       xe_vm_queue_rebind_worker(q->vm);
+-
+       xe_exec_queue_put(q);
++      dma_fence_end_signalling(cookie);
+ }
+ static const char *
+-- 
+2.43.0
+
diff --git a/queue-6.10/drm-xe-xe_guc_submit-fix-exec-queue-stop-race-condit.patch b/queue-6.10/drm-xe-xe_guc_submit-fix-exec-queue-stop-race-condit.patch
new file mode 100644 (file)
index 0000000..4dda89f
--- /dev/null
@@ -0,0 +1,43 @@
+From 631e1848172aa763280eb4fe20ba9db6779a7829 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 12:45:38 -0700
+Subject: drm/xe/xe_guc_submit: Fix exec queue stop race condition
+
+From: Jonathan Cavitt <jonathan.cavitt@intel.com>
+
+[ Upstream commit 1564d411e17f51e2f64655b4e4da015be1ba7eaa ]
+
+Reorder the xe_sched_tdr_queue_imm and set_exec_queue_banned calls in
+guc_exec_queue_stop.  This prevents a possible race condition between
+the two events in which it's possible for xe_sched_tdr_queue_imm to
+wake the ufence waiter before the exec queue is banned, causing the
+ufence waiter to miss the banned state.
+
+Suggested-by: Matthew Brost <matthew.brost@intel.com>
+Signed-off-by: Jonathan Cavitt <jonathan.cavitt@intel.com>
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Stuart Summers <stuart.summers@intel.com>
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240510194540.3246991-1-jonathan.cavitt@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_guc_submit.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
+index e4e3658e6a138..0f42971ff0a83 100644
+--- a/drivers/gpu/drm/xe/xe_guc_submit.c
++++ b/drivers/gpu/drm/xe/xe_guc_submit.c
+@@ -1429,8 +1429,8 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
+                           !xe_sched_job_completed(job)) ||
+                           xe_sched_invalidate_job(job, 2)) {
+                               trace_xe_sched_job_ban(job);
+-                              xe_sched_tdr_queue_imm(&q->guc->sched);
+                               set_exec_queue_banned(q);
++                              xe_sched_tdr_queue_imm(&q->guc->sched);
+                       }
+               }
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/ext4-fix-uninitialized-variable-in-ext4_inlinedir_to.patch b/queue-6.10/ext4-fix-uninitialized-variable-in-ext4_inlinedir_to.patch
new file mode 100644 (file)
index 0000000..84c33b2
--- /dev/null
@@ -0,0 +1,48 @@
+From 938069bddcc6d7de73703b002f19c47de12aa14b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Apr 2024 20:30:17 -0700
+Subject: ext4: fix uninitialized variable in ext4_inlinedir_to_tree
+
+From: Xiaxi Shen <shenxiaxi26@gmail.com>
+
+[ Upstream commit 8dc9c3da79c84b13fdb135e2fb0a149a8175bffe ]
+
+Syzbot has found an uninit-value bug in ext4_inlinedir_to_tree
+
+This error happens because ext4_inlinedir_to_tree does not
+handle the case when ext4fs_dirhash returns an error
+
+This can be avoided by checking the return value of ext4fs_dirhash
+and propagating the error,
+similar to how it's done with ext4_htree_store_dirent
+
+Signed-off-by: Xiaxi Shen <shenxiaxi26@gmail.com>
+Reported-and-tested-by: syzbot+eaba5abe296837a640c0@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=eaba5abe296837a640c0
+Link: https://patch.msgid.link/20240501033017.220000-1-shenxiaxi26@gmail.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inline.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index d5bd1e3a5d36c..e7a09a99837b9 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1410,7 +1410,11 @@ int ext4_inlinedir_to_tree(struct file *dir_file,
+                       hinfo->hash = EXT4_DIRENT_HASH(de);
+                       hinfo->minor_hash = EXT4_DIRENT_MINOR_HASH(de);
+               } else {
+-                      ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
++                      err = ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
++                      if (err) {
++                              ret = err;
++                              goto out;
++                      }
+               }
+               if ((hinfo->hash < start_hash) ||
+                   ((hinfo->hash == start_hash) &&
+-- 
+2.43.0
+
diff --git a/queue-6.10/ext4-sanity-check-for-null-pointer-after-ext4_force_.patch b/queue-6.10/ext4-sanity-check-for-null-pointer-after-ext4_force_.patch
new file mode 100644 (file)
index 0000000..06b30c4
--- /dev/null
@@ -0,0 +1,135 @@
+From 19bd2510608703f6f8c0ac7639edb98a16d3cf45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jul 2024 09:01:12 +0200
+Subject: ext4: sanity check for NULL pointer after ext4_force_shutdown
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Wojciech GÅ‚adysz <wojciech.gladysz@infogain.com>
+
+[ Upstream commit 83f4414b8f84249d538905825b088ff3ae555652 ]
+
+Test case: 2 threads write short inline data to a file.
+In ext4_page_mkwrite the resulting inline data is converted.
+Handling ext4_grp_locked_error with description "block bitmap
+and bg descriptor inconsistent: X vs Y free clusters" calls
+ext4_force_shutdown. The conversion clears
+EXT4_STATE_MAY_INLINE_DATA but fails for
+ext4_destroy_inline_data_nolock and ext4_mark_iloc_dirty due
+to ext4_forced_shutdown. The restoration of inline data fails
+for the same reason not setting EXT4_STATE_MAY_INLINE_DATA.
+Without the flag set a regular process path in ext4_da_write_end
+follows trying to dereference page folio private pointer that has
+not been set. The fix calls early return with -EIO error shall the
+pointer to private be NULL.
+
+Sample crash report:
+
+Unable to handle kernel paging request at virtual address dfff800000000004
+KASAN: null-ptr-deref in range [0x0000000000000020-0x0000000000000027]
+Mem abort info:
+  ESR = 0x0000000096000005
+  EC = 0x25: DABT (current EL), IL = 32 bits
+  SET = 0, FnV = 0
+  EA = 0, S1PTW = 0
+  FSC = 0x05: level 1 translation fault
+Data abort info:
+  ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
+  CM = 0, WnR = 0, TnD = 0, TagAccess = 0
+  GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+[dfff800000000004] address between user and kernel address ranges
+Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP
+Modules linked in:
+CPU: 1 PID: 20274 Comm: syz-executor185 Not tainted 6.9.0-rc7-syzkaller-gfda5695d692c #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024
+pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : __block_commit_write+0x64/0x2b0 fs/buffer.c:2167
+lr : __block_commit_write+0x3c/0x2b0 fs/buffer.c:2160
+sp : ffff8000a1957600
+x29: ffff8000a1957610 x28: dfff800000000000 x27: ffff0000e30e34b0
+x26: 0000000000000000 x25: dfff800000000000 x24: dfff800000000000
+x23: fffffdffc397c9e0 x22: 0000000000000020 x21: 0000000000000020
+x20: 0000000000000040 x19: fffffdffc397c9c0 x18: 1fffe000367bd196
+x17: ffff80008eead000 x16: ffff80008ae89e3c x15: 00000000200000c0
+x14: 1fffe0001cbe4e04 x13: 0000000000000000 x12: 0000000000000000
+x11: 0000000000000001 x10: 0000000000ff0100 x9 : 0000000000000000
+x8 : 0000000000000004 x7 : 0000000000000000 x6 : 0000000000000000
+x5 : fffffdffc397c9c0 x4 : 0000000000000020 x3 : 0000000000000020
+x2 : 0000000000000040 x1 : 0000000000000020 x0 : fffffdffc397c9c0
+Call trace:
+ __block_commit_write+0x64/0x2b0 fs/buffer.c:2167
+ block_write_end+0xb4/0x104 fs/buffer.c:2253
+ ext4_da_do_write_end fs/ext4/inode.c:2955 [inline]
+ ext4_da_write_end+0x2c4/0xa40 fs/ext4/inode.c:3028
+ generic_perform_write+0x394/0x588 mm/filemap.c:3985
+ ext4_buffered_write_iter+0x2c0/0x4ec fs/ext4/file.c:299
+ ext4_file_write_iter+0x188/0x1780
+ call_write_iter include/linux/fs.h:2110 [inline]
+ new_sync_write fs/read_write.c:497 [inline]
+ vfs_write+0x968/0xc3c fs/read_write.c:590
+ ksys_write+0x15c/0x26c fs/read_write.c:643
+ __do_sys_write fs/read_write.c:655 [inline]
+ __se_sys_write fs/read_write.c:652 [inline]
+ __arm64_sys_write+0x7c/0x90 fs/read_write.c:652
+ __invoke_syscall arch/arm64/kernel/syscall.c:34 [inline]
+ invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:48
+ el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:133
+ do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:152
+ el0_svc+0x54/0x168 arch/arm64/kernel/entry-common.c:712
+ el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730
+ el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598
+Code: 97f85911 f94002da 91008356 d343fec8 (38796908)
+---[ end trace 0000000000000000 ]---
+----------------
+Code disassembly (best guess):
+   0:  97f85911        bl      0xffffffffffe16444
+   4:  f94002da        ldr     x26, [x22]
+   8:  91008356        add     x22, x26, #0x20
+   c:  d343fec8        lsr     x8, x22, #3
+* 10:  38796908        ldrb    w8, [x8, x25] <-- trapping instruction
+
+Reported-by: syzbot+18df508cf00a0598d9a6@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=18df508cf00a0598d9a6
+Link: https://lore.kernel.org/all/000000000000f19a1406109eb5c5@google.com/T/
+Signed-off-by: Wojciech GÅ‚adysz <wojciech.gladysz@infogain.com>
+Link: https://patch.msgid.link/20240703070112.10235-1-wojciech.gladysz@infogain.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/buffer.c     | 2 ++
+ fs/ext4/inode.c | 5 +++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index 8c19e705b9c33..645f0387dfe1d 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -2187,6 +2187,8 @@ static void __block_commit_write(struct folio *folio, size_t from, size_t to)
+       struct buffer_head *bh, *head;
+       bh = head = folio_buffers(folio);
++      if (!bh)
++              return;
+       blocksize = bh->b_size;
+       block_start = 0;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 4b0d64a76e88e..238e196338234 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2973,6 +2973,11 @@ static int ext4_da_do_write_end(struct address_space *mapping,
+       bool disksize_changed = false;
+       loff_t new_i_size;
++      if (unlikely(!folio_buffers(folio))) {
++              folio_unlock(folio);
++              folio_put(folio);
++              return -EIO;
++      }
+       /*
+        * block_write_end() will mark the inode as dirty with I_DIRTY_PAGES
+        * flag, which all that's needed to trigger page writeback.
+-- 
+2.43.0
+
diff --git a/queue-6.10/gpio-prevent-potential-speculation-leaks-in-gpio_dev.patch b/queue-6.10/gpio-prevent-potential-speculation-leaks-in-gpio_dev.patch
new file mode 100644 (file)
index 0000000..e99090d
--- /dev/null
@@ -0,0 +1,54 @@
+From 326813cd370e4a615d144750cc76857c60105b7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 May 2024 08:53:32 +0000
+Subject: gpio: prevent potential speculation leaks in gpio_device_get_desc()
+
+From: Hagar Hemdan <hagarhem@amazon.com>
+
+[ Upstream commit d795848ecce24a75dfd46481aee066ae6fe39775 ]
+
+Userspace may trigger a speculative read of an address outside the gpio
+descriptor array.
+Users can do that by calling gpio_ioctl() with an offset out of range.
+Offset is copied from user and then used as an array index to get
+the gpio descriptor without sanitization in gpio_device_get_desc().
+
+This change ensures that the offset is sanitized by using
+array_index_nospec() to mitigate any possibility of speculative
+information leaks.
+
+This bug was discovered and resolved using Coverity Static Analysis
+Security Testing (SAST) by Synopsys, Inc.
+
+Signed-off-by: Hagar Hemdan <hagarhem@amazon.com>
+Link: https://lore.kernel.org/r/20240523085332.1801-1-hagarhem@amazon.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpiolib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index fa62367ee9290..1a9aadd4c803c 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -17,6 +17,7 @@
+ #include <linux/list.h>
+ #include <linux/lockdep.h>
+ #include <linux/module.h>
++#include <linux/nospec.h>
+ #include <linux/of.h>
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/seq_file.h>
+@@ -198,7 +199,7 @@ gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum)
+       if (hwnum >= gdev->ngpio)
+               return ERR_PTR(-EINVAL);
+-      return &gdev->descs[hwnum];
++      return &gdev->descs[array_index_nospec(hwnum, gdev->ngpio)];
+ }
+ EXPORT_SYMBOL_GPL(gpio_device_get_desc);
+-- 
+2.43.0
+
diff --git a/queue-6.10/gve-fix-use-of-netif_carrier_ok.patch b/queue-6.10/gve-fix-use-of-netif_carrier_ok.patch
new file mode 100644 (file)
index 0000000..0ca5c20
--- /dev/null
@@ -0,0 +1,105 @@
+From 280dfdbc195fd9e86fdd021104ef7fce411313d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 13:56:19 -0700
+Subject: gve: Fix use of netif_carrier_ok()
+
+From: Praveen Kaligineedi <pkaligineedi@google.com>
+
+[ Upstream commit fba917b169bea5f8f2ee300e19d5f7a6341a5251 ]
+
+GVE driver wrongly relies on netif_carrier_ok() to check the
+interface administrative state when resources are being
+allocated/deallocated for queue(s). netif_carrier_ok() needs
+to be replaced with netif_running() for all such cases.
+
+Administrative state is the result of "ip link set dev <dev>
+up/down". It reflects whether the administrator wants to use
+the device for traffic and the corresponding resources have
+been allocated.
+
+Fixes: 5f08cd3d6423 ("gve: Alloc before freeing when adjusting queues")
+Signed-off-by: Praveen Kaligineedi <pkaligineedi@google.com>
+Reviewed-by: Shailend Chand <shailend@google.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20240801205619.987396-1-pkaligineedi@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/google/gve/gve_ethtool.c |  2 +-
+ drivers/net/ethernet/google/gve/gve_main.c    | 12 ++++++------
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
+index fe1741d482b4a..cf816ede05f69 100644
+--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
++++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
+@@ -492,7 +492,7 @@ static int gve_set_channels(struct net_device *netdev,
+               return -EINVAL;
+       }
+-      if (!netif_carrier_ok(netdev)) {
++      if (!netif_running(netdev)) {
+               priv->tx_cfg.num_queues = new_tx;
+               priv->rx_cfg.num_queues = new_rx;
+               return 0;
+diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
+index cabf7d4bcecb8..8b14efd14a505 100644
+--- a/drivers/net/ethernet/google/gve/gve_main.c
++++ b/drivers/net/ethernet/google/gve/gve_main.c
+@@ -1511,7 +1511,7 @@ static int gve_set_xdp(struct gve_priv *priv, struct bpf_prog *prog,
+       u32 status;
+       old_prog = READ_ONCE(priv->xdp_prog);
+-      if (!netif_carrier_ok(priv->dev)) {
++      if (!netif_running(priv->dev)) {
+               WRITE_ONCE(priv->xdp_prog, prog);
+               if (old_prog)
+                       bpf_prog_put(old_prog);
+@@ -1784,7 +1784,7 @@ int gve_adjust_queues(struct gve_priv *priv,
+       rx_alloc_cfg.qcfg = &new_rx_config;
+       tx_alloc_cfg.num_rings = new_tx_config.num_queues;
+-      if (netif_carrier_ok(priv->dev)) {
++      if (netif_running(priv->dev)) {
+               err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
+               return err;
+       }
+@@ -2001,7 +2001,7 @@ static int gve_set_features(struct net_device *netdev,
+       if ((netdev->features & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
+               netdev->features ^= NETIF_F_LRO;
+-              if (netif_carrier_ok(netdev)) {
++              if (netif_running(netdev)) {
+                       err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
+                       if (err) {
+                               /* Revert the change on error. */
+@@ -2290,7 +2290,7 @@ static int gve_reset_recovery(struct gve_priv *priv, bool was_up)
+ int gve_reset(struct gve_priv *priv, bool attempt_teardown)
+ {
+-      bool was_up = netif_carrier_ok(priv->dev);
++      bool was_up = netif_running(priv->dev);
+       int err;
+       dev_info(&priv->pdev->dev, "Performing reset\n");
+@@ -2631,7 +2631,7 @@ static void gve_shutdown(struct pci_dev *pdev)
+ {
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct gve_priv *priv = netdev_priv(netdev);
+-      bool was_up = netif_carrier_ok(priv->dev);
++      bool was_up = netif_running(priv->dev);
+       rtnl_lock();
+       if (was_up && gve_close(priv->dev)) {
+@@ -2649,7 +2649,7 @@ static int gve_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct gve_priv *priv = netdev_priv(netdev);
+-      bool was_up = netif_carrier_ok(priv->dev);
++      bool was_up = netif_running(priv->dev);
+       priv->suspend_cnt++;
+       rtnl_lock();
+-- 
+2.43.0
+
diff --git a/queue-6.10/hwmon-corsair-psu-add-usb-id-of-hx1200i-series-2023-.patch b/queue-6.10/hwmon-corsair-psu-add-usb-id-of-hx1200i-series-2023-.patch
new file mode 100644 (file)
index 0000000..cae51a7
--- /dev/null
@@ -0,0 +1,69 @@
+From 6193b8c2c40664cb3fba9b9e6a35f8ed53e6bead Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 May 2024 04:38:11 +0000
+Subject: hwmon: corsair-psu: add USB id of HX1200i Series 2023 psu
+
+From: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+
+[ Upstream commit b9c15c96ccb47ad860af2e075c5f3c90c4cd1730 ]
+
+Add the usb id of the HX1200i Series 2023. Update the documentation
+accordingly. Also fix the version comments, there are no Series 2022
+products. That are legacy or first version products going back many
+many years.
+
+Signed-off-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+Link: https://lore.kernel.org/r/ZlAZs4u0dU7JxtDf@monster.localdomain
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/corsair-psu.rst | 6 +++---
+ drivers/hwmon/corsair-psu.c         | 7 ++++---
+ 2 files changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/Documentation/hwmon/corsair-psu.rst b/Documentation/hwmon/corsair-psu.rst
+index 16db34d464dd6..7ed794087f848 100644
+--- a/Documentation/hwmon/corsair-psu.rst
++++ b/Documentation/hwmon/corsair-psu.rst
+@@ -15,11 +15,11 @@ Supported devices:
+   Corsair HX850i
+-  Corsair HX1000i (Series 2022 and 2023)
++  Corsair HX1000i (Legacy and Series 2023)
+-  Corsair HX1200i
++  Corsair HX1200i (Legacy and Series 2023)
+-  Corsair HX1500i (Series 2022 and 2023)
++  Corsair HX1500i (Legacy and Series 2023)
+   Corsair RM550i
+diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
+index 2c7c92272fe39..f8f22b8a67cdf 100644
+--- a/drivers/hwmon/corsair-psu.c
++++ b/drivers/hwmon/corsair-psu.c
+@@ -875,15 +875,16 @@ static const struct hid_device_id corsairpsu_idtable[] = {
+       { HID_USB_DEVICE(0x1b1c, 0x1c04) }, /* Corsair HX650i */
+       { HID_USB_DEVICE(0x1b1c, 0x1c05) }, /* Corsair HX750i */
+       { HID_USB_DEVICE(0x1b1c, 0x1c06) }, /* Corsair HX850i */
+-      { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Series 2022 */
+-      { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i */
++      { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Legacy */
++      { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i Legacy */
+       { HID_USB_DEVICE(0x1b1c, 0x1c09) }, /* Corsair RM550i */
+       { HID_USB_DEVICE(0x1b1c, 0x1c0a) }, /* Corsair RM650i */
+       { HID_USB_DEVICE(0x1b1c, 0x1c0b) }, /* Corsair RM750i */
+       { HID_USB_DEVICE(0x1b1c, 0x1c0c) }, /* Corsair RM850i */
+       { HID_USB_DEVICE(0x1b1c, 0x1c0d) }, /* Corsair RM1000i */
+       { HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i Series 2023 */
+-      { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Series 2022 and 2023 */
++      { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Legacy and Series 2023 */
++      { HID_USB_DEVICE(0x1b1c, 0x1c23) }, /* Corsair HX1200i Series 2023 */
+       { },
+ };
+ MODULE_DEVICE_TABLE(hid, corsairpsu_idtable);
+-- 
+2.43.0
+
diff --git a/queue-6.10/ice-fix-reset-handler.patch b/queue-6.10/ice-fix-reset-handler.patch
new file mode 100644 (file)
index 0000000..73decf8
--- /dev/null
@@ -0,0 +1,39 @@
+From 9f00e4f8b752d687416d233e2a16915ac6c6c2e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jul 2024 17:39:10 +0200
+Subject: ice: Fix reset handler
+
+From: Grzegorz Nitka <grzegorz.nitka@intel.com>
+
+[ Upstream commit 25a7123579ecac9a89a7e5b8d8a580bee4b68acd ]
+
+Synchronize OICR IRQ when preparing for reset to avoid potential
+race conditions between the reset procedure and OICR
+
+Fixes: 4aad5335969f ("ice: add individual interrupt allocation")
+Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
+Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_main.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
+index 9b075dd48889e..f16d13e9ff6e3 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -560,6 +560,8 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
+       if (test_bit(ICE_PREPARED_FOR_RESET, pf->state))
+               return;
++      synchronize_irq(pf->oicr_irq.virq);
++
+       ice_unplug_aux_dev(pf);
+       /* Notify VFs of impending reset */
+-- 
+2.43.0
+
diff --git a/queue-6.10/idpf-fix-memory-leaks-and-crashes-while-performing-a.patch b/queue-6.10/idpf-fix-memory-leaks-and-crashes-while-performing-a.patch
new file mode 100644 (file)
index 0000000..eb3194a
--- /dev/null
@@ -0,0 +1,134 @@
+From 48d1b9ca863052b0adc33c883a25f95c6bf51f26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 15:09:20 -0700
+Subject: idpf: fix memory leaks and crashes while performing a soft reset
+
+From: Alexander Lobakin <aleksander.lobakin@intel.com>
+
+[ Upstream commit f01032a2ca099ec8d619aaa916c3762aa62495df ]
+
+The second tagged commit introduced a UAF, as it removed restoring
+q_vector->vport pointers after reinitializating the structures.
+This is due to that all queue allocation functions are performed here
+with the new temporary vport structure and those functions rewrite
+the backpointers to the vport. Then, this new struct is freed and
+the pointers start leading to nowhere.
+
+But generally speaking, the current logic is very fragile. It claims
+to be more reliable when the system is low on memory, but in fact, it
+consumes two times more memory as at the moment of running this
+function, there are two vports allocated with their queues and vectors.
+Moreover, it claims to prevent the driver from running into "bad state",
+but in fact, any error during the rebuild leaves the old vport in the
+partially allocated state.
+Finally, if the interface is down when the function is called, it always
+allocates a new queue set, but when the user decides to enable the
+interface later on, vport_open() allocates them once again, IOW there's
+a clear memory leak here.
+
+Just don't allocate a new queue set when performing a reset, that solves
+crashes and memory leaks. Readd the old queue number and reopen the
+interface on rollback - that solves limbo states when the device is left
+disabled and/or without HW queues enabled.
+
+Fixes: 02cbfba1add5 ("idpf: add ethtool callbacks")
+Fixes: e4891e4687c8 ("idpf: split &idpf_queue into 4 strictly-typed queue structures")
+Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Krishneil Singh <krishneil.k.singh@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Link: https://patch.msgid.link/20240806220923.3359860-2-anthony.l.nguyen@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/idpf/idpf_lib.c | 30 +++++++++++-----------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
+index f1ee5584e8fa2..32b6f0d52e3c5 100644
+--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
++++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
+@@ -1337,9 +1337,8 @@ static void idpf_rx_init_buf_tail(struct idpf_vport *vport)
+ /**
+  * idpf_vport_open - Bring up a vport
+  * @vport: vport to bring up
+- * @alloc_res: allocate queue resources
+  */
+-static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res)
++static int idpf_vport_open(struct idpf_vport *vport)
+ {
+       struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
+       struct idpf_adapter *adapter = vport->adapter;
+@@ -1352,11 +1351,9 @@ static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res)
+       /* we do not allow interface up just yet */
+       netif_carrier_off(vport->netdev);
+-      if (alloc_res) {
+-              err = idpf_vport_queues_alloc(vport);
+-              if (err)
+-                      return err;
+-      }
++      err = idpf_vport_queues_alloc(vport);
++      if (err)
++              return err;
+       err = idpf_vport_intr_alloc(vport);
+       if (err) {
+@@ -1541,7 +1538,7 @@ void idpf_init_task(struct work_struct *work)
+       np = netdev_priv(vport->netdev);
+       np->state = __IDPF_VPORT_DOWN;
+       if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags))
+-              idpf_vport_open(vport, true);
++              idpf_vport_open(vport);
+       /* Spawn and return 'idpf_init_task' work queue until all the
+        * default vports are created
+@@ -1900,9 +1897,6 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
+               goto free_vport;
+       }
+-      err = idpf_vport_queues_alloc(new_vport);
+-      if (err)
+-              goto free_vport;
+       if (current_state <= __IDPF_VPORT_DOWN) {
+               idpf_send_delete_queues_msg(vport);
+       } else {
+@@ -1974,17 +1968,23 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
+       err = idpf_set_real_num_queues(vport);
+       if (err)
+-              goto err_reset;
++              goto err_open;
+       if (current_state == __IDPF_VPORT_UP)
+-              err = idpf_vport_open(vport, false);
++              err = idpf_vport_open(vport);
+       kfree(new_vport);
+       return err;
+ err_reset:
+-      idpf_vport_queues_rel(new_vport);
++      idpf_send_add_queues_msg(vport, vport->num_txq, vport->num_complq,
++                               vport->num_rxq, vport->num_bufq);
++
++err_open:
++      if (current_state == __IDPF_VPORT_UP)
++              idpf_vport_open(vport);
++
+ free_vport:
+       kfree(new_vport);
+@@ -2213,7 +2213,7 @@ static int idpf_open(struct net_device *netdev)
+       idpf_vport_ctrl_lock(netdev);
+       vport = idpf_netdev_to_vport(netdev);
+-      err = idpf_vport_open(vport, true);
++      err = idpf_vport_open(vport);
+       idpf_vport_ctrl_unlock(netdev);
+-- 
+2.43.0
+
diff --git a/queue-6.10/idpf-fix-uafs-when-destroying-the-queues.patch b/queue-6.10/idpf-fix-uafs-when-destroying-the-queues.patch
new file mode 100644 (file)
index 0000000..e2888ea
--- /dev/null
@@ -0,0 +1,167 @@
+From 1af8bab4a3f2749b1597ae7f8ef4daaac1130494 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 15:09:22 -0700
+Subject: idpf: fix UAFs when destroying the queues
+
+From: Alexander Lobakin <aleksander.lobakin@intel.com>
+
+[ Upstream commit 290f1c033281c1a502a3cd1c53c3a549259c491f ]
+
+The second tagged commit started sometimes (very rarely, but possible)
+throwing WARNs from
+net/core/page_pool.c:page_pool_disable_direct_recycling().
+Turned out idpf frees interrupt vectors with embedded NAPIs *before*
+freeing the queues making page_pools' NAPI pointers lead to freed
+memory before these pools are destroyed by libeth.
+It's not clear whether there are other accesses to the freed vectors
+when destroying the queues, but anyway, we usually free queue/interrupt
+vectors only when the queues are destroyed and the NAPIs are guaranteed
+to not be referenced anywhere.
+
+Invert the allocation and freeing logic making queue/interrupt vectors
+be allocated first and freed last. Vectors don't require queues to be
+present, so this is safe. Additionally, this change allows to remove
+that useless queue->q_vector pointer cleanup, as vectors are still
+valid when freeing the queues (+ both are freed within one function,
+so it's not clear why nullify the pointers at all).
+
+Fixes: 1c325aac10a8 ("idpf: configure resources for TX queues")
+Fixes: 90912f9f4f2d ("idpf: convert header split mode to libeth + napi_build_skb()")
+Reported-by: Michal Kubiak <michal.kubiak@intel.com>
+Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Krishneil Singh <krishneil.k.singh@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Link: https://patch.msgid.link/20240806220923.3359860-4-anthony.l.nguyen@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/idpf/idpf_lib.c  | 24 ++++++++++-----------
+ drivers/net/ethernet/intel/idpf/idpf_txrx.c | 24 +--------------------
+ 2 files changed, 13 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
+index 32b6f0d52e3c5..3ac9d7ab83f20 100644
+--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
++++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
+@@ -905,8 +905,8 @@ static void idpf_vport_stop(struct idpf_vport *vport)
+       vport->link_up = false;
+       idpf_vport_intr_deinit(vport);
+-      idpf_vport_intr_rel(vport);
+       idpf_vport_queues_rel(vport);
++      idpf_vport_intr_rel(vport);
+       np->state = __IDPF_VPORT_DOWN;
+ }
+@@ -1351,43 +1351,43 @@ static int idpf_vport_open(struct idpf_vport *vport)
+       /* we do not allow interface up just yet */
+       netif_carrier_off(vport->netdev);
+-      err = idpf_vport_queues_alloc(vport);
+-      if (err)
+-              return err;
+-
+       err = idpf_vport_intr_alloc(vport);
+       if (err) {
+               dev_err(&adapter->pdev->dev, "Failed to allocate interrupts for vport %u: %d\n",
+                       vport->vport_id, err);
+-              goto queues_rel;
++              return err;
+       }
++      err = idpf_vport_queues_alloc(vport);
++      if (err)
++              goto intr_rel;
++
+       err = idpf_vport_queue_ids_init(vport);
+       if (err) {
+               dev_err(&adapter->pdev->dev, "Failed to initialize queue ids for vport %u: %d\n",
+                       vport->vport_id, err);
+-              goto intr_rel;
++              goto queues_rel;
+       }
+       err = idpf_vport_intr_init(vport);
+       if (err) {
+               dev_err(&adapter->pdev->dev, "Failed to initialize interrupts for vport %u: %d\n",
+                       vport->vport_id, err);
+-              goto intr_rel;
++              goto queues_rel;
+       }
+       err = idpf_rx_bufs_init_all(vport);
+       if (err) {
+               dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n",
+                       vport->vport_id, err);
+-              goto intr_rel;
++              goto queues_rel;
+       }
+       err = idpf_queue_reg_init(vport);
+       if (err) {
+               dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n",
+                       vport->vport_id, err);
+-              goto intr_rel;
++              goto queues_rel;
+       }
+       idpf_rx_init_buf_tail(vport);
+@@ -1454,10 +1454,10 @@ static int idpf_vport_open(struct idpf_vport *vport)
+       idpf_send_map_unmap_queue_vector_msg(vport, false);
+ intr_deinit:
+       idpf_vport_intr_deinit(vport);
+-intr_rel:
+-      idpf_vport_intr_rel(vport);
+ queues_rel:
+       idpf_vport_queues_rel(vport);
++intr_rel:
++      idpf_vport_intr_rel(vport);
+       return err;
+ }
+diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+index b023704bbbdab..0c22e524e56db 100644
+--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+@@ -3436,9 +3436,7 @@ static void idpf_vport_intr_napi_dis_all(struct idpf_vport *vport)
+  */
+ void idpf_vport_intr_rel(struct idpf_vport *vport)
+ {
+-      int i, j, v_idx;
+-
+-      for (v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) {
++      for (u32 v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) {
+               struct idpf_q_vector *q_vector = &vport->q_vectors[v_idx];
+               kfree(q_vector->bufq);
+@@ -3449,26 +3447,6 @@ void idpf_vport_intr_rel(struct idpf_vport *vport)
+               q_vector->rx = NULL;
+       }
+-      /* Clean up the mapping of queues to vectors */
+-      for (i = 0; i < vport->num_rxq_grp; i++) {
+-              struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];
+-
+-              if (idpf_is_queue_model_split(vport->rxq_model))
+-                      for (j = 0; j < rx_qgrp->splitq.num_rxq_sets; j++)
+-                              rx_qgrp->splitq.rxq_sets[j]->rxq.q_vector = NULL;
+-              else
+-                      for (j = 0; j < rx_qgrp->singleq.num_rxq; j++)
+-                              rx_qgrp->singleq.rxqs[j]->q_vector = NULL;
+-      }
+-
+-      if (idpf_is_queue_model_split(vport->txq_model))
+-              for (i = 0; i < vport->num_txq_grp; i++)
+-                      vport->txq_grps[i].complq->q_vector = NULL;
+-      else
+-              for (i = 0; i < vport->num_txq_grp; i++)
+-                      for (j = 0; j < vport->txq_grps[i].num_txq; j++)
+-                              vport->txq_grps[i].txqs[j]->q_vector = NULL;
+-
+       kfree(vport->q_vectors);
+       vport->q_vectors = NULL;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/irqchip-gic-v3-don-t-return-errors-from-gic_acpi_mat.patch b/queue-6.10/irqchip-gic-v3-don-t-return-errors-from-gic_acpi_mat.patch
new file mode 100644 (file)
index 0000000..ab36f54
--- /dev/null
@@ -0,0 +1,72 @@
+From cb6803bff3500e0963d27f0ba8b9808ceb7f47bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 May 2024 14:34:40 +0100
+Subject: irqchip/gic-v3: Don't return errors from gic_acpi_match_gicc()
+
+From: James Morse <james.morse@arm.com>
+
+[ Upstream commit fa2dabe57220e6af78ed7a2f7016bf250a618204 ]
+
+gic_acpi_match_gicc() is only called via gic_acpi_count_gicr_regions().
+It should only count the number of enabled redistributors, but it
+also tries to sanity check the GICC entry, currently returning an
+error if the Enabled bit is set, but the gicr_base_address is zero.
+
+Adding support for the online-capable bit to the sanity check will
+complicate it, for no benefit. The existing check implicitly depends on
+gic_acpi_count_gicr_regions() previous failing to find any GICR regions
+(as it is valid to have gicr_base_address of zero if the redistributors
+are described via a GICR entry).
+
+Instead of complicating the check, remove it. Failures that happen at
+this point cause the irqchip not to register, meaning no irqs can be
+requested. The kernel grinds to a panic() pretty quickly.
+
+Without the check, MADT tables that exhibit this problem are still
+caught by gic_populate_rdist(), which helpfully also prints what went
+wrong:
+| CPU4: mpidr 100 has no re-distributor!
+
+Signed-off-by: James Morse <james.morse@arm.com>
+Reviewed-by: Gavin Shan <gshan@redhat.com>
+Tested-by: Miguel Luis <miguel.luis@oracle.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20240529133446.28446-14-Jonathan.Cameron@huawei.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-gic-v3.c | 13 ++-----------
+ 1 file changed, 2 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
+index 6fb276504bcc8..10af15f93d4d4 100644
+--- a/drivers/irqchip/irq-gic-v3.c
++++ b/drivers/irqchip/irq-gic-v3.c
+@@ -2415,19 +2415,10 @@ static int __init gic_acpi_match_gicc(union acpi_subtable_headers *header,
+        * If GICC is enabled and has valid gicr base address, then it means
+        * GICR base is presented via GICC
+        */
+-      if (acpi_gicc_is_usable(gicc) && gicc->gicr_base_address) {
++      if (acpi_gicc_is_usable(gicc) && gicc->gicr_base_address)
+               acpi_data.enabled_rdists++;
+-              return 0;
+-      }
+-      /*
+-       * It's perfectly valid firmware can pass disabled GICC entry, driver
+-       * should not treat as errors, skip the entry instead of probe fail.
+-       */
+-      if (!acpi_gicc_is_usable(gicc))
+-              return 0;
+-
+-      return -ENODEV;
++      return 0;
+ }
+ static int __init gic_acpi_count_gicr_regions(void)
+-- 
+2.43.0
+
diff --git a/queue-6.10/irqchip-mbigen-fix-mbigen-node-address-layout.patch b/queue-6.10/irqchip-mbigen-fix-mbigen-node-address-layout.patch
new file mode 100644 (file)
index 0000000..ac7957a
--- /dev/null
@@ -0,0 +1,89 @@
+From 5f106f43bb5fce672ba9267df68be411bd460179 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 09:44:00 +0800
+Subject: irqchip/mbigen: Fix mbigen node address layout
+
+From: Yipeng Zou <zouyipeng@huawei.com>
+
+[ Upstream commit 6be6cba9c4371d27f78d900ccfe34bb880d9ee20 ]
+
+The mbigen interrupt chip has its per node registers located in a
+contiguous region of page sized chunks. The code maps them into virtual
+address space as a contiguous region and determines the address of a node
+by using the node ID as index.
+
+                    mbigen chip
+       |-----------------|------------|--------------|
+   mgn_node_0         mgn_node_1     ...         mgn_node_i
+|--------------|   |--------------|       |----------------------|
+[0x0000, 0x0x0FFF] [0x1000, 0x1FFF]    [i*0x1000, (i+1)*0x1000 - 1]
+
+This works correctly up to 10 nodes, but then fails because the 11th's
+array slot is used for the MGN_CLEAR registers.
+
+                         mbigen chip
+    |-----------|--------|--------|---------------|--------|
+mgn_node_0  mgn_node_1  ...  mgn_clear_register  ...   mgn_node_i
+                            |-----------------|
+                             [0xA000, 0xAFFF]
+
+Skip the MGN_CLEAR register space when calculating the offset for node IDs
+greater than or equal to ten.
+
+Fixes: a6c2f87b8820 ("irqchip/mbigen: Implement the mbigen irq chip operation functions")
+Signed-off-by: Yipeng Zou <zouyipeng@huawei.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/all/20240730014400.1751530-1-zouyipeng@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-mbigen.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
+index 58881d3139792..244a8d489cac6 100644
+--- a/drivers/irqchip/irq-mbigen.c
++++ b/drivers/irqchip/irq-mbigen.c
+@@ -64,6 +64,20 @@ struct mbigen_device {
+       void __iomem            *base;
+ };
++static inline unsigned int get_mbigen_node_offset(unsigned int nid)
++{
++      unsigned int offset = nid * MBIGEN_NODE_OFFSET;
++
++      /*
++       * To avoid touched clear register in unexpected way, we need to directly
++       * skip clear register when access to more than 10 mbigen nodes.
++       */
++      if (nid >= (REG_MBIGEN_CLEAR_OFFSET / MBIGEN_NODE_OFFSET))
++              offset += MBIGEN_NODE_OFFSET;
++
++      return offset;
++}
++
+ static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
+ {
+       unsigned int nid, pin;
+@@ -72,8 +86,7 @@ static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
+       nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
+       pin = hwirq % IRQS_PER_MBIGEN_NODE;
+-      return pin * 4 + nid * MBIGEN_NODE_OFFSET
+-                      + REG_MBIGEN_VEC_OFFSET;
++      return pin * 4 + get_mbigen_node_offset(nid) + REG_MBIGEN_VEC_OFFSET;
+ }
+ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
+@@ -88,8 +101,7 @@ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
+       *mask = 1 << (irq_ofst % 32);
+       ofst = irq_ofst / 32 * 4;
+-      *addr = ofst + nid * MBIGEN_NODE_OFFSET
+-              + REG_MBIGEN_TYPE_OFFSET;
++      *addr = ofst + get_mbigen_node_offset(nid) + REG_MBIGEN_TYPE_OFFSET;
+ }
+ static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
+-- 
+2.43.0
+
diff --git a/queue-6.10/jbd2-avoid-memleak-in-jbd2_journal_write_metadata_bu.patch b/queue-6.10/jbd2-avoid-memleak-in-jbd2_journal_write_metadata_bu.patch
new file mode 100644 (file)
index 0000000..ac01638
--- /dev/null
@@ -0,0 +1,37 @@
+From 2a7f4000bc674db6d88b0dcc7ef33f06f3dabda5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 May 2024 19:24:30 +0800
+Subject: jbd2: avoid memleak in jbd2_journal_write_metadata_buffer
+
+From: Kemeng Shi <shikemeng@huaweicloud.com>
+
+[ Upstream commit cc102aa24638b90e04364d64e4f58a1fa91a1976 ]
+
+The new_bh is from alloc_buffer_head, we should call free_buffer_head to
+free it in error case.
+
+Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
+Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240514112438.1269037-2-shikemeng@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jbd2/journal.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index ae5b544ed0cc0..c8d9d85e0e871 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -399,6 +399,7 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
+               tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS);
+               if (!tmp) {
+                       brelse(new_bh);
++                      free_buffer_head(new_bh);
+                       return -ENOMEM;
+               }
+               spin_lock(&jh_in->b_state_lock);
+-- 
+2.43.0
+
diff --git a/queue-6.10/jump_label-fix-the-fix-brown-paper-bags-galore.patch b/queue-6.10/jump_label-fix-the-fix-brown-paper-bags-galore.patch
new file mode 100644 (file)
index 0000000..5e8b985
--- /dev/null
@@ -0,0 +1,62 @@
+From 5f26cebd62e22fd6022ca20f0ac44ecad8b381cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 12:43:21 +0200
+Subject: jump_label: Fix the fix, brown paper bags galore
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 224fa3552029a3d14bec7acf72ded8171d551b88 ]
+
+Per the example of:
+
+  !atomic_cmpxchg(&key->enabled, 0, 1)
+
+the inverse was written as:
+
+  atomic_cmpxchg(&key->enabled, 1, 0)
+
+except of course, that while !old is only true for old == 0, old is
+true for everything except old == 0.
+
+Fix it to read:
+
+  atomic_cmpxchg(&key->enabled, 1, 0) == 1
+
+such that only the 1->0 transition returns true and goes on to disable
+the keys.
+
+Fixes: 83ab38ef0a0b ("jump_label: Fix concurrency issues in static_key_slow_dec()")
+Reported-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Tested-by: Darrick J. Wong <djwong@kernel.org>
+Link: https://lkml.kernel.org/r/20240731105557.GY33588@noisy.programming.kicks-ass.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/jump_label.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/jump_label.c b/kernel/jump_label.c
+index 1f05a19918f47..c6ac0d0377d72 100644
+--- a/kernel/jump_label.c
++++ b/kernel/jump_label.c
+@@ -231,7 +231,7 @@ void static_key_disable_cpuslocked(struct static_key *key)
+       }
+       jump_label_lock();
+-      if (atomic_cmpxchg(&key->enabled, 1, 0))
++      if (atomic_cmpxchg(&key->enabled, 1, 0) == 1)
+               jump_label_update(key);
+       jump_label_unlock();
+ }
+@@ -284,7 +284,7 @@ static void __static_key_slow_dec_cpuslocked(struct static_key *key)
+               return;
+       guard(mutex)(&jump_label_mutex);
+-      if (atomic_cmpxchg(&key->enabled, 1, 0))
++      if (atomic_cmpxchg(&key->enabled, 1, 0) == 1)
+               jump_label_update(key);
+       else
+               WARN_ON_ONCE(!static_key_slow_try_dec(key));
+-- 
+2.43.0
+
diff --git a/queue-6.10/l2tp-fix-lockdep-splat.patch b/queue-6.10/l2tp-fix-lockdep-splat.patch
new file mode 100644 (file)
index 0000000..a2f5941
--- /dev/null
@@ -0,0 +1,216 @@
+From eb851d4bba57158911fe10573dbd59bd358f7fed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 17:06:26 +0100
+Subject: l2tp: fix lockdep splat
+
+From: James Chapman <jchapman@katalix.com>
+
+[ Upstream commit 86a41ea9fd79ddb6145cb8ebf5aeafceabca6f7d ]
+
+When l2tp tunnels use a socket provided by userspace, we can hit
+lockdep splats like the below when data is transmitted through another
+(unrelated) userspace socket which then gets routed over l2tp.
+
+This issue was previously discussed here:
+https://lore.kernel.org/netdev/87sfialu2n.fsf@cloudflare.com/
+
+The solution is to have lockdep treat socket locks of l2tp tunnel
+sockets separately than those of standard INET sockets. To do so, use
+a different lockdep subclass where lock nesting is possible.
+
+  ============================================
+  WARNING: possible recursive locking detected
+  6.10.0+ #34 Not tainted
+  --------------------------------------------
+  iperf3/771 is trying to acquire lock:
+  ffff8881027601d8 (slock-AF_INET/1){+.-.}-{2:2}, at: l2tp_xmit_skb+0x243/0x9d0
+
+  but task is already holding lock:
+  ffff888102650d98 (slock-AF_INET/1){+.-.}-{2:2}, at: tcp_v4_rcv+0x1848/0x1e10
+
+  other info that might help us debug this:
+   Possible unsafe locking scenario:
+
+         CPU0
+         ----
+    lock(slock-AF_INET/1);
+    lock(slock-AF_INET/1);
+
+   *** DEADLOCK ***
+
+   May be due to missing lock nesting notation
+
+  10 locks held by iperf3/771:
+   #0: ffff888102650258 (sk_lock-AF_INET){+.+.}-{0:0}, at: tcp_sendmsg+0x1a/0x40
+   #1: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: __ip_queue_xmit+0x4b/0xbc0
+   #2: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: ip_finish_output2+0x17a/0x1130
+   #3: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: process_backlog+0x28b/0x9f0
+   #4: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: ip_local_deliver_finish+0xf9/0x260
+   #5: ffff888102650d98 (slock-AF_INET/1){+.-.}-{2:2}, at: tcp_v4_rcv+0x1848/0x1e10
+   #6: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: __ip_queue_xmit+0x4b/0xbc0
+   #7: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: ip_finish_output2+0x17a/0x1130
+   #8: ffffffff822ac1e0 (rcu_read_lock_bh){....}-{1:2}, at: __dev_queue_xmit+0xcc/0x1450
+   #9: ffff888101f33258 (dev->qdisc_tx_busylock ?: &qdisc_tx_busylock#2){+...}-{2:2}, at: __dev_queue_xmit+0x513/0x1450
+
+  stack backtrace:
+  CPU: 2 UID: 0 PID: 771 Comm: iperf3 Not tainted 6.10.0+ #34
+  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+  Call Trace:
+   <IRQ>
+   dump_stack_lvl+0x69/0xa0
+   dump_stack+0xc/0x20
+   __lock_acquire+0x135d/0x2600
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   lock_acquire+0xc4/0x2a0
+   ? l2tp_xmit_skb+0x243/0x9d0
+   ? __skb_checksum+0xa3/0x540
+   _raw_spin_lock_nested+0x35/0x50
+   ? l2tp_xmit_skb+0x243/0x9d0
+   l2tp_xmit_skb+0x243/0x9d0
+   l2tp_eth_dev_xmit+0x3c/0xc0
+   dev_hard_start_xmit+0x11e/0x420
+   sch_direct_xmit+0xc3/0x640
+   __dev_queue_xmit+0x61c/0x1450
+   ? ip_finish_output2+0xf4c/0x1130
+   ip_finish_output2+0x6b6/0x1130
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   ? __ip_finish_output+0x217/0x380
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   __ip_finish_output+0x217/0x380
+   ip_output+0x99/0x120
+   __ip_queue_xmit+0xae4/0xbc0
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   ? tcp_options_write.constprop.0+0xcb/0x3e0
+   ip_queue_xmit+0x34/0x40
+   __tcp_transmit_skb+0x1625/0x1890
+   __tcp_send_ack+0x1b8/0x340
+   tcp_send_ack+0x23/0x30
+   __tcp_ack_snd_check+0xa8/0x530
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   tcp_rcv_established+0x412/0xd70
+   tcp_v4_do_rcv+0x299/0x420
+   tcp_v4_rcv+0x1991/0x1e10
+   ip_protocol_deliver_rcu+0x50/0x220
+   ip_local_deliver_finish+0x158/0x260
+   ip_local_deliver+0xc8/0xe0
+   ip_rcv+0xe5/0x1d0
+   ? __pfx_ip_rcv+0x10/0x10
+   __netif_receive_skb_one_core+0xce/0xe0
+   ? process_backlog+0x28b/0x9f0
+   __netif_receive_skb+0x34/0xd0
+   ? process_backlog+0x28b/0x9f0
+   process_backlog+0x2cb/0x9f0
+   __napi_poll.constprop.0+0x61/0x280
+   net_rx_action+0x332/0x670
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   ? find_held_lock+0x2b/0x80
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   handle_softirqs+0xda/0x480
+   ? __dev_queue_xmit+0xa2c/0x1450
+   do_softirq+0xa1/0xd0
+   </IRQ>
+   <TASK>
+   __local_bh_enable_ip+0xc8/0xe0
+   ? __dev_queue_xmit+0xa2c/0x1450
+   __dev_queue_xmit+0xa48/0x1450
+   ? ip_finish_output2+0xf4c/0x1130
+   ip_finish_output2+0x6b6/0x1130
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   ? __ip_finish_output+0x217/0x380
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   __ip_finish_output+0x217/0x380
+   ip_output+0x99/0x120
+   __ip_queue_xmit+0xae4/0xbc0
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   ? tcp_options_write.constprop.0+0xcb/0x3e0
+   ip_queue_xmit+0x34/0x40
+   __tcp_transmit_skb+0x1625/0x1890
+   tcp_write_xmit+0x766/0x2fb0
+   ? __entry_text_end+0x102ba9/0x102bad
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   ? __might_fault+0x74/0xc0
+   ? srso_alias_return_thunk+0x5/0xfbef5
+   __tcp_push_pending_frames+0x56/0x190
+   tcp_push+0x117/0x310
+   tcp_sendmsg_locked+0x14c1/0x1740
+   tcp_sendmsg+0x28/0x40
+   inet_sendmsg+0x5d/0x90
+   sock_write_iter+0x242/0x2b0
+   vfs_write+0x68d/0x800
+   ? __pfx_sock_write_iter+0x10/0x10
+   ksys_write+0xc8/0xf0
+   __x64_sys_write+0x3d/0x50
+   x64_sys_call+0xfaf/0x1f50
+   do_syscall_64+0x6d/0x140
+   entry_SYSCALL_64_after_hwframe+0x76/0x7e
+  RIP: 0033:0x7f4d143af992
+  Code: c3 8b 07 85 c0 75 24 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> e9 01 cc ff ff 41 54 b8 02 00 00 0
+  RSP: 002b:00007ffd65032058 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
+  RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f4d143af992
+  RDX: 0000000000000025 RSI: 00007f4d143f3bcc RDI: 0000000000000005
+  RBP: 00007f4d143f2b28 R08: 0000000000000000 R09: 0000000000000000
+  R10: 0000000000000000 R11: 0000000000000246 R12: 00007f4d143f3bcc
+  R13: 0000000000000005 R14: 0000000000000000 R15: 00007ffd650323f0
+   </TASK>
+
+Fixes: 0b2c59720e65 ("l2tp: close all race conditions in l2tp_tunnel_register()")
+Suggested-by: Eric Dumazet <edumazet@google.com>
+Reported-by: syzbot+6acef9e0a4d1f46c83d4@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=6acef9e0a4d1f46c83d4
+CC: gnault@redhat.com
+CC: cong.wang@bytedance.com
+Signed-off-by: James Chapman <jchapman@katalix.com>
+Signed-off-by: Tom Parkin <tparkin@katalix.com>
+Link: https://patch.msgid.link/20240806160626.1248317-1-jchapman@katalix.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/l2tp/l2tp_core.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
+index 88a34db265d86..7ea4adf81d859 100644
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -88,6 +88,11 @@
+ /* Default trace flags */
+ #define L2TP_DEFAULT_DEBUG_FLAGS      0
++#define L2TP_DEPTH_NESTING            2
++#if L2TP_DEPTH_NESTING == SINGLE_DEPTH_NESTING
++#error "L2TP requires its own lockdep subclass"
++#endif
++
+ /* Private data stored for received packets in the skb.
+  */
+ struct l2tp_skb_cb {
+@@ -1085,7 +1090,13 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
+       IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
+       nf_reset_ct(skb);
+-      bh_lock_sock_nested(sk);
++      /* L2TP uses its own lockdep subclass to avoid lockdep splats caused by
++       * nested socket calls on the same lockdep socket class. This can
++       * happen when data from a user socket is routed over l2tp, which uses
++       * another userspace socket.
++       */
++      spin_lock_nested(&sk->sk_lock.slock, L2TP_DEPTH_NESTING);
++
+       if (sock_owned_by_user(sk)) {
+               kfree_skb(skb);
+               ret = NET_XMIT_DROP;
+@@ -1137,7 +1148,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
+       ret = l2tp_xmit_queue(tunnel, skb, &inet->cork.fl);
+ out_unlock:
+-      bh_unlock_sock(sk);
++      spin_unlock(&sk->sk_lock.slock);
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/locking-pvqspinlock-correct-the-type-of-old-variable.patch b/queue-6.10/locking-pvqspinlock-correct-the-type-of-old-variable.patch
new file mode 100644 (file)
index 0000000..a03431d
--- /dev/null
@@ -0,0 +1,45 @@
+From fed28319395deb213e9ffec499733460f57640c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 21 Jul 2024 18:45:41 +0200
+Subject: locking/pvqspinlock: Correct the type of "old" variable in
+ pv_kick_node()
+
+From: Uros Bizjak <ubizjak@gmail.com>
+
+[ Upstream commit 6623b0217d0c9bed80bfa43b778ce1c0eb03b497 ]
+
+"enum vcpu_state" is not compatible with "u8" type for all targets,
+resulting in:
+
+error: initialization of 'u8 *' {aka 'unsigned char *'} from incompatible pointer type 'enum vcpu_state *'
+
+for LoongArch. Correct the type of "old" variable to "u8".
+
+Fixes: fea0e1820b51 ("locking/pvqspinlock: Use try_cmpxchg() in qspinlock_paravirt.h")
+Closes: https://lore.kernel.org/lkml/20240719024010.3296488-1-maobibo@loongson.cn/
+Reported-by: Bibo Mao <maobibo@loongson.cn>
+Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Acked-by: Waiman Long <longman@redhat.com>
+Link: https://lore.kernel.org/r/20240721164552.50175-1-ubizjak@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/locking/qspinlock_paravirt.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock_paravirt.h
+index f5a36e67b5935..ac2e225027410 100644
+--- a/kernel/locking/qspinlock_paravirt.h
++++ b/kernel/locking/qspinlock_paravirt.h
+@@ -357,7 +357,7 @@ static void pv_wait_node(struct mcs_spinlock *node, struct mcs_spinlock *prev)
+ static void pv_kick_node(struct qspinlock *lock, struct mcs_spinlock *node)
+ {
+       struct pv_node *pn = (struct pv_node *)node;
+-      enum vcpu_state old = vcpu_halted;
++      u8 old = vcpu_halted;
+       /*
+        * If the vCPU is indeed halted, advance its state to match that of
+        * pv_wait_node(). If OTOH this fails, the vCPU was running and will
+-- 
+2.43.0
+
diff --git a/queue-6.10/md-change-the-return-value-type-of-md_write_start-to.patch b/queue-6.10/md-change-the-return-value-type-of-md_write_start-to.patch
new file mode 100644 (file)
index 0000000..0c45199
--- /dev/null
@@ -0,0 +1,125 @@
+From 1c475a309fe6d4cf4dab2a21d8bf742e4f7d95b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 May 2024 02:52:56 +0800
+Subject: md: change the return value type of md_write_start to void
+
+From: Li Nan <linan122@huawei.com>
+
+[ Upstream commit 03e792eaf18ec2e93e2c623f9f1a4bdb97fe4126 ]
+
+Commit cc27b0c78c79 ("md: fix deadlock between mddev_suspend() and
+md_write_start()") aborted md_write_start() with false when mddev is
+suspended, which fixed a deadlock if calling mddev_suspend() with
+holding reconfig_mutex(). Since mddev_suspend() now includes
+lockdep_assert_not_held(), it no longer holds the reconfig_mutex. This
+makes previous abort unnecessary. Now, remove unnecessary abort and
+change function return value to void.
+
+Signed-off-by: Li Nan <linan122@huawei.com>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20240525185257.3896201-2-linan666@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md.c     | 14 ++++----------
+ drivers/md/md.h     |  2 +-
+ drivers/md/raid1.c  |  3 +--
+ drivers/md/raid10.c |  3 +--
+ drivers/md/raid5.c  |  3 +--
+ 5 files changed, 8 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 60a5fda7c8aea..a5b5801baa9e8 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -8638,12 +8638,12 @@ EXPORT_SYMBOL(md_done_sync);
+  * A return value of 'false' means that the write wasn't recorded
+  * and cannot proceed as the array is being suspend.
+  */
+-bool md_write_start(struct mddev *mddev, struct bio *bi)
++void md_write_start(struct mddev *mddev, struct bio *bi)
+ {
+       int did_change = 0;
+       if (bio_data_dir(bi) != WRITE)
+-              return true;
++              return;
+       BUG_ON(mddev->ro == MD_RDONLY);
+       if (mddev->ro == MD_AUTO_READ) {
+@@ -8676,15 +8676,9 @@ bool md_write_start(struct mddev *mddev, struct bio *bi)
+       if (did_change)
+               sysfs_notify_dirent_safe(mddev->sysfs_state);
+       if (!mddev->has_superblocks)
+-              return true;
++              return;
+       wait_event(mddev->sb_wait,
+-                 !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) ||
+-                 is_md_suspended(mddev));
+-      if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
+-              percpu_ref_put(&mddev->writes_pending);
+-              return false;
+-      }
+-      return true;
++                 !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
+ }
+ EXPORT_SYMBOL(md_write_start);
+diff --git a/drivers/md/md.h b/drivers/md/md.h
+index ca085ecad5044..487582058f741 100644
+--- a/drivers/md/md.h
++++ b/drivers/md/md.h
+@@ -785,7 +785,7 @@ extern void md_unregister_thread(struct mddev *mddev, struct md_thread __rcu **t
+ extern void md_wakeup_thread(struct md_thread __rcu *thread);
+ extern void md_check_recovery(struct mddev *mddev);
+ extern void md_reap_sync_thread(struct mddev *mddev);
+-extern bool md_write_start(struct mddev *mddev, struct bio *bi);
++extern void md_write_start(struct mddev *mddev, struct bio *bi);
+ extern void md_write_inc(struct mddev *mddev, struct bio *bi);
+ extern void md_write_end(struct mddev *mddev);
+ extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 22bbd06ba6a29..5ea57b6748c53 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1688,8 +1688,7 @@ static bool raid1_make_request(struct mddev *mddev, struct bio *bio)
+       if (bio_data_dir(bio) == READ)
+               raid1_read_request(mddev, bio, sectors, NULL);
+       else {
+-              if (!md_write_start(mddev,bio))
+-                      return false;
++              md_write_start(mddev,bio);
+               raid1_write_request(mddev, bio, sectors);
+       }
+       return true;
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index a4556d2e46bf9..f8d7c02c6ed56 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -1836,8 +1836,7 @@ static bool raid10_make_request(struct mddev *mddev, struct bio *bio)
+           && md_flush_request(mddev, bio))
+               return true;
+-      if (!md_write_start(mddev, bio))
+-              return false;
++      md_write_start(mddev, bio);
+       if (unlikely(bio_op(bio) == REQ_OP_DISCARD))
+               if (!raid10_handle_discard(mddev, bio))
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 1c6b58adec133..d600030c20f46 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -6097,8 +6097,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
+               ctx.do_flush = bi->bi_opf & REQ_PREFLUSH;
+       }
+-      if (!md_write_start(mddev, bi))
+-              return false;
++      md_write_start(mddev, bi);
+       /*
+        * If array is degraded, better not do chunk aligned read because
+        * later we might have to read it again in order to reconstruct
+-- 
+2.43.0
+
diff --git a/queue-6.10/md-do-not-delete-safemode_timer-in-mddev_suspend.patch b/queue-6.10/md-do-not-delete-safemode_timer-in-mddev_suspend.patch
new file mode 100644 (file)
index 0000000..0374031
--- /dev/null
@@ -0,0 +1,48 @@
+From b44ae01194d94f931c56978e6000e1674ea25cf6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 May 2024 17:20:53 +0800
+Subject: md: do not delete safemode_timer in mddev_suspend
+
+From: Li Nan <linan122@huawei.com>
+
+[ Upstream commit a8768a134518e406d41799a3594aeb74e0889cf7 ]
+
+The deletion of safemode_timer in mddev_suspend() is redundant and
+potentially harmful now. If timer is about to be woken up but gets
+deleted, 'in_sync' will remain 0 until the next write, causing array
+to stay in the 'active' state instead of transitioning to 'clean'.
+
+Commit 0d9f4f135eb6 ("MD: Add del_timer_sync to mddev_suspend (fix
+nasty panic))" introduced this deletion for dm, because if timer fired
+after dm is destroyed, the resource which the timer depends on might
+have been freed.
+
+However, commit 0dd84b319352 ("md: call __md_stop_writes in md_stop")
+added __md_stop_writes() to md_stop(), which is called before freeing
+resource. Timer is deleted in __md_stop_writes(), and the origin issue
+is resolved. Therefore, delete safemode_timer can be removed safely now.
+
+Signed-off-by: Li Nan <linan122@huawei.com>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20240508092053.1447930-1-linan666@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 9c5be016e5073..60a5fda7c8aea 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -479,7 +479,6 @@ int mddev_suspend(struct mddev *mddev, bool interruptible)
+        */
+       WRITE_ONCE(mddev->suspended, mddev->suspended + 1);
+-      del_timer_sync(&mddev->safemode_timer);
+       /* restrict memory reclaim I/O during raid array is suspend */
+       mddev->noio_flag = memalloc_noio_save();
+-- 
+2.43.0
+
diff --git a/queue-6.10/md-raid5-avoid-bug_on-while-continue-reshape-after-r.patch b/queue-6.10/md-raid5-avoid-bug_on-while-continue-reshape-after-r.patch
new file mode 100644 (file)
index 0000000..6d6b2a1
--- /dev/null
@@ -0,0 +1,93 @@
+From d60b757a4fd882e728f3fda3bc803ba357d9bb5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jun 2024 21:22:51 +0800
+Subject: md/raid5: avoid BUG_ON() while continue reshape after reassembling
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 305a5170dc5cf3d395bb4c4e9239bca6d0b54b49 ]
+
+Currently, mdadm support --revert-reshape to abort the reshape while
+reassembling, as the test 07revert-grow. However, following BUG_ON()
+can be triggerred by the test:
+
+kernel BUG at drivers/md/raid5.c:6278!
+invalid opcode: 0000 [#1] PREEMPT SMP PTI
+irq event stamp: 158985
+CPU: 6 PID: 891 Comm: md0_reshape Not tainted 6.9.0-03335-g7592a0b0049a #94
+RIP: 0010:reshape_request+0x3f1/0xe60
+Call Trace:
+ <TASK>
+ raid5_sync_request+0x43d/0x550
+ md_do_sync+0xb7a/0x2110
+ md_thread+0x294/0x2b0
+ kthread+0x147/0x1c0
+ ret_from_fork+0x59/0x70
+ ret_from_fork_asm+0x1a/0x30
+ </TASK>
+
+Root cause is that --revert-reshape update the raid_disks from 5 to 4,
+while reshape position is still set, and after reassembling the array,
+reshape position will be read from super block, then during reshape the
+checking of 'writepos' that is caculated by old reshape position will
+fail.
+
+Fix this panic the easy way first, by converting the BUG_ON() to
+WARN_ON(), and stop the reshape if checkings fail.
+
+Noted that mdadm must fix --revert-shape as well, and probably md/raid
+should enhance metadata validation as well, however this means
+reassemble will fail and there must be user tools to fix the wrong
+metadata.
+
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20240611132251.1967786-13-yukuai1@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/raid5.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index d600030c20f46..ff9f4751c0965 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -6272,7 +6272,9 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
+       safepos = conf->reshape_safe;
+       sector_div(safepos, data_disks);
+       if (mddev->reshape_backwards) {
+-              BUG_ON(writepos < reshape_sectors);
++              if (WARN_ON(writepos < reshape_sectors))
++                      return MaxSector;
++
+               writepos -= reshape_sectors;
+               readpos += reshape_sectors;
+               safepos += reshape_sectors;
+@@ -6290,14 +6292,18 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
+        * to set 'stripe_addr' which is where we will write to.
+        */
+       if (mddev->reshape_backwards) {
+-              BUG_ON(conf->reshape_progress == 0);
++              if (WARN_ON(conf->reshape_progress == 0))
++                      return MaxSector;
++
+               stripe_addr = writepos;
+-              BUG_ON((mddev->dev_sectors &
+-                      ~((sector_t)reshape_sectors - 1))
+-                     - reshape_sectors - stripe_addr
+-                     != sector_nr);
++              if (WARN_ON((mddev->dev_sectors &
++                  ~((sector_t)reshape_sectors - 1)) -
++                  reshape_sectors - stripe_addr != sector_nr))
++                      return MaxSector;
+       } else {
+-              BUG_ON(writepos != sector_nr + reshape_sectors);
++              if (WARN_ON(writepos != sector_nr + reshape_sectors))
++                      return MaxSector;
++
+               stripe_addr = sector_nr;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/media-amphion-remove-lock-in-s_ctrl-callback.patch b/queue-6.10/media-amphion-remove-lock-in-s_ctrl-callback.patch
new file mode 100644 (file)
index 0000000..0bd1ca9
--- /dev/null
@@ -0,0 +1,65 @@
+From 8aa23f4e314d0dd9f62062228ae18c02fdcd89f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 May 2024 17:49:17 +0900
+Subject: media: amphion: Remove lock in s_ctrl callback
+
+From: Ming Qian <ming.qian@nxp.com>
+
+[ Upstream commit 065927b51eb1f042c3e026cebfd55e72ccc26093 ]
+
+There is no need to add a lock in s_ctrl callback, it has been
+synchronized by the ctrl_handler's lock, otherwise it may led to
+a deadlock if the driver calls v4l2_ctrl_s_ctrl().
+
+Signed-off-by: Ming Qian <ming.qian@nxp.com>
+Signed-off-by: Sebastian Fricke <sebastian.fricke@collabora.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/amphion/vdec.c | 2 --
+ drivers/media/platform/amphion/venc.c | 2 --
+ 2 files changed, 4 deletions(-)
+
+diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c
+index a57f9f4f3b876..6a38a0fa0e2d4 100644
+--- a/drivers/media/platform/amphion/vdec.c
++++ b/drivers/media/platform/amphion/vdec.c
+@@ -195,7 +195,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
+       struct vdec_t *vdec = inst->priv;
+       int ret = 0;
+-      vpu_inst_lock(inst);
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:
+               vdec->params.display_delay_enable = ctrl->val;
+@@ -207,7 +206,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
+               ret = -EINVAL;
+               break;
+       }
+-      vpu_inst_unlock(inst);
+       return ret;
+ }
+diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c
+index 4eb57d793a9c0..16ed4d21519cd 100644
+--- a/drivers/media/platform/amphion/venc.c
++++ b/drivers/media/platform/amphion/venc.c
+@@ -518,7 +518,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
+       struct venc_t *venc = inst->priv;
+       int ret = 0;
+-      vpu_inst_lock(inst);
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               venc->params.profile = ctrl->val;
+@@ -579,7 +578,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
+               ret = -EINVAL;
+               break;
+       }
+-      vpu_inst_unlock(inst);
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/media-i2c-ov5647-replacing-of_node_put-with-__free-d.patch b/queue-6.10/media-i2c-ov5647-replacing-of_node_put-with-__free-d.patch
new file mode 100644 (file)
index 0000000..7d3df4f
--- /dev/null
@@ -0,0 +1,58 @@
+From eef42813941642af47101e5524f80d8824ad39c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jun 2024 06:51:58 -0400
+Subject: media: i2c: ov5647: replacing of_node_put with __free(device_node)
+
+From: Abdulrasaq Lawani <abdulrasaqolawani@gmail.com>
+
+[ Upstream commit 971b4eef86ccb8b107ad2875993e510eec4fdeae ]
+
+Replace instance of of_node_put with __free(device_node)
+to protect against any memory leaks due to future changes
+in control flow.
+
+Signed-off-by: Abdulrasaq Lawani <abdulrasaqolawani@gmail.com>
+Acked-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/ov5647.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c
+index 7e1ecdf2485f7..0fb4d7bff9d14 100644
+--- a/drivers/media/i2c/ov5647.c
++++ b/drivers/media/i2c/ov5647.c
+@@ -1360,24 +1360,21 @@ static int ov5647_parse_dt(struct ov5647 *sensor, struct device_node *np)
+       struct v4l2_fwnode_endpoint bus_cfg = {
+               .bus_type = V4L2_MBUS_CSI2_DPHY,
+       };
+-      struct device_node *ep;
++      struct device_node *ep __free(device_node) =
++              of_graph_get_endpoint_by_regs(np, 0, -1);
+       int ret;
+-      ep = of_graph_get_endpoint_by_regs(np, 0, -1);
+       if (!ep)
+               return -EINVAL;
+       ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
+       if (ret)
+-              goto out;
++              return ret;
+       sensor->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
+                             V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
+-out:
+-      of_node_put(ep);
+-
+-      return ret;
++      return 0;
+ }
+ static int ov5647_probe(struct i2c_client *client)
+-- 
+2.43.0
+
diff --git a/queue-6.10/media-uvcvideo-fix-the-bandwdith-quirk-on-usb-3.x.patch b/queue-6.10/media-uvcvideo-fix-the-bandwdith-quirk-on-usb-3.x.patch
new file mode 100644 (file)
index 0000000..4c52579
--- /dev/null
@@ -0,0 +1,52 @@
+From 21532cf722d3213bd830a52ca71e6f316e3141e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Apr 2024 19:00:40 +0200
+Subject: media: uvcvideo: Fix the bandwdith quirk on USB 3.x
+
+From: Michal Pecio <michal.pecio@gmail.com>
+
+[ Upstream commit 9e3d55fbd160b3ca376599a68b4cddfdc67d4153 ]
+
+The bandwidth fixup quirk doesn't know that SuperSpeed exists and has
+the same 8 service intervals per millisecond as High Speed, hence its
+calculations are wrong.
+
+Assume that all speeds from HS up use 8 intervals per millisecond.
+
+No further changes are needed, updated code has been confirmed to work
+with all speeds from FS to SS.
+
+Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
+Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Link: https://lore.kernel.org/r/20240414190040.2255a0bc@foxbook
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index 0055a05470c47..5bebe1460a9f7 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -214,13 +214,13 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
+                * Compute a bandwidth estimation by multiplying the frame
+                * size by the number of video frames per second, divide the
+                * result by the number of USB frames (or micro-frames for
+-               * high-speed devices) per second and add the UVC header size
+-               * (assumed to be 12 bytes long).
++               * high- and super-speed devices) per second and add the UVC
++               * header size (assumed to be 12 bytes long).
+                */
+               bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
+               bandwidth *= 10000000 / interval + 1;
+               bandwidth /= 1000;
+-              if (stream->dev->udev->speed == USB_SPEED_HIGH)
++              if (stream->dev->udev->speed >= USB_SPEED_HIGH)
+                       bandwidth /= 8;
+               bandwidth += 12;
+-- 
+2.43.0
+
diff --git a/queue-6.10/media-uvcvideo-ignore-empty-ts-packets.patch b/queue-6.10/media-uvcvideo-ignore-empty-ts-packets.patch
new file mode 100644 (file)
index 0000000..abb26d4
--- /dev/null
@@ -0,0 +1,129 @@
+From e05394917945485e8c7b7f986e3fe7bc17d5a9e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 Mar 2024 10:48:03 +0000
+Subject: media: uvcvideo: Ignore empty TS packets
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 5cd7c25f6f0576073b3d03bc4cfb1e8ca63a1195 ]
+
+Some SunplusIT cameras took a borderline interpretation of the UVC 1.5
+standard, and fill the PTS and SCR fields with invalid data if the
+package does not contain data.
+
+"STC must be captured when the first video data of a video frame is put
+on the USB bus."
+
+Some SunplusIT devices send, e.g.,
+
+buffer: 0xa7755c00 len 000012 header:0x8c stc 00000000 sof 0000 pts 00000000
+buffer: 0xa7755c00 len 000012 header:0x8c stc 00000000 sof 0000 pts 00000000
+buffer: 0xa7755c00 len 000668 header:0x8c stc 73779dba sof 070c pts 7376d37a
+
+While the UVC specification meant that the first two packets shouldn't
+have had the SCR bit set in the header.
+
+This borderline/buggy interpretation has been implemented in a variety
+of devices, from directly SunplusIT and from other OEMs that rebrand
+SunplusIT products. So quirking based on VID:PID will be problematic.
+
+All the affected modules have the following extension unit:
+VideoControl Interface Descriptor:
+  guidExtensionCode         {82066163-7050-ab49-b8cc-b3855e8d221d}
+
+But the vendor plans to use that GUID in the future and fix the bug,
+this means that we should use heuristic to figure out the broken
+packets.
+
+This patch takes care of this.
+
+lsusb of one of the affected cameras:
+
+Bus 001 Device 003: ID 1bcf:2a01 Sunplus Innovation Technology Inc.
+Device Descriptor:
+  bLength                18
+  bDescriptorType         1
+  bcdUSB               2.01
+  bDeviceClass          239 Miscellaneous Device
+  bDeviceSubClass         2 ?
+  bDeviceProtocol         1 Interface Association
+  bMaxPacketSize0        64
+  idVendor           0x1bcf Sunplus Innovation Technology Inc.
+  idProduct          0x2a01
+  bcdDevice            0.02
+  iManufacturer           1 SunplusIT Inc
+  iProduct                2 HanChen Wise Camera
+  iSerial                 3 01.00.00
+  bNumConfigurations      1
+
+Tested-by: HungNien Chen <hn.chen@sunplusit.com>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Tomasz Figa <tfiga@chromium.org>
+Link: https://lore.kernel.org/r/20240323-resend-hwtimestamp-v10-2-b08e590d97c7@chromium.org
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 31 ++++++++++++++++++++++++++++++-
+ 1 file changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index 51f4f653b983d..0055a05470c47 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -478,6 +478,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+       ktime_t time;
+       u16 host_sof;
+       u16 dev_sof;
++      u32 dev_stc;
+       switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
+       case UVC_STREAM_PTS | UVC_STREAM_SCR:
+@@ -526,6 +527,34 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+       if (dev_sof == stream->clock.last_sof)
+               return;
++      dev_stc = get_unaligned_le32(&data[header_size - 6]);
++
++      /*
++       * STC (Source Time Clock) is the clock used by the camera. The UVC 1.5
++       * standard states that it "must be captured when the first video data
++       * of a video frame is put on the USB bus". This is generally understood
++       * as requiring devices to clear the payload header's SCR bit before
++       * the first packet containing video data.
++       *
++       * Most vendors follow that interpretation, but some (namely SunplusIT
++       * on some devices) always set the `UVC_STREAM_SCR` bit, fill the SCR
++       * field with 0's,and expect that the driver only processes the SCR if
++       * there is data in the packet.
++       *
++       * Ignore all the hardware timestamp information if we haven't received
++       * any data for this frame yet, the packet contains no data, and both
++       * STC and SOF are zero. This heuristics should be safe on compliant
++       * devices. This should be safe with compliant devices, as in the very
++       * unlikely case where a UVC 1.1 device would send timing information
++       * only before the first packet containing data, and both STC and SOF
++       * happen to be zero for a particular frame, we would only miss one
++       * clock sample from many and the clock recovery algorithm wouldn't
++       * suffer from this condition.
++       */
++      if (buf && buf->bytesused == 0 && len == header_size &&
++          dev_stc == 0 && dev_sof == 0)
++              return;
++
+       stream->clock.last_sof = dev_sof;
+       host_sof = usb_get_current_frame_number(stream->dev->udev);
+@@ -575,7 +604,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+       spin_lock_irqsave(&stream->clock.lock, flags);
+       sample = &stream->clock.samples[stream->clock.head];
+-      sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
++      sample->dev_stc = dev_stc;
+       sample->dev_sof = dev_sof;
+       sample->host_sof = host_sof;
+       sample->host_time = time;
+-- 
+2.43.0
+
diff --git a/queue-6.10/media-xc2028-avoid-use-after-free-in-load_firmware_c.patch b/queue-6.10/media-xc2028-avoid-use-after-free-in-load_firmware_c.patch
new file mode 100644 (file)
index 0000000..2030926
--- /dev/null
@@ -0,0 +1,129 @@
+From f4afc234a5ac4ee3af59108a4e74abb8da0d3af6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 08:22:25 -0700
+Subject: media: xc2028: avoid use-after-free in load_firmware_cb()
+
+From: Chi Zhiling <chizhiling@kylinos.cn>
+
+[ Upstream commit 68594cec291ff9523b9feb3f43fd853dcddd1f60 ]
+
+syzkaller reported use-after-free in load_firmware_cb() [1].
+The reason is because the module allocated a struct tuner in tuner_probe(),
+and then the module initialization failed, the struct tuner was released.
+A worker which created during module initialization accesses this struct
+tuner later, it caused use-after-free.
+
+The process is as follows:
+
+task-6504           worker_thread
+tuner_probe                             <= alloc dvb_frontend [2]
+...
+request_firmware_nowait                 <= create a worker
+...
+tuner_remove                            <= free dvb_frontend
+...
+                    request_firmware_work_func  <= the firmware is ready
+                    load_firmware_cb    <= but now the dvb_frontend has been freed
+
+To fix the issue, check the dvd_frontend in load_firmware_cb(), if it is
+null, report a warning and just return.
+
+[1]:
+    ==================================================================
+     BUG: KASAN: use-after-free in load_firmware_cb+0x1310/0x17a0
+     Read of size 8 at addr ffff8000d7ca2308 by task kworker/2:3/6504
+
+     Call trace:
+      load_firmware_cb+0x1310/0x17a0
+      request_firmware_work_func+0x128/0x220
+      process_one_work+0x770/0x1824
+      worker_thread+0x488/0xea0
+      kthread+0x300/0x430
+      ret_from_fork+0x10/0x20
+
+     Allocated by task 6504:
+      kzalloc
+      tuner_probe+0xb0/0x1430
+      i2c_device_probe+0x92c/0xaf0
+      really_probe+0x678/0xcd0
+      driver_probe_device+0x280/0x370
+      __device_attach_driver+0x220/0x330
+      bus_for_each_drv+0x134/0x1c0
+      __device_attach+0x1f4/0x410
+      device_initial_probe+0x20/0x30
+      bus_probe_device+0x184/0x200
+      device_add+0x924/0x12c0
+      device_register+0x24/0x30
+      i2c_new_device+0x4e0/0xc44
+      v4l2_i2c_new_subdev_board+0xbc/0x290
+      v4l2_i2c_new_subdev+0xc8/0x104
+      em28xx_v4l2_init+0x1dd0/0x3770
+
+     Freed by task 6504:
+      kfree+0x238/0x4e4
+      tuner_remove+0x144/0x1c0
+      i2c_device_remove+0xc8/0x290
+      __device_release_driver+0x314/0x5fc
+      device_release_driver+0x30/0x44
+      bus_remove_device+0x244/0x490
+      device_del+0x350/0x900
+      device_unregister+0x28/0xd0
+      i2c_unregister_device+0x174/0x1d0
+      v4l2_device_unregister+0x224/0x380
+      em28xx_v4l2_init+0x1d90/0x3770
+
+     The buggy address belongs to the object at ffff8000d7ca2000
+      which belongs to the cache kmalloc-2k of size 2048
+     The buggy address is located 776 bytes inside of
+      2048-byte region [ffff8000d7ca2000, ffff8000d7ca2800)
+     The buggy address belongs to the page:
+     page:ffff7fe00035f280 count:1 mapcount:0 mapping:ffff8000c001f000 index:0x0
+     flags: 0x7ff800000000100(slab)
+     raw: 07ff800000000100 ffff7fe00049d880 0000000300000003 ffff8000c001f000
+     raw: 0000000000000000 0000000080100010 00000001ffffffff 0000000000000000
+     page dumped because: kasan: bad access detected
+
+     Memory state around the buggy address:
+      ffff8000d7ca2200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+      ffff8000d7ca2280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+     >ffff8000d7ca2300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+                           ^
+      ffff8000d7ca2380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+      ffff8000d7ca2400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+     ==================================================================
+
+[2]
+    Actually, it is allocated for struct tuner, and dvb_frontend is inside.
+
+Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/tuners/xc2028.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/tuners/xc2028.c b/drivers/media/tuners/xc2028.c
+index 5a967edceca93..352b8a3679b72 100644
+--- a/drivers/media/tuners/xc2028.c
++++ b/drivers/media/tuners/xc2028.c
+@@ -1361,9 +1361,16 @@ static void load_firmware_cb(const struct firmware *fw,
+                            void *context)
+ {
+       struct dvb_frontend *fe = context;
+-      struct xc2028_data *priv = fe->tuner_priv;
++      struct xc2028_data *priv;
+       int rc;
++      if (!fe) {
++              pr_warn("xc2028: No frontend in %s\n", __func__);
++              return;
++      }
++
++      priv = fe->tuner_priv;
++
+       tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error");
+       if (!fw) {
+               tuner_err("Could not load firmware %s.\n", priv->fname);
+-- 
+2.43.0
+
diff --git a/queue-6.10/mlxsw-pci-lock-configuration-space-of-upstream-bridg.patch b/queue-6.10/mlxsw-pci-lock-configuration-space-of-upstream-bridg.patch
new file mode 100644 (file)
index 0000000..082cab6
--- /dev/null
@@ -0,0 +1,70 @@
+From 54c51fb53554f5c2a50bd288002f8407f33ff2aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Jul 2024 16:23:42 +0200
+Subject: mlxsw: pci: Lock configuration space of upstream bridge during reset
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 0970836c348b6bc2ea77ce4348a136d6febfd440 ]
+
+The driver triggers a "Secondary Bus Reset" (SBR) by calling
+__pci_reset_function_locked() which asserts the SBR bit in the "Bridge
+Control Register" in the configuration space of the upstream bridge for
+2ms. This is done without locking the configuration space of the
+upstream bridge port, allowing user space to access it concurrently.
+
+Linux 6.11 will start warning about such unlocked resets [1][2]:
+
+pcieport 0000:00:01.0: unlocked secondary bus reset via: pci_reset_bus_function+0x51c/0x6a0
+
+Avoid the warning and the concurrent access by locking the configuration
+space of the upstream bridge prior to the reset and unlocking it
+afterwards.
+
+[1] https://lore.kernel.org/all/171711746953.1628941.4692125082286867825.stgit@dwillia2-xfh.jf.intel.com/
+[2] https://lore.kernel.org/all/20240531213150.GA610983@bhelgaas/
+
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Petr Machata <petrm@nvidia.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Link: https://patch.msgid.link/9937b0afdb50f2f2825945393c94c093c04a5897.1720447210.git.petrm@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlxsw/pci.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
+index c0ced4d315f3d..d92f640bae575 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
+@@ -1599,6 +1599,7 @@ static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci,
+ {
+       struct pci_dev *pdev = mlxsw_pci->pdev;
+       char mrsr_pl[MLXSW_REG_MRSR_LEN];
++      struct pci_dev *bridge;
+       int err;
+       if (!pci_reset_sbr_supported) {
+@@ -1615,6 +1616,9 @@ static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci,
+ sbr:
+       device_lock_assert(&pdev->dev);
++      bridge = pci_upstream_bridge(pdev);
++      if (bridge)
++              pci_cfg_access_lock(bridge);
+       pci_cfg_access_lock(pdev);
+       pci_save_state(pdev);
+@@ -1624,6 +1628,8 @@ static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci,
+       pci_restore_state(pdev);
+       pci_cfg_access_unlock(pdev);
++      if (bridge)
++              pci_cfg_access_unlock(bridge);
+       return err;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-bcmgenet-properly-overlay-phy-and-mac-wake-on-la.patch b/queue-6.10/net-bcmgenet-properly-overlay-phy-and-mac-wake-on-la.patch
new file mode 100644 (file)
index 0000000..dda84dc
--- /dev/null
@@ -0,0 +1,55 @@
+From fe3cc5d6e1596c945a8d0c3d4a383f3bd16b1864 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 10:56:59 -0700
+Subject: net: bcmgenet: Properly overlay PHY and MAC Wake-on-LAN capabilities
+
+From: Florian Fainelli <florian.fainelli@broadcom.com>
+
+[ Upstream commit 9ee09edc05f20422e7ced84b1f8a5d3359926ac8 ]
+
+Some Wake-on-LAN modes such as WAKE_FILTER may only be supported by the MAC,
+while others might be only supported by the PHY. Make sure that the .get_wol()
+returns the union of both rather than only that of the PHY if the PHY supports
+Wake-on-LAN.
+
+Fixes: 7e400ff35cbe ("net: bcmgenet: Add support for PHY-based Wake-on-LAN")
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://patch.msgid.link/20240806175659.3232204-1-florian.fainelli@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c | 14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+index 1248792d7fd4d..0715ea5bf13ed 100644
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+@@ -42,19 +42,15 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+       struct bcmgenet_priv *priv = netdev_priv(dev);
+       struct device *kdev = &priv->pdev->dev;
+-      if (dev->phydev) {
++      if (dev->phydev)
+               phy_ethtool_get_wol(dev->phydev, wol);
+-              if (wol->supported)
+-                      return;
+-      }
+-      if (!device_can_wakeup(kdev)) {
+-              wol->supported = 0;
+-              wol->wolopts = 0;
++      /* MAC is not wake-up capable, return what the PHY does */
++      if (!device_can_wakeup(kdev))
+               return;
+-      }
+-      wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
++      /* Overlay MAC capabilities with that of the PHY queried before */
++      wol->supported |= WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
+       wol->wolopts = priv->wolopts;
+       memset(wol->sopass, 0, sizeof(wol->sopass));
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-bridge-mcast-wait-for-previous-gc-cycles-when-re.patch b/queue-6.10/net-bridge-mcast-wait-for-previous-gc-cycles-when-re.patch
new file mode 100644 (file)
index 0000000..530663e
--- /dev/null
@@ -0,0 +1,82 @@
+From 2c2fcaa66479fa8e5132b282b9d8ddca68cf4ce8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 11:07:30 +0300
+Subject: net: bridge: mcast: wait for previous gc cycles when removing port
+
+From: Nikolay Aleksandrov <razor@blackwall.org>
+
+[ Upstream commit 92c4ee25208d0f35dafc3213cdf355fbe449e078 ]
+
+syzbot hit a use-after-free[1] which is caused because the bridge doesn't
+make sure that all previous garbage has been collected when removing a
+port. What happens is:
+      CPU 1                   CPU 2
+ start gc cycle           remove port
+                         acquire gc lock first
+ wait for lock
+                         call br_multicasg_gc() directly
+ acquire lock now but    free port
+ the port can be freed
+ while grp timers still
+ running
+
+Make sure all previous gc cycles have finished by using flush_work before
+freeing the port.
+
+[1]
+  BUG: KASAN: slab-use-after-free in br_multicast_port_group_expired+0x4c0/0x550 net/bridge/br_multicast.c:861
+  Read of size 8 at addr ffff888071d6d000 by task syz.5.1232/9699
+
+  CPU: 1 PID: 9699 Comm: syz.5.1232 Not tainted 6.10.0-rc5-syzkaller-00021-g24ca36a562d6 #0
+  Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/07/2024
+  Call Trace:
+   <IRQ>
+   __dump_stack lib/dump_stack.c:88 [inline]
+   dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:114
+   print_address_description mm/kasan/report.c:377 [inline]
+   print_report+0xc3/0x620 mm/kasan/report.c:488
+   kasan_report+0xd9/0x110 mm/kasan/report.c:601
+   br_multicast_port_group_expired+0x4c0/0x550 net/bridge/br_multicast.c:861
+   call_timer_fn+0x1a3/0x610 kernel/time/timer.c:1792
+   expire_timers kernel/time/timer.c:1843 [inline]
+   __run_timers+0x74b/0xaf0 kernel/time/timer.c:2417
+   __run_timer_base kernel/time/timer.c:2428 [inline]
+   __run_timer_base kernel/time/timer.c:2421 [inline]
+   run_timer_base+0x111/0x190 kernel/time/timer.c:2437
+
+Reported-by: syzbot+263426984509be19c9a0@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=263426984509be19c9a0
+Fixes: e12cec65b554 ("net: bridge: mcast: destroy all entries via gc")
+Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20240802080730.3206303-1-razor@blackwall.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_multicast.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
+index 9a1cb5079a7a0..b2ae0d2434d2e 100644
+--- a/net/bridge/br_multicast.c
++++ b/net/bridge/br_multicast.c
+@@ -2045,16 +2045,14 @@ void br_multicast_del_port(struct net_bridge_port *port)
+ {
+       struct net_bridge *br = port->br;
+       struct net_bridge_port_group *pg;
+-      HLIST_HEAD(deleted_head);
+       struct hlist_node *n;
+       /* Take care of the remaining groups, only perm ones should be left */
+       spin_lock_bh(&br->multicast_lock);
+       hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
+               br_multicast_find_del_pg(br, pg);
+-      hlist_move_list(&br->mcast_gc_list, &deleted_head);
+       spin_unlock_bh(&br->multicast_lock);
+-      br_multicast_gc(&deleted_head);
++      flush_work(&br->mcast_gc_work);
+       br_multicast_port_ctx_deinit(&port->multicast_ctx);
+       free_percpu(port->mcast_stats);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-dsa-bcm_sf2-fix-a-possible-memory-leak-in-bcm_sf.patch b/queue-6.10/net-dsa-bcm_sf2-fix-a-possible-memory-leak-in-bcm_sf.patch
new file mode 100644 (file)
index 0000000..f18472c
--- /dev/null
@@ -0,0 +1,50 @@
+From 0a021dbaf4b0a8000aeb7c742070e461b17e0821 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 10:13:27 +0900
+Subject: net: dsa: bcm_sf2: Fix a possible memory leak in
+ bcm_sf2_mdio_register()
+
+From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+
+[ Upstream commit e3862093ee93fcfbdadcb7957f5f8974fffa806a ]
+
+bcm_sf2_mdio_register() calls of_phy_find_device() and then
+phy_device_remove() in a loop to remove existing PHY devices.
+of_phy_find_device() eventually calls bus_find_device(), which calls
+get_device() on the returned struct device * to increment the refcount.
+The current implementation does not decrement the refcount, which causes
+memory leak.
+
+This commit adds the missing phy_device_free() call to decrement the
+refcount via put_device() to balance the refcount.
+
+Fixes: 771089c2a485 ("net: dsa: bcm_sf2: Ensure that MDIO diversion is used")
+Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://patch.msgid.link/20240806011327.3817861-1-joe@pf.is.s.u-tokyo.ac.jp
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/bcm_sf2.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
+index ed1e6560df25e..0e663ec0c12a3 100644
+--- a/drivers/net/dsa/bcm_sf2.c
++++ b/drivers/net/dsa/bcm_sf2.c
+@@ -675,8 +675,10 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
+                       of_remove_property(child, prop);
+               phydev = of_phy_find_device(child);
+-              if (phydev)
++              if (phydev) {
+                       phy_device_remove(phydev);
++                      phy_device_free(phydev);
++              }
+       }
+       err = mdiobus_register(priv->user_mii_bus);
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-dsa-microchip-disable-eee-for-ksz8567-ksz9567-ks.patch b/queue-6.10/net-dsa-microchip-disable-eee-for-ksz8567-ksz9567-ks.patch
new file mode 100644 (file)
index 0000000..2fbfb8c
--- /dev/null
@@ -0,0 +1,72 @@
+From 38765944c6c8500c34eee8c1514f3701656032e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 21:52:09 +0100
+Subject: net: dsa: microchip: disable EEE for KSZ8567/KSZ9567/KSZ9896/KSZ9897.
+
+From: Martin Whitaker <foss@martin-whitaker.me.uk>
+
+[ Upstream commit 0411f73c13afcf619d7aa7546edbc5710a871cae ]
+
+As noted in the device errata [1-8], EEE support is not fully operational
+in the KSZ8567, KSZ9477, KSZ9567, KSZ9896, and KSZ9897 devices, causing
+link drops when connected to another device that supports EEE. The patch
+series "net: add EEE support for KSZ9477 switch family" merged in commit
+9b0bf4f77162 caused EEE support to be enabled in these devices. A fix for
+this regression for the KSZ9477 alone was merged in commit 08c6d8bae48c2.
+This patch extends this fix to the other affected devices.
+
+[1] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ8567R-Errata-DS80000752.pdf
+[2] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ8567S-Errata-DS80000753.pdf
+[3] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9477S-Errata-DS80000754.pdf
+[4] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9567R-Errata-DS80000755.pdf
+[5] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9567S-Errata-DS80000756.pdf
+[6] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9896C-Errata-DS80000757.pdf
+[7] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9897R-Errata-DS80000758.pdf
+[8] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9897S-Errata-DS80000759.pdf
+
+Fixes: 69d3b36ca045 ("net: dsa: microchip: enable EEE support") # for KSZ8567/KSZ9567/KSZ9896/KSZ9897
+Link: https://lore.kernel.org/netdev/137ce1ee-0b68-4c96-a717-c8164b514eec@martin-whitaker.me.uk/
+Signed-off-by: Martin Whitaker <foss@martin-whitaker.me.uk>
+Acked-by: Arun Ramadoss <arun.ramadoss@microchip.com>
+Reviewed-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Reviewed-by: Lukasz Majewski <lukma@denx.de>
+Link: https://patch.msgid.link/20240807205209.21464-1-foss@martin-whitaker.me.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/microchip/ksz_common.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
+index 077935cf5e381..3103e1b32d0ba 100644
+--- a/drivers/net/dsa/microchip/ksz_common.c
++++ b/drivers/net/dsa/microchip/ksz_common.c
+@@ -2578,7 +2578,11 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
+               if (!port)
+                       return MICREL_KSZ8_P1_ERRATA;
+               break;
++      case KSZ8567_CHIP_ID:
+       case KSZ9477_CHIP_ID:
++      case KSZ9567_CHIP_ID:
++      case KSZ9896_CHIP_ID:
++      case KSZ9897_CHIP_ID:
+               /* KSZ9477 Errata DS80000754C
+                *
+                * Module 4: Energy Efficient Ethernet (EEE) feature select must
+@@ -2588,6 +2592,13 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
+                *   controls. If not disabled, the PHY ports can auto-negotiate
+                *   to enable EEE, and this feature can cause link drops when
+                *   linked to another device supporting EEE.
++               *
++               * The same item appears in the errata for the KSZ9567, KSZ9896,
++               * and KSZ9897.
++               *
++               * A similar item appears in the errata for the KSZ8567, but
++               * provides an alternative workaround. For now, use the simple
++               * workaround of disabling the EEE feature for this device too.
+                */
+               return MICREL_NO_EEE;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-dsa-microchip-fix-wake-on-lan-check-to-not-retur.patch b/queue-6.10/net-dsa-microchip-fix-wake-on-lan-check-to-not-retur.patch
new file mode 100644 (file)
index 0000000..58c4f27
--- /dev/null
@@ -0,0 +1,44 @@
+From 881f1d5fb207a51add1fd66cf2aabf4c58f6ae8f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 16:52:00 -0700
+Subject: net: dsa: microchip: Fix Wake-on-LAN check to not return an error
+
+From: Tristram Ha <tristram.ha@microchip.com>
+
+[ Upstream commit c7a19018bd557c24072b59088ad2684fd83ea3f4 ]
+
+The wol variable in ksz_port_set_mac_address() is declared with random
+data, but the code in ksz_get_wol call may not be executed so the
+WAKE_MAGIC check may be invalid resulting in an error message when
+setting a MAC address after starting the DSA driver.
+
+Fixes: 3b454b6390c3 ("net: dsa: microchip: ksz9477: Add Wake on Magic Packet support")
+Signed-off-by: Tristram Ha <tristram.ha@microchip.com>
+Reviewed-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://patch.msgid.link/20240805235200.24982-1-Tristram.Ha@microchip.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/microchip/ksz_common.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
+index baa1eeb9a1b04..077935cf5e381 100644
+--- a/drivers/net/dsa/microchip/ksz_common.c
++++ b/drivers/net/dsa/microchip/ksz_common.c
+@@ -3763,6 +3763,11 @@ static int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
+               return -EBUSY;
+       }
++      /* Need to initialize variable as the code to fill in settings may
++       * not be executed.
++       */
++      wol.wolopts = 0;
++
+       ksz_get_wol(ds, dp->index, &wol);
+       if (wol.wolopts & WAKE_MAGIC) {
+               dev_err(ds->dev,
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-fec-stop-pps-on-driver-remove.patch b/queue-6.10/net-fec-stop-pps-on-driver-remove.patch
new file mode 100644 (file)
index 0000000..b526d64
--- /dev/null
@@ -0,0 +1,46 @@
+From 3cc8f38bc5dd1f1dfbf076ba3441e413537e79c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 10:09:56 +0200
+Subject: net: fec: Stop PPS on driver remove
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Csókás, Bence <csokas.bence@prolan.hu>
+
+[ Upstream commit 8fee6d5ad5fa18c270eedb2a2cdf58dbadefb94b ]
+
+PPS was not stopped in `fec_ptp_stop()`, called when
+the adapter was removed. Consequentially, you couldn't
+safely reload the driver with the PPS signal on.
+
+Fixes: 32cba57ba74b ("net: fec: introduce fec_ptp_stop and use in probe fail path")
+Reviewed-by: Fabio Estevam <festevam@gmail.com>
+Link: https://lore.kernel.org/netdev/CAOMZO5BzcZR8PwKKwBssQq_wAGzVgf1ffwe_nhpQJjviTdxy-w@mail.gmail.com/T/#m01dcb810bfc451a492140f6797ca77443d0cb79f
+Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20240807080956.2556602-1-csokas.bence@prolan.hu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_ptp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
+index e32f6724f5681..2e4f3e1782a25 100644
+--- a/drivers/net/ethernet/freescale/fec_ptp.c
++++ b/drivers/net/ethernet/freescale/fec_ptp.c
+@@ -775,6 +775,9 @@ void fec_ptp_stop(struct platform_device *pdev)
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct fec_enet_private *fep = netdev_priv(ndev);
++      if (fep->pps_enable)
++              fec_ptp_enable_pps(fep, 0);
++
+       cancel_delayed_work_sync(&fep->time_keep);
+       hrtimer_cancel(&fep->perout_timer);
+       if (fep->ptp_clock)
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-linkwatch-use-system_unbound_wq.patch b/queue-6.10/net-linkwatch-use-system_unbound_wq.patch
new file mode 100644 (file)
index 0000000..25427a7
--- /dev/null
@@ -0,0 +1,52 @@
+From 9c8f913bb330d9a6562b9335958ccbb3413ab95d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 08:58:21 +0000
+Subject: net: linkwatch: use system_unbound_wq
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3e7917c0cdad835a5121520fc5686d954b7a61ab ]
+
+linkwatch_event() grabs possibly very contended RTNL mutex.
+
+system_wq is not suitable for such work.
+
+Inspired by many noisy syzbot reports.
+
+3 locks held by kworker/0:7/5266:
+ #0: ffff888015480948 ((wq_completion)events){+.+.}-{0:0}, at: process_one_work kernel/workqueue.c:3206 [inline]
+ #0: ffff888015480948 ((wq_completion)events){+.+.}-{0:0}, at: process_scheduled_works+0x90a/0x1830 kernel/workqueue.c:3312
+ #1: ffffc90003f6fd00 ((linkwatch_work).work){+.+.}-{0:0}, at: process_one_work kernel/workqueue.c:3207 [inline]
+ , at: process_scheduled_works+0x945/0x1830 kernel/workqueue.c:3312
+ #2: ffffffff8fa6f208 (rtnl_mutex){+.+.}-{3:3}, at: linkwatch_event+0xe/0x60 net/core/link_watch.c:276
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20240805085821.1616528-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/link_watch.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/link_watch.c b/net/core/link_watch.c
+index 8ec35194bfcb8..ab150641142aa 100644
+--- a/net/core/link_watch.c
++++ b/net/core/link_watch.c
+@@ -148,9 +148,9 @@ static void linkwatch_schedule_work(int urgent)
+        * override the existing timer.
+        */
+       if (test_bit(LW_URGENT, &linkwatch_flags))
+-              mod_delayed_work(system_wq, &linkwatch_work, 0);
++              mod_delayed_work(system_unbound_wq, &linkwatch_work, 0);
+       else
+-              schedule_delayed_work(&linkwatch_work, delay);
++              queue_delayed_work(system_unbound_wq, &linkwatch_work, delay);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-mlx5e-shampo-fix-invalid-wq-linked-list-unlink.patch b/queue-6.10/net-mlx5e-shampo-fix-invalid-wq-linked-list-unlink.patch
new file mode 100644 (file)
index 0000000..7848470
--- /dev/null
@@ -0,0 +1,44 @@
+From 249809b1f8b24bf6aec02e7ce3d455bb954958d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 00:22:08 +0300
+Subject: net/mlx5e: SHAMPO, Fix invalid WQ linked list unlink
+
+From: Dragos Tatulea <dtatulea@nvidia.com>
+
+[ Upstream commit fba8334721e266f92079632598e46e5f89082f30 ]
+
+When all the strides in a WQE have been consumed, the WQE is unlinked
+from the WQ linked list (mlx5_wq_ll_pop()). For SHAMPO, it is possible
+to receive CQEs with 0 consumed strides for the same WQE even after the
+WQE is fully consumed and unlinked. This triggers an additional unlink
+for the same wqe which corrupts the linked list.
+
+Fix this scenario by accepting 0 sized consumed strides without
+unlinking the WQE again.
+
+Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://lore.kernel.org/r/20240603212219.1037656-4-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+index b5333da20e8a7..cdc84a27a04ed 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+@@ -2374,6 +2374,9 @@ static void mlx5e_handle_rx_cqe_mpwrq_shampo(struct mlx5e_rq *rq, struct mlx5_cq
+       if (likely(wi->consumed_strides < rq->mpwqe.num_strides))
+               return;
++      if (unlikely(!cstrides))
++              return;
++
+       wq  = &rq->mpwqe.wq;
+       wqe = mlx5_wq_ll_get_wqe(wq, wqe_id);
+       mlx5_wq_ll_pop(wq, cqe->wqe_id, &wqe->next.next_wqe_index);
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-pse-pd-tps23881-fix-the-device-id-check.patch b/queue-6.10/net-pse-pd-tps23881-fix-the-device-id-check.patch
new file mode 100644 (file)
index 0000000..6d5e797
--- /dev/null
@@ -0,0 +1,50 @@
+From 8e55abe94209a3f0f393ba56da6f21124dbbe2dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 15:42:14 +0000
+Subject: net: pse-pd: tps23881: Fix the device ID check
+
+From: Kyle Swenson <kyle.swenson@est.tech>
+
+[ Upstream commit 89108cb5c28527c1882df2987394e5c261a1f4aa ]
+
+The DEVID register contains two pieces of information: the device ID in
+the upper nibble, and the silicon revision number in the lower nibble.
+The driver should work fine with any silicon revision, so let's mask
+that out in the device ID check.
+
+Fixes: 20e6d190ffe1 ("net: pse-pd: Add TI TPS23881 PSE controller driver")
+Signed-off-by: Kyle Swenson <kyle.swenson@est.tech>
+Reviewed-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Link: https://patch.msgid.link/20240731154152.4020668-1-kyle.swenson@est.tech
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/pse-pd/tps23881.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/pse-pd/tps23881.c b/drivers/net/pse-pd/tps23881.c
+index 98ffbb1bbf13c..e95109c1130dc 100644
+--- a/drivers/net/pse-pd/tps23881.c
++++ b/drivers/net/pse-pd/tps23881.c
+@@ -29,6 +29,8 @@
+ #define TPS23881_REG_TPON     BIT(0)
+ #define TPS23881_REG_FWREV    0x41
+ #define TPS23881_REG_DEVID    0x43
++#define TPS23881_REG_DEVID_MASK       0xF0
++#define TPS23881_DEVICE_ID    0x02
+ #define TPS23881_REG_SRAM_CTRL        0x60
+ #define TPS23881_REG_SRAM_DATA        0x61
+@@ -750,7 +752,7 @@ static int tps23881_i2c_probe(struct i2c_client *client)
+       if (ret < 0)
+               return ret;
+-      if (ret != 0x22) {
++      if (FIELD_GET(TPS23881_REG_DEVID_MASK, ret) != TPS23881_DEVICE_ID) {
+               dev_err(dev, "Wrong device ID\n");
+               return -ENXIO;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-pse-pd-tps23881-include-missing-bitfield.h-heade.patch b/queue-6.10/net-pse-pd-tps23881-include-missing-bitfield.h-heade.patch
new file mode 100644 (file)
index 0000000..002db22
--- /dev/null
@@ -0,0 +1,42 @@
+From 05c3d118aef4464fad29d0171d84e21b2b3e6dbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 09:54:22 +0200
+Subject: net: pse-pd: tps23881: include missing bitfield.h header
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit a70b637db15b4de25af3c5946c4399144b3bc241 ]
+
+Using FIELD_GET() fails in configurations that don't already include
+the header file indirectly:
+
+drivers/net/pse-pd/tps23881.c: In function 'tps23881_i2c_probe':
+drivers/net/pse-pd/tps23881.c:755:13: error: implicit declaration of function 'FIELD_GET' [-Wimplicit-function-declaration]
+  755 |         if (FIELD_GET(TPS23881_REG_DEVID_MASK, ret) != TPS23881_DEVICE_ID) {
+      |             ^~~~~~~~~
+
+Fixes: 89108cb5c285 ("net: pse-pd: tps23881: Fix the device ID check")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Link: https://patch.msgid.link/20240807075455.2055224-1-arnd@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/pse-pd/tps23881.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/pse-pd/tps23881.c b/drivers/net/pse-pd/tps23881.c
+index e95109c1130dc..2d1c2e5706f8b 100644
+--- a/drivers/net/pse-pd/tps23881.c
++++ b/drivers/net/pse-pd/tps23881.c
+@@ -5,6 +5,7 @@
+  * Copyright (c) 2023 Bootlin, Kory Maincent <kory.maincent@bootlin.com>
+  */
++#include <linux/bitfield.h>
+ #include <linux/delay.h>
+ #include <linux/firmware.h>
+ #include <linux/i2c.h>
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-reference-bpf_redirect_info-via-task_struct-on-p.patch b/queue-6.10/net-reference-bpf_redirect_info-via-task_struct-on-p.patch
new file mode 100644 (file)
index 0000000..336e0d3
--- /dev/null
@@ -0,0 +1,681 @@
+From 12b7a3a48179413fe2ed1554c15a9fdd40c7faae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jun 2024 15:22:04 +0200
+Subject: net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 401cb7dae8130fd34eb84648e02ab4c506df7d5e ]
+
+The XDP redirect process is two staged:
+- bpf_prog_run_xdp() is invoked to run a eBPF program which inspects the
+  packet and makes decisions. While doing that, the per-CPU variable
+  bpf_redirect_info is used.
+
+- Afterwards xdp_do_redirect() is invoked and accesses bpf_redirect_info
+  and it may also access other per-CPU variables like xskmap_flush_list.
+
+At the very end of the NAPI callback, xdp_do_flush() is invoked which
+does not access bpf_redirect_info but will touch the individual per-CPU
+lists.
+
+The per-CPU variables are only used in the NAPI callback hence disabling
+bottom halves is the only protection mechanism. Users from preemptible
+context (like cpu_map_kthread_run()) explicitly disable bottom halves
+for protections reasons.
+Without locking in local_bh_disable() on PREEMPT_RT this data structure
+requires explicit locking.
+
+PREEMPT_RT has forced-threaded interrupts enabled and every
+NAPI-callback runs in a thread. If each thread has its own data
+structure then locking can be avoided.
+
+Create a struct bpf_net_context which contains struct bpf_redirect_info.
+Define the variable on stack, use bpf_net_ctx_set() to save a pointer to
+it, bpf_net_ctx_clear() removes it again.
+The bpf_net_ctx_set() may nest. For instance a function can be used from
+within NET_RX_SOFTIRQ/ net_rx_action which uses bpf_net_ctx_set() and
+NET_TX_SOFTIRQ which does not. Therefore only the first invocations
+updates the pointer.
+Use bpf_net_ctx_get_ri() as a wrapper to retrieve the current struct
+bpf_redirect_info. The returned data structure is zero initialized to
+ensure nothing is leaked from stack. This is done on first usage of the
+struct. bpf_net_ctx_set() sets bpf_redirect_info::kern_flags to 0 to
+note that initialisation is required. First invocation of
+bpf_net_ctx_get_ri() will memset() the data structure and update
+bpf_redirect_info::kern_flags.
+bpf_redirect_info::nh is excluded from memset because it is only used
+once BPF_F_NEIGH is set which also sets the nh member. The kern_flags is
+moved past nh to exclude it from memset.
+
+The pointer to bpf_net_context is saved task's task_struct. Using
+always the bpf_net_context approach has the advantage that there is
+almost zero differences between PREEMPT_RT and non-PREEMPT_RT builds.
+
+Cc: Andrii Nakryiko <andrii@kernel.org>
+Cc: Eduard Zingerman <eddyz87@gmail.com>
+Cc: Hao Luo <haoluo@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: John Fastabend <john.fastabend@gmail.com>
+Cc: KP Singh <kpsingh@kernel.org>
+Cc: Martin KaFai Lau <martin.lau@linux.dev>
+Cc: Song Liu <song@kernel.org>
+Cc: Stanislav Fomichev <sdf@google.com>
+Cc: Yonghong Song <yonghong.song@linux.dev>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Acked-by: Jesper Dangaard Brouer <hawk@kernel.org>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20240620132727.660738-15-bigeasy@linutronix.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/filter.h | 56 ++++++++++++++++++++++++++++++++++--------
+ include/linux/sched.h  |  3 +++
+ kernel/bpf/cpumap.c    |  3 +++
+ kernel/bpf/devmap.c    |  9 ++++++-
+ kernel/fork.c          |  1 +
+ net/bpf/test_run.c     | 11 ++++++++-
+ net/core/dev.c         | 29 +++++++++++++++++++++-
+ net/core/filter.c      | 44 +++++++++------------------------
+ net/core/lwt_bpf.c     |  3 +++
+ 9 files changed, 114 insertions(+), 45 deletions(-)
+
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index 5669da513cd7c..b2dc932fdc35e 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -733,21 +733,59 @@ struct bpf_nh_params {
+       };
+ };
++/* flags for bpf_redirect_info kern_flags */
++#define BPF_RI_F_RF_NO_DIRECT BIT(0)  /* no napi_direct on return_frame */
++#define BPF_RI_F_RI_INIT      BIT(1)
++
+ struct bpf_redirect_info {
+       u64 tgt_index;
+       void *tgt_value;
+       struct bpf_map *map;
+       u32 flags;
+-      u32 kern_flags;
+       u32 map_id;
+       enum bpf_map_type map_type;
+       struct bpf_nh_params nh;
++      u32 kern_flags;
+ };
+-DECLARE_PER_CPU(struct bpf_redirect_info, bpf_redirect_info);
++struct bpf_net_context {
++      struct bpf_redirect_info ri;
++};
+-/* flags for bpf_redirect_info kern_flags */
+-#define BPF_RI_F_RF_NO_DIRECT BIT(0)  /* no napi_direct on return_frame */
++static inline struct bpf_net_context *bpf_net_ctx_set(struct bpf_net_context *bpf_net_ctx)
++{
++      struct task_struct *tsk = current;
++
++      if (tsk->bpf_net_context != NULL)
++              return NULL;
++      bpf_net_ctx->ri.kern_flags = 0;
++
++      tsk->bpf_net_context = bpf_net_ctx;
++      return bpf_net_ctx;
++}
++
++static inline void bpf_net_ctx_clear(struct bpf_net_context *bpf_net_ctx)
++{
++      if (bpf_net_ctx)
++              current->bpf_net_context = NULL;
++}
++
++static inline struct bpf_net_context *bpf_net_ctx_get(void)
++{
++      return current->bpf_net_context;
++}
++
++static inline struct bpf_redirect_info *bpf_net_ctx_get_ri(void)
++{
++      struct bpf_net_context *bpf_net_ctx = bpf_net_ctx_get();
++
++      if (!(bpf_net_ctx->ri.kern_flags & BPF_RI_F_RI_INIT)) {
++              memset(&bpf_net_ctx->ri, 0, offsetof(struct bpf_net_context, ri.nh));
++              bpf_net_ctx->ri.kern_flags |= BPF_RI_F_RI_INIT;
++      }
++
++      return &bpf_net_ctx->ri;
++}
+ /* Compute the linear packet data range [data, data_end) which
+  * will be accessed by various program types (cls_bpf, act_bpf,
+@@ -1018,25 +1056,23 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
+                                      const struct bpf_insn *patch, u32 len);
+ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt);
+-void bpf_clear_redirect_map(struct bpf_map *map);
+-
+ static inline bool xdp_return_frame_no_direct(void)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       return ri->kern_flags & BPF_RI_F_RF_NO_DIRECT;
+ }
+ static inline void xdp_set_return_frame_no_direct(void)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       ri->kern_flags |= BPF_RI_F_RF_NO_DIRECT;
+ }
+ static inline void xdp_clear_return_frame_no_direct(void)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       ri->kern_flags &= ~BPF_RI_F_RF_NO_DIRECT;
+ }
+@@ -1592,7 +1628,7 @@ static __always_inline long __bpf_xdp_redirect_map(struct bpf_map *map, u64 inde
+                                                  u64 flags, const u64 flag_mask,
+                                                  void *lookup_elem(struct bpf_map *map, u32 key))
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       const u64 action_mask = XDP_ABORTED | XDP_DROP | XDP_PASS | XDP_TX;
+       /* Lower bits of the flags are used as return code on lookup failure */
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index 76214d7c819de..550d9dd8ceb58 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -53,6 +53,7 @@ struct bio_list;
+ struct blk_plug;
+ struct bpf_local_storage;
+ struct bpf_run_ctx;
++struct bpf_net_context;
+ struct capture_control;
+ struct cfs_rq;
+ struct fs_struct;
+@@ -1506,6 +1507,8 @@ struct task_struct {
+       /* Used for BPF run context */
+       struct bpf_run_ctx              *bpf_ctx;
+ #endif
++      /* Used by BPF for per-TASK xdp storage */
++      struct bpf_net_context          *bpf_net_context;
+ #ifdef CONFIG_GCC_PLUGIN_STACKLEAK
+       unsigned long                   lowest_stack;
+diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c
+index a8e34416e960f..66974bd027109 100644
+--- a/kernel/bpf/cpumap.c
++++ b/kernel/bpf/cpumap.c
+@@ -240,12 +240,14 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
+                               int xdp_n, struct xdp_cpumap_stats *stats,
+                               struct list_head *list)
+ {
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       int nframes;
+       if (!rcpu->prog)
+               return xdp_n;
+       rcu_read_lock_bh();
++      bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+       nframes = cpu_map_bpf_prog_run_xdp(rcpu, frames, xdp_n, stats);
+@@ -255,6 +257,7 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
+       if (unlikely(!list_empty(list)))
+               cpu_map_bpf_prog_run_skb(rcpu, list, stats);
++      bpf_net_ctx_clear(bpf_net_ctx);
+       rcu_read_unlock_bh(); /* resched point, may call do_softirq() */
+       return nframes;
+diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
+index 7f3b34452243c..fbfdfb60db8d7 100644
+--- a/kernel/bpf/devmap.c
++++ b/kernel/bpf/devmap.c
+@@ -196,7 +196,14 @@ static void dev_map_free(struct bpf_map *map)
+       list_del_rcu(&dtab->list);
+       spin_unlock(&dev_map_lock);
+-      bpf_clear_redirect_map(map);
++      /* bpf_redirect_info->map is assigned in __bpf_xdp_redirect_map()
++       * during NAPI callback and cleared after the XDP redirect. There is no
++       * explicit RCU read section which protects bpf_redirect_info->map but
++       * local_bh_disable() also marks the beginning an RCU section. This
++       * makes the complete softirq callback RCU protected. Thus after
++       * following synchronize_rcu() there no bpf_redirect_info->map == map
++       * assignment.
++       */
+       synchronize_rcu();
+       /* Make sure prior __dev_map_entry_free() have completed. */
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 99076dbe27d83..f314bdd7e6108 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2355,6 +2355,7 @@ __latent_entropy struct task_struct *copy_process(
+       RCU_INIT_POINTER(p->bpf_storage, NULL);
+       p->bpf_ctx = NULL;
+ #endif
++      p->bpf_net_context =  NULL;
+       /* Perform scheduler related setup. Assign this task to a CPU. */
+       retval = sched_fork(clone_flags, p);
+diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
+index 36ae54f57bf57..a6d7f790cdda8 100644
+--- a/net/bpf/test_run.c
++++ b/net/bpf/test_run.c
+@@ -283,9 +283,10 @@ static int xdp_recv_frames(struct xdp_frame **frames, int nframes,
+ static int xdp_test_run_batch(struct xdp_test_data *xdp, struct bpf_prog *prog,
+                             u32 repeat)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       int err = 0, act, ret, i, nframes = 0, batch_sz;
+       struct xdp_frame **frames = xdp->frames;
++      struct bpf_redirect_info *ri;
+       struct xdp_page_head *head;
+       struct xdp_frame *frm;
+       bool redirect = false;
+@@ -295,6 +296,8 @@ static int xdp_test_run_batch(struct xdp_test_data *xdp, struct bpf_prog *prog,
+       batch_sz = min_t(u32, repeat, xdp->batch_size);
+       local_bh_disable();
++      bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
++      ri = bpf_net_ctx_get_ri();
+       xdp_set_return_frame_no_direct();
+       for (i = 0; i < batch_sz; i++) {
+@@ -359,6 +362,7 @@ static int xdp_test_run_batch(struct xdp_test_data *xdp, struct bpf_prog *prog,
+       }
+       xdp_clear_return_frame_no_direct();
++      bpf_net_ctx_clear(bpf_net_ctx);
+       local_bh_enable();
+       return err;
+ }
+@@ -394,6 +398,7 @@ static int bpf_test_run_xdp_live(struct bpf_prog *prog, struct xdp_buff *ctx,
+ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
+                       u32 *retval, u32 *time, bool xdp)
+ {
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       struct bpf_prog_array_item item = {.prog = prog};
+       struct bpf_run_ctx *old_ctx;
+       struct bpf_cg_run_ctx run_ctx;
+@@ -419,10 +424,14 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
+       do {
+               run_ctx.prog_item = &item;
+               local_bh_disable();
++              bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
++
+               if (xdp)
+                       *retval = bpf_prog_run_xdp(prog, ctx);
+               else
+                       *retval = bpf_prog_run(prog, ctx);
++
++              bpf_net_ctx_clear(bpf_net_ctx);
+               local_bh_enable();
+       } while (bpf_test_timer_continue(&t, 1, repeat, &ret, time));
+       bpf_reset_run_ctx(old_ctx);
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 2b4819b610b8a..195aa4d488bec 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -4029,10 +4029,13 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
+ {
+       struct bpf_mprog_entry *entry = rcu_dereference_bh(skb->dev->tcx_ingress);
+       enum skb_drop_reason drop_reason = SKB_DROP_REASON_TC_INGRESS;
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       int sch_ret;
+       if (!entry)
+               return skb;
++
++      bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+       if (*pt_prev) {
+               *ret = deliver_skb(skb, *pt_prev, orig_dev);
+               *pt_prev = NULL;
+@@ -4061,10 +4064,12 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
+                       break;
+               }
+               *ret = NET_RX_SUCCESS;
++              bpf_net_ctx_clear(bpf_net_ctx);
+               return NULL;
+       case TC_ACT_SHOT:
+               kfree_skb_reason(skb, drop_reason);
+               *ret = NET_RX_DROP;
++              bpf_net_ctx_clear(bpf_net_ctx);
+               return NULL;
+       /* used by tc_run */
+       case TC_ACT_STOLEN:
+@@ -4074,8 +4079,10 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
+               fallthrough;
+       case TC_ACT_CONSUMED:
+               *ret = NET_RX_SUCCESS;
++              bpf_net_ctx_clear(bpf_net_ctx);
+               return NULL;
+       }
++      bpf_net_ctx_clear(bpf_net_ctx);
+       return skb;
+ }
+@@ -4085,11 +4092,14 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
+ {
+       struct bpf_mprog_entry *entry = rcu_dereference_bh(dev->tcx_egress);
+       enum skb_drop_reason drop_reason = SKB_DROP_REASON_TC_EGRESS;
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       int sch_ret;
+       if (!entry)
+               return skb;
++      bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
++
+       /* qdisc_skb_cb(skb)->pkt_len & tcx_set_ingress() was
+        * already set by the caller.
+        */
+@@ -4105,10 +4115,12 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
+               /* No need to push/pop skb's mac_header here on egress! */
+               skb_do_redirect(skb);
+               *ret = NET_XMIT_SUCCESS;
++              bpf_net_ctx_clear(bpf_net_ctx);
+               return NULL;
+       case TC_ACT_SHOT:
+               kfree_skb_reason(skb, drop_reason);
+               *ret = NET_XMIT_DROP;
++              bpf_net_ctx_clear(bpf_net_ctx);
+               return NULL;
+       /* used by tc_run */
+       case TC_ACT_STOLEN:
+@@ -4118,8 +4130,10 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
+               fallthrough;
+       case TC_ACT_CONSUMED:
+               *ret = NET_XMIT_SUCCESS;
++              bpf_net_ctx_clear(bpf_net_ctx);
+               return NULL;
+       }
++      bpf_net_ctx_clear(bpf_net_ctx);
+       return skb;
+ }
+@@ -6301,6 +6315,7 @@ enum {
+ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock,
+                          unsigned flags, u16 budget)
+ {
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       bool skip_schedule = false;
+       unsigned long timeout;
+       int rc;
+@@ -6318,6 +6333,7 @@ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock,
+       clear_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state);
+       local_bh_disable();
++      bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+       if (flags & NAPI_F_PREFER_BUSY_POLL) {
+               napi->defer_hard_irqs_count = READ_ONCE(napi->dev->napi_defer_hard_irqs);
+@@ -6340,6 +6356,7 @@ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock,
+       netpoll_poll_unlock(have_poll_lock);
+       if (rc == budget)
+               __busy_poll_stop(napi, skip_schedule);
++      bpf_net_ctx_clear(bpf_net_ctx);
+       local_bh_enable();
+ }
+@@ -6349,6 +6366,7 @@ static void __napi_busy_loop(unsigned int napi_id,
+ {
+       unsigned long start_time = loop_end ? busy_loop_current_time() : 0;
+       int (*napi_poll)(struct napi_struct *napi, int budget);
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       void *have_poll_lock = NULL;
+       struct napi_struct *napi;
+@@ -6367,6 +6385,7 @@ static void __napi_busy_loop(unsigned int napi_id,
+               int work = 0;
+               local_bh_disable();
++              bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+               if (!napi_poll) {
+                       unsigned long val = READ_ONCE(napi->state);
+@@ -6397,6 +6416,7 @@ static void __napi_busy_loop(unsigned int napi_id,
+                       __NET_ADD_STATS(dev_net(napi->dev),
+                                       LINUX_MIB_BUSYPOLLRXPACKETS, work);
+               skb_defer_free_flush(this_cpu_ptr(&softnet_data));
++              bpf_net_ctx_clear(bpf_net_ctx);
+               local_bh_enable();
+               if (!loop_end || loop_end(loop_end_arg, start_time))
+@@ -6824,6 +6844,7 @@ static int napi_thread_wait(struct napi_struct *napi)
+ static void napi_threaded_poll_loop(struct napi_struct *napi)
+ {
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       struct softnet_data *sd;
+       unsigned long last_qs = jiffies;
+@@ -6832,6 +6853,8 @@ static void napi_threaded_poll_loop(struct napi_struct *napi)
+               void *have;
+               local_bh_disable();
++              bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
++
+               sd = this_cpu_ptr(&softnet_data);
+               sd->in_napi_threaded_poll = true;
+@@ -6847,6 +6870,7 @@ static void napi_threaded_poll_loop(struct napi_struct *napi)
+                       net_rps_action_and_irq_enable(sd);
+               }
+               skb_defer_free_flush(sd);
++              bpf_net_ctx_clear(bpf_net_ctx);
+               local_bh_enable();
+               if (!repoll)
+@@ -6872,10 +6896,12 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
+       struct softnet_data *sd = this_cpu_ptr(&softnet_data);
+       unsigned long time_limit = jiffies +
+               usecs_to_jiffies(READ_ONCE(net_hotdata.netdev_budget_usecs));
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       int budget = READ_ONCE(net_hotdata.netdev_budget);
+       LIST_HEAD(list);
+       LIST_HEAD(repoll);
++      bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+ start:
+       sd->in_net_rx_action = true;
+       local_irq_disable();
+@@ -6928,7 +6954,8 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
+               sd->in_net_rx_action = false;
+       net_rps_action_and_irq_enable(sd);
+-end:;
++end:
++      bpf_net_ctx_clear(bpf_net_ctx);
+ }
+ struct netdev_adjacent {
+diff --git a/net/core/filter.c b/net/core/filter.c
+index 110692c1dd95a..05296c289cefb 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -2476,9 +2476,6 @@ static const struct bpf_func_proto bpf_clone_redirect_proto = {
+       .arg3_type      = ARG_ANYTHING,
+ };
+-DEFINE_PER_CPU(struct bpf_redirect_info, bpf_redirect_info);
+-EXPORT_PER_CPU_SYMBOL_GPL(bpf_redirect_info);
+-
+ static struct net_device *skb_get_peer_dev(struct net_device *dev)
+ {
+       const struct net_device_ops *ops = dev->netdev_ops;
+@@ -2491,7 +2488,7 @@ static struct net_device *skb_get_peer_dev(struct net_device *dev)
+ int skb_do_redirect(struct sk_buff *skb)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       struct net *net = dev_net(skb->dev);
+       struct net_device *dev;
+       u32 flags = ri->flags;
+@@ -2524,7 +2521,7 @@ int skb_do_redirect(struct sk_buff *skb)
+ BPF_CALL_2(bpf_redirect, u32, ifindex, u64, flags)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       if (unlikely(flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL)))
+               return TC_ACT_SHOT;
+@@ -2545,7 +2542,7 @@ static const struct bpf_func_proto bpf_redirect_proto = {
+ BPF_CALL_2(bpf_redirect_peer, u32, ifindex, u64, flags)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       if (unlikely(flags))
+               return TC_ACT_SHOT;
+@@ -2567,7 +2564,7 @@ static const struct bpf_func_proto bpf_redirect_peer_proto = {
+ BPF_CALL_4(bpf_redirect_neigh, u32, ifindex, struct bpf_redir_neigh *, params,
+          int, plen, u64, flags)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       if (unlikely((plen && plen < sizeof(*params)) || flags))
+               return TC_ACT_SHOT;
+@@ -4300,30 +4297,13 @@ void xdp_do_check_flushed(struct napi_struct *napi)
+ }
+ #endif
+-void bpf_clear_redirect_map(struct bpf_map *map)
+-{
+-      struct bpf_redirect_info *ri;
+-      int cpu;
+-
+-      for_each_possible_cpu(cpu) {
+-              ri = per_cpu_ptr(&bpf_redirect_info, cpu);
+-              /* Avoid polluting remote cacheline due to writes if
+-               * not needed. Once we pass this test, we need the
+-               * cmpxchg() to make sure it hasn't been changed in
+-               * the meantime by remote CPU.
+-               */
+-              if (unlikely(READ_ONCE(ri->map) == map))
+-                      cmpxchg(&ri->map, map, NULL);
+-      }
+-}
+-
+ DEFINE_STATIC_KEY_FALSE(bpf_master_redirect_enabled_key);
+ EXPORT_SYMBOL_GPL(bpf_master_redirect_enabled_key);
+ u32 xdp_master_redirect(struct xdp_buff *xdp)
+ {
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       struct net_device *master, *slave;
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
+       master = netdev_master_upper_dev_get_rcu(xdp->rxq->dev);
+       slave = master->netdev_ops->ndo_xdp_get_xmit_slave(master, xdp);
+@@ -4395,7 +4375,7 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
+                       map = READ_ONCE(ri->map);
+                       /* The map pointer is cleared when the map is being torn
+-                       * down by bpf_clear_redirect_map()
++                       * down by dev_map_free()
+                        */
+                       if (unlikely(!map)) {
+                               err = -ENOENT;
+@@ -4440,7 +4420,7 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
+ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
+                   struct bpf_prog *xdp_prog)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       enum bpf_map_type map_type = ri->map_type;
+       if (map_type == BPF_MAP_TYPE_XSKMAP)
+@@ -4454,7 +4434,7 @@ EXPORT_SYMBOL_GPL(xdp_do_redirect);
+ int xdp_do_redirect_frame(struct net_device *dev, struct xdp_buff *xdp,
+                         struct xdp_frame *xdpf, struct bpf_prog *xdp_prog)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       enum bpf_map_type map_type = ri->map_type;
+       if (map_type == BPF_MAP_TYPE_XSKMAP)
+@@ -4471,7 +4451,7 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
+                                      enum bpf_map_type map_type, u32 map_id,
+                                      u32 flags)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       struct bpf_map *map;
+       int err;
+@@ -4483,7 +4463,7 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
+                       map = READ_ONCE(ri->map);
+                       /* The map pointer is cleared when the map is being torn
+-                       * down by bpf_clear_redirect_map()
++                       * down by dev_map_free()
+                        */
+                       if (unlikely(!map)) {
+                               err = -ENOENT;
+@@ -4525,7 +4505,7 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
+ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
+                           struct xdp_buff *xdp, struct bpf_prog *xdp_prog)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       enum bpf_map_type map_type = ri->map_type;
+       void *fwd = ri->tgt_value;
+       u32 map_id = ri->map_id;
+@@ -4561,7 +4541,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
+ BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags)
+ {
+-      struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++      struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+       if (unlikely(flags))
+               return XDP_ABORTED;
+diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
+index 4a0797f0a154b..5350dce2e52d6 100644
+--- a/net/core/lwt_bpf.c
++++ b/net/core/lwt_bpf.c
+@@ -38,6 +38,7 @@ static inline struct bpf_lwt *bpf_lwt_lwtunnel(struct lwtunnel_state *lwt)
+ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
+                      struct dst_entry *dst, bool can_redirect)
+ {
++      struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+       int ret;
+       /* Migration disable and BH disable are needed to protect per-cpu
+@@ -45,6 +46,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
+        */
+       migrate_disable();
+       local_bh_disable();
++      bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+       bpf_compute_data_pointers(skb);
+       ret = bpf_prog_run_save_cb(lwt->prog, skb);
+@@ -77,6 +79,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
+               break;
+       }
++      bpf_net_ctx_clear(bpf_net_ctx);
+       local_bh_enable();
+       migrate_enable();
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-smc-add-the-max-value-of-fallback-reason-count.patch b/queue-6.10/net-smc-add-the-max-value-of-fallback-reason-count.patch
new file mode 100644 (file)
index 0000000..468cf9a
--- /dev/null
@@ -0,0 +1,42 @@
+From aa4bc1c51cd7d1ddf365ba2035b0b3df1c672833 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 12:38:56 +0800
+Subject: net/smc: add the max value of fallback reason count
+
+From: Zhengchao Shao <shaozhengchao@huawei.com>
+
+[ Upstream commit d27a835f41d947f62e6a95e89ba523299c9e6437 ]
+
+The number of fallback reasons defined in the smc_clc.h file has reached
+36. For historical reasons, some are no longer quoted, and there's 33
+actually in use. So, add the max value of fallback reason count to 36.
+
+Fixes: 6ac1e6563f59 ("net/smc: support smc v2.x features validate")
+Fixes: 7f0620b9940b ("net/smc: support max connections per lgr negotiation")
+Fixes: 69b888e3bb4b ("net/smc: support max links per lgr negotiation in clc handshake")
+Signed-off-by: Zhengchao Shao <shaozhengchao@huawei.com>
+Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
+Reviewed-by: D. Wythe <alibuda@linux.alibaba.com>
+Link: https://patch.msgid.link/20240805043856.565677-1-shaozhengchao@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_stats.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_stats.h b/net/smc/smc_stats.h
+index 9d32058db2b5d..e19177ce40923 100644
+--- a/net/smc/smc_stats.h
++++ b/net/smc/smc_stats.h
+@@ -19,7 +19,7 @@
+ #include "smc_clc.h"
+-#define SMC_MAX_FBACK_RSN_CNT 30
++#define SMC_MAX_FBACK_RSN_CNT 36
+ enum {
+       SMC_BUF_8K,
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-stmmac-qcom-ethqos-enable-sgmii-loopback-during-.patch b/queue-6.10/net-stmmac-qcom-ethqos-enable-sgmii-loopback-during-.patch
new file mode 100644 (file)
index 0000000..a4b4be5
--- /dev/null
@@ -0,0 +1,120 @@
+From 517a8082696b6dc917e704b8aaa5fe512ef1924f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jul 2024 20:14:59 +0200
+Subject: net: stmmac: qcom-ethqos: enable SGMII loopback during DMA reset on
+ sa8775p-ride-r3
+
+From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+[ Upstream commit 3c466d6537b99f801b3f68af3d8124d4312437a0 ]
+
+On sa8775p-ride-r3 the RX clocks from the AQR115C PHY are not available at
+the time of the DMA reset. We can however extract the RX clock from the
+internal SERDES block. Once the link is up, we can revert to the
+previous state.
+
+The AQR115C PHY doesn't support in-band signalling so we can count on
+getting the link up notification and safely reuse existing callbacks
+which are already used by another HW quirk workaround which enables the
+functional clock to avoid a DMA reset due to timeout.
+
+Only enable loopback on revision 3 of the board - check the phy_mode to
+make sure.
+
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20240703181500.28491-3-brgl@bgdev.pl
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../stmicro/stmmac/dwmac-qcom-ethqos.c        | 23 +++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+index 466c4002f00d4..3a7f3a8b06718 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+@@ -21,6 +21,7 @@
+ #define RGMII_IO_MACRO_CONFIG2                0x1C
+ #define RGMII_IO_MACRO_DEBUG1         0x20
+ #define EMAC_SYSTEM_LOW_POWER_DEBUG   0x28
++#define EMAC_WRAPPER_SGMII_PHY_CNTRL1 0xf4
+ /* RGMII_IO_MACRO_CONFIG fields */
+ #define RGMII_CONFIG_FUNC_CLK_EN              BIT(30)
+@@ -79,6 +80,9 @@
+ #define ETHQOS_MAC_CTRL_SPEED_MODE            BIT(14)
+ #define ETHQOS_MAC_CTRL_PORT_SEL              BIT(15)
++/* EMAC_WRAPPER_SGMII_PHY_CNTRL1 bits */
++#define SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN   BIT(3)
++
+ #define SGMII_10M_RX_CLK_DVDR                 0x31
+ struct ethqos_emac_por {
+@@ -95,6 +99,7 @@ struct ethqos_emac_driver_data {
+       bool has_integrated_pcs;
+       u32 dma_addr_width;
+       struct dwmac4_addrs dwmac4_addrs;
++      bool needs_sgmii_loopback;
+ };
+ struct qcom_ethqos {
+@@ -114,6 +119,7 @@ struct qcom_ethqos {
+       unsigned int num_por;
+       bool rgmii_config_loopback_en;
+       bool has_emac_ge_3;
++      bool needs_sgmii_loopback;
+ };
+ static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
+@@ -191,8 +197,22 @@ ethqos_update_link_clk(struct qcom_ethqos *ethqos, unsigned int speed)
+       clk_set_rate(ethqos->link_clk, ethqos->link_clk_rate);
+ }
++static void
++qcom_ethqos_set_sgmii_loopback(struct qcom_ethqos *ethqos, bool enable)
++{
++      if (!ethqos->needs_sgmii_loopback ||
++          ethqos->phy_mode != PHY_INTERFACE_MODE_2500BASEX)
++              return;
++
++      rgmii_updatel(ethqos,
++                    SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN,
++                    enable ? SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN : 0,
++                    EMAC_WRAPPER_SGMII_PHY_CNTRL1);
++}
++
+ static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos)
+ {
++      qcom_ethqos_set_sgmii_loopback(ethqos, true);
+       rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN,
+                     RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG);
+ }
+@@ -277,6 +297,7 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_data = {
+       .has_emac_ge_3 = true,
+       .link_clk_name = "phyaux",
+       .has_integrated_pcs = true,
++      .needs_sgmii_loopback = true,
+       .dma_addr_width = 36,
+       .dwmac4_addrs = {
+               .dma_chan = 0x00008100,
+@@ -674,6 +695,7 @@ static void ethqos_fix_mac_speed(void *priv, unsigned int speed, unsigned int mo
+ {
+       struct qcom_ethqos *ethqos = priv;
++      qcom_ethqos_set_sgmii_loopback(ethqos, false);
+       ethqos->speed = speed;
+       ethqos_update_link_clk(ethqos, speed);
+       ethqos_configure(ethqos);
+@@ -809,6 +831,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
+       ethqos->num_por = data->num_por;
+       ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
+       ethqos->has_emac_ge_3 = data->has_emac_ge_3;
++      ethqos->needs_sgmii_loopback = data->needs_sgmii_loopback;
+       ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii");
+       if (IS_ERR(ethqos->link_clk))
+-- 
+2.43.0
+
diff --git a/queue-6.10/net-usb-qmi_wwan-fix-memory-leak-for-not-ip-packets.patch b/queue-6.10/net-usb-qmi_wwan-fix-memory-leak-for-not-ip-packets.patch
new file mode 100644 (file)
index 0000000..d446227
--- /dev/null
@@ -0,0 +1,38 @@
+From 9bd3cba08d7a9f2686e4c4b80a515d8ce29946ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 15:55:12 +0200
+Subject: net: usb: qmi_wwan: fix memory leak for not ip packets
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Daniele Palmas <dnlplm@gmail.com>
+
+[ Upstream commit 7ab107544b777c3bd7feb9fe447367d8edd5b202 ]
+
+Free the unused skb when not ip packets arrive.
+
+Fixes: c6adf77953bc ("net: usb: qmi_wwan: add qmap mux protocol support")
+Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
+Acked-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/qmi_wwan.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 386d62769dedb..cfda32047cffb 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -201,6 +201,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+                       break;
+               default:
+                       /* not ip - do not know what to do */
++                      kfree_skb(skbn);
+                       goto skip;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.10/nvme-apple-fix-device-reference-counting.patch b/queue-6.10/nvme-apple-fix-device-reference-counting.patch
new file mode 100644 (file)
index 0000000..0c2ea43
--- /dev/null
@@ -0,0 +1,87 @@
+From 88109c7f7caabe4f2a816e8918b2bacc920ddf76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 11:59:04 -0700
+Subject: nvme: apple: fix device reference counting
+
+From: Keith Busch <kbusch@kernel.org>
+
+[ Upstream commit b9ecbfa45516182cd062fecd286db7907ba84210 ]
+
+Drivers must call nvme_uninit_ctrl after a successful nvme_init_ctrl.
+Split the allocation side out to make the error handling boundary easier
+to navigate. The apple driver had been doing this wrong, leaking the
+controller device memory on a tagset failure.
+
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/apple.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
+index 0cfa39361d3b6..25ecc1a005c5a 100644
+--- a/drivers/nvme/host/apple.c
++++ b/drivers/nvme/host/apple.c
+@@ -1388,7 +1388,7 @@ static void devm_apple_nvme_mempool_destroy(void *data)
+       mempool_destroy(data);
+ }
+-static int apple_nvme_probe(struct platform_device *pdev)
++static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+       struct apple_nvme *anv;
+@@ -1396,7 +1396,7 @@ static int apple_nvme_probe(struct platform_device *pdev)
+       anv = devm_kzalloc(dev, sizeof(*anv), GFP_KERNEL);
+       if (!anv)
+-              return -ENOMEM;
++              return ERR_PTR(-ENOMEM);
+       anv->dev = get_device(dev);
+       anv->adminq.is_adminq = true;
+@@ -1516,10 +1516,26 @@ static int apple_nvme_probe(struct platform_device *pdev)
+               goto put_dev;
+       }
++      return anv;
++put_dev:
++      put_device(anv->dev);
++      return ERR_PTR(ret);
++}
++
++static int apple_nvme_probe(struct platform_device *pdev)
++{
++      struct apple_nvme *anv;
++      int ret;
++
++      anv = apple_nvme_alloc(pdev);
++      if (IS_ERR(anv))
++              return PTR_ERR(anv);
++
+       anv->ctrl.admin_q = blk_mq_alloc_queue(&anv->admin_tagset, NULL, NULL);
+       if (IS_ERR(anv->ctrl.admin_q)) {
+               ret = -ENOMEM;
+-              goto put_dev;
++              anv->ctrl.admin_q = NULL;
++              goto out_uninit_ctrl;
+       }
+       nvme_reset_ctrl(&anv->ctrl);
+@@ -1527,8 +1543,9 @@ static int apple_nvme_probe(struct platform_device *pdev)
+       return 0;
+-put_dev:
+-      put_device(anv->dev);
++out_uninit_ctrl:
++      nvme_uninit_ctrl(&anv->ctrl);
++      nvme_put_ctrl(&anv->ctrl);
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/pci-add-edimax-vendor-id-to-pci_ids.h.patch b/queue-6.10/pci-add-edimax-vendor-id-to-pci_ids.h.patch
new file mode 100644 (file)
index 0000000..1849dd7
--- /dev/null
@@ -0,0 +1,38 @@
+From cb4eaff98e9f6c9bb7b03ac27c7e4561423684e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jun 2024 08:55:01 +0900
+Subject: PCI: Add Edimax Vendor ID to pci_ids.h
+
+From: FUJITA Tomonori <fujita.tomonori@gmail.com>
+
+[ Upstream commit eee5528890d54b22b46f833002355a5ee94c3bb4 ]
+
+Add the Edimax Vendor ID (0x1432) for an ethernet driver for Tehuti
+Networks TN40xx chips. This ID can be used for Realtek 8180 and Ralink
+rt28xx wireless drivers.
+
+Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Link: https://patch.msgid.link/20240623235507.108147-2-fujita.tomonori@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/pci_ids.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 942a587bb97e3..677aea20d3e11 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -2126,6 +2126,8 @@
+ #define PCI_VENDOR_ID_CHELSIO         0x1425
++#define PCI_VENDOR_ID_EDIMAX          0x1432
++
+ #define PCI_VENDOR_ID_ADLINK          0x144a
+ #define PCI_VENDOR_ID_SAMSUNG         0x144d
+-- 
+2.43.0
+
diff --git a/queue-6.10/perf-x86-amd-use-try_cmpxchg-in-events-amd-un-core.c.patch b/queue-6.10/perf-x86-amd-use-try_cmpxchg-in-events-amd-un-core.c.patch
new file mode 100644 (file)
index 0000000..8765880
--- /dev/null
@@ -0,0 +1,76 @@
+From 7aea1d980841c78c46186af0ade988b6db7de3ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 12:16:14 +0200
+Subject: perf/x86/amd: Use try_cmpxchg() in events/amd/{un,}core.c
+
+From: Uros Bizjak <ubizjak@gmail.com>
+
+[ Upstream commit cd84351c8c1baec86342d784feb884ace007d51c ]
+
+Replace this pattern in events/amd/{un,}core.c:
+
+    cmpxchg(*ptr, old, new) == old
+
+... with the simpler and faster:
+
+    try_cmpxchg(*ptr, &old, new)
+
+The x86 CMPXCHG instruction returns success in the ZF flag, so this change
+saves a compare after the CMPXCHG.
+
+No functional change intended.
+
+Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Link: https://lore.kernel.org/r/20240425101708.5025-1-ubizjak@gmail.com
+Stable-dep-of: f73cefa3b72e ("perf/x86: Fix smp_processor_id()-in-preemptible warnings")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/amd/core.c   | 4 +++-
+ arch/x86/events/amd/uncore.c | 8 ++++++--
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
+index 1fc4ce44e743c..18bfe3451f3aa 100644
+--- a/arch/x86/events/amd/core.c
++++ b/arch/x86/events/amd/core.c
+@@ -433,7 +433,9 @@ static void __amd_put_nb_event_constraints(struct cpu_hw_events *cpuc,
+        * when we come here
+        */
+       for (i = 0; i < x86_pmu.num_counters; i++) {
+-              if (cmpxchg(nb->owners + i, event, NULL) == event)
++              struct perf_event *tmp = event;
++
++              if (try_cmpxchg(nb->owners + i, &tmp, NULL))
+                       break;
+       }
+ }
+diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
+index 5a4bfe9aea237..0bfde2ea5cb8c 100644
+--- a/arch/x86/events/amd/uncore.c
++++ b/arch/x86/events/amd/uncore.c
+@@ -162,7 +162,9 @@ static int amd_uncore_add(struct perf_event *event, int flags)
+       /* if not, take the first available counter */
+       hwc->idx = -1;
+       for (i = 0; i < pmu->num_counters; i++) {
+-              if (cmpxchg(&ctx->events[i], NULL, event) == NULL) {
++              struct perf_event *tmp = NULL;
++
++              if (try_cmpxchg(&ctx->events[i], &tmp, event)) {
+                       hwc->idx = i;
+                       break;
+               }
+@@ -196,7 +198,9 @@ static void amd_uncore_del(struct perf_event *event, int flags)
+       event->pmu->stop(event, PERF_EF_UPDATE);
+       for (i = 0; i < pmu->num_counters; i++) {
+-              if (cmpxchg(&ctx->events[i], event, NULL) == event)
++              struct perf_event *tmp = event;
++
++              if (try_cmpxchg(&ctx->events[i], &tmp, NULL))
+                       break;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/perf-x86-fix-smp_processor_id-in-preemptible-warning.patch b/queue-6.10/perf-x86-fix-smp_processor_id-in-preemptible-warning.patch
new file mode 100644 (file)
index 0000000..ac51287
--- /dev/null
@@ -0,0 +1,98 @@
+From ade587b6d2d92bc9bed6cb7147eb464f4066b969 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 06:09:28 +0800
+Subject: perf/x86: Fix smp_processor_id()-in-preemptible warnings
+
+From: Li Huafei <lihuafei1@huawei.com>
+
+[ Upstream commit f73cefa3b72eaa90abfc43bf6d68137ba059d4b1 ]
+
+The following bug was triggered on a system built with
+CONFIG_DEBUG_PREEMPT=y:
+
+ # echo p > /proc/sysrq-trigger
+
+ BUG: using smp_processor_id() in preemptible [00000000] code: sh/117
+ caller is perf_event_print_debug+0x1a/0x4c0
+ CPU: 3 UID: 0 PID: 117 Comm: sh Not tainted 6.11.0-rc1 #109
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
+ Call Trace:
+  <TASK>
+  dump_stack_lvl+0x4f/0x60
+  check_preemption_disabled+0xc8/0xd0
+  perf_event_print_debug+0x1a/0x4c0
+  __handle_sysrq+0x140/0x180
+  write_sysrq_trigger+0x61/0x70
+  proc_reg_write+0x4e/0x70
+  vfs_write+0xd0/0x430
+  ? handle_mm_fault+0xc8/0x240
+  ksys_write+0x9c/0xd0
+  do_syscall_64+0x96/0x190
+  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+
+This is because the commit d4b294bf84db ("perf/x86: Hybrid PMU support
+for counters") took smp_processor_id() outside the irq critical section.
+If a preemption occurs in perf_event_print_debug() and the task is
+migrated to another cpu, we may get incorrect pmu debug information.
+Move smp_processor_id() back inside the irq critical section to fix this
+issue.
+
+Fixes: d4b294bf84db ("perf/x86: Hybrid PMU support for counters")
+Signed-off-by: Li Huafei <lihuafei1@huawei.com>
+Reviewed-and-tested-by: K Prateek Nayak <kprateek.nayak@amd.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Link: https://lore.kernel.org/r/20240729220928.325449-1-lihuafei1@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/core.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
+index 0c51cfdf76092..83d12dd3f831a 100644
+--- a/arch/x86/events/core.c
++++ b/arch/x86/events/core.c
+@@ -1521,20 +1521,23 @@ static void x86_pmu_start(struct perf_event *event, int flags)
+ void perf_event_print_debug(void)
+ {
+       u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed;
++      unsigned long *cntr_mask, *fixed_cntr_mask;
++      struct event_constraint *pebs_constraints;
++      struct cpu_hw_events *cpuc;
+       u64 pebs, debugctl;
+-      int cpu = smp_processor_id();
+-      struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+-      unsigned long *cntr_mask = hybrid(cpuc->pmu, cntr_mask);
+-      unsigned long *fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask);
+-      struct event_constraint *pebs_constraints = hybrid(cpuc->pmu, pebs_constraints);
+-      unsigned long flags;
+-      int idx;
++      int cpu, idx;
++
++      guard(irqsave)();
++
++      cpu = smp_processor_id();
++      cpuc = &per_cpu(cpu_hw_events, cpu);
++      cntr_mask = hybrid(cpuc->pmu, cntr_mask);
++      fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask);
++      pebs_constraints = hybrid(cpuc->pmu, pebs_constraints);
+       if (!*(u64 *)cntr_mask)
+               return;
+-      local_irq_save(flags);
+-
+       if (x86_pmu.version >= 2) {
+               rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
+               rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
+@@ -1578,7 +1581,6 @@ void perf_event_print_debug(void)
+               pr_info("CPU#%d: fixed-PMC%d count: %016llx\n",
+                       cpu, idx, pmc_count);
+       }
+-      local_irq_restore(flags);
+ }
+ void x86_pmu_stop(struct perf_event *event, int flags)
+-- 
+2.43.0
+
diff --git a/queue-6.10/perf-x86-intel-cstate-add-arrowlake-support.patch b/queue-6.10/perf-x86-intel-cstate-add-arrowlake-support.patch
new file mode 100644 (file)
index 0000000..510412e
--- /dev/null
@@ -0,0 +1,102 @@
+From d7646c3bd205da17c72cbe83eb093cfb2a46cf06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jun 2024 11:17:57 +0800
+Subject: perf/x86/intel/cstate: Add Arrowlake support
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+[ Upstream commit a31000753d41305d2fb7faa8cc80a8edaeb7b56b ]
+
+Like Alderlake, Arrowlake supports CC1/CC6/CC7 and PC2/PC3/PC6/PC8/PC10.
+
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Link: https://lore.kernel.org/r/20240628031758.43103-3-rui.zhang@intel.com
+Stable-dep-of: b1d0e15c8725 ("perf/x86/intel/cstate: Add pkg C2 residency counter for Sierra Forest")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/intel/cstate.c | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
+index dd18320558914..cb165af1a1bfd 100644
+--- a/arch/x86/events/intel/cstate.c
++++ b/arch/x86/events/intel/cstate.c
+@@ -41,7 +41,7 @@
+  *    MSR_CORE_C1_RES: CORE C1 Residency Counter
+  *                     perf code: 0x00
+  *                     Available model: SLM,AMT,GLM,CNL,ICX,TNT,ADL,RPL
+- *                                      MTL,SRF,GRR
++ *                                      MTL,SRF,GRR,ARL
+  *                     Scope: Core (each processor core has a MSR)
+  *    MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
+  *                           perf code: 0x01
+@@ -53,30 +53,31 @@
+  *                           Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
+  *                                            SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
+  *                                            TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
+- *                                            GRR
++ *                                            GRR,ARL
+  *                           Scope: Core
+  *    MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
+  *                           perf code: 0x03
+  *                           Available model: SNB,IVB,HSW,BDW,SKL,CNL,KBL,CML,
+- *                                            ICL,TGL,RKL,ADL,RPL,MTL
++ *                                            ICL,TGL,RKL,ADL,RPL,MTL,ARL
+  *                           Scope: Core
+  *    MSR_PKG_C2_RESIDENCY:  Package C2 Residency Counter.
+  *                           perf code: 0x00
+  *                           Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
+  *                                            KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL,
+- *                                            RPL,SPR,MTL
++ *                                            RPL,SPR,MTL,ARL
+  *                           Scope: Package (physical package)
+  *    MSR_PKG_C3_RESIDENCY:  Package C3 Residency Counter.
+  *                           perf code: 0x01
+  *                           Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL,
+  *                                            GLM,CNL,KBL,CML,ICL,TGL,TNT,RKL,
+- *                                            ADL,RPL,MTL
++ *                                            ADL,RPL,MTL,ARL
+  *                           Scope: Package (physical package)
+  *    MSR_PKG_C6_RESIDENCY:  Package C6 Residency Counter.
+  *                           perf code: 0x02
+  *                           Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
+  *                                            SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
+- *                                            TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF
++ *                                            TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
++ *                                            ARL
+  *                           Scope: Package (physical package)
+  *    MSR_PKG_C7_RESIDENCY:  Package C7 Residency Counter.
+  *                           perf code: 0x03
+@@ -86,7 +87,7 @@
+  *    MSR_PKG_C8_RESIDENCY:  Package C8 Residency Counter.
+  *                           perf code: 0x04
+  *                           Available model: HSW ULT,KBL,CNL,CML,ICL,TGL,RKL,
+- *                                            ADL,RPL,MTL
++ *                                            ADL,RPL,MTL,ARL
+  *                           Scope: Package (physical package)
+  *    MSR_PKG_C9_RESIDENCY:  Package C9 Residency Counter.
+  *                           perf code: 0x05
+@@ -95,7 +96,7 @@
+  *    MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
+  *                           perf code: 0x06
+  *                           Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL,
+- *                                            TNT,RKL,ADL,RPL,MTL
++ *                                            TNT,RKL,ADL,RPL,MTL,ARL
+  *                           Scope: Package (physical package)
+  *    MSR_MODULE_C6_RES_MS:  Module C6 Residency Counter.
+  *                           perf code: 0x00
+@@ -760,6 +761,9 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
+       X86_MATCH_VFM(INTEL_RAPTORLAKE_S,       &adl_cstates),
+       X86_MATCH_VFM(INTEL_METEORLAKE,         &adl_cstates),
+       X86_MATCH_VFM(INTEL_METEORLAKE_L,       &adl_cstates),
++      X86_MATCH_VFM(INTEL_ARROWLAKE,          &adl_cstates),
++      X86_MATCH_VFM(INTEL_ARROWLAKE_H,        &adl_cstates),
++      X86_MATCH_VFM(INTEL_ARROWLAKE_U,        &adl_cstates),
+       { },
+ };
+ MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
+-- 
+2.43.0
+
diff --git a/queue-6.10/perf-x86-intel-cstate-add-lunarlake-support.patch b/queue-6.10/perf-x86-intel-cstate-add-lunarlake-support.patch
new file mode 100644 (file)
index 0000000..83a90c0
--- /dev/null
@@ -0,0 +1,110 @@
+From 2628b6f24b07d5d5fc198874a932a5f046ff60ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jun 2024 11:17:58 +0800
+Subject: perf/x86/intel/cstate: Add Lunarlake support
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+[ Upstream commit 26579860fbd5129e18de9d6fa0751a48420b26b7 ]
+
+Compared with previous client platforms, PC8 is removed from Lunarlake.
+It supports CC1/CC6/CC7 and PC2/PC3/PC6/PC10 residency counters.
+
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Link: https://lore.kernel.org/r/20240628031758.43103-4-rui.zhang@intel.com
+Stable-dep-of: b1d0e15c8725 ("perf/x86/intel/cstate: Add pkg C2 residency counter for Sierra Forest")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/intel/cstate.c | 26 +++++++++++++++++++-------
+ 1 file changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
+index cb165af1a1bfd..be58cfb012dd1 100644
+--- a/arch/x86/events/intel/cstate.c
++++ b/arch/x86/events/intel/cstate.c
+@@ -41,7 +41,7 @@
+  *    MSR_CORE_C1_RES: CORE C1 Residency Counter
+  *                     perf code: 0x00
+  *                     Available model: SLM,AMT,GLM,CNL,ICX,TNT,ADL,RPL
+- *                                      MTL,SRF,GRR,ARL
++ *                                      MTL,SRF,GRR,ARL,LNL
+  *                     Scope: Core (each processor core has a MSR)
+  *    MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
+  *                           perf code: 0x01
+@@ -53,31 +53,31 @@
+  *                           Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
+  *                                            SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
+  *                                            TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
+- *                                            GRR,ARL
++ *                                            GRR,ARL,LNL
+  *                           Scope: Core
+  *    MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
+  *                           perf code: 0x03
+  *                           Available model: SNB,IVB,HSW,BDW,SKL,CNL,KBL,CML,
+- *                                            ICL,TGL,RKL,ADL,RPL,MTL,ARL
++ *                                            ICL,TGL,RKL,ADL,RPL,MTL,ARL,LNL
+  *                           Scope: Core
+  *    MSR_PKG_C2_RESIDENCY:  Package C2 Residency Counter.
+  *                           perf code: 0x00
+  *                           Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
+  *                                            KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL,
+- *                                            RPL,SPR,MTL,ARL
++ *                                            RPL,SPR,MTL,ARL,LNL
+  *                           Scope: Package (physical package)
+  *    MSR_PKG_C3_RESIDENCY:  Package C3 Residency Counter.
+  *                           perf code: 0x01
+  *                           Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL,
+  *                                            GLM,CNL,KBL,CML,ICL,TGL,TNT,RKL,
+- *                                            ADL,RPL,MTL,ARL
++ *                                            ADL,RPL,MTL,ARL,LNL
+  *                           Scope: Package (physical package)
+  *    MSR_PKG_C6_RESIDENCY:  Package C6 Residency Counter.
+  *                           perf code: 0x02
+  *                           Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
+  *                                            SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
+  *                                            TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
+- *                                            ARL
++ *                                            ARL,LNL
+  *                           Scope: Package (physical package)
+  *    MSR_PKG_C7_RESIDENCY:  Package C7 Residency Counter.
+  *                           perf code: 0x03
+@@ -96,7 +96,7 @@
+  *    MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
+  *                           perf code: 0x06
+  *                           Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL,
+- *                                            TNT,RKL,ADL,RPL,MTL,ARL
++ *                                            TNT,RKL,ADL,RPL,MTL,ARL,LNL
+  *                           Scope: Package (physical package)
+  *    MSR_MODULE_C6_RES_MS:  Module C6 Residency Counter.
+  *                           perf code: 0x00
+@@ -641,6 +641,17 @@ static const struct cstate_model adl_cstates __initconst = {
+                                 BIT(PERF_CSTATE_PKG_C10_RES),
+ };
++static const struct cstate_model lnl_cstates __initconst = {
++      .core_events            = BIT(PERF_CSTATE_CORE_C1_RES) |
++                                BIT(PERF_CSTATE_CORE_C6_RES) |
++                                BIT(PERF_CSTATE_CORE_C7_RES),
++
++      .pkg_events             = BIT(PERF_CSTATE_PKG_C2_RES) |
++                                BIT(PERF_CSTATE_PKG_C3_RES) |
++                                BIT(PERF_CSTATE_PKG_C6_RES) |
++                                BIT(PERF_CSTATE_PKG_C10_RES),
++};
++
+ static const struct cstate_model slm_cstates __initconst = {
+       .core_events            = BIT(PERF_CSTATE_CORE_C1_RES) |
+                                 BIT(PERF_CSTATE_CORE_C6_RES),
+@@ -764,6 +775,7 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
+       X86_MATCH_VFM(INTEL_ARROWLAKE,          &adl_cstates),
+       X86_MATCH_VFM(INTEL_ARROWLAKE_H,        &adl_cstates),
+       X86_MATCH_VFM(INTEL_ARROWLAKE_U,        &adl_cstates),
++      X86_MATCH_VFM(INTEL_LUNARLAKE_M,        &lnl_cstates),
+       { },
+ };
+ MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
+-- 
+2.43.0
+
diff --git a/queue-6.10/perf-x86-intel-cstate-add-pkg-c2-residency-counter-f.patch b/queue-6.10/perf-x86-intel-cstate-add-pkg-c2-residency-counter-f.patch
new file mode 100644 (file)
index 0000000..56cda37
--- /dev/null
@@ -0,0 +1,49 @@
+From 30b9430ff2763c3d7e3b4af439b883fe560abdc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jul 2024 11:16:09 +0800
+Subject: perf/x86/intel/cstate: Add pkg C2 residency counter for Sierra Forest
+
+From: Zhenyu Wang <zhenyuw@linux.intel.com>
+
+[ Upstream commit b1d0e15c8725d21a73c22c099418a63940261041 ]
+
+Package C2 residency counter is also available on Sierra Forest.
+So add it support in srf_cstates.
+
+Fixes: 3877d55a0db2 ("perf/x86/intel/cstate: Add Sierra Forest support")
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Tested-by: Wendy Wang <wendy.wang@intel.com>
+Link: https://lore.kernel.org/r/20240717031609.74513-1-zhenyuw@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/intel/cstate.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
+index be58cfb012dd1..9f116dfc47284 100644
+--- a/arch/x86/events/intel/cstate.c
++++ b/arch/x86/events/intel/cstate.c
+@@ -64,7 +64,7 @@
+  *                           perf code: 0x00
+  *                           Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
+  *                                            KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL,
+- *                                            RPL,SPR,MTL,ARL,LNL
++ *                                            RPL,SPR,MTL,ARL,LNL,SRF
+  *                           Scope: Package (physical package)
+  *    MSR_PKG_C3_RESIDENCY:  Package C3 Residency Counter.
+  *                           perf code: 0x01
+@@ -693,7 +693,8 @@ static const struct cstate_model srf_cstates __initconst = {
+       .core_events            = BIT(PERF_CSTATE_CORE_C1_RES) |
+                                 BIT(PERF_CSTATE_CORE_C6_RES),
+-      .pkg_events             = BIT(PERF_CSTATE_PKG_C6_RES),
++      .pkg_events             = BIT(PERF_CSTATE_PKG_C2_RES) |
++                                BIT(PERF_CSTATE_PKG_C6_RES),
+       .module_events          = BIT(PERF_CSTATE_MODULE_C6_RES),
+ };
+-- 
+2.43.0
+
diff --git a/queue-6.10/perf-x86-intel-support-the-pebs-event-mask.patch b/queue-6.10/perf-x86-intel-support-the-pebs-event-mask.patch
new file mode 100644 (file)
index 0000000..9effcd7
--- /dev/null
@@ -0,0 +1,188 @@
+From 34d459e35c1ad1e14de2d13bcae9cebe8a72f8cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jun 2024 07:35:33 -0700
+Subject: perf/x86/intel: Support the PEBS event mask
+
+From: Kan Liang <kan.liang@linux.intel.com>
+
+[ Upstream commit a23eb2fc1d818cdac9b31f032842d55483a6a040 ]
+
+The current perf assumes that the counters that support PEBS are
+contiguous. But it's not guaranteed with the new leaf 0x23 introduced.
+The counters are enumerated with a counter mask. There may be holes in
+the counter mask for future platforms or in a virtualization
+environment.
+
+Store the PEBS event mask rather than the maximum number of PEBS
+counters in the x86 PMU structures.
+
+Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Andi Kleen <ak@linux.intel.com>
+Reviewed-by: Ian Rogers <irogers@google.com>
+Link: https://lkml.kernel.org/r/20240626143545.480761-2-kan.liang@linux.intel.com
+Stable-dep-of: f73cefa3b72e ("perf/x86: Fix smp_processor_id()-in-preemptible warnings")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/intel/core.c    |  8 ++++----
+ arch/x86/events/intel/ds.c      | 15 ++++++++-------
+ arch/x86/events/perf_event.h    | 15 +++++++++++++--
+ arch/x86/include/asm/intel_ds.h |  1 +
+ 4 files changed, 26 insertions(+), 13 deletions(-)
+
+diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
+index 101a21fe9c213..2175ca2fdba47 100644
+--- a/arch/x86/events/intel/core.c
++++ b/arch/x86/events/intel/core.c
+@@ -4728,7 +4728,7 @@ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu)
+ {
+       intel_pmu_check_num_counters(&pmu->num_counters, &pmu->num_counters_fixed,
+                                    &pmu->intel_ctrl, (1ULL << pmu->num_counters_fixed) - 1);
+-      pmu->max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, pmu->num_counters);
++      pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
+       pmu->unconstrained = (struct event_constraint)
+                            __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+                                               0, pmu->num_counters, 0, 0);
+@@ -6070,7 +6070,7 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
+               pmu->num_counters = x86_pmu.num_counters;
+               pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
+-              pmu->max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, pmu->num_counters);
++              pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
+               pmu->unconstrained = (struct event_constraint)
+                                    __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+                                                       0, pmu->num_counters, 0, 0);
+@@ -6193,7 +6193,7 @@ __init int intel_pmu_init(void)
+       x86_pmu.events_maskl            = ebx.full;
+       x86_pmu.events_mask_len         = eax.split.mask_length;
+-      x86_pmu.max_pebs_events         = min_t(unsigned, MAX_PEBS_EVENTS, x86_pmu.num_counters);
++      x86_pmu.pebs_events_mask        = intel_pmu_pebs_mask(GENMASK_ULL(x86_pmu.num_counters - 1, 0));
+       x86_pmu.pebs_capable            = PEBS_COUNTER_MASK;
+       /*
+@@ -6826,7 +6826,7 @@ __init int intel_pmu_init(void)
+                       pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
+               }
+-              pmu->max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, pmu->num_counters);
++              pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
+               pmu->unconstrained = (struct event_constraint)
+                                       __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+                                                          0, pmu->num_counters, 0, 0);
+diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
+index 80a4f712217b7..87d3feb9f8fe8 100644
+--- a/arch/x86/events/intel/ds.c
++++ b/arch/x86/events/intel/ds.c
+@@ -1137,7 +1137,7 @@ void intel_pmu_pebs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sche
+ static inline void pebs_update_threshold(struct cpu_hw_events *cpuc)
+ {
+       struct debug_store *ds = cpuc->ds;
+-      int max_pebs_events = hybrid(cpuc->pmu, max_pebs_events);
++      int max_pebs_events = intel_pmu_max_num_pebs(cpuc->pmu);
+       int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+       u64 threshold;
+       int reserved;
+@@ -2161,6 +2161,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
+       void *base, *at, *top;
+       short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
+       short error[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
++      int max_pebs_events = intel_pmu_max_num_pebs(NULL);
+       int bit, i, size;
+       u64 mask;
+@@ -2172,8 +2173,8 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
+       ds->pebs_index = ds->pebs_buffer_base;
+-      mask = (1ULL << x86_pmu.max_pebs_events) - 1;
+-      size = x86_pmu.max_pebs_events;
++      mask = x86_pmu.pebs_events_mask;
++      size = max_pebs_events;
+       if (x86_pmu.flags & PMU_FL_PEBS_ALL) {
+               mask |= ((1ULL << x86_pmu.num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED;
+               size = INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed;
+@@ -2212,8 +2213,9 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
+                       pebs_status = p->status = cpuc->pebs_enabled;
+               bit = find_first_bit((unsigned long *)&pebs_status,
+-                                      x86_pmu.max_pebs_events);
+-              if (bit >= x86_pmu.max_pebs_events)
++                                   max_pebs_events);
++
++              if (!(x86_pmu.pebs_events_mask & (1 << bit)))
+                       continue;
+               /*
+@@ -2271,7 +2273,6 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+ {
+       short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+-      int max_pebs_events = hybrid(cpuc->pmu, max_pebs_events);
+       int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+       struct debug_store *ds = cpuc->ds;
+       struct perf_event *event;
+@@ -2287,7 +2288,7 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+       ds->pebs_index = ds->pebs_buffer_base;
+-      mask = ((1ULL << max_pebs_events) - 1) |
++      mask = hybrid(cpuc->pmu, pebs_events_mask) |
+              (((1ULL << num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED);
+       size = INTEL_PMC_IDX_FIXED + num_counters_fixed;
+diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
+index 72b022a1e16c5..a7ba2868018ca 100644
+--- a/arch/x86/events/perf_event.h
++++ b/arch/x86/events/perf_event.h
+@@ -684,7 +684,7 @@ struct x86_hybrid_pmu {
+       cpumask_t                       supported_cpus;
+       union perf_capabilities         intel_cap;
+       u64                             intel_ctrl;
+-      int                             max_pebs_events;
++      u64                             pebs_events_mask;
+       int                             num_counters;
+       int                             num_counters_fixed;
+       struct event_constraint         unconstrained;
+@@ -852,7 +852,7 @@ struct x86_pmu {
+                       pebs_ept                :1;
+       int             pebs_record_size;
+       int             pebs_buffer_size;
+-      int             max_pebs_events;
++      u64             pebs_events_mask;
+       void            (*drain_pebs)(struct pt_regs *regs, struct perf_sample_data *data);
+       struct event_constraint *pebs_constraints;
+       void            (*pebs_aliases)(struct perf_event *event);
+@@ -1661,6 +1661,17 @@ static inline int is_ht_workaround_enabled(void)
+       return !!(x86_pmu.flags & PMU_FL_EXCL_ENABLED);
+ }
++static inline u64 intel_pmu_pebs_mask(u64 cntr_mask)
++{
++      return MAX_PEBS_EVENTS_MASK & cntr_mask;
++}
++
++static inline int intel_pmu_max_num_pebs(struct pmu *pmu)
++{
++      static_assert(MAX_PEBS_EVENTS == 32);
++      return fls((u32)hybrid(pmu, pebs_events_mask));
++}
++
+ #else /* CONFIG_CPU_SUP_INTEL */
+ static inline void reserve_ds_buffers(void)
+diff --git a/arch/x86/include/asm/intel_ds.h b/arch/x86/include/asm/intel_ds.h
+index 2f9eeb5c3069a..5dbeac48a5b93 100644
+--- a/arch/x86/include/asm/intel_ds.h
++++ b/arch/x86/include/asm/intel_ds.h
+@@ -9,6 +9,7 @@
+ /* The maximal number of PEBS events: */
+ #define MAX_PEBS_EVENTS_FMT4  8
+ #define MAX_PEBS_EVENTS               32
++#define MAX_PEBS_EVENTS_MASK  GENMASK_ULL(MAX_PEBS_EVENTS - 1, 0)
+ #define MAX_FIXED_PEBS_EVENTS 16
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.10/perf-x86-support-counter-mask.patch b/queue-6.10/perf-x86-support-counter-mask.patch
new file mode 100644 (file)
index 0000000..cac4126
--- /dev/null
@@ -0,0 +1,1052 @@
+From 83cdd752bf447ef52d3f5d3936f02912070d4c7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jun 2024 07:35:34 -0700
+Subject: perf/x86: Support counter mask
+
+From: Kan Liang <kan.liang@linux.intel.com>
+
+[ Upstream commit 722e42e45c2f1c6d1adec7813651dba5139f52f4 ]
+
+The current perf assumes that both GP and fixed counters are contiguous.
+But it's not guaranteed on newer Intel platforms or in a virtualization
+environment.
+
+Use the counter mask to replace the number of counters for both GP and
+the fixed counters. For the other ARCHs or old platforms which don't
+support a counter mask, using GENMASK_ULL(num_counter - 1, 0) to
+replace. There is no functional change for them.
+
+The interface to KVM is not changed. The number of counters still be
+passed to KVM. It can be updated later separately.
+
+Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Andi Kleen <ak@linux.intel.com>
+Reviewed-by: Ian Rogers <irogers@google.com>
+Link: https://lkml.kernel.org/r/20240626143545.480761-3-kan.liang@linux.intel.com
+Stable-dep-of: f73cefa3b72e ("perf/x86: Fix smp_processor_id()-in-preemptible warnings")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/amd/core.c     |  24 ++---
+ arch/x86/events/core.c         |  98 ++++++++++----------
+ arch/x86/events/intel/core.c   | 164 ++++++++++++++++-----------------
+ arch/x86/events/intel/ds.c     |  19 ++--
+ arch/x86/events/intel/knc.c    |   2 +-
+ arch/x86/events/intel/p4.c     |  10 +-
+ arch/x86/events/intel/p6.c     |   2 +-
+ arch/x86/events/perf_event.h   |  47 ++++++++--
+ arch/x86/events/zhaoxin/core.c |  12 +--
+ 9 files changed, 199 insertions(+), 179 deletions(-)
+
+diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
+index 18bfe3451f3aa..920e3a640cadd 100644
+--- a/arch/x86/events/amd/core.c
++++ b/arch/x86/events/amd/core.c
+@@ -432,7 +432,7 @@ static void __amd_put_nb_event_constraints(struct cpu_hw_events *cpuc,
+        * be removed on one CPU at a time AND PMU is disabled
+        * when we come here
+        */
+-      for (i = 0; i < x86_pmu.num_counters; i++) {
++      for_each_set_bit(i, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               struct perf_event *tmp = event;
+               if (try_cmpxchg(nb->owners + i, &tmp, NULL))
+@@ -501,7 +501,7 @@ __amd_get_nb_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *ev
+        * because of successive calls to x86_schedule_events() from
+        * hw_perf_group_sched_in() without hw_perf_enable()
+        */
+-      for_each_set_bit(idx, c->idxmsk, x86_pmu.num_counters) {
++      for_each_set_bit(idx, c->idxmsk, x86_pmu_max_num_counters(NULL)) {
+               if (new == -1 || hwc->idx == idx)
+                       /* assign free slot, prefer hwc->idx */
+                       old = cmpxchg(nb->owners + idx, NULL, event);
+@@ -544,7 +544,7 @@ static struct amd_nb *amd_alloc_nb(int cpu)
+       /*
+        * initialize all possible NB constraints
+        */
+-      for (i = 0; i < x86_pmu.num_counters; i++) {
++      for_each_set_bit(i, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               __set_bit(i, nb->event_constraints[i].idxmsk);
+               nb->event_constraints[i].weight = 1;
+       }
+@@ -737,7 +737,7 @@ static void amd_pmu_check_overflow(void)
+        * counters are always enabled when this function is called and
+        * ARCH_PERFMON_EVENTSEL_INT is always set.
+        */
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+@@ -757,7 +757,7 @@ static void amd_pmu_enable_all(int added)
+       amd_brs_enable_all();
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               /* only activate events which are marked as active */
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+@@ -980,7 +980,7 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
+       /* Clear any reserved bits set by buggy microcode */
+       status &= amd_pmu_global_cntr_mask;
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+@@ -1315,7 +1315,7 @@ static __initconst const struct x86_pmu amd_pmu = {
+       .addr_offset            = amd_pmu_addr_offset,
+       .event_map              = amd_pmu_event_map,
+       .max_events             = ARRAY_SIZE(amd_perfmon_event_map),
+-      .num_counters           = AMD64_NUM_COUNTERS,
++      .cntr_mask64            = GENMASK_ULL(AMD64_NUM_COUNTERS - 1, 0),
+       .add                    = amd_pmu_add_event,
+       .del                    = amd_pmu_del_event,
+       .cntval_bits            = 48,
+@@ -1414,7 +1414,7 @@ static int __init amd_core_pmu_init(void)
+        */
+       x86_pmu.eventsel        = MSR_F15H_PERF_CTL;
+       x86_pmu.perfctr         = MSR_F15H_PERF_CTR;
+-      x86_pmu.num_counters    = AMD64_NUM_COUNTERS_CORE;
++      x86_pmu.cntr_mask64     = GENMASK_ULL(AMD64_NUM_COUNTERS_CORE - 1, 0);
+       /* Check for Performance Monitoring v2 support */
+       if (boot_cpu_has(X86_FEATURE_PERFMON_V2)) {
+@@ -1424,9 +1424,9 @@ static int __init amd_core_pmu_init(void)
+               x86_pmu.version = 2;
+               /* Find the number of available Core PMCs */
+-              x86_pmu.num_counters = ebx.split.num_core_pmc;
++              x86_pmu.cntr_mask64 = GENMASK_ULL(ebx.split.num_core_pmc - 1, 0);
+-              amd_pmu_global_cntr_mask = (1ULL << x86_pmu.num_counters) - 1;
++              amd_pmu_global_cntr_mask = x86_pmu.cntr_mask64;
+               /* Update PMC handling functions */
+               x86_pmu.enable_all = amd_pmu_v2_enable_all;
+@@ -1454,12 +1454,12 @@ static int __init amd_core_pmu_init(void)
+                * even numbered counter that has a consecutive adjacent odd
+                * numbered counter following it.
+                */
+-              for (i = 0; i < x86_pmu.num_counters - 1; i += 2)
++              for (i = 0; i < x86_pmu_max_num_counters(NULL) - 1; i += 2)
+                       even_ctr_mask |= BIT_ULL(i);
+               pair_constraint = (struct event_constraint)
+                                   __EVENT_CONSTRAINT(0, even_ctr_mask, 0,
+-                                  x86_pmu.num_counters / 2, 0,
++                                  x86_pmu_max_num_counters(NULL) / 2, 0,
+                                   PERF_X86_EVENT_PAIR);
+               x86_pmu.get_event_constraints = amd_get_event_constraints_f17h;
+diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
+index acd367c453341..0c51cfdf76092 100644
+--- a/arch/x86/events/core.c
++++ b/arch/x86/events/core.c
+@@ -189,29 +189,31 @@ static DEFINE_MUTEX(pmc_reserve_mutex);
+ #ifdef CONFIG_X86_LOCAL_APIC
+-static inline int get_possible_num_counters(void)
++static inline u64 get_possible_counter_mask(void)
+ {
+-      int i, num_counters = x86_pmu.num_counters;
++      u64 cntr_mask = x86_pmu.cntr_mask64;
++      int i;
+       if (!is_hybrid())
+-              return num_counters;
++              return cntr_mask;
+       for (i = 0; i < x86_pmu.num_hybrid_pmus; i++)
+-              num_counters = max_t(int, num_counters, x86_pmu.hybrid_pmu[i].num_counters);
++              cntr_mask |= x86_pmu.hybrid_pmu[i].cntr_mask64;
+-      return num_counters;
++      return cntr_mask;
+ }
+ static bool reserve_pmc_hardware(void)
+ {
+-      int i, num_counters = get_possible_num_counters();
++      u64 cntr_mask = get_possible_counter_mask();
++      int i, end;
+-      for (i = 0; i < num_counters; i++) {
++      for_each_set_bit(i, (unsigned long *)&cntr_mask, X86_PMC_IDX_MAX) {
+               if (!reserve_perfctr_nmi(x86_pmu_event_addr(i)))
+                       goto perfctr_fail;
+       }
+-      for (i = 0; i < num_counters; i++) {
++      for_each_set_bit(i, (unsigned long *)&cntr_mask, X86_PMC_IDX_MAX) {
+               if (!reserve_evntsel_nmi(x86_pmu_config_addr(i)))
+                       goto eventsel_fail;
+       }
+@@ -219,13 +221,14 @@ static bool reserve_pmc_hardware(void)
+       return true;
+ eventsel_fail:
+-      for (i--; i >= 0; i--)
++      end = i;
++      for_each_set_bit(i, (unsigned long *)&cntr_mask, end)
+               release_evntsel_nmi(x86_pmu_config_addr(i));
+-
+-      i = num_counters;
++      i = X86_PMC_IDX_MAX;
+ perfctr_fail:
+-      for (i--; i >= 0; i--)
++      end = i;
++      for_each_set_bit(i, (unsigned long *)&cntr_mask, end)
+               release_perfctr_nmi(x86_pmu_event_addr(i));
+       return false;
+@@ -233,9 +236,10 @@ static bool reserve_pmc_hardware(void)
+ static void release_pmc_hardware(void)
+ {
+-      int i, num_counters = get_possible_num_counters();
++      u64 cntr_mask = get_possible_counter_mask();
++      int i;
+-      for (i = 0; i < num_counters; i++) {
++      for_each_set_bit(i, (unsigned long *)&cntr_mask, X86_PMC_IDX_MAX) {
+               release_perfctr_nmi(x86_pmu_event_addr(i));
+               release_evntsel_nmi(x86_pmu_config_addr(i));
+       }
+@@ -248,7 +252,8 @@ static void release_pmc_hardware(void) {}
+ #endif
+-bool check_hw_exists(struct pmu *pmu, int num_counters, int num_counters_fixed)
++bool check_hw_exists(struct pmu *pmu, unsigned long *cntr_mask,
++                   unsigned long *fixed_cntr_mask)
+ {
+       u64 val, val_fail = -1, val_new= ~0;
+       int i, reg, reg_fail = -1, ret = 0;
+@@ -259,7 +264,7 @@ bool check_hw_exists(struct pmu *pmu, int num_counters, int num_counters_fixed)
+        * Check to see if the BIOS enabled any of the counters, if so
+        * complain and bail.
+        */
+-      for (i = 0; i < num_counters; i++) {
++      for_each_set_bit(i, cntr_mask, X86_PMC_IDX_MAX) {
+               reg = x86_pmu_config_addr(i);
+               ret = rdmsrl_safe(reg, &val);
+               if (ret)
+@@ -273,12 +278,12 @@ bool check_hw_exists(struct pmu *pmu, int num_counters, int num_counters_fixed)
+               }
+       }
+-      if (num_counters_fixed) {
++      if (*(u64 *)fixed_cntr_mask) {
+               reg = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
+               ret = rdmsrl_safe(reg, &val);
+               if (ret)
+                       goto msr_fail;
+-              for (i = 0; i < num_counters_fixed; i++) {
++              for_each_set_bit(i, fixed_cntr_mask, X86_PMC_IDX_MAX) {
+                       if (fixed_counter_disabled(i, pmu))
+                               continue;
+                       if (val & (0x03ULL << i*4)) {
+@@ -679,7 +684,7 @@ void x86_pmu_disable_all(void)
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+               u64 val;
+@@ -736,7 +741,7 @@ void x86_pmu_enable_all(int added)
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+               if (!test_bit(idx, cpuc->active_mask))
+@@ -975,7 +980,6 @@ EXPORT_SYMBOL_GPL(perf_assign_events);
+ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+ {
+-      int num_counters = hybrid(cpuc->pmu, num_counters);
+       struct event_constraint *c;
+       struct perf_event *e;
+       int n0, i, wmin, wmax, unsched = 0;
+@@ -1051,7 +1055,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+       /* slow path */
+       if (i != n) {
+-              int gpmax = num_counters;
++              int gpmax = x86_pmu_max_num_counters(cpuc->pmu);
+               /*
+                * Do not allow scheduling of more than half the available
+@@ -1072,7 +1076,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+                * the extra Merge events needed by large increment events.
+                */
+               if (x86_pmu.flags & PMU_FL_PAIR) {
+-                      gpmax = num_counters - cpuc->n_pair;
++                      gpmax -= cpuc->n_pair;
+                       WARN_ON(gpmax <= 0);
+               }
+@@ -1157,12 +1161,10 @@ static int collect_event(struct cpu_hw_events *cpuc, struct perf_event *event,
+  */
+ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, bool dogrp)
+ {
+-      int num_counters = hybrid(cpuc->pmu, num_counters);
+-      int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+       struct perf_event *event;
+       int n, max_count;
+-      max_count = num_counters + num_counters_fixed;
++      max_count = x86_pmu_num_counters(cpuc->pmu) + x86_pmu_num_counters_fixed(cpuc->pmu);
+       /* current number of events already accepted */
+       n = cpuc->n_events;
+@@ -1522,13 +1524,13 @@ void perf_event_print_debug(void)
+       u64 pebs, debugctl;
+       int cpu = smp_processor_id();
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+-      int num_counters = hybrid(cpuc->pmu, num_counters);
+-      int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
++      unsigned long *cntr_mask = hybrid(cpuc->pmu, cntr_mask);
++      unsigned long *fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask);
+       struct event_constraint *pebs_constraints = hybrid(cpuc->pmu, pebs_constraints);
+       unsigned long flags;
+       int idx;
+-      if (!num_counters)
++      if (!*(u64 *)cntr_mask)
+               return;
+       local_irq_save(flags);
+@@ -1555,7 +1557,7 @@ void perf_event_print_debug(void)
+       }
+       pr_info("CPU#%d: active:     %016llx\n", cpu, *(u64 *)cpuc->active_mask);
+-      for (idx = 0; idx < num_counters; idx++) {
++      for_each_set_bit(idx, cntr_mask, X86_PMC_IDX_MAX) {
+               rdmsrl(x86_pmu_config_addr(idx), pmc_ctrl);
+               rdmsrl(x86_pmu_event_addr(idx), pmc_count);
+@@ -1568,7 +1570,7 @@ void perf_event_print_debug(void)
+               pr_info("CPU#%d:   gen-PMC%d left:  %016llx\n",
+                       cpu, idx, prev_left);
+       }
+-      for (idx = 0; idx < num_counters_fixed; idx++) {
++      for_each_set_bit(idx, fixed_cntr_mask, X86_PMC_IDX_MAX) {
+               if (fixed_counter_disabled(idx, cpuc->pmu))
+                       continue;
+               rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, pmc_count);
+@@ -1682,7 +1684,7 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+@@ -2038,18 +2040,15 @@ static void _x86_pmu_read(struct perf_event *event)
+       static_call(x86_pmu_update)(event);
+ }
+-void x86_pmu_show_pmu_cap(int num_counters, int num_counters_fixed,
+-                        u64 intel_ctrl)
++void x86_pmu_show_pmu_cap(struct pmu *pmu)
+ {
+       pr_info("... version:                %d\n",     x86_pmu.version);
+       pr_info("... bit width:              %d\n",     x86_pmu.cntval_bits);
+-      pr_info("... generic registers:      %d\n",     num_counters);
++      pr_info("... generic registers:      %d\n",     x86_pmu_num_counters(pmu));
+       pr_info("... value mask:             %016Lx\n", x86_pmu.cntval_mask);
+       pr_info("... max period:             %016Lx\n", x86_pmu.max_period);
+-      pr_info("... fixed-purpose events:   %lu\n",
+-                      hweight64((((1ULL << num_counters_fixed) - 1)
+-                                      << INTEL_PMC_IDX_FIXED) & intel_ctrl));
+-      pr_info("... event mask:             %016Lx\n", intel_ctrl);
++      pr_info("... fixed-purpose events:   %d\n",     x86_pmu_num_counters_fixed(pmu));
++      pr_info("... event mask:             %016Lx\n", hybrid(pmu, intel_ctrl));
+ }
+ static int __init init_hw_perf_events(void)
+@@ -2086,7 +2085,7 @@ static int __init init_hw_perf_events(void)
+       pmu_check_apic();
+       /* sanity check that the hardware exists or is emulated */
+-      if (!check_hw_exists(&pmu, x86_pmu.num_counters, x86_pmu.num_counters_fixed))
++      if (!check_hw_exists(&pmu, x86_pmu.cntr_mask, x86_pmu.fixed_cntr_mask))
+               goto out_bad_pmu;
+       pr_cont("%s PMU driver.\n", x86_pmu.name);
+@@ -2097,14 +2096,14 @@ static int __init init_hw_perf_events(void)
+               quirk->func();
+       if (!x86_pmu.intel_ctrl)
+-              x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
++              x86_pmu.intel_ctrl = x86_pmu.cntr_mask64;
+       perf_events_lapic_init();
+       register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
+       unconstrained = (struct event_constraint)
+-              __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
+-                                 0, x86_pmu.num_counters, 0, 0);
++              __EVENT_CONSTRAINT(0, x86_pmu.cntr_mask64,
++                                 0, x86_pmu_num_counters(NULL), 0, 0);
+       x86_pmu_format_group.attrs = x86_pmu.format_attrs;
+@@ -2113,11 +2112,8 @@ static int __init init_hw_perf_events(void)
+       pmu.attr_update = x86_pmu.attr_update;
+-      if (!is_hybrid()) {
+-              x86_pmu_show_pmu_cap(x86_pmu.num_counters,
+-                                   x86_pmu.num_counters_fixed,
+-                                   x86_pmu.intel_ctrl);
+-      }
++      if (!is_hybrid())
++              x86_pmu_show_pmu_cap(NULL);
+       if (!x86_pmu.read)
+               x86_pmu.read = _x86_pmu_read;
+@@ -2481,7 +2477,7 @@ void perf_clear_dirty_counters(void)
+       for_each_set_bit(i, cpuc->dirty, X86_PMC_IDX_MAX) {
+               if (i >= INTEL_PMC_IDX_FIXED) {
+                       /* Metrics and fake events don't have corresponding HW counters. */
+-                      if ((i - INTEL_PMC_IDX_FIXED) >= hybrid(cpuc->pmu, num_counters_fixed))
++                      if (!test_bit(i - INTEL_PMC_IDX_FIXED, hybrid(cpuc->pmu, fixed_cntr_mask)))
+                               continue;
+                       wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + (i - INTEL_PMC_IDX_FIXED), 0);
+@@ -2986,8 +2982,8 @@ void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
+        * base PMU holds the correct number of counters for P-cores.
+        */
+       cap->version            = x86_pmu.version;
+-      cap->num_counters_gp    = x86_pmu.num_counters;
+-      cap->num_counters_fixed = x86_pmu.num_counters_fixed;
++      cap->num_counters_gp    = x86_pmu_num_counters(NULL);
++      cap->num_counters_fixed = x86_pmu_num_counters_fixed(NULL);
+       cap->bit_width_gp       = x86_pmu.cntval_bits;
+       cap->bit_width_fixed    = x86_pmu.cntval_bits;
+       cap->events_mask        = (unsigned int)x86_pmu.events_maskl;
+diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
+index 2175ca2fdba47..f25205d047e83 100644
+--- a/arch/x86/events/intel/core.c
++++ b/arch/x86/events/intel/core.c
+@@ -2874,23 +2874,23 @@ static void intel_pmu_reset(void)
+ {
+       struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+-      int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+-      int num_counters = hybrid(cpuc->pmu, num_counters);
++      unsigned long *cntr_mask = hybrid(cpuc->pmu, cntr_mask);
++      unsigned long *fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask);
+       unsigned long flags;
+       int idx;
+-      if (!num_counters)
++      if (!*(u64 *)cntr_mask)
+               return;
+       local_irq_save(flags);
+       pr_info("clearing PMU state on CPU#%d\n", smp_processor_id());
+-      for (idx = 0; idx < num_counters; idx++) {
++      for_each_set_bit(idx, cntr_mask, INTEL_PMC_MAX_GENERIC) {
+               wrmsrl_safe(x86_pmu_config_addr(idx), 0ull);
+               wrmsrl_safe(x86_pmu_event_addr(idx),  0ull);
+       }
+-      for (idx = 0; idx < num_counters_fixed; idx++) {
++      for_each_set_bit(idx, fixed_cntr_mask, INTEL_PMC_MAX_FIXED) {
+               if (fixed_counter_disabled(idx, cpuc->pmu))
+                       continue;
+               wrmsrl_safe(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
+@@ -2940,8 +2940,7 @@ static void x86_pmu_handle_guest_pebs(struct pt_regs *regs,
+           !guest_pebs_idxs)
+               return;
+-      for_each_set_bit(bit, (unsigned long *)&guest_pebs_idxs,
+-                       INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed) {
++      for_each_set_bit(bit, (unsigned long *)&guest_pebs_idxs, X86_PMC_IDX_MAX) {
+               event = cpuc->events[bit];
+               if (!event->attr.precise_ip)
+                       continue;
+@@ -4199,7 +4198,7 @@ static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr, void *data)
+       struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+       int idx;
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++)  {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               struct perf_event *event = cpuc->events[idx];
+               arr[idx].msr = x86_pmu_config_addr(idx);
+@@ -4217,7 +4216,7 @@ static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr, void *data)
+                       arr[idx].guest &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+       }
+-      *nr = x86_pmu.num_counters;
++      *nr = x86_pmu_max_num_counters(cpuc->pmu);
+       return arr;
+ }
+@@ -4232,7 +4231,7 @@ static void core_pmu_enable_all(int added)
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+               if (!test_bit(idx, cpuc->active_mask) ||
+@@ -4684,13 +4683,33 @@ static void flip_smm_bit(void *data)
+       }
+ }
+-static void intel_pmu_check_num_counters(int *num_counters,
+-                                       int *num_counters_fixed,
+-                                       u64 *intel_ctrl, u64 fixed_mask);
++static void intel_pmu_check_counters_mask(u64 *cntr_mask,
++                                        u64 *fixed_cntr_mask,
++                                        u64 *intel_ctrl)
++{
++      unsigned int bit;
++
++      bit = fls64(*cntr_mask);
++      if (bit > INTEL_PMC_MAX_GENERIC) {
++              WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
++                   bit, INTEL_PMC_MAX_GENERIC);
++              *cntr_mask &= GENMASK_ULL(INTEL_PMC_MAX_GENERIC - 1, 0);
++      }
++      *intel_ctrl = *cntr_mask;
++
++      bit = fls64(*fixed_cntr_mask);
++      if (bit > INTEL_PMC_MAX_FIXED) {
++              WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
++                   bit, INTEL_PMC_MAX_FIXED);
++              *fixed_cntr_mask &= GENMASK_ULL(INTEL_PMC_MAX_FIXED - 1, 0);
++      }
++
++      *intel_ctrl |= *fixed_cntr_mask << INTEL_PMC_IDX_FIXED;
++}
+ static void intel_pmu_check_event_constraints(struct event_constraint *event_constraints,
+-                                            int num_counters,
+-                                            int num_counters_fixed,
++                                            u64 cntr_mask,
++                                            u64 fixed_cntr_mask,
+                                             u64 intel_ctrl);
+ static void intel_pmu_check_extra_regs(struct extra_reg *extra_regs);
+@@ -4713,11 +4732,10 @@ static void update_pmu_cap(struct x86_hybrid_pmu *pmu)
+       if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT) {
+               cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF,
+                           &eax, &ebx, &ecx, &edx);
+-              pmu->num_counters = fls(eax);
+-              pmu->num_counters_fixed = fls(ebx);
++              pmu->cntr_mask64 = eax;
++              pmu->fixed_cntr_mask64 = ebx;
+       }
+-
+       if (!intel_pmu_broken_perf_cap()) {
+               /* Perf Metric (Bit 15) and PEBS via PT (Bit 16) are hybrid enumeration */
+               rdmsrl(MSR_IA32_PERF_CAPABILITIES, pmu->intel_cap.capabilities);
+@@ -4726,12 +4744,12 @@ static void update_pmu_cap(struct x86_hybrid_pmu *pmu)
+ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu)
+ {
+-      intel_pmu_check_num_counters(&pmu->num_counters, &pmu->num_counters_fixed,
+-                                   &pmu->intel_ctrl, (1ULL << pmu->num_counters_fixed) - 1);
+-      pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
++      intel_pmu_check_counters_mask(&pmu->cntr_mask64, &pmu->fixed_cntr_mask64,
++                                    &pmu->intel_ctrl);
++      pmu->pebs_events_mask = intel_pmu_pebs_mask(pmu->cntr_mask64);
+       pmu->unconstrained = (struct event_constraint)
+-                           __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+-                                              0, pmu->num_counters, 0, 0);
++                           __EVENT_CONSTRAINT(0, pmu->cntr_mask64,
++                                              0, x86_pmu_num_counters(&pmu->pmu), 0, 0);
+       if (pmu->intel_cap.perf_metrics)
+               pmu->intel_ctrl |= 1ULL << GLOBAL_CTRL_EN_PERF_METRICS;
+@@ -4744,8 +4762,8 @@ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu)
+               pmu->pmu.capabilities &= ~PERF_PMU_CAP_AUX_OUTPUT;
+       intel_pmu_check_event_constraints(pmu->event_constraints,
+-                                        pmu->num_counters,
+-                                        pmu->num_counters_fixed,
++                                        pmu->cntr_mask64,
++                                        pmu->fixed_cntr_mask64,
+                                         pmu->intel_ctrl);
+       intel_pmu_check_extra_regs(pmu->extra_regs);
+@@ -4806,7 +4824,7 @@ static bool init_hybrid_pmu(int cpu)
+       intel_pmu_check_hybrid_pmus(pmu);
+-      if (!check_hw_exists(&pmu->pmu, pmu->num_counters, pmu->num_counters_fixed))
++      if (!check_hw_exists(&pmu->pmu, pmu->cntr_mask, pmu->fixed_cntr_mask))
+               return false;
+       pr_info("%s PMU driver: ", pmu->name);
+@@ -4816,8 +4834,7 @@ static bool init_hybrid_pmu(int cpu)
+       pr_cont("\n");
+-      x86_pmu_show_pmu_cap(pmu->num_counters, pmu->num_counters_fixed,
+-                           pmu->intel_ctrl);
++      x86_pmu_show_pmu_cap(&pmu->pmu);
+ end:
+       cpumask_set_cpu(cpu, &pmu->supported_cpus);
+@@ -5955,29 +5972,9 @@ static const struct attribute_group *hybrid_attr_update[] = {
+ static struct attribute *empty_attrs;
+-static void intel_pmu_check_num_counters(int *num_counters,
+-                                       int *num_counters_fixed,
+-                                       u64 *intel_ctrl, u64 fixed_mask)
+-{
+-      if (*num_counters > INTEL_PMC_MAX_GENERIC) {
+-              WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
+-                   *num_counters, INTEL_PMC_MAX_GENERIC);
+-              *num_counters = INTEL_PMC_MAX_GENERIC;
+-      }
+-      *intel_ctrl = (1ULL << *num_counters) - 1;
+-
+-      if (*num_counters_fixed > INTEL_PMC_MAX_FIXED) {
+-              WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
+-                   *num_counters_fixed, INTEL_PMC_MAX_FIXED);
+-              *num_counters_fixed = INTEL_PMC_MAX_FIXED;
+-      }
+-
+-      *intel_ctrl |= fixed_mask << INTEL_PMC_IDX_FIXED;
+-}
+-
+ static void intel_pmu_check_event_constraints(struct event_constraint *event_constraints,
+-                                            int num_counters,
+-                                            int num_counters_fixed,
++                                            u64 cntr_mask,
++                                            u64 fixed_cntr_mask,
+                                             u64 intel_ctrl)
+ {
+       struct event_constraint *c;
+@@ -6014,10 +6011,9 @@ static void intel_pmu_check_event_constraints(struct event_constraint *event_con
+                        * generic counters
+                        */
+                       if (!use_fixed_pseudo_encoding(c->code))
+-                              c->idxmsk64 |= (1ULL << num_counters) - 1;
++                              c->idxmsk64 |= cntr_mask;
+               }
+-              c->idxmsk64 &=
+-                      ~(~0ULL << (INTEL_PMC_IDX_FIXED + num_counters_fixed));
++              c->idxmsk64 &= cntr_mask | (fixed_cntr_mask << INTEL_PMC_IDX_FIXED);
+               c->weight = hweight64(c->idxmsk64);
+       }
+ }
+@@ -6068,12 +6064,12 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
+               pmu->pmu_type = intel_hybrid_pmu_type_map[bit].id;
+               pmu->name = intel_hybrid_pmu_type_map[bit].name;
+-              pmu->num_counters = x86_pmu.num_counters;
+-              pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
+-              pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
++              pmu->cntr_mask64 = x86_pmu.cntr_mask64;
++              pmu->fixed_cntr_mask64 = x86_pmu.fixed_cntr_mask64;
++              pmu->pebs_events_mask = intel_pmu_pebs_mask(pmu->cntr_mask64);
+               pmu->unconstrained = (struct event_constraint)
+-                                   __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+-                                                      0, pmu->num_counters, 0, 0);
++                                   __EVENT_CONSTRAINT(0, pmu->cntr_mask64,
++                                                      0, x86_pmu_num_counters(&pmu->pmu), 0, 0);
+               pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities;
+               if (pmu->pmu_type & hybrid_small) {
+@@ -6186,14 +6182,14 @@ __init int intel_pmu_init(void)
+               x86_pmu = intel_pmu;
+       x86_pmu.version                 = version;
+-      x86_pmu.num_counters            = eax.split.num_counters;
++      x86_pmu.cntr_mask64             = GENMASK_ULL(eax.split.num_counters - 1, 0);
+       x86_pmu.cntval_bits             = eax.split.bit_width;
+       x86_pmu.cntval_mask             = (1ULL << eax.split.bit_width) - 1;
+       x86_pmu.events_maskl            = ebx.full;
+       x86_pmu.events_mask_len         = eax.split.mask_length;
+-      x86_pmu.pebs_events_mask        = intel_pmu_pebs_mask(GENMASK_ULL(x86_pmu.num_counters - 1, 0));
++      x86_pmu.pebs_events_mask        = intel_pmu_pebs_mask(x86_pmu.cntr_mask64);
+       x86_pmu.pebs_capable            = PEBS_COUNTER_MASK;
+       /*
+@@ -6203,12 +6199,10 @@ __init int intel_pmu_init(void)
+       if (version > 1 && version < 5) {
+               int assume = 3 * !boot_cpu_has(X86_FEATURE_HYPERVISOR);
+-              x86_pmu.num_counters_fixed =
+-                      max((int)edx.split.num_counters_fixed, assume);
+-
+-              fixed_mask = (1L << x86_pmu.num_counters_fixed) - 1;
++              x86_pmu.fixed_cntr_mask64 =
++                      GENMASK_ULL(max((int)edx.split.num_counters_fixed, assume) - 1, 0);
+       } else if (version >= 5)
+-              x86_pmu.num_counters_fixed = fls(fixed_mask);
++              x86_pmu.fixed_cntr_mask64 = fixed_mask;
+       if (boot_cpu_has(X86_FEATURE_PDCM)) {
+               u64 capabilities;
+@@ -6807,11 +6801,13 @@ __init int intel_pmu_init(void)
+               pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX];
+               intel_pmu_init_glc(&pmu->pmu);
+               if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) {
+-                      pmu->num_counters = x86_pmu.num_counters + 2;
+-                      pmu->num_counters_fixed = x86_pmu.num_counters_fixed + 1;
++                      pmu->cntr_mask64 <<= 2;
++                      pmu->cntr_mask64 |= 0x3;
++                      pmu->fixed_cntr_mask64 <<= 1;
++                      pmu->fixed_cntr_mask64 |= 0x1;
+               } else {
+-                      pmu->num_counters = x86_pmu.num_counters;
+-                      pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
++                      pmu->cntr_mask64 = x86_pmu.cntr_mask64;
++                      pmu->fixed_cntr_mask64 = x86_pmu.fixed_cntr_mask64;
+               }
+               /*
+@@ -6821,15 +6817,16 @@ __init int intel_pmu_init(void)
+                * mistakenly add extra counters for P-cores. Correct the number of
+                * counters here.
+                */
+-              if ((pmu->num_counters > 8) || (pmu->num_counters_fixed > 4)) {
+-                      pmu->num_counters = x86_pmu.num_counters;
+-                      pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
++              if ((x86_pmu_num_counters(&pmu->pmu) > 8) || (x86_pmu_num_counters_fixed(&pmu->pmu) > 4)) {
++                      pmu->cntr_mask64 = x86_pmu.cntr_mask64;
++                      pmu->fixed_cntr_mask64 = x86_pmu.fixed_cntr_mask64;
+               }
+-              pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
++              pmu->pebs_events_mask = intel_pmu_pebs_mask(pmu->cntr_mask64);
+               pmu->unconstrained = (struct event_constraint)
+-                                      __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+-                                                         0, pmu->num_counters, 0, 0);
++                                   __EVENT_CONSTRAINT(0, pmu->cntr_mask64,
++                                   0, x86_pmu_num_counters(&pmu->pmu), 0, 0);
++
+               pmu->extra_regs = intel_glc_extra_regs;
+               /* Initialize Atom core specific PerfMon capabilities.*/
+@@ -6896,9 +6893,9 @@ __init int intel_pmu_init(void)
+                        * The constraints may be cut according to the CPUID enumeration
+                        * by inserting the EVENT_CONSTRAINT_END.
+                        */
+-                      if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED)
+-                              x86_pmu.num_counters_fixed = INTEL_PMC_MAX_FIXED;
+-                      intel_v5_gen_event_constraints[x86_pmu.num_counters_fixed].weight = -1;
++                      if (fls64(x86_pmu.fixed_cntr_mask64) > INTEL_PMC_MAX_FIXED)
++                              x86_pmu.fixed_cntr_mask64 &= GENMASK_ULL(INTEL_PMC_MAX_FIXED - 1, 0);
++                      intel_v5_gen_event_constraints[fls64(x86_pmu.fixed_cntr_mask64)].weight = -1;
+                       x86_pmu.event_constraints = intel_v5_gen_event_constraints;
+                       pr_cont("generic architected perfmon, ");
+                       name = "generic_arch_v5+";
+@@ -6925,18 +6922,17 @@ __init int intel_pmu_init(void)
+               x86_pmu.attr_update = hybrid_attr_update;
+       }
+-      intel_pmu_check_num_counters(&x86_pmu.num_counters,
+-                                   &x86_pmu.num_counters_fixed,
+-                                   &x86_pmu.intel_ctrl,
+-                                   (u64)fixed_mask);
++      intel_pmu_check_counters_mask(&x86_pmu.cntr_mask64,
++                                    &x86_pmu.fixed_cntr_mask64,
++                                    &x86_pmu.intel_ctrl);
+       /* AnyThread may be deprecated on arch perfmon v5 or later */
+       if (x86_pmu.intel_cap.anythread_deprecated)
+               x86_pmu.format_attrs = intel_arch_formats_attr;
+       intel_pmu_check_event_constraints(x86_pmu.event_constraints,
+-                                        x86_pmu.num_counters,
+-                                        x86_pmu.num_counters_fixed,
++                                        x86_pmu.cntr_mask64,
++                                        x86_pmu.fixed_cntr_mask64,
+                                         x86_pmu.intel_ctrl);
+       /*
+        * Access LBR MSR may cause #GP under certain circumstances.
+diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
+index 87d3feb9f8fe8..9212053f6f1d6 100644
+--- a/arch/x86/events/intel/ds.c
++++ b/arch/x86/events/intel/ds.c
+@@ -1138,7 +1138,6 @@ static inline void pebs_update_threshold(struct cpu_hw_events *cpuc)
+ {
+       struct debug_store *ds = cpuc->ds;
+       int max_pebs_events = intel_pmu_max_num_pebs(cpuc->pmu);
+-      int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+       u64 threshold;
+       int reserved;
+@@ -1146,7 +1145,7 @@ static inline void pebs_update_threshold(struct cpu_hw_events *cpuc)
+               return;
+       if (x86_pmu.flags & PMU_FL_PEBS_ALL)
+-              reserved = max_pebs_events + num_counters_fixed;
++              reserved = max_pebs_events + x86_pmu_max_num_counters_fixed(cpuc->pmu);
+       else
+               reserved = max_pebs_events;
+@@ -2176,8 +2175,8 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
+       mask = x86_pmu.pebs_events_mask;
+       size = max_pebs_events;
+       if (x86_pmu.flags & PMU_FL_PEBS_ALL) {
+-              mask |= ((1ULL << x86_pmu.num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED;
+-              size = INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed;
++              mask |= x86_pmu.fixed_cntr_mask64 << INTEL_PMC_IDX_FIXED;
++              size = INTEL_PMC_IDX_FIXED + x86_pmu_max_num_counters_fixed(NULL);
+       }
+       if (unlikely(base >= top)) {
+@@ -2273,11 +2272,10 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+ {
+       short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+-      int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+       struct debug_store *ds = cpuc->ds;
+       struct perf_event *event;
+       void *base, *at, *top;
+-      int bit, size;
++      int bit;
+       u64 mask;
+       if (!x86_pmu.pebs_active)
+@@ -2289,11 +2287,10 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+       ds->pebs_index = ds->pebs_buffer_base;
+       mask = hybrid(cpuc->pmu, pebs_events_mask) |
+-             (((1ULL << num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED);
+-      size = INTEL_PMC_IDX_FIXED + num_counters_fixed;
++             (hybrid(cpuc->pmu, fixed_cntr_mask64) << INTEL_PMC_IDX_FIXED);
+       if (unlikely(base >= top)) {
+-              intel_pmu_pebs_event_update_no_drain(cpuc, size);
++              intel_pmu_pebs_event_update_no_drain(cpuc, X86_PMC_IDX_MAX);
+               return;
+       }
+@@ -2303,11 +2300,11 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+               pebs_status = get_pebs_status(at) & cpuc->pebs_enabled;
+               pebs_status &= mask;
+-              for_each_set_bit(bit, (unsigned long *)&pebs_status, size)
++              for_each_set_bit(bit, (unsigned long *)&pebs_status, X86_PMC_IDX_MAX)
+                       counts[bit]++;
+       }
+-      for_each_set_bit(bit, (unsigned long *)&mask, size) {
++      for_each_set_bit(bit, (unsigned long *)&mask, X86_PMC_IDX_MAX) {
+               if (counts[bit] == 0)
+                       continue;
+diff --git a/arch/x86/events/intel/knc.c b/arch/x86/events/intel/knc.c
+index 618001c208e81..034a1f6a457c6 100644
+--- a/arch/x86/events/intel/knc.c
++++ b/arch/x86/events/intel/knc.c
+@@ -303,7 +303,7 @@ static const struct x86_pmu knc_pmu __initconst = {
+       .apic                   = 1,
+       .max_period             = (1ULL << 39) - 1,
+       .version                = 0,
+-      .num_counters           = 2,
++      .cntr_mask64            = 0x3,
+       .cntval_bits            = 40,
+       .cntval_mask            = (1ULL << 40) - 1,
+       .get_event_constraints  = x86_get_event_constraints,
+diff --git a/arch/x86/events/intel/p4.c b/arch/x86/events/intel/p4.c
+index 35936188db01b..844bc4fc4724d 100644
+--- a/arch/x86/events/intel/p4.c
++++ b/arch/x86/events/intel/p4.c
+@@ -919,7 +919,7 @@ static void p4_pmu_disable_all(void)
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               struct perf_event *event = cpuc->events[idx];
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+@@ -998,7 +998,7 @@ static void p4_pmu_enable_all(int added)
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               struct perf_event *event = cpuc->events[idx];
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+@@ -1040,7 +1040,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
+       cpuc = this_cpu_ptr(&cpu_hw_events);
+-      for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++      for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               int overflow;
+               if (!test_bit(idx, cpuc->active_mask)) {
+@@ -1353,7 +1353,7 @@ static __initconst const struct x86_pmu p4_pmu = {
+        * though leave it restricted at moment assuming
+        * HT is on
+        */
+-      .num_counters           = ARCH_P4_MAX_CCCR,
++      .cntr_mask64            = GENMASK_ULL(ARCH_P4_MAX_CCCR - 1, 0),
+       .apic                   = 1,
+       .cntval_bits            = ARCH_P4_CNTRVAL_BITS,
+       .cntval_mask            = ARCH_P4_CNTRVAL_MASK,
+@@ -1395,7 +1395,7 @@ __init int p4_pmu_init(void)
+        *
+        * Solve this by zero'ing out the registers to mimic a reset.
+        */
+-      for (i = 0; i < x86_pmu.num_counters; i++) {
++      for_each_set_bit(i, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+               reg = x86_pmu_config_addr(i);
+               wrmsrl_safe(reg, 0ULL);
+       }
+diff --git a/arch/x86/events/intel/p6.c b/arch/x86/events/intel/p6.c
+index 408879b0c0d4e..a6cffb4f4ef52 100644
+--- a/arch/x86/events/intel/p6.c
++++ b/arch/x86/events/intel/p6.c
+@@ -214,7 +214,7 @@ static __initconst const struct x86_pmu p6_pmu = {
+       .apic                   = 1,
+       .max_period             = (1ULL << 31) - 1,
+       .version                = 0,
+-      .num_counters           = 2,
++      .cntr_mask64            = 0x3,
+       /*
+        * Events have 40 bits implemented. However they are designed such
+        * that bits [32-39] are sign extensions of bit 31. As such the
+diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
+index a7ba2868018ca..745c174fc8809 100644
+--- a/arch/x86/events/perf_event.h
++++ b/arch/x86/events/perf_event.h
+@@ -685,8 +685,14 @@ struct x86_hybrid_pmu {
+       union perf_capabilities         intel_cap;
+       u64                             intel_ctrl;
+       u64                             pebs_events_mask;
+-      int                             num_counters;
+-      int                             num_counters_fixed;
++      union {
++                      u64             cntr_mask64;
++                      unsigned long   cntr_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
++      };
++      union {
++                      u64             fixed_cntr_mask64;
++                      unsigned long   fixed_cntr_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
++      };
+       struct event_constraint         unconstrained;
+       u64                             hw_cache_event_ids
+@@ -774,8 +780,14 @@ struct x86_pmu {
+       int             (*rdpmc_index)(int index);
+       u64             (*event_map)(int);
+       int             max_events;
+-      int             num_counters;
+-      int             num_counters_fixed;
++      union {
++                      u64             cntr_mask64;
++                      unsigned long   cntr_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
++      };
++      union {
++                      u64             fixed_cntr_mask64;
++                      unsigned long   fixed_cntr_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
++      };
+       int             cntval_bits;
+       u64             cntval_mask;
+       union {
+@@ -1125,8 +1137,8 @@ static inline int x86_pmu_rdpmc_index(int index)
+       return x86_pmu.rdpmc_index ? x86_pmu.rdpmc_index(index) : index;
+ }
+-bool check_hw_exists(struct pmu *pmu, int num_counters,
+-                   int num_counters_fixed);
++bool check_hw_exists(struct pmu *pmu, unsigned long *cntr_mask,
++                   unsigned long *fixed_cntr_mask);
+ int x86_add_exclusive(unsigned int what);
+@@ -1197,8 +1209,27 @@ void x86_pmu_enable_event(struct perf_event *event);
+ int x86_pmu_handle_irq(struct pt_regs *regs);
+-void x86_pmu_show_pmu_cap(int num_counters, int num_counters_fixed,
+-                        u64 intel_ctrl);
++void x86_pmu_show_pmu_cap(struct pmu *pmu);
++
++static inline int x86_pmu_num_counters(struct pmu *pmu)
++{
++      return hweight64(hybrid(pmu, cntr_mask64));
++}
++
++static inline int x86_pmu_max_num_counters(struct pmu *pmu)
++{
++      return fls64(hybrid(pmu, cntr_mask64));
++}
++
++static inline int x86_pmu_num_counters_fixed(struct pmu *pmu)
++{
++      return hweight64(hybrid(pmu, fixed_cntr_mask64));
++}
++
++static inline int x86_pmu_max_num_counters_fixed(struct pmu *pmu)
++{
++      return fls64(hybrid(pmu, fixed_cntr_mask64));
++}
+ extern struct event_constraint emptyconstraint;
+diff --git a/arch/x86/events/zhaoxin/core.c b/arch/x86/events/zhaoxin/core.c
+index 3e9acdaeed1ec..2fd9b0cf9a5e5 100644
+--- a/arch/x86/events/zhaoxin/core.c
++++ b/arch/x86/events/zhaoxin/core.c
+@@ -530,13 +530,13 @@ __init int zhaoxin_pmu_init(void)
+       pr_info("Version check pass!\n");
+       x86_pmu.version                 = version;
+-      x86_pmu.num_counters            = eax.split.num_counters;
++      x86_pmu.cntr_mask64             = GENMASK_ULL(eax.split.num_counters - 1, 0);
+       x86_pmu.cntval_bits             = eax.split.bit_width;
+       x86_pmu.cntval_mask             = (1ULL << eax.split.bit_width) - 1;
+       x86_pmu.events_maskl            = ebx.full;
+       x86_pmu.events_mask_len         = eax.split.mask_length;
+-      x86_pmu.num_counters_fixed = edx.split.num_counters_fixed;
++      x86_pmu.fixed_cntr_mask64       = GENMASK_ULL(edx.split.num_counters_fixed - 1, 0);
+       x86_add_quirk(zhaoxin_arch_events_quirk);
+       switch (boot_cpu_data.x86) {
+@@ -604,13 +604,13 @@ __init int zhaoxin_pmu_init(void)
+               return -ENODEV;
+       }
+-      x86_pmu.intel_ctrl = (1 << (x86_pmu.num_counters)) - 1;
+-      x86_pmu.intel_ctrl |= ((1LL << x86_pmu.num_counters_fixed)-1) << INTEL_PMC_IDX_FIXED;
++      x86_pmu.intel_ctrl = x86_pmu.cntr_mask64;
++      x86_pmu.intel_ctrl |= x86_pmu.fixed_cntr_mask64 << INTEL_PMC_IDX_FIXED;
+       if (x86_pmu.event_constraints) {
+               for_each_event_constraint(c, x86_pmu.event_constraints) {
+-                      c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
+-                      c->weight += x86_pmu.num_counters;
++                      c->idxmsk64 |= x86_pmu.cntr_mask64;
++                      c->weight += x86_pmu_num_counters(NULL);
+               }
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/platform-chrome-cros_ec_lpc-add-a-new-quirk-for-acpi.patch b/queue-6.10/platform-chrome-cros_ec_lpc-add-a-new-quirk-for-acpi.patch
new file mode 100644 (file)
index 0000000..607cbe9
--- /dev/null
@@ -0,0 +1,130 @@
+From d95e53db9dc2db9cb26f741797e8dabefd0fe374 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 07:33:49 +0100
+Subject: platform/chrome: cros_ec_lpc: Add a new quirk for ACPI id
+
+From: Ben Walsh <ben@jubnut.com>
+
+[ Upstream commit 040159e0912c31fe959d8671f9700bda105ab63a ]
+
+Framework Laptops' ACPI exposes the EC with id "PNP0C09". But
+"PNP0C09" is part of the ACPI standard; there are lots of computers
+with EC chips with this id, and most of them don't support the cros_ec
+protocol.
+
+The driver could find the ACPI device by having "PNP0C09" in the
+acpi_match_table, but this would match devices which don't support the
+cros_ec protocol. Instead, add a new quirk "CROS_EC_LPC_QUIRK_ACPI_ID"
+which allows the id to be specified. This quirk is applied after the
+DMI check shows that the device is supported.
+
+Tested-by: Dustin L. Howett <dustin@howett.net>
+Signed-off-by: Ben Walsh <ben@jubnut.com>
+Link: https://lore.kernel.org/r/20240605063351.14836-4-ben@jubnut.com
+Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/chrome/cros_ec_lpc.c | 50 ++++++++++++++++++++-------
+ 1 file changed, 38 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
+index ddfbfec44f4cc..43e0914256a3c 100644
+--- a/drivers/platform/chrome/cros_ec_lpc.c
++++ b/drivers/platform/chrome/cros_ec_lpc.c
+@@ -39,6 +39,11 @@ static bool cros_ec_lpc_acpi_device_found;
+  * be used as the base port for EC mapped memory.
+  */
+ #define CROS_EC_LPC_QUIRK_REMAP_MEMORY              BIT(0)
++/*
++ * Indicates that lpc_driver_data.quirk_acpi_id should be used to find
++ * the ACPI device.
++ */
++#define CROS_EC_LPC_QUIRK_ACPI_ID                   BIT(1)
+ /**
+  * struct lpc_driver_data - driver data attached to a DMI device ID to indicate
+@@ -46,10 +51,12 @@ static bool cros_ec_lpc_acpi_device_found;
+  * @quirks: a bitfield composed of quirks from CROS_EC_LPC_QUIRK_*
+  * @quirk_mmio_memory_base: The first I/O port addressing EC mapped memory (used
+  *                          when quirk ...REMAP_MEMORY is set.)
++ * @quirk_acpi_id: An ACPI HID to be used to find the ACPI device.
+  */
+ struct lpc_driver_data {
+       u32 quirks;
+       u16 quirk_mmio_memory_base;
++      const char *quirk_acpi_id;
+ };
+ /**
+@@ -374,6 +381,26 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
+               pm_system_wakeup();
+ }
++static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level,
++                                          void *context, void **retval)
++{
++      *(struct acpi_device **)context = acpi_fetch_acpi_dev(handle);
++      return AE_CTRL_TERMINATE;
++}
++
++static struct acpi_device *cros_ec_lpc_get_device(const char *id)
++{
++      struct acpi_device *adev = NULL;
++      acpi_status status = acpi_get_devices(id, cros_ec_lpc_parse_device,
++                                            &adev, NULL);
++      if (ACPI_FAILURE(status)) {
++              pr_warn(DRV_NAME ": Looking for %s failed\n", id);
++              return NULL;
++      }
++
++      return adev;
++}
++
+ static int cros_ec_lpc_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -401,6 +428,16 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
+               if (quirks & CROS_EC_LPC_QUIRK_REMAP_MEMORY)
+                       ec_lpc->mmio_memory_base = driver_data->quirk_mmio_memory_base;
++
++              if (quirks & CROS_EC_LPC_QUIRK_ACPI_ID) {
++                      adev = cros_ec_lpc_get_device(driver_data->quirk_acpi_id);
++                      if (!adev) {
++                              dev_err(dev, "failed to get ACPI device '%s'",
++                                      driver_data->quirk_acpi_id);
++                              return -ENODEV;
++                      }
++                      ACPI_COMPANION_SET(dev, adev);
++              }
+       }
+       /*
+@@ -661,23 +698,12 @@ static struct platform_device cros_ec_lpc_device = {
+       .name = DRV_NAME
+ };
+-static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level,
+-                                          void *context, void **retval)
+-{
+-      *(bool *)context = true;
+-      return AE_CTRL_TERMINATE;
+-}
+-
+ static int __init cros_ec_lpc_init(void)
+ {
+       int ret;
+-      acpi_status status;
+       const struct dmi_system_id *dmi_match;
+-      status = acpi_get_devices(ACPI_DRV_NAME, cros_ec_lpc_parse_device,
+-                                &cros_ec_lpc_acpi_device_found, NULL);
+-      if (ACPI_FAILURE(status))
+-              pr_warn(DRV_NAME ": Looking for %s failed\n", ACPI_DRV_NAME);
++      cros_ec_lpc_acpi_device_found = !!cros_ec_lpc_get_device(ACPI_DRV_NAME);
+       dmi_match = dmi_first_match(cros_ec_lpc_dmi_table);
+-- 
+2.43.0
+
diff --git a/queue-6.10/platform-x86-intel-ifs-initialize-union-ifs_status-t.patch b/queue-6.10/platform-x86-intel-ifs-initialize-union-ifs_status-t.patch
new file mode 100644 (file)
index 0000000..322e955
--- /dev/null
@@ -0,0 +1,47 @@
+From c59d4f8d1068a600dda81b5c20d4391e622eb1fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 15:59:30 +0000
+Subject: platform/x86/intel/ifs: Initialize union ifs_status to zero
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+
+[ Upstream commit 3114f77e9453daa292ec0906f313a715c69b5943 ]
+
+If the IFS scan test exits prematurely due to a timeout before
+completing a single run, the union ifs_status remains uninitialized,
+leading to incorrect test status reporting. To prevent this, always
+initialize the union ifs_status to zero.
+
+Fixes: 2b40e654b73a ("platform/x86/intel/ifs: Add scan test support")
+Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Reviewed-by: Jithu Joseph <jithu.joseph@intel.com>
+Reviewed-by: Ashok Raj <ashok.raj@intel.com>
+Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+Link: https://lore.kernel.org/r/20240730155930.1754744-1-sathyanarayanan.kuppuswamy@linux.intel.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/intel/ifs/runtest.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
+index 282e4bfe30da3..be3d51ed0e474 100644
+--- a/drivers/platform/x86/intel/ifs/runtest.c
++++ b/drivers/platform/x86/intel/ifs/runtest.c
+@@ -221,8 +221,8 @@ static int doscan(void *data)
+  */
+ static void ifs_test_core(int cpu, struct device *dev)
+ {
++      union ifs_status status = {};
+       union ifs_scan activate;
+-      union ifs_status status;
+       unsigned long timeout;
+       struct ifs_data *ifsd;
+       int to_start, to_stop;
+-- 
+2.43.0
+
diff --git a/queue-6.10/platform-x86-intel-vbtn-protect-acpi-notify-handler-.patch b/queue-6.10/platform-x86-intel-vbtn-protect-acpi-notify-handler-.patch
new file mode 100644 (file)
index 0000000..0368138
--- /dev/null
@@ -0,0 +1,97 @@
+From 75caffd4f52c38007990781d90e01b59c0a0b3ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 14:04:43 +0200
+Subject: platform/x86: intel-vbtn: Protect ACPI notify handler against
+ recursion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit e075c3b13a0a142dcd3151b25d29a24f31b7b640 ]
+
+Since commit e2ffcda16290 ("ACPI: OSL: Allow Notify () handlers to run on
+all CPUs") ACPI notify handlers like the intel-vbtn notify_handler() may
+run on multiple CPU cores racing with themselves.
+
+This race gets hit on Dell Venue 7140 tablets when undocking from
+the keyboard, causing the handler to try and register priv->switches_dev
+twice, as can be seen from the dev_info() message getting logged twice:
+
+[ 83.861800] intel-vbtn INT33D6:00: Registering Intel Virtual Switches input-dev after receiving a switch event
+[ 83.861858] input: Intel Virtual Switches as /devices/pci0000:00/0000:00:1f.0/PNP0C09:00/INT33D6:00/input/input17
+[ 83.861865] intel-vbtn INT33D6:00: Registering Intel Virtual Switches input-dev after receiving a switch event
+
+After which things go seriously wrong:
+[ 83.861872] sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:1f.0/PNP0C09:00/INT33D6:00/input/input17'
+...
+[ 83.861967] kobject: kobject_add_internal failed for input17 with -EEXIST, don't try to register things with the same name in the same directory.
+[ 83.877338] BUG: kernel NULL pointer dereference, address: 0000000000000018
+...
+
+Protect intel-vbtn notify_handler() from racing with itself with a mutex
+to fix this.
+
+Fixes: e2ffcda16290 ("ACPI: OSL: Allow Notify () handlers to run on all CPUs")
+Reported-by: En-Wei Wu <en-wei.wu@canonical.com>
+Closes: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2073001
+Tested-by: Kostadin Stoilov <kmstoilov@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20240729120443.14779-1-hdegoede@redhat.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/intel/vbtn.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/platform/x86/intel/vbtn.c b/drivers/platform/x86/intel/vbtn.c
+index 9b7ce03ba085c..a353e830b65fd 100644
+--- a/drivers/platform/x86/intel/vbtn.c
++++ b/drivers/platform/x86/intel/vbtn.c
+@@ -7,11 +7,13 @@
+  */
+ #include <linux/acpi.h>
++#include <linux/cleanup.h>
+ #include <linux/dmi.h>
+ #include <linux/input.h>
+ #include <linux/input/sparse-keymap.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/mutex.h>
+ #include <linux/platform_device.h>
+ #include <linux/suspend.h>
+ #include "../dual_accel_detect.h"
+@@ -66,6 +68,7 @@ static const struct key_entry intel_vbtn_switchmap[] = {
+ };
+ struct intel_vbtn_priv {
++      struct mutex mutex; /* Avoid notify_handler() racing with itself */
+       struct input_dev *buttons_dev;
+       struct input_dev *switches_dev;
+       bool dual_accel;
+@@ -155,6 +158,8 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
+       bool autorelease;
+       int ret;
++      guard(mutex)(&priv->mutex);
++
+       if ((ke = sparse_keymap_entry_from_scancode(priv->buttons_dev, event))) {
+               if (!priv->has_buttons) {
+                       dev_warn(&device->dev, "Warning: received 0x%02x button event on a device without buttons, please report this.\n",
+@@ -290,6 +295,10 @@ static int intel_vbtn_probe(struct platform_device *device)
+               return -ENOMEM;
+       dev_set_drvdata(&device->dev, priv);
++      err = devm_mutex_init(&device->dev, &priv->mutex);
++      if (err)
++              return err;
++
+       priv->dual_accel = dual_accel;
+       priv->has_buttons = has_buttons;
+       priv->has_switches = has_switches;
+-- 
+2.43.0
+
diff --git a/queue-6.10/power-supply-rt5033-bring-back-i2c_set_clientdata.patch b/queue-6.10/power-supply-rt5033-bring-back-i2c_set_clientdata.patch
new file mode 100644 (file)
index 0000000..1e1fcb2
--- /dev/null
@@ -0,0 +1,41 @@
+From df8ea4860eda6b9d624193269506702028ff9a33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 18:53:27 +0500
+Subject: power: supply: rt5033: Bring back i2c_set_clientdata
+
+From: Nikita Travkin <nikita@trvn.ru>
+
+[ Upstream commit d3911f1639e67fc7b12aae0efa5a540976d7443b ]
+
+Commit 3a93da231c12 ("power: supply: rt5033: Use devm_power_supply_register() helper")
+reworked the driver to use devm. While at it, the i2c_set_clientdata
+was dropped along with the remove callback. Unfortunately other parts
+of the driver also rely on i2c clientdata so this causes kernel oops.
+
+Bring the call back to fix the driver.
+
+Fixes: 3a93da231c12 ("power: supply: rt5033: Use devm_power_supply_register() helper")
+Tested-by: Raymond Hackley <raymondhackley@protonmail.com>
+Signed-off-by: Nikita Travkin <nikita@trvn.ru>
+Link: https://lore.kernel.org/r/20240605-rt5033-null-clientdata-v1-1-558d710eeb4d@trvn.ru
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/rt5033_battery.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c
+index 32eafe2c00af5..7a27b262fb84a 100644
+--- a/drivers/power/supply/rt5033_battery.c
++++ b/drivers/power/supply/rt5033_battery.c
+@@ -159,6 +159,7 @@ static int rt5033_battery_probe(struct i2c_client *client)
+               return -EINVAL;
+       }
++      i2c_set_clientdata(client, battery);
+       psy_cfg.of_node = client->dev.of_node;
+       psy_cfg.drv_data = battery;
+-- 
+2.43.0
+
diff --git a/queue-6.10/r8169-remove-detection-of-chip-version-11-early-rtl8.patch b/queue-6.10/r8169-remove-detection-of-chip-version-11-early-rtl8.patch
new file mode 100644 (file)
index 0000000..61a00aa
--- /dev/null
@@ -0,0 +1,41 @@
+From c95d51f2944b26eb1d7db90295af840770ed150c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 21:20:16 +0200
+Subject: r8169: remove detection of chip version 11 (early RTL8168b)
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 982300c115d229565d7af8e8b38aa1ee7bb1f5bd ]
+
+This early RTL8168b version was the first PCIe chip version, and it's
+quite quirky. Last sign of life is from more than 15 yrs ago.
+Let's remove detection of this chip version, we'll see whether anybody
+complains. If not, support for this chip version can be removed a few
+kernel versions later.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/875cdcf4-843c-420a-ad5d-417447b68572@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index b6e89fc5a4ae7..e5f883a66f47a 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2274,7 +2274,9 @@ static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
+               /* 8168B family. */
+               { 0x7c8, 0x380, RTL_GIGA_MAC_VER_17 },
+-              { 0x7c8, 0x300, RTL_GIGA_MAC_VER_11 },
++              /* This one is very old and rare, let's see if anybody complains.
++               * { 0x7c8, 0x300,      RTL_GIGA_MAC_VER_11 },
++               */
+               /* 8101 family. */
+               { 0x7c8, 0x448, RTL_GIGA_MAC_VER_39 },
+-- 
+2.43.0
+
diff --git a/queue-6.10/rcu-fix-rcu_barrier-vs-post-cpuhp_teardown_cpu-invoc.patch b/queue-6.10/rcu-fix-rcu_barrier-vs-post-cpuhp_teardown_cpu-invoc.patch
new file mode 100644 (file)
index 0000000..4f9dd89
--- /dev/null
@@ -0,0 +1,120 @@
+From 87be42b489031f336fd6306b38dac82246e01748 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 May 2024 16:05:24 +0200
+Subject: rcu: Fix rcu_barrier() VS post CPUHP_TEARDOWN_CPU invocation
+
+From: Frederic Weisbecker <frederic@kernel.org>
+
+[ Upstream commit 55d4669ef1b76823083caecfab12a8bd2ccdcf64 ]
+
+When rcu_barrier() calls rcu_rdp_cpu_online() and observes a CPU off
+rnp->qsmaskinitnext, it means that all accesses from the offline CPU
+preceding the CPUHP_TEARDOWN_CPU are visible to RCU barrier, including
+callbacks expiration and counter updates.
+
+However interrupts can still fire after stop_machine() re-enables
+interrupts and before rcutree_report_cpu_dead(). The related accesses
+happening between CPUHP_TEARDOWN_CPU and rnp->qsmaskinitnext clearing
+are _NOT_ guaranteed to be seen by rcu_barrier() without proper
+ordering, especially when callbacks are invoked there to the end, making
+rcutree_migrate_callback() bypass barrier_lock.
+
+The following theoretical race example can make rcu_barrier() hang:
+
+CPU 0                                               CPU 1
+-----                                               -----
+//cpu_down()
+smpboot_park_threads()
+//ksoftirqd is parked now
+<IRQ>
+rcu_sched_clock_irq()
+   invoke_rcu_core()
+do_softirq()
+   rcu_core()
+      rcu_do_batch()
+         // callback storm
+         // rcu_do_batch() returns
+         // before completing all
+         // of them
+   // do_softirq also returns early because of
+   // timeout. It defers to ksoftirqd but
+   // it's parked
+</IRQ>
+stop_machine()
+   take_cpu_down()
+                                                    rcu_barrier()
+                                                        spin_lock(barrier_lock)
+                                                        // observes rcu_segcblist_n_cbs(&rdp->cblist) != 0
+<IRQ>
+do_softirq()
+   rcu_core()
+      rcu_do_batch()
+         //completes all pending callbacks
+         //smp_mb() implied _after_ callback number dec
+</IRQ>
+
+rcutree_report_cpu_dead()
+   rnp->qsmaskinitnext &= ~rdp->grpmask;
+
+rcutree_migrate_callback()
+   // no callback, early return without locking
+   // barrier_lock
+                                                        //observes !rcu_rdp_cpu_online(rdp)
+                                                        rcu_barrier_entrain()
+                                                           rcu_segcblist_entrain()
+                                                              // Observe rcu_segcblist_n_cbs(rsclp) == 0
+                                                              // because no barrier between reading
+                                                              // rnp->qsmaskinitnext and rsclp->len
+                                                              rcu_segcblist_add_len()
+                                                                 smp_mb__before_atomic()
+                                                                 // will now observe the 0 count and empty
+                                                                 // list, but too late, we enqueue regardless
+                                                                 WRITE_ONCE(rsclp->len, rsclp->len + v);
+                                                        // ignored barrier callback
+                                                        // rcu barrier stall...
+
+This could be solved with a read memory barrier, enforcing the message
+passing between rnp->qsmaskinitnext and rsclp->len, matching the full
+memory barrier after rsclp->len addition in rcu_segcblist_add_len()
+performed at the end of rcu_do_batch().
+
+However the rcu_barrier() is complicated enough and probably doesn't
+need too many more subtleties. CPU down is a slowpath and the
+barrier_lock seldom contended. Solve the issue with unconditionally
+locking the barrier_lock on rcutree_migrate_callbacks(). This makes sure
+that either rcu_barrier() sees the empty queue or its entrained
+callback will be migrated.
+
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/tree.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
+index 28c7031711a3f..63fb007beeaf5 100644
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -5110,11 +5110,15 @@ void rcutree_migrate_callbacks(int cpu)
+       struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
+       bool needwake;
+-      if (rcu_rdp_is_offloaded(rdp) ||
+-          rcu_segcblist_empty(&rdp->cblist))
+-              return;  /* No callbacks to migrate. */
++      if (rcu_rdp_is_offloaded(rdp))
++              return;
+       raw_spin_lock_irqsave(&rcu_state.barrier_lock, flags);
++      if (rcu_segcblist_empty(&rdp->cblist)) {
++              raw_spin_unlock_irqrestore(&rcu_state.barrier_lock, flags);
++              return;  /* No callbacks to migrate. */
++      }
++
+       WARN_ON_ONCE(rcu_rdp_cpu_online(rdp));
+       rcu_barrier_entrain(rdp);
+       my_rdp = this_cpu_ptr(&rcu_data);
+-- 
+2.43.0
+
diff --git a/queue-6.10/rcutorture-fix-rcu_torture_fwd_cb_cr-data-race.patch b/queue-6.10/rcutorture-fix-rcu_torture_fwd_cb_cr-data-race.patch
new file mode 100644 (file)
index 0000000..40c7913
--- /dev/null
@@ -0,0 +1,50 @@
+From 979bb844576dfc17e70114e5e6cd38e05ba19815 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Apr 2024 12:02:11 -0700
+Subject: rcutorture: Fix rcu_torture_fwd_cb_cr() data race
+
+From: Paul E. McKenney <paulmck@kernel.org>
+
+[ Upstream commit 6040072f4774a575fa67b912efe7722874be337b ]
+
+On powerpc systems, spinlock acquisition does not order prior stores
+against later loads.  This means that this statement:
+
+       rfcp->rfc_next = NULL;
+
+Can be reordered to follow this statement:
+
+       WRITE_ONCE(*rfcpp, rfcp);
+
+Which is then a data race with rcu_torture_fwd_prog_cr(), specifically,
+this statement:
+
+       rfcpn = READ_ONCE(rfcp->rfc_next)
+
+KCSAN located this data race, which represents a real failure on powerpc.
+
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Acked-by: Marco Elver <elver@google.com>
+Cc: Andrey Konovalov <andreyknvl@gmail.com>
+Cc: <kasan-dev@googlegroups.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/rcutorture.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
+index 807fbf6123a77..251cead744603 100644
+--- a/kernel/rcu/rcutorture.c
++++ b/kernel/rcu/rcutorture.c
+@@ -2626,7 +2626,7 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp)
+       spin_lock_irqsave(&rfp->rcu_fwd_lock, flags);
+       rfcpp = rfp->rcu_fwd_cb_tail;
+       rfp->rcu_fwd_cb_tail = &rfcp->rfc_next;
+-      WRITE_ONCE(*rfcpp, rfcp);
++      smp_store_release(rfcpp, rfcp);
+       WRITE_ONCE(rfp->n_launders_cb, rfp->n_launders_cb + 1);
+       i = ((jiffies - rfp->rcu_fwd_startat) / (HZ / FWD_CBS_HIST_DIV));
+       if (i >= ARRAY_SIZE(rfp->n_launders_hist))
+-- 
+2.43.0
+
diff --git a/queue-6.10/regmap-kunit-fix-memory-leaks-in-gen_regmap-and-gen_.patch b/queue-6.10/regmap-kunit-fix-memory-leaks-in-gen_regmap-and-gen_.patch
new file mode 100644 (file)
index 0000000..13156ba
--- /dev/null
@@ -0,0 +1,161 @@
+From 115d098e4b21deb2d3a85f86b1fc8ee34e9f8895 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Apr 2024 11:37:24 +0100
+Subject: regmap: kunit: Fix memory leaks in gen_regmap() and gen_raw_regmap()
+
+From: Richard Fitzgerald <rf@opensource.cirrus.com>
+
+[ Upstream commit c3820641da87442251e0c00b6874ef1022da8f58 ]
+
+- Use kunit_kcalloc() to allocate the defaults table so that it will be
+  freed when the test case ends.
+- kfree() the buf and *data buffers on the error paths.
+- Use kunit_add_action_or_reset() instead of kunit_add_action() so that
+  if it fails it will call regmap_exit().
+
+Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
+Link: https://msgid.link/r/20240411103724.54063-1-rf@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap-kunit.c | 72 +++++++++++++++++++-----------
+ 1 file changed, 45 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c
+index be32cd4e84da4..292e86f601978 100644
+--- a/drivers/base/regmap/regmap-kunit.c
++++ b/drivers/base/regmap/regmap-kunit.c
+@@ -145,9 +145,9 @@ static struct regmap *gen_regmap(struct kunit *test,
+       const struct regmap_test_param *param = test->param_value;
+       struct regmap_test_priv *priv = test->priv;
+       unsigned int *buf;
+-      struct regmap *ret;
++      struct regmap *ret = ERR_PTR(-ENOMEM);
+       size_t size;
+-      int i;
++      int i, error;
+       struct reg_default *defaults;
+       config->cache_type = param->cache;
+@@ -172,15 +172,17 @@ static struct regmap *gen_regmap(struct kunit *test,
+       *data = kzalloc(sizeof(**data), GFP_KERNEL);
+       if (!(*data))
+-              return ERR_PTR(-ENOMEM);
++              goto out_free;
+       (*data)->vals = buf;
+       if (config->num_reg_defaults) {
+-              defaults = kcalloc(config->num_reg_defaults,
+-                                 sizeof(struct reg_default),
+-                                 GFP_KERNEL);
++              defaults = kunit_kcalloc(test,
++                                       config->num_reg_defaults,
++                                       sizeof(struct reg_default),
++                                       GFP_KERNEL);
+               if (!defaults)
+-                      return ERR_PTR(-ENOMEM);
++                      goto out_free;
++
+               config->reg_defaults = defaults;
+               for (i = 0; i < config->num_reg_defaults; i++) {
+@@ -190,12 +192,19 @@ static struct regmap *gen_regmap(struct kunit *test,
+       }
+       ret = regmap_init_ram(priv->dev, config, *data);
+-      if (IS_ERR(ret)) {
+-              kfree(buf);
+-              kfree(*data);
+-      } else {
+-              kunit_add_action(test, regmap_exit_action, ret);
+-      }
++      if (IS_ERR(ret))
++              goto out_free;
++
++      /* This calls regmap_exit() on failure, which frees buf and *data */
++      error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
++      if (error)
++              ret = ERR_PTR(error);
++
++      return ret;
++
++out_free:
++      kfree(buf);
++      kfree(*data);
+       return ret;
+ }
+@@ -1497,9 +1506,9 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
+       struct regmap_test_priv *priv = test->priv;
+       const struct regmap_test_param *param = test->param_value;
+       u16 *buf;
+-      struct regmap *ret;
++      struct regmap *ret = ERR_PTR(-ENOMEM);
+       size_t size = (config->max_register + 1) * config->reg_bits / 8;
+-      int i;
++      int i, error;
+       struct reg_default *defaults;
+       config->cache_type = param->cache;
+@@ -1515,15 +1524,16 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
+       *data = kzalloc(sizeof(**data), GFP_KERNEL);
+       if (!(*data))
+-              return ERR_PTR(-ENOMEM);
++              goto out_free;
+       (*data)->vals = (void *)buf;
+       config->num_reg_defaults = config->max_register + 1;
+-      defaults = kcalloc(config->num_reg_defaults,
+-                         sizeof(struct reg_default),
+-                         GFP_KERNEL);
++      defaults = kunit_kcalloc(test,
++                               config->num_reg_defaults,
++                               sizeof(struct reg_default),
++                               GFP_KERNEL);
+       if (!defaults)
+-              return ERR_PTR(-ENOMEM);
++              goto out_free;
+       config->reg_defaults = defaults;
+       for (i = 0; i < config->num_reg_defaults; i++) {
+@@ -1536,7 +1546,8 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
+                       defaults[i].def = be16_to_cpu(buf[i]);
+                       break;
+               default:
+-                      return ERR_PTR(-EINVAL);
++                      ret = ERR_PTR(-EINVAL);
++                      goto out_free;
+               }
+       }
+@@ -1548,12 +1559,19 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
+               config->num_reg_defaults = 0;
+       ret = regmap_init_raw_ram(priv->dev, config, *data);
+-      if (IS_ERR(ret)) {
+-              kfree(buf);
+-              kfree(*data);
+-      } else {
+-              kunit_add_action(test, regmap_exit_action, ret);
+-      }
++      if (IS_ERR(ret))
++              goto out_free;
++
++      /* This calls regmap_exit() on failure, which frees buf and *data */
++      error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
++      if (error)
++              ret = ERR_PTR(error);
++
++      return ret;
++
++out_free:
++      kfree(buf);
++      kfree(*data);
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/revert-rcu-tasks-fix-synchronize_rcu_tasks-vs-zap_pi.patch b/queue-6.10/revert-rcu-tasks-fix-synchronize_rcu_tasks-vs-zap_pi.patch
new file mode 100644 (file)
index 0000000..46d3a7b
--- /dev/null
@@ -0,0 +1,130 @@
+From c7ef3842aaf54bb8a367f6a94b90e86066a7e5cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 16:24:04 +0200
+Subject: Revert "rcu-tasks: Fix synchronize_rcu_tasks() VS
+ zap_pid_ns_processes()"
+
+From: Frederic Weisbecker <frederic@kernel.org>
+
+[ Upstream commit 9855c37edf0009cc276cecfee09f7e76e2380212 ]
+
+This reverts commit 28319d6dc5e2ffefa452c2377dd0f71621b5bff0. The race
+it fixed was subject to conditions that don't exist anymore since:
+
+       1612160b9127 ("rcu-tasks: Eliminate deadlocks involving do_exit() and RCU tasks")
+
+This latter commit removes the use of SRCU that used to cover the
+RCU-tasks blind spot on exit between the tasklist's removal and the
+final preemption disabling. The task is now placed instead into a
+temporary list inside which voluntary sleeps are accounted as RCU-tasks
+quiescent states. This would disarm the deadlock initially reported
+against PID namespace exit.
+
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Reviewed-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/rcupdate.h |  2 --
+ kernel/pid_namespace.c   | 17 -----------------
+ kernel/rcu/tasks.h       | 16 +++-------------
+ 3 files changed, 3 insertions(+), 32 deletions(-)
+
+diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
+index dfd2399f2cde0..61cb3de236af1 100644
+--- a/include/linux/rcupdate.h
++++ b/include/linux/rcupdate.h
+@@ -209,7 +209,6 @@ void synchronize_rcu_tasks_rude(void);
+ #define rcu_note_voluntary_context_switch(t) rcu_tasks_qs(t, false)
+ void exit_tasks_rcu_start(void);
+-void exit_tasks_rcu_stop(void);
+ void exit_tasks_rcu_finish(void);
+ #else /* #ifdef CONFIG_TASKS_RCU_GENERIC */
+ #define rcu_tasks_classic_qs(t, preempt) do { } while (0)
+@@ -218,7 +217,6 @@ void exit_tasks_rcu_finish(void);
+ #define call_rcu_tasks call_rcu
+ #define synchronize_rcu_tasks synchronize_rcu
+ static inline void exit_tasks_rcu_start(void) { }
+-static inline void exit_tasks_rcu_stop(void) { }
+ static inline void exit_tasks_rcu_finish(void) { }
+ #endif /* #else #ifdef CONFIG_TASKS_RCU_GENERIC */
+diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
+index 25f3cf679b358..bdf0087d64423 100644
+--- a/kernel/pid_namespace.c
++++ b/kernel/pid_namespace.c
+@@ -249,24 +249,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (pid_ns->pid_allocated == init_pids)
+                       break;
+-              /*
+-               * Release tasks_rcu_exit_srcu to avoid following deadlock:
+-               *
+-               * 1) TASK A unshare(CLONE_NEWPID)
+-               * 2) TASK A fork() twice -> TASK B (child reaper for new ns)
+-               *    and TASK C
+-               * 3) TASK B exits, kills TASK C, waits for TASK A to reap it
+-               * 4) TASK A calls synchronize_rcu_tasks()
+-               *                   -> synchronize_srcu(tasks_rcu_exit_srcu)
+-               * 5) *DEADLOCK*
+-               *
+-               * It is considered safe to release tasks_rcu_exit_srcu here
+-               * because we assume the current task can not be concurrently
+-               * reaped at this point.
+-               */
+-              exit_tasks_rcu_stop();
+               schedule();
+-              exit_tasks_rcu_start();
+       }
+       __set_current_state(TASK_RUNNING);
+diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
+index 098e82bcc427f..ba3440a45b6dd 100644
+--- a/kernel/rcu/tasks.h
++++ b/kernel/rcu/tasks.h
+@@ -858,7 +858,7 @@ static void rcu_tasks_wait_gp(struct rcu_tasks *rtp)
+ //    not know to synchronize with this RCU Tasks grace period) have
+ //    completed exiting.  The synchronize_rcu() in rcu_tasks_postgp()
+ //    will take care of any tasks stuck in the non-preemptible region
+-//    of do_exit() following its call to exit_tasks_rcu_stop().
++//    of do_exit() following its call to exit_tasks_rcu_finish().
+ // check_all_holdout_tasks(), repeatedly until holdout list is empty:
+ //    Scans the holdout list, attempting to identify a quiescent state
+ //    for each task on the list.  If there is a quiescent state, the
+@@ -1220,7 +1220,7 @@ void exit_tasks_rcu_start(void)
+  * Remove the task from the "yet another list" because do_exit() is now
+  * non-preemptible, allowing synchronize_rcu() to wait beyond this point.
+  */
+-void exit_tasks_rcu_stop(void)
++void exit_tasks_rcu_finish(void)
+ {
+       unsigned long flags;
+       struct rcu_tasks_percpu *rtpcp;
+@@ -1231,22 +1231,12 @@ void exit_tasks_rcu_stop(void)
+       raw_spin_lock_irqsave_rcu_node(rtpcp, flags);
+       list_del_init(&t->rcu_tasks_exit_list);
+       raw_spin_unlock_irqrestore_rcu_node(rtpcp, flags);
+-}
+-/*
+- * Contribute to protect against tasklist scan blind spot while the
+- * task is exiting and may be removed from the tasklist. See
+- * corresponding synchronize_srcu() for further details.
+- */
+-void exit_tasks_rcu_finish(void)
+-{
+-      exit_tasks_rcu_stop();
+-      exit_tasks_rcu_finish_trace(current);
++      exit_tasks_rcu_finish_trace(t);
+ }
+ #else /* #ifdef CONFIG_TASKS_RCU */
+ void exit_tasks_rcu_start(void) { }
+-void exit_tasks_rcu_stop(void) { }
+ void exit_tasks_rcu_finish(void) { exit_tasks_rcu_finish_trace(current); }
+ #endif /* #else #ifdef CONFIG_TASKS_RCU */
+-- 
+2.43.0
+
diff --git a/queue-6.10/rtnetlink-move-rtnl_lock-handling-out-of-af_netlink.patch b/queue-6.10/rtnetlink-move-rtnl_lock-handling-out-of-af_netlink.patch
new file mode 100644 (file)
index 0000000..b249ef2
--- /dev/null
@@ -0,0 +1,84 @@
+From f55180327012f0f847d9cd05ce4662c3e3d56e38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jun 2024 12:29:05 -0700
+Subject: rtnetlink: move rtnl_lock handling out of af_netlink
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 5380d64f8d766576ac5c0f627418b2d0e1d2641f ]
+
+Now that we have an intermediate layer of code for handling
+rtnl-level netlink dump quirks, we can move the rtnl_lock
+taking there.
+
+For dump handlers with RTNL_FLAG_DUMP_SPLIT_NLM_DONE we can
+avoid taking rtnl_lock just to generate NLM_DONE, once again.
+
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/rtnetlink.c     | 9 +++++++--
+ net/netlink/af_netlink.c | 2 --
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 5e589f0a62bc5..cb8792800cee8 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -6486,6 +6486,7 @@ static int rtnl_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
+ static int rtnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+ {
++      const bool needs_lock = !(cb->flags & RTNL_FLAG_DUMP_UNLOCKED);
+       rtnl_dumpit_func dumpit = cb->data;
+       int err;
+@@ -6495,7 +6496,11 @@ static int rtnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+       if (!dumpit)
+               return 0;
++      if (needs_lock)
++              rtnl_lock();
+       err = dumpit(skb, cb);
++      if (needs_lock)
++              rtnl_unlock();
+       /* Old dump handlers used to send NLM_DONE as in a separate recvmsg().
+        * Some applications which parse netlink manually depend on this.
+@@ -6515,7 +6520,8 @@ static int rtnetlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+                               const struct nlmsghdr *nlh,
+                               struct netlink_dump_control *control)
+ {
+-      if (control->flags & RTNL_FLAG_DUMP_SPLIT_NLM_DONE) {
++      if (control->flags & RTNL_FLAG_DUMP_SPLIT_NLM_DONE ||
++          !(control->flags & RTNL_FLAG_DUMP_UNLOCKED)) {
+               WARN_ON(control->data);
+               control->data = control->dump;
+               control->dump = rtnl_dumpit;
+@@ -6703,7 +6709,6 @@ static int __net_init rtnetlink_net_init(struct net *net)
+       struct netlink_kernel_cfg cfg = {
+               .groups         = RTNLGRP_MAX,
+               .input          = rtnetlink_rcv,
+-              .cb_mutex       = &rtnl_mutex,
+               .flags          = NL_CFG_F_NONROOT_RECV,
+               .bind           = rtnetlink_bind,
+       };
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index fa9c090cf629e..8bbbe75e75dbe 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -2330,8 +2330,6 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
+               cb->extack = &extack;
+-              if (cb->flags & RTNL_FLAG_DUMP_UNLOCKED)
+-                      extra_mutex = NULL;
+               if (extra_mutex)
+                       mutex_lock(extra_mutex);
+               nlk->dump_done_errno = cb->dump(skb, cb);
+-- 
+2.43.0
+
diff --git a/queue-6.10/s390-sclp-prevent-release-of-buffer-in-i-o.patch b/queue-6.10/s390-sclp-prevent-release-of-buffer-in-i-o.patch
new file mode 100644 (file)
index 0000000..296e902
--- /dev/null
@@ -0,0 +1,52 @@
+From 3abb325358c8ba00fd9fdcdf21bcb33da7e2252e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jun 2024 14:20:27 +0200
+Subject: s390/sclp: Prevent release of buffer in I/O
+
+From: Peter Oberparleiter <oberpar@linux.ibm.com>
+
+[ Upstream commit bf365071ea92b9579d5a272679b74052a5643e35 ]
+
+When a task waiting for completion of a Store Data operation is
+interrupted, an attempt is made to halt this operation. If this attempt
+fails due to a hardware or firmware problem, there is a chance that the
+SCLP facility might store data into buffers referenced by the original
+operation at a later time.
+
+Handle this situation by not releasing the referenced data buffers if
+the halt attempt fails. For current use cases, this might result in a
+leak of few pages of memory in case of a rare hardware/firmware
+malfunction.
+
+Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/char/sclp_sd.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/s390/char/sclp_sd.c b/drivers/s390/char/sclp_sd.c
+index f9e164be7568f..944e75beb160c 100644
+--- a/drivers/s390/char/sclp_sd.c
++++ b/drivers/s390/char/sclp_sd.c
+@@ -320,8 +320,14 @@ static int sclp_sd_store_data(struct sclp_sd_data *result, u8 di)
+                         &esize);
+       if (rc) {
+               /* Cancel running request if interrupted */
+-              if (rc == -ERESTARTSYS)
+-                      sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL);
++              if (rc == -ERESTARTSYS) {
++                      if (sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL)) {
++                              pr_warn("Could not stop Store Data request - leaking at least %zu bytes\n",
++                                      (size_t)dsize * PAGE_SIZE);
++                              data = NULL;
++                              asce = 0;
++                      }
++              }
+               vfree(data);
+               goto out;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/sctp-fix-null-ptr-deref-in-reuseport_add_sock.patch b/queue-6.10/sctp-fix-null-ptr-deref-in-reuseport_add_sock.patch
new file mode 100644 (file)
index 0000000..0d35c44
--- /dev/null
@@ -0,0 +1,169 @@
+From 9ae4a4f48a9ec79154e3f499ba5468050ba5a9e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 16:46:24 -0700
+Subject: sctp: Fix null-ptr-deref in reuseport_add_sock().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 9ab0faa7f9ffe31296dbb9bbe6f76c72c14eea18 ]
+
+syzbot reported a null-ptr-deref while accessing sk2->sk_reuseport_cb in
+reuseport_add_sock(). [0]
+
+The repro first creates a listener with SO_REUSEPORT.  Then, it creates
+another listener on the same port and concurrently closes the first
+listener.
+
+The second listen() calls reuseport_add_sock() with the first listener as
+sk2, where sk2->sk_reuseport_cb is not expected to be cleared concurrently,
+but the close() does clear it by reuseport_detach_sock().
+
+The problem is SCTP does not properly synchronise reuseport_alloc(),
+reuseport_add_sock(), and reuseport_detach_sock().
+
+The caller of reuseport_alloc() and reuseport_{add,detach}_sock() must
+provide synchronisation for sockets that are classified into the same
+reuseport group.
+
+Otherwise, such sockets form multiple identical reuseport groups, and
+all groups except one would be silently dead.
+
+  1. Two sockets call listen() concurrently
+  2. No socket in the same group found in sctp_ep_hashtable[]
+  3. Two sockets call reuseport_alloc() and form two reuseport groups
+  4. Only one group hit first in __sctp_rcv_lookup_endpoint() receives
+      incoming packets
+
+Also, the reported null-ptr-deref could occur.
+
+TCP/UDP guarantees that would not happen by holding the hash bucket lock.
+
+Let's apply the locking strategy to __sctp_hash_endpoint() and
+__sctp_unhash_endpoint().
+
+[0]:
+Oops: general protection fault, probably for non-canonical address 0xdffffc0000000002: 0000 [#1] PREEMPT SMP KASAN PTI
+KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
+CPU: 1 UID: 0 PID: 10230 Comm: syz-executor119 Not tainted 6.10.0-syzkaller-12585-g301927d2d2eb #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/27/2024
+RIP: 0010:reuseport_add_sock+0x27e/0x5e0 net/core/sock_reuseport.c:350
+Code: 00 0f b7 5d 00 bf 01 00 00 00 89 de e8 1b a4 ff f7 83 fb 01 0f 85 a3 01 00 00 e8 6d a0 ff f7 49 8d 7e 12 48 89 f8 48 c1 e8 03 <42> 0f b6 04 28 84 c0 0f 85 4b 02 00 00 41 0f b7 5e 12 49 8d 7e 14
+RSP: 0018:ffffc9000b947c98 EFLAGS: 00010202
+RAX: 0000000000000002 RBX: ffff8880252ddf98 RCX: ffff888079478000
+RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000012
+RBP: 0000000000000001 R08: ffffffff8993e18d R09: 1ffffffff1fef385
+R10: dffffc0000000000 R11: fffffbfff1fef386 R12: ffff8880252ddac0
+R13: dffffc0000000000 R14: 0000000000000000 R15: 0000000000000000
+FS:  00007f24e45b96c0(0000) GS:ffff8880b9300000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007ffcced5f7b8 CR3: 00000000241be000 CR4: 00000000003506f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+ DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ __sctp_hash_endpoint net/sctp/input.c:762 [inline]
+ sctp_hash_endpoint+0x52a/0x600 net/sctp/input.c:790
+ sctp_listen_start net/sctp/socket.c:8570 [inline]
+ sctp_inet_listen+0x767/0xa20 net/sctp/socket.c:8625
+ __sys_listen_socket net/socket.c:1883 [inline]
+ __sys_listen+0x1b7/0x230 net/socket.c:1894
+ __do_sys_listen net/socket.c:1902 [inline]
+ __se_sys_listen net/socket.c:1900 [inline]
+ __x64_sys_listen+0x5a/0x70 net/socket.c:1900
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f24e46039b9
+Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 91 1a 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007f24e45b9228 EFLAGS: 00000246 ORIG_RAX: 0000000000000032
+RAX: ffffffffffffffda RBX: 00007f24e468e428 RCX: 00007f24e46039b9
+RDX: 00007f24e46039b9 RSI: 0000000000000003 RDI: 0000000000000004
+RBP: 00007f24e468e420 R08: 00007f24e45b96c0 R09: 00007f24e45b96c0
+R10: 00007f24e45b96c0 R11: 0000000000000246 R12: 00007f24e468e42c
+R13: 00007f24e465a5dc R14: 0020000000000001 R15: 00007ffcced5f7d8
+ </TASK>
+Modules linked in:
+
+Fixes: 6ba845740267 ("sctp: process sk_reuseport in sctp_get_port_local")
+Reported-by: syzbot+e6979a5d2f10ecb700e4@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=e6979a5d2f10ecb700e4
+Tested-by: syzbot+e6979a5d2f10ecb700e4@syzkaller.appspotmail.com
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20240731234624.94055-1-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/input.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/net/sctp/input.c b/net/sctp/input.c
+index 17fcaa9b0df94..a8a254a5008e5 100644
+--- a/net/sctp/input.c
++++ b/net/sctp/input.c
+@@ -735,15 +735,19 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep)
+       struct sock *sk = ep->base.sk;
+       struct net *net = sock_net(sk);
+       struct sctp_hashbucket *head;
++      int err = 0;
+       ep->hashent = sctp_ep_hashfn(net, ep->base.bind_addr.port);
+       head = &sctp_ep_hashtable[ep->hashent];
++      write_lock(&head->lock);
+       if (sk->sk_reuseport) {
+               bool any = sctp_is_ep_boundall(sk);
+               struct sctp_endpoint *ep2;
+               struct list_head *list;
+-              int cnt = 0, err = 1;
++              int cnt = 0;
++
++              err = 1;
+               list_for_each(list, &ep->base.bind_addr.address_list)
+                       cnt++;
+@@ -761,24 +765,24 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep)
+                       if (!err) {
+                               err = reuseport_add_sock(sk, sk2, any);
+                               if (err)
+-                                      return err;
++                                      goto out;
+                               break;
+                       } else if (err < 0) {
+-                              return err;
++                              goto out;
+                       }
+               }
+               if (err) {
+                       err = reuseport_alloc(sk, any);
+                       if (err)
+-                              return err;
++                              goto out;
+               }
+       }
+-      write_lock(&head->lock);
+       hlist_add_head(&ep->node, &head->chain);
++out:
+       write_unlock(&head->lock);
+-      return 0;
++      return err;
+ }
+ /* Add an endpoint to the hash. Local BH-safe. */
+@@ -803,10 +807,9 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
+       head = &sctp_ep_hashtable[ep->hashent];
++      write_lock(&head->lock);
+       if (rcu_access_pointer(sk->sk_reuseport_cb))
+               reuseport_detach_sock(sk);
+-
+-      write_lock(&head->lock);
+       hlist_del_init(&ep->node);
+       write_unlock(&head->lock);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.10/selftests-bpf-fix-send_signal-test-with-nested-confi.patch b/queue-6.10/selftests-bpf-fix-send_signal-test-with-nested-confi.patch
new file mode 100644 (file)
index 0000000..9f1694e
--- /dev/null
@@ -0,0 +1,120 @@
+From f6ca913a5be30cea9b776bdfbdd426d33f0f5367 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 13:12:03 -0700
+Subject: selftests/bpf: Fix send_signal test with nested CONFIG_PARAVIRT
+
+From: Yonghong Song <yonghong.song@linux.dev>
+
+[ Upstream commit 7015843afcaf68c132784c89528dfddc0005e483 ]
+
+Alexei reported that send_signal test may fail with nested CONFIG_PARAVIRT
+configs. In this particular case, the base VM is AMD with 166 cpus, and I
+run selftests with regular qemu on top of that and indeed send_signal test
+failed. I also tried with an Intel box with 80 cpus and there is no issue.
+
+The main qemu command line includes:
+
+  -enable-kvm -smp 16 -cpu host
+
+The failure log looks like:
+
+  $ ./test_progs -t send_signal
+  [   48.501588] watchdog: BUG: soft lockup - CPU#9 stuck for 26s! [test_progs:2225]
+  [   48.503622] Modules linked in: bpf_testmod(O)
+  [   48.503622] CPU: 9 PID: 2225 Comm: test_progs Tainted: G           O       6.9.0-08561-g2c1713a8f1c9-dirty #69
+  [   48.507629] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014
+  [   48.511635] RIP: 0010:handle_softirqs+0x71/0x290
+  [   48.511635] Code: [...] 10 0a 00 00 00 31 c0 65 66 89 05 d5 f4 fa 7e fb bb ff ff ff ff <49> c7 c2 cb
+  [   48.518527] RSP: 0018:ffffc90000310fa0 EFLAGS: 00000246
+  [   48.519579] RAX: 0000000000000000 RBX: 00000000ffffffff RCX: 00000000000006e0
+  [   48.522526] RDX: 0000000000000006 RSI: ffff88810791ae80 RDI: 0000000000000000
+  [   48.523587] RBP: ffffc90000fabc88 R08: 00000005a0af4f7f R09: 0000000000000000
+  [   48.525525] R10: 0000000561d2f29c R11: 0000000000006534 R12: 0000000000000280
+  [   48.528525] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+  [   48.528525] FS:  00007f2f2885cd00(0000) GS:ffff888237c40000(0000) knlGS:0000000000000000
+  [   48.531600] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  [   48.535520] CR2: 00007f2f287059f0 CR3: 0000000106a28002 CR4: 00000000003706f0
+  [   48.537538] Call Trace:
+  [   48.537538]  <IRQ>
+  [   48.537538]  ? watchdog_timer_fn+0x1cd/0x250
+  [   48.539590]  ? lockup_detector_update_enable+0x50/0x50
+  [   48.539590]  ? __hrtimer_run_queues+0xff/0x280
+  [   48.542520]  ? hrtimer_interrupt+0x103/0x230
+  [   48.544524]  ? __sysvec_apic_timer_interrupt+0x4f/0x140
+  [   48.545522]  ? sysvec_apic_timer_interrupt+0x3a/0x90
+  [   48.547612]  ? asm_sysvec_apic_timer_interrupt+0x1a/0x20
+  [   48.547612]  ? handle_softirqs+0x71/0x290
+  [   48.547612]  irq_exit_rcu+0x63/0x80
+  [   48.551585]  sysvec_apic_timer_interrupt+0x75/0x90
+  [   48.552521]  </IRQ>
+  [   48.553529]  <TASK>
+  [   48.553529]  asm_sysvec_apic_timer_interrupt+0x1a/0x20
+  [   48.555609] RIP: 0010:finish_task_switch.isra.0+0x90/0x260
+  [   48.556526] Code: [...] 9f 58 0a 00 00 48 85 db 0f 85 89 01 00 00 4c 89 ff e8 53 d9 bd 00 fb 66 90 <4d> 85 ed 74
+  [   48.562524] RSP: 0018:ffffc90000fabd38 EFLAGS: 00000282
+  [   48.563589] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffffffff83385620
+  [   48.563589] RDX: ffff888237c73ae4 RSI: 0000000000000000 RDI: ffff888237c6fd00
+  [   48.568521] RBP: ffffc90000fabd68 R08: 0000000000000000 R09: 0000000000000000
+  [   48.569528] R10: 0000000000000001 R11: 0000000000000000 R12: ffff8881009d0000
+  [   48.573525] R13: ffff8881024e5400 R14: ffff88810791ae80 R15: ffff888237c6fd00
+  [   48.575614]  ? finish_task_switch.isra.0+0x8d/0x260
+  [   48.576523]  __schedule+0x364/0xac0
+  [   48.577535]  schedule+0x2e/0x110
+  [   48.578555]  pipe_read+0x301/0x400
+  [   48.579589]  ? destroy_sched_domains_rcu+0x30/0x30
+  [   48.579589]  vfs_read+0x2b3/0x2f0
+  [   48.579589]  ksys_read+0x8b/0xc0
+  [   48.583590]  do_syscall_64+0x3d/0xc0
+  [   48.583590]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+  [   48.586525] RIP: 0033:0x7f2f28703fa1
+  [   48.587592] Code: [...] 00 00 00 0f 1f 44 00 00 f3 0f 1e fa 80 3d c5 23 14 00 00 74 13 31 c0 0f 05 <48> 3d 00 f0
+  [   48.593534] RSP: 002b:00007ffd90f8cf88 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
+  [   48.595589] RAX: ffffffffffffffda RBX: 00007ffd90f8d5e8 RCX: 00007f2f28703fa1
+  [   48.595589] RDX: 0000000000000001 RSI: 00007ffd90f8cfb0 RDI: 0000000000000006
+  [   48.599592] RBP: 00007ffd90f8d2f0 R08: 0000000000000064 R09: 0000000000000000
+  [   48.602527] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+  [   48.603589] R13: 00007ffd90f8d608 R14: 00007f2f288d8000 R15: 0000000000f6bdb0
+  [   48.605527]  </TASK>
+
+In the test, two processes are communicating through pipe. Further debugging
+with strace found that the above splat is triggered as read() syscall could
+not receive the data even if the corresponding write() syscall in another
+process successfully wrote data into the pipe.
+
+The failed subtest is "send_signal_perf". The corresponding perf event has
+sample_period 1 and config PERF_COUNT_SW_CPU_CLOCK. sample_period 1 means every
+overflow event will trigger a call to the BPF program. So I suspect this may
+overwhelm the system. So I increased the sample_period to 100,000 and the test
+passed. The sample_period 10,000 still has the test failed.
+
+In other parts of selftest, e.g., [1], sample_freq is used instead. So I
+decided to use sample_freq = 1,000 since the test can pass as well.
+
+  [1] https://lore.kernel.org/bpf/20240604070700.3032142-1-song@kernel.org/
+
+Reported-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/bpf/20240605201203.2603846-1-yonghong.song@linux.dev
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/prog_tests/send_signal.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c
+index 920aee41bd58c..6cc69900b3106 100644
+--- a/tools/testing/selftests/bpf/prog_tests/send_signal.c
++++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c
+@@ -156,7 +156,8 @@ static void test_send_signal_tracepoint(bool signal_thread)
+ static void test_send_signal_perf(bool signal_thread)
+ {
+       struct perf_event_attr attr = {
+-              .sample_period = 1,
++              .freq = 1,
++              .sample_freq = 1000,
+               .type = PERF_TYPE_SOFTWARE,
+               .config = PERF_COUNT_SW_CPU_CLOCK,
+       };
+-- 
+2.43.0
+
diff --git a/queue-6.10/selftests-ksft-fix-finished-helper-exit-code-on-skip.patch b/queue-6.10/selftests-ksft-fix-finished-helper-exit-code-on-skip.patch
new file mode 100644 (file)
index 0000000..ef12b7f
--- /dev/null
@@ -0,0 +1,43 @@
+From d9b11444b59d3863a586715d1b6e7adef7d12781 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 12:29:28 +0200
+Subject: selftests: ksft: Fix finished() helper exit code on skipped tests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Laura Nao <laura.nao@collabora.com>
+
+[ Upstream commit 170c966cbe274e664288cfc12ee919d5e706dc50 ]
+
+The Python finished() helper currently exits with KSFT_FAIL when there
+are only passed and skipped tests. Fix the logic to exit with KSFT_PASS
+instead, making it consistent with its C and bash counterparts
+(ksft_finished() and ktap_finished() respectively).
+
+Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Fixes: dacf1d7a78bf ("kselftest: Add test to verify probe of devices from discoverable buses")
+Signed-off-by: Laura Nao <laura.nao@collabora.com>
+Reviewed-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/devices/ksft.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/devices/ksft.py b/tools/testing/selftests/devices/ksft.py
+index cd89fb2bc10e7..bf215790a89d7 100644
+--- a/tools/testing/selftests/devices/ksft.py
++++ b/tools/testing/selftests/devices/ksft.py
+@@ -70,7 +70,7 @@ def test_result(condition, description=""):
+ def finished():
+-    if ksft_cnt["pass"] == ksft_num_tests:
++    if ksft_cnt["pass"] + ksft_cnt["skip"] == ksft_num_tests:
+         exit_code = KSFT_PASS
+     else:
+         exit_code = KSFT_FAIL
+-- 
+2.43.0
+
diff --git a/queue-6.10/selftests-mptcp-join-ability-to-invert-add_addr-chec.patch b/queue-6.10/selftests-mptcp-join-ability-to-invert-add_addr-chec.patch
new file mode 100644 (file)
index 0000000..5ed26d7
--- /dev/null
@@ -0,0 +1,147 @@
+From 469e6fe99988649029b7f136218d5c3d8854e705 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 13:05:58 +0200
+Subject: selftests: mptcp: join: ability to invert ADD_ADDR check
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+[ Upstream commit bec1f3b119ebc613d08dfbcdbaef01a79aa7de92 ]
+
+In the following commit, the client will initiate the ADD_ADDR, instead
+of the server. We need to way to verify the ADD_ADDR have been correctly
+sent.
+
+Note: the default expected counters for when the port number is given
+are never changed by the caller, no need to accept them as parameter
+then.
+
+The 'Fixes' tag here below is the same as the one from the previous
+commit: this patch here is not fixing anything wrong in the selftests,
+but it validates the previous fix for an issue introduced by this commit
+ID.
+
+Fixes: 86e39e04482b ("mptcp: keep track of local endpoint still available for each msk")
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-endp-subflow-signal-v1-6-c8a9b036493b@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../testing/selftests/net/mptcp/mptcp_join.sh | 40 ++++++++++++-------
+ 1 file changed, 26 insertions(+), 14 deletions(-)
+
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+index 7043984b7e74a..8ab350059ce10 100755
+--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+@@ -1415,18 +1415,28 @@ chk_add_nr()
+       local add_nr=$1
+       local echo_nr=$2
+       local port_nr=${3:-0}
+-      local syn_nr=${4:-$port_nr}
+-      local syn_ack_nr=${5:-$port_nr}
+-      local ack_nr=${6:-$port_nr}
+-      local mis_syn_nr=${7:-0}
+-      local mis_ack_nr=${8:-0}
++      local ns_invert=${4:-""}
++      local syn_nr=$port_nr
++      local syn_ack_nr=$port_nr
++      local ack_nr=$port_nr
++      local mis_syn_nr=0
++      local mis_ack_nr=0
++      local ns_tx=$ns1
++      local ns_rx=$ns2
++      local extra_msg=""
+       local count
+       local timeout
+-      timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout)
++      if [[ $ns_invert = "invert" ]]; then
++              ns_tx=$ns2
++              ns_rx=$ns1
++              extra_msg="invert"
++      fi
++
++      timeout=$(ip netns exec ${ns_tx} sysctl -n net.mptcp.add_addr_timeout)
+       print_check "add"
+-      count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtAddAddr")
++      count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtAddAddr")
+       if [ -z "$count" ]; then
+               print_skip
+       # if the test configured a short timeout tolerate greater then expected
+@@ -1438,7 +1448,7 @@ chk_add_nr()
+       fi
+       print_check "echo"
+-      count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtEchoAdd")
++      count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtEchoAdd")
+       if [ -z "$count" ]; then
+               print_skip
+       elif [ "$count" != "$echo_nr" ]; then
+@@ -1449,7 +1459,7 @@ chk_add_nr()
+       if [ $port_nr -gt 0 ]; then
+               print_check "pt"
+-              count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtPortAdd")
++              count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtPortAdd")
+               if [ -z "$count" ]; then
+                       print_skip
+               elif [ "$count" != "$port_nr" ]; then
+@@ -1459,7 +1469,7 @@ chk_add_nr()
+               fi
+               print_check "syn"
+-              count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortSynRx")
++              count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortSynRx")
+               if [ -z "$count" ]; then
+                       print_skip
+               elif [ "$count" != "$syn_nr" ]; then
+@@ -1470,7 +1480,7 @@ chk_add_nr()
+               fi
+               print_check "synack"
+-              count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx")
++              count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPJoinPortSynAckRx")
+               if [ -z "$count" ]; then
+                       print_skip
+               elif [ "$count" != "$syn_ack_nr" ]; then
+@@ -1481,7 +1491,7 @@ chk_add_nr()
+               fi
+               print_check "ack"
+-              count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortAckRx")
++              count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortAckRx")
+               if [ -z "$count" ]; then
+                       print_skip
+               elif [ "$count" != "$ack_nr" ]; then
+@@ -1492,7 +1502,7 @@ chk_add_nr()
+               fi
+               print_check "syn"
+-              count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortSynRx")
++              count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortSynRx")
+               if [ -z "$count" ]; then
+                       print_skip
+               elif [ "$count" != "$mis_syn_nr" ]; then
+@@ -1503,7 +1513,7 @@ chk_add_nr()
+               fi
+               print_check "ack"
+-              count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortAckRx")
++              count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortAckRx")
+               if [ -z "$count" ]; then
+                       print_skip
+               elif [ "$count" != "$mis_ack_nr" ]; then
+@@ -1513,6 +1523,8 @@ chk_add_nr()
+                       print_ok
+               fi
+       fi
++
++      print_info "$extra_msg"
+ }
+ chk_add_tx_nr()
+-- 
+2.43.0
+
diff --git a/queue-6.10/selftests-mptcp-join-test-both-signal-subflow.patch b/queue-6.10/selftests-mptcp-join-test-both-signal-subflow.patch
new file mode 100644 (file)
index 0000000..7c32aa0
--- /dev/null
@@ -0,0 +1,69 @@
+From 3cc461a175266db86d3e3918e915988108c8953c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 13:05:59 +0200
+Subject: selftests: mptcp: join: test both signal & subflow
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+[ Upstream commit 4d2868b5d191c74262f7407972d68d1bf3245d6a ]
+
+It should be quite uncommon to set both the subflow and the signal
+flags: the initiator of the connection is typically the one creating new
+subflows, not the other peer, then no need to announce additional local
+addresses, and use it to create subflows.
+
+But some people might be confused about the flags, and set both "just to
+be sure at least the right one is set". To verify the previous fix, and
+avoid future regressions, this specific case is now validated: the
+client announces a new address, and initiates a new subflow from the
+same address.
+
+While working on this, another bug has been noticed, where the client
+reset the new subflow because an ADD_ADDR echo got received as the 3rd
+ACK: this new test also explicitly checks that no RST have been sent by
+the client and server.
+
+The 'Fixes' tag here below is the same as the one from the previous
+commit: this patch here is not fixing anything wrong in the selftests,
+but it validates the previous fix for an issue introduced by this commit
+ID.
+
+Fixes: 86e39e04482b ("mptcp: keep track of local endpoint still available for each msk")
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-endp-subflow-signal-v1-7-c8a9b036493b@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/mptcp/mptcp_join.sh | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+index 8ab350059ce10..a3293043c85dd 100755
+--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+@@ -1989,6 +1989,21 @@ signal_address_tests()
+               chk_add_nr 1 1
+       fi
++      # uncommon: subflow and signal flags on the same endpoint
++      # or because the user wrongly picked both, but still expects the client
++      # to create additional subflows
++      if reset "subflow and signal together"; then
++              pm_nl_set_limits $ns1 0 2
++              pm_nl_set_limits $ns2 0 2
++              pm_nl_add_endpoint $ns2 10.0.3.2 flags signal,subflow
++              run_tests $ns1 $ns2 10.0.1.1
++              chk_join_nr 1 1 1
++              chk_add_nr 1 1 0 invert  # only initiated by ns2
++              chk_add_nr 0 0 0         # none initiated by ns1
++              chk_rst_nr 0 0 invert    # no RST sent by the client
++              chk_rst_nr 0 0           # no RST sent by the server
++      fi
++
+       # accept and use add_addr with additional subflows
+       if reset "multiple subflows and signal"; then
+               pm_nl_set_limits $ns1 0 3
+-- 
+2.43.0
+
index 058ef66d012cb6576f1ff9ed811b0d15c3cda1a9..879710093d9e56d8364ea2323f55751037d9b272 100644 (file)
@@ -1 +1,123 @@
 drm-amd-display-refactor-function-dm_dp_mst_is_port_support_mode.patch
+locking-pvqspinlock-correct-the-type-of-old-variable.patch
+perf-x86-intel-cstate-add-arrowlake-support.patch
+perf-x86-intel-cstate-add-lunarlake-support.patch
+perf-x86-intel-cstate-add-pkg-c2-residency-counter-f.patch
+platform-x86-intel-vbtn-protect-acpi-notify-handler-.patch
+irqchip-mbigen-fix-mbigen-node-address-layout.patch
+platform-x86-intel-ifs-initialize-union-ifs_status-t.patch
+jump_label-fix-the-fix-brown-paper-bags-galore.patch
+perf-x86-amd-use-try_cmpxchg-in-events-amd-un-core.c.patch
+perf-x86-intel-support-the-pebs-event-mask.patch
+perf-x86-support-counter-mask.patch
+perf-x86-fix-smp_processor_id-in-preemptible-warning.patch
+selftests-ksft-fix-finished-helper-exit-code-on-skip.patch
+x86-mm-fix-pti_clone_pgtable-alignment-assumption.patch
+x86-mm-fix-pti_clone_entry_text-for-i386.patch
+smb-client-handle-lack-of-fsctl_get_reparse_point-su.patch
+power-supply-rt5033-bring-back-i2c_set_clientdata.patch
+selftests-mptcp-join-ability-to-invert-add_addr-chec.patch
+selftests-mptcp-join-test-both-signal-subflow.patch
+sctp-fix-null-ptr-deref-in-reuseport_add_sock.patch
+net-pse-pd-tps23881-fix-the-device-id-check.patch
+gve-fix-use-of-netif_carrier_ok.patch
+virtio-net-unbreak-vq-resizing-when-coalescing-is-no.patch
+net-usb-qmi_wwan-fix-memory-leak-for-not-ip-packets.patch
+net-bridge-mcast-wait-for-previous-gc-cycles-when-re.patch
+net-linkwatch-use-system_unbound_wq.patch
+net-dsa-microchip-fix-wake-on-lan-check-to-not-retur.patch
+ice-fix-reset-handler.patch
+bluetooth-l2cap-always-unlock-channel-in-l2cap_conle.patch
+bluetooth-hci_sync-avoid-dup-filtering-when-passive-.patch
+net-smc-add-the-max-value-of-fallback-reason-count.patch
+net-dsa-bcm_sf2-fix-a-possible-memory-leak-in-bcm_sf.patch
+bnxt_en-fix-memory-out-of-bounds-in-bnxt_fill_hw_rss.patch
+idpf-fix-memory-leaks-and-crashes-while-performing-a.patch
+idpf-fix-uafs-when-destroying-the-queues.patch
+l2tp-fix-lockdep-splat.patch
+net-bcmgenet-properly-overlay-phy-and-mac-wake-on-la.patch
+net-fec-stop-pps-on-driver-remove.patch
+net-pse-pd-tps23881-include-missing-bitfield.h-heade.patch
+net-dsa-microchip-disable-eee-for-ksz8567-ksz9567-ks.patch
+regmap-kunit-fix-memory-leaks-in-gen_regmap-and-gen_.patch
+gpio-prevent-potential-speculation-leaks-in-gpio_dev.patch
+hwmon-corsair-psu-add-usb-id-of-hx1200i-series-2023-.patch
+revert-rcu-tasks-fix-synchronize_rcu_tasks-vs-zap_pi.patch
+platform-chrome-cros_ec_lpc-add-a-new-quirk-for-acpi.patch
+rcutorture-fix-rcu_torture_fwd_cb_cr-data-race.patch
+md-do-not-delete-safemode_timer-in-mddev_suspend.patch
+md-change-the-return-value-type-of-md_write_start-to.patch
+md-raid5-avoid-bug_on-while-continue-reshape-after-r.patch
+debugobjects-annotate-racy-debug-variables.patch
+nvme-apple-fix-device-reference-counting.patch
+block-change-rq_integrity_vec-to-respect-the-iterato.patch
+irqchip-gic-v3-don-t-return-errors-from-gic_acpi_mat.patch
+rcu-fix-rcu_barrier-vs-post-cpuhp_teardown_cpu-invoc.patch
+clocksource-drivers-sh_cmt-address-race-condition-fo.patch
+acpi-battery-create-alarm-sysfs-attribute-atomically.patch
+acpi-sbs-manage-alarm-sysfs-attribute-through-psy-co.patch
+cpufreq-amd-pstate-allow-users-to-write-default-epp-.patch
+cpufreq-amd-pstate-auto-load-pstate-driver-by-defaul.patch
+soc-qcom-icc-bwmon-allow-for-interrupts-to-be-shared.patch
+xen-privcmd-switch-from-mutex-to-spinlock-for-irqfds.patch
+acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch
+acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch-7833
+thermal-intel-hfi-give-hfi-instances-package-scope.patch
+wifi-nl80211-disallow-setting-special-ap-channel-wid.patch
+wifi-ath12k-fix-race-due-to-setting-ath12k_flag_ext_.patch
+r8169-remove-detection-of-chip-version-11-early-rtl8.patch
+wifi-rtlwifi-handle-return-value-of-usb-init-tx-rx.patch
+wifi-ath12k-fix-memory-leak-in-ath12k_dp_rx_peer_fra.patch
+net-mlx5e-shampo-fix-invalid-wq-linked-list-unlink.patch
+selftests-bpf-fix-send_signal-test-with-nested-confi.patch
+rtnetlink-move-rtnl_lock-handling-out-of-af_netlink.patch
+wifi-rtw89-pci-fix-rx-tag-race-condition-resulting-i.patch
+net-reference-bpf_redirect_info-via-task_struct-on-p.patch
+af_unix-don-t-retry-after-unix_state_lock_nested-in-.patch
+pci-add-edimax-vendor-id-to-pci_ids.h.patch
+wifi-mac80211-fix-null-dereference-at-band-check-in-.patch
+udf-prevent-integer-overflow-in-udf_bitmap_free_bloc.patch
+bpf-add-missing-check_func_arg_reg_off-to-prevent-ou.patch
+wifi-nl80211-don-t-give-key-data-to-userspace.patch
+can-mcp251xfd-tef-prepare-to-workaround-broken-tef-f.patch
+can-mcp251xfd-tef-update-workaround-for-erratum-ds80.patch
+net-stmmac-qcom-ethqos-enable-sgmii-loopback-during-.patch
+mlxsw-pci-lock-configuration-space-of-upstream-bridg.patch
+btrfs-do-not-clear-page-dirty-inside-extent_write_lo.patch
+btrfs-do-not-bug_on-when-freeing-tree-block-after-er.patch
+btrfs-reduce-nesting-for-extent-processing-at-btrfs_.patch
+btrfs-fix-data-race-when-accessing-the-last_trans-fi.patch
+btrfs-fix-bitmap-leak-when-loading-free-space-cache-.patch
+bluetooth-btnxpuart-shutdown-timer-and-prevent-rearm.patch
+drm-xe-preempt_fence-enlarge-the-fence-critical-sect.patch
+drm-amd-display-handle-hpd_irq-for-internal-link.patch
+drm-amd-display-add-delay-to-improve-lttpr-uhbr-inte.patch
+drm-amdgpu-fix-potential-resource-leak-warning.patch
+drm-amdgpu-pm-fix-the-param-type-of-set_power_profil.patch
+drm-amd-amdkfd-fix-a-resource-leak-in-svm_range_vali.patch
+drm-xe-xe_guc_submit-fix-exec-queue-stop-race-condit.patch
+drm-amdgpu-pm-fix-the-null-pointer-dereference-for-s.patch
+drm-amdgpu-fix-the-null-pointer-dereference-to-ras_m.patch
+drm-amdgpu-pm-fix-the-null-pointer-dereference-in-ap.patch
+drm-admgpu-fix-dereferencing-null-pointer-context.patch
+drm-amdgpu-add-lock-around-vf-rlcg-interface.patch
+drm-amd-pm-fix-the-null-pointer-dereference-for-vega.patch
+drm-amd-display-add-null-checks-for-stream-and-plane.patch
+media-amphion-remove-lock-in-s_ctrl-callback.patch
+drm-amd-display-add-null-check-for-afb-before-derefe.patch
+drm-amd-display-wake-dmcub-before-sending-a-command-.patch
+drm-amd-display-reduce-odm-slice-count-to-initial-ne.patch
+drm-amd-display-don-t-refer-to-dc_sink-in-is_dsc_nee.patch
+drm-amd-display-remove-dpp-pipes-on-failure-to-updat.patch
+drm-amd-display-add-null-checker-before-passing-vari.patch
+media-i2c-ov5647-replacing-of_node_put-with-__free-d.patch
+media-uvcvideo-ignore-empty-ts-packets.patch
+media-uvcvideo-fix-the-bandwdith-quirk-on-usb-3.x.patch
+drm-amd-display-fix-null-pointer-dereference-for-dtn.patch
+media-xc2028-avoid-use-after-free-in-load_firmware_c.patch
+ext4-fix-uninitialized-variable-in-ext4_inlinedir_to.patch
+jbd2-avoid-memleak-in-jbd2_journal_write_metadata_bu.patch
+drm-amd-display-fix-null-pointer-deref-in-dcn20_reso.patch
+s390-sclp-prevent-release-of-buffer-in-i-o.patch
+ext4-sanity-check-for-null-pointer-after-ext4_force_.patch
+sunrpc-fix-a-race-to-wake-a-sync-task.patch
diff --git a/queue-6.10/smb-client-handle-lack-of-fsctl_get_reparse_point-su.patch b/queue-6.10/smb-client-handle-lack-of-fsctl_get_reparse_point-su.patch
new file mode 100644 (file)
index 0000000..7528140
--- /dev/null
@@ -0,0 +1,134 @@
+From 9a7075723424ef12129d1a1b93d081871fa45c80 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 10:23:39 -0300
+Subject: smb: client: handle lack of FSCTL_GET_REPARSE_POINT support
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+[ Upstream commit 4b96024ef2296b1d323af327cae5e52809b61420 ]
+
+As per MS-FSA 2.1.5.10.14, support for FSCTL_GET_REPARSE_POINT is
+optional and if the server doesn't support it,
+STATUS_INVALID_DEVICE_REQUEST must be returned for the operation.
+
+If we find files with reparse points and we can't read them due to
+lack of client or server support, just ignore it and then treat them
+as regular files or junctions.
+
+Fixes: 5f71ebc41294 ("smb: client: parse reparse point flag in create response")
+Reported-by: Sebastian Steinbeisser <Sebastian.Steinbeisser@lrz.de>
+Tested-by: Sebastian Steinbeisser <Sebastian.Steinbeisser@lrz.de>
+Acked-by: Tom Talpey <tom@talpey.com>
+Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/inode.c     | 17 +++++++++++++++--
+ fs/smb/client/reparse.c   |  4 ++++
+ fs/smb/client/reparse.h   | 19 +++++++++++++++++--
+ fs/smb/client/smb2inode.c |  2 ++
+ 4 files changed, 38 insertions(+), 4 deletions(-)
+
+diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
+index 4a8aa1de95223..dd0afa23734c8 100644
+--- a/fs/smb/client/inode.c
++++ b/fs/smb/client/inode.c
+@@ -1042,13 +1042,26 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
+       }
+       rc = -EOPNOTSUPP;
+-      switch ((data->reparse.tag = tag)) {
+-      case 0: /* SMB1 symlink */
++      data->reparse.tag = tag;
++      if (!data->reparse.tag) {
+               if (server->ops->query_symlink) {
+                       rc = server->ops->query_symlink(xid, tcon,
+                                                       cifs_sb, full_path,
+                                                       &data->symlink_target);
+               }
++              if (rc == -EOPNOTSUPP)
++                      data->reparse.tag = IO_REPARSE_TAG_INTERNAL;
++      }
++
++      switch (data->reparse.tag) {
++      case 0: /* SMB1 symlink */
++              break;
++      case IO_REPARSE_TAG_INTERNAL:
++              rc = 0;
++              if (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY) {
++                      cifs_create_junction_fattr(fattr, sb);
++                      goto out;
++              }
+               break;
+       case IO_REPARSE_TAG_MOUNT_POINT:
+               cifs_create_junction_fattr(fattr, sb);
+diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
+index a0ffbda907331..689d8a506d459 100644
+--- a/fs/smb/client/reparse.c
++++ b/fs/smb/client/reparse.c
+@@ -505,6 +505,10 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
+       }
+       switch (tag) {
++      case IO_REPARSE_TAG_INTERNAL:
++              if (!(fattr->cf_cifsattrs & ATTR_DIRECTORY))
++                      return false;
++              fallthrough;
+       case IO_REPARSE_TAG_DFS:
+       case IO_REPARSE_TAG_DFSR:
+       case IO_REPARSE_TAG_MOUNT_POINT:
+diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
+index 6b55d1df9e2f8..2c0644bc4e65a 100644
+--- a/fs/smb/client/reparse.h
++++ b/fs/smb/client/reparse.h
+@@ -12,6 +12,12 @@
+ #include "fs_context.h"
+ #include "cifsglob.h"
++/*
++ * Used only by cifs.ko to ignore reparse points from files when client or
++ * server doesn't support FSCTL_GET_REPARSE_POINT.
++ */
++#define IO_REPARSE_TAG_INTERNAL ((__u32)~0U)
++
+ static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf)
+ {
+       u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer);
+@@ -78,10 +84,19 @@ static inline u32 reparse_mode_wsl_tag(mode_t mode)
+ static inline bool reparse_inode_match(struct inode *inode,
+                                      struct cifs_fattr *fattr)
+ {
++      struct cifsInodeInfo *cinode = CIFS_I(inode);
+       struct timespec64 ctime = inode_get_ctime(inode);
+-      return (CIFS_I(inode)->cifsAttrs & ATTR_REPARSE) &&
+-              CIFS_I(inode)->reparse_tag == fattr->cf_cifstag &&
++      /*
++       * Do not match reparse tags when client or server doesn't support
++       * FSCTL_GET_REPARSE_POINT.  @fattr->cf_cifstag should contain correct
++       * reparse tag from query dir response but the client won't be able to
++       * read the reparse point data anyway.  This spares us a revalidation.
++       */
++      if (cinode->reparse_tag != IO_REPARSE_TAG_INTERNAL &&
++          cinode->reparse_tag != fattr->cf_cifstag)
++              return false;
++      return (cinode->cifsAttrs & ATTR_REPARSE) &&
+               timespec64_equal(&ctime, &fattr->cf_ctime);
+ }
+diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
+index 5c02a12251c84..062b86a4936fd 100644
+--- a/fs/smb/client/smb2inode.c
++++ b/fs/smb/client/smb2inode.c
+@@ -930,6 +930,8 @@ int smb2_query_path_info(const unsigned int xid,
+       switch (rc) {
+       case 0:
++              rc = parse_create_response(data, cifs_sb, &out_iov[0]);
++              break;
+       case -EOPNOTSUPP:
+               /*
+                * BB TODO: When support for special files added to Samba
+-- 
+2.43.0
+
diff --git a/queue-6.10/soc-qcom-icc-bwmon-allow-for-interrupts-to-be-shared.patch b/queue-6.10/soc-qcom-icc-bwmon-allow-for-interrupts-to-be-shared.patch
new file mode 100644 (file)
index 0000000..dcf3631
--- /dev/null
@@ -0,0 +1,61 @@
+From c0664fb300408b27a12b709a39a168c2e3c3cd07 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jun 2024 14:52:13 +0530
+Subject: soc: qcom: icc-bwmon: Allow for interrupts to be shared across
+ instances
+
+From: Sibi Sankar <quic_sibis@quicinc.com>
+
+[ Upstream commit dc18836435e7f8dda019db2c618c69194933157f ]
+
+The multiple BWMONv4 instances available on the X1E80100 SoC use the
+same interrupt number. Mark them are shared to allow for re-use across
+instances.
+
+Using IRQF_SHARED coupled with devm_request_threaded_irq implies that
+the irq can still trigger during/after bwmon_remove due to other active
+bwmon instances. Handle this race by relying on bwmon_disable to disable
+the interrupt and coupled with explicit request/free irqs.
+
+Signed-off-by: Sibi Sankar <quic_sibis@quicinc.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20240624092214.146935-4-quic_sibis@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/icc-bwmon.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
+index ecddb60bd6650..e7851974084b6 100644
+--- a/drivers/soc/qcom/icc-bwmon.c
++++ b/drivers/soc/qcom/icc-bwmon.c
+@@ -783,9 +783,14 @@ static int bwmon_probe(struct platform_device *pdev)
+       bwmon->dev = dev;
+       bwmon_disable(bwmon);
+-      ret = devm_request_threaded_irq(dev, bwmon->irq, bwmon_intr,
+-                                      bwmon_intr_thread,
+-                                      IRQF_ONESHOT, dev_name(dev), bwmon);
++
++      /*
++       * SoCs with multiple cpu-bwmon instances can end up using a shared interrupt
++       * line. Using the devm_ variant might result in the IRQ handler being executed
++       * after bwmon_disable in bwmon_remove()
++       */
++      ret = request_threaded_irq(bwmon->irq, bwmon_intr, bwmon_intr_thread,
++                                 IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), bwmon);
+       if (ret)
+               return dev_err_probe(dev, ret, "failed to request IRQ\n");
+@@ -800,6 +805,7 @@ static void bwmon_remove(struct platform_device *pdev)
+       struct icc_bwmon *bwmon = platform_get_drvdata(pdev);
+       bwmon_disable(bwmon);
++      free_irq(bwmon->irq, bwmon);
+ }
+ static const struct icc_bwmon_data msm8998_bwmon_data = {
+-- 
+2.43.0
+
diff --git a/queue-6.10/sunrpc-fix-a-race-to-wake-a-sync-task.patch b/queue-6.10/sunrpc-fix-a-race-to-wake-a-sync-task.patch
new file mode 100644 (file)
index 0000000..f81efa5
--- /dev/null
@@ -0,0 +1,53 @@
+From ac69c54756981d59319f63c63598c30005cf18d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jul 2024 10:49:33 -0400
+Subject: SUNRPC: Fix a race to wake a sync task
+
+From: Benjamin Coddington <bcodding@redhat.com>
+
+[ Upstream commit ed0172af5d6fc07d1b40ca82f5ca3979300369f7 ]
+
+We've observed NFS clients with sync tasks sleeping in __rpc_execute
+waiting on RPC_TASK_QUEUED that have not responded to a wake-up from
+rpc_make_runnable().  I suspect this problem usually goes unnoticed,
+because on a busy client the task will eventually be re-awoken by another
+task completion or xprt event.  However, if the state manager is draining
+the slot table, a sync task missing a wake-up can result in a hung client.
+
+We've been able to prove that the waker in rpc_make_runnable() successfully
+calls wake_up_bit() (ie- there's no race to tk_runstate), but the
+wake_up_bit() call fails to wake the waiter.  I suspect the waker is
+missing the load of the bit's wait_queue_head, so waitqueue_active() is
+false.  There are some very helpful comments about this problem above
+wake_up_bit(), prepare_to_wait(), and waitqueue_active().
+
+Fix this by inserting smp_mb__after_atomic() before the wake_up_bit(),
+which pairs with prepare_to_wait() calling set_current_state().
+
+Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sunrpc/sched.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
+index 6debf4fd42d4e..cef623ea15060 100644
+--- a/net/sunrpc/sched.c
++++ b/net/sunrpc/sched.c
+@@ -369,8 +369,10 @@ static void rpc_make_runnable(struct workqueue_struct *wq,
+       if (RPC_IS_ASYNC(task)) {
+               INIT_WORK(&task->u.tk_work, rpc_async_schedule);
+               queue_work(wq, &task->u.tk_work);
+-      } else
++      } else {
++              smp_mb__after_atomic();
+               wake_up_bit(&task->tk_runstate, RPC_TASK_QUEUED);
++      }
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.10/thermal-intel-hfi-give-hfi-instances-package-scope.patch b/queue-6.10/thermal-intel-hfi-give-hfi-instances-package-scope.patch
new file mode 100644 (file)
index 0000000..32a323a
--- /dev/null
@@ -0,0 +1,125 @@
+From 2ec2adabc97a9bdb14c023d44ce6706c8265be4e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jul 2024 13:54:45 +0800
+Subject: thermal: intel: hfi: Give HFI instances package scope
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+[ Upstream commit b755367602d70deade956cbe0b8a3f5a12f569dc ]
+
+The Intel Software Developer's Manual defines the scope of HFI (registers
+and memory buffer) as a package. Use package scope(*) in the software
+representation of an HFI instance.
+
+Using die scope in HFI instances has the effect of creating multiple
+conflicting instances for the same package: each instance allocates its
+own memory buffer and configures the same package-level registers.
+Specifically, only one of the allocated memory buffers can be set in the
+MSR_IA32_HW_FEEDBACK_PTR register. CPUs get incorrect HFI data from the
+table.
+
+The problem does not affect current HFI-capable platforms because they
+all have single-die processors.
+
+(*) We used die scope for HFI instances because there had been
+    processors with packages enumerated as dies. None of those systems
+    supported HFI, though. If such a system emerged, it would need to
+    be quirked.
+
+Co-developed-by: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+Reviewed-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
+Link: https://patch.msgid.link/20240703055445.125362-1-rui.zhang@intel.com
+[ rjw: Changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/thermal/intel/intel_hfi.c | 30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/intel_hfi.c
+index a180a98bb9f15..5b18a46a10b06 100644
+--- a/drivers/thermal/intel/intel_hfi.c
++++ b/drivers/thermal/intel/intel_hfi.c
+@@ -401,10 +401,10 @@ static void hfi_disable(void)
+  * intel_hfi_online() - Enable HFI on @cpu
+  * @cpu:      CPU in which the HFI will be enabled
+  *
+- * Enable the HFI to be used in @cpu. The HFI is enabled at the die/package
+- * level. The first CPU in the die/package to come online does the full HFI
++ * Enable the HFI to be used in @cpu. The HFI is enabled at the package
++ * level. The first CPU in the package to come online does the full HFI
+  * initialization. Subsequent CPUs will just link themselves to the HFI
+- * instance of their die/package.
++ * instance of their package.
+  *
+  * This function is called before enabling the thermal vector in the local APIC
+  * in order to ensure that @cpu has an associated HFI instance when it receives
+@@ -414,31 +414,31 @@ void intel_hfi_online(unsigned int cpu)
+ {
+       struct hfi_instance *hfi_instance;
+       struct hfi_cpu_info *info;
+-      u16 die_id;
++      u16 pkg_id;
+       /* Nothing to do if hfi_instances are missing. */
+       if (!hfi_instances)
+               return;
+       /*
+-       * Link @cpu to the HFI instance of its package/die. It does not
++       * Link @cpu to the HFI instance of its package. It does not
+        * matter whether the instance has been initialized.
+        */
+       info = &per_cpu(hfi_cpu_info, cpu);
+-      die_id = topology_logical_die_id(cpu);
++      pkg_id = topology_logical_package_id(cpu);
+       hfi_instance = info->hfi_instance;
+       if (!hfi_instance) {
+-              if (die_id >= max_hfi_instances)
++              if (pkg_id >= max_hfi_instances)
+                       return;
+-              hfi_instance = &hfi_instances[die_id];
++              hfi_instance = &hfi_instances[pkg_id];
+               info->hfi_instance = hfi_instance;
+       }
+       init_hfi_cpu_index(info);
+       /*
+-       * Now check if the HFI instance of the package/die of @cpu has been
++       * Now check if the HFI instance of the package of @cpu has been
+        * initialized (by checking its header). In such case, all we have to
+        * do is to add @cpu to this instance's cpumask and enable the instance
+        * if needed.
+@@ -504,7 +504,7 @@ void intel_hfi_online(unsigned int cpu)
+  *
+  * On some processors, hardware remembers previous programming settings even
+  * after being reprogrammed. Thus, keep HFI enabled even if all CPUs in the
+- * die/package of @cpu are offline. See note in intel_hfi_online().
++ * package of @cpu are offline. See note in intel_hfi_online().
+  */
+ void intel_hfi_offline(unsigned int cpu)
+ {
+@@ -674,9 +674,13 @@ void __init intel_hfi_init(void)
+       if (hfi_parse_features())
+               return;
+-      /* There is one HFI instance per die/package. */
+-      max_hfi_instances = topology_max_packages() *
+-                          topology_max_dies_per_package();
++      /*
++       * Note: HFI resources are managed at the physical package scope.
++       * There could be platforms that enumerate packages as Linux dies.
++       * Special handling would be needed if this happens on an HFI-capable
++       * platform.
++       */
++      max_hfi_instances = topology_max_packages();
+       /*
+        * This allocation may fail. CPU hotplug callbacks must check
+-- 
+2.43.0
+
diff --git a/queue-6.10/udf-prevent-integer-overflow-in-udf_bitmap_free_bloc.patch b/queue-6.10/udf-prevent-integer-overflow-in-udf_bitmap_free_bloc.patch
new file mode 100644 (file)
index 0000000..3948be6
--- /dev/null
@@ -0,0 +1,113 @@
+From 7037c8e9ddb173ac89ddeef484fccf17f5d15bde Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jun 2024 10:24:13 +0300
+Subject: udf: prevent integer overflow in udf_bitmap_free_blocks()
+
+From: Roman Smirnov <r.smirnov@omp.ru>
+
+[ Upstream commit 56e69e59751d20993f243fb7dd6991c4e522424c ]
+
+An overflow may occur if the function is called with the last
+block and an offset greater than zero. It is necessary to add
+a check to avoid this.
+
+Found by Linux Verification Center (linuxtesting.org) with Svace.
+
+[JK: Make test cover also unalloc table freeing]
+
+Link: https://patch.msgid.link/20240620072413.7448-1-r.smirnov@omp.ru
+Suggested-by: Jan Kara <jack@suse.com>
+Signed-off-by: Roman Smirnov <r.smirnov@omp.ru>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/udf/balloc.c | 36 +++++++++++++-----------------------
+ 1 file changed, 13 insertions(+), 23 deletions(-)
+
+diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
+index 558ad046972ad..bb471ec364046 100644
+--- a/fs/udf/balloc.c
++++ b/fs/udf/balloc.c
+@@ -18,6 +18,7 @@
+ #include "udfdecl.h"
+ #include <linux/bitops.h>
++#include <linux/overflow.h>
+ #include "udf_i.h"
+ #include "udf_sb.h"
+@@ -140,7 +141,6 @@ static void udf_bitmap_free_blocks(struct super_block *sb,
+ {
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       struct buffer_head *bh = NULL;
+-      struct udf_part_map *partmap;
+       unsigned long block;
+       unsigned long block_group;
+       unsigned long bit;
+@@ -149,19 +149,9 @@ static void udf_bitmap_free_blocks(struct super_block *sb,
+       unsigned long overflow;
+       mutex_lock(&sbi->s_alloc_mutex);
+-      partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
+-      if (bloc->logicalBlockNum + count < count ||
+-          (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
+-              udf_debug("%u < %d || %u + %u > %u\n",
+-                        bloc->logicalBlockNum, 0,
+-                        bloc->logicalBlockNum, count,
+-                        partmap->s_partition_len);
+-              goto error_return;
+-      }
+-
++      /* We make sure this cannot overflow when mounting the filesystem */
+       block = bloc->logicalBlockNum + offset +
+               (sizeof(struct spaceBitmapDesc) << 3);
+-
+       do {
+               overflow = 0;
+               block_group = block >> (sb->s_blocksize_bits + 3);
+@@ -391,7 +381,6 @@ static void udf_table_free_blocks(struct super_block *sb,
+                                 uint32_t count)
+ {
+       struct udf_sb_info *sbi = UDF_SB(sb);
+-      struct udf_part_map *partmap;
+       uint32_t start, end;
+       uint32_t elen;
+       struct kernel_lb_addr eloc;
+@@ -400,16 +389,6 @@ static void udf_table_free_blocks(struct super_block *sb,
+       struct udf_inode_info *iinfo;
+       mutex_lock(&sbi->s_alloc_mutex);
+-      partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
+-      if (bloc->logicalBlockNum + count < count ||
+-          (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
+-              udf_debug("%u < %d || %u + %u > %u\n",
+-                        bloc->logicalBlockNum, 0,
+-                        bloc->logicalBlockNum, count,
+-                        partmap->s_partition_len);
+-              goto error_return;
+-      }
+-
+       iinfo = UDF_I(table);
+       udf_add_free_space(sb, sbi->s_partition, count);
+@@ -684,6 +663,17 @@ void udf_free_blocks(struct super_block *sb, struct inode *inode,
+ {
+       uint16_t partition = bloc->partitionReferenceNum;
+       struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
++      uint32_t blk;
++
++      if (check_add_overflow(bloc->logicalBlockNum, offset, &blk) ||
++          check_add_overflow(blk, count, &blk) ||
++          bloc->logicalBlockNum + count > map->s_partition_len) {
++              udf_debug("Invalid request to free blocks: (%d, %u), off %u, "
++                        "len %u, partition len %u\n",
++                        partition, bloc->logicalBlockNum, offset, count,
++                        map->s_partition_len);
++              return;
++      }
+       if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) {
+               udf_bitmap_free_blocks(sb, map->s_uspace.s_bitmap,
+-- 
+2.43.0
+
diff --git a/queue-6.10/virtio-net-unbreak-vq-resizing-when-coalescing-is-no.patch b/queue-6.10/virtio-net-unbreak-vq-resizing-when-coalescing-is-no.patch
new file mode 100644 (file)
index 0000000..a12c736
--- /dev/null
@@ -0,0 +1,55 @@
+From 7f6adfb3e6f58e0744f80dec409f7dac7a881e4c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 21:23:38 +0800
+Subject: virtio-net: unbreak vq resizing when coalescing is not negotiated
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Heng Qi <hengqi@linux.alibaba.com>
+
+[ Upstream commit 4ba8d97083707409822264fd1776aad7233f353e ]
+
+Don't break the resize action if the vq coalescing feature
+named VIRTIO_NET_F_VQ_NOTF_COAL is not negotiated.
+
+Fixes: f61fe5f081cf ("virtio-net: fix the vq coalescing setting for vq resize")
+Signed-off-by: Heng Qi <hengqi@linux.alibaba.com>
+Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Acked-by: Eugenio Pé rez <eperezma@redhat.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/virtio_net.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 5161e7efda2cb..f32e017b62e9b 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -3257,7 +3257,11 @@ static int virtnet_set_ringparam(struct net_device *dev,
+                       err = virtnet_send_tx_ctrl_coal_vq_cmd(vi, i,
+                                                              vi->intr_coal_tx.max_usecs,
+                                                              vi->intr_coal_tx.max_packets);
+-                      if (err)
++
++                      /* Don't break the tx resize action if the vq coalescing is not
++                       * supported. The same is true for rx resize below.
++                       */
++                      if (err && err != -EOPNOTSUPP)
+                               return err;
+               }
+@@ -3272,7 +3276,7 @@ static int virtnet_set_ringparam(struct net_device *dev,
+                                                              vi->intr_coal_rx.max_usecs,
+                                                              vi->intr_coal_rx.max_packets);
+                       mutex_unlock(&vi->rq[i].dim_lock);
+-                      if (err)
++                      if (err && err != -EOPNOTSUPP)
+                               return err;
+               }
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/wifi-ath12k-fix-memory-leak-in-ath12k_dp_rx_peer_fra.patch b/queue-6.10/wifi-ath12k-fix-memory-leak-in-ath12k_dp_rx_peer_fra.patch
new file mode 100644 (file)
index 0000000..7a2cef3
--- /dev/null
@@ -0,0 +1,40 @@
+From ff178d8b532a407e5ef2a9c4c5b6636a28ffb4f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 May 2024 20:42:26 +0800
+Subject: wifi: ath12k: fix memory leak in ath12k_dp_rx_peer_frag_setup()
+
+From: Baochen Qiang <quic_bqiang@quicinc.com>
+
+[ Upstream commit 3d60041543189438cd1b03a1fa40ff6681c77970 ]
+
+Currently the resource allocated by crypto_alloc_shash() is not
+freed in case ath12k_peer_find() fails, resulting in memory leak.
+
+Add crypto_free_shash() to fix it.
+
+This is found during code review, compile tested only.
+
+Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://msgid.link/20240526124226.24661-1-quic_bqiang@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/dp_rx.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
+index 121f27284be59..1d287ed25a949 100644
+--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
+@@ -2793,6 +2793,7 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev
+       peer = ath12k_peer_find(ab, vdev_id, peer_mac);
+       if (!peer) {
+               spin_unlock_bh(&ab->base_lock);
++              crypto_free_shash(tfm);
+               ath12k_warn(ab, "failed to find the peer to set up fragment info\n");
+               return -ENOENT;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.10/wifi-ath12k-fix-race-due-to-setting-ath12k_flag_ext_.patch b/queue-6.10/wifi-ath12k-fix-race-due-to-setting-ath12k_flag_ext_.patch
new file mode 100644 (file)
index 0000000..0ab444d
--- /dev/null
@@ -0,0 +1,75 @@
+From 0fc79574406532ac31165c556c8cc8365bcabb53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 May 2024 10:36:42 +0800
+Subject: wifi: ath12k: fix race due to setting ATH12K_FLAG_EXT_IRQ_ENABLED too
+ early
+
+From: Baochen Qiang <quic_bqiang@quicinc.com>
+
+[ Upstream commit 0a993772e0f0934d730c0d451622c80e03a40ab1 ]
+
+Commit 5082b3e3027e ("wifi: ath11k: fix race due to setting
+ATH11K_FLAG_EXT_IRQ_ENABLED too early") fixes a race in ath11k
+driver. Since ath12k shares the same logic as ath11k, currently
+the race also exists in ath12k: in ath12k_pci_ext_irq_enable(),
+ATH12K_FLAG_EXT_IRQ_ENABLED is set before NAPI is enabled.
+In cases where only one MSI vector is allocated, this results
+in a race condition: after ATH12K_FLAG_EXT_IRQ_ENABLED is set
+but before NAPI enabled, CE interrupt breaks in. Since IRQ is
+shared by CE and data path, ath12k_pci_ext_interrupt_handler()
+is also called where we call disable_irq_nosync() to disable
+IRQ. Then napi_schedule() is called but it does nothing because
+NAPI is not enabled at that time, meaning that
+ath12k_pci_ext_grp_napi_poll() will never run, so we have
+no chance to call enable_irq() to enable IRQ back. Since IRQ
+is shared, all interrupts are disabled and we would finally
+get no response from target.
+
+So port ath11k fix here, this is done by setting
+ATH12K_FLAG_EXT_IRQ_ENABLED after all NAPI and IRQ work are
+done. With the fix, we are sure that by the time
+ATH12K_FLAG_EXT_IRQ_ENABLED is set, NAPI is enabled.
+
+Note that the fix above also introduce some side effects:
+if ath12k_pci_ext_interrupt_handler() breaks in after NAPI
+enabled but before ATH12K_FLAG_EXT_IRQ_ENABLED set, nothing
+will be done by the handler this time, the work will be
+postponed till the next time the IRQ fires.
+
+This is found during code review.
+
+Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
+
+Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://msgid.link/20240524023642.37030-1-quic_bqiang@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/pci.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
+index 55fde0d33183c..f92b4ce49dfd4 100644
+--- a/drivers/net/wireless/ath/ath12k/pci.c
++++ b/drivers/net/wireless/ath/ath12k/pci.c
+@@ -1091,14 +1091,14 @@ void ath12k_pci_ext_irq_enable(struct ath12k_base *ab)
+ {
+       int i;
+-      set_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags);
+-
+       for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {
+               struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
+               napi_enable(&irq_grp->napi);
+               ath12k_pci_ext_grp_enable(irq_grp);
+       }
++
++      set_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags);
+ }
+ void ath12k_pci_ext_irq_disable(struct ath12k_base *ab)
+-- 
+2.43.0
+
diff --git a/queue-6.10/wifi-mac80211-fix-null-dereference-at-band-check-in-.patch b/queue-6.10/wifi-mac80211-fix-null-dereference-at-band-check-in-.patch
new file mode 100644 (file)
index 0000000..d832fee
--- /dev/null
@@ -0,0 +1,110 @@
+From 3d948b9ac5f1492d6a0cc4165c3c33f8139e1bfa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jun 2024 19:52:17 +0800
+Subject: wifi: mac80211: fix NULL dereference at band check in starting tx ba
+ session
+
+From: Zong-Zhe Yang <kevin_yang@realtek.com>
+
+[ Upstream commit 021d53a3d87eeb9dbba524ac515651242a2a7e3b ]
+
+In MLD connection, link_data/link_conf are dynamically allocated. They
+don't point to vif->bss_conf. So, there will be no chanreq assigned to
+vif->bss_conf and then the chan will be NULL. Tweak the code to check
+ht_supported/vht_supported/has_he/has_eht on sta deflink.
+
+Crash log (with rtw89 version under MLO development):
+[ 9890.526087] BUG: kernel NULL pointer dereference, address: 0000000000000000
+[ 9890.526102] #PF: supervisor read access in kernel mode
+[ 9890.526105] #PF: error_code(0x0000) - not-present page
+[ 9890.526109] PGD 0 P4D 0
+[ 9890.526114] Oops: 0000 [#1] PREEMPT SMP PTI
+[ 9890.526119] CPU: 2 PID: 6367 Comm: kworker/u16:2 Kdump: loaded Tainted: G           OE      6.9.0 #1
+[ 9890.526123] Hardware name: LENOVO 2356AD1/2356AD1, BIOS G7ETB3WW (2.73 ) 11/28/2018
+[ 9890.526126] Workqueue: phy2 rtw89_core_ba_work [rtw89_core]
+[ 9890.526203] RIP: 0010:ieee80211_start_tx_ba_session (net/mac80211/agg-tx.c:618 (discriminator 1)) mac80211
+[ 9890.526279] Code: f7 e8 d5 93 3e ea 48 83 c4 28 89 d8 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 49 8b 84 24 e0 f1 ff ff 48 8b 80 90 1b 00 00 <83> 38 03 0f 84 37 fe ff ff bb ea ff ff ff eb cc 49 8b 84 24 10 f3
+All code
+========
+   0:  f7 e8                   imul   %eax
+   2:  d5                      (bad)
+   3:  93                      xchg   %eax,%ebx
+   4:  3e ea                   ds (bad)
+   6:  48 83 c4 28             add    $0x28,%rsp
+   a:  89 d8                   mov    %ebx,%eax
+   c:  5b                      pop    %rbx
+   d:  41 5c                   pop    %r12
+   f:  41 5d                   pop    %r13
+  11:  41 5e                   pop    %r14
+  13:  41 5f                   pop    %r15
+  15:  5d                      pop    %rbp
+  16:  c3                      retq
+  17:  cc                      int3
+  18:  cc                      int3
+  19:  cc                      int3
+  1a:  cc                      int3
+  1b:  49 8b 84 24 e0 f1 ff    mov    -0xe20(%r12),%rax
+  22:  ff
+  23:  48 8b 80 90 1b 00 00    mov    0x1b90(%rax),%rax
+  2a:* 83 38 03                cmpl   $0x3,(%rax)              <-- trapping instruction
+  2d:  0f 84 37 fe ff ff       je     0xfffffffffffffe6a
+  33:  bb ea ff ff ff          mov    $0xffffffea,%ebx
+  38:  eb cc                   jmp    0x6
+  3a:  49                      rex.WB
+  3b:  8b                      .byte 0x8b
+  3c:  84 24 10                test   %ah,(%rax,%rdx,1)
+  3f:  f3                      repz
+
+Code starting with the faulting instruction
+===========================================
+   0:  83 38 03                cmpl   $0x3,(%rax)
+   3:  0f 84 37 fe ff ff       je     0xfffffffffffffe40
+   9:  bb ea ff ff ff          mov    $0xffffffea,%ebx
+   e:  eb cc                   jmp    0xffffffffffffffdc
+  10:  49                      rex.WB
+  11:  8b                      .byte 0x8b
+  12:  84 24 10                test   %ah,(%rax,%rdx,1)
+  15:  f3                      repz
+[ 9890.526285] RSP: 0018:ffffb8db09013d68 EFLAGS: 00010246
+[ 9890.526291] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff9308e0d656c8
+[ 9890.526295] RDX: 0000000000000000 RSI: ffffffffab99460b RDI: ffffffffab9a7685
+[ 9890.526300] RBP: ffffb8db09013db8 R08: 0000000000000000 R09: 0000000000000873
+[ 9890.526304] R10: ffff9308e0d64800 R11: 0000000000000002 R12: ffff9308e5ff6e70
+[ 9890.526308] R13: ffff930952500e20 R14: ffff9309192a8c00 R15: 0000000000000000
+[ 9890.526313] FS:  0000000000000000(0000) GS:ffff930b4e700000(0000) knlGS:0000000000000000
+[ 9890.526316] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 9890.526318] CR2: 0000000000000000 CR3: 0000000391c58005 CR4: 00000000001706f0
+[ 9890.526321] Call Trace:
+[ 9890.526324]  <TASK>
+[ 9890.526327] ? show_regs (arch/x86/kernel/dumpstack.c:479)
+[ 9890.526335] ? __die (arch/x86/kernel/dumpstack.c:421 arch/x86/kernel/dumpstack.c:434)
+[ 9890.526340] ? page_fault_oops (arch/x86/mm/fault.c:713)
+[ 9890.526347] ? search_module_extables (kernel/module/main.c:3256 (discriminator 3))
+[ 9890.526353] ? ieee80211_start_tx_ba_session (net/mac80211/agg-tx.c:618 (discriminator 1)) mac80211
+
+Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
+Link: https://patch.msgid.link/20240617115217.22344-1-kevin_yang@realtek.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/agg-tx.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
+index 21d55dc539f6c..677bbbac9f169 100644
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -616,7 +616,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
+               return -EINVAL;
+       if (!pubsta->deflink.ht_cap.ht_supported &&
+-          sta->sdata->vif.bss_conf.chanreq.oper.chan->band != NL80211_BAND_6GHZ)
++          !pubsta->deflink.vht_cap.vht_supported &&
++          !pubsta->deflink.he_cap.has_he &&
++          !pubsta->deflink.eht_cap.has_eht)
+               return -EINVAL;
+       if (WARN_ON_ONCE(!local->ops->ampdu_action))
+-- 
+2.43.0
+
diff --git a/queue-6.10/wifi-nl80211-disallow-setting-special-ap-channel-wid.patch b/queue-6.10/wifi-nl80211-disallow-setting-special-ap-channel-wid.patch
new file mode 100644 (file)
index 0000000..8e8d05a
--- /dev/null
@@ -0,0 +1,62 @@
+From 128d3b9c21d94b6bce2f537c77f5cbc686cef97d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 May 2024 14:16:00 +0200
+Subject: wifi: nl80211: disallow setting special AP channel widths
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 23daf1b4c91db9b26f8425cc7039cf96d22ccbfe ]
+
+Setting the AP channel width is meant for use with the normal
+20/40/... MHz channel width progression, and switching around
+in S1G or narrow channels isn't supported. Disallow that.
+
+Reported-by: syzbot+bc0f5b92cc7091f45fb6@syzkaller.appspotmail.com
+Link: https://msgid.link/20240515141600.d4a9590bfe32.I19a32d60097e81b527eafe6b0924f6c5fbb2dc45@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/nl80211.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 0fd075238fc74..07538be6805ef 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -3422,6 +3422,33 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
+                       if (chandef.chan != cur_chan)
+                               return -EBUSY;
++                      /* only allow this for regular channel widths */
++                      switch (wdev->links[link_id].ap.chandef.width) {
++                      case NL80211_CHAN_WIDTH_20_NOHT:
++                      case NL80211_CHAN_WIDTH_20:
++                      case NL80211_CHAN_WIDTH_40:
++                      case NL80211_CHAN_WIDTH_80:
++                      case NL80211_CHAN_WIDTH_80P80:
++                      case NL80211_CHAN_WIDTH_160:
++                      case NL80211_CHAN_WIDTH_320:
++                              break;
++                      default:
++                              return -EINVAL;
++                      }
++
++                      switch (chandef.width) {
++                      case NL80211_CHAN_WIDTH_20_NOHT:
++                      case NL80211_CHAN_WIDTH_20:
++                      case NL80211_CHAN_WIDTH_40:
++                      case NL80211_CHAN_WIDTH_80:
++                      case NL80211_CHAN_WIDTH_80P80:
++                      case NL80211_CHAN_WIDTH_160:
++                      case NL80211_CHAN_WIDTH_320:
++                              break;
++                      default:
++                              return -EINVAL;
++                      }
++
+                       result = rdev_set_ap_chanwidth(rdev, dev, link_id,
+                                                      &chandef);
+                       if (result)
+-- 
+2.43.0
+
diff --git a/queue-6.10/wifi-nl80211-don-t-give-key-data-to-userspace.patch b/queue-6.10/wifi-nl80211-don-t-give-key-data-to-userspace.patch
new file mode 100644 (file)
index 0000000..90e44ef
--- /dev/null
@@ -0,0 +1,55 @@
+From 9a5a3f985f453310f4d4782f0bd4320f38f66d91 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jun 2024 10:44:11 +0200
+Subject: wifi: nl80211: don't give key data to userspace
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit a7e5793035792cc46a1a4b0a783655ffa897dfe9 ]
+
+When a key is requested by userspace, there's really no need
+to include the key data, the sequence counter is really what
+userspace needs in this case. The fact that it's included is
+just a historic quirk.
+
+Remove the key data.
+
+Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20240627104411.b6a4f097e4ea.I7e6cc976cb9e8a80ef25a3351330f313373b4578@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/nl80211.c | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 07538be6805ef..c2829d673bc76 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -4485,10 +4485,7 @@ static void get_key_callback(void *c, struct key_params *params)
+       struct nlattr *key;
+       struct get_key_cookie *cookie = c;
+-      if ((params->key &&
+-           nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
+-                   params->key_len, params->key)) ||
+-          (params->seq &&
++      if ((params->seq &&
+            nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
+                    params->seq_len, params->seq)) ||
+           (params->cipher &&
+@@ -4500,10 +4497,7 @@ static void get_key_callback(void *c, struct key_params *params)
+       if (!key)
+               goto nla_put_failure;
+-      if ((params->key &&
+-           nla_put(cookie->msg, NL80211_KEY_DATA,
+-                   params->key_len, params->key)) ||
+-          (params->seq &&
++      if ((params->seq &&
+            nla_put(cookie->msg, NL80211_KEY_SEQ,
+                    params->seq_len, params->seq)) ||
+           (params->cipher &&
+-- 
+2.43.0
+
diff --git a/queue-6.10/wifi-rtlwifi-handle-return-value-of-usb-init-tx-rx.patch b/queue-6.10/wifi-rtlwifi-handle-return-value-of-usb-init-tx-rx.patch
new file mode 100644 (file)
index 0000000..ee0531c
--- /dev/null
@@ -0,0 +1,142 @@
+From bfebd03fbda839faa4cb55256add3d525b7db80a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 May 2024 08:32:48 +0800
+Subject: wifi: rtlwifi: handle return value of usb init TX/RX
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 9c4fde42cce05719120cf892a44b76ff61d908c7 ]
+
+Handle error code to cause failed to USB probe result from unexpected
+USB EP number, otherwise when USB disconnect skb_dequeue() an uninitialized
+skb list and cause warnings below.
+
+usb 2-1: USB disconnect, device number 76
+INFO: trying to register non-static key.
+The code is fine but needs lockdep annotation, or maybe
+you didn't initialize this object before use?
+turning off the locking correctness validator.
+CPU: 0 PID: 54060 Comm: kworker/0:1 Not tainted 6.9.0-rc7 #1
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.2-0-gea1b7a073390-prebuilt.qemu.org 04/01/2014
+Workqueue: usb_hub_wq hub_event
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:88 [inline]
+ dump_stack_lvl+0x116/0x1b0 lib/dump_stack.c:114
+ assign_lock_key kernel/locking/lockdep.c:976 [inline]
+ register_lock_class+0xc18/0xfa0 kernel/locking/lockdep.c:1289
+ __lock_acquire+0x108/0x3bc0 kernel/locking/lockdep.c:5014
+ lock_acquire kernel/locking/lockdep.c:5754 [inline]
+ lock_acquire+0x1b0/0x550 kernel/locking/lockdep.c:5719
+ __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline]
+ _raw_spin_lock_irqsave+0x3d/0x60 kernel/locking/spinlock.c:162
+ skb_dequeue+0x20/0x180 net/core/skbuff.c:3846
+ rtl_usb_cleanup drivers/net/wireless/realtek/rtlwifi/usb.c:706 [inline]
+ rtl_usb_deinit drivers/net/wireless/realtek/rtlwifi/usb.c:721 [inline]
+ rtl_usb_disconnect+0x4a4/0x850 drivers/net/wireless/realtek/rtlwifi/usb.c:1051
+ usb_unbind_interface+0x1e8/0x980 drivers/usb/core/driver.c:461
+ device_remove drivers/base/dd.c:568 [inline]
+ device_remove+0x122/0x170 drivers/base/dd.c:560
+ __device_release_driver drivers/base/dd.c:1270 [inline]
+ device_release_driver_internal+0x443/0x620 drivers/base/dd.c:1293
+ bus_remove_device+0x22f/0x420 drivers/base/bus.c:574
+ device_del+0x395/0x9f0 drivers/base/core.c:3909
+ usb_disable_device+0x360/0x7b0 drivers/usb/core/message.c:1418
+ usb_disconnect+0x2db/0x930 drivers/usb/core/hub.c:2305
+ hub_port_connect drivers/usb/core/hub.c:5362 [inline]
+ hub_port_connect_change drivers/usb/core/hub.c:5662 [inline]
+ port_event drivers/usb/core/hub.c:5822 [inline]
+ hub_event+0x1e39/0x4ce0 drivers/usb/core/hub.c:5904
+ process_one_work+0x97b/0x1a90 kernel/workqueue.c:3267
+ process_scheduled_works kernel/workqueue.c:3348 [inline]
+ worker_thread+0x680/0xf00 kernel/workqueue.c:3429
+ kthread+0x2c7/0x3b0 kernel/kthread.c:388
+ ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+ </TASK>
+
+Reported-by: Shichao Lai <shichaorai@gmail.com>
+Closes: https://lore.kernel.org/linux-wireless/CAEk6kZuuezkH1dVRJf3EAVZK-83=OpTz62qCugkpTkswj8JF6w@mail.gmail.com/T/#u
+Tested-by: Shichao Lai <shichaorai@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://msgid.link/20240524003248.5952-1-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtlwifi/usb.c | 34 +++++++++++++++++-----
+ 1 file changed, 26 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
+index 2ea72d9e39577..4d2931e544278 100644
+--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
++++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
+@@ -23,6 +23,8 @@ MODULE_DESCRIPTION("USB basic driver for rtlwifi");
+ #define MAX_USBCTRL_VENDORREQ_TIMES           10
++static void _rtl_usb_cleanup_tx(struct ieee80211_hw *hw);
++
+ static void _usbctrl_vendorreq_sync(struct usb_device *udev, u8 reqtype,
+                                  u16 value, void *pdata, u16 len)
+ {
+@@ -285,9 +287,23 @@ static int _rtl_usb_init(struct ieee80211_hw *hw)
+       }
+       /* usb endpoint mapping */
+       err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw);
+-      rtlusb->usb_mq_to_hwq =  rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq;
+-      _rtl_usb_init_tx(hw);
+-      _rtl_usb_init_rx(hw);
++      if (err)
++              return err;
++
++      rtlusb->usb_mq_to_hwq = rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq;
++
++      err = _rtl_usb_init_tx(hw);
++      if (err)
++              return err;
++
++      err = _rtl_usb_init_rx(hw);
++      if (err)
++              goto err_out;
++
++      return 0;
++
++err_out:
++      _rtl_usb_cleanup_tx(hw);
+       return err;
+ }
+@@ -691,17 +707,13 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
+ }
+ /*=======================  tx =========================================*/
+-static void rtl_usb_cleanup(struct ieee80211_hw *hw)
++static void _rtl_usb_cleanup_tx(struct ieee80211_hw *hw)
+ {
+       u32 i;
+       struct sk_buff *_skb;
+       struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+       struct ieee80211_tx_info *txinfo;
+-      /* clean up rx stuff. */
+-      _rtl_usb_cleanup_rx(hw);
+-
+-      /* clean up tx stuff */
+       for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) {
+               while ((_skb = skb_dequeue(&rtlusb->tx_skb_queue[i]))) {
+                       rtlusb->usb_tx_cleanup(hw, _skb);
+@@ -715,6 +727,12 @@ static void rtl_usb_cleanup(struct ieee80211_hw *hw)
+       usb_kill_anchored_urbs(&rtlusb->tx_submitted);
+ }
++static void rtl_usb_cleanup(struct ieee80211_hw *hw)
++{
++      _rtl_usb_cleanup_rx(hw);
++      _rtl_usb_cleanup_tx(hw);
++}
++
+ /* We may add some struct into struct rtl_usb later. Do deinit here.  */
+ static void rtl_usb_deinit(struct ieee80211_hw *hw)
+ {
+-- 
+2.43.0
+
diff --git a/queue-6.10/wifi-rtw89-pci-fix-rx-tag-race-condition-resulting-i.patch b/queue-6.10/wifi-rtw89-pci-fix-rx-tag-race-condition-resulting-i.patch
new file mode 100644 (file)
index 0000000..33791ca
--- /dev/null
@@ -0,0 +1,59 @@
+From 7677d35617d23618b64bdd3b3017b4113c92887b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jun 2024 10:19:01 +0800
+Subject: wifi: rtw89: pci: fix RX tag race condition resulting in wrong RX
+ length
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 94298477f81a1701fc4e1b5a0ce9672acab5dcb2 ]
+
+Read 32 bits RX info to a local variable to fix race condition between
+reading RX length and RX tag.
+
+Another solution is to get RX tag at first statement, but adopted solution
+can save some memory read, and also save 15 bytes binary code.
+
+RX tag, a sequence number, is used to ensure that RX data has been DMA to
+memory completely, so driver must check sequence number is expected before
+reading other data.
+
+This potential problem happens only after enabling 36-bit DMA.
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://msgid.link/20240611021901.26394-2-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/pci.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
+index b36aa9a6bb3fc..312b57d7da642 100644
+--- a/drivers/net/wireless/realtek/rtw89/pci.c
++++ b/drivers/net/wireless/realtek/rtw89/pci.c
+@@ -183,14 +183,17 @@ static void rtw89_pci_sync_skb_for_device(struct rtw89_dev *rtwdev,
+ static void rtw89_pci_rxbd_info_update(struct rtw89_dev *rtwdev,
+                                      struct sk_buff *skb)
+ {
+-      struct rtw89_pci_rxbd_info *rxbd_info;
+       struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb);
++      struct rtw89_pci_rxbd_info *rxbd_info;
++      __le32 info;
+       rxbd_info = (struct rtw89_pci_rxbd_info *)skb->data;
+-      rx_info->fs = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_FS);
+-      rx_info->ls = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_LS);
+-      rx_info->len = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_WRITE_SIZE);
+-      rx_info->tag = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_TAG);
++      info = rxbd_info->dword;
++
++      rx_info->fs = le32_get_bits(info, RTW89_PCI_RXBD_FS);
++      rx_info->ls = le32_get_bits(info, RTW89_PCI_RXBD_LS);
++      rx_info->len = le32_get_bits(info, RTW89_PCI_RXBD_WRITE_SIZE);
++      rx_info->tag = le32_get_bits(info, RTW89_PCI_RXBD_TAG);
+ }
+ static int rtw89_pci_validate_rx_tag(struct rtw89_dev *rtwdev,
+-- 
+2.43.0
+
diff --git a/queue-6.10/x86-mm-fix-pti_clone_entry_text-for-i386.patch b/queue-6.10/x86-mm-fix-pti_clone_entry_text-for-i386.patch
new file mode 100644 (file)
index 0000000..f2e81e7
--- /dev/null
@@ -0,0 +1,42 @@
+From 7b2dbb7688f8b5a467236a644510e7bb7317c5cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 12:42:25 +0200
+Subject: x86/mm: Fix pti_clone_entry_text() for i386
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 3db03fb4995ef85fc41e86262ead7b4852f4bcf0 ]
+
+While x86_64 has PMD aligned text sections, i386 does not have this
+luxery. Notably ALIGN_ENTRY_TEXT_END is empty and _etext has PAGE
+alignment.
+
+This means that text on i386 can be page granular at the tail end,
+which in turn means that the PTI text clones should consistently
+account for this.
+
+Make pti_clone_entry_text() consistent with pti_clone_kernel_text().
+
+Fixes: 16a3fe634f6a ("x86/mm/pti: Clone kernel-image on PTE level for 32 bit")
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/pti.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
+index 48c503208c794..bfdf5f45b1370 100644
+--- a/arch/x86/mm/pti.c
++++ b/arch/x86/mm/pti.c
+@@ -496,7 +496,7 @@ static void pti_clone_entry_text(void)
+ {
+       pti_clone_pgtable((unsigned long) __entry_text_start,
+                         (unsigned long) __entry_text_end,
+-                        PTI_CLONE_PMD);
++                        PTI_LEVEL_KERNEL_IMAGE);
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.10/x86-mm-fix-pti_clone_pgtable-alignment-assumption.patch b/queue-6.10/x86-mm-fix-pti_clone_pgtable-alignment-assumption.patch
new file mode 100644 (file)
index 0000000..1390e9a
--- /dev/null
@@ -0,0 +1,68 @@
+From 77c77e2f8adae016f5e842e959c4aef7e51eddff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 18:31:05 +0200
+Subject: x86/mm: Fix pti_clone_pgtable() alignment assumption
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 41e71dbb0e0a0fe214545fe64af031303a08524c ]
+
+Guenter reported dodgy crashes on an i386-nosmp build using GCC-11
+that had the form of endless traps until entry stack exhaust and then
+#DF from the stack guard.
+
+It turned out that pti_clone_pgtable() had alignment assumptions on
+the start address, notably it hard assumes start is PMD aligned. This
+is true on x86_64, but very much not true on i386.
+
+These assumptions can cause the end condition to malfunction, leading
+to a 'short' clone. Guess what happens when the user mapping has a
+short copy of the entry text?
+
+Use the correct increment form for addr to avoid alignment
+assumptions.
+
+Fixes: 16a3fe634f6a ("x86/mm/pti: Clone kernel-image on PTE level for 32 bit")
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Tested-by: Guenter Roeck <linux@roeck-us.net>
+Suggested-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20240731163105.GG33588@noisy.programming.kicks-ass.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/pti.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
+index 2e69abf4f852a..48c503208c794 100644
+--- a/arch/x86/mm/pti.c
++++ b/arch/x86/mm/pti.c
+@@ -374,14 +374,14 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
+                        */
+                       *target_pmd = *pmd;
+-                      addr += PMD_SIZE;
++                      addr = round_up(addr + 1, PMD_SIZE);
+               } else if (level == PTI_CLONE_PTE) {
+                       /* Walk the page-table down to the pte level */
+                       pte = pte_offset_kernel(pmd, addr);
+                       if (pte_none(*pte)) {
+-                              addr += PAGE_SIZE;
++                              addr = round_up(addr + 1, PAGE_SIZE);
+                               continue;
+                       }
+@@ -401,7 +401,7 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
+                       /* Clone the PTE */
+                       *target_pte = *pte;
+-                      addr += PAGE_SIZE;
++                      addr = round_up(addr + 1, PAGE_SIZE);
+               } else {
+                       BUG();
+-- 
+2.43.0
+
diff --git a/queue-6.10/xen-privcmd-switch-from-mutex-to-spinlock-for-irqfds.patch b/queue-6.10/xen-privcmd-switch-from-mutex-to-spinlock-for-irqfds.patch
new file mode 100644 (file)
index 0000000..44997b1
--- /dev/null
@@ -0,0 +1,127 @@
+From e4857f0c15cc1227c949f2bdb69f932018283206 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jun 2024 15:12:28 +0530
+Subject: xen: privcmd: Switch from mutex to spinlock for irqfds
+
+From: Viresh Kumar <viresh.kumar@linaro.org>
+
+[ Upstream commit 1c682593096a487fd9aebc079a307ff7a6d054a3 ]
+
+irqfd_wakeup() gets EPOLLHUP, when it is called by
+eventfd_release() by way of wake_up_poll(&ctx->wqh, EPOLLHUP), which
+gets called under spin_lock_irqsave(). We can't use a mutex here as it
+will lead to a deadlock.
+
+Fix it by switching over to a spin lock.
+
+Reported-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Link: https://lore.kernel.org/r/a66d7a7a9001424d432f52a9fc3931a1f345464f.1718703669.git.viresh.kumar@linaro.org
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/xen/privcmd.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
+index 67dfa47788649..c9c620e32fa8b 100644
+--- a/drivers/xen/privcmd.c
++++ b/drivers/xen/privcmd.c
+@@ -845,7 +845,7 @@ static long privcmd_ioctl_mmap_resource(struct file *file,
+ #ifdef CONFIG_XEN_PRIVCMD_EVENTFD
+ /* Irqfd support */
+ static struct workqueue_struct *irqfd_cleanup_wq;
+-static DEFINE_MUTEX(irqfds_lock);
++static DEFINE_SPINLOCK(irqfds_lock);
+ static LIST_HEAD(irqfds_list);
+ struct privcmd_kernel_irqfd {
+@@ -909,9 +909,11 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key)
+               irqfd_inject(kirqfd);
+       if (flags & EPOLLHUP) {
+-              mutex_lock(&irqfds_lock);
++              unsigned long flags;
++
++              spin_lock_irqsave(&irqfds_lock, flags);
+               irqfd_deactivate(kirqfd);
+-              mutex_unlock(&irqfds_lock);
++              spin_unlock_irqrestore(&irqfds_lock, flags);
+       }
+       return 0;
+@@ -929,6 +931,7 @@ irqfd_poll_func(struct file *file, wait_queue_head_t *wqh, poll_table *pt)
+ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
+ {
+       struct privcmd_kernel_irqfd *kirqfd, *tmp;
++      unsigned long flags;
+       __poll_t events;
+       struct fd f;
+       void *dm_op;
+@@ -968,18 +971,18 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
+       init_waitqueue_func_entry(&kirqfd->wait, irqfd_wakeup);
+       init_poll_funcptr(&kirqfd->pt, irqfd_poll_func);
+-      mutex_lock(&irqfds_lock);
++      spin_lock_irqsave(&irqfds_lock, flags);
+       list_for_each_entry(tmp, &irqfds_list, list) {
+               if (kirqfd->eventfd == tmp->eventfd) {
+                       ret = -EBUSY;
+-                      mutex_unlock(&irqfds_lock);
++                      spin_unlock_irqrestore(&irqfds_lock, flags);
+                       goto error_eventfd;
+               }
+       }
+       list_add_tail(&kirqfd->list, &irqfds_list);
+-      mutex_unlock(&irqfds_lock);
++      spin_unlock_irqrestore(&irqfds_lock, flags);
+       /*
+        * Check if there was an event already pending on the eventfd before we
+@@ -1011,12 +1014,13 @@ static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd)
+ {
+       struct privcmd_kernel_irqfd *kirqfd;
+       struct eventfd_ctx *eventfd;
++      unsigned long flags;
+       eventfd = eventfd_ctx_fdget(irqfd->fd);
+       if (IS_ERR(eventfd))
+               return PTR_ERR(eventfd);
+-      mutex_lock(&irqfds_lock);
++      spin_lock_irqsave(&irqfds_lock, flags);
+       list_for_each_entry(kirqfd, &irqfds_list, list) {
+               if (kirqfd->eventfd == eventfd) {
+@@ -1025,7 +1029,7 @@ static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd)
+               }
+       }
+-      mutex_unlock(&irqfds_lock);
++      spin_unlock_irqrestore(&irqfds_lock, flags);
+       eventfd_ctx_put(eventfd);
+@@ -1073,13 +1077,14 @@ static int privcmd_irqfd_init(void)
+ static void privcmd_irqfd_exit(void)
+ {
+       struct privcmd_kernel_irqfd *kirqfd, *tmp;
++      unsigned long flags;
+-      mutex_lock(&irqfds_lock);
++      spin_lock_irqsave(&irqfds_lock, flags);
+       list_for_each_entry_safe(kirqfd, tmp, &irqfds_list, list)
+               irqfd_deactivate(kirqfd);
+-      mutex_unlock(&irqfds_lock);
++      spin_unlock_irqrestore(&irqfds_lock, flags);
+       destroy_workqueue(irqfd_cleanup_wq);
+ }
+-- 
+2.43.0
+