]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Thu, 30 May 2024 18:48:11 +0000 (14:48 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 30 May 2024 18:48:11 +0000 (14:48 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
177 files changed:
queue-6.6/alsa-timer-set-lower-bound-of-start-tick-time.patch [new file with mode: 0644]
queue-6.6/arm64-dts-meson-fix-s4-power-controller-node.patch [new file with mode: 0644]
queue-6.6/arm64-fpsimd-avoid-erroneous-elide-of-user-state-rel.patch [new file with mode: 0644]
queue-6.6/arm64-fpsimd-drop-unneeded-busy-flag.patch [new file with mode: 0644]
queue-6.6/arm64-fpsimd-implement-lazy-restore-for-kernel-mode-.patch [new file with mode: 0644]
queue-6.6/arm64-fpsimd-preserve-restore-kernel-mode-neon-at-co.patch [new file with mode: 0644]
queue-6.6/coresight-etm4x-do-not-hardcode-iomem-access-for-reg.patch [new file with mode: 0644]
queue-6.6/coresight-etm4x-do-not-save-restore-data-trace-contr.patch [new file with mode: 0644]
queue-6.6/coresight-etm4x-fix-access-to-resource-selector-regi.patch [new file with mode: 0644]
queue-6.6/coresight-etm4x-fix-unbalanced-pm_runtime_enable.patch [new file with mode: 0644]
queue-6.6/coresight-etm4x-safe-access-for-trcqcltr.patch [new file with mode: 0644]
queue-6.6/counter-linux-counter.h-fix-excess-kernel-doc-descri.patch [new file with mode: 0644]
queue-6.6/dmaengine-idma64-add-check-for-dma_set_max_seg_size.patch [new file with mode: 0644]
queue-6.6/dmaengine-idxd-avoid-unnecessary-destruction-of-file.patch [new file with mode: 0644]
queue-6.6/drm-amd-display-remove-pixle-rate-limit-for-subvp.patch [new file with mode: 0644]
queue-6.6/drm-amd-display-revert-remove-pixle-rate-limit-for-s.patch [new file with mode: 0644]
queue-6.6/dt-bindings-adc-axi-adc-add-clocks-property.patch [new file with mode: 0644]
queue-6.6/dt-bindings-adc-axi-adc-update-bindings-for-backend-.patch [new file with mode: 0644]
queue-6.6/dt-bindings-pci-rcar-pci-host-add-missing-iommu-prop.patch [new file with mode: 0644]
queue-6.6/dt-bindings-pci-rcar-pci-host-add-optional-regulator.patch [new file with mode: 0644]
queue-6.6/dt-bindings-pci-rockchip-rk3399-pcie-add-missing-max.patch [new file with mode: 0644]
queue-6.6/dt-bindings-phy-qcom-sc8280xp-qmp-ufs-phy-fix-msm899.patch [new file with mode: 0644]
queue-6.6/dt-bindings-phy-qcom-usb-snps-femto-v2-use-correct-f.patch [new file with mode: 0644]
queue-6.6/dt-bindings-pinctrl-mediatek-mt7622-fix-array-proper.patch [new file with mode: 0644]
queue-6.6/dt-bindings-spmi-hisilicon-hisi-spmi-controller-fix-.patch [new file with mode: 0644]
queue-6.6/eventfs-create-eventfs_root_inode-to-store-dentry.patch [new file with mode: 0644]
queue-6.6/eventfs-do-not-differentiate-the-toplevel-events-dir.patch [new file with mode: 0644]
queue-6.6/eventfs-free-all-of-the-eventfs_inode-after-rcu.patch [new file with mode: 0644]
queue-6.6/eventfs-have-events-directory-get-permissions-from-i.patch [new file with mode: 0644]
queue-6.6/eventfs-tracing-add-callback-for-release-of-an-event.patch [new file with mode: 0644]
queue-6.6/extcon-max8997-select-irq_domain-instead-of-dependin.patch [new file with mode: 0644]
queue-6.6/f2fs-clean-up-errors-in-segment.h.patch [new file with mode: 0644]
queue-6.6/f2fs-compress-don-t-allow-unaligned-truncation-on-re.patch [new file with mode: 0644]
queue-6.6/f2fs-compress-fix-error-path-of-inc_valid_block_coun.patch [new file with mode: 0644]
queue-6.6/f2fs-compress-fix-to-cover-reserve-release-_compress.patch [new file with mode: 0644]
queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch [new file with mode: 0644]
queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch-466 [new file with mode: 0644]
queue-6.6/f2fs-compress-fix-to-update-i_compr_blocks-correctly.patch [new file with mode: 0644]
queue-6.6/f2fs-deprecate-io_bits.patch [new file with mode: 0644]
queue-6.6/f2fs-fix-block-migration-when-section-is-not-aligned.patch [new file with mode: 0644]
queue-6.6/f2fs-fix-to-add-missing-iput-in-gc_data_segment.patch [new file with mode: 0644]
queue-6.6/f2fs-fix-to-check-pinfile-flag-in-f2fs_move_file_ran.patch [new file with mode: 0644]
queue-6.6/f2fs-fix-to-release-node-block-count-in-error-path-o.patch [new file with mode: 0644]
queue-6.6/f2fs-fix-to-relocate-check-condition-in-f2fs_falloca.patch [new file with mode: 0644]
queue-6.6/f2fs-fix-to-wait-on-page-writeback-in-__clone_blkadd.patch [new file with mode: 0644]
queue-6.6/f2fs-introduce-get_available_block_count-for-cleanup.patch [new file with mode: 0644]
queue-6.6/f2fs-kill-heap-based-allocation.patch [new file with mode: 0644]
queue-6.6/f2fs-multidev-fix-to-recognize-valid-zero-block-addr.patch [new file with mode: 0644]
queue-6.6/f2fs-separate-f2fs_gc_range-to-use-gc-for-a-range.patch [new file with mode: 0644]
queue-6.6/f2fs-support-file-pinning-for-zoned-devices.patch [new file with mode: 0644]
queue-6.6/f2fs-support-printk_ratelimited-in-f2fs_printk.patch [new file with mode: 0644]
queue-6.6/f2fs-use-blks_per_seg-blks_per_sec-and-segs_per_sec.patch [new file with mode: 0644]
queue-6.6/firmware-dmi-id-add-a-release-callback-function.patch [new file with mode: 0644]
queue-6.6/fpga-bridge-add-owner-module-and-take-its-refcount.patch [new file with mode: 0644]
queue-6.6/fpga-manager-add-owner-module-and-take-its-refcount.patch [new file with mode: 0644]
queue-6.6/fpga-region-add-owner-module-and-take-its-refcount.patch [new file with mode: 0644]
queue-6.6/fs-move-kiocb_start_write-into-vfs_iocb_iter_write.patch [new file with mode: 0644]
queue-6.6/gpiolib-acpi-fix-failed-in-acpi_gpiochip_find-by-add.patch [new file with mode: 0644]
queue-6.6/greybus-arche-ctrl-move-device-table-to-its-right-lo.patch [new file with mode: 0644]
queue-6.6/greybus-lights-check-return-of-get_channel_from_mode.patch [new file with mode: 0644]
queue-6.6/i2c-cadence-avoid-fifo-clear-after-start.patch [new file with mode: 0644]
queue-6.6/i2c-synquacer-fix-an-error-handling-path-in-synquace.patch [new file with mode: 0644]
queue-6.6/i915-make-inject_virtual_interrupt-void.patch [new file with mode: 0644]
queue-6.6/iio-accel-mxc4005-allow-module-autoloading-via-of-co.patch [new file with mode: 0644]
queue-6.6/iio-accel-mxc4005-reset-chip-on-probe-and-resume.patch [new file with mode: 0644]
queue-6.6/iio-adc-ad9467-convert-to-backend-framework.patch [new file with mode: 0644]
queue-6.6/iio-adc-ad9467-use-chip_info-variables-instead-of-ar.patch [new file with mode: 0644]
queue-6.6/iio-adc-ad9467-use-spi_get_device_match_data.patch [new file with mode: 0644]
queue-6.6/iio-adc-adi-axi-adc-convert-to-regmap.patch [new file with mode: 0644]
queue-6.6/iio-adc-adi-axi-adc-move-to-backend-framework.patch [new file with mode: 0644]
queue-6.6/iio-adc-adi-axi-adc-only-error-out-in-major-version-.patch [new file with mode: 0644]
queue-6.6/iio-adc-stm32-fixing-err-code-to-not-indicate-succes.patch [new file with mode: 0644]
queue-6.6/iio-add-the-iio-backend-framework.patch [new file with mode: 0644]
queue-6.6/iio-buffer-dmaengine-export-buffer-alloc-and-free-fu.patch [new file with mode: 0644]
queue-6.6/iio-core-leave-private-pointer-null-when-no-private-.patch [new file with mode: 0644]
queue-6.6/iio-pressure-dps310-support-negative-temperature-val.patch [new file with mode: 0644]
queue-6.6/interconnect-qcom-qcm2290-fix-mas_snoc_bimc-qos-port.patch [new file with mode: 0644]
queue-6.6/kbuild-fix-build-id-symlinks-to-installed-debug-vdso.patch [new file with mode: 0644]
queue-6.6/kbuild-unify-vdso_install-rules.patch [new file with mode: 0644]
queue-6.6/leds-pwm-disable-pwm-when-going-to-suspend.patch [new file with mode: 0644]
queue-6.6/libsubcmd-fix-parse-options-memory-leak.patch [new file with mode: 0644]
queue-6.6/loongarch-fix-callchain-parse-error-with-kernel-trac.patch [new file with mode: 0644]
queue-6.6/microblaze-remove-early-printk-call-from-cpuinfo-sta.patch [new file with mode: 0644]
queue-6.6/microblaze-remove-gcc-flag-for-non-existing-early_pr.patch [new file with mode: 0644]
queue-6.6/misc-pvpanic-deduplicate-common-code.patch [new file with mode: 0644]
queue-6.6/misc-pvpanic-pci-register-attributes-via-pci_driver.patch [new file with mode: 0644]
queue-6.6/module-don-t-ignore-sysfs_create_link-failures.patch [new file with mode: 0644]
queue-6.6/ovl-add-helper-ovl_file_modified.patch [new file with mode: 0644]
queue-6.6/ovl-remove-upper-umask-handling-from-ovl_create_uppe.patch [new file with mode: 0644]
queue-6.6/pci-edr-align-edr_port_dpc_enable_dsm-with-pci-firmw.patch [new file with mode: 0644]
queue-6.6/pci-edr-align-edr_port_locate_dsm-with-pci-firmware-.patch [new file with mode: 0644]
queue-6.6/pci-of_property-return-error-for-int_map-allocation-.patch [new file with mode: 0644]
queue-6.6/pci-tegra194-fix-probe-path-for-endpoint-mode.patch [new file with mode: 0644]
queue-6.6/pci-wait-for-link-training-0-before-starting-link-re.patch [new file with mode: 0644]
queue-6.6/perf-annotate-fix-annotation_calc_lines-to-pass-corr.patch [new file with mode: 0644]
queue-6.6/perf-annotate-get-rid-of-duplicate-group-option-item.patch [new file with mode: 0644]
queue-6.6/perf-annotate-introduce-global-annotation_options.patch [new file with mode: 0644]
queue-6.6/perf-annotate-split-branch-stack-cycles-information-.patch [new file with mode: 0644]
queue-6.6/perf-annotate-use-global-annotation_options.patch [new file with mode: 0644]
queue-6.6/perf-bench-internals-inject-build-id-fix-trap-divide.patch [new file with mode: 0644]
queue-6.6/perf-bench-uprobe-remove-lib64-from-libc.so.6-binary.patch [new file with mode: 0644]
queue-6.6/perf-daemon-fix-file-leak-in-daemon_session__control.patch [new file with mode: 0644]
queue-6.6/perf-docs-document-bpf-event-modifier.patch [new file with mode: 0644]
queue-6.6/perf-evlist-add-evlist__findnew_tracking_event-helpe.patch [new file with mode: 0644]
queue-6.6/perf-intel-pt-fix-unassigned-instruction-op-discover.patch [new file with mode: 0644]
queue-6.6/perf-machine-thread-remove-exited-threads-by-default.patch [new file with mode: 0644]
queue-6.6/perf-maps-move-symbol-maps-functions-to-maps.c.patch [new file with mode: 0644]
queue-6.6/perf-pmu-assume-sysfs-events-are-always-the-same-cas.patch [new file with mode: 0644]
queue-6.6/perf-pmu-compat-supports-regular-expression-matching.patch [new file with mode: 0644]
queue-6.6/perf-pmu-count-sys-and-cpuid-json-events-separately.patch [new file with mode: 0644]
queue-6.6/perf-pmu-move-pmu__find_core_pmu-to-pmus.c.patch [new file with mode: 0644]
queue-6.6/perf-probe-add-missing-libgen.h-header-needed-for-us.patch [new file with mode: 0644]
queue-6.6/perf-record-delete-session-after-stopping-sideband-t.patch [new file with mode: 0644]
queue-6.6/perf-record-fix-debug-message-placement-for-test-con.patch [new file with mode: 0644]
queue-6.6/perf-record-lazy-load-kernel-symbols.patch [new file with mode: 0644]
queue-6.6/perf-record-move-setting-tracking-events-before-reco.patch [new file with mode: 0644]
queue-6.6/perf-report-avoid-segv-in-report__setup_sample_type.patch [new file with mode: 0644]
queue-6.6/perf-report-convert-to-the-global-annotation_options.patch [new file with mode: 0644]
queue-6.6/perf-stat-do-not-fail-on-metrics-on-s390-z-vm-system.patch [new file with mode: 0644]
queue-6.6/perf-stat-don-t-display-metric-header-for-non-leader.patch [new file with mode: 0644]
queue-6.6/perf-symbols-fix-ownership-of-string-in-dso__load_vm.patch [new file with mode: 0644]
queue-6.6/perf-test-add-a-test-for-strcmp_cpuid_str-expression.patch [new file with mode: 0644]
queue-6.6/perf-test-shell-arm_coresight-increase-buffer-size-f.patch [new file with mode: 0644]
queue-6.6/perf-tests-apply-attributes-to-all-events-in-object-.patch [new file with mode: 0644]
queue-6.6/perf-tests-make-test-data-symbol-more-robust-on-neov.patch [new file with mode: 0644]
queue-6.6/perf-thread-fixes-to-thread__new-related-to-initiali.patch [new file with mode: 0644]
queue-6.6/perf-tools-add-use-pmu-reverse-lookup-from-config-to.patch [new file with mode: 0644]
queue-6.6/perf-tools-use-pmus-to-describe-type-from-attribute.patch [new file with mode: 0644]
queue-6.6/perf-top-convert-to-the-global-annotation_options.patch [new file with mode: 0644]
queue-6.6/perf-ui-browser-avoid-segv-on-title.patch [new file with mode: 0644]
queue-6.6/perf-ui-browser-don-t-save-pointer-to-stack-memory.patch [new file with mode: 0644]
queue-6.6/phy-qcom-qmp-combo-fix-duplicate-return-in-qmp_v4_co.patch [new file with mode: 0644]
queue-6.6/pinctrl-qcom-pinctrl-sm7150-fix-sdc1-and-ufs-special.patch [new file with mode: 0644]
queue-6.6/ppdev-add-an-error-check-in-register_device.patch [new file with mode: 0644]
queue-6.6/ppdev-remove-usage-of-the-deprecated-ida_simple_xx-a.patch [new file with mode: 0644]
queue-6.6/pwm-rename-pwm_apply_state-to-pwm_apply_might_sleep.patch [new file with mode: 0644]
queue-6.6/reapply-arm64-fpsimd-implement-lazy-restore-for-kern.patch [new file with mode: 0644]
queue-6.6/remove-call_-read-write-_iter-functions.patch [new file with mode: 0644]
queue-6.6/revert-arm64-fpsimd-implement-lazy-restore-for-kerne.patch [new file with mode: 0644]
queue-6.6/risc-v-enable-cbo.zero-in-usermode.patch [new file with mode: 0644]
queue-6.6/riscv-dts-starfive-visionfive-2-remove-non-existing-.patch [new file with mode: 0644]
queue-6.6/riscv-flush-the-instruction-cache-during-smp-bringup.patch [new file with mode: 0644]
queue-6.6/s390-boot-remove-alt_stfle_fac_list-from-decompresso.patch [new file with mode: 0644]
queue-6.6/s390-ipl-fix-incorrect-initialization-of-len-fields-.patch [new file with mode: 0644]
queue-6.6/s390-ipl-fix-incorrect-initialization-of-nvme-dump-b.patch [new file with mode: 0644]
queue-6.6/s390-vdso-create-.build-id-links-for-unstripped-vdso.patch [new file with mode: 0644]
queue-6.6/s390-vdso-generate-unwind-information-for-c-modules.patch [new file with mode: 0644]
queue-6.6/s390-vdso-use-standard-stack-frame-layout.patch [new file with mode: 0644]
queue-6.6/s390-vdso64-filter-out-munaligned-symbols-flag-for-v.patch [new file with mode: 0644]
queue-6.6/serial-max3100-fix-bitwise-types.patch [new file with mode: 0644]
queue-6.6/serial-max3100-lock-port-lock-when-calling-uart_hand.patch [new file with mode: 0644]
queue-6.6/serial-max3100-update-uart_driver_registered-on-driv.patch [new file with mode: 0644]
queue-6.6/serial-sc16is7xx-add-proper-sched.h-include-for-sche.patch [new file with mode: 0644]
queue-6.6/serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch [new file with mode: 0644]
queue-6.6/serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch [new file with mode: 0644]
queue-6.6/serial-sh-sci-protect-invalidating-rxdma-on-shutdown.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/soundwire-cadence-fix-invalid-pdi-offset.patch [new file with mode: 0644]
queue-6.6/splice-remove-permission-hook-from-iter_file_splice_.patch [new file with mode: 0644]
queue-6.6/stm-class-fix-a-double-free-in-stm_register_device.patch [new file with mode: 0644]
queue-6.6/udf-convert-udf_expand_file_adinicb-to-use-a-folio.patch [new file with mode: 0644]
queue-6.6/udf-remove-gfp_nofs-allocation-in-udf_expand_file_ad.patch [new file with mode: 0644]
queue-6.6/usb-fotg210-add-missing-kernel-doc-description.patch [new file with mode: 0644]
queue-6.6/usb-gadget-u_audio-clear-uac-pointer-when-freed.patch [new file with mode: 0644]
queue-6.6/usb-gadget-u_audio-fix-race-condition-use-of-control.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-always-register-a-link-to-usb-pd-devi.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-simplify-partner-s-pd-caps-registrati.patch [new file with mode: 0644]
queue-6.6/vfio-pci-fix-potential-memory-leak-in-vfio_intx_enab.patch [new file with mode: 0644]
queue-6.6/vmci-fix-an-error-handling-path-in-vmci_guest_probe_.patch [new file with mode: 0644]
queue-6.6/watchdog-bd9576-drop-always-running-property.patch [new file with mode: 0644]
queue-6.6/watchdog-cpu5wdt.c-fix-use-after-free-bug-caused-by-.patch [new file with mode: 0644]
queue-6.6/watchdog-sa1100-fix-ptr_err_or_zero-vs-null-check-in.patch [new file with mode: 0644]
queue-6.6/xfs-convert-kmem_free-for-kvmalloc-users-to-kvfree.patch [new file with mode: 0644]
queue-6.6/xfs-fix-log-recovery-buffer-allocation-for-the-legac.patch [new file with mode: 0644]
queue-6.6/xfs-match-lock-mode-in-xfs_buffered_write_iomap_begi.patch [new file with mode: 0644]
queue-6.6/xfs-require-xfs_sb_feat_incompat_log_xattrs-for-attr.patch [new file with mode: 0644]
queue-6.6/xfs-upgrade-the-extent-counters-in-xfs_reflink_end_c.patch [new file with mode: 0644]

diff --git a/queue-6.6/alsa-timer-set-lower-bound-of-start-tick-time.patch b/queue-6.6/alsa-timer-set-lower-bound-of-start-tick-time.patch
new file mode 100644 (file)
index 0000000..babb871
--- /dev/null
@@ -0,0 +1,52 @@
+From 7135223dedc8c3395286133970ddecae77b2a9d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 May 2024 20:27:36 +0200
+Subject: ALSA: timer: Set lower bound of start tick time
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 4a63bd179fa8d3fcc44a0d9d71d941ddd62f0c4e ]
+
+Currently ALSA timer doesn't have the lower limit of the start tick
+time, and it allows a very small size, e.g. 1 tick with 1ns resolution
+for hrtimer.  Such a situation may lead to an unexpected RCU stall,
+where  the callback repeatedly queuing the expire update, as reported
+by fuzzer.
+
+This patch introduces a sanity check of the timer start tick time, so
+that the system returns an error when a too small start size is set.
+As of this patch, the lower limit is hard-coded to 100us, which is
+small enough but can still work somehow.
+
+Reported-by: syzbot+43120c2af6ca2938cc38@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/r/000000000000fa00a1061740ab6d@google.com
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20240514182745.4015-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/core/timer.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/sound/core/timer.c b/sound/core/timer.c
+index e6e551d4a29e0..42c4c2b029526 100644
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -553,6 +553,14 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,
+               goto unlock;
+       }
++      /* check the actual time for the start tick;
++       * bail out as error if it's way too low (< 100us)
++       */
++      if (start) {
++              if ((u64)snd_timer_hw_resolution(timer) * ticks < 100000)
++                      return -EINVAL;
++      }
++
+       if (start)
+               timeri->ticks = timeri->cticks = ticks;
+       else if (!timeri->cticks)
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-meson-fix-s4-power-controller-node.patch b/queue-6.6/arm64-dts-meson-fix-s4-power-controller-node.patch
new file mode 100644 (file)
index 0000000..f76bea3
--- /dev/null
@@ -0,0 +1,49 @@
+From 7c31198635b5c27e2c9ecb3fbfdcfba0d152ea3a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Apr 2024 16:42:30 +0800
+Subject: arm64: dts: meson: fix S4 power-controller node
+
+From: Xianwei Zhao <xianwei.zhao@amlogic.com>
+
+[ Upstream commit 72907de9051dc2aa7b55c2a020e2872184ac17cd ]
+
+The power-controller module works well by adding its parent
+node secure-monitor.
+
+Fixes: 085f7a298a14 ("arm64: dts: add support for S4 power domain controller")
+Signed-off-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://lore.kernel.org/r/20240412-fix-secpwr-s4-v2-1-3802fd936d77@amlogic.com
+Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/amlogic/meson-s4.dtsi | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
+index 55ddea6dc9f8e..a781eabe21f04 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
+@@ -61,10 +61,15 @@ xtal: xtal-clk {
+               #clock-cells = <0>;
+       };
+-      pwrc: power-controller {
+-              compatible = "amlogic,meson-s4-pwrc";
+-              #power-domain-cells = <1>;
+-              status = "okay";
++      firmware {
++              sm: secure-monitor {
++                      compatible = "amlogic,meson-gxbb-sm";
++
++                      pwrc: power-controller {
++                              compatible = "amlogic,meson-s4-pwrc";
++                              #power-domain-cells = <1>;
++                      };
++              };
+       };
+       soc {
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-fpsimd-avoid-erroneous-elide-of-user-state-rel.patch b/queue-6.6/arm64-fpsimd-avoid-erroneous-elide-of-user-state-rel.patch
new file mode 100644 (file)
index 0000000..587a678
--- /dev/null
@@ -0,0 +1,127 @@
+From 0180bc16b0f2c38cf9215f40fdca39302bc242da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 May 2024 11:13:36 +0200
+Subject: arm64/fpsimd: Avoid erroneous elide of user state reload
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+[ Upstream commit e92bee9f861b466c676f0200be3e46af7bc4ac6b ]
+
+TIF_FOREIGN_FPSTATE is a 'convenience' flag that should reflect whether
+the current CPU holds the most recent user mode FP/SIMD state of the
+current task. It combines two conditions:
+- whether the current CPU's FP/SIMD state belongs to the task;
+- whether that state is the most recent associated with the task (as a
+  task may have executed on other CPUs as well).
+
+When a task is scheduled in and TIF_KERNEL_FPSTATE is set, it means the
+task was in a kernel mode NEON section when it was scheduled out, and so
+the kernel mode FP/SIMD state is restored. Since this implies that the
+current CPU is *not* holding the most recent user mode FP/SIMD state of
+the current task, the TIF_FOREIGN_FPSTATE flag is set too, so that the
+user mode FP/SIMD state is reloaded from memory when returning to
+userland.
+
+However, the task may be scheduled out after completing the kernel mode
+NEON section, but before returning to userland. When this happens, the
+TIF_FOREIGN_FPSTATE flag will not be preserved, but will be set as usual
+the next time the task is scheduled in, and will be based on the above
+conditions.
+
+This means that, rather than setting TIF_FOREIGN_FPSTATE when scheduling
+in a task with TIF_KERNEL_FPSTATE set, the underlying state should be
+updated so that TIF_FOREIGN_FPSTATE will assume the expected value as a
+result.
+
+So instead, call fpsimd_flush_cpu_state(), which takes care of this.
+
+Closes: https://lore.kernel.org/all/cb8822182231850108fa43e0446a4c7f@kernel.org
+Reported-by: Johannes Nixdorf <mixi@shadowice.org>
+Fixes: aefbab8e77eb ("arm64: fpsimd: Preserve/restore kernel mode NEON at context switch")
+Cc: Mark Brown <broonie@kernel.org>
+Cc: Dave Martin <Dave.Martin@arm.com>
+Cc: Janne Grunau <j@jannau.net>
+Cc: stable@vger.kernel.org
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Tested-by: Janne Grunau <j@jannau.net>
+Tested-by: Johannes Nixdorf <mixi@shadowice.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20240522091335.335346-2-ardb+git@google.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kernel/fpsimd.c | 44 +++++++++++++++++++-------------------
+ 1 file changed, 22 insertions(+), 22 deletions(-)
+
+diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
+index aa695057c93dd..55963fa64dec8 100644
+--- a/arch/arm64/kernel/fpsimd.c
++++ b/arch/arm64/kernel/fpsimd.c
+@@ -1560,6 +1560,27 @@ static void fpsimd_save_kernel_state(struct task_struct *task)
+       fpsimd_save_state(&task->thread.kernel_fpsimd_state);
+ }
++/*
++ * Invalidate any task's FPSIMD state that is present on this cpu.
++ * The FPSIMD context should be acquired with get_cpu_fpsimd_context()
++ * before calling this function.
++ */
++static void fpsimd_flush_cpu_state(void)
++{
++      WARN_ON(!system_supports_fpsimd());
++      __this_cpu_write(fpsimd_last_state.st, NULL);
++
++      /*
++       * Leaving streaming mode enabled will cause issues for any kernel
++       * NEON and leaving streaming mode or ZA enabled may increase power
++       * consumption.
++       */
++      if (system_supports_sme())
++              sme_smstop();
++
++      set_thread_flag(TIF_FOREIGN_FPSTATE);
++}
++
+ void fpsimd_thread_switch(struct task_struct *next)
+ {
+       bool wrong_task, wrong_cpu;
+@@ -1577,7 +1598,7 @@ void fpsimd_thread_switch(struct task_struct *next)
+       if (test_tsk_thread_flag(next, TIF_KERNEL_FPSTATE)) {
+               fpsimd_load_kernel_state(next);
+-              set_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE);
++              fpsimd_flush_cpu_state();
+       } else {
+               /*
+                * Fix up TIF_FOREIGN_FPSTATE to correctly describe next's
+@@ -1856,27 +1877,6 @@ void fpsimd_flush_task_state(struct task_struct *t)
+       barrier();
+ }
+-/*
+- * Invalidate any task's FPSIMD state that is present on this cpu.
+- * The FPSIMD context should be acquired with get_cpu_fpsimd_context()
+- * before calling this function.
+- */
+-static void fpsimd_flush_cpu_state(void)
+-{
+-      WARN_ON(!system_supports_fpsimd());
+-      __this_cpu_write(fpsimd_last_state.st, NULL);
+-
+-      /*
+-       * Leaving streaming mode enabled will cause issues for any kernel
+-       * NEON and leaving streaming mode or ZA enabled may increase power
+-       * consumption.
+-       */
+-      if (system_supports_sme())
+-              sme_smstop();
+-
+-      set_thread_flag(TIF_FOREIGN_FPSTATE);
+-}
+-
+ /*
+  * Save the FPSIMD state to memory and invalidate cpu view.
+  * This function must be called with preemption disabled.
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-fpsimd-drop-unneeded-busy-flag.patch b/queue-6.6/arm64-fpsimd-drop-unneeded-busy-flag.patch
new file mode 100644 (file)
index 0000000..bb2e8c8
--- /dev/null
@@ -0,0 +1,218 @@
+From 37f2773a1ef05374538d5e4ed26cbacebe363241 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Dec 2023 12:32:20 +0100
+Subject: arm64: fpsimd: Drop unneeded 'busy' flag
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+[ Upstream commit 9b19700e623f96222c69ecb2adecb1a3e3664cc0 ]
+
+Kernel mode NEON will preserve the user mode FPSIMD state by saving it
+into the task struct before clobbering the registers. In order to avoid
+the need for preserving kernel mode state too, we disallow nested use of
+kernel mode NEON, i..e, use in softirq context while the interrupted
+task context was using kernel mode NEON too.
+
+Originally, this policy was implemented using a per-CPU flag which was
+exposed via may_use_simd(), requiring the users of the kernel mode NEON
+to deal with the possibility that it might return false, and having NEON
+and non-NEON code paths. This policy was changed by commit
+13150149aa6ded1 ("arm64: fpsimd: run kernel mode NEON with softirqs
+disabled"), and now, softirq processing is disabled entirely instead,
+and so may_use_simd() can never fail when called from task or softirq
+context.
+
+This means we can drop the fpsimd_context_busy flag entirely, and
+instead, ensure that we disable softirq processing in places where we
+formerly relied on the flag for preventing races in the FPSIMD preserve
+routines.
+
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20231208113218.3001940-7-ardb@google.com
+[will: Folded in fix from CAMj1kXFhzbJRyWHELCivQW1yJaF=p07LLtbuyXYX3G1WtsdyQg@mail.gmail.com]
+Signed-off-by: Will Deacon <will@kernel.org>
+Stable-dep-of: b8995a184170 ("Revert "arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD"")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/simd.h | 11 +------
+ arch/arm64/kernel/fpsimd.c    | 55 +++++++++--------------------------
+ 2 files changed, 15 insertions(+), 51 deletions(-)
+
+diff --git a/arch/arm64/include/asm/simd.h b/arch/arm64/include/asm/simd.h
+index 6a75d7ecdcaa2..8e86c9e70e483 100644
+--- a/arch/arm64/include/asm/simd.h
++++ b/arch/arm64/include/asm/simd.h
+@@ -12,8 +12,6 @@
+ #include <linux/preempt.h>
+ #include <linux/types.h>
+-DECLARE_PER_CPU(bool, fpsimd_context_busy);
+-
+ #ifdef CONFIG_KERNEL_MODE_NEON
+ /*
+@@ -28,17 +26,10 @@ static __must_check inline bool may_use_simd(void)
+       /*
+        * We must make sure that the SVE has been initialized properly
+        * before using the SIMD in kernel.
+-       * fpsimd_context_busy is only set while preemption is disabled,
+-       * and is clear whenever preemption is enabled. Since
+-       * this_cpu_read() is atomic w.r.t. preemption, fpsimd_context_busy
+-       * cannot change under our feet -- if it's set we cannot be
+-       * migrated, and if it's clear we cannot be migrated to a CPU
+-       * where it is set.
+        */
+       return !WARN_ON(!system_capabilities_finalized()) &&
+              system_supports_fpsimd() &&
+-             !in_hardirq() && !irqs_disabled() && !in_nmi() &&
+-             !this_cpu_read(fpsimd_context_busy);
++             !in_hardirq() && !irqs_disabled() && !in_nmi();
+ }
+ #else /* ! CONFIG_KERNEL_MODE_NEON */
+diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
+index 5cdfcc9e3e54b..b805bdab284c4 100644
+--- a/arch/arm64/kernel/fpsimd.c
++++ b/arch/arm64/kernel/fpsimd.c
+@@ -85,13 +85,13 @@
+  * softirq kicks in. Upon vcpu_put(), KVM will save the vcpu FP state and
+  * flag the register state as invalid.
+  *
+- * In order to allow softirq handlers to use FPSIMD, kernel_neon_begin() may
+- * save the task's FPSIMD context back to task_struct from softirq context.
+- * To prevent this from racing with the manipulation of the task's FPSIMD state
+- * from task context and thereby corrupting the state, it is necessary to
+- * protect any manipulation of a task's fpsimd_state or TIF_FOREIGN_FPSTATE
+- * flag with {, __}get_cpu_fpsimd_context(). This will still allow softirqs to
+- * run but prevent them to use FPSIMD.
++ * In order to allow softirq handlers to use FPSIMD, kernel_neon_begin() may be
++ * called from softirq context, which will save the task's FPSIMD context back
++ * to task_struct. To prevent this from racing with the manipulation of the
++ * task's FPSIMD state from task context and thereby corrupting the state, it
++ * is necessary to protect any manipulation of a task's fpsimd_state or
++ * TIF_FOREIGN_FPSTATE flag with get_cpu_fpsimd_context(), which will suspend
++ * softirq servicing entirely until put_cpu_fpsimd_context() is called.
+  *
+  * For a certain task, the sequence may look something like this:
+  * - the task gets scheduled in; if both the task's fpsimd_cpu field
+@@ -209,27 +209,14 @@ static inline void sme_free(struct task_struct *t) { }
+ #endif
+-DEFINE_PER_CPU(bool, fpsimd_context_busy);
+-EXPORT_PER_CPU_SYMBOL(fpsimd_context_busy);
+-
+ static void fpsimd_bind_task_to_cpu(void);
+-static void __get_cpu_fpsimd_context(void)
+-{
+-      bool busy = __this_cpu_xchg(fpsimd_context_busy, true);
+-
+-      WARN_ON(busy);
+-}
+-
+ /*
+  * Claim ownership of the CPU FPSIMD context for use by the calling context.
+  *
+  * The caller may freely manipulate the FPSIMD context metadata until
+  * put_cpu_fpsimd_context() is called.
+  *
+- * The double-underscore version must only be called if you know the task
+- * can't be preempted.
+- *
+  * On RT kernels local_bh_disable() is not sufficient because it only
+  * serializes soft interrupt related sections via a local lock, but stays
+  * preemptible. Disabling preemption is the right choice here as bottom
+@@ -242,14 +229,6 @@ static void get_cpu_fpsimd_context(void)
+               local_bh_disable();
+       else
+               preempt_disable();
+-      __get_cpu_fpsimd_context();
+-}
+-
+-static void __put_cpu_fpsimd_context(void)
+-{
+-      bool busy = __this_cpu_xchg(fpsimd_context_busy, false);
+-
+-      WARN_ON(!busy); /* No matching get_cpu_fpsimd_context()? */
+ }
+ /*
+@@ -261,18 +240,12 @@ static void __put_cpu_fpsimd_context(void)
+  */
+ static void put_cpu_fpsimd_context(void)
+ {
+-      __put_cpu_fpsimd_context();
+       if (!IS_ENABLED(CONFIG_PREEMPT_RT))
+               local_bh_enable();
+       else
+               preempt_enable();
+ }
+-static bool have_cpu_fpsimd_context(void)
+-{
+-      return !preemptible() && __this_cpu_read(fpsimd_context_busy);
+-}
+-
+ unsigned int task_get_vl(const struct task_struct *task, enum vec_type type)
+ {
+       return task->thread.vl[type];
+@@ -383,7 +356,7 @@ static void task_fpsimd_load(void)
+       bool restore_ffr;
+       WARN_ON(!system_supports_fpsimd());
+-      WARN_ON(!have_cpu_fpsimd_context());
++      WARN_ON(preemptible());
+       if (system_supports_sve() || system_supports_sme()) {
+               switch (current->thread.fp_type) {
+@@ -467,7 +440,7 @@ static void fpsimd_save(void)
+       unsigned int vl;
+       WARN_ON(!system_supports_fpsimd());
+-      WARN_ON(!have_cpu_fpsimd_context());
++      WARN_ON(preemptible());
+       if (test_thread_flag(TIF_FOREIGN_FPSTATE))
+               return;
+@@ -1583,7 +1556,7 @@ void fpsimd_thread_switch(struct task_struct *next)
+       if (!system_supports_fpsimd())
+               return;
+-      __get_cpu_fpsimd_context();
++      WARN_ON_ONCE(!irqs_disabled());
+       /* Save unsaved fpsimd state, if any: */
+       fpsimd_save();
+@@ -1599,8 +1572,6 @@ void fpsimd_thread_switch(struct task_struct *next)
+       update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE,
+                              wrong_task || wrong_cpu);
+-
+-      __put_cpu_fpsimd_context();
+ }
+ static void fpsimd_flush_thread_vl(enum vec_type type)
+@@ -1892,13 +1863,15 @@ static void fpsimd_flush_cpu_state(void)
+  */
+ void fpsimd_save_and_flush_cpu_state(void)
+ {
++      unsigned long flags;
++
+       if (!system_supports_fpsimd())
+               return;
+       WARN_ON(preemptible());
+-      __get_cpu_fpsimd_context();
++      local_irq_save(flags);
+       fpsimd_save();
+       fpsimd_flush_cpu_state();
+-      __put_cpu_fpsimd_context();
++      local_irq_restore(flags);
+ }
+ #ifdef CONFIG_KERNEL_MODE_NEON
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-fpsimd-implement-lazy-restore-for-kernel-mode-.patch b/queue-6.6/arm64-fpsimd-implement-lazy-restore-for-kernel-mode-.patch
new file mode 100644 (file)
index 0000000..b23abe8
--- /dev/null
@@ -0,0 +1,86 @@
+From afeeeb2dbfdded9651e5b4e01083c2d1c114ea82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Dec 2023 12:32:22 +0100
+Subject: arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+[ Upstream commit 2632e25217696712681dd1f3ecc0d71624ea3b23 ]
+
+Now that kernel mode FPSIMD state is context switched along with other
+task state, we can enable the existing logic that keeps track of which
+task's FPSIMD state the CPU is holding in its registers. If it is the
+context of the task that we are switching to, we can elide the reload of
+the FPSIMD state from memory.
+
+Note that we also need to check whether the FPSIMD state on this CPU is
+the most recent: if a task gets migrated away and back again, the state
+in memory may be more recent than the state in the CPU. So add another
+CPU id field to task_struct to keep track of this. (We could reuse the
+existing CPU id field used for user mode context, but that might result
+in user state to be discarded unnecessarily, given that two distinct
+CPUs could be holding the most recent user mode state and the most
+recent kernel mode state)
+
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20231208113218.3001940-9-ardb@google.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Stable-dep-of: b8995a184170 ("Revert "arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD"")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/processor.h |  1 +
+ arch/arm64/kernel/fpsimd.c         | 18 ++++++++++++++++++
+ 2 files changed, 19 insertions(+)
+
+diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
+index ce6eebd6c08bd..5b0a04810b236 100644
+--- a/arch/arm64/include/asm/processor.h
++++ b/arch/arm64/include/asm/processor.h
+@@ -169,6 +169,7 @@ struct thread_struct {
+       struct debug_info       debug;          /* debugging */
+       struct user_fpsimd_state        kernel_fpsimd_state;
++      unsigned int                    kernel_fpsimd_cpu;
+ #ifdef CONFIG_ARM64_PTR_AUTH
+       struct ptrauth_keys_user        keys_user;
+ #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
+diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
+index aa695057c93dd..92cb6dd1cfc1a 100644
+--- a/arch/arm64/kernel/fpsimd.c
++++ b/arch/arm64/kernel/fpsimd.c
+@@ -1552,12 +1552,30 @@ void do_fpsimd_exc(unsigned long esr, struct pt_regs *regs)
+ static void fpsimd_load_kernel_state(struct task_struct *task)
+ {
++      struct cpu_fp_state *last = this_cpu_ptr(&fpsimd_last_state);
++
++      /*
++       * Elide the load if this CPU holds the most recent kernel mode
++       * FPSIMD context of the current task.
++       */
++      if (last->st == &task->thread.kernel_fpsimd_state &&
++          task->thread.kernel_fpsimd_cpu == smp_processor_id())
++              return;
++
+       fpsimd_load_state(&task->thread.kernel_fpsimd_state);
+ }
+ static void fpsimd_save_kernel_state(struct task_struct *task)
+ {
++      struct cpu_fp_state cpu_fp_state = {
++              .st             = &task->thread.kernel_fpsimd_state,
++              .to_save        = FP_STATE_FPSIMD,
++      };
++
+       fpsimd_save_state(&task->thread.kernel_fpsimd_state);
++      fpsimd_bind_state_to_cpu(&cpu_fp_state);
++
++      task->thread.kernel_fpsimd_cpu = smp_processor_id();
+ }
+ void fpsimd_thread_switch(struct task_struct *next)
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-fpsimd-preserve-restore-kernel-mode-neon-at-co.patch b/queue-6.6/arm64-fpsimd-preserve-restore-kernel-mode-neon-at-co.patch
new file mode 100644 (file)
index 0000000..dca376b
--- /dev/null
@@ -0,0 +1,251 @@
+From bf3880ed007142c4d7ff620fb293c8c2becd58ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Dec 2023 12:32:21 +0100
+Subject: arm64: fpsimd: Preserve/restore kernel mode NEON at context switch
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+[ Upstream commit aefbab8e77eb16b56e18f24b85a09ebf4dc60e93 ]
+
+Currently, the FPSIMD register file is not preserved and restored along
+with the general registers on exception entry/exit or context switch.
+For this reason, we disable preemption when enabling FPSIMD for kernel
+mode use in task context, and suspend the processing of softirqs so that
+there are no concurrent uses in the kernel. (Kernel mode FPSIMD may not
+be used at all in other contexts).
+
+Disabling preemption while doing CPU intensive work on inputs of
+potentially unbounded size is bad for real-time performance, which is
+why we try and ensure that SIMD crypto code does not operate on more
+than ~4k at a time, which is an arbitrary limit and requires assembler
+code to implement efficiently.
+
+We can avoid the need for disabling preemption if we can ensure that any
+in-kernel users of the NEON will not lose the FPSIMD register state
+across a context switch. And given that disabling softirqs implicitly
+disables preemption as well, we will also have to ensure that a softirq
+that runs code using FPSIMD can safely interrupt an in-kernel user.
+
+So introduce a thread_info flag TIF_KERNEL_FPSTATE, and modify the
+context switch hook for FPSIMD to preserve and restore the kernel mode
+FPSIMD to/from struct thread_struct when it is set. This avoids any
+scheduling blackouts due to prolonged use of FPSIMD in kernel mode,
+without the need for manual yielding.
+
+In order to support softirq processing while FPSIMD is being used in
+kernel task context, use the same flag to decide whether the kernel mode
+FPSIMD state needs to be preserved and restored before allowing FPSIMD
+to be used in softirq context.
+
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Reviewed-by: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20231208113218.3001940-8-ardb@google.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Stable-dep-of: b8995a184170 ("Revert "arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD"")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/processor.h   |  2 +
+ arch/arm64/include/asm/thread_info.h |  1 +
+ arch/arm64/kernel/fpsimd.c           | 92 ++++++++++++++++++++++------
+ 3 files changed, 77 insertions(+), 18 deletions(-)
+
+diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
+index e5bc54522e711..ce6eebd6c08bd 100644
+--- a/arch/arm64/include/asm/processor.h
++++ b/arch/arm64/include/asm/processor.h
+@@ -167,6 +167,8 @@ struct thread_struct {
+       unsigned long           fault_address;  /* fault info */
+       unsigned long           fault_code;     /* ESR_EL1 value */
+       struct debug_info       debug;          /* debugging */
++
++      struct user_fpsimd_state        kernel_fpsimd_state;
+ #ifdef CONFIG_ARM64_PTR_AUTH
+       struct ptrauth_keys_user        keys_user;
+ #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
+diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
+index 553d1bc559c60..e72a3bf9e5634 100644
+--- a/arch/arm64/include/asm/thread_info.h
++++ b/arch/arm64/include/asm/thread_info.h
+@@ -80,6 +80,7 @@ void arch_setup_new_exec(void);
+ #define TIF_TAGGED_ADDR               26      /* Allow tagged user addresses */
+ #define TIF_SME                       27      /* SME in use */
+ #define TIF_SME_VL_INHERIT    28      /* Inherit SME vl_onexec across exec */
++#define TIF_KERNEL_FPSTATE    29      /* Task is in a kernel mode FPSIMD section */
+ #define _TIF_SIGPENDING               (1 << TIF_SIGPENDING)
+ #define _TIF_NEED_RESCHED     (1 << TIF_NEED_RESCHED)
+diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
+index b805bdab284c4..aa695057c93dd 100644
+--- a/arch/arm64/kernel/fpsimd.c
++++ b/arch/arm64/kernel/fpsimd.c
+@@ -357,6 +357,7 @@ static void task_fpsimd_load(void)
+       WARN_ON(!system_supports_fpsimd());
+       WARN_ON(preemptible());
++      WARN_ON(test_thread_flag(TIF_KERNEL_FPSTATE));
+       if (system_supports_sve() || system_supports_sme()) {
+               switch (current->thread.fp_type) {
+@@ -379,7 +380,7 @@ static void task_fpsimd_load(void)
+               default:
+                       /*
+                        * This indicates either a bug in
+-                       * fpsimd_save() or memory corruption, we
++                       * fpsimd_save_user_state() or memory corruption, we
+                        * should always record an explicit format
+                        * when we save. We always at least have the
+                        * memory allocated for FPSMID registers so
+@@ -430,7 +431,7 @@ static void task_fpsimd_load(void)
+  * than via current, if we are saving KVM state then it will have
+  * ensured that the type of registers to save is set in last->to_save.
+  */
+-static void fpsimd_save(void)
++static void fpsimd_save_user_state(void)
+ {
+       struct cpu_fp_state const *last =
+               this_cpu_ptr(&fpsimd_last_state);
+@@ -863,7 +864,7 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,
+       if (task == current) {
+               get_cpu_fpsimd_context();
+-              fpsimd_save();
++              fpsimd_save_user_state();
+       }
+       fpsimd_flush_task_state(task);
+@@ -1549,6 +1550,16 @@ void do_fpsimd_exc(unsigned long esr, struct pt_regs *regs)
+                      current);
+ }
++static void fpsimd_load_kernel_state(struct task_struct *task)
++{
++      fpsimd_load_state(&task->thread.kernel_fpsimd_state);
++}
++
++static void fpsimd_save_kernel_state(struct task_struct *task)
++{
++      fpsimd_save_state(&task->thread.kernel_fpsimd_state);
++}
++
+ void fpsimd_thread_switch(struct task_struct *next)
+ {
+       bool wrong_task, wrong_cpu;
+@@ -1559,19 +1570,28 @@ void fpsimd_thread_switch(struct task_struct *next)
+       WARN_ON_ONCE(!irqs_disabled());
+       /* Save unsaved fpsimd state, if any: */
+-      fpsimd_save();
++      if (test_thread_flag(TIF_KERNEL_FPSTATE))
++              fpsimd_save_kernel_state(current);
++      else
++              fpsimd_save_user_state();
+-      /*
+-       * Fix up TIF_FOREIGN_FPSTATE to correctly describe next's
+-       * state.  For kernel threads, FPSIMD registers are never loaded
+-       * and wrong_task and wrong_cpu will always be true.
+-       */
+-      wrong_task = __this_cpu_read(fpsimd_last_state.st) !=
+-                                      &next->thread.uw.fpsimd_state;
+-      wrong_cpu = next->thread.fpsimd_cpu != smp_processor_id();
++      if (test_tsk_thread_flag(next, TIF_KERNEL_FPSTATE)) {
++              fpsimd_load_kernel_state(next);
++              set_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE);
++      } else {
++              /*
++               * Fix up TIF_FOREIGN_FPSTATE to correctly describe next's
++               * state.  For kernel threads, FPSIMD registers are never
++               * loaded with user mode FPSIMD state and so wrong_task and
++               * wrong_cpu will always be true.
++               */
++              wrong_task = __this_cpu_read(fpsimd_last_state.st) !=
++                      &next->thread.uw.fpsimd_state;
++              wrong_cpu = next->thread.fpsimd_cpu != smp_processor_id();
+-      update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE,
+-                             wrong_task || wrong_cpu);
++              update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE,
++                                     wrong_task || wrong_cpu);
++      }
+ }
+ static void fpsimd_flush_thread_vl(enum vec_type type)
+@@ -1661,7 +1681,7 @@ void fpsimd_preserve_current_state(void)
+               return;
+       get_cpu_fpsimd_context();
+-      fpsimd_save();
++      fpsimd_save_user_state();
+       put_cpu_fpsimd_context();
+ }
+@@ -1869,7 +1889,7 @@ void fpsimd_save_and_flush_cpu_state(void)
+               return;
+       WARN_ON(preemptible());
+       local_irq_save(flags);
+-      fpsimd_save();
++      fpsimd_save_user_state();
+       fpsimd_flush_cpu_state();
+       local_irq_restore(flags);
+ }
+@@ -1903,10 +1923,37 @@ void kernel_neon_begin(void)
+       get_cpu_fpsimd_context();
+       /* Save unsaved fpsimd state, if any: */
+-      fpsimd_save();
++      if (test_thread_flag(TIF_KERNEL_FPSTATE)) {
++              BUG_ON(IS_ENABLED(CONFIG_PREEMPT_RT) || !in_serving_softirq());
++              fpsimd_save_kernel_state(current);
++      } else {
++              fpsimd_save_user_state();
++
++              /*
++               * Set the thread flag so that the kernel mode FPSIMD state
++               * will be context switched along with the rest of the task
++               * state.
++               *
++               * On non-PREEMPT_RT, softirqs may interrupt task level kernel
++               * mode FPSIMD, but the task will not be preemptible so setting
++               * TIF_KERNEL_FPSTATE for those would be both wrong (as it
++               * would mark the task context FPSIMD state as requiring a
++               * context switch) and unnecessary.
++               *
++               * On PREEMPT_RT, softirqs are serviced from a separate thread,
++               * which is scheduled as usual, and this guarantees that these
++               * softirqs are not interrupting use of the FPSIMD in kernel
++               * mode in task context. So in this case, setting the flag here
++               * is always appropriate.
++               */
++              if (IS_ENABLED(CONFIG_PREEMPT_RT) || !in_serving_softirq())
++                      set_thread_flag(TIF_KERNEL_FPSTATE);
++      }
+       /* Invalidate any task state remaining in the fpsimd regs: */
+       fpsimd_flush_cpu_state();
++
++      put_cpu_fpsimd_context();
+ }
+ EXPORT_SYMBOL_GPL(kernel_neon_begin);
+@@ -1924,7 +1971,16 @@ void kernel_neon_end(void)
+       if (!system_supports_fpsimd())
+               return;
+-      put_cpu_fpsimd_context();
++      /*
++       * If we are returning from a nested use of kernel mode FPSIMD, restore
++       * the task context kernel mode FPSIMD state. This can only happen when
++       * running in softirq context on non-PREEMPT_RT.
++       */
++      if (!IS_ENABLED(CONFIG_PREEMPT_RT) && in_serving_softirq() &&
++          test_thread_flag(TIF_KERNEL_FPSTATE))
++              fpsimd_load_kernel_state(current);
++      else
++              clear_thread_flag(TIF_KERNEL_FPSTATE);
+ }
+ EXPORT_SYMBOL_GPL(kernel_neon_end);
+-- 
+2.43.0
+
diff --git a/queue-6.6/coresight-etm4x-do-not-hardcode-iomem-access-for-reg.patch b/queue-6.6/coresight-etm4x-do-not-hardcode-iomem-access-for-reg.patch
new file mode 100644 (file)
index 0000000..f05011c
--- /dev/null
@@ -0,0 +1,44 @@
+From 59860d678e1c04295013eec8d29a0ccc2d6d3632 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Apr 2024 15:26:59 +0100
+Subject: coresight: etm4x: Do not hardcode IOMEM access for register restore
+
+From: Suzuki K Poulose <suzuki.poulose@arm.com>
+
+[ Upstream commit 1e7ba33fa591de1cf60afffcabb45600b3607025 ]
+
+When we restore the register state for ETM4x, while coming back
+from CPU idle, we hardcode IOMEM access. This is wrong and could
+blow up for an ETM with system instructions access (and for ETE).
+
+Fixes: f5bd523690d2 ("coresight: etm4x: Convert all register accesses")
+Reported-by: Yabin Cui <yabinc@google.com>
+Reviewed-by: Mike Leach <mike.leach@linaro.org>
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Tested-by: Yabin Cui <yabinc@google.com>
+Link: https://lore.kernel.org/r/20240412142702.2882478-2-suzuki.poulose@arm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/coresight/coresight-etm4x-core.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+index 003245a791a23..ad866e29020e3 100644
+--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
++++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+@@ -1805,8 +1805,10 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
+ {
+       int i;
+       struct etmv4_save_state *state = drvdata->save_state;
+-      struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
+-      struct csdev_access *csa = &tmp_csa;
++      struct csdev_access *csa = &drvdata->csdev->access;
++
++      if (WARN_ON(!drvdata->csdev))
++              return;
+       etm4_cs_unlock(drvdata, csa);
+       etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
+-- 
+2.43.0
+
diff --git a/queue-6.6/coresight-etm4x-do-not-save-restore-data-trace-contr.patch b/queue-6.6/coresight-etm4x-do-not-save-restore-data-trace-contr.patch
new file mode 100644 (file)
index 0000000..72b53a2
--- /dev/null
@@ -0,0 +1,119 @@
+From 579f6a62807f9f21231a2b1715bb45dcfb4f9cbb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Apr 2024 15:27:00 +0100
+Subject: coresight: etm4x: Do not save/restore Data trace control registers
+
+From: Suzuki K Poulose <suzuki.poulose@arm.com>
+
+[ Upstream commit 5eb3a0c2c52368cb9902e9a6ea04888e093c487d ]
+
+ETM4x doesn't support Data trace on A class CPUs. As such do not access the
+Data trace control registers during CPU idle. This could cause problems for
+ETE. While at it, remove all references to the Data trace control registers.
+
+Fixes: f188b5e76aae ("coresight: etm4x: Save/restore state across CPU low power states")
+Reported-by: Yabin Cui <yabinc@google.com>
+Reviewed-by: Mike Leach <mike.leach@linaro.org>
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Tested-by: Yabin Cui <yabinc@google.com>
+Link: https://lore.kernel.org/r/20240412142702.2882478-3-suzuki.poulose@arm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../coresight/coresight-etm4x-core.c          |  6 ----
+ drivers/hwtracing/coresight/coresight-etm4x.h | 28 -------------------
+ 2 files changed, 34 deletions(-)
+
+diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+index ad866e29020e3..98895bd918ea5 100644
+--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
++++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+@@ -1701,9 +1701,6 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
+       state->trcvissctlr = etm4x_read32(csa, TRCVISSCTLR);
+       if (drvdata->nr_pe_cmp)
+               state->trcvipcssctlr = etm4x_read32(csa, TRCVIPCSSCTLR);
+-      state->trcvdctlr = etm4x_read32(csa, TRCVDCTLR);
+-      state->trcvdsacctlr = etm4x_read32(csa, TRCVDSACCTLR);
+-      state->trcvdarcctlr = etm4x_read32(csa, TRCVDARCCTLR);
+       for (i = 0; i < drvdata->nrseqstate - 1; i++)
+               state->trcseqevr[i] = etm4x_read32(csa, TRCSEQEVRn(i));
+@@ -1834,9 +1831,6 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
+       etm4x_relaxed_write32(csa, state->trcvissctlr, TRCVISSCTLR);
+       if (drvdata->nr_pe_cmp)
+               etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR);
+-      etm4x_relaxed_write32(csa, state->trcvdctlr, TRCVDCTLR);
+-      etm4x_relaxed_write32(csa, state->trcvdsacctlr, TRCVDSACCTLR);
+-      etm4x_relaxed_write32(csa, state->trcvdarcctlr, TRCVDARCCTLR);
+       for (i = 0; i < drvdata->nrseqstate - 1; i++)
+               etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i));
+diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
+index da17b6c49b0f1..574dbaef50836 100644
+--- a/drivers/hwtracing/coresight/coresight-etm4x.h
++++ b/drivers/hwtracing/coresight/coresight-etm4x.h
+@@ -43,9 +43,6 @@
+ #define TRCVIIECTLR                   0x084
+ #define TRCVISSCTLR                   0x088
+ #define TRCVIPCSSCTLR                 0x08C
+-#define TRCVDCTLR                     0x0A0
+-#define TRCVDSACCTLR                  0x0A4
+-#define TRCVDARCCTLR                  0x0A8
+ /* Derived resources registers */
+ #define TRCSEQEVRn(n)                 (0x100 + (n * 4)) /* n = 0-2 */
+ #define TRCSEQRSTEVR                  0x118
+@@ -90,9 +87,6 @@
+ /* Address Comparator registers n = 0-15 */
+ #define TRCACVRn(n)                   (0x400 + (n * 8))
+ #define TRCACATRn(n)                  (0x480 + (n * 8))
+-/* Data Value Comparator Value registers, n = 0-7 */
+-#define TRCDVCVRn(n)                  (0x500 + (n * 16))
+-#define TRCDVCMRn(n)                  (0x580 + (n * 16))
+ /* ContextID/Virtual ContextID comparators, n = 0-7 */
+ #define TRCCIDCVRn(n)                 (0x600 + (n * 8))
+ #define TRCVMIDCVRn(n)                        (0x640 + (n * 8))
+@@ -272,9 +266,6 @@
+ /* List of registers accessible via System instructions */
+ #define ETM4x_ONLY_SYSREG_LIST(op, val)               \
+       CASE_##op((val), TRCPROCSELR)           \
+-      CASE_##op((val), TRCVDCTLR)             \
+-      CASE_##op((val), TRCVDSACCTLR)          \
+-      CASE_##op((val), TRCVDARCCTLR)          \
+       CASE_##op((val), TRCOSLAR)
+ #define ETM_COMMON_SYSREG_LIST(op, val)               \
+@@ -422,22 +413,6 @@
+       CASE_##op((val), TRCACATRn(13))         \
+       CASE_##op((val), TRCACATRn(14))         \
+       CASE_##op((val), TRCACATRn(15))         \
+-      CASE_##op((val), TRCDVCVRn(0))          \
+-      CASE_##op((val), TRCDVCVRn(1))          \
+-      CASE_##op((val), TRCDVCVRn(2))          \
+-      CASE_##op((val), TRCDVCVRn(3))          \
+-      CASE_##op((val), TRCDVCVRn(4))          \
+-      CASE_##op((val), TRCDVCVRn(5))          \
+-      CASE_##op((val), TRCDVCVRn(6))          \
+-      CASE_##op((val), TRCDVCVRn(7))          \
+-      CASE_##op((val), TRCDVCMRn(0))          \
+-      CASE_##op((val), TRCDVCMRn(1))          \
+-      CASE_##op((val), TRCDVCMRn(2))          \
+-      CASE_##op((val), TRCDVCMRn(3))          \
+-      CASE_##op((val), TRCDVCMRn(4))          \
+-      CASE_##op((val), TRCDVCMRn(5))          \
+-      CASE_##op((val), TRCDVCMRn(6))          \
+-      CASE_##op((val), TRCDVCMRn(7))          \
+       CASE_##op((val), TRCCIDCVRn(0))         \
+       CASE_##op((val), TRCCIDCVRn(1))         \
+       CASE_##op((val), TRCCIDCVRn(2))         \
+@@ -907,9 +882,6 @@ struct etmv4_save_state {
+       u32     trcviiectlr;
+       u32     trcvissctlr;
+       u32     trcvipcssctlr;
+-      u32     trcvdctlr;
+-      u32     trcvdsacctlr;
+-      u32     trcvdarcctlr;
+       u32     trcseqevr[ETM_MAX_SEQ_STATES];
+       u32     trcseqrstevr;
+-- 
+2.43.0
+
diff --git a/queue-6.6/coresight-etm4x-fix-access-to-resource-selector-regi.patch b/queue-6.6/coresight-etm4x-fix-access-to-resource-selector-regi.patch
new file mode 100644 (file)
index 0000000..278aa6e
--- /dev/null
@@ -0,0 +1,51 @@
+From a0ce376526dcb538277f4a3a4011f6060e64bd13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Apr 2024 15:27:02 +0100
+Subject: coresight: etm4x: Fix access to resource selector registers
+
+From: Suzuki K Poulose <suzuki.poulose@arm.com>
+
+[ Upstream commit d6fc00d0f640d6010b51054aa8b0fd191177dbc9 ]
+
+Resource selector pair 0 is always implemented and reserved. We must not
+touch it, even during save/restore for CPU Idle. Rest of the driver is
+well behaved. Fix the offending ones.
+
+Reported-by: Yabin Cui <yabinc@google.com>
+Fixes: f188b5e76aae ("coresight: etm4x: Save/restore state across CPU low power states")
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Tested-by: Yabin Cui <yabinc@google.com>
+Reviewed-by: Mike Leach <mike.leach@linaro.org>
+Link: https://lore.kernel.org/r/20240412142702.2882478-5-suzuki.poulose@arm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/coresight/coresight-etm4x-core.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+index a409872c25717..840e4cccf8c4b 100644
+--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
++++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+@@ -1720,7 +1720,8 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
+               state->trccntvr[i] = etm4x_read32(csa, TRCCNTVRn(i));
+       }
+-      for (i = 0; i < drvdata->nr_resource * 2; i++)
++      /* Resource selector pair 0 is reserved */
++      for (i = 2; i < drvdata->nr_resource * 2; i++)
+               state->trcrsctlr[i] = etm4x_read32(csa, TRCRSCTLRn(i));
+       for (i = 0; i < drvdata->nr_ss_cmp; i++) {
+@@ -1851,7 +1852,8 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
+               etm4x_relaxed_write32(csa, state->trccntvr[i], TRCCNTVRn(i));
+       }
+-      for (i = 0; i < drvdata->nr_resource * 2; i++)
++      /* Resource selector pair 0 is reserved */
++      for (i = 2; i < drvdata->nr_resource * 2; i++)
+               etm4x_relaxed_write32(csa, state->trcrsctlr[i], TRCRSCTLRn(i));
+       for (i = 0; i < drvdata->nr_ss_cmp; i++) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/coresight-etm4x-fix-unbalanced-pm_runtime_enable.patch b/queue-6.6/coresight-etm4x-fix-unbalanced-pm_runtime_enable.patch
new file mode 100644 (file)
index 0000000..1068825
--- /dev/null
@@ -0,0 +1,66 @@
+From 5f219d57184fe676e237174f3738e17e6de28b54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Mar 2024 11:28:33 +0530
+Subject: coresight: etm4x: Fix unbalanced pm_runtime_enable()
+
+From: Anshuman Khandual <anshuman.khandual@arm.com>
+
+[ Upstream commit caa41c47dab7e1054f587e592ab21296e3a6781c ]
+
+There is an unbalanced pm_runtime_enable() in etm4_probe_platform_dev()
+when etm4_probe() fails. This problem can be observed via the coresight
+etm4 module's (load -> unload -> load) sequence when etm4_probe() fails
+in etm4_probe_platform_dev().
+
+[   63.379943] coresight-etm4x 7040000.etm: Unbalanced pm_runtime_enable!
+[   63.393630] coresight-etm4x 7140000.etm: Unbalanced pm_runtime_enable!
+[   63.407455] coresight-etm4x 7240000.etm: Unbalanced pm_runtime_enable!
+[   63.420983] coresight-etm4x 7340000.etm: Unbalanced pm_runtime_enable!
+[   63.420999] coresight-etm4x 7440000.etm: Unbalanced pm_runtime_enable!
+[   63.441209] coresight-etm4x 7540000.etm: Unbalanced pm_runtime_enable!
+[   63.454689] coresight-etm4x 7640000.etm: Unbalanced pm_runtime_enable!
+[   63.474982] coresight-etm4x 7740000.etm: Unbalanced pm_runtime_enable!
+
+This fixes the above problem - with an explicit pm_runtime_disable() call
+when etm4_probe() fails during etm4_probe_platform_dev().
+
+Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Cc: Hanjun Guo <guohanjun@huawei.com>
+Cc: Sudeep Holla <sudeep.holla@arm.com>
+Cc: "Rafael J. Wysocki" <rafael@kernel.org>
+Cc: Len Brown <lenb@kernel.org>
+Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
+Cc: Mike Leach <mike.leach@linaro.org>
+Cc: James Clark <james.clark@arm.com>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: linux-acpi@vger.kernel.org
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-kernel@vger.kernel.org
+Cc: coresight@lists.linaro.org
+Fixes: 5214b563588e ("coresight: etm4x: Add support for sysreg only devices")
+Reviewed-by: James Clark <james.clark@arm.com>
+Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Link: https://lore.kernel.org/r/20240314055843.2625883-2-anshuman.khandual@arm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/coresight/coresight-etm4x-core.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+index 18c4544f60454..003245a791a23 100644
+--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
++++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+@@ -2175,6 +2175,9 @@ static int etm4_probe_platform_dev(struct platform_device *pdev)
+       ret = etm4_probe(&pdev->dev);
+       pm_runtime_put(&pdev->dev);
++      if (ret)
++              pm_runtime_disable(&pdev->dev);
++
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/coresight-etm4x-safe-access-for-trcqcltr.patch b/queue-6.6/coresight-etm4x-safe-access-for-trcqcltr.patch
new file mode 100644 (file)
index 0000000..5a6f369
--- /dev/null
@@ -0,0 +1,90 @@
+From c12501a4fa3d1b6121d1f36c73afd512a8f42749 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Apr 2024 15:27:01 +0100
+Subject: coresight: etm4x: Safe access for TRCQCLTR
+
+From: Suzuki K Poulose <suzuki.poulose@arm.com>
+
+[ Upstream commit 46bf8d7cd8530eca607379033b9bc4ac5590a0cd ]
+
+ETM4x implements TRCQCLTR only when the Q elements are supported
+and the Q element filtering is supported (TRCIDR0.QFILT). Access
+to the register otherwise could be fatal. Fix this by tracking the
+availability, like the others.
+
+Fixes: f188b5e76aae ("coresight: etm4x: Save/restore state across CPU low power states")
+Reported-by: Yabin Cui <yabinc@google.com>
+Reviewed-by: Mike Leach <mike.leach@linaro.org>
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Tested-by: Yabin Cui <yabinc@google.com>
+Link: https://lore.kernel.org/r/20240412142702.2882478-4-suzuki.poulose@arm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/coresight/coresight-etm4x-core.c | 8 ++++++--
+ drivers/hwtracing/coresight/coresight-etm4x.h      | 3 +++
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+index 98895bd918ea5..a409872c25717 100644
+--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
++++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+@@ -1204,6 +1204,8 @@ static void etm4_init_arch_data(void *info)
+       drvdata->nr_event = FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0);
+       /* QSUPP, bits[16:15] Q element support field */
+       drvdata->q_support = FIELD_GET(TRCIDR0_QSUPP_MASK, etmidr0);
++      if (drvdata->q_support)
++              drvdata->q_filt = !!(etmidr0 & TRCIDR0_QFILT);
+       /* TSSIZE, bits[28:24] Global timestamp size field */
+       drvdata->ts_size = FIELD_GET(TRCIDR0_TSSIZE_MASK, etmidr0);
+@@ -1694,7 +1696,8 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
+       state->trcccctlr = etm4x_read32(csa, TRCCCCTLR);
+       state->trcbbctlr = etm4x_read32(csa, TRCBBCTLR);
+       state->trctraceidr = etm4x_read32(csa, TRCTRACEIDR);
+-      state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
++      if (drvdata->q_filt)
++              state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
+       state->trcvictlr = etm4x_read32(csa, TRCVICTLR);
+       state->trcviiectlr = etm4x_read32(csa, TRCVIIECTLR);
+@@ -1824,7 +1827,8 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
+       etm4x_relaxed_write32(csa, state->trcccctlr, TRCCCCTLR);
+       etm4x_relaxed_write32(csa, state->trcbbctlr, TRCBBCTLR);
+       etm4x_relaxed_write32(csa, state->trctraceidr, TRCTRACEIDR);
+-      etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR);
++      if (drvdata->q_filt)
++              etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR);
+       etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR);
+       etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR);
+diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
+index 574dbaef50836..6b6760e49ed35 100644
+--- a/drivers/hwtracing/coresight/coresight-etm4x.h
++++ b/drivers/hwtracing/coresight/coresight-etm4x.h
+@@ -135,6 +135,7 @@
+ #define TRCIDR0_TRCCCI                                BIT(7)
+ #define TRCIDR0_RETSTACK                      BIT(9)
+ #define TRCIDR0_NUMEVENT_MASK                 GENMASK(11, 10)
++#define TRCIDR0_QFILT                         BIT(14)
+ #define TRCIDR0_QSUPP_MASK                    GENMASK(16, 15)
+ #define TRCIDR0_TSSIZE_MASK                   GENMASK(28, 24)
+@@ -954,6 +955,7 @@ struct etmv4_save_state {
+  * @os_unlock:  True if access to management registers is allowed.
+  * @instrp0:  Tracing of load and store instructions
+  *            as P0 elements is supported.
++ * @q_filt:   Q element filtering support, if Q elements are supported.
+  * @trcbb:    Indicates if the trace unit supports branch broadcast tracing.
+  * @trccond:  If the trace unit supports conditional
+  *            instruction tracing.
+@@ -1017,6 +1019,7 @@ struct etmv4_drvdata {
+       bool                            boot_enable;
+       bool                            os_unlock;
+       bool                            instrp0;
++      bool                            q_filt;
+       bool                            trcbb;
+       bool                            trccond;
+       bool                            retstack;
+-- 
+2.43.0
+
diff --git a/queue-6.6/counter-linux-counter.h-fix-excess-kernel-doc-descri.patch b/queue-6.6/counter-linux-counter.h-fix-excess-kernel-doc-descri.patch
new file mode 100644 (file)
index 0000000..7d75f1b
--- /dev/null
@@ -0,0 +1,37 @@
+From 30e80f5c5db3ce5919ee3701cb35419af3586e27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Dec 2023 21:05:11 -0800
+Subject: counter: linux/counter.h: fix Excess kernel-doc description warning
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit 416bdb89605d960405178b9bf04df512d1ace1a3 ]
+
+Remove the @priv: line to prevent the kernel-doc warning:
+
+include/linux/counter.h:400: warning: Excess struct member 'priv' description in 'counter_device'
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Fixes: f2ee4759fb70 ("counter: remove old and now unused registration API")
+Link: https://lore.kernel.org/r/20231223050511.13849-1-rdunlap@infradead.org
+Signed-off-by: William Breathitt Gray <william.gray@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/counter.h | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/include/linux/counter.h b/include/linux/counter.h
+index 702e9108bbb44..b767b5c821f58 100644
+--- a/include/linux/counter.h
++++ b/include/linux/counter.h
+@@ -359,7 +359,6 @@ struct counter_ops {
+  * @num_counts:               number of Counts specified in @counts
+  * @ext:              optional array of Counter device extensions
+  * @num_ext:          number of Counter device extensions specified in @ext
+- * @priv:             optional private data supplied by driver
+  * @dev:              internal device structure
+  * @chrdev:           internal character device structure
+  * @events_list:      list of current watching Counter events
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-idma64-add-check-for-dma_set_max_seg_size.patch b/queue-6.6/dmaengine-idma64-add-check-for-dma_set_max_seg_size.patch
new file mode 100644 (file)
index 0000000..90432d4
--- /dev/null
@@ -0,0 +1,40 @@
+From 5bc3b03a14281f9ee397826e154a9d7089c8f4e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Apr 2024 02:49:32 +0000
+Subject: dmaengine: idma64: Add check for dma_set_max_seg_size
+
+From: Chen Ni <nichen@iscas.ac.cn>
+
+[ Upstream commit 2b1c1cf08a0addb6df42f16b37133dc7a351de29 ]
+
+As the possible failure of the dma_set_max_seg_size(), it should be
+better to check the return value of the dma_set_max_seg_size().
+
+Fixes: e3fdb1894cfa ("dmaengine: idma64: set maximum allowed segment size for DMA")
+Signed-off-by: Chen Ni <nichen@iscas.ac.cn>
+Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20240403024932.3342606-1-nichen@iscas.ac.cn
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/idma64.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c
+index f86939fa33b95..6fa797fd85017 100644
+--- a/drivers/dma/idma64.c
++++ b/drivers/dma/idma64.c
+@@ -598,7 +598,9 @@ static int idma64_probe(struct idma64_chip *chip)
+       idma64->dma.dev = chip->sysdev;
+-      dma_set_max_seg_size(idma64->dma.dev, IDMA64C_CTLH_BLOCK_TS_MASK);
++      ret = dma_set_max_seg_size(idma64->dma.dev, IDMA64C_CTLH_BLOCK_TS_MASK);
++      if (ret)
++              return ret;
+       ret = dma_async_device_register(&idma64->dma);
+       if (ret)
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-idxd-avoid-unnecessary-destruction-of-file.patch b/queue-6.6/dmaengine-idxd-avoid-unnecessary-destruction-of-file.patch
new file mode 100644 (file)
index 0000000..cc6b008
--- /dev/null
@@ -0,0 +1,46 @@
+From 3103ab70c738b7ae28abb12b0c39efbb2454be87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jan 2024 17:39:54 -0800
+Subject: dmaengine: idxd: Avoid unnecessary destruction of file_ida
+
+From: Fenghua Yu <fenghua.yu@intel.com>
+
+[ Upstream commit 76e43fa6a456787bad31b8d0daeabda27351a480 ]
+
+file_ida is allocated during cdev open and is freed accordingly
+during cdev release. This sequence is guaranteed by driver file
+operations. Therefore, there is no need to destroy an already empty
+file_ida when the WQ cdev is removed.
+
+Worse, ida_free() in cdev release may happen after destruction of
+file_ida per WQ cdev. This can lead to accessing an id in file_ida
+after it has been destroyed, resulting in a kernel panic.
+
+Remove ida_destroy(&file_ida) to address these issues.
+
+Fixes: e6fd6d7e5f0f ("dmaengine: idxd: add a device to represent the file opened")
+Signed-off-by: Lijun Pan <lijun.pan@intel.com>
+Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
+Reviewed-by: Dave Jiang <dave.jiang@intel.com>
+Link: https://lore.kernel.org/r/20240130013954.2024231-1-fenghua.yu@intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/idxd/cdev.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c
+index 26f1dedc92d38..c18633ad8455f 100644
+--- a/drivers/dma/idxd/cdev.c
++++ b/drivers/dma/idxd/cdev.c
+@@ -577,7 +577,6 @@ void idxd_wq_del_cdev(struct idxd_wq *wq)
+       struct idxd_cdev *idxd_cdev;
+       idxd_cdev = wq->idxd_cdev;
+-      ida_destroy(&file_ida);
+       wq->idxd_cdev = NULL;
+       cdev_device_del(&idxd_cdev->cdev, cdev_dev(idxd_cdev));
+       put_device(cdev_dev(idxd_cdev));
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-amd-display-remove-pixle-rate-limit-for-subvp.patch b/queue-6.6/drm-amd-display-remove-pixle-rate-limit-for-subvp.patch
new file mode 100644 (file)
index 0000000..ed9e106
--- /dev/null
@@ -0,0 +1,39 @@
+From 3d8437b947cfb87b486dfbdf336ac40b5fe2b60f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Feb 2024 10:40:36 -0500
+Subject: drm/amd/display: Remove pixle rate limit for subvp
+
+From: Alvin Lee <alvin.lee2@amd.com>
+
+[ Upstream commit 340383c734f8a4e1663d26356b35fd8050851168 ]
+
+Subvp bugs related to 8K60 have been fixed, so remove the limit that
+blocks 8K60 timings from enabling SubVP.
+
+Reviewed-by: Nevenko Stupar <nevenko.stupar@amd.com>
+Reviewed-by: Chaitanya Dhere <chaitanya.dhere@amd.com>
+Acked-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alvin Lee <alvin.lee2@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: cf8c498694a4 ("drm/amd/display: Revert Remove pixle rate limit for subvp")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+index cf3b400c8619b..426902578ca46 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+@@ -697,7 +697,6 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
+                * - Not TMZ surface
+                */
+               if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) &&
+-                              !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) &&
+                               (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) &&
+                               pipe->stream->mall_stream_config.type == SUBVP_NONE &&
+                               (refresh_rate < 120 || dcn32_allow_subvp_high_refresh_rate(dc, context, pipe)) &&
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-amd-display-revert-remove-pixle-rate-limit-for-s.patch b/queue-6.6/drm-amd-display-revert-remove-pixle-rate-limit-for-s.patch
new file mode 100644 (file)
index 0000000..421de19
--- /dev/null
@@ -0,0 +1,48 @@
+From c6e80daf894af5870d141f1b3ec5e2561d02ef85 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 11:20:27 -0500
+Subject: drm/amd/display: Revert Remove pixle rate limit for subvp
+
+From: Wenjing Liu <wenjing.liu@amd.com>
+
+[ Upstream commit cf8c498694a443e28dc1222f3ab94677114a4724 ]
+
+This reverts commit 340383c734f8 ("drm/amd/display: Remove pixle rate
+limit for subvp")
+
+[why]
+The original commit causes a regression when subvp is applied
+on ODM required 8k60hz timing. The display shows black screen
+on boot. The issue can be recovered with hotplug. It also causes
+MPO to fail. We will temprarily revert this commit and investigate
+the root cause further.
+
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Chaitanya Dhere <chaitanya.dhere@amd.com>
+Reviewed-by: Martin Leung <martin.leung@amd.com>
+Acked-by: Wayne Lin <wayne.lin@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/dml/dcn32/dcn32_fpu.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+index 426902578ca46..cf3b400c8619b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+@@ -697,6 +697,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
+                * - Not TMZ surface
+                */
+               if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) &&
++                              !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) &&
+                               (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) &&
+                               pipe->stream->mall_stream_config.type == SUBVP_NONE &&
+                               (refresh_rate < 120 || dcn32_allow_subvp_high_refresh_rate(dc, context, pipe)) &&
+-- 
+2.43.0
+
diff --git a/queue-6.6/dt-bindings-adc-axi-adc-add-clocks-property.patch b/queue-6.6/dt-bindings-adc-axi-adc-add-clocks-property.patch
new file mode 100644 (file)
index 0000000..81882fa
--- /dev/null
@@ -0,0 +1,60 @@
+From aeddb3e106079974f48cbea958a3c6149b093763 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Apr 2024 17:42:12 +0200
+Subject: dt-bindings: adc: axi-adc: add clocks property
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit 19fb11d7220b8abc016aa254dc7e6d9f2d49b178 ]
+
+Add a required clock property as we can't access the device registers if
+the AXI bus clock is not properly enabled.
+
+Note this clock is a very fundamental one that is typically enabled
+pretty early during boot. Independently of that, we should really rely on
+it to be enabled.
+
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Fixes: 96553a44e96d ("dt-bindings: iio: adc: add bindings doc for AXI ADC driver")
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20240426-ad9467-new-features-v2-3-6361fc3ba1cc@analog.com
+Cc: <Stable@ver.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml b/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml
+index 3d49d21ad33df..e1f450b80db27 100644
+--- a/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml
++++ b/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml
+@@ -28,6 +28,9 @@ properties:
+   reg:
+     maxItems: 1
++  clocks:
++    maxItems: 1
++
+   dmas:
+     maxItems: 1
+@@ -48,6 +51,7 @@ required:
+   - compatible
+   - dmas
+   - reg
++  - clocks
+ additionalProperties: false
+@@ -58,6 +62,7 @@ examples:
+         reg = <0x44a00000 0x10000>;
+         dmas = <&rx_dma 0>;
+         dma-names = "rx";
++        clocks = <&axi_clk>;
+         #io-backend-cells = <0>;
+     };
+ ...
+-- 
+2.43.0
+
diff --git a/queue-6.6/dt-bindings-adc-axi-adc-update-bindings-for-backend-.patch b/queue-6.6/dt-bindings-adc-axi-adc-update-bindings-for-backend-.patch
new file mode 100644 (file)
index 0000000..f3dcae5
--- /dev/null
@@ -0,0 +1,65 @@
+From 5a3e337fac251434c04e8a0af8719f67c3c321d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 10 Feb 2024 21:57:14 +0100
+Subject: dt-bindings: adc: axi-adc: update bindings for backend framework
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit a032b921bdeba2274866daafc8e791edd609eb13 ]
+
+'adi,adc-dev' is now deprecated and must not be used anymore. Hence,
+also remove it from being required.
+
+The reason why it's being deprecated is because the axi-adc CORE is now
+an IIO service provider hardware (IIO backends) for consumers to make use
+of. Before, the logic with 'adi,adc-dev' was the opposite (it was kind
+of consumer referencing other nodes/devices) and that proved to be wrong
+and to not scale.
+
+Now, IIO consumers of this hardware are expected to reference it using the
+io-backends property. Hence, the new '#io-backend-cells' is being added
+so the device is easily identified as a provider.
+
+Reviewed-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20240210-iio-backend-v11-2-f5242a5fb42a@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 19fb11d7220b ("dt-bindings: adc: axi-adc: add clocks property")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../devicetree/bindings/iio/adc/adi,axi-adc.yaml          | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml b/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml
+index 9996dd93f84b2..3d49d21ad33df 100644
+--- a/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml
++++ b/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml
+@@ -39,12 +39,15 @@ properties:
+     $ref: /schemas/types.yaml#/definitions/phandle
+     description:
+       A reference to a the actual ADC to which this FPGA ADC interfaces to.
++    deprecated: true
++
++  '#io-backend-cells':
++    const: 0
+ required:
+   - compatible
+   - dmas
+   - reg
+-  - adi,adc-dev
+ additionalProperties: false
+@@ -55,7 +58,6 @@ examples:
+         reg = <0x44a00000 0x10000>;
+         dmas = <&rx_dma 0>;
+         dma-names = "rx";
+-
+-        adi,adc-dev = <&spi_adc>;
++        #io-backend-cells = <0>;
+     };
+ ...
+-- 
+2.43.0
+
diff --git a/queue-6.6/dt-bindings-pci-rcar-pci-host-add-missing-iommu-prop.patch b/queue-6.6/dt-bindings-pci-rcar-pci-host-add-missing-iommu-prop.patch
new file mode 100644 (file)
index 0000000..f45b02d
--- /dev/null
@@ -0,0 +1,47 @@
+From 8c66b6e330e76a6816aae8edc696e72d1bb22046 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Feb 2024 16:52:01 +0100
+Subject: dt-bindings: PCI: rcar-pci-host: Add missing IOMMU properties
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+[ Upstream commit 78d212851f0e56b7d7083c4d5014aa7fa8b77e20 ]
+
+make dtbs_check:
+
+    arch/arm64/boot/dts/renesas/r8a77951-salvator-xs.dtb: pcie@fe000000: Unevaluated properties are not allowed ('iommu-map', 'iommu-map-mask' were unexpected)
+           from schema $id: http://devicetree.org/schemas/pci/rcar-pci-host.yaml#
+
+Fix this by adding the missing IOMMU-related properties.
+
+[kwilczynski: added missing Fixes: tag]
+Fixes: 0d69ce3c2c63 ("dt-bindings: PCI: rcar-pci-host: Convert bindings to json-schema")
+Link: https://lore.kernel.org/linux-pci/babc878a93cb6461a5d39331f8ecfa654dfda921.1706802597.git.geert+renesas@glider.be
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Acked-by: Conor Dooley <conor.dooley@microchip.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/devicetree/bindings/pci/rcar-pci-host.yaml | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml b/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml
+index b6a7cb32f61e5..835b6db00c279 100644
+--- a/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml
++++ b/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml
+@@ -77,6 +77,9 @@ properties:
+   vpcie12v-supply:
+     description: The 12v regulator to use for PCIe.
++  iommu-map: true
++  iommu-map-mask: true
++
+ required:
+   - compatible
+   - reg
+-- 
+2.43.0
+
diff --git a/queue-6.6/dt-bindings-pci-rcar-pci-host-add-optional-regulator.patch b/queue-6.6/dt-bindings-pci-rcar-pci-host-add-optional-regulator.patch
new file mode 100644 (file)
index 0000000..c3ae50a
--- /dev/null
@@ -0,0 +1,57 @@
+From 49b2ba213754cdfc3041073aee3a4d080c323ddd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Nov 2023 10:29:07 +0100
+Subject: dt-bindings: PCI: rcar-pci-host: Add optional regulators
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+
+[ Upstream commit b952f96a57e6fb4528c1d6be19e941c3322f9905 ]
+
+Support regulators found on the KingFisher board for miniPCIe (1.5 and
+3.3v). For completeness, describe a 12v regulator while we are here.
+
+Link: https://lore.kernel.org/linux-pci/20231105092908.3792-2-wsa+renesas@sang-engineering.com
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Stable-dep-of: 78d212851f0e ("dt-bindings: PCI: rcar-pci-host: Add missing IOMMU properties")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../devicetree/bindings/pci/rcar-pci-host.yaml        | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml b/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml
+index 8fdfbc763d704..b6a7cb32f61e5 100644
+--- a/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml
++++ b/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml
+@@ -68,6 +68,15 @@ properties:
+   phy-names:
+     const: pcie
++  vpcie1v5-supply:
++    description: The 1.5v regulator to use for PCIe.
++
++  vpcie3v3-supply:
++    description: The 3.3v regulator to use for PCIe.
++
++  vpcie12v-supply:
++    description: The 12v regulator to use for PCIe.
++
+ required:
+   - compatible
+   - reg
+@@ -121,5 +130,7 @@ examples:
+              clock-names = "pcie", "pcie_bus";
+              power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
+              resets = <&cpg 319>;
++             vpcie3v3-supply = <&pcie_3v3>;
++             vpcie12v-supply = <&pcie_12v>;
+          };
+     };
+-- 
+2.43.0
+
diff --git a/queue-6.6/dt-bindings-pci-rockchip-rk3399-pcie-add-missing-max.patch b/queue-6.6/dt-bindings-pci-rockchip-rk3399-pcie-add-missing-max.patch
new file mode 100644 (file)
index 0000000..686a599
--- /dev/null
@@ -0,0 +1,42 @@
+From 0d1229515c8f504b64e178cdedeb6a9bb6be96e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Apr 2024 12:00:58 +0200
+Subject: dt-bindings: PCI: rockchip,rk3399-pcie: Add missing maxItems to
+ ep-gpios
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 52d06636a4ae4db24ebfe23fae7a525f7e983604 ]
+
+Properties with GPIOs should define number of actual GPIOs, so add
+missing maxItems to ep-gpios.  Otherwise multiple GPIOs could be
+provided which is not a true hardware description.
+
+Fixes: aa222f9311e1 ("dt-bindings: PCI: Convert Rockchip RK3399 PCIe to DT schema")
+Link: https://lore.kernel.org/linux-pci/20240401100058.15749-1-krzysztof.kozlowski@linaro.org
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Acked-by: Conor Dooley <conor.dooley@microchip.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie.yaml b/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie.yaml
+index 531008f0b6ac3..002b728cbc718 100644
+--- a/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie.yaml
++++ b/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie.yaml
+@@ -37,6 +37,7 @@ properties:
+     description: This property is needed if using 24MHz OSC for RC's PHY.
+   ep-gpios:
++    maxItems: 1
+     description: pre-reset GPIO
+   vpcie12v-supply:
+-- 
+2.43.0
+
diff --git a/queue-6.6/dt-bindings-phy-qcom-sc8280xp-qmp-ufs-phy-fix-msm899.patch b/queue-6.6/dt-bindings-phy-qcom-sc8280xp-qmp-ufs-phy-fix-msm899.patch
new file mode 100644 (file)
index 0000000..9dfbd31
--- /dev/null
@@ -0,0 +1,61 @@
+From ea6e02d5cc98a6fba22e4107b49ea6061f0a5c4b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 May 2024 19:19:28 +0300
+Subject: dt-bindings: phy: qcom,sc8280xp-qmp-ufs-phy: fix msm899[68]
+ power-domains
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 59e377a124dc9039d9554d823b1cb4942bcee9a0 ]
+
+The Qualcomm MSM8996 and MSM8998 platforms don't have separate power
+domain for the UFS PHY. Replace required:power-domains with the
+conditional schema.
+
+Fixes: dc5cb63592bd ("dt-bindings: phy: migrate QMP UFS PHY bindings to qcom,sc8280xp-qmp-ufs-phy.yaml")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20240501-qcom-phy-fixes-v1-2-f1fd15c33fb3@linaro.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml  | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
+index d981d77e82e40..a6244c33faf61 100644
+--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
++++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
+@@ -71,7 +71,6 @@ required:
+   - reg
+   - clocks
+   - clock-names
+-  - power-domains
+   - resets
+   - reset-names
+   - vdda-phy-supply
+@@ -130,6 +129,21 @@ allOf:
+         clock-names:
+           maxItems: 1
++  - if:
++      properties:
++        compatible:
++          contains:
++            enum:
++              - qcom,msm8996-qmp-ufs-phy
++              - qcom,msm8998-qmp-ufs-phy
++    then:
++      properties:
++        power-domains:
++          false
++    else:
++      required:
++        - power-domains
++
+ additionalProperties: false
+ examples:
+-- 
+2.43.0
+
diff --git a/queue-6.6/dt-bindings-phy-qcom-usb-snps-femto-v2-use-correct-f.patch b/queue-6.6/dt-bindings-phy-qcom-usb-snps-femto-v2-use-correct-f.patch
new file mode 100644 (file)
index 0000000..d251ac6
--- /dev/null
@@ -0,0 +1,48 @@
+From 34e61e48c9e39ecaf1c90d713aa4ce99ce943c50 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 May 2024 19:19:29 +0300
+Subject: dt-bindings: phy: qcom,usb-snps-femto-v2: use correct fallback for
+ sc8180x
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 960b3f023d3bda0efd6e573a0647227d1115d266 ]
+
+The qcom,sc8180x-usb-hs-phy device uses qcom,usb-snps-hs-7nm-phy
+fallback. Correct the schema for this platform.
+
+Fixes: 9160fb7c39a1 ("dt-bindings: phy: qcom,usb-snps-femto-v2: use fallback compatibles")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20240501-qcom-phy-fixes-v1-3-f1fd15c33fb3@linaro.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml       | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml
+index 0f200e3f97a9a..fce7f8a19e9c0 100644
+--- a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml
++++ b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml
+@@ -15,9 +15,6 @@ description: |
+ properties:
+   compatible:
+     oneOf:
+-      - enum:
+-          - qcom,sc8180x-usb-hs-phy
+-          - qcom,usb-snps-femto-v2-phy
+       - items:
+           - enum:
+               - qcom,sa8775p-usb-hs-phy
+@@ -26,6 +23,7 @@ properties:
+       - items:
+           - enum:
+               - qcom,sc7280-usb-hs-phy
++              - qcom,sc8180x-usb-hs-phy
+               - qcom,sdx55-usb-hs-phy
+               - qcom,sdx65-usb-hs-phy
+               - qcom,sm6375-usb-hs-phy
+-- 
+2.43.0
+
diff --git a/queue-6.6/dt-bindings-pinctrl-mediatek-mt7622-fix-array-proper.patch b/queue-6.6/dt-bindings-pinctrl-mediatek-mt7622-fix-array-proper.patch
new file mode 100644 (file)
index 0000000..027345b
--- /dev/null
@@ -0,0 +1,168 @@
+From 33ff4eb014f64b42c041e3efaa4b7ac68daa9a4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Apr 2024 06:55:01 +0200
+Subject: dt-bindings: pinctrl: mediatek: mt7622: fix array properties
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rafał Miłecki <rafal@milecki.pl>
+
+[ Upstream commit 61fcbbf3ca038c048c942ce31bb3d3c846c87581 ]
+
+Some properties (function groups & pins) are meant to be arrays and
+should allow multiple entries out of enum sets. Use "items" for those.
+
+Mistake was noticed during validation of in-kernel DTS files.
+
+Fixes: b9ffc18c6388 ("dt-bindings: mediatek: convert pinctrl to yaml")
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Acked-by: Rob Herring <robh@kernel.org>
+Message-ID: <20240423045502.7778-1-zajec5@gmail.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../pinctrl/mediatek,mt7622-pinctrl.yaml      | 92 ++++++++++---------
+ 1 file changed, 49 insertions(+), 43 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
+index bd72a326e6e06..60f30a59f3853 100644
+--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
++++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
+@@ -97,7 +97,8 @@ patternProperties:
+             then:
+               properties:
+                 groups:
+-                  enum: [emmc, emmc_rst]
++                  items:
++                    enum: [emmc, emmc_rst]
+           - if:
+               properties:
+                 function:
+@@ -105,8 +106,9 @@ patternProperties:
+             then:
+               properties:
+                 groups:
+-                  enum: [esw, esw_p0_p1, esw_p2_p3_p4, rgmii_via_esw,
+-                         rgmii_via_gmac1, rgmii_via_gmac2, mdc_mdio]
++                  items:
++                    enum: [esw, esw_p0_p1, esw_p2_p3_p4, rgmii_via_esw,
++                           rgmii_via_gmac1, rgmii_via_gmac2, mdc_mdio]
+           - if:
+               properties:
+                 function:
+@@ -123,10 +125,11 @@ patternProperties:
+             then:
+               properties:
+                 groups:
+-                  enum: [i2s_in_mclk_bclk_ws, i2s1_in_data, i2s2_in_data,
+-                         i2s3_in_data, i2s4_in_data, i2s_out_mclk_bclk_ws,
+-                         i2s1_out_data, i2s2_out_data, i2s3_out_data,
+-                         i2s4_out_data]
++                  items:
++                    enum: [i2s_in_mclk_bclk_ws, i2s1_in_data, i2s2_in_data,
++                           i2s3_in_data, i2s4_in_data, i2s_out_mclk_bclk_ws,
++                           i2s1_out_data, i2s2_out_data, i2s3_out_data,
++                           i2s4_out_data]
+           - if:
+               properties:
+                 function:
+@@ -159,10 +162,11 @@ patternProperties:
+             then:
+               properties:
+                 groups:
+-                  enum: [pcie0_0_waken, pcie0_1_waken, pcie1_0_waken,
+-                         pcie0_0_clkreq, pcie0_1_clkreq, pcie1_0_clkreq,
+-                         pcie0_pad_perst, pcie1_pad_perst, pcie_pereset,
+-                         pcie_wake, pcie_clkreq]
++                  items:
++                    enum: [pcie0_0_waken, pcie0_1_waken, pcie1_0_waken,
++                           pcie0_0_clkreq, pcie0_1_clkreq, pcie1_0_clkreq,
++                           pcie0_pad_perst, pcie1_pad_perst, pcie_pereset,
++                           pcie_wake, pcie_clkreq]
+           - if:
+               properties:
+                 function:
+@@ -178,11 +182,12 @@ patternProperties:
+             then:
+               properties:
+                 groups:
+-                  enum: [pwm_ch1_0, pwm_ch1_1, pwm_ch1_2, pwm_ch2_0, pwm_ch2_1,
+-                         pwm_ch2_2, pwm_ch3_0, pwm_ch3_1, pwm_ch3_2, pwm_ch4_0,
+-                         pwm_ch4_1, pwm_ch4_2, pwm_ch4_3, pwm_ch5_0, pwm_ch5_1,
+-                         pwm_ch5_2, pwm_ch6_0, pwm_ch6_1, pwm_ch6_2, pwm_ch6_3,
+-                         pwm_ch7_0, pwm_0, pwm_1]
++                  items:
++                    enum: [pwm_ch1_0, pwm_ch1_1, pwm_ch1_2, pwm_ch2_0, pwm_ch2_1,
++                           pwm_ch2_2, pwm_ch3_0, pwm_ch3_1, pwm_ch3_2, pwm_ch4_0,
++                           pwm_ch4_1, pwm_ch4_2, pwm_ch4_3, pwm_ch5_0, pwm_ch5_1,
++                           pwm_ch5_2, pwm_ch6_0, pwm_ch6_1, pwm_ch6_2, pwm_ch6_3,
++                           pwm_ch7_0, pwm_0, pwm_1]
+           - if:
+               properties:
+                 function:
+@@ -260,33 +265,34 @@ patternProperties:
+           pins:
+             description:
+               An array of strings. Each string contains the name of a pin.
+-            enum: [GPIO_A, I2S1_IN, I2S1_OUT, I2S_BCLK, I2S_WS, I2S_MCLK, TXD0,
+-                   RXD0, SPI_WP, SPI_HOLD, SPI_CLK, SPI_MOSI, SPI_MISO, SPI_CS,
+-                   I2C_SDA, I2C_SCL, I2S2_IN, I2S3_IN, I2S4_IN, I2S2_OUT,
+-                   I2S3_OUT, I2S4_OUT, GPIO_B, MDC, MDIO, G2_TXD0, G2_TXD1,
+-                   G2_TXD2, G2_TXD3, G2_TXEN, G2_TXC, G2_RXD0, G2_RXD1, G2_RXD2,
+-                   G2_RXD3, G2_RXDV, G2_RXC, NCEB, NWEB, NREB, NDL4, NDL5, NDL6,
+-                   NDL7, NRB, NCLE, NALE, NDL0, NDL1, NDL2, NDL3, MDI_TP_P0,
+-                   MDI_TN_P0, MDI_RP_P0, MDI_RN_P0, MDI_TP_P1, MDI_TN_P1,
+-                   MDI_RP_P1, MDI_RN_P1, MDI_RP_P2, MDI_RN_P2, MDI_TP_P2,
+-                   MDI_TN_P2, MDI_TP_P3, MDI_TN_P3, MDI_RP_P3, MDI_RN_P3,
+-                   MDI_RP_P4, MDI_RN_P4, MDI_TP_P4, MDI_TN_P4, PMIC_SCL,
+-                   PMIC_SDA, SPIC1_CLK, SPIC1_MOSI, SPIC1_MISO, SPIC1_CS,
+-                   GPIO_D, WATCHDOG, RTS3_N, CTS3_N, TXD3, RXD3, PERST0_N,
+-                   PERST1_N, WLED_N, EPHY_LED0_N, AUXIN0, AUXIN1, AUXIN2,
+-                   AUXIN3, TXD4, RXD4, RTS4_N, CST4_N, PWM1, PWM2, PWM3, PWM4,
+-                   PWM5, PWM6, PWM7, GPIO_E, TOP_5G_CLK, TOP_5G_DATA,
+-                   WF0_5G_HB0, WF0_5G_HB1, WF0_5G_HB2, WF0_5G_HB3, WF0_5G_HB4,
+-                   WF0_5G_HB5, WF0_5G_HB6, XO_REQ, TOP_RST_N, SYS_WATCHDOG,
+-                   EPHY_LED0_N_JTDO, EPHY_LED1_N_JTDI, EPHY_LED2_N_JTMS,
+-                   EPHY_LED3_N_JTCLK, EPHY_LED4_N_JTRST_N, WF2G_LED_N,
+-                   WF5G_LED_N, GPIO_9, GPIO_10, GPIO_11, GPIO_12, UART1_TXD,
+-                   UART1_RXD, UART1_CTS, UART1_RTS, UART2_TXD, UART2_RXD,
+-                   UART2_CTS, UART2_RTS, SMI_MDC, SMI_MDIO, PCIE_PERESET_N,
+-                   PWM_0, GPIO_0, GPIO_1, GPIO_2, GPIO_3, GPIO_4, GPIO_5,
+-                   GPIO_6, GPIO_7, GPIO_8, UART0_TXD, UART0_RXD, TOP_2G_CLK,
+-                   TOP_2G_DATA, WF0_2G_HB0, WF0_2G_HB1, WF0_2G_HB2, WF0_2G_HB3,
+-                   WF0_2G_HB4, WF0_2G_HB5, WF0_2G_HB6]
++            items:
++              enum: [GPIO_A, I2S1_IN, I2S1_OUT, I2S_BCLK, I2S_WS, I2S_MCLK, TXD0,
++                     RXD0, SPI_WP, SPI_HOLD, SPI_CLK, SPI_MOSI, SPI_MISO, SPI_CS,
++                     I2C_SDA, I2C_SCL, I2S2_IN, I2S3_IN, I2S4_IN, I2S2_OUT,
++                     I2S3_OUT, I2S4_OUT, GPIO_B, MDC, MDIO, G2_TXD0, G2_TXD1,
++                     G2_TXD2, G2_TXD3, G2_TXEN, G2_TXC, G2_RXD0, G2_RXD1, G2_RXD2,
++                     G2_RXD3, G2_RXDV, G2_RXC, NCEB, NWEB, NREB, NDL4, NDL5, NDL6,
++                     NDL7, NRB, NCLE, NALE, NDL0, NDL1, NDL2, NDL3, MDI_TP_P0,
++                     MDI_TN_P0, MDI_RP_P0, MDI_RN_P0, MDI_TP_P1, MDI_TN_P1,
++                     MDI_RP_P1, MDI_RN_P1, MDI_RP_P2, MDI_RN_P2, MDI_TP_P2,
++                     MDI_TN_P2, MDI_TP_P3, MDI_TN_P3, MDI_RP_P3, MDI_RN_P3,
++                     MDI_RP_P4, MDI_RN_P4, MDI_TP_P4, MDI_TN_P4, PMIC_SCL,
++                     PMIC_SDA, SPIC1_CLK, SPIC1_MOSI, SPIC1_MISO, SPIC1_CS,
++                     GPIO_D, WATCHDOG, RTS3_N, CTS3_N, TXD3, RXD3, PERST0_N,
++                     PERST1_N, WLED_N, EPHY_LED0_N, AUXIN0, AUXIN1, AUXIN2,
++                     AUXIN3, TXD4, RXD4, RTS4_N, CST4_N, PWM1, PWM2, PWM3, PWM4,
++                     PWM5, PWM6, PWM7, GPIO_E, TOP_5G_CLK, TOP_5G_DATA,
++                     WF0_5G_HB0, WF0_5G_HB1, WF0_5G_HB2, WF0_5G_HB3, WF0_5G_HB4,
++                     WF0_5G_HB5, WF0_5G_HB6, XO_REQ, TOP_RST_N, SYS_WATCHDOG,
++                     EPHY_LED0_N_JTDO, EPHY_LED1_N_JTDI, EPHY_LED2_N_JTMS,
++                     EPHY_LED3_N_JTCLK, EPHY_LED4_N_JTRST_N, WF2G_LED_N,
++                     WF5G_LED_N, GPIO_9, GPIO_10, GPIO_11, GPIO_12, UART1_TXD,
++                     UART1_RXD, UART1_CTS, UART1_RTS, UART2_TXD, UART2_RXD,
++                     UART2_CTS, UART2_RTS, SMI_MDC, SMI_MDIO, PCIE_PERESET_N,
++                     PWM_0, GPIO_0, GPIO_1, GPIO_2, GPIO_3, GPIO_4, GPIO_5,
++                     GPIO_6, GPIO_7, GPIO_8, UART0_TXD, UART0_RXD, TOP_2G_CLK,
++                     TOP_2G_DATA, WF0_2G_HB0, WF0_2G_HB1, WF0_2G_HB2, WF0_2G_HB3,
++                     WF0_2G_HB4, WF0_2G_HB5, WF0_2G_HB6]
+           bias-disable: true
+-- 
+2.43.0
+
diff --git a/queue-6.6/dt-bindings-spmi-hisilicon-hisi-spmi-controller-fix-.patch b/queue-6.6/dt-bindings-spmi-hisilicon-hisi-spmi-controller-fix-.patch
new file mode 100644 (file)
index 0000000..63598f9
--- /dev/null
@@ -0,0 +1,51 @@
+From 3d067de7036452a3627d1e9fe23b627402742079 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 14:07:39 -0700
+Subject: dt-bindings: spmi: hisilicon,hisi-spmi-controller: fix binding
+ references
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit c6c1b27f9a9a20ad2db663628fccaed72c6a0f1f ]
+
+Fix up the free text binding references which were not updated when
+moving the bindings out of staging and which had a leading current
+directory component, respectively.
+
+Fixes: 9bd9e0de1cf5 ("mfd: hi6421-spmi-pmic: move driver from staging")
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Link: https://lore.kernel.org/r/20231130173757.13011-2-johan+linaro@kernel.org
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Link: https://lore.kernel.org/r/20240507210809.3479953-3-sboyd@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../bindings/spmi/hisilicon,hisi-spmi-controller.yaml         | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
+index f882903769f95..eee7c8d4cf4a2 100644
+--- a/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
++++ b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
+@@ -14,7 +14,7 @@ description: |
+   It is a MIPI System Power Management (SPMI) controller.
+   The PMIC part is provided by
+-  ./Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml.
++  Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml.
+ allOf:
+   - $ref: spmi.yaml#
+@@ -48,7 +48,7 @@ patternProperties:
+       PMIC properties, which are specific to the used SPMI PMIC device(s).
+       When used in combination with HiSilicon 6421v600, the properties
+       are documented at
+-      drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
++      Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
+ unevaluatedProperties: false
+-- 
+2.43.0
+
diff --git a/queue-6.6/eventfs-create-eventfs_root_inode-to-store-dentry.patch b/queue-6.6/eventfs-create-eventfs_root_inode-to-store-dentry.patch
new file mode 100644 (file)
index 0000000..89c7df9
--- /dev/null
@@ -0,0 +1,195 @@
+From e8922e6166b250e9020a99dfa7e20ebd93ded2f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Feb 2024 10:34:52 -0500
+Subject: eventfs: Create eventfs_root_inode to store dentry
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit c3137ab6318d56370dd5541ebf027ddfc0c8557c ]
+
+Only the root "events" directory stores a dentry. There's no reason to
+hold a dentry pointer for every eventfs_inode as it is never set except
+for the root "events" eventfs_inode.
+
+Create a eventfs_root_inode structure that holds the events_dir dentry.
+The "events" eventfs_inode *is* special, let it have its own descriptor.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20240201161617.658992558@goodmis.org
+
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Al Viro <viro@ZenIV.linux.org.uk>
+Cc: Ajay Kaher <ajay.kaher@broadcom.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Stable-dep-of: b63db58e2fa5 ("eventfs/tracing: Add callback for release of an eventfs_inode")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/tracefs/event_inode.c | 65 +++++++++++++++++++++++++++++++++-------
+ fs/tracefs/internal.h    |  2 --
+ 2 files changed, 55 insertions(+), 12 deletions(-)
+
+diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
+index 47228de4c17af..6d3a11b0c606a 100644
+--- a/fs/tracefs/event_inode.c
++++ b/fs/tracefs/event_inode.c
+@@ -35,6 +35,17 @@ static DEFINE_MUTEX(eventfs_mutex);
+ /* Choose something "unique" ;-) */
+ #define EVENTFS_FILE_INODE_INO                0x12c4e37
++struct eventfs_root_inode {
++      struct eventfs_inode            ei;
++      struct dentry                   *events_dir;
++};
++
++static struct eventfs_root_inode *get_root_inode(struct eventfs_inode *ei)
++{
++      WARN_ON_ONCE(!ei->is_events);
++      return container_of(ei, struct eventfs_root_inode, ei);
++}
++
+ /* Just try to make something consistent and unique */
+ static int eventfs_dir_ino(struct eventfs_inode *ei)
+ {
+@@ -72,12 +83,18 @@ enum {
+ static void release_ei(struct kref *ref)
+ {
+       struct eventfs_inode *ei = container_of(ref, struct eventfs_inode, kref);
++      struct eventfs_root_inode *rei;
+       WARN_ON_ONCE(!ei->is_freed);
+       kfree(ei->entry_attrs);
+       kfree_const(ei->name);
+-      kfree_rcu(ei, rcu);
++      if (ei->is_events) {
++              rei = get_root_inode(ei);
++              kfree_rcu(rei, ei.rcu);
++      } else {
++              kfree_rcu(ei, rcu);
++      }
+ }
+ static inline void put_ei(struct eventfs_inode *ei)
+@@ -418,19 +435,43 @@ static struct dentry *lookup_dir_entry(struct dentry *dentry,
+       return NULL;
+ }
++static inline struct eventfs_inode *init_ei(struct eventfs_inode *ei, const char *name)
++{
++      ei->name = kstrdup_const(name, GFP_KERNEL);
++      if (!ei->name)
++              return NULL;
++      kref_init(&ei->kref);
++      return ei;
++}
++
+ static inline struct eventfs_inode *alloc_ei(const char *name)
+ {
+       struct eventfs_inode *ei = kzalloc(sizeof(*ei), GFP_KERNEL);
++      struct eventfs_inode *result;
+       if (!ei)
+               return NULL;
+-      ei->name = kstrdup_const(name, GFP_KERNEL);
+-      if (!ei->name) {
++      result = init_ei(ei, name);
++      if (!result)
+               kfree(ei);
++
++      return result;
++}
++
++static inline struct eventfs_inode *alloc_root_ei(const char *name)
++{
++      struct eventfs_root_inode *rei = kzalloc(sizeof(*rei), GFP_KERNEL);
++      struct eventfs_inode *ei;
++
++      if (!rei)
+               return NULL;
+-      }
+-      kref_init(&ei->kref);
++
++      rei->ei.is_events = 1;
++      ei = init_ei(&rei->ei, name);
++      if (!ei)
++              kfree(rei);
++
+       return ei;
+ }
+@@ -719,6 +760,7 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
+                                               int size, void *data)
+ {
+       struct dentry *dentry = tracefs_start_creating(name, parent);
++      struct eventfs_root_inode *rei;
+       struct eventfs_inode *ei;
+       struct tracefs_inode *ti;
+       struct inode *inode;
+@@ -731,7 +773,7 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
+       if (IS_ERR(dentry))
+               return ERR_CAST(dentry);
+-      ei = alloc_ei(name);
++      ei = alloc_root_ei(name);
+       if (!ei)
+               goto fail;
+@@ -740,10 +782,11 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
+               goto fail;
+       // Note: we have a ref to the dentry from tracefs_start_creating()
+-      ei->events_dir = dentry;
++      rei = get_root_inode(ei);
++      rei->events_dir = dentry;
++
+       ei->entries = entries;
+       ei->nr_entries = size;
+-      ei->is_events = 1;
+       ei->data = data;
+       /* Save the ownership of this directory */
+@@ -846,13 +889,15 @@ void eventfs_remove_dir(struct eventfs_inode *ei)
+  */
+ void eventfs_remove_events_dir(struct eventfs_inode *ei)
+ {
++      struct eventfs_root_inode *rei;
+       struct dentry *dentry;
+-      dentry = ei->events_dir;
++      rei = get_root_inode(ei);
++      dentry = rei->events_dir;
+       if (!dentry)
+               return;
+-      ei->events_dir = NULL;
++      rei->events_dir = NULL;
+       eventfs_remove_dir(ei);
+       /*
+diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h
+index b79ab2827b504..f704d8348357e 100644
+--- a/fs/tracefs/internal.h
++++ b/fs/tracefs/internal.h
+@@ -39,7 +39,6 @@ struct eventfs_attr {
+  * @children: link list into the child eventfs_inode
+  * @entries:  the array of entries representing the files in the directory
+  * @name:     the name of the directory to create
+- * @events_dir: the dentry of the events directory
+  * @entry_attrs: Saved mode and ownership of the @d_children
+  * @data:     The private data to pass to the callbacks
+  * @attr:     Saved mode and ownership of eventfs_inode itself
+@@ -57,7 +56,6 @@ struct eventfs_inode {
+       struct list_head                children;
+       const struct eventfs_entry      *entries;
+       const char                      *name;
+-      struct dentry                   *events_dir;
+       struct eventfs_attr             *entry_attrs;
+       void                            *data;
+       struct eventfs_attr             attr;
+-- 
+2.43.0
+
diff --git a/queue-6.6/eventfs-do-not-differentiate-the-toplevel-events-dir.patch b/queue-6.6/eventfs-do-not-differentiate-the-toplevel-events-dir.patch
new file mode 100644 (file)
index 0000000..f68695d
--- /dev/null
@@ -0,0 +1,150 @@
+From 50b530a0f377c2ddba3da0a33f7bd05bb4fdb658 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 May 2024 16:08:25 -0400
+Subject: eventfs: Do not differentiate the toplevel events directory
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit d53891d348ac3eceaf48f4732a1f4f5c0e0a55ce ]
+
+The toplevel events directory is really no different than the events
+directory of instances. Having the two be different caused
+inconsistencies and made it harder to fix the permissions bugs.
+
+Make all events directories act the same.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20240502200905.846448710@goodmis.org
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Fixes: 8186fff7ab649 ("tracefs/eventfs: Use root and instance inodes as default ownership")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/tracefs/event_inode.c | 29 ++++++++---------------------
+ fs/tracefs/internal.h    |  7 +++----
+ 2 files changed, 11 insertions(+), 25 deletions(-)
+
+diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
+index 56d1741fe0413..47228de4c17af 100644
+--- a/fs/tracefs/event_inode.c
++++ b/fs/tracefs/event_inode.c
+@@ -57,7 +57,6 @@ enum {
+       EVENTFS_SAVE_MODE       = BIT(16),
+       EVENTFS_SAVE_UID        = BIT(17),
+       EVENTFS_SAVE_GID        = BIT(18),
+-      EVENTFS_TOPLEVEL        = BIT(19),
+ };
+ #define EVENTFS_MODE_MASK     (EVENTFS_SAVE_MODE - 1)
+@@ -182,14 +181,10 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
+       return ret;
+ }
+-static void update_top_events_attr(struct eventfs_inode *ei, struct super_block *sb)
++static void update_events_attr(struct eventfs_inode *ei, struct super_block *sb)
+ {
+       struct inode *root;
+-      /* Only update if the "events" was on the top level */
+-      if (!ei || !(ei->attr.mode & EVENTFS_TOPLEVEL))
+-              return;
+-
+       /* Get the tracefs root inode. */
+       root = d_inode(sb->s_root);
+       ei->attr.uid = root->i_uid;
+@@ -202,10 +197,10 @@ static void set_top_events_ownership(struct inode *inode)
+       struct eventfs_inode *ei = ti->private;
+       /* The top events directory doesn't get automatically updated */
+-      if (!ei || !ei->is_events || !(ei->attr.mode & EVENTFS_TOPLEVEL))
++      if (!ei || !ei->is_events)
+               return;
+-      update_top_events_attr(ei, inode->i_sb);
++      update_events_attr(ei, inode->i_sb);
+       if (!(ei->attr.mode & EVENTFS_SAVE_UID))
+               inode->i_uid = ei->attr.uid;
+@@ -234,7 +229,7 @@ static int eventfs_permission(struct mnt_idmap *idmap,
+       return generic_permission(idmap, inode, mask);
+ }
+-static const struct inode_operations eventfs_root_dir_inode_operations = {
++static const struct inode_operations eventfs_dir_inode_operations = {
+       .lookup         = eventfs_root_lookup,
+       .setattr        = eventfs_set_attr,
+       .getattr        = eventfs_get_attr,
+@@ -302,7 +297,7 @@ static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
+               // Walk upwards until you find the events inode
+       } while (!ei->is_events);
+-      update_top_events_attr(ei, dentry->d_sb);
++      update_events_attr(ei, dentry->d_sb);
+       return ei;
+ }
+@@ -406,7 +401,7 @@ static struct dentry *lookup_dir_entry(struct dentry *dentry,
+       update_inode_attr(dentry, inode, &ei->attr,
+                         S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
+-      inode->i_op = &eventfs_root_dir_inode_operations;
++      inode->i_op = &eventfs_dir_inode_operations;
+       inode->i_fop = &eventfs_file_operations;
+       /* All directories will have the same inode number */
+@@ -755,14 +750,6 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
+       uid = d_inode(dentry->d_parent)->i_uid;
+       gid = d_inode(dentry->d_parent)->i_gid;
+-      /*
+-       * If the events directory is of the top instance, then parent
+-       * is NULL. Set the attr.mode to reflect this and its permissions will
+-       * default to the tracefs root dentry.
+-       */
+-      if (!parent)
+-              ei->attr.mode = EVENTFS_TOPLEVEL;
+-
+       /* This is used as the default ownership of the files and directories */
+       ei->attr.uid = uid;
+       ei->attr.gid = gid;
+@@ -771,13 +758,13 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
+       INIT_LIST_HEAD(&ei->list);
+       ti = get_tracefs(inode);
+-      ti->flags |= TRACEFS_EVENT_INODE | TRACEFS_EVENT_TOP_INODE;
++      ti->flags |= TRACEFS_EVENT_INODE;
+       ti->private = ei;
+       inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
+       inode->i_uid = uid;
+       inode->i_gid = gid;
+-      inode->i_op = &eventfs_root_dir_inode_operations;
++      inode->i_op = &eventfs_dir_inode_operations;
+       inode->i_fop = &eventfs_file_operations;
+       dentry->d_fsdata = get_ei(ei);
+diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h
+index 824cbe83679cc..b79ab2827b504 100644
+--- a/fs/tracefs/internal.h
++++ b/fs/tracefs/internal.h
+@@ -4,10 +4,9 @@
+ enum {
+       TRACEFS_EVENT_INODE             = BIT(1),
+-      TRACEFS_EVENT_TOP_INODE         = BIT(2),
+-      TRACEFS_GID_PERM_SET            = BIT(3),
+-      TRACEFS_UID_PERM_SET            = BIT(4),
+-      TRACEFS_INSTANCE_INODE          = BIT(5),
++      TRACEFS_GID_PERM_SET            = BIT(2),
++      TRACEFS_UID_PERM_SET            = BIT(3),
++      TRACEFS_INSTANCE_INODE          = BIT(4),
+ };
+ struct tracefs_inode {
+-- 
+2.43.0
+
diff --git a/queue-6.6/eventfs-free-all-of-the-eventfs_inode-after-rcu.patch b/queue-6.6/eventfs-free-all-of-the-eventfs_inode-after-rcu.patch
new file mode 100644 (file)
index 0000000..c451ecc
--- /dev/null
@@ -0,0 +1,84 @@
+From bf38d7f5807027bef3401ff9dd0c352a713940a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 May 2024 16:08:22 -0400
+Subject: eventfs: Free all of the eventfs_inode after RCU
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit ee4e0379475e4fe723986ae96293e465014fa8d9 ]
+
+The freeing of eventfs_inode via a kfree_rcu() callback. But the content
+of the eventfs_inode was being freed after the last kref. This is
+dangerous, as changes are being made that can access the content of an
+eventfs_inode from an RCU loop.
+
+Instead of using kfree_rcu() use call_rcu() that calls a function to do
+all the freeing of the eventfs_inode after a RCU grace period has expired.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20240502200905.370261163@goodmis.org
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Fixes: 43aa6f97c2d03 ("eventfs: Get rid of dentry pointers without refcounts")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/tracefs/event_inode.c | 25 ++++++++++++++++---------
+ 1 file changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
+index a598fec065684..fd111e10f04e4 100644
+--- a/fs/tracefs/event_inode.c
++++ b/fs/tracefs/event_inode.c
+@@ -72,6 +72,21 @@ enum {
+ #define EVENTFS_MODE_MASK     (EVENTFS_SAVE_MODE - 1)
++static void free_ei_rcu(struct rcu_head *rcu)
++{
++      struct eventfs_inode *ei = container_of(rcu, struct eventfs_inode, rcu);
++      struct eventfs_root_inode *rei;
++
++      kfree(ei->entry_attrs);
++      kfree_const(ei->name);
++      if (ei->is_events) {
++              rei = get_root_inode(ei);
++              kfree(rei);
++      } else {
++              kfree(ei);
++      }
++}
++
+ /*
+  * eventfs_inode reference count management.
+  *
+@@ -84,7 +99,6 @@ static void release_ei(struct kref *ref)
+ {
+       struct eventfs_inode *ei = container_of(ref, struct eventfs_inode, kref);
+       const struct eventfs_entry *entry;
+-      struct eventfs_root_inode *rei;
+       WARN_ON_ONCE(!ei->is_freed);
+@@ -94,14 +108,7 @@ static void release_ei(struct kref *ref)
+                       entry->release(entry->name, ei->data);
+       }
+-      kfree(ei->entry_attrs);
+-      kfree_const(ei->name);
+-      if (ei->is_events) {
+-              rei = get_root_inode(ei);
+-              kfree_rcu(rei, ei.rcu);
+-      } else {
+-              kfree_rcu(ei, rcu);
+-      }
++      call_rcu(&ei->rcu, free_ei_rcu);
+ }
+ static inline void put_ei(struct eventfs_inode *ei)
+-- 
+2.43.0
+
diff --git a/queue-6.6/eventfs-have-events-directory-get-permissions-from-i.patch b/queue-6.6/eventfs-have-events-directory-get-permissions-from-i.patch
new file mode 100644 (file)
index 0000000..449417a
--- /dev/null
@@ -0,0 +1,133 @@
+From d9e4cb4bc552444ea539694561eb74a2a954f485 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 May 2024 16:08:27 -0400
+Subject: eventfs: Have "events" directory get permissions from its parent
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit d57cf30c4c07837799edec949102b0adf58bae79 ]
+
+The events directory gets its permissions from the root inode. But this
+can cause an inconsistency if the instances directory changes its
+permissions, as the permissions of the created directories under it should
+inherit the permissions of the instances directory when directories under
+it are created.
+
+Currently the behavior is:
+
+ # cd /sys/kernel/tracing
+ # chgrp 1002 instances
+ # mkdir instances/foo
+ # ls -l instances/foo
+[..]
+ -r--r-----  1 root lkp  0 May  1 18:55 buffer_total_size_kb
+ -rw-r-----  1 root lkp  0 May  1 18:55 current_tracer
+ -rw-r-----  1 root lkp  0 May  1 18:55 error_log
+ drwxr-xr-x  1 root root 0 May  1 18:55 events
+ --w-------  1 root lkp  0 May  1 18:55 free_buffer
+ drwxr-x---  2 root lkp  0 May  1 18:55 options
+ drwxr-x--- 10 root lkp  0 May  1 18:55 per_cpu
+ -rw-r-----  1 root lkp  0 May  1 18:55 set_event
+
+All the files and directories under "foo" has the "lkp" group except the
+"events" directory. That's because its getting its default value from the
+mount point instead of its parent.
+
+Have the "events" directory make its default value based on its parent's
+permissions. That now gives:
+
+ # ls -l instances/foo
+[..]
+ -rw-r-----  1 root lkp 0 May  1 21:16 buffer_subbuf_size_kb
+ -r--r-----  1 root lkp 0 May  1 21:16 buffer_total_size_kb
+ -rw-r-----  1 root lkp 0 May  1 21:16 current_tracer
+ -rw-r-----  1 root lkp 0 May  1 21:16 error_log
+ drwxr-xr-x  1 root lkp 0 May  1 21:16 events
+ --w-------  1 root lkp 0 May  1 21:16 free_buffer
+ drwxr-x---  2 root lkp 0 May  1 21:16 options
+ drwxr-x--- 10 root lkp 0 May  1 21:16 per_cpu
+ -rw-r-----  1 root lkp 0 May  1 21:16 set_event
+
+Link: https://lore.kernel.org/linux-trace-kernel/20240502200906.161887248@goodmis.org
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Fixes: 8186fff7ab649 ("tracefs/eventfs: Use root and instance inodes as default ownership")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/tracefs/event_inode.c | 30 ++++++++++++++++++++++++------
+ 1 file changed, 24 insertions(+), 6 deletions(-)
+
+diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
+index fd111e10f04e4..3b785f4ca95e4 100644
+--- a/fs/tracefs/event_inode.c
++++ b/fs/tracefs/event_inode.c
+@@ -37,6 +37,7 @@ static DEFINE_MUTEX(eventfs_mutex);
+ struct eventfs_root_inode {
+       struct eventfs_inode            ei;
++      struct inode                    *parent_inode;
+       struct dentry                   *events_dir;
+ };
+@@ -226,12 +227,23 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
+ static void update_events_attr(struct eventfs_inode *ei, struct super_block *sb)
+ {
+-      struct inode *root;
++      struct eventfs_root_inode *rei;
++      struct inode *parent;
++
++      rei = get_root_inode(ei);
++
++      /* Use the parent inode permissions unless root set its permissions */
++      parent = rei->parent_inode;
+-      /* Get the tracefs root inode. */
+-      root = d_inode(sb->s_root);
+-      ei->attr.uid = root->i_uid;
+-      ei->attr.gid = root->i_gid;
++      if (rei->ei.attr.mode & EVENTFS_SAVE_UID)
++              ei->attr.uid = rei->ei.attr.uid;
++      else
++              ei->attr.uid = parent->i_uid;
++
++      if (rei->ei.attr.mode & EVENTFS_SAVE_GID)
++              ei->attr.gid = rei->ei.attr.gid;
++      else
++              ei->attr.gid = parent->i_gid;
+ }
+ static void set_top_events_ownership(struct inode *inode)
+@@ -810,6 +822,7 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
+       // Note: we have a ref to the dentry from tracefs_start_creating()
+       rei = get_root_inode(ei);
+       rei->events_dir = dentry;
++      rei->parent_inode = d_inode(dentry->d_sb->s_root);
+       ei->entries = entries;
+       ei->nr_entries = size;
+@@ -819,10 +832,15 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
+       uid = d_inode(dentry->d_parent)->i_uid;
+       gid = d_inode(dentry->d_parent)->i_gid;
+-      /* This is used as the default ownership of the files and directories */
+       ei->attr.uid = uid;
+       ei->attr.gid = gid;
++      /*
++       * When the "events" directory is created, it takes on the
++       * permissions of its parent. But can be reset on remount.
++       */
++      ei->attr.mode |= EVENTFS_SAVE_UID | EVENTFS_SAVE_GID;
++
+       INIT_LIST_HEAD(&ei->children);
+       INIT_LIST_HEAD(&ei->list);
+-- 
+2.43.0
+
diff --git a/queue-6.6/eventfs-tracing-add-callback-for-release-of-an-event.patch b/queue-6.6/eventfs-tracing-add-callback-for-release-of-an-event.patch
new file mode 100644 (file)
index 0000000..843cb0d
--- /dev/null
@@ -0,0 +1,199 @@
+From 64ff8ab11760417874c0519e144cb7a681af3c63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 May 2024 09:03:15 -0400
+Subject: eventfs/tracing: Add callback for release of an eventfs_inode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit b63db58e2fa5d6963db9c45df88e60060f0ff35f ]
+
+Synthetic events create and destroy tracefs files when they are created
+and removed. The tracing subsystem has its own file descriptor
+representing the state of the events attached to the tracefs files.
+There's a race between the eventfs files and this file descriptor of the
+tracing system where the following can cause an issue:
+
+With two scripts 'A' and 'B' doing:
+
+  Script 'A':
+    echo "hello int aaa" > /sys/kernel/tracing/synthetic_events
+    while :
+    do
+      echo 0 > /sys/kernel/tracing/events/synthetic/hello/enable
+    done
+
+  Script 'B':
+    echo > /sys/kernel/tracing/synthetic_events
+
+Script 'A' creates a synthetic event "hello" and then just writes zero
+into its enable file.
+
+Script 'B' removes all synthetic events (including the newly created
+"hello" event).
+
+What happens is that the opening of the "enable" file has:
+
+ {
+       struct trace_event_file *file = inode->i_private;
+       int ret;
+
+       ret = tracing_check_open_get_tr(file->tr);
+ [..]
+
+But deleting the events frees the "file" descriptor, and a "use after
+free" happens with the dereference at "file->tr".
+
+The file descriptor does have a reference counter, but there needs to be a
+way to decrement it from the eventfs when the eventfs_inode is removed
+that represents this file descriptor.
+
+Add an optional "release" callback to the eventfs_entry array structure,
+that gets called when the eventfs file is about to be removed. This allows
+for the creating on the eventfs file to increment the tracing file
+descriptor ref counter. When the eventfs file is deleted, it can call the
+release function that will call the put function for the tracing file
+descriptor.
+
+This will protect the tracing file from being freed while a eventfs file
+that references it is being opened.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20240426073410.17154-1-Tze-nan.Wu@mediatek.com/
+Link: https://lore.kernel.org/linux-trace-kernel/20240502090315.448cba46@gandalf.local.home
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Fixes: 5790b1fb3d672 ("eventfs: Remove eventfs_file and just use eventfs_inode")
+Reported-by: Tze-nan wu <Tze-nan.Wu@mediatek.com>
+Tested-by: Tze-nan Wu (吳澤南) <Tze-nan.Wu@mediatek.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/tracefs/event_inode.c    | 23 +++++++++++++++++++++--
+ include/linux/tracefs.h     |  3 +++
+ kernel/trace/trace_events.c | 12 ++++++++++++
+ 3 files changed, 36 insertions(+), 2 deletions(-)
+
+diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
+index 6d3a11b0c606a..a598fec065684 100644
+--- a/fs/tracefs/event_inode.c
++++ b/fs/tracefs/event_inode.c
+@@ -83,10 +83,17 @@ enum {
+ static void release_ei(struct kref *ref)
+ {
+       struct eventfs_inode *ei = container_of(ref, struct eventfs_inode, kref);
++      const struct eventfs_entry *entry;
+       struct eventfs_root_inode *rei;
+       WARN_ON_ONCE(!ei->is_freed);
++      for (int i = 0; i < ei->nr_entries; i++) {
++              entry = &ei->entries[i];
++              if (entry->release)
++                      entry->release(entry->name, ei->data);
++      }
++
+       kfree(ei->entry_attrs);
+       kfree_const(ei->name);
+       if (ei->is_events) {
+@@ -111,6 +118,18 @@ static inline void free_ei(struct eventfs_inode *ei)
+       }
+ }
++/*
++ * Called when creation of an ei fails, do not call release() functions.
++ */
++static inline void cleanup_ei(struct eventfs_inode *ei)
++{
++      if (ei) {
++              /* Set nr_entries to 0 to prevent release() function being called */
++              ei->nr_entries = 0;
++              free_ei(ei);
++      }
++}
++
+ static inline struct eventfs_inode *get_ei(struct eventfs_inode *ei)
+ {
+       if (ei)
+@@ -737,7 +756,7 @@ struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode
+       /* Was the parent freed? */
+       if (list_empty(&ei->list)) {
+-              free_ei(ei);
++              cleanup_ei(ei);
+               ei = NULL;
+       }
+       return ei;
+@@ -830,7 +849,7 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
+       return ei;
+  fail:
+-      free_ei(ei);
++      cleanup_ei(ei);
+       tracefs_failed_creating(dentry);
+       return ERR_PTR(-ENOMEM);
+ }
+diff --git a/include/linux/tracefs.h b/include/linux/tracefs.h
+index 7a5fe17b6bf9c..d03f746587167 100644
+--- a/include/linux/tracefs.h
++++ b/include/linux/tracefs.h
+@@ -62,6 +62,8 @@ struct eventfs_file;
+ typedef int (*eventfs_callback)(const char *name, umode_t *mode, void **data,
+                               const struct file_operations **fops);
++typedef void (*eventfs_release)(const char *name, void *data);
++
+ /**
+  * struct eventfs_entry - dynamically created eventfs file call back handler
+  * @name:     Then name of the dynamic file in an eventfs directory
+@@ -72,6 +74,7 @@ typedef int (*eventfs_callback)(const char *name, umode_t *mode, void **data,
+ struct eventfs_entry {
+       const char                      *name;
+       eventfs_callback                callback;
++      eventfs_release                 release;
+ };
+ struct eventfs_inode;
+diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
+index 99f1308122866..2ae0f2807438a 100644
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -2518,6 +2518,14 @@ static int event_callback(const char *name, umode_t *mode, void **data,
+       return 0;
+ }
++/* The file is incremented on creation and freeing the enable file decrements it */
++static void event_release(const char *name, void *data)
++{
++      struct trace_event_file *file = data;
++
++      event_file_put(file);
++}
++
+ static int
+ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
+ {
+@@ -2532,6 +2540,7 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
+               {
+                       .name           = "enable",
+                       .callback       = event_callback,
++                      .release        = event_release,
+               },
+               {
+                       .name           = "filter",
+@@ -2600,6 +2609,9 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
+               return ret;
+       }
++      /* Gets decremented on freeing of the "enable" file */
++      event_file_get(file);
++
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/extcon-max8997-select-irq_domain-instead-of-dependin.patch b/queue-6.6/extcon-max8997-select-irq_domain-instead-of-dependin.patch
new file mode 100644 (file)
index 0000000..97a1e7f
--- /dev/null
@@ -0,0 +1,47 @@
+From 40e2dbecc624250de675f25ecfb6d09181ad2f5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Feb 2024 22:00:28 -0800
+Subject: extcon: max8997: select IRQ_DOMAIN instead of depending on it
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit b1781d0a1458070d40134e4f3412ec9d70099bec ]
+
+IRQ_DOMAIN is a hidden (not user visible) symbol. Users cannot set
+it directly thru "make *config", so drivers should select it instead
+of depending on it if they need it.
+Relying on it being set for a dependency is risky.
+
+Consistently using "select" or "depends on" can also help reduce
+Kconfig circular dependency issues.
+
+Therefore, change EXTCON_MAX8997's use of "depends on" for
+IRQ_DOMAIN to "select".
+
+Link: https://lore.kernel.org/lkml/20240213060028.9744-1-rdunlap@infradead.org/
+Fixes: dca1a71e4108 ("extcon: Add support irq domain for MAX8997 muic")
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/extcon/Kconfig | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
+index 8de9023c2a387..cf472e44c5ff9 100644
+--- a/drivers/extcon/Kconfig
++++ b/drivers/extcon/Kconfig
+@@ -116,7 +116,8 @@ config EXTCON_MAX77843
+ config EXTCON_MAX8997
+       tristate "Maxim MAX8997 EXTCON Support"
+-      depends on MFD_MAX8997 && IRQ_DOMAIN
++      depends on MFD_MAX8997
++      select IRQ_DOMAIN
+       help
+         If you say yes here you get support for the MUIC device of
+         Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-clean-up-errors-in-segment.h.patch b/queue-6.6/f2fs-clean-up-errors-in-segment.h.patch
new file mode 100644 (file)
index 0000000..2c4ab46
--- /dev/null
@@ -0,0 +1,43 @@
+From 54203fa23517a6a6ca298cba950126b42ecc3018 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Oct 2023 14:45:42 +0800
+Subject: f2fs: Clean up errors in segment.h
+
+From: KaiLong Wang <wangkailong@jari.cn>
+
+[ Upstream commit 37768434b7a7d00ac5a08b2c1d31aa7aaa0846a0 ]
+
+Fix the following errors reported by checkpatch:
+
+ERROR: spaces required around that ':' (ctx:VxW)
+
+Signed-off-by: KaiLong Wang <wangkailong@jari.cn>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/segment.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
+index 20580ebd24138..c77a562831493 100644
+--- a/fs/f2fs/segment.h
++++ b/fs/f2fs/segment.h
+@@ -108,11 +108,11 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
+       ((sbi)->segs_per_sec - ((sbi)->unusable_blocks_per_sec >>\
+       (sbi)->log_blocks_per_seg))
+ #define GET_SEC_FROM_SEG(sbi, segno)                          \
+-      (((segno) == -1) ? -1: (segno) / (sbi)->segs_per_sec)
++      (((segno) == -1) ? -1 : (segno) / (sbi)->segs_per_sec)
+ #define GET_SEG_FROM_SEC(sbi, secno)                          \
+       ((secno) * (sbi)->segs_per_sec)
+ #define GET_ZONE_FROM_SEC(sbi, secno)                         \
+-      (((secno) == -1) ? -1: (secno) / (sbi)->secs_per_zone)
++      (((secno) == -1) ? -1 : (secno) / (sbi)->secs_per_zone)
+ #define GET_ZONE_FROM_SEG(sbi, segno)                         \
+       GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno))
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-compress-don-t-allow-unaligned-truncation-on-re.patch b/queue-6.6/f2fs-compress-don-t-allow-unaligned-truncation-on-re.patch
new file mode 100644 (file)
index 0000000..267873b
--- /dev/null
@@ -0,0 +1,65 @@
+From bcd7980ca7cfe5489347b65936ded080d6db5b0e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 11:33:39 +0800
+Subject: f2fs: compress: don't allow unaligned truncation on released compress
+ inode
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 29ed2b5dd521ce7c5d8466cd70bf0cc9d07afeee ]
+
+f2fs image may be corrupted after below testcase:
+- mkfs.f2fs -O extra_attr,compression -f /dev/vdb
+- mount /dev/vdb /mnt/f2fs
+- touch /mnt/f2fs/file
+- f2fs_io setflags compression /mnt/f2fs/file
+- dd if=/dev/zero of=/mnt/f2fs/file bs=4k count=4
+- f2fs_io release_cblocks /mnt/f2fs/file
+- truncate -s 8192 /mnt/f2fs/file
+- umount /mnt/f2fs
+- fsck.f2fs /dev/vdb
+
+[ASSERT] (fsck_chk_inode_blk:1256)  --> ino: 0x5 has i_blocks: 0x00000002, but has 0x3 blocks
+[FSCK] valid_block_count matching with CP             [Fail] [0x4, 0x5]
+[FSCK] other corrupted bugs                           [Fail]
+
+The reason is: partial truncation assume compressed inode has reserved
+blocks, after partial truncation, valid block count may change w/o
+.i_blocks and .total_valid_block_count update, result in corruption.
+
+This patch only allow cluster size aligned truncation on released
+compress inode for fixing.
+
+Fixes: c61404153eb6 ("f2fs: introduce FI_COMPRESS_RELEASED instead of using IMMUTABLE bit")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/file.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index ac592059c68be..154c55c1a0f47 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -929,9 +929,14 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                                 ATTR_GID | ATTR_TIMES_SET))))
+               return -EPERM;
+-      if ((attr->ia_valid & ATTR_SIZE) &&
+-              !f2fs_is_compress_backend_ready(inode))
+-              return -EOPNOTSUPP;
++      if ((attr->ia_valid & ATTR_SIZE)) {
++              if (!f2fs_is_compress_backend_ready(inode))
++                      return -EOPNOTSUPP;
++              if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) &&
++                      !IS_ALIGNED(attr->ia_size,
++                      F2FS_BLK_TO_BYTES(F2FS_I(inode)->i_cluster_size)))
++                      return -EINVAL;
++      }
+       err = setattr_prepare(idmap, dentry, attr);
+       if (err)
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-compress-fix-error-path-of-inc_valid_block_coun.patch b/queue-6.6/f2fs-compress-fix-error-path-of-inc_valid_block_coun.patch
new file mode 100644 (file)
index 0000000..94df371
--- /dev/null
@@ -0,0 +1,71 @@
+From 96c3fba9d7993cbc866c99258a8d77fe8755cffe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 May 2024 18:41:37 +0800
+Subject: f2fs: compress: fix error path of inc_valid_block_count()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 043c832371cd9023fbd725138ddc6c7f288dc469 ]
+
+If inc_valid_block_count() can not allocate all requested blocks,
+it needs to release block count in .total_valid_block_count and
+resevation blocks in inode.
+
+Fixes: 54607494875e ("f2fs: compress: fix to avoid inconsistence bewteen i_blocks and dnode")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/f2fs.h | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index c90f6f9855c8e..f1fbfa7fb279e 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -2296,7 +2296,7 @@ static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool);
+ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
+                                struct inode *inode, blkcnt_t *count, bool partial)
+ {
+-      blkcnt_t diff = 0, release = 0;
++      long long diff = 0, release = 0;
+       block_t avail_user_block_count;
+       int ret;
+@@ -2316,26 +2316,27 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
+       percpu_counter_add(&sbi->alloc_valid_block_count, (*count));
+       spin_lock(&sbi->stat_lock);
+-      sbi->total_valid_block_count += (block_t)(*count);
+-      avail_user_block_count = get_available_block_count(sbi, inode, true);
+-      if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
++      avail_user_block_count = get_available_block_count(sbi, inode, true);
++      diff = (long long)sbi->total_valid_block_count + *count -
++                                              avail_user_block_count;
++      if (unlikely(diff > 0)) {
+               if (!partial) {
+                       spin_unlock(&sbi->stat_lock);
++                      release = *count;
+                       goto enospc;
+               }
+-
+-              diff = sbi->total_valid_block_count - avail_user_block_count;
+               if (diff > *count)
+                       diff = *count;
+               *count -= diff;
+               release = diff;
+-              sbi->total_valid_block_count -= diff;
+               if (!*count) {
+                       spin_unlock(&sbi->stat_lock);
+                       goto enospc;
+               }
+       }
++      sbi->total_valid_block_count += (block_t)(*count);
++
+       spin_unlock(&sbi->stat_lock);
+       if (unlikely(release)) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-compress-fix-to-cover-reserve-release-_compress.patch b/queue-6.6/f2fs-compress-fix-to-cover-reserve-release-_compress.patch
new file mode 100644 (file)
index 0000000..80363b9
--- /dev/null
@@ -0,0 +1,75 @@
+From a5e5af37ced2348a0f75e1ec44bdea87d6a9931e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 May 2024 18:41:39 +0800
+Subject: f2fs: compress: fix to cover {reserve,release}_compress_blocks() w/
+ cp_rwsem lock
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 0a4ed2d97cb6d044196cc3e726b6699222b41019 ]
+
+It needs to cover {reserve,release}_compress_blocks() w/ cp_rwsem lock
+to avoid racing with checkpoint, otherwise, filesystem metadata including
+blkaddr in dnode, inode fields and .total_valid_block_count may be
+corrupted after SPO case.
+
+Fixes: ef8d563f184e ("f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS")
+Fixes: c75488fb4d82 ("f2fs: introduce F2FS_IOC_RESERVE_COMPRESS_BLOCKS")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/file.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index fdd9825e57483..ac592059c68be 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -3547,9 +3547,12 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
+               struct dnode_of_data dn;
+               pgoff_t end_offset, count;
++              f2fs_lock_op(sbi);
++
+               set_new_dnode(&dn, inode, NULL, NULL, 0);
+               ret = f2fs_get_dnode_of_data(&dn, page_idx, LOOKUP_NODE);
+               if (ret) {
++                      f2fs_unlock_op(sbi);
+                       if (ret == -ENOENT) {
+                               page_idx = f2fs_get_next_page_offset(&dn,
+                                                               page_idx);
+@@ -3567,6 +3570,8 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
+               f2fs_put_dnode(&dn);
++              f2fs_unlock_op(sbi);
++
+               if (ret < 0)
+                       break;
+@@ -3719,9 +3724,12 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
+               struct dnode_of_data dn;
+               pgoff_t end_offset, count;
++              f2fs_lock_op(sbi);
++
+               set_new_dnode(&dn, inode, NULL, NULL, 0);
+               ret = f2fs_get_dnode_of_data(&dn, page_idx, LOOKUP_NODE);
+               if (ret) {
++                      f2fs_unlock_op(sbi);
+                       if (ret == -ENOENT) {
+                               page_idx = f2fs_get_next_page_offset(&dn,
+                                                               page_idx);
+@@ -3739,6 +3747,8 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
+               f2fs_put_dnode(&dn);
++              f2fs_unlock_op(sbi);
++
+               if (ret < 0)
+                       break;
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch b/queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch
new file mode 100644 (file)
index 0000000..854b3be
--- /dev/null
@@ -0,0 +1,70 @@
+From ce6baf48fe8951884b1a600116e2d16315eb39b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 7 Apr 2024 15:26:03 +0800
+Subject: f2fs: compress: fix to relocate check condition in
+ f2fs_{release,reserve}_compress_blocks()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 7c5dffb3d90c5921b91981cc663e02757d90526e ]
+
+Compress flag should be checked after inode lock held to avoid
+racing w/ f2fs_setflags_common(), fix it.
+
+Fixes: 4c8ff7095bef ("f2fs: support data compression")
+Reported-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
+Closes: https://lore.kernel.org/linux-f2fs-devel/CAHJ8P3LdZXLc2rqeYjvymgYHr2+YLuJ0sLG9DdsJZmwO7deuhw@mail.gmail.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/file.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index 7f631a617ee99..0350f36d043d6 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -3488,9 +3488,6 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
+       if (!f2fs_sb_has_compression(sbi))
+               return -EOPNOTSUPP;
+-      if (!f2fs_compressed_file(inode))
+-              return -EINVAL;
+-
+       if (f2fs_readonly(sbi->sb))
+               return -EROFS;
+@@ -3509,7 +3506,8 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
+               goto out;
+       }
+-      if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
++      if (!f2fs_compressed_file(inode) ||
++              is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
+               ret = -EINVAL;
+               goto out;
+       }
+@@ -3672,9 +3670,6 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
+       if (!f2fs_sb_has_compression(sbi))
+               return -EOPNOTSUPP;
+-      if (!f2fs_compressed_file(inode))
+-              return -EINVAL;
+-
+       if (f2fs_readonly(sbi->sb))
+               return -EROFS;
+@@ -3686,7 +3681,8 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
+       inode_lock(inode);
+-      if (!is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
++      if (!f2fs_compressed_file(inode) ||
++              !is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
+               ret = -EINVAL;
+               goto unlock_inode;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch-466 b/queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch-466
new file mode 100644 (file)
index 0000000..d2c5219
--- /dev/null
@@ -0,0 +1,70 @@
+From ffcaaece3b29fd183a50d8b38b0c564a1b92f92b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 7 Apr 2024 15:26:04 +0800
+Subject: f2fs: compress: fix to relocate check condition in
+ f2fs_ioc_{,de}compress_file()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit bd9ae4ae9e585061acfd4a169f2321706f900246 ]
+
+Compress flag should be checked after inode lock held to avoid
+racing w/ f2fs_setflags_common() , fix it.
+
+Fixes: 5fdb322ff2c2 ("f2fs: add F2FS_IOC_DECOMPRESS_FILE and F2FS_IOC_COMPRESS_FILE")
+Reported-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
+Closes: https://lore.kernel.org/linux-f2fs-devel/CAHJ8P3LdZXLc2rqeYjvymgYHr2+YLuJ0sLG9DdsJZmwO7deuhw@mail.gmail.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/file.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index 0350f36d043d6..420939ca36422 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -4086,9 +4086,6 @@ static int f2fs_ioc_decompress_file(struct file *filp)
+       if (!(filp->f_mode & FMODE_WRITE))
+               return -EBADF;
+-      if (!f2fs_compressed_file(inode))
+-              return -EINVAL;
+-
+       f2fs_balance_fs(sbi, true);
+       file_start_write(filp);
+@@ -4099,7 +4096,8 @@ static int f2fs_ioc_decompress_file(struct file *filp)
+               goto out;
+       }
+-      if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
++      if (!f2fs_compressed_file(inode) ||
++              is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
+               ret = -EINVAL;
+               goto out;
+       }
+@@ -4165,9 +4163,6 @@ static int f2fs_ioc_compress_file(struct file *filp)
+       if (!(filp->f_mode & FMODE_WRITE))
+               return -EBADF;
+-      if (!f2fs_compressed_file(inode))
+-              return -EINVAL;
+-
+       f2fs_balance_fs(sbi, true);
+       file_start_write(filp);
+@@ -4178,7 +4173,8 @@ static int f2fs_ioc_compress_file(struct file *filp)
+               goto out;
+       }
+-      if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
++      if (!f2fs_compressed_file(inode) ||
++              is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
+               ret = -EINVAL;
+               goto out;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-compress-fix-to-update-i_compr_blocks-correctly.patch b/queue-6.6/f2fs-compress-fix-to-update-i_compr_blocks-correctly.patch
new file mode 100644 (file)
index 0000000..49f0a5e
--- /dev/null
@@ -0,0 +1,82 @@
+From 9269a0dc033b512ea0ac028c2ae6f580f7ecaacc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 May 2024 18:41:36 +0800
+Subject: f2fs: compress: fix to update i_compr_blocks correctly
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 186e7d71534df4589405925caca5597af7626c12 ]
+
+Previously, we account reserved blocks and compressed blocks into
+@compr_blocks, then, f2fs_i_compr_blocks_update(,compr_blocks) will
+update i_compr_blocks incorrectly, fix it.
+
+Meanwhile, for the case all blocks in cluster were reserved, fix to
+update dn->ofs_in_node correctly.
+
+Fixes: eb8fbaa53374 ("f2fs: compress: fix to check unreleased compressed cluster")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/file.c | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index 20dc11b58bb69..206cb01875c48 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -3622,7 +3622,8 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
+       while (count) {
+               int compr_blocks = 0;
+-              blkcnt_t reserved;
++              blkcnt_t reserved = 0;
++              blkcnt_t to_reserved;
+               int ret;
+               for (i = 0; i < cluster_size; i++) {
+@@ -3642,20 +3643,26 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
+                        * fails in release_compress_blocks(), so NEW_ADDR
+                        * is a possible case.
+                        */
+-                      if (blkaddr == NEW_ADDR ||
+-                              __is_valid_data_blkaddr(blkaddr)) {
++                      if (blkaddr == NEW_ADDR) {
++                              reserved++;
++                              continue;
++                      }
++                      if (__is_valid_data_blkaddr(blkaddr)) {
+                               compr_blocks++;
+                               continue;
+                       }
+               }
+-              reserved = cluster_size - compr_blocks;
++              to_reserved = cluster_size - compr_blocks - reserved;
+               /* for the case all blocks in cluster were reserved */
+-              if (reserved == 1)
++              if (to_reserved == 1) {
++                      dn->ofs_in_node += cluster_size;
+                       goto next;
++              }
+-              ret = inc_valid_block_count(sbi, dn->inode, &reserved, false);
++              ret = inc_valid_block_count(sbi, dn->inode,
++                                              &to_reserved, false);
+               if (unlikely(ret))
+                       return ret;
+@@ -3666,7 +3673,7 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
+               f2fs_i_compr_blocks_update(dn->inode, compr_blocks, true);
+-              *reserved_blocks += reserved;
++              *reserved_blocks += to_reserved;
+ next:
+               count -= cluster_size;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-deprecate-io_bits.patch b/queue-6.6/f2fs-deprecate-io_bits.patch
new file mode 100644 (file)
index 0000000..5a818de
--- /dev/null
@@ -0,0 +1,556 @@
+From 70f45ea8dd75472b68ba8a0a76fc35f918bfc193 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Feb 2024 11:21:00 -0800
+Subject: f2fs: deprecate io_bits
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+[ Upstream commit 87161a2b0aed9e9b614bbf6fe8697ad560ceb0cb ]
+
+Let's deprecate an unused io_bits feature to save CPU cycles and memory.
+
+Reviewed-by: Daeho Jeong <daehojeong@google.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 043c832371cd ("f2fs: compress: fix error path of inc_valid_block_count()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/filesystems/f2fs.rst |  2 -
+ fs/f2fs/data.c                     | 73 +------------------------
+ fs/f2fs/f2fs.h                     | 25 ++-------
+ fs/f2fs/file.c                     |  2 -
+ fs/f2fs/gc.c                       | 10 +---
+ fs/f2fs/segment.c                  |  9 +--
+ fs/f2fs/super.c                    | 88 +-----------------------------
+ include/linux/f2fs_fs.h            |  6 --
+ 8 files changed, 10 insertions(+), 205 deletions(-)
+
+diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
+index 798ca4132928c..dbfbbe9ab28b1 100644
+--- a/Documentation/filesystems/f2fs.rst
++++ b/Documentation/filesystems/f2fs.rst
+@@ -226,8 +226,6 @@ mode=%s                     Control block allocation mode which supports "adaptive"
+                        option for more randomness.
+                        Please, use these options for your experiments and we strongly
+                        recommend to re-format the filesystem after using these options.
+-io_bits=%u             Set the bit size of write IO requests. It should be set
+-                       with "mode=lfs".
+ usrquota               Enable plain user disk quota accounting.
+ grpquota               Enable plain group disk quota accounting.
+ prjquota               Enable plain project quota accounting.
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index b639299a55f27..2c4cb801899e8 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -338,17 +338,6 @@ static void f2fs_write_end_io(struct bio *bio)
+               struct page *page = bvec->bv_page;
+               enum count_type type = WB_DATA_TYPE(page, false);
+-              if (page_private_dummy(page)) {
+-                      clear_page_private_dummy(page);
+-                      unlock_page(page);
+-                      mempool_free(page, sbi->write_io_dummy);
+-
+-                      if (unlikely(bio->bi_status))
+-                              f2fs_stop_checkpoint(sbi, true,
+-                                              STOP_CP_REASON_WRITE_FAIL);
+-                      continue;
+-              }
+-
+               fscrypt_finalize_bounce_page(&page);
+ #ifdef CONFIG_F2FS_FS_COMPRESSION
+@@ -522,50 +511,13 @@ void f2fs_submit_read_bio(struct f2fs_sb_info *sbi, struct bio *bio,
+       submit_bio(bio);
+ }
+-static void f2fs_align_write_bio(struct f2fs_sb_info *sbi, struct bio *bio)
+-{
+-      unsigned int start =
+-              (bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS) % F2FS_IO_SIZE(sbi);
+-
+-      if (start == 0)
+-              return;
+-
+-      /* fill dummy pages */
+-      for (; start < F2FS_IO_SIZE(sbi); start++) {
+-              struct page *page =
+-                      mempool_alloc(sbi->write_io_dummy,
+-                                    GFP_NOIO | __GFP_NOFAIL);
+-              f2fs_bug_on(sbi, !page);
+-
+-              lock_page(page);
+-
+-              zero_user_segment(page, 0, PAGE_SIZE);
+-              set_page_private_dummy(page);
+-
+-              if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE)
+-                      f2fs_bug_on(sbi, 1);
+-      }
+-}
+-
+ static void f2fs_submit_write_bio(struct f2fs_sb_info *sbi, struct bio *bio,
+                                 enum page_type type)
+ {
+       WARN_ON_ONCE(is_read_io(bio_op(bio)));
+-      if (type == DATA || type == NODE) {
+-              if (f2fs_lfs_mode(sbi) && current->plug)
+-                      blk_finish_plug(current->plug);
+-
+-              if (F2FS_IO_ALIGNED(sbi)) {
+-                      f2fs_align_write_bio(sbi, bio);
+-                      /*
+-                       * In the NODE case, we lose next block address chain.
+-                       * So, we need to do checkpoint in f2fs_sync_file.
+-                       */
+-                      if (type == NODE)
+-                              set_sbi_flag(sbi, SBI_NEED_CP);
+-              }
+-      }
++      if (f2fs_lfs_mode(sbi) && current->plug && PAGE_TYPE_ON_MAIN(type))
++              blk_finish_plug(current->plug);
+       trace_f2fs_submit_write_bio(sbi->sb, type, bio);
+       iostat_update_submit_ctx(bio, type);
+@@ -794,16 +746,6 @@ static bool io_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio,
+                                       block_t last_blkaddr,
+                                       block_t cur_blkaddr)
+ {
+-      if (F2FS_IO_ALIGNED(sbi) && (fio->type == DATA || fio->type == NODE)) {
+-              unsigned int filled_blocks =
+-                              F2FS_BYTES_TO_BLK(bio->bi_iter.bi_size);
+-              unsigned int io_size = F2FS_IO_SIZE(sbi);
+-              unsigned int left_vecs = bio->bi_max_vecs - bio->bi_vcnt;
+-
+-              /* IOs in bio is aligned and left space of vectors is not enough */
+-              if (!(filled_blocks % io_size) && left_vecs < io_size)
+-                      return false;
+-      }
+       if (!page_is_mergeable(sbi, bio, last_blkaddr, cur_blkaddr))
+               return false;
+       return io_type_is_mergeable(io, fio);
+@@ -1055,14 +997,6 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
+               __submit_merged_bio(io);
+ alloc_new:
+       if (io->bio == NULL) {
+-              if (F2FS_IO_ALIGNED(sbi) &&
+-                              (fio->type == DATA || fio->type == NODE) &&
+-                              fio->new_blkaddr & F2FS_IO_SIZE_MASK(sbi)) {
+-                      dec_page_count(sbi, WB_DATA_TYPE(bio_page,
+-                                              fio->compressed_page));
+-                      fio->retry = 1;
+-                      goto skip;
+-              }
+               io->bio = __bio_alloc(fio, BIO_MAX_VECS);
+               f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host,
+                                      bio_page->index, fio, GFP_NOIO);
+@@ -1092,7 +1026,6 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
+               __submit_merged_bio(io);
+       }
+ #endif
+-skip:
+       if (fio->in_list)
+               goto next;
+ out:
+@@ -2666,8 +2599,6 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
+       if (fio) {
+               if (page_private_gcing(fio->page))
+                       return true;
+-              if (page_private_dummy(fio->page))
+-                      return true;
+               if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
+                       f2fs_is_checkpointed_data(sbi, fio->old_blkaddr)))
+                       return true;
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index 82f54ffde4cd4..8aa7b481320ec 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -147,7 +147,6 @@ struct f2fs_rwsem {
+ struct f2fs_mount_info {
+       unsigned int opt;
+-      int write_io_size_bits;         /* Write IO size bits */
+       block_t root_reserved_blocks;   /* root reserved blocks */
+       kuid_t s_resuid;                /* reserved blocks for uid */
+       kgid_t s_resgid;                /* reserved blocks for gid */
+@@ -1109,6 +1108,7 @@ enum count_type {
+  * ...                        Only can be used with META.
+  */
+ #define PAGE_TYPE_OF_BIO(type)        ((type) > META ? META : (type))
++#define PAGE_TYPE_ON_MAIN(type)       ((type) == DATA || (type) == NODE)
+ enum page_type {
+       DATA = 0,
+       NODE = 1,       /* should not change this */
+@@ -1203,7 +1203,6 @@ struct f2fs_io_info {
+       unsigned int submitted:1;       /* indicate IO submission */
+       unsigned int in_list:1;         /* indicate fio is in io_list */
+       unsigned int is_por:1;          /* indicate IO is from recovery or not */
+-      unsigned int retry:1;           /* need to reallocate block address */
+       unsigned int encrypted:1;       /* indicate file is encrypted */
+       unsigned int post_read:1;       /* require post read */
+       enum iostat_type io_type;       /* io type */
+@@ -1404,18 +1403,16 @@ static inline void f2fs_clear_bit(unsigned int nr, char *addr);
+  * Layout A: lowest bit should be 1
+  * | bit0 = 1 | bit1 | bit2 | ... | bit MAX | private data .... |
+  * bit 0      PAGE_PRIVATE_NOT_POINTER
+- * bit 1      PAGE_PRIVATE_DUMMY_WRITE
+- * bit 2      PAGE_PRIVATE_ONGOING_MIGRATION
+- * bit 3      PAGE_PRIVATE_INLINE_INODE
+- * bit 4      PAGE_PRIVATE_REF_RESOURCE
+- * bit 5-     f2fs private data
++ * bit 1      PAGE_PRIVATE_ONGOING_MIGRATION
++ * bit 2      PAGE_PRIVATE_INLINE_INODE
++ * bit 3      PAGE_PRIVATE_REF_RESOURCE
++ * bit 4-     f2fs private data
+  *
+  * Layout B: lowest bit should be 0
+  * page.private is a wrapped pointer.
+  */
+ enum {
+       PAGE_PRIVATE_NOT_POINTER,               /* private contains non-pointer data */
+-      PAGE_PRIVATE_DUMMY_WRITE,               /* data page for padding aligned IO */
+       PAGE_PRIVATE_ONGOING_MIGRATION,         /* data page which is on-going migrating */
+       PAGE_PRIVATE_INLINE_INODE,              /* inode page contains inline data */
+       PAGE_PRIVATE_REF_RESOURCE,              /* dirty page has referenced resources */
+@@ -1562,7 +1559,6 @@ struct f2fs_sb_info {
+       struct f2fs_bio_info *write_io[NR_PAGE_TYPE];   /* for write bios */
+       /* keep migration IO order for LFS mode */
+       struct f2fs_rwsem io_order_lock;
+-      mempool_t *write_io_dummy;              /* Dummy pages */
+       pgoff_t page_eio_ofs[NR_PAGE_TYPE];     /* EIO page offset */
+       int page_eio_cnt[NR_PAGE_TYPE];         /* EIO count */
+@@ -2306,10 +2302,6 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
+       if (!__allow_reserved_blocks(sbi, inode, true))
+               avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks;
+-      if (F2FS_IO_ALIGNED(sbi))
+-              avail_user_block_count -= sbi->blocks_per_seg *
+-                              SM_I(sbi)->additional_reserved_segments;
+-
+       if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
+               if (avail_user_block_count > sbi->unusable_block_count)
+                       avail_user_block_count -= sbi->unusable_block_count;
+@@ -2377,17 +2369,14 @@ static inline void clear_page_private_##name(struct page *page) \
+ PAGE_PRIVATE_GET_FUNC(nonpointer, NOT_POINTER);
+ PAGE_PRIVATE_GET_FUNC(inline, INLINE_INODE);
+ PAGE_PRIVATE_GET_FUNC(gcing, ONGOING_MIGRATION);
+-PAGE_PRIVATE_GET_FUNC(dummy, DUMMY_WRITE);
+ PAGE_PRIVATE_SET_FUNC(reference, REF_RESOURCE);
+ PAGE_PRIVATE_SET_FUNC(inline, INLINE_INODE);
+ PAGE_PRIVATE_SET_FUNC(gcing, ONGOING_MIGRATION);
+-PAGE_PRIVATE_SET_FUNC(dummy, DUMMY_WRITE);
+ PAGE_PRIVATE_CLEAR_FUNC(reference, REF_RESOURCE);
+ PAGE_PRIVATE_CLEAR_FUNC(inline, INLINE_INODE);
+ PAGE_PRIVATE_CLEAR_FUNC(gcing, ONGOING_MIGRATION);
+-PAGE_PRIVATE_CLEAR_FUNC(dummy, DUMMY_WRITE);
+ static inline unsigned long get_page_private_data(struct page *page)
+ {
+@@ -2640,10 +2629,6 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
+       if (!__allow_reserved_blocks(sbi, inode, false))
+               valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks;
+-      if (F2FS_IO_ALIGNED(sbi))
+-              valid_block_count += sbi->blocks_per_seg *
+-                              SM_I(sbi)->additional_reserved_segments;
+-
+       user_block_count = sbi->user_block_count;
+       if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
+               user_block_count -= sbi->unusable_block_count;
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index 206cb01875c48..fdd9825e57483 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -813,8 +813,6 @@ static bool f2fs_force_buffered_io(struct inode *inode, int rw)
+        */
+       if (f2fs_sb_has_blkzoned(sbi) && (rw == WRITE))
+               return true;
+-      if (f2fs_lfs_mode(sbi) && rw == WRITE && F2FS_IO_ALIGNED(sbi))
+-              return true;
+       if (is_sbi_flag_set(sbi, SBI_CP_DISABLED))
+               return true;
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+index 9a4ec639e58a7..ab8e54d8bfe04 100644
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -1183,7 +1183,6 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
+               .op_flags = 0,
+               .encrypted_page = NULL,
+               .in_list = 0,
+-              .retry = 0,
+       };
+       int err;
+@@ -1272,7 +1271,6 @@ static int move_data_block(struct inode *inode, block_t bidx,
+               .op_flags = 0,
+               .encrypted_page = NULL,
+               .in_list = 0,
+-              .retry = 0,
+       };
+       struct dnode_of_data dn;
+       struct f2fs_summary sum;
+@@ -1392,18 +1390,12 @@ static int move_data_block(struct inode *inode, block_t bidx,
+       fio.op_flags = REQ_SYNC;
+       fio.new_blkaddr = newaddr;
+       f2fs_submit_page_write(&fio);
+-      if (fio.retry) {
+-              err = -EAGAIN;
+-              if (PageWriteback(fio.encrypted_page))
+-                      end_page_writeback(fio.encrypted_page);
+-              goto put_page_out;
+-      }
+       f2fs_update_iostat(fio.sbi, NULL, FS_GC_DATA_IO, F2FS_BLKSIZE);
+       f2fs_update_data_blkaddr(&dn, newaddr);
+       set_inode_flag(inode, FI_APPEND_WRITE);
+-put_page_out:
++
+       f2fs_put_page(fio.encrypted_page, 1);
+ recover_block:
+       if (err)
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 52b281e9f472f..a29fdf30c5842 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -3517,9 +3517,6 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
+       if (fio) {
+               struct f2fs_bio_info *io;
+-              if (F2FS_IO_ALIGNED(sbi))
+-                      fio->retry = 0;
+-
+               INIT_LIST_HEAD(&fio->list);
+               fio->in_list = 1;
+               io = sbi->write_io[fio->type] + fio->temp;
+@@ -3567,7 +3564,7 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
+       if (keep_order)
+               f2fs_down_read(&fio->sbi->io_order_lock);
+-reallocate:
++
+       f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
+                       &fio->new_blkaddr, sum, type, fio);
+       if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO)
+@@ -3575,10 +3572,6 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
+       /* writeout dirty page into bdev */
+       f2fs_submit_page_write(fio);
+-      if (fio->retry) {
+-              fio->old_blkaddr = fio->new_blkaddr;
+-              goto reallocate;
+-      }
+       f2fs_update_device_state(fio->sbi, fio->ino, fio->new_blkaddr, 1);
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index a20014fb5fc51..ce2293e13fadd 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -122,7 +122,6 @@ enum {
+       Opt_resgid,
+       Opt_resuid,
+       Opt_mode,
+-      Opt_io_size_bits,
+       Opt_fault_injection,
+       Opt_fault_type,
+       Opt_lazytime,
+@@ -201,7 +200,6 @@ static match_table_t f2fs_tokens = {
+       {Opt_resgid, "resgid=%u"},
+       {Opt_resuid, "resuid=%u"},
+       {Opt_mode, "mode=%s"},
+-      {Opt_io_size_bits, "io_bits=%u"},
+       {Opt_fault_injection, "fault_injection=%u"},
+       {Opt_fault_type, "fault_type=%u"},
+       {Opt_lazytime, "lazytime"},
+@@ -333,46 +331,6 @@ static inline void limit_reserve_root(struct f2fs_sb_info *sbi)
+                                          F2FS_OPTION(sbi).s_resgid));
+ }
+-static inline int adjust_reserved_segment(struct f2fs_sb_info *sbi)
+-{
+-      unsigned int sec_blks = sbi->blocks_per_seg * sbi->segs_per_sec;
+-      unsigned int avg_vblocks;
+-      unsigned int wanted_reserved_segments;
+-      block_t avail_user_block_count;
+-
+-      if (!F2FS_IO_ALIGNED(sbi))
+-              return 0;
+-
+-      /* average valid block count in section in worst case */
+-      avg_vblocks = sec_blks / F2FS_IO_SIZE(sbi);
+-
+-      /*
+-       * we need enough free space when migrating one section in worst case
+-       */
+-      wanted_reserved_segments = (F2FS_IO_SIZE(sbi) / avg_vblocks) *
+-                                              reserved_segments(sbi);
+-      wanted_reserved_segments -= reserved_segments(sbi);
+-
+-      avail_user_block_count = sbi->user_block_count -
+-                              sbi->current_reserved_blocks -
+-                              F2FS_OPTION(sbi).root_reserved_blocks;
+-
+-      if (wanted_reserved_segments * sbi->blocks_per_seg >
+-                                      avail_user_block_count) {
+-              f2fs_err(sbi, "IO align feature can't grab additional reserved segment: %u, available segments: %u",
+-                      wanted_reserved_segments,
+-                      avail_user_block_count >> sbi->log_blocks_per_seg);
+-              return -ENOSPC;
+-      }
+-
+-      SM_I(sbi)->additional_reserved_segments = wanted_reserved_segments;
+-
+-      f2fs_info(sbi, "IO align feature needs additional reserved segment: %u",
+-                       wanted_reserved_segments);
+-
+-      return 0;
+-}
+-
+ static inline void adjust_unusable_cap_perc(struct f2fs_sb_info *sbi)
+ {
+       if (!F2FS_OPTION(sbi).unusable_cap_perc)
+@@ -907,16 +865,6 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
+                       }
+                       kfree(name);
+                       break;
+-              case Opt_io_size_bits:
+-                      if (args->from && match_int(args, &arg))
+-                              return -EINVAL;
+-                      if (arg <= 0 || arg > __ilog2_u32(BIO_MAX_VECS)) {
+-                              f2fs_warn(sbi, "Not support %ld, larger than %d",
+-                                      BIT(arg), BIO_MAX_VECS);
+-                              return -EINVAL;
+-                      }
+-                      F2FS_OPTION(sbi).write_io_size_bits = arg;
+-                      break;
+ #ifdef CONFIG_F2FS_FAULT_INJECTION
+               case Opt_fault_injection:
+                       if (args->from && match_int(args, &arg))
+@@ -1386,12 +1334,6 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
+       }
+ #endif
+-      if (F2FS_IO_SIZE_BITS(sbi) && !f2fs_lfs_mode(sbi)) {
+-              f2fs_err(sbi, "Should set mode=lfs with %luKB-sized IO",
+-                       F2FS_IO_SIZE_KB(sbi));
+-              return -EINVAL;
+-      }
+-
+       if (test_opt(sbi, INLINE_XATTR_SIZE)) {
+               int min_size, max_size;
+@@ -1719,7 +1661,6 @@ static void f2fs_put_super(struct super_block *sb)
+       destroy_device_list(sbi);
+       f2fs_destroy_page_array_cache(sbi);
+       f2fs_destroy_xattr_caches(sbi);
+-      mempool_destroy(sbi->write_io_dummy);
+ #ifdef CONFIG_QUOTA
+       for (i = 0; i < MAXQUOTAS; i++)
+               kfree(F2FS_OPTION(sbi).s_qf_names[i]);
+@@ -2076,9 +2017,6 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
+                                       F2FS_OPTION(sbi).s_resuid),
+                               from_kgid_munged(&init_user_ns,
+                                       F2FS_OPTION(sbi).s_resgid));
+-      if (F2FS_IO_SIZE_BITS(sbi))
+-              seq_printf(seq, ",io_bits=%u",
+-                              F2FS_OPTION(sbi).write_io_size_bits);
+ #ifdef CONFIG_F2FS_FAULT_INJECTION
+       if (test_opt(sbi, FAULT_INJECTION)) {
+               seq_printf(seq, ",fault_injection=%u",
+@@ -2329,7 +2267,6 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
+       bool no_read_extent_cache = !test_opt(sbi, READ_EXTENT_CACHE);
+       bool no_age_extent_cache = !test_opt(sbi, AGE_EXTENT_CACHE);
+       bool enable_checkpoint = !test_opt(sbi, DISABLE_CHECKPOINT);
+-      bool no_io_align = !F2FS_IO_ALIGNED(sbi);
+       bool no_atgc = !test_opt(sbi, ATGC);
+       bool no_discard = !test_opt(sbi, DISCARD);
+       bool no_compress_cache = !test_opt(sbi, COMPRESS_CACHE);
+@@ -2437,12 +2374,6 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
+               goto restore_opts;
+       }
+-      if (no_io_align == !!F2FS_IO_ALIGNED(sbi)) {
+-              err = -EINVAL;
+-              f2fs_warn(sbi, "switch io_bits option is not allowed");
+-              goto restore_opts;
+-      }
+-
+       if (no_compress_cache == !!test_opt(sbi, COMPRESS_CACHE)) {
+               err = -EINVAL;
+               f2fs_warn(sbi, "switch compress_cache option is not allowed");
+@@ -4290,8 +4221,6 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
+                         FDEV(i).total_segments,
+                         FDEV(i).start_blk, FDEV(i).end_blk);
+       }
+-      f2fs_info(sbi,
+-                "IO Block Size: %8ld KB", F2FS_IO_SIZE_KB(sbi));
+       return 0;
+ }
+@@ -4504,19 +4433,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
+       if (err)
+               goto free_iostat;
+-      if (F2FS_IO_ALIGNED(sbi)) {
+-              sbi->write_io_dummy =
+-                      mempool_create_page_pool(2 * (F2FS_IO_SIZE(sbi) - 1), 0);
+-              if (!sbi->write_io_dummy) {
+-                      err = -ENOMEM;
+-                      goto free_percpu;
+-              }
+-      }
+-
+       /* init per sbi slab cache */
+       err = f2fs_init_xattr_caches(sbi);
+       if (err)
+-              goto free_io_dummy;
++              goto free_percpu;
+       err = f2fs_init_page_array_cache(sbi);
+       if (err)
+               goto free_xattr_cache;
+@@ -4604,10 +4524,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
+               goto free_nm;
+       }
+-      err = adjust_reserved_segment(sbi);
+-      if (err)
+-              goto free_nm;
+-
+       /* For write statistics */
+       sbi->sectors_written_start = f2fs_get_sectors_written(sbi);
+@@ -4839,8 +4755,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
+       f2fs_destroy_page_array_cache(sbi);
+ free_xattr_cache:
+       f2fs_destroy_xattr_caches(sbi);
+-free_io_dummy:
+-      mempool_destroy(sbi->write_io_dummy);
+ free_percpu:
+       destroy_percpu_info(sbi);
+ free_iostat:
+diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
+index 5aa00bcd42fe9..3b04657787d09 100644
+--- a/include/linux/f2fs_fs.h
++++ b/include/linux/f2fs_fs.h
+@@ -41,12 +41,6 @@
+ #define F2FS_ENC_UTF8_12_1    1
+-#define F2FS_IO_SIZE(sbi)     BIT(F2FS_OPTION(sbi).write_io_size_bits) /* Blocks */
+-#define F2FS_IO_SIZE_KB(sbi)  BIT(F2FS_OPTION(sbi).write_io_size_bits + 2) /* KB */
+-#define F2FS_IO_SIZE_BITS(sbi)        (F2FS_OPTION(sbi).write_io_size_bits) /* power of 2 */
+-#define F2FS_IO_SIZE_MASK(sbi)        (F2FS_IO_SIZE(sbi) - 1)
+-#define F2FS_IO_ALIGNED(sbi)  (F2FS_IO_SIZE(sbi) > 1)
+-
+ /* This flag is used by node and meta inodes, and by recovery */
+ #define GFP_F2FS_ZERO         (GFP_NOFS | __GFP_ZERO)
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-fix-block-migration-when-section-is-not-aligned.patch b/queue-6.6/f2fs-fix-block-migration-when-section-is-not-aligned.patch
new file mode 100644 (file)
index 0000000..d75d70b
--- /dev/null
@@ -0,0 +1,62 @@
+From fc6119b710db1b40a90569bdb44b9fa0f63065d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 28 Apr 2024 21:51:42 -0600
+Subject: f2fs: fix block migration when section is not aligned to pow2
+
+From: Wu Bo <bo.wu@vivo.com>
+
+[ Upstream commit aa4074e8fec4d2e686daee627fcafb3503efe365 ]
+
+As for zoned-UFS, f2fs section size is forced to zone size. And zone
+size may not aligned to pow2.
+
+Fixes: 859fca6b706e ("f2fs: swap: support migrating swapfile in aligned write mode")
+Signed-off-by: Liao Yuanhong <liaoyuanhong@vivo.com>
+Signed-off-by: Wu Bo <bo.wu@vivo.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/data.c | 17 ++++++++---------
+ 1 file changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index 3558fc3387f54..b639299a55f27 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -3974,15 +3974,14 @@ static int check_swap_activate(struct swap_info_struct *sis,
+       struct address_space *mapping = swap_file->f_mapping;
+       struct inode *inode = mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+-      sector_t cur_lblock;
+-      sector_t last_lblock;
+-      sector_t pblock;
+-      sector_t lowest_pblock = -1;
+-      sector_t highest_pblock = 0;
++      block_t cur_lblock;
++      block_t last_lblock;
++      block_t pblock;
++      block_t lowest_pblock = -1;
++      block_t highest_pblock = 0;
+       int nr_extents = 0;
+-      unsigned long nr_pblocks;
++      unsigned int nr_pblocks;
+       unsigned int blks_per_sec = BLKS_PER_SEC(sbi);
+-      unsigned int sec_blks_mask = BLKS_PER_SEC(sbi) - 1;
+       unsigned int not_aligned = 0;
+       int ret = 0;
+@@ -4020,8 +4019,8 @@ static int check_swap_activate(struct swap_info_struct *sis,
+               pblock = map.m_pblk;
+               nr_pblocks = map.m_len;
+-              if ((pblock - SM_I(sbi)->main_blkaddr) & sec_blks_mask ||
+-                              nr_pblocks & sec_blks_mask ||
++              if ((pblock - SM_I(sbi)->main_blkaddr) % blks_per_sec ||
++                              nr_pblocks % blks_per_sec ||
+                               !f2fs_valid_pinned_area(sbi, pblock)) {
+                       bool last_extent = false;
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-fix-to-add-missing-iput-in-gc_data_segment.patch b/queue-6.6/f2fs-fix-to-add-missing-iput-in-gc_data_segment.patch
new file mode 100644 (file)
index 0000000..47bdafc
--- /dev/null
@@ -0,0 +1,46 @@
+From 8928bd3793b0708c8181bc47a39e7669c577dbcb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 11:43:33 +0800
+Subject: f2fs: fix to add missing iput() in gc_data_segment()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit a798ff17cd2dabe47d5d4ed3d509631793c36e19 ]
+
+During gc_data_segment(), if inode state is abnormal, it missed to call
+iput(), fix it.
+
+Fixes: b73e52824c89 ("f2fs: reposition unlock_new_inode to prevent accessing invalid inode")
+Fixes: 9056d6489f5a ("f2fs: fix to do sanity check on inode type during garbage collection")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/gc.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+index ab8e54d8bfe04..3f0632dd9d2e6 100644
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -1551,10 +1551,15 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+                       int err;
+                       inode = f2fs_iget(sb, dni.ino);
+-                      if (IS_ERR(inode) || is_bad_inode(inode) ||
+-                                      special_file(inode->i_mode))
++                      if (IS_ERR(inode))
+                               continue;
++                      if (is_bad_inode(inode) ||
++                                      special_file(inode->i_mode)) {
++                              iput(inode);
++                              continue;
++                      }
++
+                       err = f2fs_gc_pinned_control(inode, gc_type, segno);
+                       if (err == -EAGAIN) {
+                               iput(inode);
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-fix-to-check-pinfile-flag-in-f2fs_move_file_ran.patch b/queue-6.6/f2fs-fix-to-check-pinfile-flag-in-f2fs_move_file_ran.patch
new file mode 100644 (file)
index 0000000..9c00223
--- /dev/null
@@ -0,0 +1,37 @@
+From c76afe1cc5d3e22dbae960e334dd4f7ab6059804 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Apr 2024 22:24:20 +0800
+Subject: f2fs: fix to check pinfile flag in f2fs_move_file_range()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit e07230da0500e0919a765037c5e81583b519be2c ]
+
+ioctl(F2FS_IOC_MOVE_RANGE) can truncate or punch hole on pinned file,
+fix to disallow it.
+
+Fixes: 5fed0be8583f ("f2fs: do not allow partial truncation on pinned file")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/file.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index d908ef72fef6e..5c24d18f4e297 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -2813,7 +2813,8 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
+                       goto out;
+       }
+-      if (f2fs_compressed_file(src) || f2fs_compressed_file(dst)) {
++      if (f2fs_compressed_file(src) || f2fs_compressed_file(dst) ||
++              f2fs_is_pinned_file(src) || f2fs_is_pinned_file(dst)) {
+               ret = -EOPNOTSUPP;
+               goto out_unlock;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-fix-to-release-node-block-count-in-error-path-o.patch b/queue-6.6/f2fs-fix-to-release-node-block-count-in-error-path-o.patch
new file mode 100644 (file)
index 0000000..5b2542e
--- /dev/null
@@ -0,0 +1,44 @@
+From ccfd934e6a7e05d809249ea7078f575444a90b4a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 11:31:00 +0800
+Subject: f2fs: fix to release node block count in error path of
+ f2fs_new_node_page()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 0fa4e57c1db263effd72d2149d4e21da0055c316 ]
+
+It missed to call dec_valid_node_count() to release node block count
+in error path, fix it.
+
+Fixes: 141170b759e0 ("f2fs: fix to avoid use f2fs_bug_on() in f2fs_new_node_page()")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/node.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
+index ab113fd3a3432..c765bda3beaac 100644
+--- a/fs/f2fs/node.c
++++ b/fs/f2fs/node.c
+@@ -1319,6 +1319,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs)
+       }
+       if (unlikely(new_ni.blk_addr != NULL_ADDR)) {
+               err = -EFSCORRUPTED;
++              dec_valid_node_count(sbi, dn->inode, !ofs);
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
+               goto fail;
+@@ -1345,7 +1346,6 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs)
+       if (ofs == 0)
+               inc_valid_inode_count(sbi);
+       return page;
+-
+ fail:
+       clear_node_page_dirty(page);
+       f2fs_put_page(page, 1);
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-fix-to-relocate-check-condition-in-f2fs_falloca.patch b/queue-6.6/f2fs-fix-to-relocate-check-condition-in-f2fs_falloca.patch
new file mode 100644 (file)
index 0000000..b2ab709
--- /dev/null
@@ -0,0 +1,62 @@
+From afb6a7e47cf1d857621652fb1353b928f77f910f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Apr 2024 22:24:19 +0800
+Subject: f2fs: fix to relocate check condition in f2fs_fallocate()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 278a6253a673611dbc8ab72a3b34b151a8e75822 ]
+
+compress and pinfile flag should be checked after inode lock held to
+avoid race condition, fix it.
+
+Fixes: 4c8ff7095bef ("f2fs: support data compression")
+Fixes: 5fed0be8583f ("f2fs: do not allow partial truncation on pinned file")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/file.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index 420939ca36422..d908ef72fef6e 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -1797,15 +1797,6 @@ static long f2fs_fallocate(struct file *file, int mode,
+               (mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE)))
+               return -EOPNOTSUPP;
+-      /*
+-       * Pinned file should not support partial truncation since the block
+-       * can be used by applications.
+-       */
+-      if ((f2fs_compressed_file(inode) || f2fs_is_pinned_file(inode)) &&
+-              (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE |
+-                      FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE)))
+-              return -EOPNOTSUPP;
+-
+       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
+                       FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE |
+                       FALLOC_FL_INSERT_RANGE))
+@@ -1813,6 +1804,17 @@ static long f2fs_fallocate(struct file *file, int mode,
+       inode_lock(inode);
++      /*
++       * Pinned file should not support partial truncation since the block
++       * can be used by applications.
++       */
++      if ((f2fs_compressed_file(inode) || f2fs_is_pinned_file(inode)) &&
++              (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE |
++                      FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE))) {
++              ret = -EOPNOTSUPP;
++              goto out;
++      }
++
+       ret = file_modified(file);
+       if (ret)
+               goto out;
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-fix-to-wait-on-page-writeback-in-__clone_blkadd.patch b/queue-6.6/f2fs-fix-to-wait-on-page-writeback-in-__clone_blkadd.patch
new file mode 100644 (file)
index 0000000..41c0855
--- /dev/null
@@ -0,0 +1,53 @@
+From 84cf7134c45ec0d668dfbad1dca3527cc2a87771 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Mar 2024 19:28:45 +0800
+Subject: f2fs: fix to wait on page writeback in __clone_blkaddrs()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit d3876e34e7e789e2cbdd782360fef2a777391082 ]
+
+In below race condition, dst page may become writeback status
+in __clone_blkaddrs(), it needs to wait writeback before update,
+fix it.
+
+Thread A                               GC Thread
+- f2fs_move_file_range
+  - filemap_write_and_wait_range(dst)
+                                       - gc_data_segment
+                                        - f2fs_down_write(dst)
+                                        - move_data_page
+                                         - set_page_writeback(dst_page)
+                                         - f2fs_submit_page_write
+                                        - f2fs_up_write(dst)
+  - f2fs_down_write(dst)
+  - __exchange_data_block
+   - __clone_blkaddrs
+    - f2fs_get_new_data_page
+    - memcpy_page
+
+Fixes: 0a2aa8fbb969 ("f2fs: refactor __exchange_data_block for speed up")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/file.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index ee5df9adaf775..7f631a617ee99 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -1305,6 +1305,9 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
+                               f2fs_put_page(psrc, 1);
+                               return PTR_ERR(pdst);
+                       }
++
++                      f2fs_wait_on_page_writeback(pdst, DATA, true, true);
++
+                       memcpy_page(pdst, 0, psrc, 0, PAGE_SIZE);
+                       set_page_dirty(pdst);
+                       set_page_private_gcing(pdst);
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-introduce-get_available_block_count-for-cleanup.patch b/queue-6.6/f2fs-introduce-get_available_block_count-for-cleanup.patch
new file mode 100644 (file)
index 0000000..f435e4a
--- /dev/null
@@ -0,0 +1,110 @@
+From b6bde298f3c504aca681c279e9140ef510df4684 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Feb 2024 11:15:15 +0800
+Subject: f2fs: introduce get_available_block_count() for cleanup
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 0f1c6ede6da9f7c5dd7380b74a64850298279168 ]
+
+There are very similar codes in inc_valid_block_count() and
+inc_valid_node_count() which is used for available user block
+count calculation.
+
+This patch introduces a new helper get_available_block_count()
+to include those common codes, and used it to clean up codes.
+
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 043c832371cd ("f2fs: compress: fix error path of inc_valid_block_count()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/f2fs.h | 49 +++++++++++++++++++++++++++----------------------
+ 1 file changed, 27 insertions(+), 22 deletions(-)
+
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index 8aa7b481320ec..c90f6f9855c8e 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -2271,6 +2271,27 @@ static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi,
+       return false;
+ }
++static inline unsigned int get_available_block_count(struct f2fs_sb_info *sbi,
++                                              struct inode *inode, bool cap)
++{
++      block_t avail_user_block_count;
++
++      avail_user_block_count = sbi->user_block_count -
++                                      sbi->current_reserved_blocks;
++
++      if (!__allow_reserved_blocks(sbi, inode, cap))
++              avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks;
++
++      if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
++              if (avail_user_block_count > sbi->unusable_block_count)
++                      avail_user_block_count -= sbi->unusable_block_count;
++              else
++                      avail_user_block_count = 0;
++      }
++
++      return avail_user_block_count;
++}
++
+ static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool);
+ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
+                                struct inode *inode, blkcnt_t *count, bool partial)
+@@ -2296,18 +2317,8 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
+       spin_lock(&sbi->stat_lock);
+       sbi->total_valid_block_count += (block_t)(*count);
+-      avail_user_block_count = sbi->user_block_count -
+-                                      sbi->current_reserved_blocks;
++      avail_user_block_count = get_available_block_count(sbi, inode, true);
+-      if (!__allow_reserved_blocks(sbi, inode, true))
+-              avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks;
+-
+-      if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
+-              if (avail_user_block_count > sbi->unusable_block_count)
+-                      avail_user_block_count -= sbi->unusable_block_count;
+-              else
+-                      avail_user_block_count = 0;
+-      }
+       if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
+               if (!partial) {
+                       spin_unlock(&sbi->stat_lock);
+@@ -2603,7 +2614,8 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
+                                       struct inode *inode, bool is_inode)
+ {
+       block_t valid_block_count;
+-      unsigned int valid_node_count, user_block_count;
++      unsigned int valid_node_count;
++      unsigned int avail_user_block_count;
+       int err;
+       if (is_inode) {
+@@ -2623,17 +2635,10 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
+       spin_lock(&sbi->stat_lock);
+-      valid_block_count = sbi->total_valid_block_count +
+-                                      sbi->current_reserved_blocks + 1;
+-
+-      if (!__allow_reserved_blocks(sbi, inode, false))
+-              valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks;
+-
+-      user_block_count = sbi->user_block_count;
+-      if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
+-              user_block_count -= sbi->unusable_block_count;
++      valid_block_count = sbi->total_valid_block_count + 1;
++      avail_user_block_count = get_available_block_count(sbi, inode, false);
+-      if (unlikely(valid_block_count > user_block_count)) {
++      if (unlikely(valid_block_count > avail_user_block_count)) {
+               spin_unlock(&sbi->stat_lock);
+               goto enospc;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-kill-heap-based-allocation.patch b/queue-6.6/f2fs-kill-heap-based-allocation.patch
new file mode 100644 (file)
index 0000000..938af41
--- /dev/null
@@ -0,0 +1,229 @@
+From 4ea2c31297553ba66b1a27ece8fddac6514c1cd9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Feb 2024 12:48:44 -0800
+Subject: f2fs: kill heap-based allocation
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+[ Upstream commit 4e0197f9932f70cc7be8744aa0ed4dd9b5d97d85 ]
+
+No one uses this feature. Let's kill it.
+
+Reviewed-by: Daeho Jeong <daehojeong@google.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/filesystems/f2fs.rst |  4 +--
+ fs/f2fs/gc.c                       |  5 ++-
+ fs/f2fs/segment.c                  | 54 ++++--------------------------
+ fs/f2fs/segment.h                  | 10 ------
+ fs/f2fs/super.c                    |  9 +----
+ 5 files changed, 11 insertions(+), 71 deletions(-)
+
+diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
+index d32c6209685d6..798ca4132928c 100644
+--- a/Documentation/filesystems/f2fs.rst
++++ b/Documentation/filesystems/f2fs.rst
+@@ -126,9 +126,7 @@ norecovery          Disable the roll-forward recovery routine, mounted read-
+ discard/nodiscard      Enable/disable real-time discard in f2fs, if discard is
+                        enabled, f2fs will issue discard/TRIM commands when a
+                        segment is cleaned.
+-no_heap                        Disable heap-style segment allocation which finds free
+-                       segments for data from the beginning of main area, while
+-                       for node from the end of main area.
++heap/no_heap           Deprecated.
+ nouser_xattr           Disable Extended User Attributes. Note: xattr is enabled
+                        by default if CONFIG_F2FS_FS_XATTR is selected.
+ noacl                  Disable POSIX Access Control List. Note: acl is enabled
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+index 4cf37f51339c3..2a3d64f4253ee 100644
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -280,12 +280,11 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
+                       p->max_search > sbi->max_victim_search)
+               p->max_search = sbi->max_victim_search;
+-      /* let's select beginning hot/small space first in no_heap mode*/
++      /* let's select beginning hot/small space first. */
+       if (f2fs_need_rand_seg(sbi))
+               p->offset = get_random_u32_below(MAIN_SECS(sbi) *
+                                               SEGS_PER_SEC(sbi));
+-      else if (test_opt(sbi, NOHEAP) &&
+-              (type == CURSEG_HOT_DATA || IS_NODESEG(type)))
++      else if (type == CURSEG_HOT_DATA || IS_NODESEG(type))
+               p->offset = 0;
+       else
+               p->offset = SIT_I(sbi)->last_victim[p->gc_mode];
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 01e9366705b25..523c3a91bdf21 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -2638,16 +2638,14 @@ static int is_next_segment_free(struct f2fs_sb_info *sbi,
+  * This function should be returned with success, otherwise BUG
+  */
+ static void get_new_segment(struct f2fs_sb_info *sbi,
+-                      unsigned int *newseg, bool new_sec, int dir)
++                      unsigned int *newseg, bool new_sec)
+ {
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int segno, secno, zoneno;
+       unsigned int total_zones = MAIN_SECS(sbi) / sbi->secs_per_zone;
+       unsigned int hint = GET_SEC_FROM_SEG(sbi, *newseg);
+       unsigned int old_zoneno = GET_ZONE_FROM_SEG(sbi, *newseg);
+-      unsigned int left_start = hint;
+       bool init = true;
+-      int go_left = 0;
+       int i;
+       spin_lock(&free_i->segmap_lock);
+@@ -2661,30 +2659,10 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
+ find_other_zone:
+       secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
+       if (secno >= MAIN_SECS(sbi)) {
+-              if (dir == ALLOC_RIGHT) {
+-                      secno = find_first_zero_bit(free_i->free_secmap,
++              secno = find_first_zero_bit(free_i->free_secmap,
+                                                       MAIN_SECS(sbi));
+-                      f2fs_bug_on(sbi, secno >= MAIN_SECS(sbi));
+-              } else {
+-                      go_left = 1;
+-                      left_start = hint - 1;
+-              }
+-      }
+-      if (go_left == 0)
+-              goto skip_left;
+-
+-      while (test_bit(left_start, free_i->free_secmap)) {
+-              if (left_start > 0) {
+-                      left_start--;
+-                      continue;
+-              }
+-              left_start = find_first_zero_bit(free_i->free_secmap,
+-                                                      MAIN_SECS(sbi));
+-              f2fs_bug_on(sbi, left_start >= MAIN_SECS(sbi));
+-              break;
++              f2fs_bug_on(sbi, secno >= MAIN_SECS(sbi));
+       }
+-      secno = left_start;
+-skip_left:
+       segno = GET_SEG_FROM_SEC(sbi, secno);
+       zoneno = GET_ZONE_FROM_SEC(sbi, secno);
+@@ -2695,21 +2673,13 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
+               goto got_it;
+       if (zoneno == old_zoneno)
+               goto got_it;
+-      if (dir == ALLOC_LEFT) {
+-              if (!go_left && zoneno + 1 >= total_zones)
+-                      goto got_it;
+-              if (go_left && zoneno == 0)
+-                      goto got_it;
+-      }
+       for (i = 0; i < NR_CURSEG_TYPE; i++)
+               if (CURSEG_I(sbi, i)->zone == zoneno)
+                       break;
+       if (i < NR_CURSEG_TYPE) {
+               /* zone is in user, try another */
+-              if (go_left)
+-                      hint = zoneno * sbi->secs_per_zone - 1;
+-              else if (zoneno + 1 >= total_zones)
++              if (zoneno + 1 >= total_zones)
+                       hint = 0;
+               else
+                       hint = (zoneno + 1) * sbi->secs_per_zone;
+@@ -2767,8 +2737,7 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
+       if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
+               return 0;
+-      if (test_opt(sbi, NOHEAP) &&
+-              (seg_type == CURSEG_HOT_DATA || IS_NODESEG(seg_type)))
++      if (seg_type == CURSEG_HOT_DATA || IS_NODESEG(seg_type))
+               return 0;
+       if (SIT_I(sbi)->last_victim[ALLOC_NEXT])
+@@ -2788,21 +2757,12 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
+ static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
+ {
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+-      unsigned short seg_type = curseg->seg_type;
+       unsigned int segno = curseg->segno;
+-      int dir = ALLOC_LEFT;
+       if (curseg->inited)
+-              write_sum_page(sbi, curseg->sum_blk,
+-                              GET_SUM_BLOCK(sbi, segno));
+-      if (seg_type == CURSEG_WARM_DATA || seg_type == CURSEG_COLD_DATA)
+-              dir = ALLOC_RIGHT;
+-
+-      if (test_opt(sbi, NOHEAP))
+-              dir = ALLOC_RIGHT;
+-
++              write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno));
+       segno = __get_next_segno(sbi, type);
+-      get_new_segment(sbi, &segno, new_sec, dir);
++      get_new_segment(sbi, &segno, new_sec);
+       curseg->next_segno = segno;
+       reset_curseg(sbi, type, 1);
+       curseg->alloc_type = LFS;
+diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
+index 61fa12f12ffdc..93ffb62e45f4d 100644
+--- a/fs/f2fs/segment.h
++++ b/fs/f2fs/segment.h
+@@ -136,16 +136,6 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
+ #define SECTOR_TO_BLOCK(sectors)                                      \
+       ((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK)
+-/*
+- * indicate a block allocation direction: RIGHT and LEFT.
+- * RIGHT means allocating new sections towards the end of volume.
+- * LEFT means the opposite direction.
+- */
+-enum {
+-      ALLOC_RIGHT = 0,
+-      ALLOC_LEFT
+-};
+-
+ /*
+  * In the victim_sel_policy->alloc_mode, there are three block allocation modes.
+  * LFS writes data sequentially with cleaning operations.
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index a0e6f804a1d0e..a20014fb5fc51 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -759,10 +759,8 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
+                       clear_opt(sbi, DISCARD);
+                       break;
+               case Opt_noheap:
+-                      set_opt(sbi, NOHEAP);
+-                      break;
+               case Opt_heap:
+-                      clear_opt(sbi, NOHEAP);
++                      f2fs_warn(sbi, "heap/no_heap options were deprecated");
+                       break;
+ #ifdef CONFIG_F2FS_FS_XATTR
+               case Opt_user_xattr:
+@@ -2013,10 +2011,6 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
+       } else {
+               seq_puts(seq, ",nodiscard");
+       }
+-      if (test_opt(sbi, NOHEAP))
+-              seq_puts(seq, ",no_heap");
+-      else
+-              seq_puts(seq, ",heap");
+ #ifdef CONFIG_F2FS_FS_XATTR
+       if (test_opt(sbi, XATTR_USER))
+               seq_puts(seq, ",user_xattr");
+@@ -2196,7 +2190,6 @@ static void default_options(struct f2fs_sb_info *sbi, bool remount)
+       set_opt(sbi, INLINE_XATTR);
+       set_opt(sbi, INLINE_DATA);
+       set_opt(sbi, INLINE_DENTRY);
+-      set_opt(sbi, NOHEAP);
+       set_opt(sbi, MERGE_CHECKPOINT);
+       F2FS_OPTION(sbi).unusable_cap = 0;
+       sbi->sb->s_flags |= SB_LAZYTIME;
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-multidev-fix-to-recognize-valid-zero-block-addr.patch b/queue-6.6/f2fs-multidev-fix-to-recognize-valid-zero-block-addr.patch
new file mode 100644 (file)
index 0000000..8d91b99
--- /dev/null
@@ -0,0 +1,119 @@
+From e8bb2c79bda202887df44572cead17adb03338d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Mar 2024 15:42:23 +0800
+Subject: f2fs: multidev: fix to recognize valid zero block address
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 33e62cd7b4c281cd737c62e5d8c4f0e602a8c5c5 ]
+
+As reported by Yi Zhang in mailing list [1], kernel warning was catched
+during zbd/010 test as below:
+
+./check zbd/010
+zbd/010 (test gap zone support with F2FS)                    [failed]
+    runtime    ...  3.752s
+    something found in dmesg:
+    [ 4378.146781] run blktests zbd/010 at 2024-02-18 11:31:13
+    [ 4378.192349] null_blk: module loaded
+    [ 4378.209860] null_blk: disk nullb0 created
+    [ 4378.413285] scsi_debug:sdebug_driver_probe: scsi_debug: trim
+poll_queues to 0. poll_q/nr_hw = (0/1)
+    [ 4378.422334] scsi host15: scsi_debug: version 0191 [20210520]
+                     dev_size_mb=1024, opts=0x0, submit_queues=1, statistics=0
+    [ 4378.434922] scsi 15:0:0:0: Direct-Access-ZBC Linux
+scsi_debug       0191 PQ: 0 ANSI: 7
+    [ 4378.443343] scsi 15:0:0:0: Power-on or device reset occurred
+    [ 4378.449371] sd 15:0:0:0: Attached scsi generic sg5 type 20
+    [ 4378.449418] sd 15:0:0:0: [sdf] Host-managed zoned block device
+    ...
+    (See '/mnt/tests/gitlab.com/api/v4/projects/19168116/repository/archive.zip/storage/blktests/blk/blktests/results/nodev/zbd/010.dmesg'
+
+WARNING: CPU: 22 PID: 44011 at fs/iomap/iter.c:51
+CPU: 22 PID: 44011 Comm: fio Not tainted 6.8.0-rc3+ #1
+RIP: 0010:iomap_iter+0x32b/0x350
+Call Trace:
+ <TASK>
+ __iomap_dio_rw+0x1df/0x830
+ f2fs_file_read_iter+0x156/0x3d0 [f2fs]
+ aio_read+0x138/0x210
+ io_submit_one+0x188/0x8c0
+ __x64_sys_io_submit+0x8c/0x1a0
+ do_syscall_64+0x86/0x170
+ entry_SYSCALL_64_after_hwframe+0x6e/0x76
+
+Shinichiro Kawasaki helps to analyse this issue and proposes a potential
+fixing patch in [2].
+
+Quoted from reply of Shinichiro Kawasaki:
+
+"I confirmed that the trigger commit is dbf8e63f48af as Yi reported. I took a
+look in the commit, but it looks fine to me. So I thought the cause is not
+in the commit diff.
+
+I found the WARN is printed when the f2fs is set up with multiple devices,
+and read requests are mapped to the very first block of the second device in the
+direct read path. In this case, f2fs_map_blocks() and f2fs_map_blocks_cached()
+modify map->m_pblk as the physical block address from each block device. It
+becomes zero when it is mapped to the first block of the device. However,
+f2fs_iomap_begin() assumes that map->m_pblk is the physical block address of the
+whole f2fs, across the all block devices. It compares map->m_pblk against
+NULL_ADDR == 0, then go into the unexpected branch and sets the invalid
+iomap->length. The WARN catches the invalid iomap->length.
+
+This WARN is printed even for non-zoned block devices, by following steps.
+
+ - Create two (non-zoned) null_blk devices memory backed with 128MB size each:
+   nullb0 and nullb1.
+ # mkfs.f2fs /dev/nullb0 -c /dev/nullb1
+ # mount -t f2fs /dev/nullb0 "${mount_dir}"
+ # dd if=/dev/zero of="${mount_dir}/test.dat" bs=1M count=192
+ # dd if="${mount_dir}/test.dat" of=/dev/null bs=1M count=192 iflag=direct
+
+..."
+
+So, the root cause of this issue is: when multi-devices feature is on,
+f2fs_map_blocks() may return zero blkaddr in non-primary device, which is
+a verified valid block address, however, f2fs_iomap_begin() treats it as
+an invalid block address, and then it triggers the warning in iomap
+framework code.
+
+Finally, as discussed, we decide to use a more simple and direct way that
+checking (map.m_flags & F2FS_MAP_MAPPED) condition instead of
+(map.m_pblk != NULL_ADDR) to fix this issue.
+
+Thanks a lot for the effort of Yi Zhang and Shinichiro Kawasaki on this
+issue.
+
+[1] https://lore.kernel.org/linux-f2fs-devel/CAHj4cs-kfojYC9i0G73PRkYzcxCTex=-vugRFeP40g_URGvnfQ@mail.gmail.com/
+[2] https://lore.kernel.org/linux-f2fs-devel/gngdj77k4picagsfdtiaa7gpgnup6fsgwzsltx6milmhegmjff@iax2n4wvrqye/
+
+Reported-by: Yi Zhang <yi.zhang@redhat.com>
+Closes: https://lore.kernel.org/linux-f2fs-devel/CAHj4cs-kfojYC9i0G73PRkYzcxCTex=-vugRFeP40g_URGvnfQ@mail.gmail.com/
+Tested-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+Tested-by: Yi Zhang <yi.zhang@redhat.com>
+Fixes: 1517c1a7a445 ("f2fs: implement iomap operations")
+Fixes: 8d3c1fa3fa5e ("f2fs: don't rely on F2FS_MAP_* in f2fs_iomap_begin")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/data.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index 5805b77d925e3..5d6ba12e84482 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -4243,7 +4243,7 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
+       if (WARN_ON_ONCE(map.m_pblk == COMPRESS_ADDR))
+               return -EINVAL;
+-      if (map.m_pblk != NULL_ADDR) {
++      if (map.m_flags & F2FS_MAP_MAPPED) {
+               iomap->length = blks_to_bytes(inode, map.m_len);
+               iomap->type = IOMAP_MAPPED;
+               iomap->flags |= IOMAP_F_MERGED;
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-separate-f2fs_gc_range-to-use-gc-for-a-range.patch b/queue-6.6/f2fs-separate-f2fs_gc_range-to-use-gc-for-a-range.patch
new file mode 100644 (file)
index 0000000..a0a22ac
--- /dev/null
@@ -0,0 +1,92 @@
+From 3071e9c718db22aeb12b3bd10c573392afeafa8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Feb 2024 14:32:55 -0800
+Subject: f2fs: separate f2fs_gc_range() to use GC for a range
+
+From: Daeho Jeong <daehojeong@google.com>
+
+[ Upstream commit 2f0209f579d12bd0ea43a01a8696e30a8eeec1da ]
+
+Make f2fs_gc_range() an extenal function to use it for GC for a range.
+
+Signed-off-by: Daeho Jeong <daehojeong@google.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/gc.c | 49 ++++++++++++++++++++++++++++---------------------
+ 1 file changed, 28 insertions(+), 21 deletions(-)
+
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+index 9c150b2dd9ec2..4cf37f51339c3 100644
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -1980,10 +1980,34 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
+       init_atgc_management(sbi);
+ }
++static int f2fs_gc_range(struct f2fs_sb_info *sbi,
++              unsigned int start_seg, unsigned int end_seg, bool dry_run)
++{
++      unsigned int segno;
++
++      for (segno = start_seg; segno <= end_seg; segno += SEGS_PER_SEC(sbi)) {
++              struct gc_inode_list gc_list = {
++                      .ilist = LIST_HEAD_INIT(gc_list.ilist),
++                      .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
++              };
++
++              do_garbage_collect(sbi, segno, &gc_list, FG_GC, true);
++              put_gc_inode(&gc_list);
++
++              if (!dry_run && get_valid_blocks(sbi, segno, true))
++                      return -EAGAIN;
++
++              if (fatal_signal_pending(current))
++                      return -ERESTARTSYS;
++      }
++
++      return 0;
++}
++
+ static int free_segment_range(struct f2fs_sb_info *sbi,
+-                              unsigned int secs, bool gc_only)
++                              unsigned int secs, bool dry_run)
+ {
+-      unsigned int segno, next_inuse, start, end;
++      unsigned int next_inuse, start, end;
+       struct cp_control cpc = { CP_RESIZE, 0, 0, 0 };
+       int gc_mode, gc_type;
+       int err = 0;
+@@ -2009,25 +2033,8 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
+               f2fs_allocate_segment_for_resize(sbi, type, start, end);
+       /* do GC to move out valid blocks in the range */
+-      for (segno = start; segno <= end; segno += SEGS_PER_SEC(sbi)) {
+-              struct gc_inode_list gc_list = {
+-                      .ilist = LIST_HEAD_INIT(gc_list.ilist),
+-                      .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
+-              };
+-
+-              do_garbage_collect(sbi, segno, &gc_list, FG_GC, true);
+-              put_gc_inode(&gc_list);
+-
+-              if (!gc_only && get_valid_blocks(sbi, segno, true)) {
+-                      err = -EAGAIN;
+-                      goto out;
+-              }
+-              if (fatal_signal_pending(current)) {
+-                      err = -ERESTARTSYS;
+-                      goto out;
+-              }
+-      }
+-      if (gc_only)
++      err = f2fs_gc_range(sbi, start, end, dry_run);
++      if (err || dry_run)
+               goto out;
+       stat_inc_cp_call_count(sbi, TOTAL_CALL);
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-support-file-pinning-for-zoned-devices.patch b/queue-6.6/f2fs-support-file-pinning-for-zoned-devices.patch
new file mode 100644 (file)
index 0000000..85a1fb7
--- /dev/null
@@ -0,0 +1,472 @@
+From 01660f99fd3ecf76b21b8c2db069abda71d6f715 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 09:38:12 -0800
+Subject: f2fs: support file pinning for zoned devices
+
+From: Daeho Jeong <daehojeong@google.com>
+
+[ Upstream commit 9703d69d9d153bb230711d0d577454552aeb13d4 ]
+
+Support file pinning with conventional storage area for zoned devices
+
+Signed-off-by: Daeho Jeong <daehojeong@google.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/data.c    | 58 ++++++++++++++++++++++++++-------------
+ fs/f2fs/f2fs.h    | 17 +++++++++++-
+ fs/f2fs/file.c    | 24 ++++++++++++-----
+ fs/f2fs/gc.c      | 14 +++++++---
+ fs/f2fs/segment.c | 69 +++++++++++++++++++++++++++++++++++++++++------
+ fs/f2fs/segment.h | 10 +++++++
+ 6 files changed, 154 insertions(+), 38 deletions(-)
+
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index 5d6ba12e84482..3558fc3387f54 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -3905,25 +3905,34 @@ static int f2fs_migrate_blocks(struct inode *inode, block_t start_blk,
+       unsigned int blkofs;
+       unsigned int blk_per_sec = BLKS_PER_SEC(sbi);
+       unsigned int secidx = start_blk / blk_per_sec;
+-      unsigned int end_sec = secidx + blkcnt / blk_per_sec;
++      unsigned int end_sec;
+       int ret = 0;
++      if (!blkcnt)
++              return 0;
++      end_sec = secidx + (blkcnt - 1) / blk_per_sec;
++
+       f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+       filemap_invalidate_lock(inode->i_mapping);
+       set_inode_flag(inode, FI_ALIGNED_WRITE);
+       set_inode_flag(inode, FI_OPU_WRITE);
+-      for (; secidx < end_sec; secidx++) {
++      for (; secidx <= end_sec; secidx++) {
++              unsigned int blkofs_end = secidx == end_sec ?
++                      (blkcnt - 1) % blk_per_sec : blk_per_sec - 1;
++
+               f2fs_down_write(&sbi->pin_sem);
+-              f2fs_lock_op(sbi);
+-              f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
+-              f2fs_unlock_op(sbi);
++              ret = f2fs_allocate_pinning_section(sbi);
++              if (ret) {
++                      f2fs_up_write(&sbi->pin_sem);
++                      break;
++              }
+               set_inode_flag(inode, FI_SKIP_WRITES);
+-              for (blkofs = 0; blkofs < blk_per_sec; blkofs++) {
++              for (blkofs = 0; blkofs <= blkofs_end; blkofs++) {
+                       struct page *page;
+                       unsigned int blkidx = secidx * blk_per_sec + blkofs;
+@@ -4012,27 +4021,34 @@ static int check_swap_activate(struct swap_info_struct *sis,
+               nr_pblocks = map.m_len;
+               if ((pblock - SM_I(sbi)->main_blkaddr) & sec_blks_mask ||
+-                              nr_pblocks & sec_blks_mask) {
++                              nr_pblocks & sec_blks_mask ||
++                              !f2fs_valid_pinned_area(sbi, pblock)) {
++                      bool last_extent = false;
++
+                       not_aligned++;
+                       nr_pblocks = roundup(nr_pblocks, blks_per_sec);
+                       if (cur_lblock + nr_pblocks > sis->max)
+                               nr_pblocks -= blks_per_sec;
++                      /* this extent is last one */
+                       if (!nr_pblocks) {
+-                              /* this extent is last one */
+-                              nr_pblocks = map.m_len;
+-                              f2fs_warn(sbi, "Swapfile: last extent is not aligned to section");
+-                              goto next;
++                              nr_pblocks = last_lblock - cur_lblock;
++                              last_extent = true;
+                       }
+                       ret = f2fs_migrate_blocks(inode, cur_lblock,
+                                                       nr_pblocks);
+-                      if (ret)
++                      if (ret) {
++                              if (ret == -ENOENT)
++                                      ret = -EINVAL;
+                               goto out;
+-                      goto retry;
++                      }
++
++                      if (!last_extent)
++                              goto retry;
+               }
+-next:
++
+               if (cur_lblock + nr_pblocks >= sis->max)
+                       nr_pblocks = sis->max - cur_lblock;
+@@ -4070,17 +4086,17 @@ static int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file,
+                               sector_t *span)
+ {
+       struct inode *inode = file_inode(file);
++      struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       int ret;
+       if (!S_ISREG(inode->i_mode))
+               return -EINVAL;
+-      if (f2fs_readonly(F2FS_I_SB(inode)->sb))
++      if (f2fs_readonly(sbi->sb))
+               return -EROFS;
+-      if (f2fs_lfs_mode(F2FS_I_SB(inode))) {
+-              f2fs_err(F2FS_I_SB(inode),
+-                      "Swapfile not supported in LFS mode");
++      if (f2fs_lfs_mode(sbi) && !f2fs_sb_has_blkzoned(sbi)) {
++              f2fs_err(sbi, "Swapfile not supported in LFS mode");
+               return -EINVAL;
+       }
+@@ -4093,13 +4109,17 @@ static int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file,
+       f2fs_precache_extents(inode);
++      ret = filemap_fdatawrite(inode->i_mapping);
++      if (ret < 0)
++              return ret;
++
+       ret = check_swap_activate(sis, file, span);
+       if (ret < 0)
+               return ret;
+       stat_inc_swapfile_inode(inode);
+       set_inode_flag(inode, FI_PIN_FILE);
+-      f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
++      f2fs_update_time(sbi, REQ_TIME);
+       return ret;
+ }
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index 9b80ceaf39502..82f54ffde4cd4 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -3704,7 +3704,8 @@ void f2fs_get_new_segment(struct f2fs_sb_info *sbi,
+                       unsigned int *newseg, bool new_sec, int dir);
+ void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
+                                       unsigned int start, unsigned int end);
+-void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force);
++int f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force);
++int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi);
+ void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi);
+ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range);
+ bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi,
+@@ -3880,6 +3881,9 @@ void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi);
+ block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode);
+ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control);
+ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi);
++int f2fs_gc_range(struct f2fs_sb_info *sbi,
++              unsigned int start_seg, unsigned int end_seg,
++              bool dry_run, unsigned int dry_run_sections);
+ int f2fs_resize_fs(struct file *filp, __u64 block_count);
+ int __init f2fs_create_garbage_collection_cache(void);
+ void f2fs_destroy_garbage_collection_cache(void);
+@@ -4536,6 +4540,17 @@ static inline bool f2fs_lfs_mode(struct f2fs_sb_info *sbi)
+       return F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS;
+ }
++static inline bool f2fs_valid_pinned_area(struct f2fs_sb_info *sbi,
++                                        block_t blkaddr)
++{
++      if (f2fs_sb_has_blkzoned(sbi)) {
++              int devi = f2fs_target_device_index(sbi, blkaddr);
++
++              return !bdev_is_zoned(FDEV(devi).bdev);
++      }
++      return true;
++}
++
+ static inline bool f2fs_low_mem_mode(struct f2fs_sb_info *sbi)
+ {
+       return F2FS_OPTION(sbi).memory_mode == MEMORY_MODE_LOW;
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index 2671a61556951..20dc11b58bb69 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -1729,9 +1729,11 @@ static int f2fs_expand_inode_data(struct inode *inode, loff_t offset,
+               f2fs_down_write(&sbi->pin_sem);
+-              f2fs_lock_op(sbi);
+-              f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
+-              f2fs_unlock_op(sbi);
++              err = f2fs_allocate_pinning_section(sbi);
++              if (err) {
++                      f2fs_up_write(&sbi->pin_sem);
++                      goto out_err;
++              }
+               map.m_seg_type = CURSEG_COLD_DATA_PINNED;
+               err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_PRE_DIO);
+@@ -3184,6 +3186,7 @@ int f2fs_pin_file_control(struct inode *inode, bool inc)
+ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
+ {
+       struct inode *inode = file_inode(filp);
++      struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       __u32 pin;
+       int ret = 0;
+@@ -3193,7 +3196,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
+       if (!S_ISREG(inode->i_mode))
+               return -EINVAL;
+-      if (f2fs_readonly(F2FS_I_SB(inode)->sb))
++      if (f2fs_readonly(sbi->sb))
+               return -EROFS;
+       ret = mnt_want_write_file(filp);
+@@ -3206,9 +3209,18 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
+               clear_inode_flag(inode, FI_PIN_FILE);
+               f2fs_i_gc_failures_write(inode, 0);
+               goto done;
++      } else if (f2fs_is_pinned_file(inode)) {
++              goto done;
+       }
+-      if (f2fs_should_update_outplace(inode, NULL)) {
++      if (f2fs_sb_has_blkzoned(sbi) && F2FS_HAS_BLOCKS(inode)) {
++              ret = -EFBIG;
++              goto out;
++      }
++
++      /* Let's allow file pinning on zoned device. */
++      if (!f2fs_sb_has_blkzoned(sbi) &&
++          f2fs_should_update_outplace(inode, NULL)) {
+               ret = -EINVAL;
+               goto out;
+       }
+@@ -3230,7 +3242,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
+       set_inode_flag(inode, FI_PIN_FILE);
+       ret = F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN];
+ done:
+-      f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
++      f2fs_update_time(sbi, REQ_TIME);
+ out:
+       inode_unlock(inode);
+       mnt_drop_write_file(filp);
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+index 2a3d64f4253ee..9a4ec639e58a7 100644
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -1979,10 +1979,12 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
+       init_atgc_management(sbi);
+ }
+-static int f2fs_gc_range(struct f2fs_sb_info *sbi,
+-              unsigned int start_seg, unsigned int end_seg, bool dry_run)
++int f2fs_gc_range(struct f2fs_sb_info *sbi,
++              unsigned int start_seg, unsigned int end_seg,
++              bool dry_run, unsigned int dry_run_sections)
+ {
+       unsigned int segno;
++      unsigned int gc_secs = dry_run_sections;
+       for (segno = start_seg; segno <= end_seg; segno += SEGS_PER_SEC(sbi)) {
+               struct gc_inode_list gc_list = {
+@@ -1990,11 +1992,15 @@ static int f2fs_gc_range(struct f2fs_sb_info *sbi,
+                       .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
+               };
+-              do_garbage_collect(sbi, segno, &gc_list, FG_GC, true);
++              do_garbage_collect(sbi, segno, &gc_list, FG_GC,
++                                              dry_run_sections == 0);
+               put_gc_inode(&gc_list);
+               if (!dry_run && get_valid_blocks(sbi, segno, true))
+                       return -EAGAIN;
++              if (dry_run && dry_run_sections &&
++                  !get_valid_blocks(sbi, segno, true) && --gc_secs == 0)
++                      break;
+               if (fatal_signal_pending(current))
+                       return -ERESTARTSYS;
+@@ -2032,7 +2038,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
+               f2fs_allocate_segment_for_resize(sbi, type, start, end);
+       /* do GC to move out valid blocks in the range */
+-      err = f2fs_gc_range(sbi, start, end, dry_run);
++      err = f2fs_gc_range(sbi, start, end, dry_run, 0);
+       if (err || dry_run)
+               goto out;
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 523c3a91bdf21..52b281e9f472f 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -2638,7 +2638,7 @@ static int is_next_segment_free(struct f2fs_sb_info *sbi,
+  * This function should be returned with success, otherwise BUG
+  */
+ static void get_new_segment(struct f2fs_sb_info *sbi,
+-                      unsigned int *newseg, bool new_sec)
++                      unsigned int *newseg, bool new_sec, bool pinning)
+ {
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int segno, secno, zoneno;
+@@ -2656,6 +2656,16 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
+               if (segno < GET_SEG_FROM_SEC(sbi, hint + 1))
+                       goto got_it;
+       }
++
++      /*
++       * If we format f2fs on zoned storage, let's try to get pinned sections
++       * from beginning of the storage, which should be a conventional one.
++       */
++      if (f2fs_sb_has_blkzoned(sbi)) {
++              segno = pinning ? 0 : max(first_zoned_segno(sbi), *newseg);
++              hint = GET_SEC_FROM_SEG(sbi, segno);
++      }
++
+ find_other_zone:
+       secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
+       if (secno >= MAIN_SECS(sbi)) {
+@@ -2754,21 +2764,30 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
+  * Allocate a current working segment.
+  * This function always allocates a free segment in LFS manner.
+  */
+-static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
++static int new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
+ {
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       unsigned int segno = curseg->segno;
++      bool pinning = type == CURSEG_COLD_DATA_PINNED;
+       if (curseg->inited)
+               write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno));
++
+       segno = __get_next_segno(sbi, type);
+-      get_new_segment(sbi, &segno, new_sec);
++      get_new_segment(sbi, &segno, new_sec, pinning);
++      if (new_sec && pinning &&
++          !f2fs_valid_pinned_area(sbi, START_BLOCK(sbi, segno))) {
++              __set_free(sbi, segno);
++              return -EAGAIN;
++      }
++
+       curseg->next_segno = segno;
+       reset_curseg(sbi, type, 1);
+       curseg->alloc_type = LFS;
+       if (F2FS_OPTION(sbi).fs_mode == FS_MODE_FRAGMENT_BLK)
+               curseg->fragment_remained_chunk =
+                               get_random_u32_inclusive(1, sbi->max_fragment_chunk);
++      return 0;
+ }
+ static int __next_free_blkoff(struct f2fs_sb_info *sbi,
+@@ -3041,7 +3060,7 @@ void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
+       f2fs_up_read(&SM_I(sbi)->curseg_lock);
+ }
+-static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type,
++static int __allocate_new_segment(struct f2fs_sb_info *sbi, int type,
+                                               bool new_sec, bool force)
+ {
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+@@ -3051,21 +3070,49 @@ static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type,
+           !curseg->next_blkoff &&
+           !get_valid_blocks(sbi, curseg->segno, new_sec) &&
+           !get_ckpt_valid_blocks(sbi, curseg->segno, new_sec))
+-              return;
++              return 0;
+       old_segno = curseg->segno;
+-      new_curseg(sbi, type, true);
++      if (new_curseg(sbi, type, true))
++              return -EAGAIN;
+       stat_inc_seg_type(sbi, curseg);
+       locate_dirty_segment(sbi, old_segno);
++      return 0;
+ }
+-void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force)
++int f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force)
+ {
++      int ret;
++
+       f2fs_down_read(&SM_I(sbi)->curseg_lock);
+       down_write(&SIT_I(sbi)->sentry_lock);
+-      __allocate_new_segment(sbi, type, true, force);
++      ret = __allocate_new_segment(sbi, type, true, force);
+       up_write(&SIT_I(sbi)->sentry_lock);
+       f2fs_up_read(&SM_I(sbi)->curseg_lock);
++
++      return ret;
++}
++
++int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi)
++{
++      int err;
++      bool gc_required = true;
++
++retry:
++      f2fs_lock_op(sbi);
++      err = f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
++      f2fs_unlock_op(sbi);
++
++      if (f2fs_sb_has_blkzoned(sbi) && err && gc_required) {
++              f2fs_down_write(&sbi->gc_lock);
++              f2fs_gc_range(sbi, 0, GET_SEGNO(sbi, FDEV(0).end_blk), true, 1);
++              f2fs_up_write(&sbi->gc_lock);
++
++              gc_required = false;
++              goto retry;
++      }
++
++      return err;
+ }
+ void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi)
+@@ -3431,6 +3478,10 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
+        * new segment.
+        */
+       if (segment_full) {
++              if (type == CURSEG_COLD_DATA_PINNED &&
++                  !((curseg->segno + 1) % sbi->segs_per_sec))
++                      goto skip_new_segment;
++
+               if (from_gc) {
+                       get_atssr_segment(sbi, type, se->type,
+                                               AT_SSR, se->mtime);
+@@ -3442,6 +3493,8 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
+                       stat_inc_seg_type(sbi, curseg);
+               }
+       }
++
++skip_new_segment:
+       /*
+        * segment dirty status should be updated after segment allocation,
+        * so we just need to update status only one time after previous
+diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
+index 93ffb62e45f4d..4595f1cc03828 100644
+--- a/fs/f2fs/segment.h
++++ b/fs/f2fs/segment.h
+@@ -956,3 +956,13 @@ static inline void wake_up_discard_thread(struct f2fs_sb_info *sbi, bool force)
+       dcc->discard_wake = true;
+       wake_up_interruptible_all(&dcc->discard_wait_queue);
+ }
++
++static inline unsigned int first_zoned_segno(struct f2fs_sb_info *sbi)
++{
++      int devi;
++
++      for (devi = 0; devi < sbi->s_ndevs; devi++)
++              if (bdev_is_zoned(FDEV(devi).bdev))
++                      return GET_SEGNO(sbi, FDEV(devi).start_blk);
++      return 0;
++}
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-support-printk_ratelimited-in-f2fs_printk.patch b/queue-6.6/f2fs-support-printk_ratelimited-in-f2fs_printk.patch
new file mode 100644 (file)
index 0000000..e93c66c
--- /dev/null
@@ -0,0 +1,165 @@
+From 2355d2363e9d0c799cb42049661c3c8566c42b37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jan 2024 23:19:16 +0800
+Subject: f2fs: support printk_ratelimited() in f2fs_printk()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit b1c9d3f833ba60a288db111d7fe38edfeb9b8fbb ]
+
+This patch supports using printk_ratelimited() in f2fs_printk(), and
+wrap ratelimited f2fs_printk() into f2fs_{err,warn,info}_ratelimited(),
+then, use these new helps to clean up codes.
+
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/compress.c | 10 +++++-----
+ fs/f2fs/dir.c      |  5 ++---
+ fs/f2fs/f2fs.h     | 40 +++++++++++++++++++++++-----------------
+ fs/f2fs/super.c    | 11 ++++++++---
+ 4 files changed, 38 insertions(+), 28 deletions(-)
+
+diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
+index a7037644b9324..814b570cdf2e7 100644
+--- a/fs/f2fs/compress.c
++++ b/fs/f2fs/compress.c
+@@ -512,8 +512,8 @@ static int lzorle_compress_pages(struct compress_ctx *cc)
+       ret = lzorle1x_1_compress(cc->rbuf, cc->rlen, cc->cbuf->cdata,
+                                       &cc->clen, cc->private);
+       if (ret != LZO_E_OK) {
+-              printk_ratelimited("%sF2FS-fs (%s): lzo-rle compress failed, ret:%d\n",
+-                              KERN_ERR, F2FS_I_SB(cc->inode)->sb->s_id, ret);
++              f2fs_err_ratelimited(F2FS_I_SB(cc->inode),
++                              "lzo-rle compress failed, ret:%d", ret);
+               return -EIO;
+       }
+       return 0;
+@@ -780,9 +780,9 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic, bool in_task)
+               if (provided != calculated) {
+                       if (!is_inode_flag_set(dic->inode, FI_COMPRESS_CORRUPT)) {
+                               set_inode_flag(dic->inode, FI_COMPRESS_CORRUPT);
+-                              printk_ratelimited(
+-                                      "%sF2FS-fs (%s): checksum invalid, nid = %lu, %x vs %x",
+-                                      KERN_INFO, sbi->sb->s_id, dic->inode->i_ino,
++                              f2fs_info_ratelimited(sbi,
++                                      "checksum invalid, nid = %lu, %x vs %x",
++                                      dic->inode->i_ino,
+                                       provided, calculated);
+                       }
+                       set_sbi_flag(sbi, SBI_NEED_FSCK);
+diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
+index e792d35304796..c624ffff6f19a 100644
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -996,9 +996,8 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
+               de = &d->dentry[bit_pos];
+               if (de->name_len == 0) {
+                       if (found_valid_dirent || !bit_pos) {
+-                              printk_ratelimited(
+-                                      "%sF2FS-fs (%s): invalid namelen(0), ino:%u, run fsck to fix.",
+-                                      KERN_WARNING, sbi->sb->s_id,
++                              f2fs_warn_ratelimited(sbi,
++                                      "invalid namelen(0), ino:%u, run fsck to fix.",
+                                       le32_to_cpu(de->ino));
+                               set_sbi_flag(sbi, SBI_NEED_FSCK);
+                       }
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index f37907f015873..9e8a3d0db11db 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -1808,6 +1808,27 @@ struct f2fs_sb_info {
+ #endif
+ };
++__printf(3, 4)
++void f2fs_printk(struct f2fs_sb_info *sbi, bool limit_rate, const char *fmt, ...);
++
++#define f2fs_err(sbi, fmt, ...)                                               \
++      f2fs_printk(sbi, false, KERN_ERR fmt, ##__VA_ARGS__)
++#define f2fs_warn(sbi, fmt, ...)                                      \
++      f2fs_printk(sbi, false, KERN_WARNING fmt, ##__VA_ARGS__)
++#define f2fs_notice(sbi, fmt, ...)                                    \
++      f2fs_printk(sbi, false, KERN_NOTICE fmt, ##__VA_ARGS__)
++#define f2fs_info(sbi, fmt, ...)                                      \
++      f2fs_printk(sbi, false, KERN_INFO fmt, ##__VA_ARGS__)
++#define f2fs_debug(sbi, fmt, ...)                                     \
++      f2fs_printk(sbi, false, KERN_DEBUG fmt, ##__VA_ARGS__)
++
++#define f2fs_err_ratelimited(sbi, fmt, ...)                           \
++      f2fs_printk(sbi, true, KERN_ERR fmt, ##__VA_ARGS__)
++#define f2fs_warn_ratelimited(sbi, fmt, ...)                          \
++      f2fs_printk(sbi, true, KERN_WARNING fmt, ##__VA_ARGS__)
++#define f2fs_info_ratelimited(sbi, fmt, ...)                          \
++      f2fs_printk(sbi, true, KERN_INFO fmt, ##__VA_ARGS__)
++
+ #ifdef CONFIG_F2FS_FAULT_INJECTION
+ #define time_to_inject(sbi, type) __time_to_inject(sbi, type, __func__,       \
+                                                                       __builtin_return_address(0))
+@@ -1825,9 +1846,8 @@ static inline bool __time_to_inject(struct f2fs_sb_info *sbi, int type,
+       atomic_inc(&ffi->inject_ops);
+       if (atomic_read(&ffi->inject_ops) >= ffi->inject_rate) {
+               atomic_set(&ffi->inject_ops, 0);
+-              printk_ratelimited("%sF2FS-fs (%s) : inject %s in %s of %pS\n",
+-                      KERN_INFO, sbi->sb->s_id, f2fs_fault_name[type],
+-                      func, parent_func);
++              f2fs_info_ratelimited(sbi, "inject %s in %s of %pS",
++                              f2fs_fault_name[type], func, parent_func);
+               return true;
+       }
+       return false;
+@@ -2321,20 +2341,6 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
+       return -ENOSPC;
+ }
+-__printf(2, 3)
+-void f2fs_printk(struct f2fs_sb_info *sbi, const char *fmt, ...);
+-
+-#define f2fs_err(sbi, fmt, ...)                                               \
+-      f2fs_printk(sbi, KERN_ERR fmt, ##__VA_ARGS__)
+-#define f2fs_warn(sbi, fmt, ...)                                      \
+-      f2fs_printk(sbi, KERN_WARNING fmt, ##__VA_ARGS__)
+-#define f2fs_notice(sbi, fmt, ...)                                    \
+-      f2fs_printk(sbi, KERN_NOTICE fmt, ##__VA_ARGS__)
+-#define f2fs_info(sbi, fmt, ...)                                      \
+-      f2fs_printk(sbi, KERN_INFO fmt, ##__VA_ARGS__)
+-#define f2fs_debug(sbi, fmt, ...)                                     \
+-      f2fs_printk(sbi, KERN_DEBUG fmt, ##__VA_ARGS__)
+-
+ #define PAGE_PRIVATE_GET_FUNC(name, flagname) \
+ static inline bool page_private_##name(struct page *page) \
+ { \
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index ab437022ea56f..5fdb75b74cf80 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -248,7 +248,8 @@ static match_table_t f2fs_tokens = {
+       {Opt_err, NULL},
+ };
+-void f2fs_printk(struct f2fs_sb_info *sbi, const char *fmt, ...)
++void f2fs_printk(struct f2fs_sb_info *sbi, bool limit_rate,
++                                              const char *fmt, ...)
+ {
+       struct va_format vaf;
+       va_list args;
+@@ -259,8 +260,12 @@ void f2fs_printk(struct f2fs_sb_info *sbi, const char *fmt, ...)
+       level = printk_get_level(fmt);
+       vaf.fmt = printk_skip_level(fmt);
+       vaf.va = &args;
+-      printk("%c%cF2FS-fs (%s): %pV\n",
+-             KERN_SOH_ASCII, level, sbi->sb->s_id, &vaf);
++      if (limit_rate)
++              printk_ratelimited("%c%cF2FS-fs (%s): %pV\n",
++                      KERN_SOH_ASCII, level, sbi->sb->s_id, &vaf);
++      else
++              printk("%c%cF2FS-fs (%s): %pV\n",
++                      KERN_SOH_ASCII, level, sbi->sb->s_id, &vaf);
+       va_end(args);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-use-blks_per_seg-blks_per_sec-and-segs_per_sec.patch b/queue-6.6/f2fs-use-blks_per_seg-blks_per_sec-and-segs_per_sec.patch
new file mode 100644 (file)
index 0000000..60c307e
--- /dev/null
@@ -0,0 +1,982 @@
+From 79bec982bab2fb9b8cee04071c4e8911d06c8a05 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Feb 2024 13:56:27 -0800
+Subject: f2fs: use BLKS_PER_SEG, BLKS_PER_SEC, and SEGS_PER_SEC
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+[ Upstream commit a60108f7dfb5867da1ad9c777d2fbbe47e4dbdd7 ]
+
+No functional change.
+
+Reviewed-by: Daeho Jeong <daehojeong@google.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/checkpoint.c |  10 ++--
+ fs/f2fs/debug.c      |   6 +--
+ fs/f2fs/f2fs.h       |  21 +++++----
+ fs/f2fs/file.c       |  16 +++----
+ fs/f2fs/gc.c         |  40 ++++++++--------
+ fs/f2fs/node.c       |   4 +-
+ fs/f2fs/node.h       |   4 +-
+ fs/f2fs/recovery.c   |   2 +-
+ fs/f2fs/segment.c    | 110 +++++++++++++++++++++----------------------
+ fs/f2fs/segment.h    |  44 +++++++++--------
+ fs/f2fs/super.c      |   8 ++--
+ fs/f2fs/sysfs.c      |   6 +--
+ 12 files changed, 135 insertions(+), 136 deletions(-)
+
+diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
+index 9afc8d24dc369..58ce751da92bf 100644
+--- a/fs/f2fs/checkpoint.c
++++ b/fs/f2fs/checkpoint.c
+@@ -889,7 +889,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
+       cp_blocks = le32_to_cpu(cp_block->cp_pack_total_block_count);
+-      if (cp_blocks > sbi->blocks_per_seg || cp_blocks <= F2FS_CP_PACKS) {
++      if (cp_blocks > BLKS_PER_SEG(sbi) || cp_blocks <= F2FS_CP_PACKS) {
+               f2fs_warn(sbi, "invalid cp_pack_total_block_count:%u",
+                         le32_to_cpu(cp_block->cp_pack_total_block_count));
+               goto invalid_cp;
+@@ -1324,7 +1324,7 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+       if (cpc->reason & CP_UMOUNT) {
+               if (le32_to_cpu(ckpt->cp_pack_total_block_count) +
+-                      NM_I(sbi)->nat_bits_blocks > sbi->blocks_per_seg) {
++                      NM_I(sbi)->nat_bits_blocks > BLKS_PER_SEG(sbi)) {
+                       clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
+                       f2fs_notice(sbi, "Disable nat_bits due to no space");
+               } else if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG) &&
+@@ -1527,7 +1527,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+               cp_ver |= ((__u64)crc32 << 32);
+               *(__le64 *)nm_i->nat_bits = cpu_to_le64(cp_ver);
+-              blk = start_blk + sbi->blocks_per_seg - nm_i->nat_bits_blocks;
++              blk = start_blk + BLKS_PER_SEG(sbi) - nm_i->nat_bits_blocks;
+               for (i = 0; i < nm_i->nat_bits_blocks; i++)
+                       f2fs_update_meta_page(sbi, nm_i->nat_bits +
+                                       (i << F2FS_BLKSIZE_BITS), blk + i);
+@@ -1731,9 +1731,9 @@ void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi)
+               im->ino_num = 0;
+       }
+-      sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS -
++      sbi->max_orphans = (BLKS_PER_SEG(sbi) - F2FS_CP_PACKS -
+                       NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) *
+-                              F2FS_ORPHANS_PER_BLOCK;
++                      F2FS_ORPHANS_PER_BLOCK;
+ }
+ int __init f2fs_create_checkpoint_caches(void)
+diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
+index fdbf994f12718..0d02224b99b72 100644
+--- a/fs/f2fs/debug.c
++++ b/fs/f2fs/debug.c
+@@ -41,7 +41,7 @@ void f2fs_update_sit_info(struct f2fs_sb_info *sbi)
+       total_vblocks = 0;
+       blks_per_sec = CAP_BLKS_PER_SEC(sbi);
+       hblks_per_sec = blks_per_sec / 2;
+-      for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
++      for (segno = 0; segno < MAIN_SEGS(sbi); segno += SEGS_PER_SEC(sbi)) {
+               vblocks = get_valid_blocks(sbi, segno, true);
+               dist = abs(vblocks - hblks_per_sec);
+               bimodal += dist * dist;
+@@ -135,7 +135,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
+       si->cur_ckpt_time = sbi->cprc_info.cur_time;
+       si->peak_ckpt_time = sbi->cprc_info.peak_time;
+       spin_unlock(&sbi->cprc_info.stat_lock);
+-      si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
++      si->total_count = (int)sbi->user_block_count / BLKS_PER_SEG(sbi);
+       si->rsvd_segs = reserved_segments(sbi);
+       si->overp_segs = overprovision_segments(sbi);
+       si->valid_count = valid_user_blocks(sbi);
+@@ -208,7 +208,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
+               if (!blks)
+                       continue;
+-              if (blks == sbi->blocks_per_seg)
++              if (blks == BLKS_PER_SEG(sbi))
+                       si->full_seg[type]++;
+               else
+                       si->dirty_seg[type]++;
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index 9e8a3d0db11db..9b80ceaf39502 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -1808,6 +1808,14 @@ struct f2fs_sb_info {
+ #endif
+ };
++/* Definitions to access f2fs_sb_info */
++#define BLKS_PER_SEG(sbi)                                     \
++      ((sbi)->blocks_per_seg)
++#define BLKS_PER_SEC(sbi)                                     \
++      ((sbi)->segs_per_sec << (sbi)->log_blocks_per_seg)
++#define SEGS_PER_SEC(sbi)                                     \
++      ((sbi)->segs_per_sec)
++
+ __printf(3, 4)
+ void f2fs_printk(struct f2fs_sb_info *sbi, bool limit_rate, const char *fmt, ...);
+@@ -2513,11 +2521,8 @@ static inline int get_dirty_pages(struct inode *inode)
+ static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
+ {
+-      unsigned int pages_per_sec = sbi->segs_per_sec * sbi->blocks_per_seg;
+-      unsigned int segs = (get_pages(sbi, block_type) + pages_per_sec - 1) >>
+-                                              sbi->log_blocks_per_seg;
+-
+-      return segs / sbi->segs_per_sec;
++      return div_u64(get_pages(sbi, block_type) + BLKS_PER_SEC(sbi) - 1,
++                                                      BLKS_PER_SEC(sbi));
+ }
+ static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
+@@ -2581,7 +2586,7 @@ static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
+       block_t start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);
+       if (sbi->cur_cp_pack == 2)
+-              start_addr += sbi->blocks_per_seg;
++              start_addr += BLKS_PER_SEG(sbi);
+       return start_addr;
+ }
+@@ -2590,7 +2595,7 @@ static inline block_t __start_cp_next_addr(struct f2fs_sb_info *sbi)
+       block_t start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);
+       if (sbi->cur_cp_pack == 1)
+-              start_addr += sbi->blocks_per_seg;
++              start_addr += BLKS_PER_SEG(sbi);
+       return start_addr;
+ }
+@@ -3463,7 +3468,7 @@ static inline __le32 *get_dnode_addr(struct inode *inode,
+               sizeof((f2fs_inode)->field))                    \
+               <= (F2FS_OLD_ATTRIBUTE_SIZE + (extra_isize)))   \
+-#define __is_large_section(sbi)               ((sbi)->segs_per_sec > 1)
++#define __is_large_section(sbi)               (SEGS_PER_SEC(sbi) > 1)
+ #define __is_meta_io(fio) (PAGE_TYPE_OF_BIO((fio)->type) == META)
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index 5c24d18f4e297..2671a61556951 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -2578,7 +2578,6 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
+                                       .m_may_create = false };
+       struct extent_info ei = {};
+       pgoff_t pg_start, pg_end, next_pgofs;
+-      unsigned int blk_per_seg = sbi->blocks_per_seg;
+       unsigned int total = 0, sec_num;
+       block_t blk_end = 0;
+       bool fragmented = false;
+@@ -2687,7 +2686,8 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
+               set_inode_flag(inode, FI_SKIP_WRITES);
+               idx = map.m_lblk;
+-              while (idx < map.m_lblk + map.m_len && cnt < blk_per_seg) {
++              while (idx < map.m_lblk + map.m_len &&
++                                              cnt < BLKS_PER_SEG(sbi)) {
+                       struct page *page;
+                       page = f2fs_get_lock_data_page(inode, idx, true);
+@@ -2707,7 +2707,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
+               map.m_lblk = idx;
+ check:
+-              if (map.m_lblk < pg_end && cnt < blk_per_seg)
++              if (map.m_lblk < pg_end && cnt < BLKS_PER_SEG(sbi))
+                       goto do_map;
+               clear_inode_flag(inode, FI_SKIP_WRITES);
+@@ -2977,8 +2977,8 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg)
+       if (!f2fs_is_multi_device(sbi) || sbi->s_ndevs - 1 <= range.dev_num ||
+                       __is_large_section(sbi)) {
+-              f2fs_warn(sbi, "Can't flush %u in %d for segs_per_sec %u != 1",
+-                        range.dev_num, sbi->s_ndevs, sbi->segs_per_sec);
++              f2fs_warn(sbi, "Can't flush %u in %d for SEGS_PER_SEC %u != 1",
++                        range.dev_num, sbi->s_ndevs, SEGS_PER_SEC(sbi));
+               return -EINVAL;
+       }
+@@ -4078,7 +4078,6 @@ static int f2fs_ioc_decompress_file(struct file *filp)
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       pgoff_t page_idx = 0, last_idx;
+-      unsigned int blk_per_seg = sbi->blocks_per_seg;
+       int cluster_size = fi->i_cluster_size;
+       int count, ret;
+@@ -4120,7 +4119,7 @@ static int f2fs_ioc_decompress_file(struct file *filp)
+               if (ret < 0)
+                       break;
+-              if (get_dirty_pages(inode) >= blk_per_seg) {
++              if (get_dirty_pages(inode) >= BLKS_PER_SEG(sbi)) {
+                       ret = filemap_fdatawrite(inode->i_mapping);
+                       if (ret < 0)
+                               break;
+@@ -4155,7 +4154,6 @@ static int f2fs_ioc_compress_file(struct file *filp)
+       struct inode *inode = file_inode(filp);
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       pgoff_t page_idx = 0, last_idx;
+-      unsigned int blk_per_seg = sbi->blocks_per_seg;
+       int cluster_size = F2FS_I(inode)->i_cluster_size;
+       int count, ret;
+@@ -4196,7 +4194,7 @@ static int f2fs_ioc_compress_file(struct file *filp)
+               if (ret < 0)
+                       break;
+-              if (get_dirty_pages(inode) >= blk_per_seg) {
++              if (get_dirty_pages(inode) >= BLKS_PER_SEG(sbi)) {
+                       ret = filemap_fdatawrite(inode->i_mapping);
+                       if (ret < 0)
+                               break;
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+index 405a6077bd83b..9c150b2dd9ec2 100644
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -259,7 +259,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
+               p->ofs_unit = 1;
+       } else {
+               p->gc_mode = select_gc_type(sbi, gc_type);
+-              p->ofs_unit = sbi->segs_per_sec;
++              p->ofs_unit = SEGS_PER_SEC(sbi);
+               if (__is_large_section(sbi)) {
+                       p->dirty_bitmap = dirty_i->dirty_secmap;
+                       p->max_search = count_bits(p->dirty_bitmap,
+@@ -282,7 +282,8 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
+       /* let's select beginning hot/small space first in no_heap mode*/
+       if (f2fs_need_rand_seg(sbi))
+-              p->offset = get_random_u32_below(MAIN_SECS(sbi) * sbi->segs_per_sec);
++              p->offset = get_random_u32_below(MAIN_SECS(sbi) *
++                                              SEGS_PER_SEC(sbi));
+       else if (test_opt(sbi, NOHEAP) &&
+               (type == CURSEG_HOT_DATA || IS_NODESEG(type)))
+               p->offset = 0;
+@@ -295,13 +296,13 @@ static unsigned int get_max_cost(struct f2fs_sb_info *sbi,
+ {
+       /* SSR allocates in a segment unit */
+       if (p->alloc_mode == SSR)
+-              return sbi->blocks_per_seg;
++              return BLKS_PER_SEG(sbi);
+       else if (p->alloc_mode == AT_SSR)
+               return UINT_MAX;
+       /* LFS */
+       if (p->gc_mode == GC_GREEDY)
+-              return 2 * sbi->blocks_per_seg * p->ofs_unit;
++              return 2 * BLKS_PER_SEG(sbi) * p->ofs_unit;
+       else if (p->gc_mode == GC_CB)
+               return UINT_MAX;
+       else if (p->gc_mode == GC_AT)
+@@ -496,9 +497,9 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
+                       return;
+       }
+-      for (i = 0; i < sbi->segs_per_sec; i++)
++      for (i = 0; i < SEGS_PER_SEC(sbi); i++)
+               mtime += get_seg_entry(sbi, start + i)->mtime;
+-      mtime = div_u64(mtime, sbi->segs_per_sec);
++      mtime = div_u64(mtime, SEGS_PER_SEC(sbi));
+       /* Handle if the system time has changed by the user */
+       if (mtime < sit_i->min_mtime)
+@@ -599,7 +600,6 @@ static void atssr_lookup_victim(struct f2fs_sb_info *sbi,
+       unsigned long long age;
+       unsigned long long max_mtime = sit_i->dirty_max_mtime;
+       unsigned long long min_mtime = sit_i->dirty_min_mtime;
+-      unsigned int seg_blocks = sbi->blocks_per_seg;
+       unsigned int vblocks;
+       unsigned int dirty_threshold = max(am->max_candidate_count,
+                                       am->candidate_ratio *
+@@ -629,7 +629,7 @@ static void atssr_lookup_victim(struct f2fs_sb_info *sbi,
+       f2fs_bug_on(sbi, !vblocks);
+       /* rare case */
+-      if (vblocks == seg_blocks)
++      if (vblocks == BLKS_PER_SEG(sbi))
+               goto skip_node;
+       iter++;
+@@ -755,7 +755,7 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
+       int ret = 0;
+       mutex_lock(&dirty_i->seglist_lock);
+-      last_segment = MAIN_SECS(sbi) * sbi->segs_per_sec;
++      last_segment = MAIN_SECS(sbi) * SEGS_PER_SEC(sbi);
+       p.alloc_mode = alloc_mode;
+       p.age = age;
+@@ -896,7 +896,7 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
+                       else
+                               sm->last_victim[p.gc_mode] = segno + p.ofs_unit;
+                       sm->last_victim[p.gc_mode] %=
+-                              (MAIN_SECS(sbi) * sbi->segs_per_sec);
++                              (MAIN_SECS(sbi) * SEGS_PER_SEC(sbi));
+                       break;
+               }
+       }
+@@ -1678,7 +1678,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
+       struct f2fs_summary_block *sum;
+       struct blk_plug plug;
+       unsigned int segno = start_segno;
+-      unsigned int end_segno = start_segno + sbi->segs_per_sec;
++      unsigned int end_segno = start_segno + SEGS_PER_SEC(sbi);
+       int seg_freed = 0, migrated = 0;
+       unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ?
+                                               SUM_TYPE_DATA : SUM_TYPE_NODE;
+@@ -1686,7 +1686,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
+       int submitted = 0;
+       if (__is_large_section(sbi))
+-              end_segno = rounddown(end_segno, sbi->segs_per_sec);
++              end_segno = rounddown(end_segno, SEGS_PER_SEC(sbi));
+       /*
+        * zone-capacity can be less than zone-size in zoned devices,
+@@ -1694,7 +1694,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
+        * calculate the end segno in the zone which can be garbage collected
+        */
+       if (f2fs_sb_has_blkzoned(sbi))
+-              end_segno -= sbi->segs_per_sec -
++              end_segno -= SEGS_PER_SEC(sbi) -
+                                       f2fs_usable_segs_in_sec(sbi, segno);
+       sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type);
+@@ -1991,7 +1991,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
+       /* Force block allocation for GC */
+       MAIN_SECS(sbi) -= secs;
+-      start = MAIN_SECS(sbi) * sbi->segs_per_sec;
++      start = MAIN_SECS(sbi) * SEGS_PER_SEC(sbi);
+       end = MAIN_SEGS(sbi) - 1;
+       mutex_lock(&DIRTY_I(sbi)->seglist_lock);
+@@ -2009,7 +2009,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
+               f2fs_allocate_segment_for_resize(sbi, type, start, end);
+       /* do GC to move out valid blocks in the range */
+-      for (segno = start; segno <= end; segno += sbi->segs_per_sec) {
++      for (segno = start; segno <= end; segno += SEGS_PER_SEC(sbi)) {
+               struct gc_inode_list gc_list = {
+                       .ilist = LIST_HEAD_INIT(gc_list.ilist),
+                       .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
+@@ -2053,7 +2053,7 @@ static void update_sb_metadata(struct f2fs_sb_info *sbi, int secs)
+       int segment_count;
+       int segment_count_main;
+       long long block_count;
+-      int segs = secs * sbi->segs_per_sec;
++      int segs = secs * SEGS_PER_SEC(sbi);
+       f2fs_down_write(&sbi->sb_lock);
+@@ -2066,7 +2066,7 @@ static void update_sb_metadata(struct f2fs_sb_info *sbi, int secs)
+       raw_sb->segment_count = cpu_to_le32(segment_count + segs);
+       raw_sb->segment_count_main = cpu_to_le32(segment_count_main + segs);
+       raw_sb->block_count = cpu_to_le64(block_count +
+-                                      (long long)segs * sbi->blocks_per_seg);
++                      (long long)(segs << sbi->log_blocks_per_seg));
+       if (f2fs_is_multi_device(sbi)) {
+               int last_dev = sbi->s_ndevs - 1;
+               int dev_segs =
+@@ -2081,8 +2081,8 @@ static void update_sb_metadata(struct f2fs_sb_info *sbi, int secs)
+ static void update_fs_metadata(struct f2fs_sb_info *sbi, int secs)
+ {
+-      int segs = secs * sbi->segs_per_sec;
+-      long long blks = (long long)segs * sbi->blocks_per_seg;
++      int segs = secs * SEGS_PER_SEC(sbi);
++      long long blks = (long long)segs << sbi->log_blocks_per_seg;
+       long long user_block_count =
+                               le64_to_cpu(F2FS_CKPT(sbi)->user_block_count);
+@@ -2124,7 +2124,7 @@ int f2fs_resize_fs(struct file *filp, __u64 block_count)
+               int last_dev = sbi->s_ndevs - 1;
+               __u64 last_segs = FDEV(last_dev).total_segments;
+-              if (block_count + last_segs * sbi->blocks_per_seg <=
++              if (block_count + (last_segs << sbi->log_blocks_per_seg) <=
+                                                               old_block_count)
+                       return -EINVAL;
+       }
+diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
+index cdd890dbd5e34..ab113fd3a3432 100644
+--- a/fs/f2fs/node.c
++++ b/fs/f2fs/node.c
+@@ -2849,7 +2849,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
+       int i, idx, last_offset, nrpages;
+       /* scan the node segment */
+-      last_offset = sbi->blocks_per_seg;
++      last_offset = BLKS_PER_SEG(sbi);
+       addr = START_BLOCK(sbi, segno);
+       sum_entry = &sum->entries[0];
+@@ -3166,7 +3166,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
+       if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG))
+               return 0;
+-      nat_bits_addr = __start_cp_addr(sbi) + sbi->blocks_per_seg -
++      nat_bits_addr = __start_cp_addr(sbi) + BLKS_PER_SEG(sbi) -
+                                               nm_i->nat_bits_blocks;
+       for (i = 0; i < nm_i->nat_bits_blocks; i++) {
+               struct page *page;
+diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
+index 5bd16a95eef8f..6aea13024ac16 100644
+--- a/fs/f2fs/node.h
++++ b/fs/f2fs/node.h
+@@ -208,10 +208,10 @@ static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start)
+       block_addr = (pgoff_t)(nm_i->nat_blkaddr +
+               (block_off << 1) -
+-              (block_off & (sbi->blocks_per_seg - 1)));
++              (block_off & (BLKS_PER_SEG(sbi) - 1)));
+       if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
+-              block_addr += sbi->blocks_per_seg;
++              block_addr += BLKS_PER_SEG(sbi);
+       return block_addr;
+ }
+diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
+index 23077cdfde367..f8852aa526408 100644
+--- a/fs/f2fs/recovery.c
++++ b/fs/f2fs/recovery.c
+@@ -354,7 +354,7 @@ static unsigned int adjust_por_ra_blocks(struct f2fs_sb_info *sbi,
+       if (blkaddr + 1 == next_blkaddr)
+               ra_blocks = min_t(unsigned int, RECOVERY_MAX_RA_BLOCKS,
+                                                       ra_blocks * 2);
+-      else if (next_blkaddr % sbi->blocks_per_seg)
++      else if (next_blkaddr % BLKS_PER_SEG(sbi))
+               ra_blocks = max_t(unsigned int, RECOVERY_MIN_RA_BLOCKS,
+                                                       ra_blocks / 2);
+       return ra_blocks;
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 4549964819731..01e9366705b25 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -450,8 +450,8 @@ static inline bool excess_dirty_threshold(struct f2fs_sb_info *sbi)
+       unsigned int nodes = get_pages(sbi, F2FS_DIRTY_NODES);
+       unsigned int meta = get_pages(sbi, F2FS_DIRTY_META);
+       unsigned int imeta = get_pages(sbi, F2FS_DIRTY_IMETA);
+-      unsigned int threshold = sbi->blocks_per_seg * factor *
+-                                      DEFAULT_DIRTY_THRESHOLD;
++      unsigned int threshold = (factor * DEFAULT_DIRTY_THRESHOLD) <<
++                              sbi->log_blocks_per_seg;
+       unsigned int global_threshold = threshold * 3 / 2;
+       if (dents >= threshold || qdata >= threshold ||
+@@ -1134,8 +1134,7 @@ static void __check_sit_bitmap(struct f2fs_sb_info *sbi,
+       struct seg_entry *sentry;
+       unsigned int segno;
+       block_t blk = start;
+-      unsigned long offset, size, max_blocks = sbi->blocks_per_seg;
+-      unsigned long *map;
++      unsigned long offset, size, *map;
+       while (blk < end) {
+               segno = GET_SEGNO(sbi, blk);
+@@ -1145,7 +1144,7 @@ static void __check_sit_bitmap(struct f2fs_sb_info *sbi,
+               if (end < START_BLOCK(sbi, segno + 1))
+                       size = GET_BLKOFF_FROM_SEG0(sbi, end);
+               else
+-                      size = max_blocks;
++                      size = BLKS_PER_SEG(sbi);
+               map = (unsigned long *)(sentry->cur_valid_map);
+               offset = __find_rev_next_bit(map, size, offset);
+               f2fs_bug_on(sbi, offset != size);
+@@ -2043,7 +2042,6 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
+                                                       bool check_only)
+ {
+       int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
+-      int max_blocks = sbi->blocks_per_seg;
+       struct seg_entry *se = get_seg_entry(sbi, cpc->trim_start);
+       unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
+       unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
+@@ -2055,8 +2053,9 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
+       struct list_head *head = &SM_I(sbi)->dcc_info->entry_list;
+       int i;
+-      if (se->valid_blocks == max_blocks || !f2fs_hw_support_discard(sbi) ||
+-                      !f2fs_block_unit_discard(sbi))
++      if (se->valid_blocks == BLKS_PER_SEG(sbi) ||
++          !f2fs_hw_support_discard(sbi) ||
++          !f2fs_block_unit_discard(sbi))
+               return false;
+       if (!force) {
+@@ -2073,13 +2072,14 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
+       while (force || SM_I(sbi)->dcc_info->nr_discards <=
+                               SM_I(sbi)->dcc_info->max_discards) {
+-              start = __find_rev_next_bit(dmap, max_blocks, end + 1);
+-              if (start >= max_blocks)
++              start = __find_rev_next_bit(dmap, BLKS_PER_SEG(sbi), end + 1);
++              if (start >= BLKS_PER_SEG(sbi))
+                       break;
+-              end = __find_rev_next_zero_bit(dmap, max_blocks, start + 1);
+-              if (force && start && end != max_blocks
+-                                      && (end - start) < cpc->trim_minlen)
++              end = __find_rev_next_zero_bit(dmap,
++                                              BLKS_PER_SEG(sbi), start + 1);
++              if (force && start && end != BLKS_PER_SEG(sbi) &&
++                  (end - start) < cpc->trim_minlen)
+                       continue;
+               if (check_only)
+@@ -2161,8 +2161,8 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
+                                                               start + 1);
+               if (section_alignment) {
+-                      start = rounddown(start, sbi->segs_per_sec);
+-                      end = roundup(end, sbi->segs_per_sec);
++                      start = rounddown(start, SEGS_PER_SEC(sbi));
++                      end = roundup(end, SEGS_PER_SEC(sbi));
+               }
+               for (i = start; i < end; i++) {
+@@ -2190,9 +2190,9 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
+               if (!IS_CURSEC(sbi, secno) &&
+                       !get_valid_blocks(sbi, start, true))
+                       f2fs_issue_discard(sbi, START_BLOCK(sbi, start_segno),
+-                              sbi->segs_per_sec << sbi->log_blocks_per_seg);
++                                              BLKS_PER_SEC(sbi));
+-              start = start_segno + sbi->segs_per_sec;
++              start = start_segno + SEGS_PER_SEC(sbi);
+               if (start < end)
+                       goto next;
+               else
+@@ -2211,7 +2211,7 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
+ find_next:
+               if (is_valid) {
+                       next_pos = find_next_zero_bit_le(entry->discard_map,
+-                                      sbi->blocks_per_seg, cur_pos);
++                                              BLKS_PER_SEG(sbi), cur_pos);
+                       len = next_pos - cur_pos;
+                       if (f2fs_sb_has_blkzoned(sbi) ||
+@@ -2223,13 +2223,13 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
+                       total_len += len;
+               } else {
+                       next_pos = find_next_bit_le(entry->discard_map,
+-                                      sbi->blocks_per_seg, cur_pos);
++                                              BLKS_PER_SEG(sbi), cur_pos);
+               }
+ skip:
+               cur_pos = next_pos;
+               is_valid = !is_valid;
+-              if (cur_pos < sbi->blocks_per_seg)
++              if (cur_pos < BLKS_PER_SEG(sbi))
+                       goto find_next;
+               release_discard_addr(entry);
+@@ -2277,7 +2277,7 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
+       dcc->discard_granularity = DEFAULT_DISCARD_GRANULARITY;
+       dcc->max_ordered_discard = DEFAULT_MAX_ORDERED_DISCARD_GRANULARITY;
+       if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SEGMENT)
+-              dcc->discard_granularity = sbi->blocks_per_seg;
++              dcc->discard_granularity = BLKS_PER_SEG(sbi);
+       else if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SECTION)
+               dcc->discard_granularity = BLKS_PER_SEC(sbi);
+@@ -2540,7 +2540,7 @@ static unsigned short f2fs_curseg_valid_blocks(struct f2fs_sb_info *sbi, int typ
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       if (sbi->ckpt->alloc_type[type] == SSR)
+-              return sbi->blocks_per_seg;
++              return BLKS_PER_SEG(sbi);
+       return curseg->next_blkoff;
+ }
+@@ -2628,7 +2628,7 @@ static int is_next_segment_free(struct f2fs_sb_info *sbi,
+       unsigned int segno = curseg->segno + 1;
+       struct free_segmap_info *free_i = FREE_I(sbi);
+-      if (segno < MAIN_SEGS(sbi) && segno % sbi->segs_per_sec)
++      if (segno < MAIN_SEGS(sbi) && segno % SEGS_PER_SEC(sbi))
+               return !test_bit(segno, free_i->free_segmap);
+       return 0;
+ }
+@@ -2652,7 +2652,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
+       spin_lock(&free_i->segmap_lock);
+-      if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) {
++      if (!new_sec && ((*newseg + 1) % SEGS_PER_SEC(sbi))) {
+               segno = find_next_zero_bit(free_i->free_segmap,
+                       GET_SEG_FROM_SEC(sbi, hint + 1), *newseg + 1);
+               if (segno < GET_SEG_FROM_SEC(sbi, hint + 1))
+@@ -2755,9 +2755,8 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
+       sanity_check_seg_type(sbi, seg_type);
+       if (f2fs_need_rand_seg(sbi))
+-              return get_random_u32_below(MAIN_SECS(sbi) * sbi->segs_per_sec);
++              return get_random_u32_below(MAIN_SECS(sbi) * SEGS_PER_SEC(sbi));
+-      /* if segs_per_sec is large than 1, we need to keep original policy. */
+       if (__is_large_section(sbi))
+               return curseg->segno;
+@@ -2825,7 +2824,7 @@ static int __next_free_blkoff(struct f2fs_sb_info *sbi,
+       for (i = 0; i < entries; i++)
+               target_map[i] = ckpt_map[i] | cur_map[i];
+-      return __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, start);
++      return __find_rev_next_zero_bit(target_map, BLKS_PER_SEG(sbi), start);
+ }
+ static int f2fs_find_next_ssr_block(struct f2fs_sb_info *sbi,
+@@ -2836,7 +2835,7 @@ static int f2fs_find_next_ssr_block(struct f2fs_sb_info *sbi,
+ bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
+ {
+-      return __next_free_blkoff(sbi, segno, 0) < sbi->blocks_per_seg;
++      return __next_free_blkoff(sbi, segno, 0) < BLKS_PER_SEG(sbi);
+ }
+ /*
+@@ -3236,8 +3235,8 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
+       end_segno = (end >= MAX_BLKADDR(sbi)) ? MAIN_SEGS(sbi) - 1 :
+                                               GET_SEGNO(sbi, end);
+       if (need_align) {
+-              start_segno = rounddown(start_segno, sbi->segs_per_sec);
+-              end_segno = roundup(end_segno + 1, sbi->segs_per_sec) - 1;
++              start_segno = rounddown(start_segno, SEGS_PER_SEC(sbi));
++              end_segno = roundup(end_segno + 1, SEGS_PER_SEC(sbi)) - 1;
+       }
+       cpc.reason = CP_DISCARD;
+@@ -3435,7 +3434,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
+       }
+       *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
+-      f2fs_bug_on(sbi, curseg->next_blkoff >= sbi->blocks_per_seg);
++      f2fs_bug_on(sbi, curseg->next_blkoff >= BLKS_PER_SEG(sbi));
+       f2fs_wait_discard_bio(sbi, *new_blkaddr);
+@@ -3885,7 +3884,7 @@ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
+               seg_i->next_blkoff = blk_off;
+               if (seg_i->alloc_type == SSR)
+-                      blk_off = sbi->blocks_per_seg;
++                      blk_off = BLKS_PER_SEG(sbi);
+               for (j = 0; j < blk_off; j++) {
+                       struct f2fs_summary *s;
+@@ -3953,7 +3952,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
+                       struct f2fs_summary *ns = &sum->entries[0];
+                       int i;
+-                      for (i = 0; i < sbi->blocks_per_seg; i++, ns++) {
++                      for (i = 0; i < BLKS_PER_SEG(sbi); i++, ns++) {
+                               ns->version = 0;
+                               ns->ofs_in_node = 0;
+                       }
+@@ -4586,21 +4585,20 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
+                       sit_valid_blocks[SE_PAGETYPE(se)] += se->valid_blocks;
+-                      if (f2fs_block_unit_discard(sbi)) {
+-                              /* build discard map only one time */
+-                              if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
+-                                      memset(se->discard_map, 0xff,
++                      if (!f2fs_block_unit_discard(sbi))
++                              goto init_discard_map_done;
++
++                      /* build discard map only one time */
++                      if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
++                              memset(se->discard_map, 0xff,
+                                               SIT_VBLOCK_MAP_SIZE);
+-                              } else {
+-                                      memcpy(se->discard_map,
+-                                              se->cur_valid_map,
++                              goto init_discard_map_done;
++                      }
++                      memcpy(se->discard_map, se->cur_valid_map,
+                                               SIT_VBLOCK_MAP_SIZE);
+-                                      sbi->discard_blks +=
+-                                              sbi->blocks_per_seg -
++                      sbi->discard_blks += BLKS_PER_SEG(sbi) -
+                                               se->valid_blocks;
+-                              }
+-                      }
+-
++init_discard_map_done:
+                       if (__is_large_section(sbi))
+                               get_sec_entry(sbi, start)->valid_blocks +=
+                                                       se->valid_blocks;
+@@ -4740,7 +4738,7 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi)
+               return;
+       mutex_lock(&dirty_i->seglist_lock);
+-      for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
++      for (segno = 0; segno < MAIN_SEGS(sbi); segno += SEGS_PER_SEC(sbi)) {
+               valid_blocks = get_valid_blocks(sbi, segno, true);
+               secno = GET_SEC_FROM_SEG(sbi, segno);
+@@ -4839,7 +4837,7 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
+               if (curseg->alloc_type == SSR)
+                       continue;
+-              for (blkofs += 1; blkofs < sbi->blocks_per_seg; blkofs++) {
++              for (blkofs += 1; blkofs < BLKS_PER_SEG(sbi); blkofs++) {
+                       if (!f2fs_test_bit(blkofs, se->cur_valid_map))
+                               continue;
+ out:
+@@ -5138,7 +5136,7 @@ static inline unsigned int f2fs_usable_zone_blks_in_seg(
+       unsigned int secno;
+       if (!sbi->unusable_blocks_per_sec)
+-              return sbi->blocks_per_seg;
++              return BLKS_PER_SEG(sbi);
+       secno = GET_SEC_FROM_SEG(sbi, segno);
+       seg_start = START_BLOCK(sbi, segno);
+@@ -5153,10 +5151,10 @@ static inline unsigned int f2fs_usable_zone_blks_in_seg(
+        */
+       if (seg_start >= sec_cap_blkaddr)
+               return 0;
+-      if (seg_start + sbi->blocks_per_seg > sec_cap_blkaddr)
++      if (seg_start + BLKS_PER_SEG(sbi) > sec_cap_blkaddr)
+               return sec_cap_blkaddr - seg_start;
+-      return sbi->blocks_per_seg;
++      return BLKS_PER_SEG(sbi);
+ }
+ #else
+ int f2fs_fix_curseg_write_pointer(struct f2fs_sb_info *sbi)
+@@ -5182,7 +5180,7 @@ unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi,
+       if (f2fs_sb_has_blkzoned(sbi))
+               return f2fs_usable_zone_blks_in_seg(sbi, segno);
+-      return sbi->blocks_per_seg;
++      return BLKS_PER_SEG(sbi);
+ }
+ unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi,
+@@ -5191,7 +5189,7 @@ unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi,
+       if (f2fs_sb_has_blkzoned(sbi))
+               return CAP_SEGS_PER_SEC(sbi);
+-      return sbi->segs_per_sec;
++      return SEGS_PER_SEC(sbi);
+ }
+ /*
+@@ -5206,14 +5204,14 @@ static void init_min_max_mtime(struct f2fs_sb_info *sbi)
+       sit_i->min_mtime = ULLONG_MAX;
+-      for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
++      for (segno = 0; segno < MAIN_SEGS(sbi); segno += SEGS_PER_SEC(sbi)) {
+               unsigned int i;
+               unsigned long long mtime = 0;
+-              for (i = 0; i < sbi->segs_per_sec; i++)
++              for (i = 0; i < SEGS_PER_SEC(sbi); i++)
+                       mtime += get_seg_entry(sbi, segno + i)->mtime;
+-              mtime = div_u64(mtime, sbi->segs_per_sec);
++              mtime = div_u64(mtime, SEGS_PER_SEC(sbi));
+               if (sit_i->min_mtime > mtime)
+                       sit_i->min_mtime = mtime;
+@@ -5252,7 +5250,7 @@ int f2fs_build_segment_manager(struct f2fs_sb_info *sbi)
+               sm_info->ipu_policy = BIT(F2FS_IPU_FSYNC);
+       sm_info->min_ipu_util = DEF_MIN_IPU_UTIL;
+       sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS;
+-      sm_info->min_seq_blocks = sbi->blocks_per_seg;
++      sm_info->min_seq_blocks = BLKS_PER_SEG(sbi);
+       sm_info->min_hot_blocks = DEF_MIN_HOT_BLOCKS;
+       sm_info->min_ssr_sections = reserved_sections(sbi);
+diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
+index c77a562831493..61fa12f12ffdc 100644
+--- a/fs/f2fs/segment.h
++++ b/fs/f2fs/segment.h
+@@ -48,21 +48,21 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
+ #define IS_CURSEC(sbi, secno)                                         \
+       (((secno) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno /            \
+-        (sbi)->segs_per_sec) ||       \
++        SEGS_PER_SEC(sbi)) || \
+        ((secno) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno /           \
+-        (sbi)->segs_per_sec) ||       \
++        SEGS_PER_SEC(sbi)) || \
+        ((secno) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno /           \
+-        (sbi)->segs_per_sec) ||       \
++        SEGS_PER_SEC(sbi)) || \
+        ((secno) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno /            \
+-        (sbi)->segs_per_sec) ||       \
++        SEGS_PER_SEC(sbi)) || \
+        ((secno) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno /           \
+-        (sbi)->segs_per_sec) ||       \
++        SEGS_PER_SEC(sbi)) || \
+        ((secno) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno /           \
+-        (sbi)->segs_per_sec) ||       \
++        SEGS_PER_SEC(sbi)) || \
+        ((secno) == CURSEG_I(sbi, CURSEG_COLD_DATA_PINNED)->segno /    \
+-        (sbi)->segs_per_sec) ||       \
++        SEGS_PER_SEC(sbi)) || \
+        ((secno) == CURSEG_I(sbi, CURSEG_ALL_DATA_ATGC)->segno /       \
+-        (sbi)->segs_per_sec))
++        SEGS_PER_SEC(sbi)))
+ #define MAIN_BLKADDR(sbi)                                             \
+       (SM_I(sbi) ? SM_I(sbi)->main_blkaddr :                          \
+@@ -93,24 +93,22 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
+ #define GET_SEGNO_FROM_SEG0(sbi, blk_addr)                            \
+       (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> (sbi)->log_blocks_per_seg)
+ #define GET_BLKOFF_FROM_SEG0(sbi, blk_addr)                           \
+-      (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1))
++      (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & (BLKS_PER_SEG(sbi) - 1))
+ #define GET_SEGNO(sbi, blk_addr)                                      \
+       ((!__is_valid_data_blkaddr(blk_addr)) ?                 \
+       NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi),                 \
+               GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
+-#define BLKS_PER_SEC(sbi)                                     \
+-      ((sbi)->segs_per_sec * (sbi)->blocks_per_seg)
+ #define CAP_BLKS_PER_SEC(sbi)                                 \
+-      ((sbi)->segs_per_sec * (sbi)->blocks_per_seg -          \
++      (SEGS_PER_SEC(sbi) * BLKS_PER_SEG(sbi) -                \
+        (sbi)->unusable_blocks_per_sec)
+ #define CAP_SEGS_PER_SEC(sbi)                                 \
+-      ((sbi)->segs_per_sec - ((sbi)->unusable_blocks_per_sec >>\
++      (SEGS_PER_SEC(sbi) - ((sbi)->unusable_blocks_per_sec >> \
+       (sbi)->log_blocks_per_seg))
+ #define GET_SEC_FROM_SEG(sbi, segno)                          \
+-      (((segno) == -1) ? -1 : (segno) / (sbi)->segs_per_sec)
++      (((segno) == -1) ? -1 : (segno) / SEGS_PER_SEC(sbi))
+ #define GET_SEG_FROM_SEC(sbi, secno)                          \
+-      ((secno) * (sbi)->segs_per_sec)
++      ((secno) * SEGS_PER_SEC(sbi))
+ #define GET_ZONE_FROM_SEC(sbi, secno)                         \
+       (((secno) == -1) ? -1 : (secno) / (sbi)->secs_per_zone)
+ #define GET_ZONE_FROM_SEG(sbi, segno)                         \
+@@ -364,7 +362,7 @@ static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi,
+               unsigned int blocks = 0;
+               int i;
+-              for (i = 0; i < sbi->segs_per_sec; i++, start_segno++) {
++              for (i = 0; i < SEGS_PER_SEC(sbi); i++, start_segno++) {
+                       struct seg_entry *se = get_seg_entry(sbi, start_segno);
+                       blocks += se->ckpt_valid_blocks;
+@@ -449,7 +447,7 @@ static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno)
+       free_i->free_segments++;
+       next = find_next_bit(free_i->free_segmap,
+-                      start_segno + sbi->segs_per_sec, start_segno);
++                      start_segno + SEGS_PER_SEC(sbi), start_segno);
+       if (next >= start_segno + usable_segs) {
+               clear_bit(secno, free_i->free_secmap);
+               free_i->free_sections++;
+@@ -485,7 +483,7 @@ static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
+               if (!inmem && IS_CURSEC(sbi, secno))
+                       goto skip_free;
+               next = find_next_bit(free_i->free_segmap,
+-                              start_segno + sbi->segs_per_sec, start_segno);
++                              start_segno + SEGS_PER_SEC(sbi), start_segno);
+               if (next >= start_segno + usable_segs) {
+                       if (test_and_clear_bit(secno, free_i->free_secmap))
+                               free_i->free_sections++;
+@@ -792,10 +790,10 @@ static inline int check_block_count(struct f2fs_sb_info *sbi,
+               return -EFSCORRUPTED;
+       }
+-      if (usable_blks_per_seg < sbi->blocks_per_seg)
++      if (usable_blks_per_seg < BLKS_PER_SEG(sbi))
+               f2fs_bug_on(sbi, find_next_bit_le(&raw_sit->valid_map,
+-                              sbi->blocks_per_seg,
+-                              usable_blks_per_seg) != sbi->blocks_per_seg);
++                              BLKS_PER_SEG(sbi),
++                              usable_blks_per_seg) != BLKS_PER_SEG(sbi));
+       /* check segment usage, and check boundary of a given segment number */
+       if (unlikely(GET_SIT_VBLOCKS(raw_sit) > usable_blks_per_seg
+@@ -914,9 +912,9 @@ static inline int nr_pages_to_skip(struct f2fs_sb_info *sbi, int type)
+               return 0;
+       if (type == DATA)
+-              return sbi->blocks_per_seg;
++              return BLKS_PER_SEG(sbi);
+       else if (type == NODE)
+-              return 8 * sbi->blocks_per_seg;
++              return 8 * BLKS_PER_SEG(sbi);
+       else if (type == META)
+               return 8 * BIO_MAX_VECS;
+       else
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index 5fdb75b74cf80..a0e6f804a1d0e 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -3701,7 +3701,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
+       }
+       main_segs = le32_to_cpu(raw_super->segment_count_main);
+-      blocks_per_seg = sbi->blocks_per_seg;
++      blocks_per_seg = BLKS_PER_SEG(sbi);
+       for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) {
+               if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
+@@ -3814,8 +3814,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
+       sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
+       sbi->total_sections = le32_to_cpu(raw_super->section_count);
+       sbi->total_node_count =
+-              (le32_to_cpu(raw_super->segment_count_nat) / 2)
+-                      * sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK;
++              ((le32_to_cpu(raw_super->segment_count_nat) / 2) *
++              NAT_ENTRY_PER_BLOCK) << sbi->log_blocks_per_seg;
+       F2FS_ROOT_INO(sbi) = le32_to_cpu(raw_super->root_ino);
+       F2FS_NODE_INO(sbi) = le32_to_cpu(raw_super->node_ino);
+       F2FS_META_INO(sbi) = le32_to_cpu(raw_super->meta_ino);
+@@ -3824,7 +3824,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
+       sbi->next_victim_seg[BG_GC] = NULL_SEGNO;
+       sbi->next_victim_seg[FG_GC] = NULL_SEGNO;
+       sbi->max_victim_search = DEF_MAX_VICTIM_SEARCH;
+-      sbi->migration_granularity = sbi->segs_per_sec;
++      sbi->migration_granularity = SEGS_PER_SEC(sbi);
+       sbi->seq_file_ra_mul = MIN_RA_MUL;
+       sbi->max_fragment_chunk = DEF_FRAGMENT_SIZE;
+       sbi->max_fragment_hole = DEF_FRAGMENT_SIZE;
+diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
+index 417fae96890f6..6347a55020c6e 100644
+--- a/fs/f2fs/sysfs.c
++++ b/fs/f2fs/sysfs.c
+@@ -466,8 +466,8 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
+               spin_lock(&sbi->stat_lock);
+               if (t > (unsigned long)(sbi->user_block_count -
+                               F2FS_OPTION(sbi).root_reserved_blocks -
+-                              sbi->blocks_per_seg *
+-                              SM_I(sbi)->additional_reserved_segments)) {
++                              (SM_I(sbi)->additional_reserved_segments <<
++                                      sbi->log_blocks_per_seg))) {
+                       spin_unlock(&sbi->stat_lock);
+                       return -EINVAL;
+               }
+@@ -517,7 +517,7 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
+       }
+       if (!strcmp(a->attr.name, "migration_granularity")) {
+-              if (t == 0 || t > sbi->segs_per_sec)
++              if (t == 0 || t > SEGS_PER_SEC(sbi))
+                       return -EINVAL;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/firmware-dmi-id-add-a-release-callback-function.patch b/queue-6.6/firmware-dmi-id-add-a-release-callback-function.patch
new file mode 100644 (file)
index 0000000..f87e632
--- /dev/null
@@ -0,0 +1,50 @@
+From 0b8801f4dca18e58258b915abfdd3053eae46f21 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Apr 2024 09:34:24 +0200
+Subject: firmware: dmi-id: add a release callback function
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit cf770af5645a41a753c55a053fa1237105b0964a ]
+
+dmi_class uses kfree() as the .release function, but that now causes
+a warning with clang-16 as it violates control flow integrity (KCFI)
+rules:
+
+drivers/firmware/dmi-id.c:174:17: error: cast from 'void (*)(const void *)' to 'void (*)(struct device *)' converts to incompatible function type [-Werror,-Wcast-function-type-strict]
+  174 |         .dev_release = (void(*)(struct device *)) kfree,
+
+Add an explicit function to call kfree() instead.
+
+Fixes: 4f5c791a850e ("DMI-based module autoloading")
+Link: https://lore.kernel.org/lkml/20240213100238.456912-1-arnd@kernel.org/
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jean Delvare <jdelvare@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/dmi-id.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
+index 5f3a3e913d28f..d19c78a78ae3a 100644
+--- a/drivers/firmware/dmi-id.c
++++ b/drivers/firmware/dmi-id.c
+@@ -169,9 +169,14 @@ static int dmi_dev_uevent(const struct device *dev, struct kobj_uevent_env *env)
+       return 0;
+ }
++static void dmi_dev_release(struct device *dev)
++{
++      kfree(dev);
++}
++
+ static struct class dmi_class = {
+       .name = "dmi",
+-      .dev_release = (void(*)(struct device *)) kfree,
++      .dev_release = dmi_dev_release,
+       .dev_uevent = dmi_dev_uevent,
+ };
+-- 
+2.43.0
+
diff --git a/queue-6.6/fpga-bridge-add-owner-module-and-take-its-refcount.patch b/queue-6.6/fpga-bridge-add-owner-module-and-take-its-refcount.patch
new file mode 100644 (file)
index 0000000..d9d285c
--- /dev/null
@@ -0,0 +1,251 @@
+From a90e3cedea2ee526844c12b307d1ba9f73ce09c8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Mar 2024 18:18:37 +0100
+Subject: fpga: bridge: add owner module and take its refcount
+
+From: Marco Pagani <marpagan@redhat.com>
+
+[ Upstream commit 1da11f822042eb6ef4b6064dc048f157a7852529 ]
+
+The current implementation of the fpga bridge assumes that the low-level
+module registers a driver for the parent device and uses its owner pointer
+to take the module's refcount. This approach is problematic since it can
+lead to a null pointer dereference while attempting to get the bridge if
+the parent device does not have a driver.
+
+To address this problem, add a module owner pointer to the fpga_bridge
+struct and use it to take the module's refcount. Modify the function for
+registering a bridge to take an additional owner module parameter and
+rename it to avoid conflicts. Use the old function name for a helper macro
+that automatically sets the module that registers the bridge as the owner.
+This ensures compatibility with existing low-level control modules and
+reduces the chances of registering a bridge without setting the owner.
+
+Also, update the documentation to keep it consistent with the new interface
+for registering an fpga bridge.
+
+Other changes: opportunistically move put_device() from __fpga_bridge_get()
+to fpga_bridge_get() and of_fpga_bridge_get() to improve code clarity since
+the bridge device is taken in these functions.
+
+Fixes: 21aeda950c5f ("fpga: add fpga bridge framework")
+Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Suggested-by: Xu Yilun <yilun.xu@intel.com>
+Reviewed-by: Russ Weight <russ.weight@linux.dev>
+Signed-off-by: Marco Pagani <marpagan@redhat.com>
+Acked-by: Xu Yilun <yilun.xu@intel.com>
+Link: https://lore.kernel.org/r/20240322171839.233864-1-marpagan@redhat.com
+Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/driver-api/fpga/fpga-bridge.rst |  7 ++-
+ drivers/fpga/fpga-bridge.c                    | 57 ++++++++++---------
+ include/linux/fpga/fpga-bridge.h              | 10 +++-
+ 3 files changed, 43 insertions(+), 31 deletions(-)
+
+diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst
+index 6042085340953..833f68fb07008 100644
+--- a/Documentation/driver-api/fpga/fpga-bridge.rst
++++ b/Documentation/driver-api/fpga/fpga-bridge.rst
+@@ -6,9 +6,12 @@ API to implement a new FPGA bridge
+ * struct fpga_bridge - The FPGA Bridge structure
+ * struct fpga_bridge_ops - Low level Bridge driver ops
+-* fpga_bridge_register() - Create and register a bridge
++* __fpga_bridge_register() - Create and register a bridge
+ * fpga_bridge_unregister() - Unregister a bridge
++The helper macro ``fpga_bridge_register()`` automatically sets
++the module that registers the FPGA bridge as the owner.
++
+ .. kernel-doc:: include/linux/fpga/fpga-bridge.h
+    :functions: fpga_bridge
+@@ -16,7 +19,7 @@ API to implement a new FPGA bridge
+    :functions: fpga_bridge_ops
+ .. kernel-doc:: drivers/fpga/fpga-bridge.c
+-   :functions: fpga_bridge_register
++   :functions: __fpga_bridge_register
+ .. kernel-doc:: drivers/fpga/fpga-bridge.c
+    :functions: fpga_bridge_unregister
+diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
+index a024be2b84e29..83d35fbb82450 100644
+--- a/drivers/fpga/fpga-bridge.c
++++ b/drivers/fpga/fpga-bridge.c
+@@ -55,33 +55,26 @@ int fpga_bridge_disable(struct fpga_bridge *bridge)
+ }
+ EXPORT_SYMBOL_GPL(fpga_bridge_disable);
+-static struct fpga_bridge *__fpga_bridge_get(struct device *dev,
++static struct fpga_bridge *__fpga_bridge_get(struct device *bridge_dev,
+                                            struct fpga_image_info *info)
+ {
+       struct fpga_bridge *bridge;
+-      int ret = -ENODEV;
+-      bridge = to_fpga_bridge(dev);
++      bridge = to_fpga_bridge(bridge_dev);
+       bridge->info = info;
+-      if (!mutex_trylock(&bridge->mutex)) {
+-              ret = -EBUSY;
+-              goto err_dev;
+-      }
++      if (!mutex_trylock(&bridge->mutex))
++              return ERR_PTR(-EBUSY);
+-      if (!try_module_get(dev->parent->driver->owner))
+-              goto err_ll_mod;
++      if (!try_module_get(bridge->br_ops_owner)) {
++              mutex_unlock(&bridge->mutex);
++              return ERR_PTR(-ENODEV);
++      }
+       dev_dbg(&bridge->dev, "get\n");
+       return bridge;
+-
+-err_ll_mod:
+-      mutex_unlock(&bridge->mutex);
+-err_dev:
+-      put_device(dev);
+-      return ERR_PTR(ret);
+ }
+ /**
+@@ -98,13 +91,18 @@ static struct fpga_bridge *__fpga_bridge_get(struct device *dev,
+ struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
+                                      struct fpga_image_info *info)
+ {
+-      struct device *dev;
++      struct fpga_bridge *bridge;
++      struct device *bridge_dev;
+-      dev = class_find_device_by_of_node(&fpga_bridge_class, np);
+-      if (!dev)
++      bridge_dev = class_find_device_by_of_node(&fpga_bridge_class, np);
++      if (!bridge_dev)
+               return ERR_PTR(-ENODEV);
+-      return __fpga_bridge_get(dev, info);
++      bridge = __fpga_bridge_get(bridge_dev, info);
++      if (IS_ERR(bridge))
++              put_device(bridge_dev);
++
++      return bridge;
+ }
+ EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
+@@ -125,6 +123,7 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data)
+ struct fpga_bridge *fpga_bridge_get(struct device *dev,
+                                   struct fpga_image_info *info)
+ {
++      struct fpga_bridge *bridge;
+       struct device *bridge_dev;
+       bridge_dev = class_find_device(&fpga_bridge_class, NULL, dev,
+@@ -132,7 +131,11 @@ struct fpga_bridge *fpga_bridge_get(struct device *dev,
+       if (!bridge_dev)
+               return ERR_PTR(-ENODEV);
+-      return __fpga_bridge_get(bridge_dev, info);
++      bridge = __fpga_bridge_get(bridge_dev, info);
++      if (IS_ERR(bridge))
++              put_device(bridge_dev);
++
++      return bridge;
+ }
+ EXPORT_SYMBOL_GPL(fpga_bridge_get);
+@@ -146,7 +149,7 @@ void fpga_bridge_put(struct fpga_bridge *bridge)
+       dev_dbg(&bridge->dev, "put\n");
+       bridge->info = NULL;
+-      module_put(bridge->dev.parent->driver->owner);
++      module_put(bridge->br_ops_owner);
+       mutex_unlock(&bridge->mutex);
+       put_device(&bridge->dev);
+ }
+@@ -316,18 +319,19 @@ static struct attribute *fpga_bridge_attrs[] = {
+ ATTRIBUTE_GROUPS(fpga_bridge);
+ /**
+- * fpga_bridge_register - create and register an FPGA Bridge device
++ * __fpga_bridge_register - create and register an FPGA Bridge device
+  * @parent:   FPGA bridge device from pdev
+  * @name:     FPGA bridge name
+  * @br_ops:   pointer to structure of fpga bridge ops
+  * @priv:     FPGA bridge private data
++ * @owner:    owner module containing the br_ops
+  *
+  * Return: struct fpga_bridge pointer or ERR_PTR()
+  */
+ struct fpga_bridge *
+-fpga_bridge_register(struct device *parent, const char *name,
+-                   const struct fpga_bridge_ops *br_ops,
+-                   void *priv)
++__fpga_bridge_register(struct device *parent, const char *name,
++                     const struct fpga_bridge_ops *br_ops,
++                     void *priv, struct module *owner)
+ {
+       struct fpga_bridge *bridge;
+       int id, ret;
+@@ -357,6 +361,7 @@ fpga_bridge_register(struct device *parent, const char *name,
+       bridge->name = name;
+       bridge->br_ops = br_ops;
++      bridge->br_ops_owner = owner;
+       bridge->priv = priv;
+       bridge->dev.groups = br_ops->groups;
+@@ -386,7 +391,7 @@ fpga_bridge_register(struct device *parent, const char *name,
+       return ERR_PTR(ret);
+ }
+-EXPORT_SYMBOL_GPL(fpga_bridge_register);
++EXPORT_SYMBOL_GPL(__fpga_bridge_register);
+ /**
+  * fpga_bridge_unregister - unregister an FPGA bridge
+diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h
+index 223da48a6d18b..94c4edd047e54 100644
+--- a/include/linux/fpga/fpga-bridge.h
++++ b/include/linux/fpga/fpga-bridge.h
+@@ -45,6 +45,7 @@ struct fpga_bridge_info {
+  * @dev: FPGA bridge device
+  * @mutex: enforces exclusive reference to bridge
+  * @br_ops: pointer to struct of FPGA bridge ops
++ * @br_ops_owner: module containing the br_ops
+  * @info: fpga image specific information
+  * @node: FPGA bridge list node
+  * @priv: low level driver private date
+@@ -54,6 +55,7 @@ struct fpga_bridge {
+       struct device dev;
+       struct mutex mutex; /* for exclusive reference to bridge */
+       const struct fpga_bridge_ops *br_ops;
++      struct module *br_ops_owner;
+       struct fpga_image_info *info;
+       struct list_head node;
+       void *priv;
+@@ -79,10 +81,12 @@ int of_fpga_bridge_get_to_list(struct device_node *np,
+                              struct fpga_image_info *info,
+                              struct list_head *bridge_list);
++#define fpga_bridge_register(parent, name, br_ops, priv) \
++      __fpga_bridge_register(parent, name, br_ops, priv, THIS_MODULE)
+ struct fpga_bridge *
+-fpga_bridge_register(struct device *parent, const char *name,
+-                   const struct fpga_bridge_ops *br_ops,
+-                   void *priv);
++__fpga_bridge_register(struct device *parent, const char *name,
++                     const struct fpga_bridge_ops *br_ops, void *priv,
++                     struct module *owner);
+ void fpga_bridge_unregister(struct fpga_bridge *br);
+ #endif /* _LINUX_FPGA_BRIDGE_H */
+-- 
+2.43.0
+
diff --git a/queue-6.6/fpga-manager-add-owner-module-and-take-its-refcount.patch b/queue-6.6/fpga-manager-add-owner-module-and-take-its-refcount.patch
new file mode 100644 (file)
index 0000000..fd9a0ca
--- /dev/null
@@ -0,0 +1,408 @@
+From f4b46ce83316c006254fd5a4155a4752f68d12aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 20:29:26 +0100
+Subject: fpga: manager: add owner module and take its refcount
+
+From: Marco Pagani <marpagan@redhat.com>
+
+[ Upstream commit 4d4d2d4346857bf778fafaa97d6f76bb1663e3c9 ]
+
+The current implementation of the fpga manager assumes that the low-level
+module registers a driver for the parent device and uses its owner pointer
+to take the module's refcount. This approach is problematic since it can
+lead to a null pointer dereference while attempting to get the manager if
+the parent device does not have a driver.
+
+To address this problem, add a module owner pointer to the fpga_manager
+struct and use it to take the module's refcount. Modify the functions for
+registering the manager to take an additional owner module parameter and
+rename them to avoid conflicts. Use the old function names for helper
+macros that automatically set the module that registers the manager as the
+owner. This ensures compatibility with existing low-level control modules
+and reduces the chances of registering a manager without setting the owner.
+
+Also, update the documentation to keep it consistent with the new interface
+for registering an fpga manager.
+
+Other changes: opportunistically move put_device() from __fpga_mgr_get() to
+fpga_mgr_get() and of_fpga_mgr_get() to improve code clarity since the
+manager device is taken in these functions.
+
+Fixes: 654ba4cc0f3e ("fpga manager: ensure lifetime with of_fpga_mgr_get")
+Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Suggested-by: Xu Yilun <yilun.xu@intel.com>
+Signed-off-by: Marco Pagani <marpagan@redhat.com>
+Acked-by: Xu Yilun <yilun.xu@intel.com>
+Link: https://lore.kernel.org/r/20240305192926.84886-1-marpagan@redhat.com
+Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/driver-api/fpga/fpga-mgr.rst | 34 +++++----
+ drivers/fpga/fpga-mgr.c                    | 82 +++++++++++++---------
+ include/linux/fpga/fpga-mgr.h              | 26 +++++--
+ 3 files changed, 89 insertions(+), 53 deletions(-)
+
+diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst
+index 49c0a95126532..8d2b79f696c1f 100644
+--- a/Documentation/driver-api/fpga/fpga-mgr.rst
++++ b/Documentation/driver-api/fpga/fpga-mgr.rst
+@@ -24,7 +24,8 @@ How to support a new FPGA device
+ --------------------------------
+ To add another FPGA manager, write a driver that implements a set of ops.  The
+-probe function calls fpga_mgr_register() or fpga_mgr_register_full(), such as::
++probe function calls ``fpga_mgr_register()`` or ``fpga_mgr_register_full()``,
++such as::
+       static const struct fpga_manager_ops socfpga_fpga_ops = {
+               .write_init = socfpga_fpga_ops_configure_init,
+@@ -69,10 +70,11 @@ probe function calls fpga_mgr_register() or fpga_mgr_register_full(), such as::
+       }
+ Alternatively, the probe function could call one of the resource managed
+-register functions, devm_fpga_mgr_register() or devm_fpga_mgr_register_full().
+-When these functions are used, the parameter syntax is the same, but the call
+-to fpga_mgr_unregister() should be removed. In the above example, the
+-socfpga_fpga_remove() function would not be required.
++register functions, ``devm_fpga_mgr_register()`` or
++``devm_fpga_mgr_register_full()``.  When these functions are used, the
++parameter syntax is the same, but the call to ``fpga_mgr_unregister()`` should be
++removed. In the above example, the ``socfpga_fpga_remove()`` function would not be
++required.
+ The ops will implement whatever device specific register writes are needed to
+ do the programming sequence for this particular FPGA.  These ops return 0 for
+@@ -125,15 +127,19 @@ API for implementing a new FPGA Manager driver
+ * struct fpga_manager -  the FPGA manager struct
+ * struct fpga_manager_ops -  Low level FPGA manager driver ops
+ * struct fpga_manager_info -  Parameter structure for fpga_mgr_register_full()
+-* fpga_mgr_register_full() -  Create and register an FPGA manager using the
++* __fpga_mgr_register_full() -  Create and register an FPGA manager using the
+   fpga_mgr_info structure to provide the full flexibility of options
+-* fpga_mgr_register() -  Create and register an FPGA manager using standard
++* __fpga_mgr_register() -  Create and register an FPGA manager using standard
+   arguments
+-* devm_fpga_mgr_register_full() -  Resource managed version of
+-  fpga_mgr_register_full()
+-* devm_fpga_mgr_register() -  Resource managed version of fpga_mgr_register()
++* __devm_fpga_mgr_register_full() -  Resource managed version of
++  __fpga_mgr_register_full()
++* __devm_fpga_mgr_register() -  Resource managed version of __fpga_mgr_register()
+ * fpga_mgr_unregister() -  Unregister an FPGA manager
++Helper macros ``fpga_mgr_register_full()``, ``fpga_mgr_register()``,
++``devm_fpga_mgr_register_full()``, and ``devm_fpga_mgr_register()`` are available
++to ease the registration.
++
+ .. kernel-doc:: include/linux/fpga/fpga-mgr.h
+    :functions: fpga_mgr_states
+@@ -147,16 +153,16 @@ API for implementing a new FPGA Manager driver
+    :functions: fpga_manager_info
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+-   :functions: fpga_mgr_register_full
++   :functions: __fpga_mgr_register_full
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+-   :functions: fpga_mgr_register
++   :functions: __fpga_mgr_register
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+-   :functions: devm_fpga_mgr_register_full
++   :functions: __devm_fpga_mgr_register_full
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+-   :functions: devm_fpga_mgr_register
++   :functions: __devm_fpga_mgr_register
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+    :functions: fpga_mgr_unregister
+diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
+index 06651389c5926..0f4035b089a2e 100644
+--- a/drivers/fpga/fpga-mgr.c
++++ b/drivers/fpga/fpga-mgr.c
+@@ -664,20 +664,16 @@ static struct attribute *fpga_mgr_attrs[] = {
+ };
+ ATTRIBUTE_GROUPS(fpga_mgr);
+-static struct fpga_manager *__fpga_mgr_get(struct device *dev)
++static struct fpga_manager *__fpga_mgr_get(struct device *mgr_dev)
+ {
+       struct fpga_manager *mgr;
+-      mgr = to_fpga_manager(dev);
++      mgr = to_fpga_manager(mgr_dev);
+-      if (!try_module_get(dev->parent->driver->owner))
+-              goto err_dev;
++      if (!try_module_get(mgr->mops_owner))
++              mgr = ERR_PTR(-ENODEV);
+       return mgr;
+-
+-err_dev:
+-      put_device(dev);
+-      return ERR_PTR(-ENODEV);
+ }
+ static int fpga_mgr_dev_match(struct device *dev, const void *data)
+@@ -693,12 +689,18 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data)
+  */
+ struct fpga_manager *fpga_mgr_get(struct device *dev)
+ {
+-      struct device *mgr_dev = class_find_device(&fpga_mgr_class, NULL, dev,
+-                                                 fpga_mgr_dev_match);
++      struct fpga_manager *mgr;
++      struct device *mgr_dev;
++
++      mgr_dev = class_find_device(&fpga_mgr_class, NULL, dev, fpga_mgr_dev_match);
+       if (!mgr_dev)
+               return ERR_PTR(-ENODEV);
+-      return __fpga_mgr_get(mgr_dev);
++      mgr = __fpga_mgr_get(mgr_dev);
++      if (IS_ERR(mgr))
++              put_device(mgr_dev);
++
++      return mgr;
+ }
+ EXPORT_SYMBOL_GPL(fpga_mgr_get);
+@@ -711,13 +713,18 @@ EXPORT_SYMBOL_GPL(fpga_mgr_get);
+  */
+ struct fpga_manager *of_fpga_mgr_get(struct device_node *node)
+ {
+-      struct device *dev;
++      struct fpga_manager *mgr;
++      struct device *mgr_dev;
+-      dev = class_find_device_by_of_node(&fpga_mgr_class, node);
+-      if (!dev)
++      mgr_dev = class_find_device_by_of_node(&fpga_mgr_class, node);
++      if (!mgr_dev)
+               return ERR_PTR(-ENODEV);
+-      return __fpga_mgr_get(dev);
++      mgr = __fpga_mgr_get(mgr_dev);
++      if (IS_ERR(mgr))
++              put_device(mgr_dev);
++
++      return mgr;
+ }
+ EXPORT_SYMBOL_GPL(of_fpga_mgr_get);
+@@ -727,7 +734,7 @@ EXPORT_SYMBOL_GPL(of_fpga_mgr_get);
+  */
+ void fpga_mgr_put(struct fpga_manager *mgr)
+ {
+-      module_put(mgr->dev.parent->driver->owner);
++      module_put(mgr->mops_owner);
+       put_device(&mgr->dev);
+ }
+ EXPORT_SYMBOL_GPL(fpga_mgr_put);
+@@ -766,9 +773,10 @@ void fpga_mgr_unlock(struct fpga_manager *mgr)
+ EXPORT_SYMBOL_GPL(fpga_mgr_unlock);
+ /**
+- * fpga_mgr_register_full - create and register an FPGA Manager device
++ * __fpga_mgr_register_full - create and register an FPGA Manager device
+  * @parent:   fpga manager device from pdev
+  * @info:     parameters for fpga manager
++ * @owner:    owner module containing the ops
+  *
+  * The caller of this function is responsible for calling fpga_mgr_unregister().
+  * Using devm_fpga_mgr_register_full() instead is recommended.
+@@ -776,7 +784,8 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unlock);
+  * Return: pointer to struct fpga_manager pointer or ERR_PTR()
+  */
+ struct fpga_manager *
+-fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info)
++__fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info,
++                       struct module *owner)
+ {
+       const struct fpga_manager_ops *mops = info->mops;
+       struct fpga_manager *mgr;
+@@ -804,6 +813,8 @@ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *in
+       mutex_init(&mgr->ref_mutex);
++      mgr->mops_owner = owner;
++
+       mgr->name = info->name;
+       mgr->mops = info->mops;
+       mgr->priv = info->priv;
+@@ -841,14 +852,15 @@ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *in
+       return ERR_PTR(ret);
+ }
+-EXPORT_SYMBOL_GPL(fpga_mgr_register_full);
++EXPORT_SYMBOL_GPL(__fpga_mgr_register_full);
+ /**
+- * fpga_mgr_register - create and register an FPGA Manager device
++ * __fpga_mgr_register - create and register an FPGA Manager device
+  * @parent:   fpga manager device from pdev
+  * @name:     fpga manager name
+  * @mops:     pointer to structure of fpga manager ops
+  * @priv:     fpga manager private data
++ * @owner:    owner module containing the ops
+  *
+  * The caller of this function is responsible for calling fpga_mgr_unregister().
+  * Using devm_fpga_mgr_register() instead is recommended. This simple
+@@ -859,8 +871,8 @@ EXPORT_SYMBOL_GPL(fpga_mgr_register_full);
+  * Return: pointer to struct fpga_manager pointer or ERR_PTR()
+  */
+ struct fpga_manager *
+-fpga_mgr_register(struct device *parent, const char *name,
+-                const struct fpga_manager_ops *mops, void *priv)
++__fpga_mgr_register(struct device *parent, const char *name,
++                  const struct fpga_manager_ops *mops, void *priv, struct module *owner)
+ {
+       struct fpga_manager_info info = { 0 };
+@@ -868,9 +880,9 @@ fpga_mgr_register(struct device *parent, const char *name,
+       info.mops = mops;
+       info.priv = priv;
+-      return fpga_mgr_register_full(parent, &info);
++      return __fpga_mgr_register_full(parent, &info, owner);
+ }
+-EXPORT_SYMBOL_GPL(fpga_mgr_register);
++EXPORT_SYMBOL_GPL(__fpga_mgr_register);
+ /**
+  * fpga_mgr_unregister - unregister an FPGA manager
+@@ -900,9 +912,10 @@ static void devm_fpga_mgr_unregister(struct device *dev, void *res)
+ }
+ /**
+- * devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register()
++ * __devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register()
+  * @parent:   fpga manager device from pdev
+  * @info:     parameters for fpga manager
++ * @owner:    owner module containing the ops
+  *
+  * Return:  fpga manager pointer on success, negative error code otherwise.
+  *
+@@ -910,7 +923,8 @@ static void devm_fpga_mgr_unregister(struct device *dev, void *res)
+  * function will be called automatically when the managing device is detached.
+  */
+ struct fpga_manager *
+-devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info)
++__devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info,
++                            struct module *owner)
+ {
+       struct fpga_mgr_devres *dr;
+       struct fpga_manager *mgr;
+@@ -919,7 +933,7 @@ devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_inf
+       if (!dr)
+               return ERR_PTR(-ENOMEM);
+-      mgr = fpga_mgr_register_full(parent, info);
++      mgr = __fpga_mgr_register_full(parent, info, owner);
+       if (IS_ERR(mgr)) {
+               devres_free(dr);
+               return mgr;
+@@ -930,14 +944,15 @@ devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_inf
+       return mgr;
+ }
+-EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full);
++EXPORT_SYMBOL_GPL(__devm_fpga_mgr_register_full);
+ /**
+- * devm_fpga_mgr_register - resource managed variant of fpga_mgr_register()
++ * __devm_fpga_mgr_register - resource managed variant of fpga_mgr_register()
+  * @parent:   fpga manager device from pdev
+  * @name:     fpga manager name
+  * @mops:     pointer to structure of fpga manager ops
+  * @priv:     fpga manager private data
++ * @owner:    owner module containing the ops
+  *
+  * Return:  fpga manager pointer on success, negative error code otherwise.
+  *
+@@ -946,8 +961,9 @@ EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full);
+  * device is detached.
+  */
+ struct fpga_manager *
+-devm_fpga_mgr_register(struct device *parent, const char *name,
+-                     const struct fpga_manager_ops *mops, void *priv)
++__devm_fpga_mgr_register(struct device *parent, const char *name,
++                       const struct fpga_manager_ops *mops, void *priv,
++                       struct module *owner)
+ {
+       struct fpga_manager_info info = { 0 };
+@@ -955,9 +971,9 @@ devm_fpga_mgr_register(struct device *parent, const char *name,
+       info.mops = mops;
+       info.priv = priv;
+-      return devm_fpga_mgr_register_full(parent, &info);
++      return __devm_fpga_mgr_register_full(parent, &info, owner);
+ }
+-EXPORT_SYMBOL_GPL(devm_fpga_mgr_register);
++EXPORT_SYMBOL_GPL(__devm_fpga_mgr_register);
+ static void fpga_mgr_dev_release(struct device *dev)
+ {
+diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
+index 54f63459efd6e..0d4fe068f3d8a 100644
+--- a/include/linux/fpga/fpga-mgr.h
++++ b/include/linux/fpga/fpga-mgr.h
+@@ -201,6 +201,7 @@ struct fpga_manager_ops {
+  * @state: state of fpga manager
+  * @compat_id: FPGA manager id for compatibility check.
+  * @mops: pointer to struct of fpga manager ops
++ * @mops_owner: module containing the mops
+  * @priv: low level driver private date
+  */
+ struct fpga_manager {
+@@ -210,6 +211,7 @@ struct fpga_manager {
+       enum fpga_mgr_states state;
+       struct fpga_compat_id *compat_id;
+       const struct fpga_manager_ops *mops;
++      struct module *mops_owner;
+       void *priv;
+ };
+@@ -230,18 +232,30 @@ struct fpga_manager *fpga_mgr_get(struct device *dev);
+ void fpga_mgr_put(struct fpga_manager *mgr);
++#define fpga_mgr_register_full(parent, info) \
++      __fpga_mgr_register_full(parent, info, THIS_MODULE)
+ struct fpga_manager *
+-fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info);
++__fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info,
++                       struct module *owner);
++#define fpga_mgr_register(parent, name, mops, priv) \
++      __fpga_mgr_register(parent, name, mops, priv, THIS_MODULE)
+ struct fpga_manager *
+-fpga_mgr_register(struct device *parent, const char *name,
+-                const struct fpga_manager_ops *mops, void *priv);
++__fpga_mgr_register(struct device *parent, const char *name,
++                  const struct fpga_manager_ops *mops, void *priv, struct module *owner);
++
+ void fpga_mgr_unregister(struct fpga_manager *mgr);
++#define devm_fpga_mgr_register_full(parent, info) \
++      __devm_fpga_mgr_register_full(parent, info, THIS_MODULE)
+ struct fpga_manager *
+-devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info);
++__devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info,
++                            struct module *owner);
++#define devm_fpga_mgr_register(parent, name, mops, priv) \
++      __devm_fpga_mgr_register(parent, name, mops, priv, THIS_MODULE)
+ struct fpga_manager *
+-devm_fpga_mgr_register(struct device *parent, const char *name,
+-                     const struct fpga_manager_ops *mops, void *priv);
++__devm_fpga_mgr_register(struct device *parent, const char *name,
++                       const struct fpga_manager_ops *mops, void *priv,
++                       struct module *owner);
+ #endif /*_LINUX_FPGA_MGR_H */
+-- 
+2.43.0
+
diff --git a/queue-6.6/fpga-region-add-owner-module-and-take-its-refcount.patch b/queue-6.6/fpga-region-add-owner-module-and-take-its-refcount.patch
new file mode 100644 (file)
index 0000000..794230f
--- /dev/null
@@ -0,0 +1,210 @@
+From e448309464a231f0a26946c37eea42779a31be01 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Apr 2024 10:35:59 +0200
+Subject: fpga: region: add owner module and take its refcount
+
+From: Marco Pagani <marpagan@redhat.com>
+
+[ Upstream commit b7c0e1ecee403a43abc89eb3e75672b01ff2ece9 ]
+
+The current implementation of the fpga region assumes that the low-level
+module registers a driver for the parent device and uses its owner pointer
+to take the module's refcount. This approach is problematic since it can
+lead to a null pointer dereference while attempting to get the region
+during programming if the parent device does not have a driver.
+
+To address this problem, add a module owner pointer to the fpga_region
+struct and use it to take the module's refcount. Modify the functions for
+registering a region to take an additional owner module parameter and
+rename them to avoid conflicts. Use the old function names for helper
+macros that automatically set the module that registers the region as the
+owner. This ensures compatibility with existing low-level control modules
+and reduces the chances of registering a region without setting the owner.
+
+Also, update the documentation to keep it consistent with the new interface
+for registering an fpga region.
+
+Fixes: 0fa20cdfcc1f ("fpga: fpga-region: device tree control for FPGA")
+Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Suggested-by: Xu Yilun <yilun.xu@intel.com>
+Reviewed-by: Russ Weight <russ.weight@linux.dev>
+Signed-off-by: Marco Pagani <marpagan@redhat.com>
+Acked-by: Xu Yilun <yilun.xu@intel.com>
+Link: https://lore.kernel.org/r/20240419083601.77403-1-marpagan@redhat.com
+Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/driver-api/fpga/fpga-region.rst | 13 ++++++----
+ drivers/fpga/fpga-region.c                    | 24 +++++++++++--------
+ include/linux/fpga/fpga-region.h              | 13 +++++++---
+ 3 files changed, 32 insertions(+), 18 deletions(-)
+
+diff --git a/Documentation/driver-api/fpga/fpga-region.rst b/Documentation/driver-api/fpga/fpga-region.rst
+index dc55d60a0b4a5..2d03b5fb76575 100644
+--- a/Documentation/driver-api/fpga/fpga-region.rst
++++ b/Documentation/driver-api/fpga/fpga-region.rst
+@@ -46,13 +46,16 @@ API to add a new FPGA region
+ ----------------------------
+ * struct fpga_region - The FPGA region struct
+-* struct fpga_region_info - Parameter structure for fpga_region_register_full()
+-* fpga_region_register_full() -  Create and register an FPGA region using the
++* struct fpga_region_info - Parameter structure for __fpga_region_register_full()
++* __fpga_region_register_full() -  Create and register an FPGA region using the
+   fpga_region_info structure to provide the full flexibility of options
+-* fpga_region_register() -  Create and register an FPGA region using standard
++* __fpga_region_register() -  Create and register an FPGA region using standard
+   arguments
+ * fpga_region_unregister() -  Unregister an FPGA region
++Helper macros ``fpga_region_register()`` and ``fpga_region_register_full()``
++automatically set the module that registers the FPGA region as the owner.
++
+ The FPGA region's probe function will need to get a reference to the FPGA
+ Manager it will be using to do the programming.  This usually would happen
+ during the region's probe function.
+@@ -82,10 +85,10 @@ following APIs to handle building or tearing down that list.
+    :functions: fpga_region_info
+ .. kernel-doc:: drivers/fpga/fpga-region.c
+-   :functions: fpga_region_register_full
++   :functions: __fpga_region_register_full
+ .. kernel-doc:: drivers/fpga/fpga-region.c
+-   :functions: fpga_region_register
++   :functions: __fpga_region_register
+ .. kernel-doc:: drivers/fpga/fpga-region.c
+    :functions: fpga_region_unregister
+diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c
+index b364a929425ce..753cd142503e0 100644
+--- a/drivers/fpga/fpga-region.c
++++ b/drivers/fpga/fpga-region.c
+@@ -53,7 +53,7 @@ static struct fpga_region *fpga_region_get(struct fpga_region *region)
+       }
+       get_device(dev);
+-      if (!try_module_get(dev->parent->driver->owner)) {
++      if (!try_module_get(region->ops_owner)) {
+               put_device(dev);
+               mutex_unlock(&region->mutex);
+               return ERR_PTR(-ENODEV);
+@@ -75,7 +75,7 @@ static void fpga_region_put(struct fpga_region *region)
+       dev_dbg(dev, "put\n");
+-      module_put(dev->parent->driver->owner);
++      module_put(region->ops_owner);
+       put_device(dev);
+       mutex_unlock(&region->mutex);
+ }
+@@ -181,14 +181,16 @@ static struct attribute *fpga_region_attrs[] = {
+ ATTRIBUTE_GROUPS(fpga_region);
+ /**
+- * fpga_region_register_full - create and register an FPGA Region device
++ * __fpga_region_register_full - create and register an FPGA Region device
+  * @parent: device parent
+  * @info: parameters for FPGA Region
++ * @owner: module containing the get_bridges function
+  *
+  * Return: struct fpga_region or ERR_PTR()
+  */
+ struct fpga_region *
+-fpga_region_register_full(struct device *parent, const struct fpga_region_info *info)
++__fpga_region_register_full(struct device *parent, const struct fpga_region_info *info,
++                          struct module *owner)
+ {
+       struct fpga_region *region;
+       int id, ret = 0;
+@@ -213,6 +215,7 @@ fpga_region_register_full(struct device *parent, const struct fpga_region_info *
+       region->compat_id = info->compat_id;
+       region->priv = info->priv;
+       region->get_bridges = info->get_bridges;
++      region->ops_owner = owner;
+       mutex_init(&region->mutex);
+       INIT_LIST_HEAD(&region->bridge_list);
+@@ -241,13 +244,14 @@ fpga_region_register_full(struct device *parent, const struct fpga_region_info *
+       return ERR_PTR(ret);
+ }
+-EXPORT_SYMBOL_GPL(fpga_region_register_full);
++EXPORT_SYMBOL_GPL(__fpga_region_register_full);
+ /**
+- * fpga_region_register - create and register an FPGA Region device
++ * __fpga_region_register - create and register an FPGA Region device
+  * @parent: device parent
+  * @mgr: manager that programs this region
+  * @get_bridges: optional function to get bridges to a list
++ * @owner: module containing the get_bridges function
+  *
+  * This simple version of the register function should be sufficient for most users.
+  * The fpga_region_register_full() function is available for users that need to
+@@ -256,17 +260,17 @@ EXPORT_SYMBOL_GPL(fpga_region_register_full);
+  * Return: struct fpga_region or ERR_PTR()
+  */
+ struct fpga_region *
+-fpga_region_register(struct device *parent, struct fpga_manager *mgr,
+-                   int (*get_bridges)(struct fpga_region *))
++__fpga_region_register(struct device *parent, struct fpga_manager *mgr,
++                     int (*get_bridges)(struct fpga_region *), struct module *owner)
+ {
+       struct fpga_region_info info = { 0 };
+       info.mgr = mgr;
+       info.get_bridges = get_bridges;
+-      return fpga_region_register_full(parent, &info);
++      return __fpga_region_register_full(parent, &info, owner);
+ }
+-EXPORT_SYMBOL_GPL(fpga_region_register);
++EXPORT_SYMBOL_GPL(__fpga_region_register);
+ /**
+  * fpga_region_unregister - unregister an FPGA region
+diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h
+index 9d4d32909340a..5fbc05fe70a6b 100644
+--- a/include/linux/fpga/fpga-region.h
++++ b/include/linux/fpga/fpga-region.h
+@@ -36,6 +36,7 @@ struct fpga_region_info {
+  * @mgr: FPGA manager
+  * @info: FPGA image info
+  * @compat_id: FPGA region id for compatibility check.
++ * @ops_owner: module containing the get_bridges function
+  * @priv: private data
+  * @get_bridges: optional function to get bridges to a list
+  */
+@@ -46,6 +47,7 @@ struct fpga_region {
+       struct fpga_manager *mgr;
+       struct fpga_image_info *info;
+       struct fpga_compat_id *compat_id;
++      struct module *ops_owner;
+       void *priv;
+       int (*get_bridges)(struct fpga_region *region);
+ };
+@@ -58,12 +60,17 @@ fpga_region_class_find(struct device *start, const void *data,
+ int fpga_region_program_fpga(struct fpga_region *region);
++#define fpga_region_register_full(parent, info) \
++      __fpga_region_register_full(parent, info, THIS_MODULE)
+ struct fpga_region *
+-fpga_region_register_full(struct device *parent, const struct fpga_region_info *info);
++__fpga_region_register_full(struct device *parent, const struct fpga_region_info *info,
++                          struct module *owner);
++#define fpga_region_register(parent, mgr, get_bridges) \
++      __fpga_region_register(parent, mgr, get_bridges, THIS_MODULE)
+ struct fpga_region *
+-fpga_region_register(struct device *parent, struct fpga_manager *mgr,
+-                   int (*get_bridges)(struct fpga_region *));
++__fpga_region_register(struct device *parent, struct fpga_manager *mgr,
++                     int (*get_bridges)(struct fpga_region *), struct module *owner);
+ void fpga_region_unregister(struct fpga_region *region);
+ #endif /* _FPGA_REGION_H */
+-- 
+2.43.0
+
diff --git a/queue-6.6/fs-move-kiocb_start_write-into-vfs_iocb_iter_write.patch b/queue-6.6/fs-move-kiocb_start_write-into-vfs_iocb_iter_write.patch
new file mode 100644 (file)
index 0000000..aa2caff
--- /dev/null
@@ -0,0 +1,124 @@
+From 17f38d69e7960a2b346db04750b0e4ba867c0b83 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Nov 2023 14:27:12 +0200
+Subject: fs: move kiocb_start_write() into vfs_iocb_iter_write()
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+[ Upstream commit 6ae654392bb516a0baa47fed1f085d84e8cad739 ]
+
+In vfs code, sb_start_write() is usually called after the permission hook
+in rw_verify_area().  vfs_iocb_iter_write() is an exception to this rule,
+where kiocb_start_write() is called by its callers.
+
+Move kiocb_start_write() from the callers into vfs_iocb_iter_write()
+after the rw_verify_area() checks, to make them "start-write-safe".
+
+The semantics of vfs_iocb_iter_write() is changed, so that the caller is
+responsible for calling kiocb_end_write() on completion only if async
+iocb was queued.  The completion handlers of both callers were adapted
+to this semantic change.
+
+This is needed for fanotify "pre content" events.
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Suggested-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Link: https://lore.kernel.org/r/20231122122715.2561213-14-amir73il@gmail.com
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Stable-dep-of: 7c98f7cb8fda ("remove call_{read,write}_iter() functions")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cachefiles/io.c  | 5 ++---
+ fs/overlayfs/file.c | 8 ++++----
+ fs/read_write.c     | 7 +++++++
+ 3 files changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c
+index 009d23cd435b5..5857241c59181 100644
+--- a/fs/cachefiles/io.c
++++ b/fs/cachefiles/io.c
+@@ -259,7 +259,8 @@ static void cachefiles_write_complete(struct kiocb *iocb, long ret)
+       _enter("%ld", ret);
+-      kiocb_end_write(iocb);
++      if (ki->was_async)
++              kiocb_end_write(iocb);
+       if (ret < 0)
+               trace_cachefiles_io_error(object, inode, ret,
+@@ -319,8 +320,6 @@ int __cachefiles_write(struct cachefiles_object *object,
+               ki->iocb.ki_complete = cachefiles_write_complete;
+       atomic_long_add(ki->b_writing, &cache->b_writing);
+-      kiocb_start_write(&ki->iocb);
+-
+       get_file(ki->iocb.ki_filp);
+       cachefiles_grab_object(object, cachefiles_obj_get_ioreq);
+diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
+index 9fd88579bfbfb..a1c64c2b8e204 100644
+--- a/fs/overlayfs/file.c
++++ b/fs/overlayfs/file.c
+@@ -295,10 +295,8 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req)
+       struct kiocb *iocb = &aio_req->iocb;
+       struct kiocb *orig_iocb = aio_req->orig_iocb;
+-      if (iocb->ki_flags & IOCB_WRITE) {
+-              kiocb_end_write(iocb);
++      if (iocb->ki_flags & IOCB_WRITE)
+               ovl_file_modified(orig_iocb->ki_filp);
+-      }
+       orig_iocb->ki_pos = iocb->ki_pos;
+       ovl_aio_put(aio_req);
+@@ -310,6 +308,9 @@ static void ovl_aio_rw_complete(struct kiocb *iocb, long res)
+                                                  struct ovl_aio_req, iocb);
+       struct kiocb *orig_iocb = aio_req->orig_iocb;
++      if (iocb->ki_flags & IOCB_WRITE)
++              kiocb_end_write(iocb);
++
+       ovl_aio_cleanup_handler(aio_req);
+       orig_iocb->ki_complete(orig_iocb, res);
+ }
+@@ -421,7 +422,6 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
+               aio_req->iocb.ki_flags = ifl;
+               aio_req->iocb.ki_complete = ovl_aio_rw_complete;
+               refcount_set(&aio_req->ref, 2);
+-              kiocb_start_write(&aio_req->iocb);
+               ret = vfs_iocb_iter_write(real.file, &aio_req->iocb, iter);
+               ovl_aio_put(aio_req);
+               if (ret != -EIOCBQUEUED)
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 4771701c896ba..9a56949f3b8d1 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -865,6 +865,10 @@ static ssize_t do_iter_write(struct file *file, struct iov_iter *iter,
+       return ret;
+ }
++/*
++ * Caller is responsible for calling kiocb_end_write() on completion
++ * if async iocb was queued.
++ */
+ ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
+                           struct iov_iter *iter)
+ {
+@@ -885,7 +889,10 @@ ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
+       if (ret < 0)
+               return ret;
++      kiocb_start_write(iocb);
+       ret = call_write_iter(file, iocb, iter);
++      if (ret != -EIOCBQUEUED)
++              kiocb_end_write(iocb);
+       if (ret > 0)
+               fsnotify_modify(file);
+-- 
+2.43.0
+
diff --git a/queue-6.6/gpiolib-acpi-fix-failed-in-acpi_gpiochip_find-by-add.patch b/queue-6.6/gpiolib-acpi-fix-failed-in-acpi_gpiochip_find-by-add.patch
new file mode 100644 (file)
index 0000000..c15f170
--- /dev/null
@@ -0,0 +1,84 @@
+From eb920a49d7241aa61732a1a9a086ae7918d74fe3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 May 2024 15:59:01 +0800
+Subject: gpiolib: acpi: Fix failed in acpi_gpiochip_find() by adding parent
+ node match
+
+From: Devyn Liu <liudingyuan@huawei.com>
+
+[ Upstream commit adbc49a5a8c6fcf7be154c2e30213bbf472940da ]
+
+Previous patch modified the standard used by acpi_gpiochip_find()
+to match device nodes. Using the device node set in gc->gpiodev->d-
+ev instead of gc->parent.
+
+However, there is a situation in gpio-dwapb where the GPIO device
+driver will set gc->fwnode for each port corresponding to a child
+node under a GPIO device, so gc->gpiodev->dev will be assigned the
+value of each child node in gpiochip_add_data().
+
+gpio-dwapb.c:
+128,31 static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
+                              struct dwapb_port_property *pp,
+                              unsigned int offs);
+port->gc.fwnode = pp->fwnode;
+
+693,39 static int dwapb_gpio_probe;
+err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i);
+
+When other drivers request GPIO pin resources through the GPIO device
+node provided by ACPI (corresponding to the parent node), the change
+of the matching object to gc->gpiodev->dev in acpi_gpiochip_find()
+only allows finding the value of each port (child node), resulting
+in a failed request.
+
+Reapply the condition of using gc->parent for match in acpi_gpio-
+chip_find() in the code can compatible with the problem of gpio-dwapb,
+and will not affect the two cases mentioned in the patch:
+1. There is no setting for gc->fwnode.
+2. The case that depends on using gc->fwnode for match.
+
+Fixes: 5062e4c14b75 ("gpiolib: acpi: use the fwnode in acpi_gpiochip_find()")
+Fixes: 067dbc1ea5ce ("gpiolib: acpi: Don't use GPIO chip fwnode in acpi_gpiochip_find()")
+Signed-off-by: Devyn Liu <liudingyuan@huawei.com>
+Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Tested-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpiolib-acpi.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
+index 4ab33d55aec47..b366b4ca4c40e 100644
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -128,7 +128,24 @@ static bool acpi_gpio_deferred_req_irqs_done;
+ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
+ {
+-      return device_match_acpi_handle(&gc->gpiodev->dev, data);
++      /* First check the actual GPIO device */
++      if (device_match_acpi_handle(&gc->gpiodev->dev, data))
++              return true;
++
++      /*
++       * When the ACPI device is artificially split to the banks of GPIOs,
++       * where each of them is represented by a separate GPIO device,
++       * the firmware node of the physical device may not be shared among
++       * the banks as they may require different values for the same property,
++       * e.g., number of GPIOs in a certain bank. In such case the ACPI handle
++       * of a GPIO device is NULL and can not be used. Hence we have to check
++       * the parent device to be sure that there is no match before bailing
++       * out.
++       */
++      if (gc->parent)
++              return device_match_acpi_handle(gc->parent, data);
++
++      return false;
+ }
+ /**
+-- 
+2.43.0
+
diff --git a/queue-6.6/greybus-arche-ctrl-move-device-table-to-its-right-lo.patch b/queue-6.6/greybus-arche-ctrl-move-device-table-to-its-right-lo.patch
new file mode 100644 (file)
index 0000000..e80d071
--- /dev/null
@@ -0,0 +1,66 @@
+From 06c24eea0b36ec38cf2271c1367ab97973fd55f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Apr 2024 10:06:35 +0200
+Subject: greybus: arche-ctrl: move device table to its right location
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 6a0b8c0da8d8d418cde6894a104cf74e6098ddfa ]
+
+The arche-ctrl has two platform drivers and three of_device_id tables,
+but one table is only used for the the module loader, while the other
+two seem to be associated with their drivers.
+
+This leads to a W=1 warning when the driver is built-in:
+
+drivers/staging/greybus/arche-platform.c:623:34: error: 'arche_combined_id' defined but not used [-Werror=unused-const-variable=]
+  623 | static const struct of_device_id arche_combined_id[] = {
+
+Drop the extra table and register both tables that are actually
+used as the ones for the module loader instead.
+
+Fixes: 7b62b61c752a ("greybus: arche-ctrl: Don't expose driver internals to arche-platform driver")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Link: https://lore.kernel.org/r/20240403080702.3509288-18-arnd@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/staging/greybus/arche-apb-ctrl.c | 1 +
+ drivers/staging/greybus/arche-platform.c | 9 +--------
+ 2 files changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c
+index 8541995008da8..aa6f266b62a14 100644
+--- a/drivers/staging/greybus/arche-apb-ctrl.c
++++ b/drivers/staging/greybus/arche-apb-ctrl.c
+@@ -466,6 +466,7 @@ static const struct of_device_id arche_apb_ctrl_of_match[] = {
+       { .compatible = "usbffff,2", },
+       { },
+ };
++MODULE_DEVICE_TABLE(of, arche_apb_ctrl_of_match);
+ static struct platform_driver arche_apb_ctrl_device_driver = {
+       .probe          = arche_apb_ctrl_probe,
+diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c
+index 891b75327d7f7..b33977ccd5271 100644
+--- a/drivers/staging/greybus/arche-platform.c
++++ b/drivers/staging/greybus/arche-platform.c
+@@ -619,14 +619,7 @@ static const struct of_device_id arche_platform_of_match[] = {
+       { .compatible = "google,arche-platform", },
+       { },
+ };
+-
+-static const struct of_device_id arche_combined_id[] = {
+-      /* Use PID/VID of SVC device */
+-      { .compatible = "google,arche-platform", },
+-      { .compatible = "usbffff,2", },
+-      { },
+-};
+-MODULE_DEVICE_TABLE(of, arche_combined_id);
++MODULE_DEVICE_TABLE(of, arche_platform_of_match);
+ static struct platform_driver arche_platform_device_driver = {
+       .probe          = arche_platform_probe,
+-- 
+2.43.0
+
diff --git a/queue-6.6/greybus-lights-check-return-of-get_channel_from_mode.patch b/queue-6.6/greybus-lights-check-return-of-get_channel_from_mode.patch
new file mode 100644 (file)
index 0000000..13626d7
--- /dev/null
@@ -0,0 +1,59 @@
+From 2928cc9c487100622fe61916e81935726560a001 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Mar 2024 22:09:55 +0000
+Subject: greybus: lights: check return of get_channel_from_mode
+
+From: Rui Miguel Silva <rmfrfs@gmail.com>
+
+[ Upstream commit a1ba19a1ae7cd1e324685ded4ab563e78fe68648 ]
+
+If channel for the given node is not found we return null from
+get_channel_from_mode. Make sure we validate the return pointer
+before using it in two of the missing places.
+
+This was originally reported in [0]:
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+[0] https://lore.kernel.org/all/20240301190425.120605-1-m.lobanov@rosalinux.ru
+
+Fixes: 2870b52bae4c ("greybus: lights: add lights implementation")
+Reported-by: Mikhail Lobanov <m.lobanov@rosalinux.ru>
+Suggested-by: Mikhail Lobanov <m.lobanov@rosalinux.ru>
+Suggested-by: Alex Elder <elder@ieee.org>
+Signed-off-by: Rui Miguel Silva <rmfrfs@gmail.com>
+Link: https://lore.kernel.org/r/20240325221549.2185265-1-rmfrfs@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/staging/greybus/light.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c
+index c6bd86a5335ab..9999f84016992 100644
+--- a/drivers/staging/greybus/light.c
++++ b/drivers/staging/greybus/light.c
+@@ -147,6 +147,9 @@ static int __gb_lights_flash_brightness_set(struct gb_channel *channel)
+               channel = get_channel_from_mode(channel->light,
+                                               GB_CHANNEL_MODE_TORCH);
++      if (!channel)
++              return -EINVAL;
++
+       /* For not flash we need to convert brightness to intensity */
+       intensity = channel->intensity_uA.min +
+                       (channel->intensity_uA.step * channel->led->brightness);
+@@ -549,7 +552,10 @@ static int gb_lights_light_v4l2_register(struct gb_light *light)
+       }
+       channel_flash = get_channel_from_mode(light, GB_CHANNEL_MODE_FLASH);
+-      WARN_ON(!channel_flash);
++      if (!channel_flash) {
++              dev_err(dev, "failed to get flash channel from mode\n");
++              return -EINVAL;
++      }
+       fled = &channel_flash->fled;
+-- 
+2.43.0
+
diff --git a/queue-6.6/i2c-cadence-avoid-fifo-clear-after-start.patch b/queue-6.6/i2c-cadence-avoid-fifo-clear-after-start.patch
new file mode 100644 (file)
index 0000000..1cf16c5
--- /dev/null
@@ -0,0 +1,39 @@
+From ec8cff744bbcacfc5c9683e2391a2c9564760b5d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 May 2024 15:12:08 +0530
+Subject: i2c: cadence: Avoid fifo clear after start
+
+From: Sai Pavan Boddu <sai.pavan.boddu@amd.com>
+
+[ Upstream commit c2e55b449de7298a751ed0256251019d302af453 ]
+
+The Driver unintentionally programs ctrl reg to clear the fifo, which
+happens after the start of transaction. Previously, this was not an issue
+as it involved read-modified-write. However, this issue breaks i2c reads
+on QEMU, as i2c-read is executed before guest starts programming control
+register.
+
+Fixes: ff0cf7bca630 ("i2c: cadence: Remove unnecessary register reads")
+Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@amd.com>
+Acked-by: Michal Simek <michal.simek@amd.com>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-cadence.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
+index de3f58b60dce5..6f7d753a8197c 100644
+--- a/drivers/i2c/busses/i2c-cadence.c
++++ b/drivers/i2c/busses/i2c-cadence.c
+@@ -633,6 +633,7 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
+       if (hold_clear) {
+               ctrl_reg &= ~CDNS_I2C_CR_HOLD;
++              ctrl_reg &= ~CDNS_I2C_CR_CLR_FIFO;
+               /*
+                * In case of Xilinx Zynq SOC, clear the HOLD bit before transfer size
+                * register reaches '0'. This is an IP bug which causes transfer size
+-- 
+2.43.0
+
diff --git a/queue-6.6/i2c-synquacer-fix-an-error-handling-path-in-synquace.patch b/queue-6.6/i2c-synquacer-fix-an-error-handling-path-in-synquace.patch
new file mode 100644 (file)
index 0000000..1082907
--- /dev/null
@@ -0,0 +1,69 @@
+From 69dbca8f3b255c5fb15b984ee0fb7dafcd49f493 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 6 Jan 2024 13:48:24 +0100
+Subject: i2c: synquacer: Fix an error handling path in synquacer_i2c_probe()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 55750148e5595bb85605e8fbb40b2759c2c4c2d7 ]
+
+If an error occurs after the clk_prepare_enable() call, it should be undone
+by a corresponding clk_disable_unprepare() call, as already done in the
+remove() function.
+
+As devm_clk_get() is used, we can switch to devm_clk_get_enabled() to
+handle it automatically and fix the probe.
+
+Update the remove() function accordingly and remove the now useless
+clk_disable_unprepare() call.
+
+Fixes: 0d676a6c4390 ("i2c: add support for Socionext SynQuacer I2C controller")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Acked-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-synquacer.c | 20 +++++++-------------
+ 1 file changed, 7 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c
+index bbea521b05dda..a73f5bb9a1645 100644
+--- a/drivers/i2c/busses/i2c-synquacer.c
++++ b/drivers/i2c/busses/i2c-synquacer.c
+@@ -550,17 +550,13 @@ static int synquacer_i2c_probe(struct platform_device *pdev)
+       device_property_read_u32(&pdev->dev, "socionext,pclk-rate",
+                                &i2c->pclkrate);
+-      i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
+-      if (PTR_ERR(i2c->pclk) == -EPROBE_DEFER)
+-              return -EPROBE_DEFER;
+-      if (!IS_ERR_OR_NULL(i2c->pclk)) {
+-              dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk);
+-
+-              ret = clk_prepare_enable(i2c->pclk);
+-              if (ret)
+-                      return dev_err_probe(&pdev->dev, ret, "failed to enable clock\n");
+-              i2c->pclkrate = clk_get_rate(i2c->pclk);
+-      }
++      i2c->pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
++      if (IS_ERR(i2c->pclk))
++              return dev_err_probe(&pdev->dev, PTR_ERR(i2c->pclk),
++                                   "failed to get and enable clock\n");
++
++      dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk);
++      i2c->pclkrate = clk_get_rate(i2c->pclk);
+       if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE ||
+           i2c->pclkrate > SYNQUACER_I2C_MAX_CLK_RATE)
+@@ -615,8 +611,6 @@ static void synquacer_i2c_remove(struct platform_device *pdev)
+       struct synquacer_i2c *i2c = platform_get_drvdata(pdev);
+       i2c_del_adapter(&i2c->adapter);
+-      if (!IS_ERR(i2c->pclk))
+-              clk_disable_unprepare(i2c->pclk);
+ };
+ static const struct of_device_id synquacer_i2c_dt_ids[] __maybe_unused = {
+-- 
+2.43.0
+
diff --git a/queue-6.6/i915-make-inject_virtual_interrupt-void.patch b/queue-6.6/i915-make-inject_virtual_interrupt-void.patch
new file mode 100644 (file)
index 0000000..b54b8f5
--- /dev/null
@@ -0,0 +1,67 @@
+From 01670f96015fe9de702a40cc6213190f41bc262f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Nov 2023 13:48:22 +0100
+Subject: i915: make inject_virtual_interrupt() void
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit 85884871921000b9bca2184077b1159771e50047 ]
+
+The single caller of inject_virtual_interrupt() ignores the return value
+anyway. This allows us to simplify eventfd_signal() in follow-up
+patches.
+
+Link: https://lore.kernel.org/r/20231122-vfs-eventfd-signal-v2-1-bd549b14ce0c@kernel.org
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Reviewed-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Stable-dep-of: 82b951e6fbd3 ("vfio/pci: fix potential memory leak in vfio_intx_enable()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/gvt/interrupt.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c
+index 68eca023bbc68..80301472ac988 100644
+--- a/drivers/gpu/drm/i915/gvt/interrupt.c
++++ b/drivers/gpu/drm/i915/gvt/interrupt.c
+@@ -405,7 +405,7 @@ static void init_irq_map(struct intel_gvt_irq *irq)
+ #define MSI_CAP_DATA(offset) (offset + 8)
+ #define MSI_CAP_EN 0x1
+-static int inject_virtual_interrupt(struct intel_vgpu *vgpu)
++static void inject_virtual_interrupt(struct intel_vgpu *vgpu)
+ {
+       unsigned long offset = vgpu->gvt->device_info.msi_cap_offset;
+       u16 control, data;
+@@ -417,10 +417,10 @@ static int inject_virtual_interrupt(struct intel_vgpu *vgpu)
+       /* Do not generate MSI if MSIEN is disabled */
+       if (!(control & MSI_CAP_EN))
+-              return 0;
++              return;
+       if (WARN(control & GENMASK(15, 1), "only support one MSI format\n"))
+-              return -EINVAL;
++              return;
+       trace_inject_msi(vgpu->id, addr, data);
+@@ -434,10 +434,9 @@ static int inject_virtual_interrupt(struct intel_vgpu *vgpu)
+        * returned and don't inject interrupt into guest.
+        */
+       if (!test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status))
+-              return -ESRCH;
+-      if (vgpu->msi_trigger && eventfd_signal(vgpu->msi_trigger, 1) != 1)
+-              return -EFAULT;
+-      return 0;
++              return;
++      if (vgpu->msi_trigger)
++              eventfd_signal(vgpu->msi_trigger, 1);
+ }
+ static void propagate_event(struct intel_gvt_irq *irq,
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-accel-mxc4005-allow-module-autoloading-via-of-co.patch b/queue-6.6/iio-accel-mxc4005-allow-module-autoloading-via-of-co.patch
new file mode 100644 (file)
index 0000000..e986676
--- /dev/null
@@ -0,0 +1,51 @@
+From b9747a492b4e0bfdbc6c2d1ee29a820d5a047e98 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Oct 2023 18:39:28 +0200
+Subject: iio: accel: mxc4005: allow module autoloading via OF compatible
+
+From: Luca Ceresoli <luca.ceresoli@bootlin.com>
+
+[ Upstream commit 4d7c16d08d248952c116f2eb9b7b5abc43a19688 ]
+
+Add OF device table with compatible strings to allow automatic module
+loading.
+
+Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20231004-mxc4005-device-tree-support-v1-2-e7c0faea72e4@bootlin.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 6b8cffdc4a31 ("iio: accel: mxc4005: Reset chip on probe() and resume()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/accel/mxc4005.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
+index b608aa5467175..88f0bf2cc1d3f 100644
+--- a/drivers/iio/accel/mxc4005.c
++++ b/drivers/iio/accel/mxc4005.c
+@@ -486,6 +486,13 @@ static const struct acpi_device_id mxc4005_acpi_match[] = {
+ };
+ MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);
++static const struct of_device_id mxc4005_of_match[] = {
++      { .compatible = "memsic,mxc4005", },
++      { .compatible = "memsic,mxc6655", },
++      { },
++};
++MODULE_DEVICE_TABLE(of, mxc4005_of_match);
++
+ static const struct i2c_device_id mxc4005_id[] = {
+       {"mxc4005",     0},
+       {"mxc6655",     0},
+@@ -497,6 +504,7 @@ static struct i2c_driver mxc4005_driver = {
+       .driver = {
+               .name = MXC4005_DRV_NAME,
+               .acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
++              .of_match_table = mxc4005_of_match,
+       },
+       .probe          = mxc4005_probe,
+       .id_table       = mxc4005_id,
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-accel-mxc4005-reset-chip-on-probe-and-resume.patch b/queue-6.6/iio-accel-mxc4005-reset-chip-on-probe-and-resume.patch
new file mode 100644 (file)
index 0000000..581afbd
--- /dev/null
@@ -0,0 +1,157 @@
+From dd372280e1259450dc919caf5f1cd84787bf9e75 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Mar 2024 12:37:00 +0100
+Subject: iio: accel: mxc4005: Reset chip on probe() and resume()
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 6b8cffdc4a31e4a72f75ecd1bc13fbf0dafee390 ]
+
+On some designs the chip is not properly reset when powered up at boot or
+after a suspend/resume cycle.
+
+Use the sw-reset feature to ensure that the chip is in a clean state
+after probe() / resume() and in the case of resume() restore the settings
+(scale, trigger-enabled).
+
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218578
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20240326113700.56725-3-hdegoede@redhat.com
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/accel/mxc4005.c | 68 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 68 insertions(+)
+
+diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
+index 88f0bf2cc1d3f..49e30b87732f5 100644
+--- a/drivers/iio/accel/mxc4005.c
++++ b/drivers/iio/accel/mxc4005.c
+@@ -5,6 +5,7 @@
+  * Copyright (c) 2014, Intel Corporation.
+  */
++#include <linux/delay.h>
+ #include <linux/module.h>
+ #include <linux/i2c.h>
+ #include <linux/iio/iio.h>
+@@ -36,6 +37,7 @@
+ #define MXC4005_REG_INT_CLR1          0x01
+ #define MXC4005_REG_INT_CLR1_BIT_DRDYC        0x01
++#define MXC4005_REG_INT_CLR1_SW_RST   0x10
+ #define MXC4005_REG_CONTROL           0x0D
+ #define MXC4005_REG_CONTROL_MASK_FSR  GENMASK(6, 5)
+@@ -43,6 +45,9 @@
+ #define MXC4005_REG_DEVICE_ID         0x0E
++/* Datasheet does not specify a reset time, this is a conservative guess */
++#define MXC4005_RESET_TIME_US         2000
++
+ enum mxc4005_axis {
+       AXIS_X,
+       AXIS_Y,
+@@ -66,6 +71,8 @@ struct mxc4005_data {
+               s64 timestamp __aligned(8);
+       } scan;
+       bool trigger_enabled;
++      unsigned int control;
++      unsigned int int_mask1;
+ };
+ /*
+@@ -349,6 +356,7 @@ static int mxc4005_set_trigger_state(struct iio_trigger *trig,
+               return ret;
+       }
++      data->int_mask1 = val;
+       data->trigger_enabled = state;
+       mutex_unlock(&data->mutex);
+@@ -384,6 +392,13 @@ static int mxc4005_chip_init(struct mxc4005_data *data)
+       dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);
++      ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
++                         MXC4005_REG_INT_CLR1_SW_RST);
++      if (ret < 0)
++              return dev_err_probe(data->dev, ret, "resetting chip\n");
++
++      fsleep(MXC4005_RESET_TIME_US);
++
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
+       if (ret < 0)
+               return dev_err_probe(data->dev, ret, "writing INT_MASK0\n");
+@@ -479,6 +494,58 @@ static int mxc4005_probe(struct i2c_client *client)
+       return devm_iio_device_register(&client->dev, indio_dev);
+ }
++static int mxc4005_suspend(struct device *dev)
++{
++      struct iio_dev *indio_dev = dev_get_drvdata(dev);
++      struct mxc4005_data *data = iio_priv(indio_dev);
++      int ret;
++
++      /* Save control to restore it on resume */
++      ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &data->control);
++      if (ret < 0)
++              dev_err(data->dev, "failed to read reg_control\n");
++
++      return ret;
++}
++
++static int mxc4005_resume(struct device *dev)
++{
++      struct iio_dev *indio_dev = dev_get_drvdata(dev);
++      struct mxc4005_data *data = iio_priv(indio_dev);
++      int ret;
++
++      ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
++                         MXC4005_REG_INT_CLR1_SW_RST);
++      if (ret) {
++              dev_err(data->dev, "failed to reset chip: %d\n", ret);
++              return ret;
++      }
++
++      fsleep(MXC4005_RESET_TIME_US);
++
++      ret = regmap_write(data->regmap, MXC4005_REG_CONTROL, data->control);
++      if (ret) {
++              dev_err(data->dev, "failed to restore control register\n");
++              return ret;
++      }
++
++      ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
++      if (ret) {
++              dev_err(data->dev, "failed to restore interrupt 0 mask\n");
++              return ret;
++      }
++
++      ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, data->int_mask1);
++      if (ret) {
++              dev_err(data->dev, "failed to restore interrupt 1 mask\n");
++              return ret;
++      }
++
++      return 0;
++}
++
++static DEFINE_SIMPLE_DEV_PM_OPS(mxc4005_pm_ops, mxc4005_suspend, mxc4005_resume);
++
+ static const struct acpi_device_id mxc4005_acpi_match[] = {
+       {"MXC4005",     0},
+       {"MXC6655",     0},
+@@ -505,6 +572,7 @@ static struct i2c_driver mxc4005_driver = {
+               .name = MXC4005_DRV_NAME,
+               .acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
+               .of_match_table = mxc4005_of_match,
++              .pm = pm_sleep_ptr(&mxc4005_pm_ops),
+       },
+       .probe          = mxc4005_probe,
+       .id_table       = mxc4005_id,
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-ad9467-convert-to-backend-framework.patch b/queue-6.6/iio-adc-ad9467-convert-to-backend-framework.patch
new file mode 100644 (file)
index 0000000..a05b078
--- /dev/null
@@ -0,0 +1,515 @@
+From 16a32525a438c8d778b3eb90afa0d1c08899c829 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 10 Feb 2024 21:57:18 +0100
+Subject: iio: adc: ad9467: convert to backend framework
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit bb42191f85c389bf816373d25c3e4c94045cf4ff ]
+
+Convert the driver to use the new IIO backend framework. The device
+functionality is expected to be the same (meaning no added or removed
+features).
+
+Also note this patch effectively breaks ABI and that's needed so we can
+properly support this device and add needed features making use of the
+new IIO framework.
+
+Given the lack of features (and devices supported) in the ad9467 driver
+compared with the ADI out of tree version, we don't expect any user of
+the upstream driver so no one should notice the ABI breakage. However,
+if someone is affected by this, ADI will happily support transitioning
+to the backend framework.
+
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20240210-iio-backend-v11-6-f5242a5fb42a@analog.com
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/Kconfig  |   2 +-
+ drivers/iio/adc/ad9467.c | 267 ++++++++++++++++++++++++++-------------
+ 2 files changed, 178 insertions(+), 91 deletions(-)
+
+diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
+index 0b94bda8be361..ae789d427b213 100644
+--- a/drivers/iio/adc/Kconfig
++++ b/drivers/iio/adc/Kconfig
+@@ -275,7 +275,7 @@ config AD799X
+ config AD9467
+       tristate "Analog Devices AD9467 High Speed ADC driver"
+       depends on SPI
+-      depends on ADI_AXI_ADC
++      select IIO_BACKEND
+       help
+         Say yes here to build support for Analog Devices:
+         * AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter
+diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
+index c5ed62cc86465..863dca5db161e 100644
+--- a/drivers/iio/adc/ad9467.c
++++ b/drivers/iio/adc/ad9467.c
+@@ -17,13 +17,12 @@
+ #include <linux/of.h>
++#include <linux/iio/backend.h>
+ #include <linux/iio/iio.h>
+ #include <linux/iio/sysfs.h>
+ #include <linux/clk.h>
+-#include <linux/iio/adc/adi-axi-adc.h>
+-
+ /*
+  * ADI High-Speed ADC common spi interface registers
+  * See Application-Note AN-877:
+@@ -102,15 +101,20 @@
+ #define AD9467_REG_VREF_MASK          0x0F
+ struct ad9467_chip_info {
+-      struct adi_axi_adc_chip_info    axi_adc_info;
+-      unsigned int                    default_output_mode;
+-      unsigned int                    vref_mask;
++      const char              *name;
++      unsigned int            id;
++      const struct            iio_chan_spec *channels;
++      unsigned int            num_channels;
++      const unsigned int      (*scale_table)[2];
++      int                     num_scales;
++      unsigned long           max_rate;
++      unsigned int            default_output_mode;
++      unsigned int            vref_mask;
+ };
+-#define to_ad9467_chip_info(_info)    \
+-      container_of(_info, struct ad9467_chip_info, axi_adc_info)
+-
+ struct ad9467_state {
++      const struct ad9467_chip_info   *info;
++      struct iio_backend              *back;
+       struct spi_device               *spi;
+       struct clk                      *clk;
+       unsigned int                    output_mode;
+@@ -151,10 +155,10 @@ static int ad9467_spi_write(struct spi_device *spi, unsigned int reg,
+       return spi_write(spi, buf, ARRAY_SIZE(buf));
+ }
+-static int ad9467_reg_access(struct adi_axi_adc_conv *conv, unsigned int reg,
++static int ad9467_reg_access(struct iio_dev *indio_dev, unsigned int reg,
+                            unsigned int writeval, unsigned int *readval)
+ {
+-      struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
++      struct ad9467_state *st = iio_priv(indio_dev);
+       struct spi_device *spi = st->spi;
+       int ret;
+@@ -191,10 +195,10 @@ static const unsigned int ad9467_scale_table[][2] = {
+       {2300, 8}, {2400, 9}, {2500, 10},
+ };
+-static void __ad9467_get_scale(struct adi_axi_adc_conv *conv, int index,
++static void __ad9467_get_scale(struct ad9467_state *st, int index,
+                              unsigned int *val, unsigned int *val2)
+ {
+-      const struct adi_axi_adc_chip_info *info = conv->chip_info;
++      const struct ad9467_chip_info *info = st->info;
+       const struct iio_chan_spec *chan = &info->channels[0];
+       unsigned int tmp;
+@@ -229,52 +233,44 @@ static const struct iio_chan_spec ad9467_channels[] = {
+ };
+ static const struct ad9467_chip_info ad9467_chip_tbl = {
+-      .axi_adc_info = {
+-              .name = "ad9467",
+-              .id = CHIPID_AD9467,
+-              .max_rate = 250000000UL,
+-              .scale_table = ad9467_scale_table,
+-              .num_scales = ARRAY_SIZE(ad9467_scale_table),
+-              .channels = ad9467_channels,
+-              .num_channels = ARRAY_SIZE(ad9467_channels),
+-      },
++      .name = "ad9467",
++      .id = CHIPID_AD9467,
++      .max_rate = 250000000UL,
++      .scale_table = ad9467_scale_table,
++      .num_scales = ARRAY_SIZE(ad9467_scale_table),
++      .channels = ad9467_channels,
++      .num_channels = ARRAY_SIZE(ad9467_channels),
+       .default_output_mode = AD9467_DEF_OUTPUT_MODE,
+       .vref_mask = AD9467_REG_VREF_MASK,
+ };
+ static const struct ad9467_chip_info ad9434_chip_tbl = {
+-      .axi_adc_info = {
+-              .name = "ad9434",
+-              .id = CHIPID_AD9434,
+-              .max_rate = 500000000UL,
+-              .scale_table = ad9434_scale_table,
+-              .num_scales = ARRAY_SIZE(ad9434_scale_table),
+-              .channels = ad9434_channels,
+-              .num_channels = ARRAY_SIZE(ad9434_channels),
+-      },
++      .name = "ad9434",
++      .id = CHIPID_AD9434,
++      .max_rate = 500000000UL,
++      .scale_table = ad9434_scale_table,
++      .num_scales = ARRAY_SIZE(ad9434_scale_table),
++      .channels = ad9434_channels,
++      .num_channels = ARRAY_SIZE(ad9434_channels),
+       .default_output_mode = AD9434_DEF_OUTPUT_MODE,
+       .vref_mask = AD9434_REG_VREF_MASK,
+ };
+ static const struct ad9467_chip_info ad9265_chip_tbl = {
+-      .axi_adc_info = {
+-              .name = "ad9265",
+-              .id = CHIPID_AD9265,
+-              .max_rate = 125000000UL,
+-              .scale_table = ad9265_scale_table,
+-              .num_scales = ARRAY_SIZE(ad9265_scale_table),
+-              .channels = ad9467_channels,
+-              .num_channels = ARRAY_SIZE(ad9467_channels),
+-      },
++      .name = "ad9265",
++      .id = CHIPID_AD9265,
++      .max_rate = 125000000UL,
++      .scale_table = ad9265_scale_table,
++      .num_scales = ARRAY_SIZE(ad9265_scale_table),
++      .channels = ad9467_channels,
++      .num_channels = ARRAY_SIZE(ad9467_channels),
+       .default_output_mode = AD9265_DEF_OUTPUT_MODE,
+       .vref_mask = AD9265_REG_VREF_MASK,
+ };
+-static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
++static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2)
+ {
+-      const struct adi_axi_adc_chip_info *info = conv->chip_info;
+-      const struct ad9467_chip_info *info1 = to_ad9467_chip_info(info);
+-      struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
++      const struct ad9467_chip_info *info = st->info;
+       unsigned int i, vref_val;
+       int ret;
+@@ -282,7 +278,7 @@ static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
+       if (ret < 0)
+               return ret;
+-      vref_val = ret & info1->vref_mask;
++      vref_val = ret & info->vref_mask;
+       for (i = 0; i < info->num_scales; i++) {
+               if (vref_val == info->scale_table[i][1])
+@@ -292,15 +288,14 @@ static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
+       if (i == info->num_scales)
+               return -ERANGE;
+-      __ad9467_get_scale(conv, i, val, val2);
++      __ad9467_get_scale(st, i, val, val2);
+       return IIO_VAL_INT_PLUS_MICRO;
+ }
+-static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)
++static int ad9467_set_scale(struct ad9467_state *st, int val, int val2)
+ {
+-      const struct adi_axi_adc_chip_info *info = conv->chip_info;
+-      struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
++      const struct ad9467_chip_info *info = st->info;
+       unsigned int scale_val[2];
+       unsigned int i;
+       int ret;
+@@ -309,7 +304,7 @@ static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)
+               return -EINVAL;
+       for (i = 0; i < info->num_scales; i++) {
+-              __ad9467_get_scale(conv, i, &scale_val[0], &scale_val[1]);
++              __ad9467_get_scale(st, i, &scale_val[0], &scale_val[1]);
+               if (scale_val[0] != val || scale_val[1] != val2)
+                       continue;
+@@ -326,15 +321,15 @@ static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)
+       return -EINVAL;
+ }
+-static int ad9467_read_raw(struct adi_axi_adc_conv *conv,
++static int ad9467_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan,
+                          int *val, int *val2, long m)
+ {
+-      struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
++      struct ad9467_state *st = iio_priv(indio_dev);
+       switch (m) {
+       case IIO_CHAN_INFO_SCALE:
+-              return ad9467_get_scale(conv, val, val2);
++              return ad9467_get_scale(st, val, val2);
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               *val = clk_get_rate(st->clk);
+@@ -344,17 +339,17 @@ static int ad9467_read_raw(struct adi_axi_adc_conv *conv,
+       }
+ }
+-static int ad9467_write_raw(struct adi_axi_adc_conv *conv,
++static int ad9467_write_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int val, int val2, long mask)
+ {
+-      const struct adi_axi_adc_chip_info *info = conv->chip_info;
+-      struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
++      struct ad9467_state *st = iio_priv(indio_dev);
++      const struct ad9467_chip_info *info = st->info;
+       long r_clk;
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+-              return ad9467_set_scale(conv, val, val2);
++              return ad9467_set_scale(st, val, val2);
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               r_clk = clk_round_rate(st->clk, val);
+               if (r_clk < 0 || r_clk > info->max_rate) {
+@@ -369,13 +364,13 @@ static int ad9467_write_raw(struct adi_axi_adc_conv *conv,
+       }
+ }
+-static int ad9467_read_avail(struct adi_axi_adc_conv *conv,
++static int ad9467_read_avail(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan,
+                            const int **vals, int *type, int *length,
+                            long mask)
+ {
+-      const struct adi_axi_adc_chip_info *info = conv->chip_info;
+-      struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
++      struct ad9467_state *st = iio_priv(indio_dev);
++      const struct ad9467_chip_info *info = st->info;
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+@@ -389,6 +384,33 @@ static int ad9467_read_avail(struct adi_axi_adc_conv *conv,
+       }
+ }
++static int ad9467_update_scan_mode(struct iio_dev *indio_dev,
++                                 const unsigned long *scan_mask)
++{
++      struct ad9467_state *st = iio_priv(indio_dev);
++      unsigned int c;
++      int ret;
++
++      for (c = 0; c < st->info->num_channels; c++) {
++              if (test_bit(c, scan_mask))
++                      ret = iio_backend_chan_enable(st->back, c);
++              else
++                      ret = iio_backend_chan_disable(st->back, c);
++              if (ret)
++                      return ret;
++      }
++
++      return 0;
++}
++
++static const struct iio_info ad9467_info = {
++      .read_raw = ad9467_read_raw,
++      .write_raw = ad9467_write_raw,
++      .update_scan_mode = ad9467_update_scan_mode,
++      .debugfs_reg_access = ad9467_reg_access,
++      .read_avail = ad9467_read_avail,
++};
++
+ static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode)
+ {
+       int ret;
+@@ -401,10 +423,9 @@ static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode)
+                               AN877_ADC_TRANSFER_SYNC);
+ }
+-static int ad9467_scale_fill(struct adi_axi_adc_conv *conv)
++static int ad9467_scale_fill(struct ad9467_state *st)
+ {
+-      const struct adi_axi_adc_chip_info *info = conv->chip_info;
+-      struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
++      const struct ad9467_chip_info *info = st->info;
+       unsigned int i, val1, val2;
+       st->scales = devm_kmalloc_array(&st->spi->dev, info->num_scales,
+@@ -413,7 +434,7 @@ static int ad9467_scale_fill(struct adi_axi_adc_conv *conv)
+               return -ENOMEM;
+       for (i = 0; i < info->num_scales; i++) {
+-              __ad9467_get_scale(conv, i, &val1, &val2);
++              __ad9467_get_scale(st, i, &val1, &val2);
+               st->scales[i][0] = val1;
+               st->scales[i][1] = val2;
+       }
+@@ -421,11 +442,27 @@ static int ad9467_scale_fill(struct adi_axi_adc_conv *conv)
+       return 0;
+ }
+-static int ad9467_preenable_setup(struct adi_axi_adc_conv *conv)
++static int ad9467_setup(struct ad9467_state *st)
+ {
+-      struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
++      struct iio_backend_data_fmt data = {
++              .sign_extend = true,
++              .enable = true,
++      };
++      unsigned int c, mode;
++      int ret;
++
++      mode = st->info->default_output_mode | AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;
++      ret = ad9467_outputmode_set(st->spi, mode);
++      if (ret)
++              return ret;
+-      return ad9467_outputmode_set(st->spi, st->output_mode);
++      for (c = 0; c < st->info->num_channels; c++) {
++              ret = iio_backend_data_format_set(st->back, c, &data);
++              if (ret)
++                      return ret;
++      }
++
++      return 0;
+ }
+ static int ad9467_reset(struct device *dev)
+@@ -443,25 +480,65 @@ static int ad9467_reset(struct device *dev)
+       return 0;
+ }
++static int ad9467_iio_backend_get(struct ad9467_state *st)
++{
++      struct device *dev = &st->spi->dev;
++      struct device_node *__back;
++
++      st->back = devm_iio_backend_get(dev, NULL);
++      if (!IS_ERR(st->back))
++              return 0;
++      /* If not found, don't error out as we might have legacy DT property */
++      if (PTR_ERR(st->back) != -ENOENT)
++              return PTR_ERR(st->back);
++
++      /*
++       * if we don't get the backend using the normal API's, use the legacy
++       * 'adi,adc-dev' property. So we get all nodes with that property, and
++       * look for the one pointing at us. Then we directly lookup that fwnode
++       * on the backend list of registered devices. This is done so we don't
++       * make io-backends mandatory which would break DT ABI.
++       */
++      for_each_node_with_property(__back, "adi,adc-dev") {
++              struct device_node *__me;
++
++              __me = of_parse_phandle(__back, "adi,adc-dev", 0);
++              if (!__me)
++                      continue;
++
++              if (!device_match_of_node(dev, __me)) {
++                      of_node_put(__me);
++                      continue;
++              }
++
++              of_node_put(__me);
++              st->back = __devm_iio_backend_get_from_fwnode_lookup(dev,
++                                                                   of_fwnode_handle(__back));
++              of_node_put(__back);
++              return PTR_ERR_OR_ZERO(st->back);
++      }
++
++      return -ENODEV;
++}
++
+ static int ad9467_probe(struct spi_device *spi)
+ {
+-      const struct ad9467_chip_info *info;
+-      struct adi_axi_adc_conv *conv;
++      struct iio_dev *indio_dev;
+       struct ad9467_state *st;
+       unsigned int id;
+       int ret;
+-      info = spi_get_device_match_data(spi);
+-      if (!info)
+-              return -ENODEV;
+-
+-      conv = devm_adi_axi_adc_conv_register(&spi->dev, sizeof(*st));
+-      if (IS_ERR(conv))
+-              return PTR_ERR(conv);
++      indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
++      if (!indio_dev)
++              return -ENOMEM;
+-      st = adi_axi_adc_conv_priv(conv);
++      st = iio_priv(indio_dev);
+       st->spi = spi;
++      st->info = spi_get_device_match_data(spi);
++      if (!st->info)
++              return -ENODEV;
++
+       st->clk = devm_clk_get_enabled(&spi->dev, "adc-clk");
+       if (IS_ERR(st->clk))
+               return PTR_ERR(st->clk);
+@@ -475,29 +552,39 @@ static int ad9467_probe(struct spi_device *spi)
+       if (ret)
+               return ret;
+-      conv->chip_info = &info->axi_adc_info;
+-
+-      ret = ad9467_scale_fill(conv);
++      ret = ad9467_scale_fill(st);
+       if (ret)
+               return ret;
+       id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID);
+-      if (id != conv->chip_info->id) {
++      if (id != st->info->id) {
+               dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n",
+-                      id, conv->chip_info->id);
++                      id, st->info->id);
+               return -ENODEV;
+       }
+-      conv->reg_access = ad9467_reg_access;
+-      conv->write_raw = ad9467_write_raw;
+-      conv->read_raw = ad9467_read_raw;
+-      conv->read_avail = ad9467_read_avail;
+-      conv->preenable_setup = ad9467_preenable_setup;
++      indio_dev->name = st->info->name;
++      indio_dev->channels = st->info->channels;
++      indio_dev->num_channels = st->info->num_channels;
++      indio_dev->info = &ad9467_info;
+-      st->output_mode = info->default_output_mode |
+-                        AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;
++      ret = ad9467_iio_backend_get(st);
++      if (ret)
++              return ret;
+-      return 0;
++      ret = devm_iio_backend_request_buffer(&spi->dev, st->back, indio_dev);
++      if (ret)
++              return ret;
++
++      ret = devm_iio_backend_enable(&spi->dev, st->back);
++      if (ret)
++              return ret;
++
++      ret = ad9467_setup(st);
++      if (ret)
++              return ret;
++
++      return devm_iio_device_register(&spi->dev, indio_dev);
+ }
+ static const struct of_device_id ad9467_of_match[] = {
+@@ -529,4 +616,4 @@ module_spi_driver(ad9467_driver);
+ MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
+ MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver");
+ MODULE_LICENSE("GPL v2");
+-MODULE_IMPORT_NS(IIO_ADI_AXI);
++MODULE_IMPORT_NS(IIO_BACKEND);
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-ad9467-use-chip_info-variables-instead-of-ar.patch b/queue-6.6/iio-adc-ad9467-use-chip_info-variables-instead-of-ar.patch
new file mode 100644 (file)
index 0000000..65e83f8
--- /dev/null
@@ -0,0 +1,147 @@
+From 999c318872e13c5bb2e12d8b3bfd07831b7cd42b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Dec 2023 13:39:29 +0100
+Subject: iio: adc: ad9467: use chip_info variables instead of array
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit 6dd3fa9fcc66cb71834dc2e0a222324af0d8b95d ]
+
+Instead of having an array and keeping IDs for each entry of the array,
+just have a chip_info struct per device.
+
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20231207-iio-backend-prep-v2-6-a4a33bc4d70e@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad9467.c | 89 +++++++++++++++++++---------------------
+ 1 file changed, 43 insertions(+), 46 deletions(-)
+
+diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
+index b16d28c1adcb0..c5ed62cc86465 100644
+--- a/drivers/iio/adc/ad9467.c
++++ b/drivers/iio/adc/ad9467.c
+@@ -101,12 +101,6 @@
+ #define AD9467_DEF_OUTPUT_MODE                0x08
+ #define AD9467_REG_VREF_MASK          0x0F
+-enum {
+-      ID_AD9265,
+-      ID_AD9434,
+-      ID_AD9467,
+-};
+-
+ struct ad9467_chip_info {
+       struct adi_axi_adc_chip_info    axi_adc_info;
+       unsigned int                    default_output_mode;
+@@ -234,43 +228,46 @@ static const struct iio_chan_spec ad9467_channels[] = {
+       AD9467_CHAN(0, 0, 16, 'S'),
+ };
+-static const struct ad9467_chip_info ad9467_chip_tbl[] = {
+-      [ID_AD9265] = {
+-              .axi_adc_info = {
+-                      .id = CHIPID_AD9265,
+-                      .max_rate = 125000000UL,
+-                      .scale_table = ad9265_scale_table,
+-                      .num_scales = ARRAY_SIZE(ad9265_scale_table),
+-                      .channels = ad9467_channels,
+-                      .num_channels = ARRAY_SIZE(ad9467_channels),
+-              },
+-              .default_output_mode = AD9265_DEF_OUTPUT_MODE,
+-              .vref_mask = AD9265_REG_VREF_MASK,
++static const struct ad9467_chip_info ad9467_chip_tbl = {
++      .axi_adc_info = {
++              .name = "ad9467",
++              .id = CHIPID_AD9467,
++              .max_rate = 250000000UL,
++              .scale_table = ad9467_scale_table,
++              .num_scales = ARRAY_SIZE(ad9467_scale_table),
++              .channels = ad9467_channels,
++              .num_channels = ARRAY_SIZE(ad9467_channels),
+       },
+-      [ID_AD9434] = {
+-              .axi_adc_info = {
+-                      .id = CHIPID_AD9434,
+-                      .max_rate = 500000000UL,
+-                      .scale_table = ad9434_scale_table,
+-                      .num_scales = ARRAY_SIZE(ad9434_scale_table),
+-                      .channels = ad9434_channels,
+-                      .num_channels = ARRAY_SIZE(ad9434_channels),
+-              },
+-              .default_output_mode = AD9434_DEF_OUTPUT_MODE,
+-              .vref_mask = AD9434_REG_VREF_MASK,
++      .default_output_mode = AD9467_DEF_OUTPUT_MODE,
++      .vref_mask = AD9467_REG_VREF_MASK,
++};
++
++static const struct ad9467_chip_info ad9434_chip_tbl = {
++      .axi_adc_info = {
++              .name = "ad9434",
++              .id = CHIPID_AD9434,
++              .max_rate = 500000000UL,
++              .scale_table = ad9434_scale_table,
++              .num_scales = ARRAY_SIZE(ad9434_scale_table),
++              .channels = ad9434_channels,
++              .num_channels = ARRAY_SIZE(ad9434_channels),
+       },
+-      [ID_AD9467] = {
+-              .axi_adc_info = {
+-                      .id = CHIPID_AD9467,
+-                      .max_rate = 250000000UL,
+-                      .scale_table = ad9467_scale_table,
+-                      .num_scales = ARRAY_SIZE(ad9467_scale_table),
+-                      .channels = ad9467_channels,
+-                      .num_channels = ARRAY_SIZE(ad9467_channels),
+-              },
+-              .default_output_mode = AD9467_DEF_OUTPUT_MODE,
+-              .vref_mask = AD9467_REG_VREF_MASK,
++      .default_output_mode = AD9434_DEF_OUTPUT_MODE,
++      .vref_mask = AD9434_REG_VREF_MASK,
++};
++
++static const struct ad9467_chip_info ad9265_chip_tbl = {
++      .axi_adc_info = {
++              .name = "ad9265",
++              .id = CHIPID_AD9265,
++              .max_rate = 125000000UL,
++              .scale_table = ad9265_scale_table,
++              .num_scales = ARRAY_SIZE(ad9265_scale_table),
++              .channels = ad9467_channels,
++              .num_channels = ARRAY_SIZE(ad9467_channels),
+       },
++      .default_output_mode = AD9265_DEF_OUTPUT_MODE,
++      .vref_mask = AD9265_REG_VREF_MASK,
+ };
+ static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
+@@ -504,17 +501,17 @@ static int ad9467_probe(struct spi_device *spi)
+ }
+ static const struct of_device_id ad9467_of_match[] = {
+-      { .compatible = "adi,ad9265", .data = &ad9467_chip_tbl[ID_AD9265], },
+-      { .compatible = "adi,ad9434", .data = &ad9467_chip_tbl[ID_AD9434], },
+-      { .compatible = "adi,ad9467", .data = &ad9467_chip_tbl[ID_AD9467], },
++      { .compatible = "adi,ad9265", .data = &ad9265_chip_tbl, },
++      { .compatible = "adi,ad9434", .data = &ad9434_chip_tbl, },
++      { .compatible = "adi,ad9467", .data = &ad9467_chip_tbl, },
+       {}
+ };
+ MODULE_DEVICE_TABLE(of, ad9467_of_match);
+ static const struct spi_device_id ad9467_ids[] = {
+-      { "ad9265", (kernel_ulong_t)&ad9467_chip_tbl[ID_AD9265] },
+-      { "ad9434", (kernel_ulong_t)&ad9467_chip_tbl[ID_AD9434] },
+-      { "ad9467", (kernel_ulong_t)&ad9467_chip_tbl[ID_AD9467] },
++      { "ad9265", (kernel_ulong_t)&ad9265_chip_tbl },
++      { "ad9434", (kernel_ulong_t)&ad9434_chip_tbl },
++      { "ad9467", (kernel_ulong_t)&ad9467_chip_tbl },
+       {}
+ };
+ MODULE_DEVICE_TABLE(spi, ad9467_ids);
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-ad9467-use-spi_get_device_match_data.patch b/queue-6.6/iio-adc-ad9467-use-spi_get_device_match_data.patch
new file mode 100644 (file)
index 0000000..c44e6e5
--- /dev/null
@@ -0,0 +1,39 @@
+From 8399e245f2b68c0bf17e2055e79ae1974eaa11c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Dec 2023 13:39:28 +0100
+Subject: iio: adc: ad9467: use spi_get_device_match_data()
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit b67cc85d45d5d2894d0e2812bba27d7b23befbe6 ]
+
+Make use of spi_get_device_match_data() to simplify things.
+
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20231207-iio-backend-prep-v2-5-a4a33bc4d70e@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad9467.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
+index f668313730cb6..b16d28c1adcb0 100644
+--- a/drivers/iio/adc/ad9467.c
++++ b/drivers/iio/adc/ad9467.c
+@@ -454,9 +454,7 @@ static int ad9467_probe(struct spi_device *spi)
+       unsigned int id;
+       int ret;
+-      info = of_device_get_match_data(&spi->dev);
+-      if (!info)
+-              info = (void *)spi_get_device_id(spi)->driver_data;
++      info = spi_get_device_match_data(spi);
+       if (!info)
+               return -ENODEV;
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-adi-axi-adc-convert-to-regmap.patch b/queue-6.6/iio-adc-adi-axi-adc-convert-to-regmap.patch
new file mode 100644 (file)
index 0000000..bcf0673
--- /dev/null
@@ -0,0 +1,198 @@
+From eaadea3f007de9d8ee0bc0a5abacd8197ca12e78 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Dec 2023 13:39:31 +0100
+Subject: iio: adc: adi-axi-adc: convert to regmap
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit 21aa971d3e295c2c81d0887f8a3e85a95dd687c5 ]
+
+Use MMIO regmap interface. It makes things easier for manipulating bits.
+
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20231207-iio-backend-prep-v2-8-a4a33bc4d70e@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/Kconfig       |  2 +-
+ drivers/iio/adc/adi-axi-adc.c | 85 +++++++++++++++++++++--------------
+ 2 files changed, 53 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
+index 517b3db114b8e..0b94bda8be361 100644
+--- a/drivers/iio/adc/Kconfig
++++ b/drivers/iio/adc/Kconfig
+@@ -292,7 +292,7 @@ config ADI_AXI_ADC
+       select IIO_BUFFER
+       select IIO_BUFFER_HW_CONSUMER
+       select IIO_BUFFER_DMAENGINE
+-      depends on HAS_IOMEM
++      select REGMAP_MMIO
+       depends on OF
+       help
+         Say yes here to build support for Analog Devices Generic
+diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
+index ae83ada7f9f2d..c247ff1541d28 100644
+--- a/drivers/iio/adc/adi-axi-adc.c
++++ b/drivers/iio/adc/adi-axi-adc.c
+@@ -14,6 +14,7 @@
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/property.h>
++#include <linux/regmap.h>
+ #include <linux/slab.h>
+ #include <linux/iio/iio.h>
+@@ -62,7 +63,7 @@ struct adi_axi_adc_state {
+       struct mutex                            lock;
+       struct adi_axi_adc_client               *client;
+-      void __iomem                            *regs;
++      struct regmap                           *regmap;
+ };
+ struct adi_axi_adc_client {
+@@ -90,19 +91,6 @@ void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
+ }
+ EXPORT_SYMBOL_NS_GPL(adi_axi_adc_conv_priv, IIO_ADI_AXI);
+-static void adi_axi_adc_write(struct adi_axi_adc_state *st,
+-                            unsigned int reg,
+-                            unsigned int val)
+-{
+-      iowrite32(val, st->regs + reg);
+-}
+-
+-static unsigned int adi_axi_adc_read(struct adi_axi_adc_state *st,
+-                                   unsigned int reg)
+-{
+-      return ioread32(st->regs + reg);
+-}
+-
+ static int adi_axi_adc_config_dma_buffer(struct device *dev,
+                                        struct iio_dev *indio_dev)
+ {
+@@ -163,17 +151,20 @@ static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev,
+ {
+       struct adi_axi_adc_state *st = iio_priv(indio_dev);
+       struct adi_axi_adc_conv *conv = &st->client->conv;
+-      unsigned int i, ctrl;
++      unsigned int i;
++      int ret;
+       for (i = 0; i < conv->chip_info->num_channels; i++) {
+-              ctrl = adi_axi_adc_read(st, ADI_AXI_REG_CHAN_CTRL(i));
+-
+               if (test_bit(i, scan_mask))
+-                      ctrl |= ADI_AXI_REG_CHAN_CTRL_ENABLE;
++                      ret = regmap_set_bits(st->regmap,
++                                            ADI_AXI_REG_CHAN_CTRL(i),
++                                            ADI_AXI_REG_CHAN_CTRL_ENABLE);
+               else
+-                      ctrl &= ~ADI_AXI_REG_CHAN_CTRL_ENABLE;
+-
+-              adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i), ctrl);
++                      ret = regmap_clear_bits(st->regmap,
++                                              ADI_AXI_REG_CHAN_CTRL(i),
++                                              ADI_AXI_REG_CHAN_CTRL_ENABLE);
++              if (ret)
++                      return ret;
+       }
+       return 0;
+@@ -310,21 +301,32 @@ static int adi_axi_adc_setup_channels(struct device *dev,
+       }
+       for (i = 0; i < conv->chip_info->num_channels; i++) {
+-              adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i),
+-                                ADI_AXI_REG_CHAN_CTRL_DEFAULTS);
++              ret = regmap_write(st->regmap, ADI_AXI_REG_CHAN_CTRL(i),
++                                 ADI_AXI_REG_CHAN_CTRL_DEFAULTS);
++              if (ret)
++                      return ret;
+       }
+       return 0;
+ }
+-static void axi_adc_reset(struct adi_axi_adc_state *st)
++static int axi_adc_reset(struct adi_axi_adc_state *st)
+ {
+-      adi_axi_adc_write(st, ADI_AXI_REG_RSTN, 0);
++      int ret;
++
++      ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
++      if (ret)
++              return ret;
++
+       mdelay(10);
+-      adi_axi_adc_write(st, ADI_AXI_REG_RSTN, ADI_AXI_REG_RSTN_MMCM_RSTN);
++      ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN,
++                         ADI_AXI_REG_RSTN_MMCM_RSTN);
++      if (ret)
++              return ret;
++
+       mdelay(10);
+-      adi_axi_adc_write(st, ADI_AXI_REG_RSTN,
+-                        ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
++      return regmap_write(st->regmap, ADI_AXI_REG_RSTN,
++                          ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
+ }
+ static void adi_axi_adc_cleanup(void *data)
+@@ -335,12 +337,20 @@ static void adi_axi_adc_cleanup(void *data)
+       module_put(cl->dev->driver->owner);
+ }
++static const struct regmap_config axi_adc_regmap_config = {
++      .val_bits = 32,
++      .reg_bits = 32,
++      .reg_stride = 4,
++      .max_register = 0x0800,
++};
++
+ static int adi_axi_adc_probe(struct platform_device *pdev)
+ {
+       struct adi_axi_adc_conv *conv;
+       struct iio_dev *indio_dev;
+       struct adi_axi_adc_client *cl;
+       struct adi_axi_adc_state *st;
++      void __iomem *base;
+       unsigned int ver;
+       int ret;
+@@ -361,15 +371,24 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
+       cl->state = st;
+       mutex_init(&st->lock);
+-      st->regs = devm_platform_ioremap_resource(pdev, 0);
+-      if (IS_ERR(st->regs))
+-              return PTR_ERR(st->regs);
++      base = devm_platform_ioremap_resource(pdev, 0);
++      if (IS_ERR(base))
++              return PTR_ERR(base);
++
++      st->regmap = devm_regmap_init_mmio(&pdev->dev, base,
++                                         &axi_adc_regmap_config);
++      if (IS_ERR(st->regmap))
++              return PTR_ERR(st->regmap);
+       conv = &st->client->conv;
+-      axi_adc_reset(st);
++      ret = axi_adc_reset(st);
++      if (ret)
++              return ret;
+-      ver = adi_axi_adc_read(st, ADI_AXI_REG_VERSION);
++      ret = regmap_read(st->regmap, ADI_AXI_REG_VERSION, &ver);
++      if (ret)
++              return ret;
+       if (cl->info->version > ver) {
+               dev_err(&pdev->dev,
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-adi-axi-adc-move-to-backend-framework.patch b/queue-6.6/iio-adc-adi-axi-adc-move-to-backend-framework.patch
new file mode 100644 (file)
index 0000000..3d75c95
--- /dev/null
@@ -0,0 +1,620 @@
+From 6ce26f79e73e192921feffabccd014737a948c26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 10 Feb 2024 21:57:19 +0100
+Subject: iio: adc: adi-axi-adc: move to backend framework
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit 794ef0e57854d794173c8ab6bcce3285032dcd95 ]
+
+Move to the IIO backend framework. Devices supported by adi-axi-adc now
+register themselves as backend devices.
+
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20240210-iio-backend-v11-7-f5242a5fb42a@analog.com
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/Kconfig             |   2 +-
+ drivers/iio/adc/adi-axi-adc.c       | 384 +++++++---------------------
+ include/linux/iio/adc/adi-axi-adc.h |  68 -----
+ 3 files changed, 96 insertions(+), 358 deletions(-)
+ delete mode 100644 include/linux/iio/adc/adi-axi-adc.h
+
+diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
+index ae789d427b213..dfb925cfe38ef 100644
+--- a/drivers/iio/adc/Kconfig
++++ b/drivers/iio/adc/Kconfig
+@@ -293,7 +293,7 @@ config ADI_AXI_ADC
+       select IIO_BUFFER_HW_CONSUMER
+       select IIO_BUFFER_DMAENGINE
+       select REGMAP_MMIO
+-      depends on OF
++      select IIO_BACKEND
+       help
+         Say yes here to build support for Analog Devices Generic
+         AXI ADC IP core. The IP core is used for interfacing with
+diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
+index 0f21d1d98b9fa..4156639b3c8bd 100644
+--- a/drivers/iio/adc/adi-axi-adc.c
++++ b/drivers/iio/adc/adi-axi-adc.c
+@@ -8,6 +8,7 @@
+ #include <linux/bitfield.h>
+ #include <linux/clk.h>
++#include <linux/err.h>
+ #include <linux/io.h>
+ #include <linux/delay.h>
+ #include <linux/module.h>
+@@ -17,13 +18,12 @@
+ #include <linux/regmap.h>
+ #include <linux/slab.h>
+-#include <linux/iio/iio.h>
+-#include <linux/iio/sysfs.h>
+-#include <linux/iio/buffer.h>
+-#include <linux/iio/buffer-dmaengine.h>
+-
+ #include <linux/fpga/adi-axi-common.h>
+-#include <linux/iio/adc/adi-axi-adc.h>
++
++#include <linux/iio/backend.h>
++#include <linux/iio/buffer-dmaengine.h>
++#include <linux/iio/buffer.h>
++#include <linux/iio/iio.h>
+ /*
+  * Register definitions:
+@@ -44,6 +44,7 @@
+ #define   ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR    BIT(10)
+ #define   ADI_AXI_REG_CHAN_CTRL_IQCOR_EN      BIT(9)
+ #define   ADI_AXI_REG_CHAN_CTRL_DCFILT_EN     BIT(8)
++#define   ADI_AXI_REG_CHAN_CTRL_FMT_MASK      GENMASK(6, 4)
+ #define   ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT   BIT(6)
+ #define   ADI_AXI_REG_CHAN_CTRL_FMT_TYPE      BIT(5)
+ #define   ADI_AXI_REG_CHAN_CTRL_FMT_EN                BIT(4)
+@@ -55,286 +56,100 @@
+        ADI_AXI_REG_CHAN_CTRL_FMT_EN |         \
+        ADI_AXI_REG_CHAN_CTRL_ENABLE)
+-struct adi_axi_adc_core_info {
+-      unsigned int                            version;
+-};
+-
+ struct adi_axi_adc_state {
+-      struct mutex                            lock;
+-
+-      struct adi_axi_adc_client               *client;
+       struct regmap                           *regmap;
+-};
+-
+-struct adi_axi_adc_client {
+-      struct list_head                        entry;
+-      struct adi_axi_adc_conv                 conv;
+-      struct adi_axi_adc_state                *state;
+       struct device                           *dev;
+-      const struct adi_axi_adc_core_info      *info;
+ };
+-static LIST_HEAD(registered_clients);
+-static DEFINE_MUTEX(registered_clients_lock);
+-
+-static struct adi_axi_adc_client *conv_to_client(struct adi_axi_adc_conv *conv)
+-{
+-      return container_of(conv, struct adi_axi_adc_client, conv);
+-}
+-
+-void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
+-{
+-      struct adi_axi_adc_client *cl = conv_to_client(conv);
+-
+-      return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client),
+-                                IIO_DMA_MINALIGN);
+-}
+-EXPORT_SYMBOL_NS_GPL(adi_axi_adc_conv_priv, IIO_ADI_AXI);
+-
+-static int adi_axi_adc_config_dma_buffer(struct device *dev,
+-                                       struct iio_dev *indio_dev)
+-{
+-      const char *dma_name;
+-
+-      if (!device_property_present(dev, "dmas"))
+-              return 0;
+-
+-      if (device_property_read_string(dev, "dma-names", &dma_name))
+-              dma_name = "rx";
+-
+-      return devm_iio_dmaengine_buffer_setup(indio_dev->dev.parent,
+-                                             indio_dev, dma_name);
+-}
+-
+-static int adi_axi_adc_read_raw(struct iio_dev *indio_dev,
+-                              struct iio_chan_spec const *chan,
+-                              int *val, int *val2, long mask)
+-{
+-      struct adi_axi_adc_state *st = iio_priv(indio_dev);
+-      struct adi_axi_adc_conv *conv = &st->client->conv;
+-
+-      if (!conv->read_raw)
+-              return -EOPNOTSUPP;
+-
+-      return conv->read_raw(conv, chan, val, val2, mask);
+-}
+-
+-static int adi_axi_adc_write_raw(struct iio_dev *indio_dev,
+-                               struct iio_chan_spec const *chan,
+-                               int val, int val2, long mask)
+-{
+-      struct adi_axi_adc_state *st = iio_priv(indio_dev);
+-      struct adi_axi_adc_conv *conv = &st->client->conv;
+-
+-      if (!conv->write_raw)
+-              return -EOPNOTSUPP;
+-
+-      return conv->write_raw(conv, chan, val, val2, mask);
+-}
+-
+-static int adi_axi_adc_read_avail(struct iio_dev *indio_dev,
+-                                struct iio_chan_spec const *chan,
+-                                const int **vals, int *type, int *length,
+-                                long mask)
+-{
+-      struct adi_axi_adc_state *st = iio_priv(indio_dev);
+-      struct adi_axi_adc_conv *conv = &st->client->conv;
+-
+-      if (!conv->read_avail)
+-              return -EOPNOTSUPP;
+-
+-      return conv->read_avail(conv, chan, vals, type, length, mask);
+-}
+-
+-static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev,
+-                                      const unsigned long *scan_mask)
++static int axi_adc_enable(struct iio_backend *back)
+ {
+-      struct adi_axi_adc_state *st = iio_priv(indio_dev);
+-      struct adi_axi_adc_conv *conv = &st->client->conv;
+-      unsigned int i;
++      struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+       int ret;
+-      for (i = 0; i < conv->chip_info->num_channels; i++) {
+-              if (test_bit(i, scan_mask))
+-                      ret = regmap_set_bits(st->regmap,
+-                                            ADI_AXI_REG_CHAN_CTRL(i),
+-                                            ADI_AXI_REG_CHAN_CTRL_ENABLE);
+-              else
+-                      ret = regmap_clear_bits(st->regmap,
+-                                              ADI_AXI_REG_CHAN_CTRL(i),
+-                                              ADI_AXI_REG_CHAN_CTRL_ENABLE);
+-              if (ret)
+-                      return ret;
+-      }
+-
+-      return 0;
+-}
+-
+-static struct adi_axi_adc_conv *adi_axi_adc_conv_register(struct device *dev,
+-                                                        size_t sizeof_priv)
+-{
+-      struct adi_axi_adc_client *cl;
+-      size_t alloc_size;
+-
+-      alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_DMA_MINALIGN);
+-      if (sizeof_priv)
+-              alloc_size += ALIGN(sizeof_priv, IIO_DMA_MINALIGN);
+-
+-      cl = kzalloc(alloc_size, GFP_KERNEL);
+-      if (!cl)
+-              return ERR_PTR(-ENOMEM);
+-
+-      mutex_lock(&registered_clients_lock);
+-
+-      cl->dev = get_device(dev);
+-
+-      list_add_tail(&cl->entry, &registered_clients);
+-
+-      mutex_unlock(&registered_clients_lock);
++      ret = regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
++                            ADI_AXI_REG_RSTN_MMCM_RSTN);
++      if (ret)
++              return ret;
+-      return &cl->conv;
++      fsleep(10000);
++      return regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
++                             ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
+ }
+-static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv)
++static void axi_adc_disable(struct iio_backend *back)
+ {
+-      struct adi_axi_adc_client *cl = conv_to_client(conv);
+-
+-      mutex_lock(&registered_clients_lock);
+-
+-      list_del(&cl->entry);
+-      put_device(cl->dev);
++      struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+-      mutex_unlock(&registered_clients_lock);
+-
+-      kfree(cl);
++      regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
+ }
+-static void devm_adi_axi_adc_conv_release(void *conv)
++static int axi_adc_data_format_set(struct iio_backend *back, unsigned int chan,
++                                 const struct iio_backend_data_fmt *data)
+ {
+-      adi_axi_adc_conv_unregister(conv);
++      struct adi_axi_adc_state *st = iio_backend_get_priv(back);
++      u32 val;
++
++      if (!data->enable)
++              return regmap_clear_bits(st->regmap,
++                                       ADI_AXI_REG_CHAN_CTRL(chan),
++                                       ADI_AXI_REG_CHAN_CTRL_FMT_EN);
++
++      val = FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_EN, true);
++      if (data->sign_extend)
++              val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT, true);
++      if (data->type == IIO_BACKEND_OFFSET_BINARY)
++              val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_TYPE, true);
++
++      return regmap_update_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
++                                ADI_AXI_REG_CHAN_CTRL_FMT_MASK, val);
+ }
+-struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,
+-                                                      size_t sizeof_priv)
++static int axi_adc_chan_enable(struct iio_backend *back, unsigned int chan)
+ {
+-      struct adi_axi_adc_conv *conv;
+-      int ret;
+-
+-      conv = adi_axi_adc_conv_register(dev, sizeof_priv);
+-      if (IS_ERR(conv))
+-              return conv;
++      struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+-      ret = devm_add_action_or_reset(dev, devm_adi_axi_adc_conv_release,
+-                                     conv);
+-      if (ret)
+-              return ERR_PTR(ret);
+-
+-      return conv;
++      return regmap_set_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
++                             ADI_AXI_REG_CHAN_CTRL_ENABLE);
+ }
+-EXPORT_SYMBOL_NS_GPL(devm_adi_axi_adc_conv_register, IIO_ADI_AXI);
+-
+-static const struct iio_info adi_axi_adc_info = {
+-      .read_raw = &adi_axi_adc_read_raw,
+-      .write_raw = &adi_axi_adc_write_raw,
+-      .update_scan_mode = &adi_axi_adc_update_scan_mode,
+-      .read_avail = &adi_axi_adc_read_avail,
+-};
+-
+-static const struct adi_axi_adc_core_info adi_axi_adc_10_0_a_info = {
+-      .version = ADI_AXI_PCORE_VER(10, 0, 'a'),
+-};
+-static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)
++static int axi_adc_chan_disable(struct iio_backend *back, unsigned int chan)
+ {
+-      const struct adi_axi_adc_core_info *info;
+-      struct adi_axi_adc_client *cl;
+-      struct device_node *cln;
+-
+-      info = of_device_get_match_data(dev);
+-      if (!info)
+-              return ERR_PTR(-ENODEV);
+-
+-      cln = of_parse_phandle(dev->of_node, "adi,adc-dev", 0);
+-      if (!cln) {
+-              dev_err(dev, "No 'adi,adc-dev' node defined\n");
+-              return ERR_PTR(-ENODEV);
+-      }
+-
+-      mutex_lock(&registered_clients_lock);
+-
+-      list_for_each_entry(cl, &registered_clients, entry) {
+-              if (!cl->dev)
+-                      continue;
+-
+-              if (cl->dev->of_node != cln)
+-                      continue;
+-
+-              if (!try_module_get(cl->dev->driver->owner)) {
+-                      mutex_unlock(&registered_clients_lock);
+-                      of_node_put(cln);
+-                      return ERR_PTR(-ENODEV);
+-              }
+-
+-              get_device(cl->dev);
+-              cl->info = info;
+-              mutex_unlock(&registered_clients_lock);
+-              of_node_put(cln);
+-              return cl;
+-      }
++      struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+-      mutex_unlock(&registered_clients_lock);
+-      of_node_put(cln);
+-
+-      return ERR_PTR(-EPROBE_DEFER);
++      return regmap_clear_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
++                               ADI_AXI_REG_CHAN_CTRL_ENABLE);
+ }
+-static int adi_axi_adc_setup_channels(struct device *dev,
+-                                    struct adi_axi_adc_state *st)
++static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
++                                               struct iio_dev *indio_dev)
+ {
+-      struct adi_axi_adc_conv *conv = &st->client->conv;
+-      int i, ret;
++      struct adi_axi_adc_state *st = iio_backend_get_priv(back);
++      struct iio_buffer *buffer;
++      const char *dma_name;
++      int ret;
+-      if (conv->preenable_setup) {
+-              ret = conv->preenable_setup(conv);
+-              if (ret)
+-                      return ret;
+-      }
++      if (device_property_read_string(st->dev, "dma-names", &dma_name))
++              dma_name = "rx";
+-      for (i = 0; i < conv->chip_info->num_channels; i++) {
+-              ret = regmap_write(st->regmap, ADI_AXI_REG_CHAN_CTRL(i),
+-                                 ADI_AXI_REG_CHAN_CTRL_DEFAULTS);
+-              if (ret)
+-                      return ret;
++      buffer = iio_dmaengine_buffer_alloc(st->dev, dma_name);
++      if (IS_ERR(buffer)) {
++              dev_err(st->dev, "Could not get DMA buffer, %ld\n",
++                      PTR_ERR(buffer));
++              return ERR_CAST(buffer);
+       }
+-      return 0;
+-}
+-
+-static int axi_adc_reset(struct adi_axi_adc_state *st)
+-{
+-      int ret;
+-
+-      ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
+-      if (ret)
+-              return ret;
+-
+-      mdelay(10);
+-      ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN,
+-                         ADI_AXI_REG_RSTN_MMCM_RSTN);
++      indio_dev->modes |= INDIO_BUFFER_HARDWARE;
++      ret = iio_device_attach_buffer(indio_dev, buffer);
+       if (ret)
+-              return ret;
++              return ERR_PTR(ret);
+-      mdelay(10);
+-      return regmap_write(st->regmap, ADI_AXI_REG_RSTN,
+-                          ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
++      return buffer;
+ }
+-static void adi_axi_adc_cleanup(void *data)
++static void axi_adc_free_buffer(struct iio_backend *back,
++                              struct iio_buffer *buffer)
+ {
+-      struct adi_axi_adc_client *cl = data;
+-
+-      put_device(cl->dev);
+-      module_put(cl->dev->driver->owner);
++      iio_dmaengine_buffer_free(buffer);
+ }
+ static const struct regmap_config axi_adc_regmap_config = {
+@@ -344,45 +159,47 @@ static const struct regmap_config axi_adc_regmap_config = {
+       .max_register = 0x0800,
+ };
++static const struct iio_backend_ops adi_axi_adc_generic = {
++      .enable = axi_adc_enable,
++      .disable = axi_adc_disable,
++      .data_format_set = axi_adc_data_format_set,
++      .chan_enable = axi_adc_chan_enable,
++      .chan_disable = axi_adc_chan_disable,
++      .request_buffer = axi_adc_request_buffer,
++      .free_buffer = axi_adc_free_buffer,
++};
++
+ static int adi_axi_adc_probe(struct platform_device *pdev)
+ {
+-      struct adi_axi_adc_conv *conv;
+-      struct iio_dev *indio_dev;
+-      struct adi_axi_adc_client *cl;
++      const unsigned int *expected_ver;
+       struct adi_axi_adc_state *st;
+       void __iomem *base;
+       unsigned int ver;
+       int ret;
+-      cl = adi_axi_adc_attach_client(&pdev->dev);
+-      if (IS_ERR(cl))
+-              return PTR_ERR(cl);
+-
+-      ret = devm_add_action_or_reset(&pdev->dev, adi_axi_adc_cleanup, cl);
+-      if (ret)
+-              return ret;
+-
+-      indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
+-      if (indio_dev == NULL)
++      st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
++      if (!st)
+               return -ENOMEM;
+-      st = iio_priv(indio_dev);
+-      st->client = cl;
+-      cl->state = st;
+-      mutex_init(&st->lock);
+-
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
++      st->dev = &pdev->dev;
+       st->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+                                          &axi_adc_regmap_config);
+       if (IS_ERR(st->regmap))
+               return PTR_ERR(st->regmap);
+-      conv = &st->client->conv;
++      expected_ver = device_get_match_data(&pdev->dev);
++      if (!expected_ver)
++              return -ENODEV;
+-      ret = axi_adc_reset(st);
++      /*
++       * Force disable the core. Up to the frontend to enable us. And we can
++       * still read/write registers...
++       */
++      ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
+       if (ret)
+               return ret;
+@@ -390,33 +207,19 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
+       if (ret)
+               return ret;
+-      if (cl->info->version > ver) {
++      if (*expected_ver > ver) {
+               dev_err(&pdev->dev,
+                       "IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
+-                      ADI_AXI_PCORE_VER_MAJOR(cl->info->version),
+-                      ADI_AXI_PCORE_VER_MINOR(cl->info->version),
+-                      ADI_AXI_PCORE_VER_PATCH(cl->info->version),
++                      ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
++                      ADI_AXI_PCORE_VER_MINOR(*expected_ver),
++                      ADI_AXI_PCORE_VER_PATCH(*expected_ver),
+                       ADI_AXI_PCORE_VER_MAJOR(ver),
+                       ADI_AXI_PCORE_VER_MINOR(ver),
+                       ADI_AXI_PCORE_VER_PATCH(ver));
+               return -ENODEV;
+       }
+-      indio_dev->info = &adi_axi_adc_info;
+-      indio_dev->name = "adi-axi-adc";
+-      indio_dev->modes = INDIO_DIRECT_MODE;
+-      indio_dev->num_channels = conv->chip_info->num_channels;
+-      indio_dev->channels = conv->chip_info->channels;
+-
+-      ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
+-      if (ret)
+-              return ret;
+-
+-      ret = adi_axi_adc_setup_channels(&pdev->dev, st);
+-      if (ret)
+-              return ret;
+-
+-      ret = devm_iio_device_register(&pdev->dev, indio_dev);
++      ret = devm_iio_backend_register(&pdev->dev, &adi_axi_adc_generic, st);
+       if (ret)
+               return ret;
+@@ -428,6 +231,8 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
+       return 0;
+ }
++static unsigned int adi_axi_adc_10_0_a_info = ADI_AXI_PCORE_VER(10, 0, 'a');
++
+ /* Match table for of_platform binding */
+ static const struct of_device_id adi_axi_adc_of_match[] = {
+       { .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },
+@@ -448,3 +253,4 @@ MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
+ MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
+ MODULE_LICENSE("GPL v2");
+ MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);
++MODULE_IMPORT_NS(IIO_BACKEND);
+diff --git a/include/linux/iio/adc/adi-axi-adc.h b/include/linux/iio/adc/adi-axi-adc.h
+deleted file mode 100644
+index b7904992d5619..0000000000000
+--- a/include/linux/iio/adc/adi-axi-adc.h
++++ /dev/null
+@@ -1,68 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Analog Devices Generic AXI ADC IP core driver/library
+- * Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
+- *
+- * Copyright 2012-2020 Analog Devices Inc.
+- */
+-#ifndef __ADI_AXI_ADC_H__
+-#define __ADI_AXI_ADC_H__
+-
+-struct device;
+-struct iio_chan_spec;
+-
+-/**
+- * struct adi_axi_adc_chip_info - Chip specific information
+- * @name              Chip name
+- * @id                        Chip ID (usually product ID)
+- * @channels          Channel specifications of type @struct iio_chan_spec
+- * @num_channels      Number of @channels
+- * @scale_table               Supported scales by the chip; tuples of 2 ints
+- * @num_scales                Number of scales in the table
+- * @max_rate          Maximum sampling rate supported by the device
+- */
+-struct adi_axi_adc_chip_info {
+-      const char                      *name;
+-      unsigned int                    id;
+-
+-      const struct iio_chan_spec      *channels;
+-      unsigned int                    num_channels;
+-
+-      const unsigned int              (*scale_table)[2];
+-      int                             num_scales;
+-
+-      unsigned long                   max_rate;
+-};
+-
+-/**
+- * struct adi_axi_adc_conv - data of the ADC attached to the AXI ADC
+- * @chip_info         chip info details for the client ADC
+- * @preenable_setup   op to run in the client before enabling the AXI ADC
+- * @reg_access                IIO debugfs_reg_access hook for the client ADC
+- * @read_raw          IIO read_raw hook for the client ADC
+- * @write_raw         IIO write_raw hook for the client ADC
+- * @read_avail                IIO read_avail hook for the client ADC
+- */
+-struct adi_axi_adc_conv {
+-      const struct adi_axi_adc_chip_info              *chip_info;
+-
+-      int (*preenable_setup)(struct adi_axi_adc_conv *conv);
+-      int (*reg_access)(struct adi_axi_adc_conv *conv, unsigned int reg,
+-                        unsigned int writeval, unsigned int *readval);
+-      int (*read_raw)(struct adi_axi_adc_conv *conv,
+-                      struct iio_chan_spec const *chan,
+-                      int *val, int *val2, long mask);
+-      int (*write_raw)(struct adi_axi_adc_conv *conv,
+-                       struct iio_chan_spec const *chan,
+-                       int val, int val2, long mask);
+-      int (*read_avail)(struct adi_axi_adc_conv *conv,
+-                        struct iio_chan_spec const *chan,
+-                        const int **val, int *type, int *length, long mask);
+-};
+-
+-struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,
+-                                                      size_t sizeof_priv);
+-
+-void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv);
+-
+-#endif
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-adi-axi-adc-only-error-out-in-major-version-.patch b/queue-6.6/iio-adc-adi-axi-adc-only-error-out-in-major-version-.patch
new file mode 100644 (file)
index 0000000..e90fa52
--- /dev/null
@@ -0,0 +1,44 @@
+From 530f9ea9d9e7188717b73f3ab2cf7050e4427abb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Apr 2024 17:36:45 +0200
+Subject: iio: adc: adi-axi-adc: only error out in major version mismatch
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit cf1c833f89e7c8635a28c3db15c68ead150ea712 ]
+
+The IP core only has breaking changes when there major version changes.
+Hence, only match the major number. This is also in line with the other
+core ADI has upstream. The current check for erroring out
+'expected_version > current_version"' is then wrong as we could just
+increase the core major with breaking changes and that would go
+unnoticed.
+
+Fixes: ef04070692a2 ("iio: adc: adi-axi-adc: add support for AXI ADC IP core")
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20240419-ad9467-new-features-v1-2-3e7628ff6d5e@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/adi-axi-adc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
+index 4156639b3c8bd..a543b91124b07 100644
+--- a/drivers/iio/adc/adi-axi-adc.c
++++ b/drivers/iio/adc/adi-axi-adc.c
+@@ -207,9 +207,9 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
+       if (ret)
+               return ret;
+-      if (*expected_ver > ver) {
++      if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) {
+               dev_err(&pdev->dev,
+-                      "IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
++                      "Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
+                       ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
+                       ADI_AXI_PCORE_VER_MINOR(*expected_ver),
+                       ADI_AXI_PCORE_VER_PATCH(*expected_ver),
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-stm32-fixing-err-code-to-not-indicate-succes.patch b/queue-6.6/iio-adc-stm32-fixing-err-code-to-not-indicate-succes.patch
new file mode 100644 (file)
index 0000000..0a01c47
--- /dev/null
@@ -0,0 +1,36 @@
+From 30e8a4f91d02af3ddf27f0dcbb20c94ce74a13c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 Mar 2024 18:53:00 +0000
+Subject: iio: adc: stm32: Fixing err code to not indicate success
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit 3735ca0b072656c3aa2cedc617a5e639b583a472 ]
+
+This path would result in returning 0 / success on an error path.
+
+Cc: Olivier Moysan <olivier.moysan@foss.st.com>
+Fixes: 95bc818404b2 ("iio: adc: stm32-adc: add support of generic channels binding")
+Reviewed-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
+Link: https://lore.kernel.org/r/20240330185305.1319844-4-jic23@kernel.org
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/stm32-adc.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
+index f7613efb870d5..0b3e487440a66 100644
+--- a/drivers/iio/adc/stm32-adc.c
++++ b/drivers/iio/adc/stm32-adc.c
+@@ -2234,6 +2234,7 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
+                       if (vin[0] != val || vin[1] >= adc_info->max_channels) {
+                               dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
+                                       vin[0], vin[1]);
++                              ret = -EINVAL;
+                               goto err;
+                       }
+               } else if (ret != -EINVAL) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-add-the-iio-backend-framework.patch b/queue-6.6/iio-add-the-iio-backend-framework.patch
new file mode 100644 (file)
index 0000000..bbb27e0
--- /dev/null
@@ -0,0 +1,593 @@
+From de741f603752ff97aa7be0c23eb331db0e1a84f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 10 Feb 2024 21:57:17 +0100
+Subject: iio: add the IIO backend framework
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit 1a97905d3e48ebe79a06d16143fbfa427c56ce5f ]
+
+This is a Framework to handle complex IIO aggregate devices.
+
+The typical architecture is to have one device as the frontend device which
+can be "linked" against one or multiple backend devices. All the IIO and
+userspace interface is expected to be registers/managed by the frontend
+device which will callback into the backends when needed (to get/set
+some configuration that it does not directly control).
+
+The basic framework interface is pretty simple:
+ - Backends should register themselves with @devm_iio_backend_register()
+ - Frontend devices should get backends with @devm_iio_backend_get()
+
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20240210-iio-backend-v11-5-f5242a5fb42a@analog.com
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ MAINTAINERS                        |   8 +
+ drivers/iio/Kconfig                |   9 +
+ drivers/iio/Makefile               |   1 +
+ drivers/iio/industrialio-backend.c | 418 +++++++++++++++++++++++++++++
+ include/linux/iio/backend.h        |  72 +++++
+ 5 files changed, 508 insertions(+)
+ create mode 100644 drivers/iio/industrialio-backend.c
+ create mode 100644 include/linux/iio/backend.h
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 72a2880afab7a..b778fdbf744ae 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -10157,6 +10157,14 @@ L:    linux-media@vger.kernel.org
+ S:    Maintained
+ F:    drivers/media/rc/iguanair.c
++IIO BACKEND FRAMEWORK
++M:    Nuno Sa <nuno.sa@analog.com>
++R:    Olivier Moysan <olivier.moysan@foss.st.com>
++L:    linux-iio@vger.kernel.org
++S:    Maintained
++F:    drivers/iio/industrialio-backend.c
++F:    include/linux/iio/backend.h
++
+ IIO DIGITAL POTENTIOMETER DAC
+ M:    Peter Rosin <peda@axentia.se>
+ L:    linux-iio@vger.kernel.org
+diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
+index 52eb46ef84c1b..9c351ffc7bed6 100644
+--- a/drivers/iio/Kconfig
++++ b/drivers/iio/Kconfig
+@@ -71,6 +71,15 @@ config IIO_TRIGGERED_EVENT
+       help
+         Provides helper functions for setting up triggered events.
++config IIO_BACKEND
++      tristate
++      help
++        Framework to handle complex IIO aggregate devices. The typical
++        architecture that can make use of this framework is to have one
++        device as the frontend device which can be "linked" against one or
++        multiple backend devices. The framework then makes it easy to get
++        and control such backend devices.
++
+ source "drivers/iio/accel/Kconfig"
+ source "drivers/iio/adc/Kconfig"
+ source "drivers/iio/addac/Kconfig"
+diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
+index 9622347a1c1be..0ba0e1521ba4f 100644
+--- a/drivers/iio/Makefile
++++ b/drivers/iio/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_IIO_GTS_HELPER) += industrialio-gts-helper.o
+ obj-$(CONFIG_IIO_SW_DEVICE) += industrialio-sw-device.o
+ obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o
+ obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o
++obj-$(CONFIG_IIO_BACKEND) += industrialio-backend.o
+ obj-y += accel/
+ obj-y += adc/
+diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
+new file mode 100644
+index 0000000000000..2fea2bbbe47fd
+--- /dev/null
++++ b/drivers/iio/industrialio-backend.c
+@@ -0,0 +1,418 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Framework to handle complex IIO aggregate devices.
++ *
++ * The typical architecture is to have one device as the frontend device which
++ * can be "linked" against one or multiple backend devices. All the IIO and
++ * userspace interface is expected to be registers/managed by the frontend
++ * device which will callback into the backends when needed (to get/set some
++ * configuration that it does not directly control).
++ *
++ *                                           -------------------------------------------------------
++ * ------------------                        | ------------         ------------      -------  FPGA|
++ * |     ADC        |------------------------| | ADC CORE |---------| DMA CORE |------| RAM |      |
++ * | (Frontend/IIO) | Serial Data (eg: LVDS) | |(backend) |---------|          |------|     |      |
++ * |                |------------------------| ------------         ------------      -------      |
++ * ------------------                        -------------------------------------------------------
++ *
++ * The framework interface is pretty simple:
++ *   - Backends should register themselves with devm_iio_backend_register()
++ *   - Frontend devices should get backends with devm_iio_backend_get()
++ *
++ * Also to note that the primary target for this framework are converters like
++ * ADC/DACs so iio_backend_ops will have some operations typical of converter
++ * devices. On top of that, this is "generic" for all IIO which means any kind
++ * of device can make use of the framework. That said, If the iio_backend_ops
++ * struct begins to grow out of control, we can always refactor things so that
++ * the industrialio-backend.c is only left with the really generic stuff. Then,
++ * we can build on top of it depending on the needs.
++ *
++ * Copyright (C) 2023-2024 Analog Devices Inc.
++ */
++#define dev_fmt(fmt) "iio-backend: " fmt
++
++#include <linux/cleanup.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/property.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++
++#include <linux/iio/backend.h>
++
++struct iio_backend {
++      struct list_head entry;
++      const struct iio_backend_ops *ops;
++      struct device *dev;
++      struct module *owner;
++      void *priv;
++};
++
++/*
++ * Helper struct for requesting buffers. This ensures that we have all data
++ * that we need to free the buffer in a device managed action.
++ */
++struct iio_backend_buffer_pair {
++      struct iio_backend *back;
++      struct iio_buffer *buffer;
++};
++
++static LIST_HEAD(iio_back_list);
++static DEFINE_MUTEX(iio_back_lock);
++
++/*
++ * Helper macros to call backend ops. Makes sure the option is supported.
++ */
++#define iio_backend_check_op(back, op) ({ \
++      struct iio_backend *____back = back;                            \
++      int ____ret = 0;                                                \
++                                                                      \
++      if (!____back->ops->op)                                         \
++              ____ret = -EOPNOTSUPP;                                  \
++                                                                      \
++      ____ret;                                                        \
++})
++
++#define iio_backend_op_call(back, op, args...) ({             \
++      struct iio_backend *__back = back;                      \
++      int __ret;                                              \
++                                                              \
++      __ret = iio_backend_check_op(__back, op);               \
++      if (!__ret)                                             \
++              __ret = __back->ops->op(__back, ##args);        \
++                                                              \
++      __ret;                                                  \
++})
++
++#define iio_backend_ptr_op_call(back, op, args...) ({         \
++      struct iio_backend *__back = back;                      \
++      void *ptr_err;                                          \
++      int __ret;                                              \
++                                                              \
++      __ret = iio_backend_check_op(__back, op);               \
++      if (__ret)                                              \
++              ptr_err = ERR_PTR(__ret);                       \
++      else                                                    \
++              ptr_err = __back->ops->op(__back, ##args);      \
++                                                              \
++      ptr_err;                                                \
++})
++
++#define iio_backend_void_op_call(back, op, args...) {         \
++      struct iio_backend *__back = back;                      \
++      int __ret;                                              \
++                                                              \
++      __ret = iio_backend_check_op(__back, op);               \
++      if (!__ret)                                             \
++              __back->ops->op(__back, ##args);                \
++}
++
++/**
++ * iio_backend_chan_enable - Enable a backend channel
++ * @back:     Backend device
++ * @chan:     Channel number
++ *
++ * RETURNS:
++ * 0 on success, negative error number on failure.
++ */
++int iio_backend_chan_enable(struct iio_backend *back, unsigned int chan)
++{
++      return iio_backend_op_call(back, chan_enable, chan);
++}
++EXPORT_SYMBOL_NS_GPL(iio_backend_chan_enable, IIO_BACKEND);
++
++/**
++ * iio_backend_chan_disable - Disable a backend channel
++ * @back:     Backend device
++ * @chan:     Channel number
++ *
++ * RETURNS:
++ * 0 on success, negative error number on failure.
++ */
++int iio_backend_chan_disable(struct iio_backend *back, unsigned int chan)
++{
++      return iio_backend_op_call(back, chan_disable, chan);
++}
++EXPORT_SYMBOL_NS_GPL(iio_backend_chan_disable, IIO_BACKEND);
++
++static void __iio_backend_disable(void *back)
++{
++      iio_backend_void_op_call(back, disable);
++}
++
++/**
++ * devm_iio_backend_enable - Device managed backend enable
++ * @dev:      Consumer device for the backend
++ * @back:     Backend device
++ *
++ * RETURNS:
++ * 0 on success, negative error number on failure.
++ */
++int devm_iio_backend_enable(struct device *dev, struct iio_backend *back)
++{
++      int ret;
++
++      ret = iio_backend_op_call(back, enable);
++      if (ret)
++              return ret;
++
++      return devm_add_action_or_reset(dev, __iio_backend_disable, back);
++}
++EXPORT_SYMBOL_NS_GPL(devm_iio_backend_enable, IIO_BACKEND);
++
++/**
++ * iio_backend_data_format_set - Configure the channel data format
++ * @back:     Backend device
++ * @chan:     Channel number
++ * @data:     Data format
++ *
++ * Properly configure a channel with respect to the expected data format. A
++ * @struct iio_backend_data_fmt must be passed with the settings.
++ *
++ * RETURNS:
++ * 0 on success, negative error number on failure.
++ */
++int iio_backend_data_format_set(struct iio_backend *back, unsigned int chan,
++                              const struct iio_backend_data_fmt *data)
++{
++      if (!data || data->type >= IIO_BACKEND_DATA_TYPE_MAX)
++              return -EINVAL;
++
++      return iio_backend_op_call(back, data_format_set, chan, data);
++}
++EXPORT_SYMBOL_NS_GPL(iio_backend_data_format_set, IIO_BACKEND);
++
++static void iio_backend_free_buffer(void *arg)
++{
++      struct iio_backend_buffer_pair *pair = arg;
++
++      iio_backend_void_op_call(pair->back, free_buffer, pair->buffer);
++}
++
++/**
++ * devm_iio_backend_request_buffer - Device managed buffer request
++ * @dev:      Consumer device for the backend
++ * @back:     Backend device
++ * @indio_dev:        IIO device
++ *
++ * Request an IIO buffer from the backend. The type of the buffer (typically
++ * INDIO_BUFFER_HARDWARE) is up to the backend to decide. This is because,
++ * normally, the backend dictates what kind of buffering we can get.
++ *
++ * The backend .free_buffer() hooks is automatically called on @dev detach.
++ *
++ * RETURNS:
++ * 0 on success, negative error number on failure.
++ */
++int devm_iio_backend_request_buffer(struct device *dev,
++                                  struct iio_backend *back,
++                                  struct iio_dev *indio_dev)
++{
++      struct iio_backend_buffer_pair *pair;
++      struct iio_buffer *buffer;
++
++      pair = devm_kzalloc(dev, sizeof(*pair), GFP_KERNEL);
++      if (!pair)
++              return -ENOMEM;
++
++      buffer = iio_backend_ptr_op_call(back, request_buffer, indio_dev);
++      if (IS_ERR(buffer))
++              return PTR_ERR(buffer);
++
++      /* weak reference should be all what we need */
++      pair->back = back;
++      pair->buffer = buffer;
++
++      return devm_add_action_or_reset(dev, iio_backend_free_buffer, pair);
++}
++EXPORT_SYMBOL_NS_GPL(devm_iio_backend_request_buffer, IIO_BACKEND);
++
++static void iio_backend_release(void *arg)
++{
++      struct iio_backend *back = arg;
++
++      module_put(back->owner);
++}
++
++static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
++{
++      struct device_link *link;
++      int ret;
++
++      /*
++       * Make sure the provider cannot be unloaded before the consumer module.
++       * Note that device_links would still guarantee that nothing is
++       * accessible (and breaks) but this makes it explicit that the consumer
++       * module must be also unloaded.
++       */
++      if (!try_module_get(back->owner))
++              return dev_err_probe(dev, -ENODEV,
++                                   "Cannot get module reference\n");
++
++      ret = devm_add_action_or_reset(dev, iio_backend_release, back);
++      if (ret)
++              return ret;
++
++      link = device_link_add(dev, back->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
++      if (!link)
++              return dev_err_probe(dev, -EINVAL,
++                                   "Could not link to supplier(%s)\n",
++                                   dev_name(back->dev));
++
++      dev_dbg(dev, "Found backend(%s) device\n", dev_name(back->dev));
++
++      return 0;
++}
++
++/**
++ * devm_iio_backend_get - Device managed backend device get
++ * @dev:      Consumer device for the backend
++ * @name:     Backend name
++ *
++ * Get's the backend associated with @dev.
++ *
++ * RETURNS:
++ * A backend pointer, negative error pointer otherwise.
++ */
++struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name)
++{
++      struct fwnode_handle *fwnode;
++      struct iio_backend *back;
++      unsigned int index;
++      int ret;
++
++      if (name) {
++              ret = device_property_match_string(dev, "io-backend-names",
++                                                 name);
++              if (ret < 0)
++                      return ERR_PTR(ret);
++              index = ret;
++      } else {
++              index = 0;
++      }
++
++      fwnode = fwnode_find_reference(dev_fwnode(dev), "io-backends", index);
++      if (IS_ERR(fwnode)) {
++              dev_err_probe(dev, PTR_ERR(fwnode),
++                            "Cannot get Firmware reference\n");
++              return ERR_CAST(fwnode);
++      }
++
++      guard(mutex)(&iio_back_lock);
++      list_for_each_entry(back, &iio_back_list, entry) {
++              if (!device_match_fwnode(back->dev, fwnode))
++                      continue;
++
++              fwnode_handle_put(fwnode);
++              ret = __devm_iio_backend_get(dev, back);
++              if (ret)
++                      return ERR_PTR(ret);
++
++              return back;
++      }
++
++      fwnode_handle_put(fwnode);
++      return ERR_PTR(-EPROBE_DEFER);
++}
++EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get, IIO_BACKEND);
++
++/**
++ * __devm_iio_backend_get_from_fwnode_lookup - Device managed fwnode backend device get
++ * @dev:      Consumer device for the backend
++ * @fwnode:   Firmware node of the backend device
++ *
++ * Search the backend list for a device matching @fwnode.
++ * This API should not be used and it's only present for preventing the first
++ * user of this framework to break it's DT ABI.
++ *
++ * RETURNS:
++ * A backend pointer, negative error pointer otherwise.
++ */
++struct iio_backend *
++__devm_iio_backend_get_from_fwnode_lookup(struct device *dev,
++                                        struct fwnode_handle *fwnode)
++{
++      struct iio_backend *back;
++      int ret;
++
++      guard(mutex)(&iio_back_lock);
++      list_for_each_entry(back, &iio_back_list, entry) {
++              if (!device_match_fwnode(back->dev, fwnode))
++                      continue;
++
++              ret = __devm_iio_backend_get(dev, back);
++              if (ret)
++                      return ERR_PTR(ret);
++
++              return back;
++      }
++
++      return ERR_PTR(-EPROBE_DEFER);
++}
++EXPORT_SYMBOL_NS_GPL(__devm_iio_backend_get_from_fwnode_lookup, IIO_BACKEND);
++
++/**
++ * iio_backend_get_priv - Get driver private data
++ * @back:     Backend device
++ */
++void *iio_backend_get_priv(const struct iio_backend *back)
++{
++      return back->priv;
++}
++EXPORT_SYMBOL_NS_GPL(iio_backend_get_priv, IIO_BACKEND);
++
++static void iio_backend_unregister(void *arg)
++{
++      struct iio_backend *back = arg;
++
++      guard(mutex)(&iio_back_lock);
++      list_del(&back->entry);
++}
++
++/**
++ * devm_iio_backend_register - Device managed backend device register
++ * @dev:      Backend device being registered
++ * @ops:      Backend ops
++ * @priv:     Device private data
++ *
++ * @ops is mandatory. Not providing it results in -EINVAL.
++ *
++ * RETURNS:
++ * 0 on success, negative error number on failure.
++ */
++int devm_iio_backend_register(struct device *dev,
++                            const struct iio_backend_ops *ops, void *priv)
++{
++      struct iio_backend *back;
++
++      if (!ops)
++              return dev_err_probe(dev, -EINVAL, "No backend ops given\n");
++
++      /*
++       * Through device_links, we guarantee that a frontend device cannot be
++       * bound/exist if the backend driver is not around. Hence, we can bind
++       * the backend object lifetime with the device being passed since
++       * removing it will tear the frontend/consumer down.
++       */
++      back = devm_kzalloc(dev, sizeof(*back), GFP_KERNEL);
++      if (!back)
++              return -ENOMEM;
++
++      back->ops = ops;
++      back->owner = dev->driver->owner;
++      back->dev = dev;
++      back->priv = priv;
++      scoped_guard(mutex, &iio_back_lock)
++              list_add(&back->entry, &iio_back_list);
++
++      return devm_add_action_or_reset(dev, iio_backend_unregister, back);
++}
++EXPORT_SYMBOL_NS_GPL(devm_iio_backend_register, IIO_BACKEND);
++
++MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
++MODULE_DESCRIPTION("Framework to handle complex IIO aggregate devices");
++MODULE_LICENSE("GPL");
+diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
+new file mode 100644
+index 0000000000000..a6d79381866ec
+--- /dev/null
++++ b/include/linux/iio/backend.h
+@@ -0,0 +1,72 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++#ifndef _IIO_BACKEND_H_
++#define _IIO_BACKEND_H_
++
++#include <linux/types.h>
++
++struct fwnode_handle;
++struct iio_backend;
++struct device;
++struct iio_dev;
++
++enum iio_backend_data_type {
++      IIO_BACKEND_TWOS_COMPLEMENT,
++      IIO_BACKEND_OFFSET_BINARY,
++      IIO_BACKEND_DATA_TYPE_MAX
++};
++
++/**
++ * struct iio_backend_data_fmt - Backend data format
++ * @type:             Data type.
++ * @sign_extend:      Bool to tell if the data is sign extended.
++ * @enable:           Enable/Disable the data format module. If disabled,
++ *                    not formatting will happen.
++ */
++struct iio_backend_data_fmt {
++      enum iio_backend_data_type type;
++      bool sign_extend;
++      bool enable;
++};
++
++/**
++ * struct iio_backend_ops - operations structure for an iio_backend
++ * @enable:           Enable backend.
++ * @disable:          Disable backend.
++ * @chan_enable:      Enable one channel.
++ * @chan_disable:     Disable one channel.
++ * @data_format_set:  Configure the data format for a specific channel.
++ * @request_buffer:   Request an IIO buffer.
++ * @free_buffer:      Free an IIO buffer.
++ **/
++struct iio_backend_ops {
++      int (*enable)(struct iio_backend *back);
++      void (*disable)(struct iio_backend *back);
++      int (*chan_enable)(struct iio_backend *back, unsigned int chan);
++      int (*chan_disable)(struct iio_backend *back, unsigned int chan);
++      int (*data_format_set)(struct iio_backend *back, unsigned int chan,
++                             const struct iio_backend_data_fmt *data);
++      struct iio_buffer *(*request_buffer)(struct iio_backend *back,
++                                           struct iio_dev *indio_dev);
++      void (*free_buffer)(struct iio_backend *back,
++                          struct iio_buffer *buffer);
++};
++
++int iio_backend_chan_enable(struct iio_backend *back, unsigned int chan);
++int iio_backend_chan_disable(struct iio_backend *back, unsigned int chan);
++int devm_iio_backend_enable(struct device *dev, struct iio_backend *back);
++int iio_backend_data_format_set(struct iio_backend *back, unsigned int chan,
++                              const struct iio_backend_data_fmt *data);
++int devm_iio_backend_request_buffer(struct device *dev,
++                                  struct iio_backend *back,
++                                  struct iio_dev *indio_dev);
++
++void *iio_backend_get_priv(const struct iio_backend *conv);
++struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name);
++struct iio_backend *
++__devm_iio_backend_get_from_fwnode_lookup(struct device *dev,
++                                        struct fwnode_handle *fwnode);
++
++int devm_iio_backend_register(struct device *dev,
++                            const struct iio_backend_ops *ops, void *priv);
++
++#endif
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-buffer-dmaengine-export-buffer-alloc-and-free-fu.patch b/queue-6.6/iio-buffer-dmaengine-export-buffer-alloc-and-free-fu.patch
new file mode 100644 (file)
index 0000000..96ad624
--- /dev/null
@@ -0,0 +1,104 @@
+From b7d7abce88c267b7ba6c7b091f7dad6abb2c0d97 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 10 Feb 2024 21:57:16 +0100
+Subject: iio: buffer-dmaengine: export buffer alloc and free functions
+
+From: Nuno Sa <nuno.sa@analog.com>
+
+[ Upstream commit 9c446288d7b31402adb454535cb2c3cbdb55bb88 ]
+
+Export iio_dmaengine_buffer_free() and iio_dmaengine_buffer_alloc().
+This is in preparation of introducing IIO backends support. This will
+allow us to allocate a buffer and control it's lifetime from a device
+different from the one holding the DMA firmware properties. Effectively,
+in this case the struct device holding the firmware information about
+the DMA channels is not the same as iio_dev->dev.parent (typical case).
+
+While at it, namespace the buffer-dmaengine exports and update the
+current user of these buffers.
+
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20240210-iio-backend-v11-4-f5242a5fb42a@analog.com
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/adi-axi-adc.c                      | 1 +
+ drivers/iio/buffer/industrialio-buffer-dmaengine.c | 8 +++++---
+ include/linux/iio/buffer-dmaengine.h               | 3 +++
+ 3 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
+index c247ff1541d28..0f21d1d98b9fa 100644
+--- a/drivers/iio/adc/adi-axi-adc.c
++++ b/drivers/iio/adc/adi-axi-adc.c
+@@ -447,3 +447,4 @@ module_platform_driver(adi_axi_adc_driver);
+ MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
+ MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
+ MODULE_LICENSE("GPL v2");
++MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);
+diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+index 5f85ba38e6f6e..0d53c0a07b0d6 100644
+--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
++++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+@@ -159,7 +159,7 @@ static const struct iio_dev_attr *iio_dmaengine_buffer_attrs[] = {
+  * Once done using the buffer iio_dmaengine_buffer_free() should be used to
+  * release it.
+  */
+-static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
++struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
+       const char *channel)
+ {
+       struct dmaengine_buffer *dmaengine_buffer;
+@@ -210,6 +210,7 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
+       kfree(dmaengine_buffer);
+       return ERR_PTR(ret);
+ }
++EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_alloc, IIO_DMAENGINE_BUFFER);
+ /**
+  * iio_dmaengine_buffer_free() - Free dmaengine buffer
+@@ -217,7 +218,7 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
+  *
+  * Frees a buffer previously allocated with iio_dmaengine_buffer_alloc().
+  */
+-static void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
++void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
+ {
+       struct dmaengine_buffer *dmaengine_buffer =
+               iio_buffer_to_dmaengine_buffer(buffer);
+@@ -227,6 +228,7 @@ static void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
+       iio_buffer_put(buffer);
+ }
++EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_free, IIO_DMAENGINE_BUFFER);
+ static void __devm_iio_dmaengine_buffer_free(void *buffer)
+ {
+@@ -288,7 +290,7 @@ int devm_iio_dmaengine_buffer_setup(struct device *dev,
+       return iio_device_attach_buffer(indio_dev, buffer);
+ }
+-EXPORT_SYMBOL_GPL(devm_iio_dmaengine_buffer_setup);
++EXPORT_SYMBOL_NS_GPL(devm_iio_dmaengine_buffer_setup, IIO_DMAENGINE_BUFFER);
+ MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+ MODULE_DESCRIPTION("DMA buffer for the IIO framework");
+diff --git a/include/linux/iio/buffer-dmaengine.h b/include/linux/iio/buffer-dmaengine.h
+index 5c355be898149..cbb8ba957fade 100644
+--- a/include/linux/iio/buffer-dmaengine.h
++++ b/include/linux/iio/buffer-dmaengine.h
+@@ -10,6 +10,9 @@
+ struct iio_dev;
+ struct device;
++struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
++                                            const char *channel);
++void iio_dmaengine_buffer_free(struct iio_buffer *buffer);
+ int devm_iio_dmaengine_buffer_setup(struct device *dev,
+                                   struct iio_dev *indio_dev,
+                                   const char *channel);
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-core-leave-private-pointer-null-when-no-private-.patch b/queue-6.6/iio-core-leave-private-pointer-null-when-no-private-.patch
new file mode 100644 (file)
index 0000000..6913f37
--- /dev/null
@@ -0,0 +1,43 @@
+From bcbce9fa71948dfafc2069f5163c0090ffcc70db Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:04:32 +0200
+Subject: iio: core: Leave private pointer NULL when no private data supplied
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit f0245ab389330cbc1d187e358a5b890d9f5383db ]
+
+In iio_device_alloc() when size of the private data is 0,
+the private pointer is calculated to point behind the valid data.
+Leave it NULL when no private data supplied.
+
+Fixes: 6d4ebd565d15 ("iio: core: wrap IIO device into an iio_dev_opaque object")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Link: https://lore.kernel.org/r/20240304140650.977784-2-andriy.shevchenko@linux.intel.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/industrialio-core.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
+index feec93adb0651..5e1a85ca12119 100644
+--- a/drivers/iio/industrialio-core.c
++++ b/drivers/iio/industrialio-core.c
+@@ -1649,8 +1649,10 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
+               return NULL;
+       indio_dev = &iio_dev_opaque->indio_dev;
+-      indio_dev->priv = (char *)iio_dev_opaque +
+-              ALIGN(sizeof(struct iio_dev_opaque), IIO_DMA_MINALIGN);
++
++      if (sizeof_priv)
++              indio_dev->priv = (char *)iio_dev_opaque +
++                      ALIGN(sizeof(*iio_dev_opaque), IIO_DMA_MINALIGN);
+       indio_dev->dev.parent = parent;
+       indio_dev->dev.type = &iio_device_type;
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-pressure-dps310-support-negative-temperature-val.patch b/queue-6.6/iio-pressure-dps310-support-negative-temperature-val.patch
new file mode 100644 (file)
index 0000000..bf5170a
--- /dev/null
@@ -0,0 +1,67 @@
+From 1317c9ddd386f387fac0a13b40445b9801aec4ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Apr 2024 12:50:27 +0200
+Subject: iio: pressure: dps310: support negative temperature values
+
+From: Thomas Haemmerle <thomas.haemmerle@leica-geosystems.com>
+
+[ Upstream commit 9dd6b32e76ff714308964cd9ec91466a343dcb8b ]
+
+The current implementation interprets negative values returned from
+`dps310_calculate_temp` as error codes.
+This has a side effect that when negative temperature values are
+calculated, they are interpreted as error.
+
+Fix this by using the return value only for error handling and passing a
+pointer for the value.
+
+Fixes: ba6ec48e76bc ("iio: Add driver for Infineon DPS310")
+Signed-off-by: Thomas Haemmerle <thomas.haemmerle@leica-geosystems.com>
+Link: https://lore.kernel.org/r/20240415105030.1161770-2-thomas.haemmerle@leica-geosystems.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/pressure/dps310.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c
+index 1ff091b2f764d..d0a516d56da47 100644
+--- a/drivers/iio/pressure/dps310.c
++++ b/drivers/iio/pressure/dps310.c
+@@ -730,7 +730,7 @@ static int dps310_read_pressure(struct dps310_data *data, int *val, int *val2,
+       }
+ }
+-static int dps310_calculate_temp(struct dps310_data *data)
++static int dps310_calculate_temp(struct dps310_data *data, int *val)
+ {
+       s64 c0;
+       s64 t;
+@@ -746,7 +746,9 @@ static int dps310_calculate_temp(struct dps310_data *data)
+       t = c0 + ((s64)data->temp_raw * (s64)data->c1);
+       /* Convert to milliCelsius and scale the temperature */
+-      return (int)div_s64(t * 1000LL, kt);
++      *val = (int)div_s64(t * 1000LL, kt);
++
++      return 0;
+ }
+ static int dps310_read_temp(struct dps310_data *data, int *val, int *val2,
+@@ -768,11 +770,10 @@ static int dps310_read_temp(struct dps310_data *data, int *val, int *val2,
+               if (rc)
+                       return rc;
+-              rc = dps310_calculate_temp(data);
+-              if (rc < 0)
++              rc = dps310_calculate_temp(data, val);
++              if (rc)
+                       return rc;
+-              *val = rc;
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+-- 
+2.43.0
+
diff --git a/queue-6.6/interconnect-qcom-qcm2290-fix-mas_snoc_bimc-qos-port.patch b/queue-6.6/interconnect-qcom-qcm2290-fix-mas_snoc_bimc-qos-port.patch
new file mode 100644 (file)
index 0000000..7a8e0e0
--- /dev/null
@@ -0,0 +1,37 @@
+From 4efd84feb4acec66b6ba3000d6e169f3e542ca9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Mar 2024 20:42:33 +0100
+Subject: interconnect: qcom: qcm2290: Fix mas_snoc_bimc QoS port assignment
+
+From: Konrad Dybcio <konrad.dybcio@linaro.org>
+
+[ Upstream commit 230d05b1179f6ce6f8dc8a2b99eba92799ac22d7 ]
+
+The value was wrong, resulting in misprogramming of the hardware.
+Fix it.
+
+Fixes: 1a14b1ac3935 ("interconnect: qcom: Add QCM2290 driver support")
+Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20240326-topic-rpm_icc_qos_cleanup-v1-2-357e736792be@linaro.org
+Signed-off-by: Georgi Djakov <djakov@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/interconnect/qcom/qcm2290.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/interconnect/qcom/qcm2290.c b/drivers/interconnect/qcom/qcm2290.c
+index 5bc4b7516608b..52346f7319acc 100644
+--- a/drivers/interconnect/qcom/qcm2290.c
++++ b/drivers/interconnect/qcom/qcm2290.c
+@@ -161,7 +161,7 @@ static struct qcom_icc_node mas_snoc_bimc = {
+       .name = "mas_snoc_bimc",
+       .buswidth = 16,
+       .qos.ap_owned = true,
+-      .qos.qos_port = 2,
++      .qos.qos_port = 6,
+       .qos.qos_mode = NOC_QOS_MODE_BYPASS,
+       .mas_rpm_id = 164,
+       .slv_rpm_id = -1,
+-- 
+2.43.0
+
diff --git a/queue-6.6/kbuild-fix-build-id-symlinks-to-installed-debug-vdso.patch b/queue-6.6/kbuild-fix-build-id-symlinks-to-installed-debug-vdso.patch
new file mode 100644 (file)
index 0000000..05f61d1
--- /dev/null
@@ -0,0 +1,36 @@
+From 6f1d3fc1dc174ebbd6f5501deccc341d2632dd9c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Dec 2023 17:18:33 +0900
+Subject: kbuild: fix build ID symlinks to installed debug VDSO files
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+[ Upstream commit c1a8627164dbe8b92958aea10c7c0848105a3d7f ]
+
+Commit 56769ba4b297 ("kbuild: unify vdso_install rules") accidentally
+dropped the '.debug' suffix from the build ID symlinks.
+
+Fixes: 56769ba4b297 ("kbuild: unify vdso_install rules")
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Stable-dep-of: fc2f5f10f9bc ("s390/vdso: Create .build-id links for unstripped vdso files")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/Makefile.vdsoinst | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/Makefile.vdsoinst b/scripts/Makefile.vdsoinst
+index 1022d9fdd976d..c477d17b0aa5b 100644
+--- a/scripts/Makefile.vdsoinst
++++ b/scripts/Makefile.vdsoinst
+@@ -22,7 +22,7 @@ $$(dest): $$(src) FORCE
+ # Some architectures create .build-id symlinks
+ ifneq ($(filter arm sparc x86, $(SRCARCH)),)
+-link := $(install-dir)/.build-id/$$(shell $(READELF) -n $$(src) | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p')
++link := $(install-dir)/.build-id/$$(shell $(READELF) -n $$(src) | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p').debug
+ __default: $$(link)
+ $$(link): $$(dest) FORCE
+-- 
+2.43.0
+
diff --git a/queue-6.6/kbuild-unify-vdso_install-rules.patch b/queue-6.6/kbuild-unify-vdso_install-rules.patch
new file mode 100644 (file)
index 0000000..5d34331
--- /dev/null
@@ -0,0 +1,585 @@
+From 05cbe0332166d35c0e5675fc548ce02a64881a2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Oct 2023 19:54:35 +0900
+Subject: kbuild: unify vdso_install rules
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+[ Upstream commit 56769ba4b297a629148eb24d554aef72d1ddfd9e ]
+
+Currently, there is no standard implementation for vdso_install,
+leading to various issues:
+
+ 1. Code duplication
+
+    Many architectures duplicate similar code just for copying files
+    to the install destination.
+
+    Some architectures (arm, sparc, x86) create build-id symlinks,
+    introducing more code duplication.
+
+ 2. Unintended updates of in-tree build artifacts
+
+    The vdso_install rule depends on the vdso files to install.
+    It may update in-tree build artifacts. This can be problematic,
+    as explained in commit 19514fc665ff ("arm, kbuild: make
+    "make install" not depend on vmlinux").
+
+ 3. Broken code in some architectures
+
+    Makefile code is often copied from one architecture to another
+    without proper adaptation.
+
+    'make vdso_install' for parisc does not work.
+
+    'make vdso_install' for s390 installs vdso64, but not vdso32.
+
+To address these problems, this commit introduces a generic vdso_install
+rule.
+
+Architectures that support vdso_install need to define vdso-install-y
+in arch/*/Makefile. vdso-install-y lists the files to install.
+
+For example, arch/x86/Makefile looks like this:
+
+  vdso-install-$(CONFIG_X86_64)           += arch/x86/entry/vdso/vdso64.so.dbg
+  vdso-install-$(CONFIG_X86_X32_ABI)      += arch/x86/entry/vdso/vdsox32.so.dbg
+  vdso-install-$(CONFIG_X86_32)           += arch/x86/entry/vdso/vdso32.so.dbg
+  vdso-install-$(CONFIG_IA32_EMULATION)   += arch/x86/entry/vdso/vdso32.so.dbg
+
+These files will be installed to $(MODLIB)/vdso/ with the .dbg suffix,
+if exists, stripped away.
+
+vdso-install-y can optionally take the second field after the colon
+separator. This is needed because some architectures install a vdso
+file as a different base name.
+
+The following is a snippet from arch/arm64/Makefile.
+
+  vdso-install-$(CONFIG_COMPAT_VDSO)      += arch/arm64/kernel/vdso32/vdso.so.dbg:vdso32.so
+
+This will rename vdso.so.dbg to vdso32.so during installation. If such
+architectures change their implementation so that the base names match,
+this workaround will go away.
+
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Acked-by: Sven Schnelle <svens@linux.ibm.com> # s390
+Reviewed-by: Nicolas Schier <nicolas@fjasle.eu>
+Reviewed-by: Guo Ren <guoren@kernel.org>
+Acked-by: Helge Deller <deller@gmx.de>  # parisc
+Acked-by: Catalin Marinas <catalin.marinas@arm.com>
+Acked-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Stable-dep-of: fc2f5f10f9bc ("s390/vdso: Create .build-id links for unstripped vdso files")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Makefile                               |  9 ++++++
+ arch/arm/Makefile                      |  7 +---
+ arch/arm/vdso/Makefile                 | 25 --------------
+ arch/arm64/Makefile                    |  9 ++----
+ arch/arm64/kernel/vdso/Makefile        | 10 ------
+ arch/arm64/kernel/vdso32/Makefile      | 10 ------
+ arch/loongarch/Makefile                |  4 +--
+ arch/loongarch/vdso/Makefile           | 10 ------
+ arch/parisc/Makefile                   |  8 ++---
+ arch/riscv/Makefile                    |  9 ++----
+ arch/riscv/kernel/compat_vdso/Makefile | 10 ------
+ arch/riscv/kernel/vdso/Makefile        | 10 ------
+ arch/s390/Makefile                     |  6 ++--
+ arch/s390/kernel/vdso32/Makefile       | 10 ------
+ arch/s390/kernel/vdso64/Makefile       | 10 ------
+ arch/sparc/Makefile                    |  5 ++-
+ arch/sparc/vdso/Makefile               | 27 ----------------
+ arch/x86/Makefile                      |  7 ++--
+ arch/x86/entry/vdso/Makefile           | 27 ----------------
+ scripts/Makefile.vdsoinst              | 45 ++++++++++++++++++++++++++
+ 20 files changed, 73 insertions(+), 185 deletions(-)
+ create mode 100644 scripts/Makefile.vdsoinst
+
+diff --git a/Makefile b/Makefile
+index c3b324ed985e6..370f9719fc2b1 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1317,6 +1317,14 @@ scripts_unifdef: scripts_basic
+ quiet_cmd_install = INSTALL $(INSTALL_PATH)
+       cmd_install = unset sub_make_done; $(srctree)/scripts/install.sh
++# ---------------------------------------------------------------------------
++# vDSO install
++
++PHONY += vdso_install
++vdso_install: export INSTALL_FILES = $(vdso-install-y)
++vdso_install:
++      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vdsoinst
++
+ # ---------------------------------------------------------------------------
+ # Tools
+@@ -1560,6 +1568,7 @@ help:
+       @echo  '* vmlinux         - Build the bare kernel'
+       @echo  '* modules         - Build all modules'
+       @echo  '  modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
++      @echo  '  vdso_install    - Install unstripped vdso to INSTALL_MOD_PATH (default: /)'
+       @echo  '  dir/            - Build all files in dir and below'
+       @echo  '  dir/file.[ois]  - Build specified target only'
+       @echo  '  dir/file.ll     - Build the LLVM assembly file'
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index 547e5856eaa0d..5ba42f69f8ce0 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -304,11 +304,7 @@ $(INSTALL_TARGETS): KBUILD_IMAGE = $(boot)/$(patsubst %install,%Image,$@)
+ $(INSTALL_TARGETS):
+       $(call cmd,install)
+-PHONY += vdso_install
+-vdso_install:
+-ifeq ($(CONFIG_VDSO),y)
+-      $(Q)$(MAKE) $(build)=arch/arm/vdso $@
+-endif
++vdso-install-$(CONFIG_VDSO) += arch/arm/vdso/vdso.so.dbg
+ # My testing targets (bypasses dependencies)
+ bp:;  $(Q)$(MAKE) $(build)=$(boot) $(boot)/bootpImage
+@@ -331,7 +327,6 @@ define archhelp
+   echo  '                  Install using (your) ~/bin/$(INSTALLKERNEL) or'
+   echo  '                  (distribution) /sbin/$(INSTALLKERNEL) or'
+   echo  '                  install to $$(INSTALL_PATH) and run lilo'
+-  echo  '  vdso_install  - Install unstripped vdso.so to $$(INSTALL_MOD_PATH)/vdso'
+   echo
+   echo  '  multi_v7_lpae_defconfig     - multi_v7_defconfig with CONFIG_ARM_LPAE enabled'
+ endef
+diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile
+index 515ca33b854c1..d761bd2e2f407 100644
+--- a/arch/arm/vdso/Makefile
++++ b/arch/arm/vdso/Makefile
+@@ -63,28 +63,3 @@ quiet_cmd_vdsold_and_vdso_check = LD      $@
+ quiet_cmd_vdsomunge = MUNGE   $@
+       cmd_vdsomunge = $(objtree)/$(obj)/vdsomunge $< $@
+-
+-#
+-# Install the unstripped copy of vdso.so.dbg.  If our toolchain
+-# supports build-id, install .build-id links as well.
+-#
+-# Cribbed from arch/x86/vdso/Makefile.
+-#
+-quiet_cmd_vdso_install = INSTALL $<
+-define cmd_vdso_install
+-      cp $< "$(MODLIB)/vdso/vdso.so"; \
+-      if readelf -n $< | grep -q 'Build ID'; then \
+-        buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
+-        first=`echo $$buildid | cut -b-2`; \
+-        last=`echo $$buildid | cut -b3-`; \
+-        mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
+-        ln -sf "../../vdso.so" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
+-      fi
+-endef
+-
+-$(MODLIB)/vdso: FORCE
+-      @mkdir -p $(MODLIB)/vdso
+-
+-PHONY += vdso_install
+-vdso_install: $(obj)/vdso.so.dbg $(MODLIB)/vdso
+-      $(call cmd,vdso_install)
+diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
+index 26b8c7630a214..9a2d3723cd0fa 100644
+--- a/arch/arm64/Makefile
++++ b/arch/arm64/Makefile
+@@ -169,12 +169,6 @@ install: KBUILD_IMAGE := $(boot)/Image
+ install zinstall:
+       $(call cmd,install)
+-PHONY += vdso_install
+-vdso_install:
+-      $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@
+-      $(if $(CONFIG_COMPAT_VDSO), \
+-              $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 $@)
+-
+ archprepare:
+       $(Q)$(MAKE) $(build)=arch/arm64/tools kapi
+ ifeq ($(CONFIG_ARM64_ERRATUM_843419),y)
+@@ -205,6 +199,9 @@ ifdef CONFIG_COMPAT_VDSO
+ endif
+ endif
++vdso-install-y                                += arch/arm64/kernel/vdso/vdso.so.dbg
++vdso-install-$(CONFIG_COMPAT_VDSO)    += arch/arm64/kernel/vdso32/vdso.so.dbg:vdso32.so
++
+ include $(srctree)/scripts/Makefile.defconf
+ PHONY += virtconfig
+diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
+index fe7a53c6781f1..8818287f10955 100644
+--- a/arch/arm64/kernel/vdso/Makefile
++++ b/arch/arm64/kernel/vdso/Makefile
+@@ -78,13 +78,3 @@ include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
+ # Actual build commands
+ quiet_cmd_vdsold_and_vdso_check = LD      $@
+       cmd_vdsold_and_vdso_check = $(cmd_ld); $(cmd_vdso_check)
+-
+-# Install commands for the unstripped file
+-quiet_cmd_vdso_install = INSTALL $@
+-      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+-
+-vdso.so: $(obj)/vdso.so.dbg
+-      @mkdir -p $(MODLIB)/vdso
+-      $(call cmd,vdso_install)
+-
+-vdso_install: vdso.so
+diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile
+index 2f73e5bca213f..1f911a76c5af3 100644
+--- a/arch/arm64/kernel/vdso32/Makefile
++++ b/arch/arm64/kernel/vdso32/Makefile
+@@ -172,13 +172,3 @@ gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh
+ quiet_cmd_vdsosym = VDSOSYM $@
+ # The AArch64 nm should be able to read an AArch32 binary
+       cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
+-
+-# Install commands for the unstripped file
+-quiet_cmd_vdso_install = INSTALL32 $@
+-      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/vdso32.so
+-
+-vdso.so: $(obj)/vdso.so.dbg
+-      @mkdir -p $(MODLIB)/vdso
+-      $(call cmd,vdso_install)
+-
+-vdso_install: vdso.so
+diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile
+index d423fba7c4062..81e8089c9c4f1 100644
+--- a/arch/loongarch/Makefile
++++ b/arch/loongarch/Makefile
+@@ -136,9 +136,7 @@ vdso_prepare: prepare0
+       $(Q)$(MAKE) $(build)=arch/loongarch/vdso include/generated/vdso-offsets.h
+ endif
+-PHONY += vdso_install
+-vdso_install:
+-      $(Q)$(MAKE) $(build)=arch/loongarch/vdso $@
++vdso-install-y += arch/loongarch/vdso/vdso.so.dbg
+ all:  $(notdir $(KBUILD_IMAGE))
+diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile
+index 4305d99b33130..f597cd08a96be 100644
+--- a/arch/loongarch/vdso/Makefile
++++ b/arch/loongarch/vdso/Makefile
+@@ -84,13 +84,3 @@ $(obj)/vdso.so: $(obj)/vdso.so.dbg FORCE
+ obj-y += vdso.o
+ $(obj)/vdso.o : $(obj)/vdso.so
+-
+-# install commands for the unstripped file
+-quiet_cmd_vdso_install = INSTALL $@
+-      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+-
+-vdso.so: $(obj)/vdso.so.dbg
+-      @mkdir -p $(MODLIB)/vdso
+-      $(call cmd,vdso_install)
+-
+-vdso_install: vdso.so
+diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
+index 968ebe17494c5..920db57b6b4cc 100644
+--- a/arch/parisc/Makefile
++++ b/arch/parisc/Makefile
+@@ -177,12 +177,8 @@ vdso_prepare: prepare0
+       $(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso32 include/generated/vdso32-offsets.h
+ endif
+-PHONY += vdso_install
+-
+-vdso_install:
+-      $(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso $@
+-      $(if $(CONFIG_COMPAT_VDSO), \
+-              $(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso32 $@)
++vdso-install-y                        += arch/parisc/kernel/vdso32/vdso32.so
++vdso-install-$(CONFIG_64BIT)  += arch/parisc/kernel/vdso64/vdso64.so
+ install: KBUILD_IMAGE := vmlinux
+ zinstall: KBUILD_IMAGE := vmlinuz
+diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
+index b43a6bb7e4dcb..4d06f34026740 100644
+--- a/arch/riscv/Makefile
++++ b/arch/riscv/Makefile
+@@ -130,12 +130,6 @@ endif
+ libs-y += arch/riscv/lib/
+ libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
+-PHONY += vdso_install
+-vdso_install:
+-      $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
+-      $(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
+-              $(build)=arch/riscv/kernel/compat_vdso compat_$@)
+-
+ ifeq ($(KBUILD_EXTMOD),)
+ ifeq ($(CONFIG_MMU),y)
+ prepare: vdso_prepare
+@@ -147,6 +141,9 @@ vdso_prepare: prepare0
+ endif
+ endif
++vdso-install-y                        += arch/riscv/kernel/vdso/vdso.so.dbg
++vdso-install-$(CONFIG_COMPAT) += arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg:../compat_vdso/compat_vdso.so
++
+ ifneq ($(CONFIG_XIP_KERNEL),y)
+ ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_ARCH_CANAAN),yy)
+ KBUILD_IMAGE := $(boot)/loader.bin
+diff --git a/arch/riscv/kernel/compat_vdso/Makefile b/arch/riscv/kernel/compat_vdso/Makefile
+index b86e5e2c3aea9..62fa393b2eb2e 100644
+--- a/arch/riscv/kernel/compat_vdso/Makefile
++++ b/arch/riscv/kernel/compat_vdso/Makefile
+@@ -76,13 +76,3 @@ quiet_cmd_compat_vdsold = VDSOLD  $@
+ # actual build commands
+ quiet_cmd_compat_vdsoas = VDSOAS $@
+       cmd_compat_vdsoas = $(COMPAT_CC) $(a_flags) $(COMPAT_CC_FLAGS) -c -o $@ $<
+-
+-# install commands for the unstripped file
+-quiet_cmd_compat_vdso_install = INSTALL $@
+-      cmd_compat_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/compat_vdso/$@
+-
+-compat_vdso.so: $(obj)/compat_vdso.so.dbg
+-      @mkdir -p $(MODLIB)/compat_vdso
+-      $(call cmd,compat_vdso_install)
+-
+-compat_vdso_install: compat_vdso.so
+diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
+index 6b1dba11bf6dc..e8aa7c3800075 100644
+--- a/arch/riscv/kernel/vdso/Makefile
++++ b/arch/riscv/kernel/vdso/Makefile
+@@ -73,13 +73,3 @@ quiet_cmd_vdsold = VDSOLD  $@
+       cmd_vdsold = $(LD) $(ld_flags) -T $(filter-out FORCE,$^) -o $@.tmp && \
+                    $(OBJCOPY) $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
+                    rm $@.tmp
+-
+-# install commands for the unstripped file
+-quiet_cmd_vdso_install = INSTALL $@
+-      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+-
+-vdso.so: $(obj)/vdso.so.dbg
+-      @mkdir -p $(MODLIB)/vdso
+-      $(call cmd,vdso_install)
+-
+-vdso_install: vdso.so
+diff --git a/arch/s390/Makefile b/arch/s390/Makefile
+index a53a36ee0731b..73873e4516866 100644
+--- a/arch/s390/Makefile
++++ b/arch/s390/Makefile
+@@ -138,9 +138,6 @@ bzImage: vmlinux
+ zfcpdump:
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+-vdso_install:
+-      $(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso64 $@
+-
+ archheaders:
+       $(Q)$(MAKE) $(build)=$(syscalls) uapi
+@@ -160,6 +157,9 @@ vdso_prepare: prepare0
+       $(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
+               $(build)=arch/s390/kernel/vdso32 include/generated/vdso32-offsets.h)
++vdso-install-y                        += arch/s390/kernel/vdso64/vdso64.so.dbg
++vdso-install-$(CONFIG_COMPAT) += arch/s390/kernel/vdso32/vdso32.so.dbg
++
+ ifdef CONFIG_EXPOLINE_EXTERN
+ modules_prepare: expoline_prepare
+ expoline_prepare: scripts
+diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile
+index 9793266245587..9090c0e5de254 100644
+--- a/arch/s390/kernel/vdso32/Makefile
++++ b/arch/s390/kernel/vdso32/Makefile
+@@ -62,16 +62,6 @@ quiet_cmd_vdso32as = VDSO32A $@
+ quiet_cmd_vdso32cc = VDSO32C $@
+       cmd_vdso32cc = $(CC) $(c_flags) -c -o $@ $<
+-# install commands for the unstripped file
+-quiet_cmd_vdso_install = INSTALL $@
+-      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+-
+-vdso32.so: $(obj)/vdso32.so.dbg
+-      @mkdir -p $(MODLIB)/vdso
+-      $(call cmd,vdso_install)
+-
+-vdso_install: vdso32.so
+-
+ # Generate VDSO offsets using helper script
+ gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
+ quiet_cmd_vdsosym = VDSOSYM $@
+diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile
+index 197fa382b58ab..a44f51de1f1ea 100644
+--- a/arch/s390/kernel/vdso64/Makefile
++++ b/arch/s390/kernel/vdso64/Makefile
+@@ -72,16 +72,6 @@ quiet_cmd_vdso64as = VDSO64A $@
+ quiet_cmd_vdso64cc = VDSO64C $@
+       cmd_vdso64cc = $(CC) $(c_flags) -c -o $@ $<
+-# install commands for the unstripped file
+-quiet_cmd_vdso_install = INSTALL $@
+-      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+-
+-vdso64.so: $(obj)/vdso64.so.dbg
+-      @mkdir -p $(MODLIB)/vdso
+-      $(call cmd,vdso_install)
+-
+-vdso_install: vdso64.so
+-
+ # Generate VDSO offsets using helper script
+ gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
+ quiet_cmd_vdsosym = VDSOSYM $@
+diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
+index 60da865c079a2..2a03daa68f285 100644
+--- a/arch/sparc/Makefile
++++ b/arch/sparc/Makefile
+@@ -76,9 +76,8 @@ install:
+ archheaders:
+       $(Q)$(MAKE) $(build)=arch/sparc/kernel/syscalls all
+-PHONY += vdso_install
+-vdso_install:
+-      $(Q)$(MAKE) $(build)=arch/sparc/vdso $@
++vdso-install-$(CONFIG_SPARC64)        += arch/sparc/vdso/vdso64.so.dbg
++vdso-install-$(CONFIG_COMPAT) += arch/sparc/vdso/vdso32.so.dbg
+ # This is the image used for packaging
+ KBUILD_IMAGE := $(boot)/zImage
+diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile
+index 77d7b9032158c..d08c3a0443f3a 100644
+--- a/arch/sparc/vdso/Makefile
++++ b/arch/sparc/vdso/Makefile
+@@ -116,30 +116,3 @@ quiet_cmd_vdso = VDSO    $@
+ VDSO_LDFLAGS = -shared --hash-style=both --build-id=sha1 -Bsymbolic
+ GCOV_PROFILE := n
+-
+-#
+-# Install the unstripped copies of vdso*.so.  If our toolchain supports
+-# build-id, install .build-id links as well.
+-#
+-quiet_cmd_vdso_install = INSTALL $(@:install_%=%)
+-define cmd_vdso_install
+-      cp $< "$(MODLIB)/vdso/$(@:install_%=%)"; \
+-      if readelf -n $< |grep -q 'Build ID'; then \
+-        buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
+-        first=`echo $$buildid | cut -b-2`; \
+-        last=`echo $$buildid | cut -b3-`; \
+-        mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
+-        ln -sf "../../$(@:install_%=%)" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
+-      fi
+-endef
+-
+-vdso_img_insttargets := $(vdso_img_sodbg:%.dbg=install_%)
+-
+-$(MODLIB)/vdso: FORCE
+-      @mkdir -p $(MODLIB)/vdso
+-
+-$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso FORCE
+-      $(call cmd,vdso_install)
+-
+-PHONY += vdso_install $(vdso_img_insttargets)
+-vdso_install: $(vdso_img_insttargets) FORCE
+diff --git a/arch/x86/Makefile b/arch/x86/Makefile
+index 5bfe5caaa444b..3ff53a2d4ff08 100644
+--- a/arch/x86/Makefile
++++ b/arch/x86/Makefile
+@@ -291,9 +291,10 @@ PHONY += install
+ install:
+       $(call cmd,install)
+-PHONY += vdso_install
+-vdso_install:
+-      $(Q)$(MAKE) $(build)=arch/x86/entry/vdso $@
++vdso-install-$(CONFIG_X86_64)         += arch/x86/entry/vdso/vdso64.so.dbg
++vdso-install-$(CONFIG_X86_X32_ABI)    += arch/x86/entry/vdso/vdsox32.so.dbg
++vdso-install-$(CONFIG_X86_32)         += arch/x86/entry/vdso/vdso32.so.dbg
++vdso-install-$(CONFIG_IA32_EMULATION) += arch/x86/entry/vdso/vdso32.so.dbg
+ archprepare: checkbin
+ checkbin:
+diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
+index 6a1821bd7d5e9..c197efd829228 100644
+--- a/arch/x86/entry/vdso/Makefile
++++ b/arch/x86/entry/vdso/Makefile
+@@ -190,31 +190,4 @@ GCOV_PROFILE := n
+ quiet_cmd_vdso_and_check = VDSO    $@
+       cmd_vdso_and_check = $(cmd_vdso); $(cmd_vdso_check)
+-#
+-# Install the unstripped copies of vdso*.so.  If our toolchain supports
+-# build-id, install .build-id links as well.
+-#
+-quiet_cmd_vdso_install = INSTALL $(@:install_%=%)
+-define cmd_vdso_install
+-      cp $< "$(MODLIB)/vdso/$(@:install_%=%)"; \
+-      if readelf -n $< |grep -q 'Build ID'; then \
+-        buildid=`readelf -n $< |grep 'Build ID' |sed -e 's/^.*Build ID: \(.*\)$$/\1/'`; \
+-        first=`echo $$buildid | cut -b-2`; \
+-        last=`echo $$buildid | cut -b3-`; \
+-        mkdir -p "$(MODLIB)/vdso/.build-id/$$first"; \
+-        ln -sf "../../$(@:install_%=%)" "$(MODLIB)/vdso/.build-id/$$first/$$last.debug"; \
+-      fi
+-endef
+-
+-vdso_img_insttargets := $(vdso_img_sodbg:%.dbg=install_%)
+-
+-$(MODLIB)/vdso: FORCE
+-      @mkdir -p $(MODLIB)/vdso
+-
+-$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso
+-      $(call cmd,vdso_install)
+-
+-PHONY += vdso_install $(vdso_img_insttargets)
+-vdso_install: $(vdso_img_insttargets)
+-
+ clean-files := vdso32.so vdso32.so.dbg vdso64* vdso-image-*.c vdsox32.so*
+diff --git a/scripts/Makefile.vdsoinst b/scripts/Makefile.vdsoinst
+new file mode 100644
+index 0000000000000..1022d9fdd976d
+--- /dev/null
++++ b/scripts/Makefile.vdsoinst
+@@ -0,0 +1,45 @@
++# SPDX-License-Identifier: GPL-2.0-only
++# ==========================================================================
++# Install unstripped copies of vDSO
++# ==========================================================================
++
++PHONY := __default
++__default:
++      @:
++
++include $(srctree)/scripts/Kbuild.include
++
++install-dir := $(MODLIB)/vdso
++
++define gen_install_rules
++
++src := $$(firstword $$(subst :,$(space),$(1)))
++dest := $(install-dir)/$$(or $$(word 2,$$(subst :,$(space),$(1))),$$(patsubst %.dbg,%,$$(notdir $(1))))
++
++__default: $$(dest)
++$$(dest): $$(src) FORCE
++      $$(call cmd,install)
++
++# Some architectures create .build-id symlinks
++ifneq ($(filter arm sparc x86, $(SRCARCH)),)
++link := $(install-dir)/.build-id/$$(shell $(READELF) -n $$(src) | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p')
++
++__default: $$(link)
++$$(link): $$(dest) FORCE
++      $$(call cmd,symlink)
++endif
++
++endef
++
++$(foreach x, $(sort $(INSTALL_FILES)), $(eval $(call gen_install_rules,$(x))))
++
++quiet_cmd_install = INSTALL $@
++      cmd_install = mkdir -p $(dir $@); cp $< $@
++
++quiet_cmd_symlink = SYMLINK $@
++      cmd_symlink = mkdir -p $(dir $@); ln -sf --relative $< $@
++
++PHONY += FORCE
++FORCE:
++
++.PHONY: $(PHONY)
+-- 
+2.43.0
+
diff --git a/queue-6.6/leds-pwm-disable-pwm-when-going-to-suspend.patch b/queue-6.6/leds-pwm-disable-pwm-when-going-to-suspend.patch
new file mode 100644 (file)
index 0000000..e6b5ee9
--- /dev/null
@@ -0,0 +1,48 @@
+From 006dc0cc9d8bb22dbb9e12db431c23223a11b1aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Apr 2024 17:38:47 +0200
+Subject: leds: pwm: Disable PWM when going to suspend
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit 974afccd37947a6951a052ef8118c961e57eaf7b ]
+
+On stm32mp1xx based machines (and others) a PWM consumer has to disable
+the PWM because an enabled PWM refuses to suspend. So check the
+LED_SUSPENDED flag and depending on that set the .enabled property.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=218559
+Fixes: 76fe464c8e64 ("leds: pwm: Don't disable the PWM when the LED should be off")
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Link: https://lore.kernel.org/r/20240417153846.271751-2-u.kleine-koenig@pengutronix.de
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/leds-pwm.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index 4e3936a39d0ed..e1b414b403534 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -53,7 +53,13 @@ static int led_pwm_set(struct led_classdev *led_cdev,
+               duty = led_dat->pwmstate.period - duty;
+       led_dat->pwmstate.duty_cycle = duty;
+-      led_dat->pwmstate.enabled = true;
++      /*
++       * Disabling a PWM doesn't guarantee that it emits the inactive level.
++       * So keep it on. Only for suspending the PWM should be disabled because
++       * otherwise it refuses to suspend. The possible downside is that the
++       * LED might stay (or even go) on.
++       */
++      led_dat->pwmstate.enabled = !(led_cdev->flags & LED_SUSPENDED);
+       return pwm_apply_might_sleep(led_dat->pwm, &led_dat->pwmstate);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/libsubcmd-fix-parse-options-memory-leak.patch b/queue-6.6/libsubcmd-fix-parse-options-memory-leak.patch
new file mode 100644 (file)
index 0000000..73e09f9
--- /dev/null
@@ -0,0 +1,61 @@
+From a5ed2fd4a0f8a8171dc5d67244260816bb42c24d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 May 2024 22:20:15 -0700
+Subject: libsubcmd: Fix parse-options memory leak
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 230a7a71f92212e723fa435d4ca5922de33ec88a ]
+
+If a usage string is built in parse_options_subcommand, also free it.
+
+Fixes: 901421a5bdf605d2 ("perf tools: Remove subcmd dependencies on strbuf")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Josh Poimboeuf <jpoimboe@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240509052015.1914670-1-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/lib/subcmd/parse-options.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
+index 9fa75943f2ed1..d943d78b787ed 100644
+--- a/tools/lib/subcmd/parse-options.c
++++ b/tools/lib/subcmd/parse-options.c
+@@ -633,11 +633,10 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
+                       const char *const subcommands[], const char *usagestr[], int flags)
+ {
+       struct parse_opt_ctx_t ctx;
++      char *buf = NULL;
+       /* build usage string if it's not provided */
+       if (subcommands && !usagestr[0]) {
+-              char *buf = NULL;
+-
+               astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]);
+               for (int i = 0; subcommands[i]; i++) {
+@@ -679,7 +678,10 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
+                       astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt);
+               usage_with_options(usagestr, options);
+       }
+-
++      if (buf) {
++              usagestr[0] = NULL;
++              free(buf);
++      }
+       return parse_options_end(&ctx);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/loongarch-fix-callchain-parse-error-with-kernel-trac.patch b/queue-6.6/loongarch-fix-callchain-parse-error-with-kernel-trac.patch
new file mode 100644 (file)
index 0000000..7795abc
--- /dev/null
@@ -0,0 +1,71 @@
+From 1a0acc8af7058fb614cd54502cbfb87b1f36b766 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 May 2024 12:24:18 +0800
+Subject: LoongArch: Fix callchain parse error with kernel tracepoint events
+ again
+
+From: Huacai Chen <chenhuacai@loongson.cn>
+
+[ Upstream commit d6af2c76399f98444a5b4de96baf4b362d9f102b ]
+
+With commit d3119bc985fb645 ("LoongArch: Fix callchain parse error with
+kernel tracepoint events"), perf can parse kernel callchain, but not
+complete and sometimes maybe error. The reason is LoongArch's unwinders
+(guess, prologue and orc) don't really need fp (i.e., regs[22]), and
+they use sp (i.e., regs[3]) as the frame address rather than the current
+stack pointer.
+
+Fix that by removing the assignment of regs[22], and instead assign the
+__builtin_frame_address(0) to regs[3].
+
+Without fix:
+
+  Children      Self  Command        Shared Object      Symbol
+  ........  ........  .............  .................  ................
+  33.91%    33.91%    swapper        [kernel.vmlinux]   [k] __schedule
+            |
+            |--33.04%--__schedule
+            |
+             --0.87%--__arch_cpu_idle
+                       __schedule
+
+With this fix:
+
+  Children      Self  Command        Shared Object      Symbol
+  ........  ........  .............  .................  ................
+  31.16%    31.16%    swapper        [kernel.vmlinux]   [k] __schedule
+            |
+            |--20.63%--smpboot_entry
+            |          cpu_startup_entry
+            |          schedule_idle
+            |          __schedule
+            |
+             --10.53%--start_kernel
+                       cpu_startup_entry
+                       schedule_idle
+                       __schedule
+
+Fixes: d3119bc985fb645 ("LoongArch: Fix callchain parse error with kernel tracepoint events")
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/loongarch/include/asm/perf_event.h | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/loongarch/include/asm/perf_event.h b/arch/loongarch/include/asm/perf_event.h
+index 52b638059e40b..f948a0676daf8 100644
+--- a/arch/loongarch/include/asm/perf_event.h
++++ b/arch/loongarch/include/asm/perf_event.h
+@@ -13,8 +13,7 @@
+ #define perf_arch_fetch_caller_regs(regs, __ip) { \
+       (regs)->csr_era = (__ip); \
+-      (regs)->regs[3] = current_stack_pointer; \
+-      (regs)->regs[22] = (unsigned long) __builtin_frame_address(0); \
++      (regs)->regs[3] = (unsigned long) __builtin_frame_address(0); \
+ }
+ #endif /* __LOONGARCH_PERF_EVENT_H__ */
+-- 
+2.43.0
+
diff --git a/queue-6.6/microblaze-remove-early-printk-call-from-cpuinfo-sta.patch b/queue-6.6/microblaze-remove-early-printk-call-from-cpuinfo-sta.patch
new file mode 100644 (file)
index 0000000..3c7d263
--- /dev/null
@@ -0,0 +1,37 @@
+From 37c647c2b4fdd3e1ed48d1e46de675844e6068a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Apr 2024 10:27:21 +0200
+Subject: microblaze: Remove early printk call from cpuinfo-static.c
+
+From: Michal Simek <michal.simek@amd.com>
+
+[ Upstream commit 58d647506c92ccd3cfa0c453c68ddd14f40bf06f ]
+
+Early printk has been removed already that's why also remove calling it.
+Similar change has been done in cpuinfo-pvr-full.c by commit cfbd8d1979af
+("microblaze: Remove early printk setup").
+
+Fixes: 96f0e6fcc9ad ("microblaze: remove redundant early_printk support")
+Signed-off-by: Michal Simek <michal.simek@amd.com>
+Link: https://lore.kernel.org/r/2f10db506be8188fa07b6ec331caca01af1b10f8.1712824039.git.michal.simek@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/microblaze/kernel/cpu/cpuinfo-static.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c
+index 85dbda4a08a81..03da36dc6d9c9 100644
+--- a/arch/microblaze/kernel/cpu/cpuinfo-static.c
++++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c
+@@ -18,7 +18,7 @@ static const char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY;
+ static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER;
+ #define err_printk(x) \
+-      early_printk("ERROR: Microblaze " x "-different for kernel and DTS\n");
++      pr_err("ERROR: Microblaze " x "-different for kernel and DTS\n");
+ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
+ {
+-- 
+2.43.0
+
diff --git a/queue-6.6/microblaze-remove-gcc-flag-for-non-existing-early_pr.patch b/queue-6.6/microblaze-remove-gcc-flag-for-non-existing-early_pr.patch
new file mode 100644 (file)
index 0000000..1e5e65e
--- /dev/null
@@ -0,0 +1,36 @@
+From 8a7b902f8b04317aa6f555320b05ec0681c33291 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Apr 2024 10:21:44 +0200
+Subject: microblaze: Remove gcc flag for non existing early_printk.c file
+
+From: Michal Simek <michal.simek@amd.com>
+
+[ Upstream commit edc66cf0c4164aa3daf6cc55e970bb94383a6a57 ]
+
+early_printk support for removed long time ago but compilation flag for
+ftrace still points to already removed file that's why remove that line
+too.
+
+Fixes: 96f0e6fcc9ad ("microblaze: remove redundant early_printk support")
+Signed-off-by: Michal Simek <michal.simek@amd.com>
+Link: https://lore.kernel.org/r/5493467419cd2510a32854e2807bcd263de981a0.1712823702.git.michal.simek@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/microblaze/kernel/Makefile | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
+index 4393bee64eaf8..85c4d29ef43e9 100644
+--- a/arch/microblaze/kernel/Makefile
++++ b/arch/microblaze/kernel/Makefile
+@@ -7,7 +7,6 @@ ifdef CONFIG_FUNCTION_TRACER
+ # Do not trace early boot code and low level code
+ CFLAGS_REMOVE_timer.o = -pg
+ CFLAGS_REMOVE_intc.o = -pg
+-CFLAGS_REMOVE_early_printk.o = -pg
+ CFLAGS_REMOVE_ftrace.o = -pg
+ CFLAGS_REMOVE_process.o = -pg
+ endif
+-- 
+2.43.0
+
diff --git a/queue-6.6/misc-pvpanic-deduplicate-common-code.patch b/queue-6.6/misc-pvpanic-deduplicate-common-code.patch
new file mode 100644 (file)
index 0000000..9380de3
--- /dev/null
@@ -0,0 +1,328 @@
+From 020cdcbd234bab8e7b0a465342e63e8635f9dd39 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Oct 2023 09:18:27 +0200
+Subject: misc/pvpanic: deduplicate common code
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit c1426d392aebc51da4944d950d89e483e43f6f14 ]
+
+pvpanic-mmio.c and pvpanic-pci.c share a lot of code.
+Refactor it into pvpanic.c where it doesn't have to be kept in sync
+manually and where the core logic can be understood more easily.
+
+No functional change.
+
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Link: https://lore.kernel.org/r/20231011-pvpanic-cleanup-v2-1-4b21d56f779f@weissschuh.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: ee59be35d7a8 ("misc/pvpanic-pci: register attributes via pci_driver")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/pvpanic/pvpanic-mmio.c | 58 +---------------------
+ drivers/misc/pvpanic/pvpanic-pci.c  | 58 +---------------------
+ drivers/misc/pvpanic/pvpanic.c      | 76 ++++++++++++++++++++++++++++-
+ drivers/misc/pvpanic/pvpanic.h      | 10 +---
+ 4 files changed, 80 insertions(+), 122 deletions(-)
+
+diff --git a/drivers/misc/pvpanic/pvpanic-mmio.c b/drivers/misc/pvpanic/pvpanic-mmio.c
+index eb97167c03fb4..9715798acce3d 100644
+--- a/drivers/misc/pvpanic/pvpanic-mmio.c
++++ b/drivers/misc/pvpanic/pvpanic-mmio.c
+@@ -24,52 +24,9 @@ MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
+ MODULE_DESCRIPTION("pvpanic-mmio device driver");
+ MODULE_LICENSE("GPL");
+-static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-      struct pvpanic_instance *pi = dev_get_drvdata(dev);
+-
+-      return sysfs_emit(buf, "%x\n", pi->capability);
+-}
+-static DEVICE_ATTR_RO(capability);
+-
+-static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-      struct pvpanic_instance *pi = dev_get_drvdata(dev);
+-
+-      return sysfs_emit(buf, "%x\n", pi->events);
+-}
+-
+-static ssize_t events_store(struct device *dev, struct device_attribute *attr,
+-                          const char *buf, size_t count)
+-{
+-      struct pvpanic_instance *pi = dev_get_drvdata(dev);
+-      unsigned int tmp;
+-      int err;
+-
+-      err = kstrtouint(buf, 16, &tmp);
+-      if (err)
+-              return err;
+-
+-      if ((tmp & pi->capability) != tmp)
+-              return -EINVAL;
+-
+-      pi->events = tmp;
+-
+-      return count;
+-}
+-static DEVICE_ATTR_RW(events);
+-
+-static struct attribute *pvpanic_mmio_dev_attrs[] = {
+-      &dev_attr_capability.attr,
+-      &dev_attr_events.attr,
+-      NULL
+-};
+-ATTRIBUTE_GROUPS(pvpanic_mmio_dev);
+-
+ static int pvpanic_mmio_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+-      struct pvpanic_instance *pi;
+       struct resource *res;
+       void __iomem *base;
+@@ -92,18 +49,7 @@ static int pvpanic_mmio_probe(struct platform_device *pdev)
+               return -EINVAL;
+       }
+-      pi = devm_kmalloc(dev, sizeof(*pi), GFP_KERNEL);
+-      if (!pi)
+-              return -ENOMEM;
+-
+-      pi->base = base;
+-      pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
+-
+-      /* initialize capability by RDPT */
+-      pi->capability &= ioread8(base);
+-      pi->events = pi->capability;
+-
+-      return devm_pvpanic_probe(dev, pi);
++      return devm_pvpanic_probe(dev, base);
+ }
+ static const struct of_device_id pvpanic_mmio_match[] = {
+@@ -123,7 +69,7 @@ static struct platform_driver pvpanic_mmio_driver = {
+               .name = "pvpanic-mmio",
+               .of_match_table = pvpanic_mmio_match,
+               .acpi_match_table = pvpanic_device_ids,
+-              .dev_groups = pvpanic_mmio_dev_groups,
++              .dev_groups = pvpanic_dev_groups,
+       },
+       .probe = pvpanic_mmio_probe,
+ };
+diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c
+index 07eddb5ea30fa..689af4c28c2a9 100644
+--- a/drivers/misc/pvpanic/pvpanic-pci.c
++++ b/drivers/misc/pvpanic/pvpanic-pci.c
+@@ -22,51 +22,8 @@ MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
+ MODULE_DESCRIPTION("pvpanic device driver");
+ MODULE_LICENSE("GPL");
+-static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-      struct pvpanic_instance *pi = dev_get_drvdata(dev);
+-
+-      return sysfs_emit(buf, "%x\n", pi->capability);
+-}
+-static DEVICE_ATTR_RO(capability);
+-
+-static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-      struct pvpanic_instance *pi = dev_get_drvdata(dev);
+-
+-      return sysfs_emit(buf, "%x\n", pi->events);
+-}
+-
+-static ssize_t events_store(struct device *dev, struct device_attribute *attr,
+-                          const char *buf, size_t count)
+-{
+-      struct pvpanic_instance *pi = dev_get_drvdata(dev);
+-      unsigned int tmp;
+-      int err;
+-
+-      err = kstrtouint(buf, 16, &tmp);
+-      if (err)
+-              return err;
+-
+-      if ((tmp & pi->capability) != tmp)
+-              return -EINVAL;
+-
+-      pi->events = tmp;
+-
+-      return count;
+-}
+-static DEVICE_ATTR_RW(events);
+-
+-static struct attribute *pvpanic_pci_dev_attrs[] = {
+-      &dev_attr_capability.attr,
+-      &dev_attr_events.attr,
+-      NULL
+-};
+-ATTRIBUTE_GROUPS(pvpanic_pci_dev);
+-
+ static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+-      struct pvpanic_instance *pi;
+       void __iomem *base;
+       int ret;
+@@ -78,18 +35,7 @@ static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+       if (!base)
+               return -ENOMEM;
+-      pi = devm_kmalloc(&pdev->dev, sizeof(*pi), GFP_KERNEL);
+-      if (!pi)
+-              return -ENOMEM;
+-
+-      pi->base = base;
+-      pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
+-
+-      /* initlize capability by RDPT */
+-      pi->capability &= ioread8(base);
+-      pi->events = pi->capability;
+-
+-      return devm_pvpanic_probe(&pdev->dev, pi);
++      return devm_pvpanic_probe(&pdev->dev, base);
+ }
+ static const struct pci_device_id pvpanic_pci_id_tbl[]  = {
+@@ -103,7 +49,7 @@ static struct pci_driver pvpanic_pci_driver = {
+       .id_table =     pvpanic_pci_id_tbl,
+       .probe =        pvpanic_pci_probe,
+       .driver = {
+-              .dev_groups = pvpanic_pci_dev_groups,
++              .dev_groups = pvpanic_dev_groups,
+       },
+ };
+ module_pci_driver(pvpanic_pci_driver);
+diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c
+index 049a120063489..305b367e0ce34 100644
+--- a/drivers/misc/pvpanic/pvpanic.c
++++ b/drivers/misc/pvpanic/pvpanic.c
+@@ -7,6 +7,7 @@
+  *  Copyright (C) 2021 Oracle.
+  */
++#include <linux/device.h>
+ #include <linux/io.h>
+ #include <linux/kernel.h>
+ #include <linux/kexec.h>
+@@ -26,6 +27,13 @@ MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
+ MODULE_DESCRIPTION("pvpanic device driver");
+ MODULE_LICENSE("GPL");
++struct pvpanic_instance {
++      void __iomem *base;
++      unsigned int capability;
++      unsigned int events;
++      struct list_head list;
++};
++
+ static struct list_head pvpanic_list;
+ static spinlock_t pvpanic_lock;
+@@ -81,11 +89,75 @@ static void pvpanic_remove(void *param)
+       spin_unlock(&pvpanic_lock);
+ }
+-int devm_pvpanic_probe(struct device *dev, struct pvpanic_instance *pi)
++static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct pvpanic_instance *pi = dev_get_drvdata(dev);
++
++      return sysfs_emit(buf, "%x\n", pi->capability);
++}
++static DEVICE_ATTR_RO(capability);
++
++static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct pvpanic_instance *pi = dev_get_drvdata(dev);
++
++      return sysfs_emit(buf, "%x\n", pi->events);
++}
++
++static ssize_t events_store(struct device *dev, struct device_attribute *attr,
++                          const char *buf, size_t count)
++{
++      struct pvpanic_instance *pi = dev_get_drvdata(dev);
++      unsigned int tmp;
++      int err;
++
++      err = kstrtouint(buf, 16, &tmp);
++      if (err)
++              return err;
++
++      if ((tmp & pi->capability) != tmp)
++              return -EINVAL;
++
++      pi->events = tmp;
++
++      return count;
++}
++static DEVICE_ATTR_RW(events);
++
++static struct attribute *pvpanic_dev_attrs[] = {
++      &dev_attr_capability.attr,
++      &dev_attr_events.attr,
++      NULL
++};
++
++static const struct attribute_group pvpanic_dev_group = {
++      .attrs = pvpanic_dev_attrs,
++};
++
++const struct attribute_group *pvpanic_dev_groups[] = {
++      &pvpanic_dev_group,
++      NULL
++};
++EXPORT_SYMBOL_GPL(pvpanic_dev_groups);
++
++int devm_pvpanic_probe(struct device *dev, void __iomem *base)
+ {
+-      if (!pi || !pi->base)
++      struct pvpanic_instance *pi;
++
++      if (!base)
+               return -EINVAL;
++      pi = devm_kmalloc(dev, sizeof(*pi), GFP_KERNEL);
++      if (!pi)
++              return -ENOMEM;
++
++      pi->base = base;
++      pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
++
++      /* initlize capability by RDPT */
++      pi->capability &= ioread8(base);
++      pi->events = pi->capability;
++
+       spin_lock(&pvpanic_lock);
+       list_add(&pi->list, &pvpanic_list);
+       spin_unlock(&pvpanic_lock);
+diff --git a/drivers/misc/pvpanic/pvpanic.h b/drivers/misc/pvpanic/pvpanic.h
+index 4935459517548..46ffb10438adf 100644
+--- a/drivers/misc/pvpanic/pvpanic.h
++++ b/drivers/misc/pvpanic/pvpanic.h
+@@ -8,13 +8,7 @@
+ #ifndef PVPANIC_H_
+ #define PVPANIC_H_
+-struct pvpanic_instance {
+-      void __iomem *base;
+-      unsigned int capability;
+-      unsigned int events;
+-      struct list_head list;
+-};
+-
+-int devm_pvpanic_probe(struct device *dev, struct pvpanic_instance *pi);
++int devm_pvpanic_probe(struct device *dev, void __iomem *base);
++extern const struct attribute_group *pvpanic_dev_groups[];
+ #endif /* PVPANIC_H_ */
+-- 
+2.43.0
+
diff --git a/queue-6.6/misc-pvpanic-pci-register-attributes-via-pci_driver.patch b/queue-6.6/misc-pvpanic-pci-register-attributes-via-pci_driver.patch
new file mode 100644 (file)
index 0000000..bb2cda1
--- /dev/null
@@ -0,0 +1,48 @@
+From 5e4eee9befaab077cf4ff5aa091dc21e7c5f9f6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Apr 2024 23:33:51 +0200
+Subject: misc/pvpanic-pci: register attributes via pci_driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit ee59be35d7a8be7fcaa2d61fb89734ab5c25e4ee ]
+
+In __pci_register_driver(), the pci core overwrites the dev_groups field of
+the embedded struct device_driver with the dev_groups from the outer
+struct pci_driver unconditionally.
+
+Set dev_groups in the pci_driver to make sure it is used.
+
+This was broken since the introduction of pvpanic-pci.
+
+Fixes: db3a4f0abefd ("misc/pvpanic: add PCI driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Fixes: ded13b9cfd59 ("PCI: Add support for dev_groups to struct pci_driver")
+Link: https://lore.kernel.org/r/20240411-pvpanic-pci-dev-groups-v1-1-db8cb69f1b09@weissschuh.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/pvpanic/pvpanic-pci.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c
+index 689af4c28c2a9..2494725dfacfa 100644
+--- a/drivers/misc/pvpanic/pvpanic-pci.c
++++ b/drivers/misc/pvpanic/pvpanic-pci.c
+@@ -48,8 +48,6 @@ static struct pci_driver pvpanic_pci_driver = {
+       .name =         "pvpanic-pci",
+       .id_table =     pvpanic_pci_id_tbl,
+       .probe =        pvpanic_pci_probe,
+-      .driver = {
+-              .dev_groups = pvpanic_dev_groups,
+-      },
++      .dev_groups =   pvpanic_dev_groups,
+ };
+ module_pci_driver(pvpanic_pci_driver);
+-- 
+2.43.0
+
diff --git a/queue-6.6/module-don-t-ignore-sysfs_create_link-failures.patch b/queue-6.6/module-don-t-ignore-sysfs_create_link-failures.patch
new file mode 100644 (file)
index 0000000..5e31bd0
--- /dev/null
@@ -0,0 +1,155 @@
+From aaef27c7eded764bf04dab56a3508f9d21caa6b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Apr 2024 10:05:58 +0200
+Subject: module: don't ignore sysfs_create_link() failures
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 85d2b0aa170351380be39fe4ff7973df1427fe76 ]
+
+The sysfs_create_link() return code is marked as __must_check, but the
+module_add_driver() function tries hard to not care, by assigning the
+return code to a variable. When building with 'make W=1', gcc still
+warns because this variable is only assigned but not used:
+
+drivers/base/module.c: In function 'module_add_driver':
+drivers/base/module.c:36:6: warning: variable 'no_warn' set but not used [-Wunused-but-set-variable]
+
+Rework the code to properly unwind and return the error code to the
+caller. My reading of the original code was that it tries to
+not fail when the links already exist, so keep ignoring -EEXIST
+errors.
+
+Fixes: e17e0f51aeea ("Driver core: show drivers in /sys/module/")
+See-also: 4a7fb6363f2d ("add __must_check to device management code")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
+Link: https://lore.kernel.org/r/20240408080616.3911573-1-arnd@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/base.h   |  9 ++++++---
+ drivers/base/bus.c    |  9 ++++++++-
+ drivers/base/module.c | 42 +++++++++++++++++++++++++++++++-----------
+ 3 files changed, 45 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/base/base.h b/drivers/base/base.h
+index eb4c0ace92420..a8e3d8165232f 100644
+--- a/drivers/base/base.h
++++ b/drivers/base/base.h
+@@ -192,11 +192,14 @@ extern struct kset *devices_kset;
+ void devices_kset_move_last(struct device *dev);
+ #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
+-void module_add_driver(struct module *mod, struct device_driver *drv);
++int module_add_driver(struct module *mod, struct device_driver *drv);
+ void module_remove_driver(struct device_driver *drv);
+ #else
+-static inline void module_add_driver(struct module *mod,
+-                                   struct device_driver *drv) { }
++static inline int module_add_driver(struct module *mod,
++                                  struct device_driver *drv)
++{
++      return 0;
++}
+ static inline void module_remove_driver(struct device_driver *drv) { }
+ #endif
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index 84a21084d67d1..d7c4330786cae 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -674,7 +674,12 @@ int bus_add_driver(struct device_driver *drv)
+               if (error)
+                       goto out_del_list;
+       }
+-      module_add_driver(drv->owner, drv);
++      error = module_add_driver(drv->owner, drv);
++      if (error) {
++              printk(KERN_ERR "%s: failed to create module links for %s\n",
++                      __func__, drv->name);
++              goto out_detach;
++      }
+       error = driver_create_file(drv, &driver_attr_uevent);
+       if (error) {
+@@ -699,6 +704,8 @@ int bus_add_driver(struct device_driver *drv)
+       return 0;
++out_detach:
++      driver_detach(drv);
+ out_del_list:
+       klist_del(&priv->knode_bus);
+ out_unregister:
+diff --git a/drivers/base/module.c b/drivers/base/module.c
+index 46ad4d636731d..a1b55da07127d 100644
+--- a/drivers/base/module.c
++++ b/drivers/base/module.c
+@@ -30,14 +30,14 @@ static void module_create_drivers_dir(struct module_kobject *mk)
+       mutex_unlock(&drivers_dir_mutex);
+ }
+-void module_add_driver(struct module *mod, struct device_driver *drv)
++int module_add_driver(struct module *mod, struct device_driver *drv)
+ {
+       char *driver_name;
+-      int no_warn;
+       struct module_kobject *mk = NULL;
++      int ret;
+       if (!drv)
+-              return;
++              return 0;
+       if (mod)
+               mk = &mod->mkobj;
+@@ -56,17 +56,37 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
+       }
+       if (!mk)
+-              return;
++              return 0;
++
++      ret = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
++      if (ret)
++              return ret;
+-      /* Don't check return codes; these calls are idempotent */
+-      no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
+       driver_name = make_driver_name(drv);
+-      if (driver_name) {
+-              module_create_drivers_dir(mk);
+-              no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj,
+-                                          driver_name);
+-              kfree(driver_name);
++      if (!driver_name) {
++              ret = -ENOMEM;
++              goto out;
++      }
++
++      module_create_drivers_dir(mk);
++      if (!mk->drivers_dir) {
++              ret = -EINVAL;
++              goto out;
+       }
++
++      ret = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, driver_name);
++      if (ret)
++              goto out;
++
++      kfree(driver_name);
++
++      return 0;
++out:
++      sysfs_remove_link(&drv->p->kobj, "module");
++      sysfs_remove_link(mk->drivers_dir, driver_name);
++      kfree(driver_name);
++
++      return ret;
+ }
+ void module_remove_driver(struct device_driver *drv)
+-- 
+2.43.0
+
diff --git a/queue-6.6/ovl-add-helper-ovl_file_modified.patch b/queue-6.6/ovl-add-helper-ovl_file_modified.patch
new file mode 100644 (file)
index 0000000..df655ce
--- /dev/null
@@ -0,0 +1,87 @@
+From f87db32c0cdadc7eea4a37560867da0bd0bb87e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Sep 2023 13:43:44 +0300
+Subject: ovl: add helper ovl_file_modified()
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+[ Upstream commit c002728f608183449673818076380124935e6b9b ]
+
+A simple wrapper for updating ovl inode size/mtime, to conform
+with ovl_file_accessed().
+
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Stable-dep-of: 7c98f7cb8fda ("remove call_{read,write}_iter() functions")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/file.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
+index 8be4dc050d1ed..9fd88579bfbfb 100644
+--- a/fs/overlayfs/file.c
++++ b/fs/overlayfs/file.c
+@@ -235,6 +235,12 @@ static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)
+       return ret;
+ }
++static void ovl_file_modified(struct file *file)
++{
++      /* Update size/mtime */
++      ovl_copyattr(file_inode(file));
++}
++
+ static void ovl_file_accessed(struct file *file)
+ {
+       struct inode *inode, *upperinode;
+@@ -290,10 +296,8 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req)
+       struct kiocb *orig_iocb = aio_req->orig_iocb;
+       if (iocb->ki_flags & IOCB_WRITE) {
+-              struct inode *inode = file_inode(orig_iocb->ki_filp);
+-
+               kiocb_end_write(iocb);
+-              ovl_copyattr(inode);
++              ovl_file_modified(orig_iocb->ki_filp);
+       }
+       orig_iocb->ki_pos = iocb->ki_pos;
+@@ -403,7 +407,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
+                                    ovl_iocb_to_rwf(ifl));
+               file_end_write(real.file);
+               /* Update size */
+-              ovl_copyattr(inode);
++              ovl_file_modified(file);
+       } else {
+               struct ovl_aio_req *aio_req;
+@@ -489,7 +493,7 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
+       file_end_write(real.file);
+       /* Update size */
+-      ovl_copyattr(inode);
++      ovl_file_modified(out);
+       revert_creds(old_cred);
+       fdput(real);
+@@ -570,7 +574,7 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len
+       revert_creds(old_cred);
+       /* Update size */
+-      ovl_copyattr(inode);
++      ovl_file_modified(file);
+       fdput(real);
+@@ -654,7 +658,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
+       revert_creds(old_cred);
+       /* Update size */
+-      ovl_copyattr(inode_out);
++      ovl_file_modified(file_out);
+       fdput(real_in);
+       fdput(real_out);
+-- 
+2.43.0
+
diff --git a/queue-6.6/ovl-remove-upper-umask-handling-from-ovl_create_uppe.patch b/queue-6.6/ovl-remove-upper-umask-handling-from-ovl_create_uppe.patch
new file mode 100644 (file)
index 0000000..bfa011c
--- /dev/null
@@ -0,0 +1,39 @@
+From eefabf053819ee36e788a325c1d982817e0aa7e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 May 2024 20:35:57 +0200
+Subject: ovl: remove upper umask handling from ovl_create_upper()
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+[ Upstream commit 096802748ea1dea8b476938e0a8dc16f4bd2f1ad ]
+
+This is already done by vfs_prepare_mode() when creating the upper object
+by vfs_create(), vfs_mkdir() and vfs_mknod().
+
+No regressions have been observed in xfstests run with posix acls turned
+off for the upper filesystem.
+
+Fixes: 1639a49ccdce ("fs: move S_ISGID stripping into the vfs_*() helpers")
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/dir.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
+index 033fc0458a3d8..54602f0bed8be 100644
+--- a/fs/overlayfs/dir.c
++++ b/fs/overlayfs/dir.c
+@@ -327,9 +327,6 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
+       struct dentry *newdentry;
+       int err;
+-      if (!attr->hardlink && !IS_POSIXACL(udir))
+-              attr->mode &= ~current_umask();
+-
+       inode_lock_nested(udir, I_MUTEX_PARENT);
+       newdentry = ovl_create_real(ofs, udir,
+                                   ovl_lookup_upper(ofs, dentry->d_name.name,
+-- 
+2.43.0
+
diff --git a/queue-6.6/pci-edr-align-edr_port_dpc_enable_dsm-with-pci-firmw.patch b/queue-6.6/pci-edr-align-edr_port_dpc_enable_dsm-with-pci-firmw.patch
new file mode 100644 (file)
index 0000000..e934fe4
--- /dev/null
@@ -0,0 +1,71 @@
+From 32d945bc6b46b361b7c9d212a97d44651a503d6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 May 2024 02:25:43 +0000
+Subject: PCI/EDR: Align EDR_PORT_DPC_ENABLE_DSM with PCI Firmware r3.3
+
+From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+
+[ Upstream commit f24ba846133d0edec785ac6430d4daf6e9c93a09 ]
+
+The "Downstream Port Containment related Enhancements" ECN of Jan 28, 2019
+(document 12888 below), defined the EDR_PORT_DPC_ENABLE_DSM function with
+Revision ID 5 with Arg3 being an integer.  But when the ECN was integrated
+into PCI Firmware r3.3, sec 4.6.12, it was defined as Revision ID 6 with
+Arg3 being a package containing an integer.
+
+The implementation in acpi_enable_dpc() supplies a package as Arg3 (arg4 in
+the code), but it previously specified Revision ID 5.  Align this with PCI
+Firmware r3.3 by using Revision ID 6.
+
+If firmware implemented per the ECN, its Revision 5 function would receive
+a package as Arg3 when it expects an integer, so acpi_enable_dpc() would
+likely fail.  If such firmware exists and lacks a Revision 6 function that
+expects a package, we may have to add support for Revision 5.
+
+Link: https://lore.kernel.org/r/20240501022543.1626025-1-sathyanarayanan.kuppuswamy@linux.intel.com
+Link: https://members.pcisig.com/wg/PCI-SIG/document/12888
+Fixes: ac1c8e35a326 ("PCI/DPC: Add Error Disconnect Recover (EDR) support")
+Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+[bhelgaas: split into two patches, update commit log]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Tested-by: Satish Thatchanamurthy <Satish.Thatchanamurt@Dell.com> # one platform
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/edr.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/pci/pcie/edr.c b/drivers/pci/pcie/edr.c
+index 5f4914d313a17..fa085677c91de 100644
+--- a/drivers/pci/pcie/edr.c
++++ b/drivers/pci/pcie/edr.c
+@@ -32,10 +32,10 @@ static int acpi_enable_dpc(struct pci_dev *pdev)
+       int status = 0;
+       /*
+-       * Behavior when calling unsupported _DSM functions is undefined,
+-       * so check whether EDR_PORT_DPC_ENABLE_DSM is supported.
++       * Per PCI Firmware r3.3, sec 4.6.12, EDR_PORT_DPC_ENABLE_DSM is
++       * optional. Return success if it's not implemented.
+        */
+-      if (!acpi_check_dsm(adev->handle, &pci_acpi_dsm_guid, 5,
++      if (!acpi_check_dsm(adev->handle, &pci_acpi_dsm_guid, 6,
+                           1ULL << EDR_PORT_DPC_ENABLE_DSM))
+               return 0;
+@@ -46,12 +46,7 @@ static int acpi_enable_dpc(struct pci_dev *pdev)
+       argv4.package.count = 1;
+       argv4.package.elements = &req;
+-      /*
+-       * Per Downstream Port Containment Related Enhancements ECN to PCI
+-       * Firmware Specification r3.2, sec 4.6.12, EDR_PORT_DPC_ENABLE_DSM is
+-       * optional.  Return success if it's not implemented.
+-       */
+-      obj = acpi_evaluate_dsm(adev->handle, &pci_acpi_dsm_guid, 5,
++      obj = acpi_evaluate_dsm(adev->handle, &pci_acpi_dsm_guid, 6,
+                               EDR_PORT_DPC_ENABLE_DSM, &argv4);
+       if (!obj)
+               return 0;
+-- 
+2.43.0
+
diff --git a/queue-6.6/pci-edr-align-edr_port_locate_dsm-with-pci-firmware-.patch b/queue-6.6/pci-edr-align-edr_port_locate_dsm-with-pci-firmware-.patch
new file mode 100644 (file)
index 0000000..82d04b1
--- /dev/null
@@ -0,0 +1,65 @@
+From a3b0fd0fe41d303ae61c2450c399947f61ef3434 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 May 2024 14:31:38 -0500
+Subject: PCI/EDR: Align EDR_PORT_LOCATE_DSM with PCI Firmware r3.3
+
+From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+
+[ Upstream commit e2e78a294a8a863898b781dbcf90e087eda3155d ]
+
+The "Downstream Port Containment related Enhancements" ECN of Jan 28, 2019
+(document 12888 below), defined the EDR_PORT_LOCATE_DSM function with
+Revision ID 5 with a return value encoding (Bits 2:0 = Function, Bits 7:3 =
+Device, Bits 15:8 = Bus).  When the ECN was integrated into PCI Firmware
+r3.3, sec 4.6.13, Bit 31 was added to indicate success or failure.
+
+Check Bit 31 for failure in acpi_dpc_port_get().
+
+Link: https://lore.kernel.org/r/20240501022543.1626025-1-sathyanarayanan.kuppuswamy@linux.intel.com
+Link: https://members.pcisig.com/wg/PCI-SIG/document/12888
+Fixes: ac1c8e35a326 ("PCI/DPC: Add Error Disconnect Recover (EDR) support")
+Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+[bhelgaas: split into two patches, update commit log]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Tested-by: Satish Thatchanamurthy <Satish.Thatchanamurt@Dell.com> # one platform
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/edr.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/pcie/edr.c b/drivers/pci/pcie/edr.c
+index fa085677c91de..e86298dbbcff6 100644
+--- a/drivers/pci/pcie/edr.c
++++ b/drivers/pci/pcie/edr.c
+@@ -80,8 +80,9 @@ static struct pci_dev *acpi_dpc_port_get(struct pci_dev *pdev)
+       u16 port;
+       /*
+-       * Behavior when calling unsupported _DSM functions is undefined,
+-       * so check whether EDR_PORT_DPC_ENABLE_DSM is supported.
++       * If EDR_PORT_LOCATE_DSM is not implemented under the target of
++       * EDR, the target is the port that experienced the containment
++       * event (PCI Firmware r3.3, sec 4.6.13).
+        */
+       if (!acpi_check_dsm(adev->handle, &pci_acpi_dsm_guid, 5,
+                           1ULL << EDR_PORT_LOCATE_DSM))
+@@ -98,6 +99,16 @@ static struct pci_dev *acpi_dpc_port_get(struct pci_dev *pdev)
+               return NULL;
+       }
++      /*
++       * Bit 31 represents the success/failure of the operation. If bit
++       * 31 is set, the operation failed.
++       */
++      if (obj->integer.value & BIT(31)) {
++              ACPI_FREE(obj);
++              pci_err(pdev, "Locate Port _DSM failed\n");
++              return NULL;
++      }
++
+       /*
+        * Firmware returns DPC port BDF details in following format:
+        *      15:8 = bus
+-- 
+2.43.0
+
diff --git a/queue-6.6/pci-of_property-return-error-for-int_map-allocation-.patch b/queue-6.6/pci-of_property-return-error-for-int_map-allocation-.patch
new file mode 100644 (file)
index 0000000..0eed8f0
--- /dev/null
@@ -0,0 +1,38 @@
+From 67d99de2108ef99e2096314e41ed275613abe845 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 Mar 2024 18:57:29 +0800
+Subject: PCI: of_property: Return error for int_map allocation failure
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+[ Upstream commit e6f7d27df5d208b50cae817a91d128fb434bb12c ]
+
+Return -ENOMEM from of_pci_prop_intr_map() if kcalloc() fails to prevent a
+NULL pointer dereference in this case.
+
+Fixes: 407d1a51921e ("PCI: Create device tree node for bridge")
+Link: https://lore.kernel.org/r/20240303105729.78624-1-duoming@zju.edu.cn
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+[bhelgaas: commit log]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/of_property.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/pci/of_property.c b/drivers/pci/of_property.c
+index c2c7334152bc0..03539e5053720 100644
+--- a/drivers/pci/of_property.c
++++ b/drivers/pci/of_property.c
+@@ -238,6 +238,8 @@ static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs,
+               return 0;
+       int_map = kcalloc(map_sz, sizeof(u32), GFP_KERNEL);
++      if (!int_map)
++              return -ENOMEM;
+       mapp = int_map;
+       list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/pci-tegra194-fix-probe-path-for-endpoint-mode.patch b/queue-6.6/pci-tegra194-fix-probe-path-for-endpoint-mode.patch
new file mode 100644 (file)
index 0000000..ab1e7e3
--- /dev/null
@@ -0,0 +1,48 @@
+From 14163ded942d908a806818b9b180bc822fc4cb70 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Apr 2024 15:00:53 +0530
+Subject: PCI: tegra194: Fix probe path for Endpoint mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Vidya Sagar <vidyas@nvidia.com>
+
+[ Upstream commit 19326006a21da26532d982254677c892dae8f29b ]
+
+Tegra194 PCIe probe path is taking failure path in success case for
+Endpoint mode. Return success from the switch case instead of going
+into the failure path.
+
+Fixes: c57247f940e8 ("PCI: tegra: Add support for PCIe endpoint mode in Tegra194")
+Link: https://lore.kernel.org/linux-pci/20240408093053.3948634-1-vidyas@nvidia.com
+Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-tegra194.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
+index 248cd9347e8fd..416d6b45d1fe8 100644
+--- a/drivers/pci/controller/dwc/pcie-tegra194.c
++++ b/drivers/pci/controller/dwc/pcie-tegra194.c
+@@ -2272,11 +2272,14 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev)
+               ret = tegra_pcie_config_ep(pcie, pdev);
+               if (ret < 0)
+                       goto fail;
++              else
++                      return 0;
+               break;
+       default:
+               dev_err(dev, "Invalid PCIe device type %d\n",
+                       pcie->of_data->mode);
++              ret = -EINVAL;
+       }
+ fail:
+-- 
+2.43.0
+
diff --git a/queue-6.6/pci-wait-for-link-training-0-before-starting-link-re.patch b/queue-6.6/pci-wait-for-link-training-0-before-starting-link-re.patch
new file mode 100644 (file)
index 0000000..4f4efae
--- /dev/null
@@ -0,0 +1,82 @@
+From 07faec99bd306a67ff17c8013d46e0d1da15ab88 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Apr 2024 16:08:19 +0300
+Subject: PCI: Wait for Link Training==0 before starting Link retrain
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+
+[ Upstream commit 73cb3a35f94db723c0211ad099bce55b2155e3f0 ]
+
+Two changes were made in link retraining logic independent of each other.
+
+The commit e7e39756363a ("PCI/ASPM: Avoid link retraining race") added a
+check to pcie_retrain_link() to ensure no Link Training is currently active
+to address the Implementation Note in PCIe r6.1 sec 7.5.3.7. At that time
+pcie_wait_for_retrain() only checked for the Link Training (LT) bit being
+cleared.
+
+The commit 680e9c47a229 ("PCI: Add support for polling DLLLA to
+pcie_retrain_link()") generalized pcie_wait_for_retrain() into
+pcie_wait_for_link_status() which can wait either for LT or the Data Link
+Layer Link Active (DLLLA) bit with 'use_lt' argument and supporting waiting
+for either cleared or set using 'active' argument.
+
+In the merge commit 1abb47390350 ("Merge branch 'pci/enumeration'"), those
+two divergent branches converged. The merge changed LT bit checking added
+in the commit e7e39756363a ("PCI/ASPM: Avoid link retraining race") to now
+wait for completion of any ongoing Link Training using DLLLA bit being set
+if 'use_lt' is false.
+
+When 'use_lt' is false, the pseudo-code steps of what occurs in
+pcie_retrain_link():
+
+       1. Wait for DLLLA==1
+       2. Trigger link to retrain
+       3. Wait for DLLLA==1
+
+Step 3 waits for the link to come up from the retraining triggered by Step
+2. As Step 1 is supposed to wait for any ongoing retraining to end, using
+DLLLA also for it does not make sense because link training being active is
+still indicated using LT bit, not with DLLLA.
+
+Correct the pcie_wait_for_link_status() parameters in Step 1 to only wait
+for LT==0 to ensure there is no ongoing Link Training.
+
+This only impacts the Target Speed quirk, which is the only case where
+waiting for DLLLA bit is used. It currently works in the problematic case
+by means of link training getting initiated by hardware repeatedly and
+respecting the new link parameters set by the caller, which then make
+training succeed and bring the link up, setting DLLLA and causing
+pcie_wait_for_link_status() to return success. We are not supposed to rely
+on luck and need to make sure that LT transitioned through the inactive
+state though before we initiate link training by hand via RL (Retrain Link)
+bit.
+
+Fixes: 1abb47390350 ("Merge branch 'pci/enumeration'")
+Link: https://lore.kernel.org/r/20240423130820.43824-1-ilpo.jarvinen@linux.intel.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index dddd30deea32b..6ea01007031a4 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -4986,7 +4986,7 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt)
+        * avoid LTSSM race as recommended in Implementation Note at the
+        * end of PCIe r6.0.1 sec 7.5.3.7.
+        */
+-      rc = pcie_wait_for_link_status(pdev, use_lt, !use_lt);
++      rc = pcie_wait_for_link_status(pdev, true, false);
+       if (rc)
+               return rc;
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-annotate-fix-annotation_calc_lines-to-pass-corr.patch b/queue-6.6/perf-annotate-fix-annotation_calc_lines-to-pass-corr.patch
new file mode 100644 (file)
index 0000000..632f96b
--- /dev/null
@@ -0,0 +1,81 @@
+From fc445b12febe61f4639b0b5244c87dc66358246a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Apr 2024 10:57:08 -0700
+Subject: perf annotate: Fix annotation_calc_lines() to pass correct address to
+ get_srcline()
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit aaf494cf483a1a835c44e942861429b30a00cab0 ]
+
+It should pass a proper address (i.e. suitable for objdump or addr2line)
+to get_srcline() in order to work correctly.  It used to pass an address
+with map__rip_2objdump() as the second argument but later it's changed
+to use notes->start.  It's ok in normal cases but it can be changed when
+annotate_opts.full_addr is set.  So let's convert the address directly
+instead of using the notes->start.
+
+Also the last argument is an IP to print symbol offset if requested.  So
+it should pass symbol-relative address.
+
+Fixes: 7d18a824b5e57ddd ("perf annotate: Toggle full address <-> offset display")
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240404175716.1225482-2-namhyung@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/annotate.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
+index 5fa4831631140..83da2bceb5959 100644
+--- a/tools/perf/util/annotate.c
++++ b/tools/perf/util/annotate.c
+@@ -2906,7 +2906,7 @@ void annotation__toggle_full_addr(struct annotation *notes, struct map_symbol *m
+       annotation__update_column_widths(notes);
+ }
+-static void annotation__calc_lines(struct annotation *notes, struct map *map,
++static void annotation__calc_lines(struct annotation *notes, struct map_symbol *ms,
+                                  struct rb_root *root)
+ {
+       struct annotation_line *al;
+@@ -2914,6 +2914,7 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
+       list_for_each_entry(al, &notes->src->source, node) {
+               double percent_max = 0.0;
++              u64 addr;
+               int i;
+               for (i = 0; i < al->data_nr; i++) {
+@@ -2929,8 +2930,9 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
+               if (percent_max <= 0.5)
+                       continue;
+-              al->path = get_srcline(map__dso(map), notes->start + al->offset, NULL,
+-                                     false, true, notes->start + al->offset);
++              addr = map__rip_2objdump(ms->map, ms->sym->start);
++              al->path = get_srcline(map__dso(ms->map), addr + al->offset, NULL,
++                                     false, true, ms->sym->start + al->offset);
+               insert_source_line(&tmp_root, al);
+       }
+@@ -2941,7 +2943,7 @@ static void symbol__calc_lines(struct map_symbol *ms, struct rb_root *root)
+ {
+       struct annotation *notes = symbol__annotation(ms->sym);
+-      annotation__calc_lines(notes, ms->map, root);
++      annotation__calc_lines(notes, ms, root);
+ }
+ int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel)
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-annotate-get-rid-of-duplicate-group-option-item.patch b/queue-6.6/perf-annotate-get-rid-of-duplicate-group-option-item.patch
new file mode 100644 (file)
index 0000000..4053f70
--- /dev/null
@@ -0,0 +1,48 @@
+From 138e4f319cb2314e08af03f90b8273f0d1610928 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Mar 2024 15:43:12 -0700
+Subject: perf annotate: Get rid of duplicate --group option item
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit 374af9f1f06b5e991c810d2e4983d6f58df32136 ]
+
+The options array in cmd_annotate() has duplicate --group options.  It
+only needs one and let's get rid of the other.
+
+  $ perf annotate -h 2>&1 | grep group
+        --group           Show event group information together
+        --group           Show event group information together
+
+Fixes: 7ebaf4890f63eb90 ("perf annotate: Support '--group' option")
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jin Yao <yao.jin@linux.intel.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240322224313.423181-1-namhyung@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-annotate.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
+index aeeb801f1ed7b..16757ea9b1a7a 100644
+--- a/tools/perf/builtin-annotate.c
++++ b/tools/perf/builtin-annotate.c
+@@ -589,8 +589,6 @@ int cmd_annotate(int argc, const char **argv)
+                   "Enable symbol demangling"),
+       OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
+                   "Enable kernel symbol demangling"),
+-      OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
+-                  "Show event group information together"),
+       OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
+                   "Show a column with the sum of periods"),
+       OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-annotate-introduce-global-annotation_options.patch b/queue-6.6/perf-annotate-introduce-global-annotation_options.patch
new file mode 100644 (file)
index 0000000..9f7af7e
--- /dev/null
@@ -0,0 +1,210 @@
+From 7ddd424c59b675f91377b763da321eef7ed0ca2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 09:54:34 -0800
+Subject: perf annotate: Introduce global annotation_options
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit 9d03194a36345796d4f0f8d6b72eb770a45d614e ]
+
+The annotation options are to control the behavior of objdump and the
+output.  It's basically used by 'perf annotate' but 'perf report' and
+'perf top' can call it on TUI dynamically.
+
+But it doesn't need to have a copy of annotation options in many places.
+
+As most of the work is done in the util/annotate.c file, add a global
+variable and set/use it instead of having their own copies.
+
+Reviewed-by: Ian Rogers <irogers@google.com>
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20231128175441.721579-2-namhyung@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-annotate.c | 43 +++++++++++++++++------------------
+ tools/perf/util/annotate.c    |  3 +++
+ tools/perf/util/annotate.h    |  2 ++
+ 3 files changed, 26 insertions(+), 22 deletions(-)
+
+diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
+index 16757ea9b1a7a..d3d410cdd9ba5 100644
+--- a/tools/perf/builtin-annotate.c
++++ b/tools/perf/builtin-annotate.c
+@@ -45,7 +45,6 @@
+ struct perf_annotate {
+       struct perf_tool tool;
+       struct perf_session *session;
+-      struct annotation_options opts;
+ #ifdef HAVE_SLANG_SUPPORT
+       bool       use_tui;
+ #endif
+@@ -315,9 +314,9 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
+                                   struct perf_annotate *ann)
+ {
+       if (!ann->use_stdio2)
+-              return symbol__tty_annotate(&he->ms, evsel, &ann->opts);
++              return symbol__tty_annotate(&he->ms, evsel, &annotate_opts);
+-      return symbol__tty_annotate2(&he->ms, evsel, &ann->opts);
++      return symbol__tty_annotate2(&he->ms, evsel, &annotate_opts);
+ }
+ static void hists__find_annotations(struct hists *hists,
+@@ -373,14 +372,14 @@ static void hists__find_annotations(struct hists *hists,
+                               return;
+                       }
+-                      ret = annotate(he, evsel, &ann->opts, NULL);
++                      ret = annotate(he, evsel, &annotate_opts, NULL);
+                       if (!ret || !ann->skip_missing)
+                               return;
+                       /* skip missing symbols */
+                       nd = rb_next(nd);
+               } else if (use_browser == 1) {
+-                      key = hist_entry__tui_annotate(he, evsel, NULL, &ann->opts);
++                      key = hist_entry__tui_annotate(he, evsel, NULL, &annotate_opts);
+                       switch (key) {
+                       case -1:
+@@ -422,9 +421,9 @@ static int __cmd_annotate(struct perf_annotate *ann)
+                       goto out;
+       }
+-      if (!ann->opts.objdump_path) {
++      if (!annotate_opts.objdump_path) {
+               ret = perf_env__lookup_objdump(&session->header.env,
+-                                             &ann->opts.objdump_path);
++                                             &annotate_opts.objdump_path);
+               if (ret)
+                       goto out;
+       }
+@@ -558,9 +557,9 @@ int cmd_annotate(int argc, const char **argv)
+                  "file", "vmlinux pathname"),
+       OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
+                   "load module symbols - WARNING: use only with -k and LIVE kernel"),
+-      OPT_BOOLEAN('l', "print-line", &annotate.opts.print_lines,
++      OPT_BOOLEAN('l', "print-line", &annotate_opts.print_lines,
+                   "print matching source lines (may be slow)"),
+-      OPT_BOOLEAN('P', "full-paths", &annotate.opts.full_path,
++      OPT_BOOLEAN('P', "full-paths", &annotate_opts.full_path,
+                   "Don't shorten the displayed pathnames"),
+       OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
+                   "Skip symbols that cannot be annotated"),
+@@ -571,15 +570,15 @@ int cmd_annotate(int argc, const char **argv)
+       OPT_CALLBACK(0, "symfs", NULL, "directory",
+                    "Look for files with symbols relative to this directory",
+                    symbol__config_symfs),
+-      OPT_BOOLEAN(0, "source", &annotate.opts.annotate_src,
++      OPT_BOOLEAN(0, "source", &annotate_opts.annotate_src,
+                   "Interleave source code with assembly code (default)"),
+-      OPT_BOOLEAN(0, "asm-raw", &annotate.opts.show_asm_raw,
++      OPT_BOOLEAN(0, "asm-raw", &annotate_opts.show_asm_raw,
+                   "Display raw encoding of assembly instructions (default)"),
+       OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
+                  "Specify disassembler style (e.g. -M intel for intel syntax)"),
+-      OPT_STRING(0, "prefix", &annotate.opts.prefix, "prefix",
++      OPT_STRING(0, "prefix", &annotate_opts.prefix, "prefix",
+                   "Add prefix to source file path names in programs (with --prefix-strip)"),
+-      OPT_STRING(0, "prefix-strip", &annotate.opts.prefix_strip, "N",
++      OPT_STRING(0, "prefix-strip", &annotate_opts.prefix_strip, "N",
+                   "Strip first N entries of source file path name in programs (with --prefix)"),
+       OPT_STRING(0, "objdump", &objdump_path, "path",
+                  "objdump binary to use for disassembly and annotations"),
+@@ -596,7 +595,7 @@ int cmd_annotate(int argc, const char **argv)
+       OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
+                            "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
+                            stdio__config_color, "always"),
+-      OPT_CALLBACK(0, "percent-type", &annotate.opts, "local-period",
++      OPT_CALLBACK(0, "percent-type", &annotate_opts, "local-period",
+                    "Set percent type local/global-period/hits",
+                    annotate_parse_percent_type),
+       OPT_CALLBACK(0, "percent-limit", &annotate, "percent",
+@@ -612,13 +611,13 @@ int cmd_annotate(int argc, const char **argv)
+       set_option_flag(options, 0, "show-total-period", PARSE_OPT_EXCLUSIVE);
+       set_option_flag(options, 0, "show-nr-samples", PARSE_OPT_EXCLUSIVE);
+-      annotation_options__init(&annotate.opts);
++      annotation_options__init(&annotate_opts);
+       ret = hists__init();
+       if (ret < 0)
+               return ret;
+-      annotation_config__init(&annotate.opts);
++      annotation_config__init(&annotate_opts);
+       argc = parse_options(argc, argv, options, annotate_usage, 0);
+       if (argc) {
+@@ -633,13 +632,13 @@ int cmd_annotate(int argc, const char **argv)
+       }
+       if (disassembler_style) {
+-              annotate.opts.disassembler_style = strdup(disassembler_style);
+-              if (!annotate.opts.disassembler_style)
++              annotate_opts.disassembler_style = strdup(disassembler_style);
++              if (!annotate_opts.disassembler_style)
+                       return -ENOMEM;
+       }
+       if (objdump_path) {
+-              annotate.opts.objdump_path = strdup(objdump_path);
+-              if (!annotate.opts.objdump_path)
++              annotate_opts.objdump_path = strdup(objdump_path);
++              if (!annotate_opts.objdump_path)
+                       return -ENOMEM;
+       }
+       if (addr2line_path) {
+@@ -648,7 +647,7 @@ int cmd_annotate(int argc, const char **argv)
+                       return -ENOMEM;
+       }
+-      if (annotate_check_args(&annotate.opts) < 0)
++      if (annotate_check_args(&annotate_opts) < 0)
+               return -EINVAL;
+ #ifdef HAVE_GTK2_SUPPORT
+@@ -729,7 +728,7 @@ int cmd_annotate(int argc, const char **argv)
+ #ifndef NDEBUG
+       perf_session__delete(annotate.session);
+ #endif
+-      annotation_options__exit(&annotate.opts);
++      annotation_options__exit(&annotate_opts);
+       return ret;
+ }
+diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
+index 99ff3bb9cad8d..2a22bd30a98b7 100644
+--- a/tools/perf/util/annotate.c
++++ b/tools/perf/util/annotate.c
+@@ -57,6 +57,9 @@
+ #include <linux/ctype.h>
++/* global annotation options */
++struct annotation_options annotate_opts;
++
+ static regex_t         file_lineno;
+ static struct ins_ops *ins__find(struct arch *arch, const char *name);
+diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
+index 19bc2f0391757..d45a777f7229b 100644
+--- a/tools/perf/util/annotate.h
++++ b/tools/perf/util/annotate.h
+@@ -101,6 +101,8 @@ struct annotation_options {
+       unsigned int percent_type;
+ };
++extern struct annotation_options annotate_opts;
++
+ enum {
+       ANNOTATION__OFFSET_JUMP_TARGETS = 1,
+       ANNOTATION__OFFSET_CALL,
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-annotate-split-branch-stack-cycles-information-.patch b/queue-6.6/perf-annotate-split-branch-stack-cycles-information-.patch
new file mode 100644 (file)
index 0000000..3b20541
--- /dev/null
@@ -0,0 +1,234 @@
+From b2dcf23780b6179d0eb4bfbb4dfd8bc4ca199826 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Nov 2023 12:19:03 -0700
+Subject: perf annotate: Split branch stack cycles information out of 'struct
+ annotation_line'
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit de2c7eb59c342d1a61124caaf2993e325a9becb7 ]
+
+The cycles info is used only when branch stack is provided.  Separate
+them from 'struct annotation_line' into a separate struct and lazy
+allocate them to save some memory.
+
+Committer notes:
+
+Make annotation__compute_ipc() check if the lazy allocation works,
+bailing out if so, its callers already do error checking and
+propagation.
+
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20231103191907.54531-2-namhyung@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/ui/browsers/annotate.c |  2 +-
+ tools/perf/util/annotate.c        | 61 ++++++++++++++++++++++---------
+ tools/perf/util/annotate.h        | 15 +++++---
+ 3 files changed, 54 insertions(+), 24 deletions(-)
+
+diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
+index ccdb2cd11fbf0..d2470f87344d0 100644
+--- a/tools/perf/ui/browsers/annotate.c
++++ b/tools/perf/ui/browsers/annotate.c
+@@ -337,7 +337,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
+                               max_percent = percent;
+               }
+-              if (max_percent < 0.01 && pos->al.ipc == 0) {
++              if (max_percent < 0.01 && (!pos->al.cycles || pos->al.cycles->ipc == 0)) {
+                       RB_CLEAR_NODE(&pos->al.rb_node);
+                       continue;
+               }
+diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
+index 82956adf99632..99ff3bb9cad8d 100644
+--- a/tools/perf/util/annotate.c
++++ b/tools/perf/util/annotate.c
+@@ -1100,8 +1100,8 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64
+               for (offset = start; offset <= end; offset++) {
+                       struct annotation_line *al = notes->offsets[offset];
+-                      if (al && al->ipc == 0.0) {
+-                              al->ipc = ipc;
++                      if (al && al->cycles && al->cycles->ipc == 0.0) {
++                              al->cycles->ipc = ipc;
+                               cover_insn++;
+                       }
+               }
+@@ -1114,12 +1114,13 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64
+       }
+ }
+-void annotation__compute_ipc(struct annotation *notes, size_t size)
++static int annotation__compute_ipc(struct annotation *notes, size_t size)
+ {
++      int err = 0;
+       s64 offset;
+       if (!notes->src || !notes->src->cycles_hist)
+-              return;
++              return 0;
+       notes->total_insn = annotation__count_insn(notes, 0, size - 1);
+       notes->hit_cycles = 0;
+@@ -1134,18 +1135,39 @@ void annotation__compute_ipc(struct annotation *notes, size_t size)
+               if (ch && ch->cycles) {
+                       struct annotation_line *al;
++                      al = notes->offsets[offset];
++                      if (al && al->cycles == NULL) {
++                              al->cycles = zalloc(sizeof(*al->cycles));
++                              if (al->cycles == NULL) {
++                                      err = ENOMEM;
++                                      break;
++                              }
++                      }
+                       if (ch->have_start)
+                               annotation__count_and_fill(notes, ch->start, offset, ch);
+-                      al = notes->offsets[offset];
+                       if (al && ch->num_aggr) {
+-                              al->cycles = ch->cycles_aggr / ch->num_aggr;
+-                              al->cycles_max = ch->cycles_max;
+-                              al->cycles_min = ch->cycles_min;
++                              al->cycles->avg = ch->cycles_aggr / ch->num_aggr;
++                              al->cycles->max = ch->cycles_max;
++                              al->cycles->min = ch->cycles_min;
+                       }
+                       notes->have_cycles = true;
+               }
+       }
++
++      if (err) {
++              while (++offset < (s64)size) {
++                      struct cyc_hist *ch = &notes->src->cycles_hist[offset];
++
++                      if (ch && ch->cycles) {
++                              struct annotation_line *al = notes->offsets[offset];
++                              if (al)
++                                      zfree(&al->cycles);
++                      }
++              }
++      }
++
+       annotation__unlock(notes);
++      return 0;
+ }
+ int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
+@@ -1225,6 +1247,7 @@ static void annotation_line__exit(struct annotation_line *al)
+ {
+       zfree_srcline(&al->path);
+       zfree(&al->line);
++      zfree(&al->cycles);
+ }
+ static size_t disasm_line_size(int nr)
+@@ -3083,8 +3106,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
+       int printed;
+       if (first_line && (al->offset == -1 || percent_max == 0.0)) {
+-              if (notes->have_cycles) {
+-                      if (al->ipc == 0.0 && al->cycles == 0)
++              if (notes->have_cycles && al->cycles) {
++                      if (al->cycles->ipc == 0.0 && al->cycles->avg == 0)
+                               show_title = true;
+               } else
+                       show_title = true;
+@@ -3121,17 +3144,17 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
+       }
+       if (notes->have_cycles) {
+-              if (al->ipc)
+-                      obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
++              if (al->cycles && al->cycles->ipc)
++                      obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->cycles->ipc);
+               else if (!show_title)
+                       obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
+               else
+                       obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
+               if (!notes->options->show_minmax_cycle) {
+-                      if (al->cycles)
++                      if (al->cycles && al->cycles->avg)
+                               obj__printf(obj, "%*" PRIu64 " ",
+-                                         ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
++                                         ANNOTATION__CYCLES_WIDTH - 1, al->cycles->avg);
+                       else if (!show_title)
+                               obj__printf(obj, "%*s",
+                                           ANNOTATION__CYCLES_WIDTH, " ");
+@@ -3145,8 +3168,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
+                               scnprintf(str, sizeof(str),
+                                       "%" PRIu64 "(%" PRIu64 "/%" PRIu64 ")",
+-                                      al->cycles, al->cycles_min,
+-                                      al->cycles_max);
++                                      al->cycles->avg, al->cycles->min,
++                                      al->cycles->max);
+                               obj__printf(obj, "%*s ",
+                                           ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
+@@ -3264,7 +3287,11 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
+       annotation__set_offsets(notes, size);
+       annotation__mark_jump_targets(notes, sym);
+-      annotation__compute_ipc(notes, size);
++
++      err = annotation__compute_ipc(notes, size);
++      if (err)
++              goto out_free_offsets;
++
+       annotation__init_column_widths(notes, sym);
+       notes->nr_events = nr_pcnt;
+diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
+index 9627805591760..19bc2f0391757 100644
+--- a/tools/perf/util/annotate.h
++++ b/tools/perf/util/annotate.h
+@@ -130,6 +130,13 @@ struct annotation_data {
+       struct sym_hist_entry    he;
+ };
++struct cycles_info {
++      float                    ipc;
++      u64                      avg;
++      u64                      max;
++      u64                      min;
++};
++
+ struct annotation_line {
+       struct list_head         node;
+       struct rb_node           rb_node;
+@@ -137,12 +144,9 @@ struct annotation_line {
+       char                    *line;
+       int                      line_nr;
+       char                    *fileloc;
+-      int                      jump_sources;
+-      float                    ipc;
+-      u64                      cycles;
+-      u64                      cycles_max;
+-      u64                      cycles_min;
+       char                    *path;
++      struct cycles_info      *cycles;
++      int                      jump_sources;
+       u32                      idx;
+       int                      idx_asm;
+       int                      data_nr;
+@@ -325,7 +329,6 @@ static inline bool annotation_line__filter(struct annotation_line *al, struct an
+ }
+ void annotation__set_offsets(struct annotation *notes, s64 size);
+-void annotation__compute_ipc(struct annotation *notes, size_t size);
+ void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym);
+ void annotation__update_column_widths(struct annotation *notes);
+ void annotation__init_column_widths(struct annotation *notes, struct symbol *sym);
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-annotate-use-global-annotation_options.patch b/queue-6.6/perf-annotate-use-global-annotation_options.patch
new file mode 100644 (file)
index 0000000..204fedf
--- /dev/null
@@ -0,0 +1,642 @@
+From 8f7406f148b75d1ceacb7e863e5dbaa1e0e2c9fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 09:54:37 -0800
+Subject: perf annotate: Use global annotation_options
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit 41fd3cacd29f47f6b9c6474b27c5b0513786c4e9 ]
+
+Now it can directly use the global options and no need to pass it as an
+argument.
+
+Reviewed-by: Ian Rogers <irogers@google.com>
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20231128175441.721579-5-namhyung@kernel.org
+[ Fixup build with GTK2=1 ]
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-annotate.c     |   7 +-
+ tools/perf/builtin-report.c       |   2 +-
+ tools/perf/builtin-top.c          |   4 +-
+ tools/perf/ui/browsers/annotate.c |   6 +-
+ tools/perf/ui/gtk/annotate.c      |   6 +-
+ tools/perf/ui/gtk/gtk.h           |   2 -
+ tools/perf/util/annotate.c        | 118 ++++++++++++++----------------
+ tools/perf/util/annotate.h        |  15 ++--
+ 8 files changed, 71 insertions(+), 89 deletions(-)
+
+diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
+index d3d410cdd9ba5..92973420c0a5a 100644
+--- a/tools/perf/builtin-annotate.c
++++ b/tools/perf/builtin-annotate.c
+@@ -314,9 +314,9 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
+                                   struct perf_annotate *ann)
+ {
+       if (!ann->use_stdio2)
+-              return symbol__tty_annotate(&he->ms, evsel, &annotate_opts);
++              return symbol__tty_annotate(&he->ms, evsel);
+-      return symbol__tty_annotate2(&he->ms, evsel, &annotate_opts);
++      return symbol__tty_annotate2(&he->ms, evsel);
+ }
+ static void hists__find_annotations(struct hists *hists,
+@@ -362,7 +362,6 @@ static void hists__find_annotations(struct hists *hists,
+                       int ret;
+                       int (*annotate)(struct hist_entry *he,
+                                       struct evsel *evsel,
+-                                      struct annotation_options *options,
+                                       struct hist_browser_timer *hbt);
+                       annotate = dlsym(perf_gtk_handle,
+@@ -372,7 +371,7 @@ static void hists__find_annotations(struct hists *hists,
+                               return;
+                       }
+-                      ret = annotate(he, evsel, &annotate_opts, NULL);
++                      ret = annotate(he, evsel, NULL);
+                       if (!ret || !ann->skip_missing)
+                               return;
+diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
+index 00354d16adb43..169c64e9a01a8 100644
+--- a/tools/perf/builtin-report.c
++++ b/tools/perf/builtin-report.c
+@@ -729,7 +729,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg)
+       if (rep->symbol_ipc && sym && !sym->annotate2) {
+               struct evsel *evsel = hists_to_evsel(he->hists);
+-              symbol__annotate2(&he->ms, evsel, &annotate_opts, NULL);
++              symbol__annotate2(&he->ms, evsel, NULL);
+       }
+       return 0;
+diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
+index ecf98169fd8fd..6ac17763de0e0 100644
+--- a/tools/perf/builtin-top.c
++++ b/tools/perf/builtin-top.c
+@@ -147,7 +147,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
+               return err;
+       }
+-      err = symbol__annotate(&he->ms, evsel, &annotate_opts, NULL);
++      err = symbol__annotate(&he->ms, evsel, NULL);
+       if (err == 0) {
+               top->sym_filter_entry = he;
+       } else {
+@@ -263,7 +263,7 @@ static void perf_top__show_details(struct perf_top *top)
+       printf("Showing %s for %s\n", evsel__name(top->sym_evsel), symbol->name);
+       printf("  Events  Pcnt (>=%d%%)\n", annotate_opts.min_pcnt);
+-      more = symbol__annotate_printf(&he->ms, top->sym_evsel, &annotate_opts);
++      more = symbol__annotate_printf(&he->ms, top->sym_evsel);
+       if (top->evlist->enabled) {
+               if (top->zero)
+diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
+index d2470f87344d0..d9f9fa254a71f 100644
+--- a/tools/perf/ui/browsers/annotate.c
++++ b/tools/perf/ui/browsers/annotate.c
+@@ -114,7 +114,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
+       if (!browser->navkeypressed)
+               ops.width += 1;
+-      annotation_line__write(al, notes, &ops, ab->opts);
++      annotation_line__write(al, notes, &ops);
+       if (ops.current_entry)
+               ab->selection = al;
+@@ -884,7 +884,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
+                       continue;
+               }
+               case 'P':
+-                      map_symbol__annotation_dump(ms, evsel, browser->opts);
++                      map_symbol__annotation_dump(ms, evsel);
+                       continue;
+               case 't':
+                       if (symbol_conf.show_total_period) {
+@@ -979,7 +979,7 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
+               return -1;
+       if (not_annotated) {
+-              err = symbol__annotate2(ms, evsel, opts, &browser.arch);
++              err = symbol__annotate2(ms, evsel, &browser.arch);
+               if (err) {
+                       char msg[BUFSIZ];
+                       dso->annotate_warned = true;
+diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
+index 2effac77ca8c6..394861245fd3e 100644
+--- a/tools/perf/ui/gtk/annotate.c
++++ b/tools/perf/ui/gtk/annotate.c
+@@ -162,7 +162,6 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct map_symbol *ms,
+ }
+ static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel,
+-                              struct annotation_options *options,
+                               struct hist_browser_timer *hbt)
+ {
+       struct dso *dso = map__dso(ms->map);
+@@ -176,7 +175,7 @@ static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel,
+       if (dso->annotate_warned)
+               return -1;
+-      err = symbol__annotate(ms, evsel, options, NULL);
++      err = symbol__annotate(ms, evsel, NULL);
+       if (err) {
+               char msg[BUFSIZ];
+               dso->annotate_warned = true;
+@@ -244,10 +243,9 @@ static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel,
+ int hist_entry__gtk_annotate(struct hist_entry *he,
+                            struct evsel *evsel,
+-                           struct annotation_options *options,
+                            struct hist_browser_timer *hbt)
+ {
+-      return symbol__gtk_annotate(&he->ms, evsel, options, hbt);
++      return symbol__gtk_annotate(&he->ms, evsel, hbt);
+ }
+ void perf_gtk__show_annotations(void)
+diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
+index 1e84dceb52671..a2b497f03fd6e 100644
+--- a/tools/perf/ui/gtk/gtk.h
++++ b/tools/perf/ui/gtk/gtk.h
+@@ -56,13 +56,11 @@ struct evsel;
+ struct evlist;
+ struct hist_entry;
+ struct hist_browser_timer;
+-struct annotation_options;
+ int evlist__gtk_browse_hists(struct evlist *evlist, const char *help,
+                            struct hist_browser_timer *hbt, float min_pcnt);
+ int hist_entry__gtk_annotate(struct hist_entry *he,
+                            struct evsel *evsel,
+-                           struct annotation_options *options,
+                            struct hist_browser_timer *hbt);
+ void perf_gtk__show_annotations(void);
+diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
+index 2a22bd30a98b7..5fa4831631140 100644
+--- a/tools/perf/util/annotate.c
++++ b/tools/perf/util/annotate.c
+@@ -1843,7 +1843,6 @@ static int symbol__disassemble_bpf(struct symbol *sym,
+                                  struct annotate_args *args)
+ {
+       struct annotation *notes = symbol__annotation(sym);
+-      struct annotation_options *opts = args->options;
+       struct bpf_prog_linfo *prog_linfo = NULL;
+       struct bpf_prog_info_node *info_node;
+       int len = sym->end - sym->start;
+@@ -1953,7 +1952,7 @@ static int symbol__disassemble_bpf(struct symbol *sym,
+               prev_buf_size = buf_size;
+               fflush(s);
+-              if (!opts->hide_src_code && srcline) {
++              if (!annotate_opts.hide_src_code && srcline) {
+                       args->offset = -1;
+                       args->line = strdup(srcline);
+                       args->line_nr = 0;
+@@ -2076,7 +2075,7 @@ static char *expand_tabs(char *line, char **storage, size_t *storage_len)
+ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
+ {
+-      struct annotation_options *opts = args->options;
++      struct annotation_options *opts = &annotate_opts;
+       struct map *map = args->ms.map;
+       struct dso *dso = map__dso(map);
+       char *command;
+@@ -2326,13 +2325,13 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
+ }
+ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
+-                   struct annotation_options *options, struct arch **parch)
++                   struct arch **parch)
+ {
+       struct symbol *sym = ms->sym;
+       struct annotation *notes = symbol__annotation(sym);
+       struct annotate_args args = {
+               .evsel          = evsel,
+-              .options        = options,
++              .options        = &annotate_opts,
+       };
+       struct perf_env *env = evsel__env(evsel);
+       const char *arch_name = perf_env__arch(env);
+@@ -2360,7 +2359,7 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
+       }
+       args.ms = *ms;
+-      if (notes->options && notes->options->full_addr)
++      if (annotate_opts.full_addr)
+               notes->start = map__objdump_2mem(ms->map, ms->sym->start);
+       else
+               notes->start = map__rip_2objdump(ms->map, ms->sym->start);
+@@ -2368,12 +2367,12 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
+       return symbol__disassemble(sym, &args);
+ }
+-static void insert_source_line(struct rb_root *root, struct annotation_line *al,
+-                             struct annotation_options *opts)
++static void insert_source_line(struct rb_root *root, struct annotation_line *al)
+ {
+       struct annotation_line *iter;
+       struct rb_node **p = &root->rb_node;
+       struct rb_node *parent = NULL;
++      unsigned int percent_type = annotate_opts.percent_type;
+       int i, ret;
+       while (*p != NULL) {
+@@ -2384,7 +2383,7 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al,
+               if (ret == 0) {
+                       for (i = 0; i < al->data_nr; i++) {
+                               iter->data[i].percent_sum += annotation_data__percent(&al->data[i],
+-                                                                                    opts->percent_type);
++                                                                                    percent_type);
+                       }
+                       return;
+               }
+@@ -2397,7 +2396,7 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al,
+       for (i = 0; i < al->data_nr; i++) {
+               al->data[i].percent_sum = annotation_data__percent(&al->data[i],
+-                                                                 opts->percent_type);
++                                                                 percent_type);
+       }
+       rb_link_node(&al->rb_node, parent, p);
+@@ -2519,8 +2518,7 @@ static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start)
+       return 0;
+ }
+-int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel,
+-                          struct annotation_options *opts)
++int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel)
+ {
+       struct map *map = ms->map;
+       struct symbol *sym = ms->sym;
+@@ -2531,6 +2529,7 @@ int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel,
+       struct annotation *notes = symbol__annotation(sym);
+       struct sym_hist *h = annotation__histogram(notes, evsel->core.idx);
+       struct annotation_line *pos, *queue = NULL;
++      struct annotation_options *opts = &annotate_opts;
+       u64 start = map__rip_2objdump(map, sym->start);
+       int printed = 2, queue_len = 0, addr_fmt_width;
+       int more = 0;
+@@ -2659,8 +2658,7 @@ static void FILE__write_graph(void *fp, int graph)
+       fputs(s, fp);
+ }
+-static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
+-                                   struct annotation_options *opts)
++static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
+ {
+       struct annotation *notes = symbol__annotation(sym);
+       struct annotation_write_ops wops = {
+@@ -2677,7 +2675,7 @@ static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
+       list_for_each_entry(al, &notes->src->source, node) {
+               if (annotation_line__filter(al, notes))
+                       continue;
+-              annotation_line__write(al, notes, &wops, opts);
++              annotation_line__write(al, notes, &wops);
+               fputc('\n', fp);
+               wops.first_line = false;
+       }
+@@ -2685,8 +2683,7 @@ static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
+       return 0;
+ }
+-int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
+-                              struct annotation_options *opts)
++int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel)
+ {
+       const char *ev_name = evsel__name(evsel);
+       char buf[1024];
+@@ -2708,7 +2705,7 @@ int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
+       fprintf(fp, "%s() %s\nEvent: %s\n\n",
+               ms->sym->name, map__dso(ms->map)->long_name, ev_name);
+-      symbol__annotate_fprintf2(ms->sym, fp, opts);
++      symbol__annotate_fprintf2(ms->sym, fp);
+       fclose(fp);
+       err = 0;
+@@ -2884,24 +2881,24 @@ void annotation__init_column_widths(struct annotation *notes, struct symbol *sym
+ void annotation__update_column_widths(struct annotation *notes)
+ {
+-      if (notes->options->use_offset)
++      if (annotate_opts.use_offset)
+               notes->widths.target = notes->widths.min_addr;
+-      else if (notes->options->full_addr)
++      else if (annotate_opts.full_addr)
+               notes->widths.target = BITS_PER_LONG / 4;
+       else
+               notes->widths.target = notes->widths.max_addr;
+       notes->widths.addr = notes->widths.target;
+-      if (notes->options->show_nr_jumps)
++      if (annotate_opts.show_nr_jumps)
+               notes->widths.addr += notes->widths.jumps + 1;
+ }
+ void annotation__toggle_full_addr(struct annotation *notes, struct map_symbol *ms)
+ {
+-      notes->options->full_addr = !notes->options->full_addr;
++      annotate_opts.full_addr = !annotate_opts.full_addr;
+-      if (notes->options->full_addr)
++      if (annotate_opts.full_addr)
+               notes->start = map__objdump_2mem(ms->map, ms->sym->start);
+       else
+               notes->start = map__rip_2objdump(ms->map, ms->sym->start);
+@@ -2910,8 +2907,7 @@ void annotation__toggle_full_addr(struct annotation *notes, struct map_symbol *m
+ }
+ static void annotation__calc_lines(struct annotation *notes, struct map *map,
+-                                 struct rb_root *root,
+-                                 struct annotation_options *opts)
++                                 struct rb_root *root)
+ {
+       struct annotation_line *al;
+       struct rb_root tmp_root = RB_ROOT;
+@@ -2924,7 +2920,7 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
+                       double percent;
+                       percent = annotation_data__percent(&al->data[i],
+-                                                         opts->percent_type);
++                                                         annotate_opts.percent_type);
+                       if (percent > percent_max)
+                               percent_max = percent;
+@@ -2935,22 +2931,20 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
+               al->path = get_srcline(map__dso(map), notes->start + al->offset, NULL,
+                                      false, true, notes->start + al->offset);
+-              insert_source_line(&tmp_root, al, opts);
++              insert_source_line(&tmp_root, al);
+       }
+       resort_source_line(root, &tmp_root);
+ }
+-static void symbol__calc_lines(struct map_symbol *ms, struct rb_root *root,
+-                             struct annotation_options *opts)
++static void symbol__calc_lines(struct map_symbol *ms, struct rb_root *root)
+ {
+       struct annotation *notes = symbol__annotation(ms->sym);
+-      annotation__calc_lines(notes, ms->map, root, opts);
++      annotation__calc_lines(notes, ms->map, root);
+ }
+-int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel,
+-                        struct annotation_options *opts)
++int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel)
+ {
+       struct dso *dso = map__dso(ms->map);
+       struct symbol *sym = ms->sym;
+@@ -2959,7 +2953,7 @@ int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel,
+       char buf[1024];
+       int err;
+-      err = symbol__annotate2(ms, evsel, opts, NULL);
++      err = symbol__annotate2(ms, evsel, NULL);
+       if (err) {
+               char msg[BUFSIZ];
+@@ -2969,31 +2963,31 @@ int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel,
+               return -1;
+       }
+-      if (opts->print_lines) {
+-              srcline_full_filename = opts->full_path;
+-              symbol__calc_lines(ms, &source_line, opts);
++      if (annotate_opts.print_lines) {
++              srcline_full_filename = annotate_opts.full_path;
++              symbol__calc_lines(ms, &source_line);
+               print_summary(&source_line, dso->long_name);
+       }
+       hists__scnprintf_title(hists, buf, sizeof(buf));
+       fprintf(stdout, "%s, [percent: %s]\n%s() %s\n",
+-              buf, percent_type_str(opts->percent_type), sym->name, dso->long_name);
+-      symbol__annotate_fprintf2(sym, stdout, opts);
++              buf, percent_type_str(annotate_opts.percent_type), sym->name,
++              dso->long_name);
++      symbol__annotate_fprintf2(sym, stdout);
+       annotated_source__purge(symbol__annotation(sym)->src);
+       return 0;
+ }
+-int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,
+-                       struct annotation_options *opts)
++int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel)
+ {
+       struct dso *dso = map__dso(ms->map);
+       struct symbol *sym = ms->sym;
+       struct rb_root source_line = RB_ROOT;
+       int err;
+-      err = symbol__annotate(ms, evsel, opts, NULL);
++      err = symbol__annotate(ms, evsel, NULL);
+       if (err) {
+               char msg[BUFSIZ];
+@@ -3005,13 +2999,13 @@ int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,
+       symbol__calc_percent(sym, evsel);
+-      if (opts->print_lines) {
+-              srcline_full_filename = opts->full_path;
+-              symbol__calc_lines(ms, &source_line, opts);
++      if (annotate_opts.print_lines) {
++              srcline_full_filename = annotate_opts.full_path;
++              symbol__calc_lines(ms, &source_line);
+               print_summary(&source_line, dso->long_name);
+       }
+-      symbol__annotate_printf(ms, evsel, opts);
++      symbol__annotate_printf(ms, evsel);
+       annotated_source__purge(symbol__annotation(sym)->src);
+@@ -3072,7 +3066,7 @@ static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
+               obj__printf(obj, "  ");
+       }
+-      disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset, notes->widths.max_ins_name);
++      disasm_line__scnprintf(dl, bf, size, !annotate_opts.use_offset, notes->widths.max_ins_name);
+ }
+ static void ipc_coverage_string(char *bf, int size, struct annotation *notes)
+@@ -3154,7 +3148,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
+               else
+                       obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
+-              if (!notes->options->show_minmax_cycle) {
++              if (!annotate_opts.show_minmax_cycle) {
+                       if (al->cycles && al->cycles->avg)
+                               obj__printf(obj, "%*" PRIu64 " ",
+                                          ANNOTATION__CYCLES_WIDTH - 1, al->cycles->avg);
+@@ -3198,7 +3192,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
+       if (!*al->line)
+               obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, " ");
+       else if (al->offset == -1) {
+-              if (al->line_nr && notes->options->show_linenr)
++              if (al->line_nr && annotate_opts.show_linenr)
+                       printed = scnprintf(bf, sizeof(bf), "%-*d ", notes->widths.addr + 1, al->line_nr);
+               else
+                       printed = scnprintf(bf, sizeof(bf), "%-*s  ", notes->widths.addr, " ");
+@@ -3208,15 +3202,15 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
+               u64 addr = al->offset;
+               int color = -1;
+-              if (!notes->options->use_offset)
++              if (!annotate_opts.use_offset)
+                       addr += notes->start;
+-              if (!notes->options->use_offset) {
++              if (!annotate_opts.use_offset) {
+                       printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
+               } else {
+                       if (al->jump_sources &&
+-                          notes->options->offset_level >= ANNOTATION__OFFSET_JUMP_TARGETS) {
+-                              if (notes->options->show_nr_jumps) {
++                          annotate_opts.offset_level >= ANNOTATION__OFFSET_JUMP_TARGETS) {
++                              if (annotate_opts.show_nr_jumps) {
+                                       int prev;
+                                       printed = scnprintf(bf, sizeof(bf), "%*d ",
+                                                           notes->widths.jumps,
+@@ -3230,9 +3224,9 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
+                               printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
+                                                   notes->widths.target, addr);
+                       } else if (ins__is_call(&disasm_line(al)->ins) &&
+-                                 notes->options->offset_level >= ANNOTATION__OFFSET_CALL) {
++                                 annotate_opts.offset_level >= ANNOTATION__OFFSET_CALL) {
+                               goto print_addr;
+-                      } else if (notes->options->offset_level == ANNOTATION__MAX_OFFSET_LEVEL) {
++                      } else if (annotate_opts.offset_level == ANNOTATION__MAX_OFFSET_LEVEL) {
+                               goto print_addr;
+                       } else {
+                               printed = scnprintf(bf, sizeof(bf), "%-*s  ",
+@@ -3254,19 +3248,18 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
+ }
+ void annotation_line__write(struct annotation_line *al, struct annotation *notes,
+-                          struct annotation_write_ops *wops,
+-                          struct annotation_options *opts)
++                          struct annotation_write_ops *wops)
+ {
+       __annotation_line__write(al, notes, wops->first_line, wops->current_entry,
+                                wops->change_color, wops->width, wops->obj,
+-                               opts->percent_type,
++                               annotate_opts.percent_type,
+                                wops->set_color, wops->set_percent_color,
+                                wops->set_jumps_percent_color, wops->printf,
+                                wops->write_graph);
+ }
+ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
+-                    struct annotation_options *options, struct arch **parch)
++                    struct arch **parch)
+ {
+       struct symbol *sym = ms->sym;
+       struct annotation *notes = symbol__annotation(sym);
+@@ -3280,11 +3273,11 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
+       if (evsel__is_group_event(evsel))
+               nr_pcnt = evsel->core.nr_members;
+-      err = symbol__annotate(ms, evsel, options, parch);
++      err = symbol__annotate(ms, evsel, parch);
+       if (err)
+               goto out_free_offsets;
+-      notes->options = options;
++      notes->options = &annotate_opts;
+       symbol__calc_percent(sym, evsel);
+@@ -3412,10 +3405,9 @@ static unsigned int parse_percent_type(char *str1, char *str2)
+       return type;
+ }
+-int annotate_parse_percent_type(const struct option *opt, const char *_str,
++int annotate_parse_percent_type(const struct option *opt __maybe_unused, const char *_str,
+                               int unset __maybe_unused)
+ {
+-      struct annotation_options *opts = opt->value;
+       unsigned int type;
+       char *str1, *str2;
+       int err = -1;
+@@ -3434,7 +3426,7 @@ int annotate_parse_percent_type(const struct option *opt, const char *_str,
+       if (type == (unsigned int) -1)
+               type = parse_percent_type(str2, str1);
+       if (type != (unsigned int) -1) {
+-              opts->percent_type = type;
++              annotate_opts.percent_type = type;
+               err = 0;
+       }
+diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
+index d45a777f7229b..0fa72eb559ac4 100644
+--- a/tools/perf/util/annotate.h
++++ b/tools/perf/util/annotate.h
+@@ -220,8 +220,7 @@ struct annotation_write_ops {
+ };
+ void annotation_line__write(struct annotation_line *al, struct annotation *notes,
+-                          struct annotation_write_ops *ops,
+-                          struct annotation_options *opts);
++                          struct annotation_write_ops *ops);
+ int __annotation__scnprintf_samples_period(struct annotation *notes,
+                                          char *bf, size_t size,
+@@ -366,11 +365,9 @@ void symbol__annotate_zero_histograms(struct symbol *sym);
+ int symbol__annotate(struct map_symbol *ms,
+                    struct evsel *evsel,
+-                   struct annotation_options *options,
+                    struct arch **parch);
+ int symbol__annotate2(struct map_symbol *ms,
+                     struct evsel *evsel,
+-                    struct annotation_options *options,
+                     struct arch **parch);
+ enum symbol_disassemble_errno {
+@@ -397,20 +394,18 @@ enum symbol_disassemble_errno {
+ int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen);
+-int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel,
+-                          struct annotation_options *options);
++int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel);
+ void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
+ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
+ void annotated_source__purge(struct annotated_source *as);
+-int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
+-                              struct annotation_options *opts);
++int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel);
+ bool ui__has_annotation(void);
+-int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts);
++int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel);
+-int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts);
++int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel);
+ #ifdef HAVE_SLANG_SUPPORT
+ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-bench-internals-inject-build-id-fix-trap-divide.patch b/queue-6.6/perf-bench-internals-inject-build-id-fix-trap-divide.patch
new file mode 100644 (file)
index 0000000..a000e18
--- /dev/null
@@ -0,0 +1,55 @@
+From 510a7a9cb3d5046218eed8eaf114bb5a3b111b45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 14:50:26 +0800
+Subject: perf bench internals inject-build-id: Fix trap divide when collecting
+ just one DSO
+
+From: He Zhe <zhe.he@windriver.com>
+
+[ Upstream commit d9180e23fbfa3875424d3a6b28b71b072862a52a ]
+
+'perf bench internals inject-build-id' suffers from the following error when
+only one DSO is collected.
+
+  # perf bench internals inject-build-id -v
+    Collected 1 DSOs
+  traps: internals-injec[2305] trap divide error
+  ip:557566ba6394 sp:7ffd4de97fe0 error:0 in perf[557566b2a000+23d000]
+    Build-id injection benchmark
+    Iteration #1
+  Floating point exception
+
+This patch removes the unnecessary minus one from the divisor which also
+corrects the randomization range.
+
+Signed-off-by: He Zhe <zhe.he@windriver.com>
+Fixes: 0bf02a0d80427f26 ("perf bench: Add build-id injection benchmark")
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Link: https://lore.kernel.org/r/20240507065026.2652929-1-zhe.he@windriver.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/bench/inject-buildid.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/bench/inject-buildid.c b/tools/perf/bench/inject-buildid.c
+index 49331743c7439..a759eb2328bea 100644
+--- a/tools/perf/bench/inject-buildid.c
++++ b/tools/perf/bench/inject-buildid.c
+@@ -362,7 +362,7 @@ static int inject_build_id(struct bench_data *data, u64 *max_rss)
+               return -1;
+       for (i = 0; i < nr_mmaps; i++) {
+-              int idx = rand() % (nr_dsos - 1);
++              int idx = rand() % nr_dsos;
+               struct bench_dso *dso = &dsos[idx];
+               u64 timestamp = rand() % 1000000;
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-bench-uprobe-remove-lib64-from-libc.so.6-binary.patch b/queue-6.6/perf-bench-uprobe-remove-lib64-from-libc.so.6-binary.patch
new file mode 100644 (file)
index 0000000..9822b97
--- /dev/null
@@ -0,0 +1,48 @@
+From 6feb6de0bcddd02b17b5e461dcfa0c05e7d5128f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Apr 2024 21:09:10 -0700
+Subject: perf bench uprobe: Remove lib64 from libc.so.6 binary path
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 459fee7b508231cd4622b3bd94aaa85e8e16b888 ]
+
+bpf_program__attach_uprobe_opts will search LD_LIBRARY_PATH and so
+specifying `/lib64` is unnecessary and causes failures for libc.so.6
+paths like `/lib/x86_64-linux-gnu/libc.so.6`.
+
+Fixes: 7b47623b8cae8149 ("perf bench uprobe trace_printk: Add entry attaching an BPF program that does a trace_printk")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Acked-by: Jiri Olsa <jolsa@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Andrei Vagin <avagin@google.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Kees Kook <keescook@chromium.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240406040911.1603801-1-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/bench/uprobe.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c
+index 914c0817fe8ad..e8e0afa13f049 100644
+--- a/tools/perf/bench/uprobe.c
++++ b/tools/perf/bench/uprobe.c
+@@ -47,7 +47,7 @@ static const char * const bench_uprobe_usage[] = {
+ #define bench_uprobe__attach_uprobe(prog) \
+       skel->links.prog = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.prog, \
+                                                          /*pid=*/-1, \
+-                                                         /*binary_path=*/"/lib64/libc.so.6", \
++                                                         /*binary_path=*/"libc.so.6", \
+                                                          /*func_offset=*/0, \
+                                                          /*opts=*/&uprobe_opts); \
+       if (!skel->links.prog) { \
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-daemon-fix-file-leak-in-daemon_session__control.patch b/queue-6.6/perf-daemon-fix-file-leak-in-daemon_session__control.patch
new file mode 100644 (file)
index 0000000..af61b22
--- /dev/null
@@ -0,0 +1,59 @@
+From c14a1f9ba027b95d7821fa8e307a9a08ebcb8269 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 May 2024 17:34:24 -0700
+Subject: perf daemon: Fix file leak in daemon_session__control
+
+From: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+
+[ Upstream commit 09541603462c399c7408d50295db99b4b8042eaa ]
+
+The open() function returns -1 on error.
+
+The 'control' and 'ack' file descriptors are both initialized with
+open() and further validated with 'if' statement.
+
+'if (!control)' would evaluate to 'true' if returned value on error were
+'0' but it is actually '-1'.
+
+Fixes: edcaa47958c7438b ("perf daemon: Add 'ping' command")
+Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240510003424.2016914-1-samasth.norway.ananda@oracle.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-daemon.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/perf/builtin-daemon.c b/tools/perf/builtin-daemon.c
+index 83954af36753a..de76bbc50bfbc 100644
+--- a/tools/perf/builtin-daemon.c
++++ b/tools/perf/builtin-daemon.c
+@@ -523,7 +523,7 @@ static int daemon_session__control(struct daemon_session *session,
+                 session->base, SESSION_CONTROL);
+       control = open(control_path, O_WRONLY|O_NONBLOCK);
+-      if (!control)
++      if (control < 0)
+               return -1;
+       if (do_ack) {
+@@ -532,7 +532,7 @@ static int daemon_session__control(struct daemon_session *session,
+                         session->base, SESSION_ACK);
+               ack = open(ack_path, O_RDONLY, O_NONBLOCK);
+-              if (!ack) {
++              if (ack < 0) {
+                       close(control);
+                       return -1;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-docs-document-bpf-event-modifier.patch b/queue-6.6/perf-docs-document-bpf-event-modifier.patch
new file mode 100644 (file)
index 0000000..a47ab97
--- /dev/null
@@ -0,0 +1,48 @@
+From dd37882c5ee844cff813eb64bae6956a9e67cb2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Apr 2024 10:00:13 -0700
+Subject: perf docs: Document bpf event modifier
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit eb4d27cf9aef3e6c9bcaf8fa1a1cadc2433d847b ]
+
+Document that 'b' is used as a modifier to make an event use a BPF
+counter.
+
+Fixes: 01bd8efcec444468 ("perf stat: Introduce ':b' modifier")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Song Liu <song@kernel.org>
+Cc: Thomas Richter <tmricht@linux.ibm.com>
+Link: https://lore.kernel.org/r/20240416170014.985191-1-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/Documentation/perf-list.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
+index d5f78e125efed..69c6d5e46ad88 100644
+--- a/tools/perf/Documentation/perf-list.txt
++++ b/tools/perf/Documentation/perf-list.txt
+@@ -67,6 +67,7 @@ counted. The following modifiers exist:
+  D - pin the event to the PMU
+  W - group is weak and will fallback to non-group if not schedulable,
+  e - group or event are exclusive and do not share the PMU
++ b - use BPF aggregration (see perf stat --bpf-counters)
+ The 'p' modifier can be used for specifying how precise the instruction
+ address should be. The 'p' modifier can be specified multiple times:
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-evlist-add-evlist__findnew_tracking_event-helpe.patch b/queue-6.6/perf-evlist-add-evlist__findnew_tracking_event-helpe.patch
new file mode 100644 (file)
index 0000000..220ee09
--- /dev/null
@@ -0,0 +1,108 @@
+From c88ce46ef805a1aa622e586f90949ddfd2784c56 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Sep 2023 02:33:36 +0000
+Subject: perf evlist: Add evlist__findnew_tracking_event() helper
+
+From: Yang Jihong <yangjihong1@huawei.com>
+
+[ Upstream commit 9c95e4ef065723496442898614d09a9a916eab81 ]
+
+Currently, intel-bts, intel-pt, and arm-spe may add tracking event to the
+evlist. We may need to search for the tracking event for some settings.
+
+Therefore, add evlist__findnew_tracking_event() helper.
+
+If system_wide is true, evlist__findnew_tracking_event() set the cpu map
+of the evsel to all online CPUs.
+
+Signed-off-by: Yang Jihong <yangjihong1@huawei.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Tested-by: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Anshuman Khandual <anshuman.khandual@arm.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Richter <tmricht@linux.ibm.com>
+Link: https://lore.kernel.org/r/20230904023340.12707-3-yangjihong1@huawei.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: 792bc998baf9 ("perf record: Fix debug message placement for test consumption")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-record.c | 11 +++--------
+ tools/perf/util/evlist.c    | 18 ++++++++++++++++++
+ tools/perf/util/evlist.h    |  1 +
+ 3 files changed, 22 insertions(+), 8 deletions(-)
+
+diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
+index 5c54fda63b581..16e21a3e883a7 100644
+--- a/tools/perf/builtin-record.c
++++ b/tools/perf/builtin-record.c
+@@ -1293,14 +1293,9 @@ static int record__open(struct record *rec)
+        */
+       if (opts->target.initial_delay || target__has_cpu(&opts->target) ||
+           perf_pmus__num_core_pmus() > 1) {
+-              pos = evlist__get_tracking_event(evlist);
+-              if (!evsel__is_dummy_event(pos)) {
+-                      /* Set up dummy event. */
+-                      if (evlist__add_dummy(evlist))
+-                              return -ENOMEM;
+-                      pos = evlist__last(evlist);
+-                      evlist__set_tracking_event(evlist, pos);
+-              }
++              pos = evlist__findnew_tracking_event(evlist, false);
++              if (!pos)
++                      return -ENOMEM;
+               /*
+                * Enable the dummy event when the process is forked for
+diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
+index 8bf537a29809a..eb1dd29c538d5 100644
+--- a/tools/perf/util/evlist.c
++++ b/tools/perf/util/evlist.c
+@@ -1702,6 +1702,24 @@ void evlist__set_tracking_event(struct evlist *evlist, struct evsel *tracking_ev
+       tracking_evsel->tracking = true;
+ }
++struct evsel *evlist__findnew_tracking_event(struct evlist *evlist, bool system_wide)
++{
++      struct evsel *evsel;
++
++      evsel = evlist__get_tracking_event(evlist);
++      if (!evsel__is_dummy_event(evsel)) {
++              evsel = evlist__add_aux_dummy(evlist, system_wide);
++              if (!evsel)
++                      return NULL;
++
++              evlist__set_tracking_event(evlist, evsel);
++      } else if (system_wide) {
++              perf_evlist__go_system_wide(&evlist->core, &evsel->core);
++      }
++
++      return evsel;
++}
++
+ struct evsel *evlist__find_evsel_by_str(struct evlist *evlist, const char *str)
+ {
+       struct evsel *evsel;
+diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
+index d63486261fd2a..cb91dc9117a27 100644
+--- a/tools/perf/util/evlist.h
++++ b/tools/perf/util/evlist.h
+@@ -387,6 +387,7 @@ bool evlist_cpu_iterator__end(const struct evlist_cpu_iterator *evlist_cpu_itr);
+ struct evsel *evlist__get_tracking_event(struct evlist *evlist);
+ void evlist__set_tracking_event(struct evlist *evlist, struct evsel *tracking_evsel);
++struct evsel *evlist__findnew_tracking_event(struct evlist *evlist, bool system_wide);
+ struct evsel *evlist__find_evsel_by_str(struct evlist *evlist, const char *str);
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-intel-pt-fix-unassigned-instruction-op-discover.patch b/queue-6.6/perf-intel-pt-fix-unassigned-instruction-op-discover.patch
new file mode 100644 (file)
index 0000000..847cb0b
--- /dev/null
@@ -0,0 +1,73 @@
+From 85026bb9282a2593c3480c4f551aa48bf1cbc058 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Mar 2024 10:32:23 +0200
+Subject: perf intel-pt: Fix unassigned instruction op (discovered by
+ MemorySanitizer)
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit e101a05f79fd4ee3e89d2f3fb716493c33a33708 ]
+
+MemorySanitizer discovered instances where the instruction op value was
+not assigned.:
+
+  WARNING: MemorySanitizer: use-of-uninitialized-value
+    #0 0x5581c00a76b3 in intel_pt_sample_flags tools/perf/util/intel-pt.c:1527:17
+  Uninitialized value was stored to memory at
+    #0 0x5581c005ddf8 in intel_pt_walk_insn tools/perf/util/intel-pt-decoder/intel-pt-decoder.c:1256:25
+
+The op value is used to set branch flags for branch instructions
+encountered when walking the code, so fix by setting op to
+INTEL_PT_OP_OTHER in other cases.
+
+Fixes: 4c761d805bb2d2ea ("perf intel-pt: Fix intel_pt_fup_event() assumptions about setting state type")
+Reported-by: Ian Rogers <irogers@google.com>
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Tested-by: Ian Rogers <irogers@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Closes: https://lore.kernel.org/linux-perf-users/20240320162619.1272015-1-irogers@google.com/
+Link: https://lore.kernel.org/r/20240326083223.10883-1-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 2 ++
+ tools/perf/util/intel-pt.c                          | 2 ++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+index b450178e3420b..e733f6b1f7ac5 100644
+--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+@@ -1319,6 +1319,8 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder, bool no_tip)
+       bool ret = false;
+       decoder->state.type &= ~INTEL_PT_BRANCH;
++      decoder->state.insn_op = INTEL_PT_OP_OTHER;
++      decoder->state.insn_len = 0;
+       if (decoder->set_fup_cfe_ip || decoder->set_fup_cfe) {
+               bool ip = decoder->set_fup_cfe_ip;
+diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
+index f38893e0b0369..4db9a098f5926 100644
+--- a/tools/perf/util/intel-pt.c
++++ b/tools/perf/util/intel-pt.c
+@@ -764,6 +764,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
+       addr_location__init(&al);
+       intel_pt_insn->length = 0;
++      intel_pt_insn->op = INTEL_PT_OP_OTHER;
+       if (to_ip && *ip == to_ip)
+               goto out_no_cache;
+@@ -898,6 +899,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
+                       if (to_ip && *ip == to_ip) {
+                               intel_pt_insn->length = 0;
++                              intel_pt_insn->op = INTEL_PT_OP_OTHER;
+                               goto out_no_cache;
+                       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-machine-thread-remove-exited-threads-by-default.patch b/queue-6.6/perf-machine-thread-remove-exited-threads-by-default.patch
new file mode 100644 (file)
index 0000000..da8f83d
--- /dev/null
@@ -0,0 +1,181 @@
+From aa5943e4c689dd47af5ce3976c039907b9f0e193 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 Nov 2023 10:56:47 -0700
+Subject: perf machine thread: Remove exited threads by default
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 9ffa6c7512ca7aaeb30e596e2c247cb1fae7123a ]
+
+'struct thread' values hold onto references to mmaps, DSOs, etc. When a
+thread exits it is necessary to clean all of this memory up by removing
+the thread from the machine's threads. Some tools require this doesn't
+happen, such as auxtrace events, 'perf report' if offcpu events exist or
+if a task list is being generated, so add a 'struct symbol_conf' member
+to make the behavior optional. When an exited thread is left in the
+machine's threads, mark it as exited.
+
+This change relates to commit 40826c45eb0b8856 ("perf thread: Remove
+notion of dead threads") . Dead threads were removed as they had a
+reference count of 0 and were difficult to reason about with the
+reference count checker. Here a thread is removed from threads when it
+exits, unless via symbol_conf the exited thread isn't remove and is
+marked as exited. Reference counting behaves as it normally does.
+
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Changbin Du <changbin.du@huawei.com>
+Cc: Colin Ian King <colin.i.king@gmail.com>
+Cc: Dmitrii Dolgov <9erthalion6@gmail.com>
+Cc: German Gomez <german.gomez@arm.com>
+Cc: Huacai Chen <chenhuacai@kernel.org>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: K Prateek Nayak <kprateek.nayak@amd.com>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: Li Dong <lidong@vivo.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Miguel Ojeda <ojeda@kernel.org>
+Cc: Ming Wang <wangming01@loongson.cn>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Nick Terrell <terrelln@fb.com>
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Sandipan Das <sandipan.das@amd.com>
+Cc: Sean Christopherson <seanjc@google.com>
+Cc: Steinar H. Gunderson <sesse@google.com>
+Cc: Vincent Whitchurch <vincent.whitchurch@axis.com>
+Cc: Wenyu Liu <liuwenyu7@huawei.com>
+Cc: Yang Jihong <yangjihong1@huawei.com>
+Link: https://lore.kernel.org/r/20231102175735.2272696-6-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-report.c   |  7 +++++++
+ tools/perf/util/machine.c     | 10 +++++++---
+ tools/perf/util/session.c     |  5 +++++
+ tools/perf/util/symbol_conf.h |  3 ++-
+ tools/perf/util/thread.h      | 14 ++++++++++++++
+ 5 files changed, 35 insertions(+), 4 deletions(-)
+
+diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
+index dcedfe00f04db..749246817aed3 100644
+--- a/tools/perf/builtin-report.c
++++ b/tools/perf/builtin-report.c
+@@ -1411,6 +1411,13 @@ int cmd_report(int argc, const char **argv)
+       if (ret < 0)
+               goto exit;
++      /*
++       * tasks_mode require access to exited threads to list those that are in
++       * the data file. Off-cpu events are synthesized after other events and
++       * reference exited threads.
++       */
++      symbol_conf.keep_exited_threads = true;
++
+       annotation_options__init(&report.annotation_opts);
+       ret = perf_config(report__config, &report);
+diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
+index e6a8d758f6fe4..7c6874804660e 100644
+--- a/tools/perf/util/machine.c
++++ b/tools/perf/util/machine.c
+@@ -2158,9 +2158,13 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event
+       if (dump_trace)
+               perf_event__fprintf_task(event, stdout);
+-      if (thread != NULL)
+-              thread__put(thread);
+-
++      if (thread != NULL) {
++              if (symbol_conf.keep_exited_threads)
++                      thread__set_exited(thread, /*exited=*/true);
++              else
++                      machine__remove_thread(machine, thread);
++      }
++      thread__put(thread);
+       return 0;
+ }
+diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
+index 1e9aa8ed15b64..c6afba7ab1a51 100644
+--- a/tools/perf/util/session.c
++++ b/tools/perf/util/session.c
+@@ -115,6 +115,11 @@ static int perf_session__open(struct perf_session *session, int repipe_fd)
+               return -1;
+       }
++      if (perf_header__has_feat(&session->header, HEADER_AUXTRACE)) {
++              /* Auxiliary events may reference exited threads, hold onto dead ones. */
++              symbol_conf.keep_exited_threads = true;
++      }
++
+       if (perf_data__is_pipe(data))
+               return 0;
+diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h
+index 2b2fb9e224b00..6040286e07a65 100644
+--- a/tools/perf/util/symbol_conf.h
++++ b/tools/perf/util/symbol_conf.h
+@@ -43,7 +43,8 @@ struct symbol_conf {
+                       disable_add2line_warn,
+                       buildid_mmap2,
+                       guest_code,
+-                      lazy_load_kernel_maps;
++                      lazy_load_kernel_maps,
++                      keep_exited_threads;
+       const char      *vmlinux_name,
+                       *kallsyms_name,
+                       *source_prefix,
+diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
+index e79225a0ea46b..0df775b5c1105 100644
+--- a/tools/perf/util/thread.h
++++ b/tools/perf/util/thread.h
+@@ -36,13 +36,22 @@ struct thread_rb_node {
+ };
+ DECLARE_RC_STRUCT(thread) {
++      /** @maps: mmaps associated with this thread. */
+       struct maps             *maps;
+       pid_t                   pid_; /* Not all tools update this */
++      /** @tid: thread ID number unique to a machine. */
+       pid_t                   tid;
++      /** @ppid: parent process of the process this thread belongs to. */
+       pid_t                   ppid;
+       int                     cpu;
+       int                     guest_cpu; /* For QEMU thread */
+       refcount_t              refcnt;
++      /**
++       * @exited: Has the thread had an exit event. Such threads are usually
++       * removed from the machine's threads but some events/tools require
++       * access to dead threads.
++       */
++      bool                    exited;
+       bool                    comm_set;
+       int                     comm_len;
+       struct list_head        namespaces_list;
+@@ -189,6 +198,11 @@ static inline refcount_t *thread__refcnt(struct thread *thread)
+       return &RC_CHK_ACCESS(thread)->refcnt;
+ }
++static inline void thread__set_exited(struct thread *thread, bool exited)
++{
++      RC_CHK_ACCESS(thread)->exited = exited;
++}
++
+ static inline bool thread__comm_set(const struct thread *thread)
+ {
+       return RC_CHK_ACCESS(thread)->comm_set;
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-maps-move-symbol-maps-functions-to-maps.c.patch b/queue-6.6/perf-maps-move-symbol-maps-functions-to-maps.c.patch
new file mode 100644 (file)
index 0000000..9bafec3
--- /dev/null
@@ -0,0 +1,634 @@
+From 8776761fe4c1cbbdb3f9c216aed63de509f6649e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Nov 2023 14:08:25 -0800
+Subject: perf maps: Move symbol maps functions to maps.c
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 0f6ab6a3fb7e380a1277f8288f315724ed517114 ]
+
+Move the find and certain other symbol maps__* functions to maps.c for
+better abstraction.
+
+Signed-off-by: Ian Rogers <irogers@google.com>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Changbin Du <changbin.du@huawei.com>
+Cc: Colin Ian King <colin.i.king@gmail.com>
+Cc: Dmitrii Dolgov <9erthalion6@gmail.com>
+Cc: German Gomez <german.gomez@arm.com>
+Cc: Guilherme Amadio <amadio@gentoo.org>
+Cc: Huacai Chen <chenhuacai@kernel.org>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: K Prateek Nayak <kprateek.nayak@amd.com>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: Li Dong <lidong@vivo.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Cc: Miguel Ojeda <ojeda@kernel.org>
+Cc: Ming Wang <wangming01@loongson.cn>
+Cc: Nick Terrell <terrelln@fb.com>
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Sandipan Das <sandipan.das@amd.com>
+Cc: Sean Christopherson <seanjc@google.com>
+Cc: Steinar H. Gunderson <sesse@google.com>
+Cc: Vincent Whitchurch <vincent.whitchurch@axis.com>
+Cc: Wenyu Liu <liuwenyu7@huawei.com>
+Cc: Yang Jihong <yangjihong1@huawei.com>
+Link: https://lore.kernel.org/r/20231127220902.1315692-14-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: 25626e19ae6d ("perf symbols: Fix ownership of string in dso__load_vmlinux()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/maps.c   | 238 +++++++++++++++++++++++++++++++++++++
+ tools/perf/util/maps.h   |  12 ++
+ tools/perf/util/symbol.c | 248 ---------------------------------------
+ tools/perf/util/symbol.h |   1 -
+ 4 files changed, 250 insertions(+), 249 deletions(-)
+
+diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c
+index 233438c95b531..9a011aed4b754 100644
+--- a/tools/perf/util/maps.c
++++ b/tools/perf/util/maps.c
+@@ -475,3 +475,241 @@ struct map_rb_node *map_rb_node__next(struct map_rb_node *node)
+       return rb_entry(next, struct map_rb_node, rb_node);
+ }
++
++static int map__strcmp(const void *a, const void *b)
++{
++      const struct map *map_a = *(const struct map **)a;
++      const struct map *map_b = *(const struct map **)b;
++      const struct dso *dso_a = map__dso(map_a);
++      const struct dso *dso_b = map__dso(map_b);
++      int ret = strcmp(dso_a->short_name, dso_b->short_name);
++
++      if (ret == 0 && map_a != map_b) {
++              /*
++               * Ensure distinct but name equal maps have an order in part to
++               * aid reference counting.
++               */
++              ret = (int)map__start(map_a) - (int)map__start(map_b);
++              if (ret == 0)
++                      ret = (int)((intptr_t)map_a - (intptr_t)map_b);
++      }
++
++      return ret;
++}
++
++static int map__strcmp_name(const void *name, const void *b)
++{
++      const struct dso *dso = map__dso(*(const struct map **)b);
++
++      return strcmp(name, dso->short_name);
++}
++
++void __maps__sort_by_name(struct maps *maps)
++{
++      qsort(maps__maps_by_name(maps), maps__nr_maps(maps), sizeof(struct map *), map__strcmp);
++}
++
++static int map__groups__sort_by_name_from_rbtree(struct maps *maps)
++{
++      struct map_rb_node *rb_node;
++      struct map **maps_by_name = realloc(maps__maps_by_name(maps),
++                                          maps__nr_maps(maps) * sizeof(struct map *));
++      int i = 0;
++
++      if (maps_by_name == NULL)
++              return -1;
++
++      up_read(maps__lock(maps));
++      down_write(maps__lock(maps));
++
++      RC_CHK_ACCESS(maps)->maps_by_name = maps_by_name;
++      RC_CHK_ACCESS(maps)->nr_maps_allocated = maps__nr_maps(maps);
++
++      maps__for_each_entry(maps, rb_node)
++              maps_by_name[i++] = map__get(rb_node->map);
++
++      __maps__sort_by_name(maps);
++
++      up_write(maps__lock(maps));
++      down_read(maps__lock(maps));
++
++      return 0;
++}
++
++static struct map *__maps__find_by_name(struct maps *maps, const char *name)
++{
++      struct map **mapp;
++
++      if (maps__maps_by_name(maps) == NULL &&
++          map__groups__sort_by_name_from_rbtree(maps))
++              return NULL;
++
++      mapp = bsearch(name, maps__maps_by_name(maps), maps__nr_maps(maps),
++                     sizeof(*mapp), map__strcmp_name);
++      if (mapp)
++              return *mapp;
++      return NULL;
++}
++
++struct map *maps__find_by_name(struct maps *maps, const char *name)
++{
++      struct map_rb_node *rb_node;
++      struct map *map;
++
++      down_read(maps__lock(maps));
++
++
++      if (RC_CHK_ACCESS(maps)->last_search_by_name) {
++              const struct dso *dso = map__dso(RC_CHK_ACCESS(maps)->last_search_by_name);
++
++              if (strcmp(dso->short_name, name) == 0) {
++                      map = RC_CHK_ACCESS(maps)->last_search_by_name;
++                      goto out_unlock;
++              }
++      }
++      /*
++       * If we have maps->maps_by_name, then the name isn't in the rbtree,
++       * as maps->maps_by_name mirrors the rbtree when lookups by name are
++       * made.
++       */
++      map = __maps__find_by_name(maps, name);
++      if (map || maps__maps_by_name(maps) != NULL)
++              goto out_unlock;
++
++      /* Fallback to traversing the rbtree... */
++      maps__for_each_entry(maps, rb_node) {
++              struct dso *dso;
++
++              map = rb_node->map;
++              dso = map__dso(map);
++              if (strcmp(dso->short_name, name) == 0) {
++                      RC_CHK_ACCESS(maps)->last_search_by_name = map;
++                      goto out_unlock;
++              }
++      }
++      map = NULL;
++
++out_unlock:
++      up_read(maps__lock(maps));
++      return map;
++}
++
++void maps__fixup_end(struct maps *maps)
++{
++      struct map_rb_node *prev = NULL, *curr;
++
++      down_write(maps__lock(maps));
++
++      maps__for_each_entry(maps, curr) {
++              if (prev != NULL && !map__end(prev->map))
++                      map__set_end(prev->map, map__start(curr->map));
++
++              prev = curr;
++      }
++
++      /*
++       * We still haven't the actual symbols, so guess the
++       * last map final address.
++       */
++      if (curr && !map__end(curr->map))
++              map__set_end(curr->map, ~0ULL);
++
++      up_write(maps__lock(maps));
++}
++
++/*
++ * Merges map into maps by splitting the new map within the existing map
++ * regions.
++ */
++int maps__merge_in(struct maps *kmaps, struct map *new_map)
++{
++      struct map_rb_node *rb_node;
++      LIST_HEAD(merged);
++      int err = 0;
++
++      maps__for_each_entry(kmaps, rb_node) {
++              struct map *old_map = rb_node->map;
++
++              /* no overload with this one */
++              if (map__end(new_map) < map__start(old_map) ||
++                  map__start(new_map) >= map__end(old_map))
++                      continue;
++
++              if (map__start(new_map) < map__start(old_map)) {
++                      /*
++                       * |new......
++                       *       |old....
++                       */
++                      if (map__end(new_map) < map__end(old_map)) {
++                              /*
++                               * |new......|     -> |new..|
++                               *       |old....| ->       |old....|
++                               */
++                              map__set_end(new_map, map__start(old_map));
++                      } else {
++                              /*
++                               * |new.............| -> |new..|       |new..|
++                               *       |old....|    ->       |old....|
++                               */
++                              struct map_list_node *m = map_list_node__new();
++
++                              if (!m) {
++                                      err = -ENOMEM;
++                                      goto out;
++                              }
++
++                              m->map = map__clone(new_map);
++                              if (!m->map) {
++                                      free(m);
++                                      err = -ENOMEM;
++                                      goto out;
++                              }
++
++                              map__set_end(m->map, map__start(old_map));
++                              list_add_tail(&m->node, &merged);
++                              map__add_pgoff(new_map, map__end(old_map) - map__start(new_map));
++                              map__set_start(new_map, map__end(old_map));
++                      }
++              } else {
++                      /*
++                       *      |new......
++                       * |old....
++                       */
++                      if (map__end(new_map) < map__end(old_map)) {
++                              /*
++                               *      |new..|   -> x
++                               * |old.........| -> |old.........|
++                               */
++                              map__put(new_map);
++                              new_map = NULL;
++                              break;
++                      } else {
++                              /*
++                               *      |new......| ->         |new...|
++                               * |old....|        -> |old....|
++                               */
++                              map__add_pgoff(new_map, map__end(old_map) - map__start(new_map));
++                              map__set_start(new_map, map__end(old_map));
++                      }
++              }
++      }
++
++out:
++      while (!list_empty(&merged)) {
++              struct map_list_node *old_node;
++
++              old_node = list_entry(merged.next, struct map_list_node, node);
++              list_del_init(&old_node->node);
++              if (!err)
++                      err = maps__insert(kmaps, old_node->map);
++              map__put(old_node->map);
++              free(old_node);
++      }
++
++      if (new_map) {
++              if (!err)
++                      err = maps__insert(kmaps, new_map);
++              map__put(new_map);
++      }
++      return err;
++}
+diff --git a/tools/perf/util/maps.h b/tools/perf/util/maps.h
+index 83144e0645ed4..a689149be8c43 100644
+--- a/tools/perf/util/maps.h
++++ b/tools/perf/util/maps.h
+@@ -21,6 +21,16 @@ struct map_rb_node {
+       struct map *map;
+ };
++struct map_list_node {
++      struct list_head node;
++      struct map *map;
++};
++
++static inline struct map_list_node *map_list_node__new(void)
++{
++      return malloc(sizeof(struct map_list_node));
++}
++
+ struct map_rb_node *maps__first(struct maps *maps);
+ struct map_rb_node *map_rb_node__next(struct map_rb_node *node);
+ struct map_rb_node *maps__find_node(struct maps *maps, struct map *map);
+@@ -133,4 +143,6 @@ int maps__merge_in(struct maps *kmaps, struct map *new_map);
+ void __maps__sort_by_name(struct maps *maps);
++void maps__fixup_end(struct maps *maps);
++
+ #endif // __PERF_MAPS_H
+diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
+index 3f36675b7c8ff..1976af974a371 100644
+--- a/tools/perf/util/symbol.c
++++ b/tools/perf/util/symbol.c
+@@ -48,11 +48,6 @@ static bool symbol__is_idle(const char *name);
+ int vmlinux_path__nr_entries;
+ char **vmlinux_path;
+-struct map_list_node {
+-      struct list_head node;
+-      struct map *map;
+-};
+-
+ struct symbol_conf symbol_conf = {
+       .nanosecs               = false,
+       .use_modules            = true,
+@@ -90,11 +85,6 @@ static enum dso_binary_type binary_type_symtab[] = {
+ #define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab)
+-static struct map_list_node *map_list_node__new(void)
+-{
+-      return malloc(sizeof(struct map_list_node));
+-}
+-
+ static bool symbol_type__filter(char symbol_type)
+ {
+       symbol_type = toupper(symbol_type);
+@@ -271,29 +261,6 @@ void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms)
+               curr->end = roundup(curr->start, 4096) + 4096;
+ }
+-void maps__fixup_end(struct maps *maps)
+-{
+-      struct map_rb_node *prev = NULL, *curr;
+-
+-      down_write(maps__lock(maps));
+-
+-      maps__for_each_entry(maps, curr) {
+-              if (prev != NULL && !map__end(prev->map))
+-                      map__set_end(prev->map, map__start(curr->map));
+-
+-              prev = curr;
+-      }
+-
+-      /*
+-       * We still haven't the actual symbols, so guess the
+-       * last map final address.
+-       */
+-      if (curr && !map__end(curr->map))
+-              map__set_end(curr->map, ~0ULL);
+-
+-      up_write(maps__lock(maps));
+-}
+-
+ struct symbol *symbol__new(u64 start, u64 len, u8 binding, u8 type, const char *name)
+ {
+       size_t namelen = strlen(name) + 1;
+@@ -1271,103 +1238,6 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
+       return 0;
+ }
+-/*
+- * Merges map into maps by splitting the new map within the existing map
+- * regions.
+- */
+-int maps__merge_in(struct maps *kmaps, struct map *new_map)
+-{
+-      struct map_rb_node *rb_node;
+-      LIST_HEAD(merged);
+-      int err = 0;
+-
+-      maps__for_each_entry(kmaps, rb_node) {
+-              struct map *old_map = rb_node->map;
+-
+-              /* no overload with this one */
+-              if (map__end(new_map) < map__start(old_map) ||
+-                  map__start(new_map) >= map__end(old_map))
+-                      continue;
+-
+-              if (map__start(new_map) < map__start(old_map)) {
+-                      /*
+-                       * |new......
+-                       *       |old....
+-                       */
+-                      if (map__end(new_map) < map__end(old_map)) {
+-                              /*
+-                               * |new......|     -> |new..|
+-                               *       |old....| ->       |old....|
+-                               */
+-                              map__set_end(new_map, map__start(old_map));
+-                      } else {
+-                              /*
+-                               * |new.............| -> |new..|       |new..|
+-                               *       |old....|    ->       |old....|
+-                               */
+-                              struct map_list_node *m = map_list_node__new();
+-
+-                              if (!m) {
+-                                      err = -ENOMEM;
+-                                      goto out;
+-                              }
+-
+-                              m->map = map__clone(new_map);
+-                              if (!m->map) {
+-                                      free(m);
+-                                      err = -ENOMEM;
+-                                      goto out;
+-                              }
+-
+-                              map__set_end(m->map, map__start(old_map));
+-                              list_add_tail(&m->node, &merged);
+-                              map__add_pgoff(new_map, map__end(old_map) - map__start(new_map));
+-                              map__set_start(new_map, map__end(old_map));
+-                      }
+-              } else {
+-                      /*
+-                       *      |new......
+-                       * |old....
+-                       */
+-                      if (map__end(new_map) < map__end(old_map)) {
+-                              /*
+-                               *      |new..|   -> x
+-                               * |old.........| -> |old.........|
+-                               */
+-                              map__put(new_map);
+-                              new_map = NULL;
+-                              break;
+-                      } else {
+-                              /*
+-                               *      |new......| ->         |new...|
+-                               * |old....|        -> |old....|
+-                               */
+-                              map__add_pgoff(new_map, map__end(old_map) - map__start(new_map));
+-                              map__set_start(new_map, map__end(old_map));
+-                      }
+-              }
+-      }
+-
+-out:
+-      while (!list_empty(&merged)) {
+-              struct map_list_node *old_node;
+-
+-              old_node = list_entry(merged.next, struct map_list_node, node);
+-              list_del_init(&old_node->node);
+-              if (!err)
+-                      err = maps__insert(kmaps, old_node->map);
+-              map__put(old_node->map);
+-              free(old_node);
+-      }
+-
+-      if (new_map) {
+-              if (!err)
+-                      err = maps__insert(kmaps, new_map);
+-              map__put(new_map);
+-      }
+-      return err;
+-}
+-
+ static int dso__load_kcore(struct dso *dso, struct map *map,
+                          const char *kallsyms_filename)
+ {
+@@ -2065,124 +1935,6 @@ int dso__load(struct dso *dso, struct map *map)
+       return ret;
+ }
+-static int map__strcmp(const void *a, const void *b)
+-{
+-      const struct map *map_a = *(const struct map **)a;
+-      const struct map *map_b = *(const struct map **)b;
+-      const struct dso *dso_a = map__dso(map_a);
+-      const struct dso *dso_b = map__dso(map_b);
+-      int ret = strcmp(dso_a->short_name, dso_b->short_name);
+-
+-      if (ret == 0 && map_a != map_b) {
+-              /*
+-               * Ensure distinct but name equal maps have an order in part to
+-               * aid reference counting.
+-               */
+-              ret = (int)map__start(map_a) - (int)map__start(map_b);
+-              if (ret == 0)
+-                      ret = (int)((intptr_t)map_a - (intptr_t)map_b);
+-      }
+-
+-      return ret;
+-}
+-
+-static int map__strcmp_name(const void *name, const void *b)
+-{
+-      const struct dso *dso = map__dso(*(const struct map **)b);
+-
+-      return strcmp(name, dso->short_name);
+-}
+-
+-void __maps__sort_by_name(struct maps *maps)
+-{
+-      qsort(maps__maps_by_name(maps), maps__nr_maps(maps), sizeof(struct map *), map__strcmp);
+-}
+-
+-static int map__groups__sort_by_name_from_rbtree(struct maps *maps)
+-{
+-      struct map_rb_node *rb_node;
+-      struct map **maps_by_name = realloc(maps__maps_by_name(maps),
+-                                          maps__nr_maps(maps) * sizeof(struct map *));
+-      int i = 0;
+-
+-      if (maps_by_name == NULL)
+-              return -1;
+-
+-      up_read(maps__lock(maps));
+-      down_write(maps__lock(maps));
+-
+-      RC_CHK_ACCESS(maps)->maps_by_name = maps_by_name;
+-      RC_CHK_ACCESS(maps)->nr_maps_allocated = maps__nr_maps(maps);
+-
+-      maps__for_each_entry(maps, rb_node)
+-              maps_by_name[i++] = map__get(rb_node->map);
+-
+-      __maps__sort_by_name(maps);
+-
+-      up_write(maps__lock(maps));
+-      down_read(maps__lock(maps));
+-
+-      return 0;
+-}
+-
+-static struct map *__maps__find_by_name(struct maps *maps, const char *name)
+-{
+-      struct map **mapp;
+-
+-      if (maps__maps_by_name(maps) == NULL &&
+-          map__groups__sort_by_name_from_rbtree(maps))
+-              return NULL;
+-
+-      mapp = bsearch(name, maps__maps_by_name(maps), maps__nr_maps(maps),
+-                     sizeof(*mapp), map__strcmp_name);
+-      if (mapp)
+-              return *mapp;
+-      return NULL;
+-}
+-
+-struct map *maps__find_by_name(struct maps *maps, const char *name)
+-{
+-      struct map_rb_node *rb_node;
+-      struct map *map;
+-
+-      down_read(maps__lock(maps));
+-
+-
+-      if (RC_CHK_ACCESS(maps)->last_search_by_name) {
+-              const struct dso *dso = map__dso(RC_CHK_ACCESS(maps)->last_search_by_name);
+-
+-              if (strcmp(dso->short_name, name) == 0) {
+-                      map = RC_CHK_ACCESS(maps)->last_search_by_name;
+-                      goto out_unlock;
+-              }
+-      }
+-      /*
+-       * If we have maps->maps_by_name, then the name isn't in the rbtree,
+-       * as maps->maps_by_name mirrors the rbtree when lookups by name are
+-       * made.
+-       */
+-      map = __maps__find_by_name(maps, name);
+-      if (map || maps__maps_by_name(maps) != NULL)
+-              goto out_unlock;
+-
+-      /* Fallback to traversing the rbtree... */
+-      maps__for_each_entry(maps, rb_node) {
+-              struct dso *dso;
+-
+-              map = rb_node->map;
+-              dso = map__dso(map);
+-              if (strcmp(dso->short_name, name) == 0) {
+-                      RC_CHK_ACCESS(maps)->last_search_by_name = map;
+-                      goto out_unlock;
+-              }
+-      }
+-      map = NULL;
+-
+-out_unlock:
+-      up_read(maps__lock(maps));
+-      return map;
+-}
+-
+ int dso__load_vmlinux(struct dso *dso, struct map *map,
+                     const char *vmlinux, bool vmlinux_allocated)
+ {
+diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
+index af87c46b3f89e..071837ddce2ac 100644
+--- a/tools/perf/util/symbol.h
++++ b/tools/perf/util/symbol.h
+@@ -189,7 +189,6 @@ void __symbols__insert(struct rb_root_cached *symbols, struct symbol *sym,
+ void symbols__insert(struct rb_root_cached *symbols, struct symbol *sym);
+ void symbols__fixup_duplicate(struct rb_root_cached *symbols);
+ void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms);
+-void maps__fixup_end(struct maps *maps);
+ typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data);
+ int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-pmu-assume-sysfs-events-are-always-the-same-cas.patch b/queue-6.6/perf-pmu-assume-sysfs-events-are-always-the-same-cas.patch
new file mode 100644 (file)
index 0000000..448fdb8
--- /dev/null
@@ -0,0 +1,126 @@
+From db4d1851701d20df07c47e81fcef09deb86df93b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 May 2024 14:35:07 -0700
+Subject: perf pmu: Assume sysfs events are always the same case
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 7b6dd7a923281a7ccb980a0f768d6926721eb3cc ]
+
+Perf event names aren't case sensitive. For sysfs events the entire
+directory of events is read then iterated comparing names in a case
+insensitive way, most often to see if an event is present.
+
+Consider:
+
+  $ perf stat -e inst_retired.any true
+
+The event inst_retired.any may be present in any PMU, so every PMU's
+sysfs events are loaded and then searched with strcasecmp to see if
+any match. This event is only present on the cpu PMU as a JSON event
+so a lot of events were loaded from sysfs unnecessarily just to prove
+an event didn't exist there.
+
+This change avoids loading all the events by assuming sysfs event
+names are always either lower or uppercase. It uses file exists and
+only loads the events when the desired event is present.
+
+For the example above, the number of openat calls measured by 'perf
+trace' on a tigerlake laptop goes from 325 down to 255. The reduction
+will be larger for machines with many PMUs, particularly replicated
+uncore PMUs.
+
+Ensure pmu_aliases_parse() is called before all uses of the aliases
+list, but remove some "pmu->sysfs_aliases_loaded" tests as they are now
+part of the function.
+
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Randy Dunlap <rdunlap@infradead.org>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Thomas Richter <tmricht@linux.ibm.com>
+Link: https://lore.kernel.org/r/20240502213507.2339733-7-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/pmu.c | 31 ++++++++++++++++++++++++++-----
+ 1 file changed, 26 insertions(+), 5 deletions(-)
+
+diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
+index 0b1c380fce901..f767f43fd3c79 100644
+--- a/tools/perf/util/pmu.c
++++ b/tools/perf/util/pmu.c
+@@ -425,9 +425,30 @@ static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu,
+ {
+       struct perf_pmu_alias *alias;
+-      if (load && !pmu->sysfs_aliases_loaded)
+-              pmu_aliases_parse(pmu);
++      if (load && !pmu->sysfs_aliases_loaded) {
++              bool has_sysfs_event;
++              char event_file_name[FILENAME_MAX + 8];
++              /*
++               * Test if alias/event 'name' exists in the PMU's sysfs/events
++               * directory. If not skip parsing the sysfs aliases. Sysfs event
++               * name must be all lower or all upper case.
++               */
++              scnprintf(event_file_name, sizeof(event_file_name), "events/%s", name);
++              for (size_t i = 7, n = 7 + strlen(name); i < n; i++)
++                      event_file_name[i] = tolower(event_file_name[i]);
++
++              has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name);
++              if (!has_sysfs_event) {
++                      for (size_t i = 7, n = 7 + strlen(name); i < n; i++)
++                              event_file_name[i] = toupper(event_file_name[i]);
++
++                      has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name);
++              }
++              if (has_sysfs_event)
++                      pmu_aliases_parse(pmu);
++
++      }
+       list_for_each_entry(alias, &pmu->aliases, list) {
+               if (!strcasecmp(alias->name, name))
+                       return alias;
+@@ -1627,9 +1648,7 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
+ {
+       size_t nr;
+-      if (!pmu->sysfs_aliases_loaded)
+-              pmu_aliases_parse(pmu);
+-
++      pmu_aliases_parse(pmu);
+       nr = pmu->sysfs_aliases;
+       if (pmu->cpu_aliases_added)
+@@ -1688,6 +1707,7 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
+       struct strbuf sb;
+       strbuf_init(&sb, /*hint=*/ 0);
++      pmu_aliases_parse(pmu);
+       pmu_add_cpu_aliases(pmu);
+       list_for_each_entry(event, &pmu->aliases, list) {
+               size_t buf_used;
+@@ -2089,6 +2109,7 @@ const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config)
+       if (!pmu)
+               return NULL;
++      pmu_aliases_parse(pmu);
+       pmu_add_cpu_aliases(pmu);
+       list_for_each_entry(event, &pmu->aliases, list) {
+               struct perf_event_attr attr = {.config = 0,};
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-pmu-compat-supports-regular-expression-matching.patch b/queue-6.6/perf-pmu-compat-supports-regular-expression-matching.patch
new file mode 100644 (file)
index 0000000..1cd94a4
--- /dev/null
@@ -0,0 +1,110 @@
+From 7412db8257d232300a3fd93c28bc7b5291268542 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Sep 2023 13:59:45 +0800
+Subject: perf pmu: "Compat" supports regular expression matching identifiers
+
+From: Jing Zhang <renyu.zj@linux.alibaba.com>
+
+[ Upstream commit 2879ff36f5ed80deec5f9d82a7a4107f2347630e ]
+
+The jevent "Compat" is used for uncore PMU alias or metric definitions.
+
+The same PMU driver has different PMU identifiers due to different
+hardware versions and types, but they may have some common PMU event.
+Since a Compat value can only match one identifier, when adding the
+same event alias to PMUs with different identifiers, each identifier
+needs to be defined once, which is not streamlined enough.
+
+So let "Compat" support using regular expression to match identifiers
+for uncore PMU alias. For example, if the "Compat" value is set to
+"43401|43c01", it would be able to match PMU identifiers such as "43401"
+or "43c01", which correspond to CMN600_r0p0 or CMN700_r0p0.
+
+Signed-off-by: Jing Zhang <renyu.zj@linux.alibaba.com>
+Reviewed-by: Ian Rogers <irogers@google.com>
+Tested-by: Ian Rogers <irogers@google.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: Mike Leach <mike.leach@linaro.org>
+Cc: Shuai Xue <xueshuai@linux.alibaba.com>
+Cc: Zhuo Song <zhuo.song@linux.alibaba.com>
+Cc: John Garry <john.g.garry@oracle.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-doc@vger.kernel.org
+Link: https://lore.kernel.org/r/1695794391-34817-2-git-send-email-renyu.zj@linux.alibaba.com
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/pmu.c | 27 +++++++++++++++++++++++++--
+ tools/perf/util/pmu.h |  1 +
+ 2 files changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
+index 72b7a1d3225f6..64b605a6060e2 100644
+--- a/tools/perf/util/pmu.c
++++ b/tools/perf/util/pmu.c
+@@ -28,6 +28,7 @@
+ #include "strbuf.h"
+ #include "fncache.h"
+ #include "util/evsel_config.h"
++#include <regex.h>
+ struct perf_pmu perf_pmu__fake = {
+       .name = "fake",
+@@ -874,6 +875,28 @@ static bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
+       return res;
+ }
++bool pmu_uncore_identifier_match(const char *compat, const char *id)
++{
++      regex_t re;
++      regmatch_t pmatch[1];
++      int match;
++
++      if (regcomp(&re, compat, REG_EXTENDED) != 0) {
++              /* Warn unable to generate match particular string. */
++              pr_info("Invalid regular expression %s\n", compat);
++              return false;
++      }
++
++      match = !regexec(&re, id, 1, pmatch, 0);
++      if (match) {
++              /* Ensure a full match. */
++              match = pmatch[0].rm_so == 0 && (size_t)pmatch[0].rm_eo == strlen(id);
++      }
++      regfree(&re);
++
++      return match;
++}
++
+ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
+                                       const struct pmu_events_table *table __maybe_unused,
+                                       void *vdata)
+@@ -914,8 +937,8 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
+       if (!pe->compat || !pe->pmu)
+               return 0;
+-      if (!strcmp(pmu->id, pe->compat) &&
+-          pmu_uncore_alias_match(pe->pmu, pmu->name)) {
++      if (pmu_uncore_alias_match(pe->pmu, pmu->name) &&
++                      pmu_uncore_identifier_match(pe->compat, pmu->id)) {
+               perf_pmu__new_alias(pmu,
+                               pe->name,
+                               pe->desc,
+diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
+index 45079f26abf60..c4b4fabe16edc 100644
+--- a/tools/perf/util/pmu.h
++++ b/tools/perf/util/pmu.h
+@@ -240,6 +240,7 @@ void pmu_add_cpu_aliases_table(struct perf_pmu *pmu,
+ char *perf_pmu__getcpuid(struct perf_pmu *pmu);
+ const struct pmu_events_table *pmu_events_table__find(void);
+ const struct pmu_metrics_table *pmu_metrics_table__find(void);
++bool pmu_uncore_identifier_match(const char *compat, const char *id);
+ int perf_pmu__convert_scale(const char *scale, char **end, double *sval);
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-pmu-count-sys-and-cpuid-json-events-separately.patch b/queue-6.6/perf-pmu-count-sys-and-cpuid-json-events-separately.patch
new file mode 100644 (file)
index 0000000..737b947
--- /dev/null
@@ -0,0 +1,202 @@
+From 4b4468c46d40c7374636e4324434ad6076f17ff8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 17:36:01 -0700
+Subject: perf pmu: Count sys and cpuid JSON events separately
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit d9c5f5f94c2d356fdf3503f7fcaf254512bc032d ]
+
+Sys events are eagerly loaded as each event has a compat option that may
+mean the event is or isn't associated with the PMU.
+
+These shouldn't be counted as loaded_json_events as that is used for
+JSON events matching the CPUID that may or may not have been loaded. The
+mismatch causes issues on ARM64 that uses sys events.
+
+Fixes: e6ff1eed3584362d ("perf pmu: Lazily add JSON events")
+Closes: https://lore.kernel.org/lkml/20240510024729.1075732-1-justin.he@arm.com/
+Reported-by: Jia He <justin.he@arm.com>
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: John Garry <john.g.garry@oracle.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240511003601.2666907-1-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/pmu.c | 70 ++++++++++++++++++++++++++++++-------------
+ tools/perf/util/pmu.h |  6 ++--
+ 2 files changed, 53 insertions(+), 23 deletions(-)
+
+diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
+index f767f43fd3c79..27393e4327922 100644
+--- a/tools/perf/util/pmu.c
++++ b/tools/perf/util/pmu.c
+@@ -36,6 +36,18 @@ struct perf_pmu perf_pmu__fake = {
+ #define UNIT_MAX_LEN  31 /* max length for event unit name */
++enum event_source {
++      /* An event loaded from /sys/devices/<pmu>/events. */
++      EVENT_SRC_SYSFS,
++      /* An event loaded from a CPUID matched json file. */
++      EVENT_SRC_CPU_JSON,
++      /*
++       * An event loaded from a /sys/devices/<pmu>/identifier matched json
++       * file.
++       */
++      EVENT_SRC_SYS_JSON,
++};
++
+ /**
+  * struct perf_pmu_alias - An event either read from sysfs or builtin in
+  * pmu-events.c, created by parsing the pmu-events json files.
+@@ -521,7 +533,7 @@ static int update_alias(const struct pmu_event *pe,
+ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
+                               const char *desc, const char *val, FILE *val_fd,
+-                              const struct pmu_event *pe)
++                              const struct pmu_event *pe, enum event_source src)
+ {
+       struct perf_pmu_alias *alias;
+       int ret;
+@@ -573,25 +585,30 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
+               }
+               snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
+       }
+-      if (!pe) {
+-              /* Update an event from sysfs with json data. */
+-              struct update_alias_data data = {
+-                      .pmu = pmu,
+-                      .alias = alias,
+-              };
+-
++      switch (src) {
++      default:
++      case EVENT_SRC_SYSFS:
+               alias->from_sysfs = true;
+               if (pmu->events_table) {
++                      /* Update an event from sysfs with json data. */
++                      struct update_alias_data data = {
++                              .pmu = pmu,
++                              .alias = alias,
++                      };
+                       if (pmu_events_table__find_event(pmu->events_table, pmu, name,
+                                                        update_alias, &data) == 0)
+-                              pmu->loaded_json_aliases++;
++                              pmu->cpu_json_aliases++;
+               }
+-      }
+-
+-      if (!pe)
+               pmu->sysfs_aliases++;
+-      else
+-              pmu->loaded_json_aliases++;
++              break;
++      case  EVENT_SRC_CPU_JSON:
++              pmu->cpu_json_aliases++;
++              break;
++      case  EVENT_SRC_SYS_JSON:
++              pmu->sys_json_aliases++;
++              break;
++
++      }
+       list_add_tail(&alias->list, &pmu->aliases);
+       return 0;
+ }
+@@ -667,7 +684,8 @@ static int pmu_aliases_parse(struct perf_pmu *pmu)
+               }
+               if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL,
+-                                      /*val=*/ NULL, file, /*pe=*/ NULL) < 0)
++                                      /*val=*/ NULL, file, /*pe=*/ NULL,
++                                      EVENT_SRC_SYSFS) < 0)
+                       pr_debug("Cannot set up %s\n", name);
+               fclose(file);
+       }
+@@ -924,7 +942,8 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
+ {
+       struct perf_pmu *pmu = vdata;
+-      perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe);
++      perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL,
++                          pe, EVENT_SRC_CPU_JSON);
+       return 0;
+ }
+@@ -959,13 +978,14 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
+               return 0;
+       if (pmu_uncore_alias_match(pe->pmu, pmu->name) &&
+-                      pmu_uncore_identifier_match(pe->compat, pmu->id)) {
++          pmu_uncore_identifier_match(pe->compat, pmu->id)) {
+               perf_pmu__new_alias(pmu,
+                               pe->name,
+                               pe->desc,
+                               pe->event,
+                               /*val_fd=*/ NULL,
+-                              pe);
++                              pe,
++                              EVENT_SRC_SYS_JSON);
+       }
+       return 0;
+@@ -1055,6 +1075,12 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
+               pmu->id = pmu_id(name);
+       pmu->max_precise = pmu_max_precise(dirfd, pmu);
+       pmu->events_table = perf_pmu__find_events_table(pmu);
++      /*
++       * Load the sys json events/aliases when loading the PMU as each event
++       * may have a different compat regular expression. We therefore can't
++       * know the number of sys json events/aliases without computing the
++       * regular expressions for them all.
++       */
+       pmu_add_sys_aliases(pmu);
+       list_add_tail(&pmu->list, pmus);
+@@ -1649,12 +1675,14 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
+       size_t nr;
+       pmu_aliases_parse(pmu);
+-      nr = pmu->sysfs_aliases;
++      nr = pmu->sysfs_aliases + pmu->sys_json_aliases;;
+       if (pmu->cpu_aliases_added)
+-               nr += pmu->loaded_json_aliases;
++               nr += pmu->cpu_json_aliases;
+       else if (pmu->events_table)
+-              nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->loaded_json_aliases;
++              nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->cpu_json_aliases;
++      else
++              assert(pmu->cpu_json_aliases == 0);
+       return pmu->selectable ? nr + 1 : nr;
+ }
+diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
+index ed6693f991867..aca4238f06a65 100644
+--- a/tools/perf/util/pmu.h
++++ b/tools/perf/util/pmu.h
+@@ -120,8 +120,10 @@ struct perf_pmu {
+       const struct pmu_events_table *events_table;
+       /** @sysfs_aliases: Number of sysfs aliases loaded. */
+       uint32_t sysfs_aliases;
+-      /** @sysfs_aliases: Number of json event aliases loaded. */
+-      uint32_t loaded_json_aliases;
++      /** @cpu_json_aliases: Number of json event aliases loaded specific to the CPUID. */
++      uint32_t cpu_json_aliases;
++      /** @sys_json_aliases: Number of json event aliases loaded matching the PMU's identifier. */
++      uint32_t sys_json_aliases;
+       /** @sysfs_aliases_loaded: Are sysfs aliases loaded from disk? */
+       bool sysfs_aliases_loaded;
+       /**
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-pmu-move-pmu__find_core_pmu-to-pmus.c.patch b/queue-6.6/perf-pmu-move-pmu__find_core_pmu-to-pmus.c.patch
new file mode 100644 (file)
index 0000000..542aebd
--- /dev/null
@@ -0,0 +1,198 @@
+From 033b5433f23258485ef92495ca7d6b6e1bbe163e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Sep 2023 16:33:48 +0100
+Subject: perf pmu: Move pmu__find_core_pmu() to pmus.c
+
+From: James Clark <james.clark@arm.com>
+
+[ Upstream commit 3d0f5f456a5786573ba6a3358178c8db580e4b85 ]
+
+pmu__find_core_pmu() more logically belongs in pmus.c because it
+iterates over all PMUs, so move it to pmus.c
+
+At the same time rename it to perf_pmus__find_core_pmu() to match the
+naming convention in this file.
+
+list_prepare_entry() can't be used in perf_pmus__scan_core() anymore now
+that it's called from the same compilation unit. This is with -O2
+(specifically -O1 -ftree-vrp -finline-functions
+-finline-small-functions) which allow the bounds of the array
+access to be determined at compile time. list_prepare_entry() subtracts
+the offset of the 'list' member in struct perf_pmu from &core_pmus,
+which isn't a struct perf_pmu. The compiler sees that pmu results in
+&core_pmus - 8 and refuses to compile. At runtime this works because
+list_for_each_entry_continue() always adds the offset back again before
+dereferencing ->next, but it's technically undefined behavior. With
+-fsanitize=undefined an additional warning is generated.
+
+Using list_first_entry_or_null() to get the first entry here avoids
+doing &core_pmus - 8 but has the same result and fixes both the compile
+warning and the undefined behavior warning. There are other uses of
+list_prepare_entry() in pmus.c, but the compiler doesn't seem to be
+able to see that they can also be called with &core_pmus, so I won't
+change any at this time.
+
+Signed-off-by: James Clark <james.clark@arm.com>
+Reviewed-by: Ian Rogers <irogers@google.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Eduard Zingerman <eddyz87@gmail.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: Mike Leach <mike.leach@linaro.org>
+Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
+Cc: Haixin Yu <yuhaixin.yhx@linux.alibaba.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Link: https://lore.kernel.org/r/20230913153355.138331-2-james.clark@arm.com
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/arch/arm64/util/pmu.c |  6 +++---
+ tools/perf/tests/expr.c          |  2 +-
+ tools/perf/util/expr.c           |  2 +-
+ tools/perf/util/pmu.c            | 17 -----------------
+ tools/perf/util/pmu.h            |  2 +-
+ tools/perf/util/pmus.c           | 20 +++++++++++++++++++-
+ 6 files changed, 25 insertions(+), 24 deletions(-)
+
+diff --git a/tools/perf/arch/arm64/util/pmu.c b/tools/perf/arch/arm64/util/pmu.c
+index 615084eb88d8c..3d9330feebd28 100644
+--- a/tools/perf/arch/arm64/util/pmu.c
++++ b/tools/perf/arch/arm64/util/pmu.c
+@@ -10,7 +10,7 @@
+ const struct pmu_metrics_table *pmu_metrics_table__find(void)
+ {
+-      struct perf_pmu *pmu = pmu__find_core_pmu();
++      struct perf_pmu *pmu = perf_pmus__find_core_pmu();
+       if (pmu)
+               return perf_pmu__find_metrics_table(pmu);
+@@ -20,7 +20,7 @@ const struct pmu_metrics_table *pmu_metrics_table__find(void)
+ const struct pmu_events_table *pmu_events_table__find(void)
+ {
+-      struct perf_pmu *pmu = pmu__find_core_pmu();
++      struct perf_pmu *pmu = perf_pmus__find_core_pmu();
+       if (pmu)
+               return perf_pmu__find_events_table(pmu);
+@@ -32,7 +32,7 @@ double perf_pmu__cpu_slots_per_cycle(void)
+ {
+       char path[PATH_MAX];
+       unsigned long long slots = 0;
+-      struct perf_pmu *pmu = pmu__find_core_pmu();
++      struct perf_pmu *pmu = perf_pmus__find_core_pmu();
+       if (pmu) {
+               perf_pmu__pathname_scnprintf(path, sizeof(path),
+diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
+index b177d09078038..cea4a506197db 100644
+--- a/tools/perf/tests/expr.c
++++ b/tools/perf/tests/expr.c
+@@ -76,7 +76,7 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
+       struct expr_parse_ctx *ctx;
+       bool is_intel = false;
+       char strcmp_cpuid_buf[256];
+-      struct perf_pmu *pmu = pmu__find_core_pmu();
++      struct perf_pmu *pmu = perf_pmus__find_core_pmu();
+       char *cpuid = perf_pmu__getcpuid(pmu);
+       char *escaped_cpuid1, *escaped_cpuid2;
+diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c
+index 80cf2478f98fc..b8875aac8f870 100644
+--- a/tools/perf/util/expr.c
++++ b/tools/perf/util/expr.c
+@@ -527,7 +527,7 @@ double expr__strcmp_cpuid_str(const struct expr_parse_ctx *ctx __maybe_unused,
+                      bool compute_ids __maybe_unused, const char *test_id)
+ {
+       double ret;
+-      struct perf_pmu *pmu = pmu__find_core_pmu();
++      struct perf_pmu *pmu = perf_pmus__find_core_pmu();
+       char *cpuid = perf_pmu__getcpuid(pmu);
+       if (!cpuid)
+diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
+index 86bfdf5db2135..72b7a1d3225f6 100644
+--- a/tools/perf/util/pmu.c
++++ b/tools/perf/util/pmu.c
+@@ -2058,20 +2058,3 @@ void perf_pmu__delete(struct perf_pmu *pmu)
+       zfree(&pmu->id);
+       free(pmu);
+ }
+-
+-struct perf_pmu *pmu__find_core_pmu(void)
+-{
+-      struct perf_pmu *pmu = NULL;
+-
+-      while ((pmu = perf_pmus__scan_core(pmu))) {
+-              /*
+-               * The cpumap should cover all CPUs. Otherwise, some CPUs may
+-               * not support some events or have different event IDs.
+-               */
+-              if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu)
+-                      return NULL;
+-
+-              return pmu;
+-      }
+-      return NULL;
+-}
+diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
+index 6a4e170c61d6b..45079f26abf60 100644
+--- a/tools/perf/util/pmu.h
++++ b/tools/perf/util/pmu.h
+@@ -264,6 +264,6 @@ int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename,
+ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name);
+ struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus);
+ void perf_pmu__delete(struct perf_pmu *pmu);
+-struct perf_pmu *pmu__find_core_pmu(void);
++struct perf_pmu *perf_pmus__find_core_pmu(void);
+ #endif /* __PMU_H */
+diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c
+index 6631367c756fd..cec869cbe163a 100644
+--- a/tools/perf/util/pmus.c
++++ b/tools/perf/util/pmus.c
+@@ -10,6 +10,7 @@
+ #include <pthread.h>
+ #include <string.h>
+ #include <unistd.h>
++#include "cpumap.h"
+ #include "debug.h"
+ #include "evsel.h"
+ #include "pmus.h"
+@@ -268,7 +269,7 @@ struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu)
+ {
+       if (!pmu) {
+               pmu_read_sysfs(/*core_only=*/true);
+-              pmu = list_prepare_entry(pmu, &core_pmus, list);
++              return list_first_entry_or_null(&core_pmus, typeof(*pmu), list);
+       }
+       list_for_each_entry_continue(pmu, &core_pmus, list)
+               return pmu;
+@@ -592,3 +593,20 @@ struct perf_pmu *evsel__find_pmu(const struct evsel *evsel)
+       }
+       return pmu;
+ }
++
++struct perf_pmu *perf_pmus__find_core_pmu(void)
++{
++      struct perf_pmu *pmu = NULL;
++
++      while ((pmu = perf_pmus__scan_core(pmu))) {
++              /*
++               * The cpumap should cover all CPUs. Otherwise, some CPUs may
++               * not support some events or have different event IDs.
++               */
++              if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu)
++                      return NULL;
++
++              return pmu;
++      }
++      return NULL;
++}
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-probe-add-missing-libgen.h-header-needed-for-us.patch b/queue-6.6/perf-probe-add-missing-libgen.h-header-needed-for-us.patch
new file mode 100644 (file)
index 0000000..fe03efc
--- /dev/null
@@ -0,0 +1,53 @@
+From 74fcaddc6d1c6a2ca131224e5cbadab427c9826f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Mar 2024 11:13:30 -0300
+Subject: perf probe: Add missing libgen.h header needed for using basename()
+
+From: Arnaldo Carvalho de Melo <acme@redhat.com>
+
+[ Upstream commit 581037151910126a7934e369e4b6ac70eda9a703 ]
+
+This prototype is obtained indirectly, by luck, from some other header
+in probe-event.c in most systems, but recently exploded on alpine:edge:
+
+   8    13.39 alpine:edge                   : FAIL gcc version 13.2.1 20240309 (Alpine 13.2.1_git20240309)
+    util/probe-event.c: In function 'convert_exec_to_group':
+    util/probe-event.c:225:16: error: implicit declaration of function 'basename' [-Werror=implicit-function-declaration]
+      225 |         ptr1 = basename(exec_copy);
+          |                ^~~~~~~~
+    util/probe-event.c:225:14: error: assignment to 'char *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion]
+      225 |         ptr1 = basename(exec_copy);
+          |              ^
+    cc1: all warnings being treated as errors
+    make[3]: *** [/git/perf-6.8.0/tools/build/Makefile.build:158: util] Error 2
+
+Fix it by adding the libgen.h header where basename() is prototyped.
+
+Fixes: fb7345bbf7fad9bf ("perf probe: Support basic dwarf-based operations on uprobe events")
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Link: https://lore.kernel.org/lkml/
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/probe-event.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
+index 1a5b7fa459b23..4026cea9fc3a2 100644
+--- a/tools/perf/util/probe-event.c
++++ b/tools/perf/util/probe-event.c
+@@ -11,6 +11,7 @@
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <errno.h>
++#include <libgen.h>
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-record-delete-session-after-stopping-sideband-t.patch b/queue-6.6/perf-record-delete-session-after-stopping-sideband-t.patch
new file mode 100644 (file)
index 0000000..6bdaa93
--- /dev/null
@@ -0,0 +1,83 @@
+From d313e8e6b6b0467ae2a2e861c47bad3d2e927d26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Feb 2024 23:46:36 -0800
+Subject: perf record: Delete session after stopping sideband thread
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 88ce0106a1f603bf360cb397e8fe293f8298fabb ]
+
+The session has a header in it which contains a perf env with
+bpf_progs. The bpf_progs are accessed by the sideband thread and so
+the sideband thread must be stopped before the session is deleted, to
+avoid a use after free.  This error was detected by AddressSanitizer
+in the following:
+
+  ==2054673==ERROR: AddressSanitizer: heap-use-after-free on address 0x61d000161e00 at pc 0x55769289de54 bp 0x7f9df36d4ab0 sp 0x7f9df36d4aa8
+  READ of size 8 at 0x61d000161e00 thread T1
+      #0 0x55769289de53 in __perf_env__insert_bpf_prog_info util/env.c:42
+      #1 0x55769289dbb1 in perf_env__insert_bpf_prog_info util/env.c:29
+      #2 0x557692bbae29 in perf_env__add_bpf_info util/bpf-event.c:483
+      #3 0x557692bbb01a in bpf_event__sb_cb util/bpf-event.c:512
+      #4 0x5576928b75f4 in perf_evlist__poll_thread util/sideband_evlist.c:68
+      #5 0x7f9df96a63eb in start_thread nptl/pthread_create.c:444
+      #6 0x7f9df9726a4b in clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
+
+  0x61d000161e00 is located 384 bytes inside of 2136-byte region [0x61d000161c80,0x61d0001624d8)
+  freed by thread T0 here:
+      #0 0x7f9dfa6d7288 in __interceptor_free libsanitizer/asan/asan_malloc_linux.cpp:52
+      #1 0x557692978d50 in perf_session__delete util/session.c:319
+      #2 0x557692673959 in __cmd_record tools/perf/builtin-record.c:2884
+      #3 0x55769267a9f0 in cmd_record tools/perf/builtin-record.c:4259
+      #4 0x55769286710c in run_builtin tools/perf/perf.c:349
+      #5 0x557692867678 in handle_internal_command tools/perf/perf.c:402
+      #6 0x557692867a40 in run_argv tools/perf/perf.c:446
+      #7 0x557692867fae in main tools/perf/perf.c:562
+      #8 0x7f9df96456c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
+
+Fixes: 657ee5531903339b ("perf evlist: Introduce side band thread")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Disha Goel <disgoel@linux.ibm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: K Prateek Nayak <kprateek.nayak@amd.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Song Liu <songliubraving@fb.com>
+Cc: Tim Chen <tim.c.chen@linux.intel.com>
+Cc: Yicong Yang <yangyicong@hisilicon.com>
+Link: https://lore.kernel.org/r/20240301074639.2260708-1-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-record.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
+index c40460e936ccd..ea80bf4dc4343 100644
+--- a/tools/perf/builtin-record.c
++++ b/tools/perf/builtin-record.c
+@@ -2822,10 +2822,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
+       }
+ #endif
+       zstd_fini(&session->zstd_data);
+-      perf_session__delete(session);
+-
+       if (!opts->no_bpf_event)
+               evlist__stop_sb_thread(rec->sb_evlist);
++
++      perf_session__delete(session);
+       return status;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-record-fix-debug-message-placement-for-test-con.patch b/queue-6.6/perf-record-fix-debug-message-placement-for-test-con.patch
new file mode 100644 (file)
index 0000000..b8bde8f
--- /dev/null
@@ -0,0 +1,57 @@
+From 958d96e8b1a3c7a7adc5cbba51cebeb9fff48f7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Apr 2024 10:54:47 +0300
+Subject: perf record: Fix debug message placement for test consumption
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit 792bc998baf9ae17297b1f93b1edc3ca34a0b7e2 ]
+
+evlist__config() might mess up the debug output consumed by test
+"Test per-thread recording" in "Miscellaneous Intel PT testing".
+
+Move it out from between the debug prints:
+
+  "perf record opening and mmapping events" and
+  "perf record done opening and mmapping events"
+
+Fixes: da4062021e0e6da5 ("perf tools: Add debug messages and comments for testing")
+Closes: https://lore.kernel.org/linux-perf-users/ZhVfc5jYLarnGzKa@x1/
+Reported-by: Arnaldo Carvalho de Melo <acme@kernel.org>
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Link: https://lore.kernel.org/r/20240411075447.17306-1-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-record.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
+index 96a3e122655b7..b94ae33a343c2 100644
+--- a/tools/perf/builtin-record.c
++++ b/tools/perf/builtin-record.c
+@@ -1317,8 +1317,6 @@ static int record__open(struct record *rec)
+       struct record_opts *opts = &rec->opts;
+       int rc = 0;
+-      evlist__config(evlist, opts, &callchain_param);
+-
+       evlist__for_each_entry(evlist, pos) {
+ try_again:
+               if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) {
+@@ -2428,6 +2426,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
+       evlist__uniquify_name(rec->evlist);
++      evlist__config(rec->evlist, opts, &callchain_param);
++
+       /* Debug message used by test scripts */
+       pr_debug3("perf record opening and mmapping events\n");
+       if (record__open(rec) != 0) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-record-lazy-load-kernel-symbols.patch b/queue-6.6/perf-record-lazy-load-kernel-symbols.patch
new file mode 100644 (file)
index 0000000..1b4bb1f
--- /dev/null
@@ -0,0 +1,129 @@
+From 2ac5c718173e7a88dc3c2ab2ef77339cb40e3550 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 Nov 2023 10:56:44 -0700
+Subject: perf record: Lazy load kernel symbols
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 1a27fc01700fbff2f205000edf0d1d315b5f85cc ]
+
+Commit 5b7ba82a75915e73 ("perf symbols: Load kernel maps before using")
+changed it so that loading a kernel DSO would cause the symbols for the
+DSO to be eagerly loaded.
+
+For 'perf record' this is overhead as the symbols won't be used. Add a
+field to 'struct symbol_conf' to control the behavior and disable it for
+'perf record' and 'perf inject'.
+
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Ian Rogers <irogers@google.com>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Changbin Du <changbin.du@huawei.com>
+Cc: Colin Ian King <colin.i.king@gmail.com>
+Cc: Dmitrii Dolgov <9erthalion6@gmail.com>
+Cc: German Gomez <german.gomez@arm.com>
+Cc: Huacai Chen <chenhuacai@kernel.org>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: K Prateek Nayak <kprateek.nayak@amd.com>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: Li Dong <lidong@vivo.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Miguel Ojeda <ojeda@kernel.org>
+Cc: Ming Wang <wangming01@loongson.cn>
+Cc: Nick Terrell <terrelln@fb.com>
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Sandipan Das <sandipan.das@amd.com>
+Cc: Sean Christopherson <seanjc@google.com>
+Cc: Steinar H. Gunderson <sesse@google.com>
+Cc: Vincent Whitchurch <vincent.whitchurch@axis.com>
+Cc: Wenyu Liu <liuwenyu7@huawei.com>
+Cc: Yang Jihong <yangjihong1@huawei.com>
+Link: https://lore.kernel.org/r/20231102175735.2272696-3-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-inject.c   | 6 ++++++
+ tools/perf/builtin-record.c   | 2 ++
+ tools/perf/util/event.c       | 4 ++--
+ tools/perf/util/symbol_conf.h | 3 ++-
+ 4 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
+index c8cf2fdd9cff9..eb3ef5c24b662 100644
+--- a/tools/perf/builtin-inject.c
++++ b/tools/perf/builtin-inject.c
+@@ -2265,6 +2265,12 @@ int cmd_inject(int argc, const char **argv)
+               "perf inject [<options>]",
+               NULL
+       };
++
++      if (!inject.itrace_synth_opts.set) {
++              /* Disable eager loading of kernel symbols that adds overhead to perf inject. */
++              symbol_conf.lazy_load_kernel_maps = true;
++      }
++
+ #ifndef HAVE_JITDUMP
+       set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true);
+ #endif
+diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
+index ea80bf4dc4343..5c54fda63b581 100644
+--- a/tools/perf/builtin-record.c
++++ b/tools/perf/builtin-record.c
+@@ -3936,6 +3936,8 @@ int cmd_record(int argc, const char **argv)
+ # undef set_nobuild
+ #endif
++      /* Disable eager loading of kernel symbols that adds overhead to perf record. */
++      symbol_conf.lazy_load_kernel_maps = true;
+       rec->opts.affinity = PERF_AFFINITY_SYS;
+       rec->evlist = evlist__new();
+diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
+index 923c0fb151222..68f45e9e63b6e 100644
+--- a/tools/perf/util/event.c
++++ b/tools/perf/util/event.c
+@@ -617,13 +617,13 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
+       if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
+               al->level = 'k';
+               maps = machine__kernel_maps(machine);
+-              load_map = true;
++              load_map = !symbol_conf.lazy_load_kernel_maps;
+       } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
+               al->level = '.';
+       } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
+               al->level = 'g';
+               maps = machine__kernel_maps(machine);
+-              load_map = true;
++              load_map = !symbol_conf.lazy_load_kernel_maps;
+       } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
+               al->level = 'u';
+       } else {
+diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h
+index 0b589570d1d09..2b2fb9e224b00 100644
+--- a/tools/perf/util/symbol_conf.h
++++ b/tools/perf/util/symbol_conf.h
+@@ -42,7 +42,8 @@ struct symbol_conf {
+                       inline_name,
+                       disable_add2line_warn,
+                       buildid_mmap2,
+-                      guest_code;
++                      guest_code,
++                      lazy_load_kernel_maps;
+       const char      *vmlinux_name,
+                       *kallsyms_name,
+                       *source_prefix,
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-record-move-setting-tracking-events-before-reco.patch b/queue-6.6/perf-record-move-setting-tracking-events-before-reco.patch
new file mode 100644 (file)
index 0000000..9a310ce
--- /dev/null
@@ -0,0 +1,272 @@
+From 4c5f79c4f9c3168f0f72899a5b41905bca175657 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Sep 2023 02:33:37 +0000
+Subject: perf record: Move setting tracking events before
+ record__init_thread_masks()
+
+From: Yang Jihong <yangjihong1@huawei.com>
+
+[ Upstream commit 1285ab300d598ead593b190af65a16f4b0843c68 ]
+
+User space tasks can migrate between CPUs, so when tracing selected CPUs,
+sideband for all CPUs is needed. In this case set the cpu map of the evsel
+to all online CPUs. This may modify the original cpu map of the evlist.
+
+Therefore, need to check whether the preceding scenario exists before
+record__init_thread_masks().
+
+Dummy tracking has been set in record__open(), move it before
+record__init_thread_masks() and add a helper for unified processing.
+
+The sys_perf_event_open invoked is as follows:
+
+  # perf --debug verbose=3 record -e cpu-clock -D 100 true
+  <SNIP>
+  Opening: cpu-clock
+  ------------------------------------------------------------
+  perf_event_attr:
+    type                             1 (PERF_TYPE_SOFTWARE)
+    size                             136
+    config                           0 (PERF_COUNT_SW_CPU_CLOCK)
+    { sample_period, sample_freq }   4000
+    sample_type                      IP|TID|TIME|PERIOD|IDENTIFIER
+    read_format                      ID|LOST
+    disabled                         1
+    inherit                          1
+    freq                             1
+    sample_id_all                    1
+    exclude_guest                    1
+  ------------------------------------------------------------
+  sys_perf_event_open: pid 10318  cpu 0  group_fd -1  flags 0x8 = 5
+  sys_perf_event_open: pid 10318  cpu 1  group_fd -1  flags 0x8 = 6
+  sys_perf_event_open: pid 10318  cpu 2  group_fd -1  flags 0x8 = 7
+  sys_perf_event_open: pid 10318  cpu 3  group_fd -1  flags 0x8 = 9
+  sys_perf_event_open: pid 10318  cpu 4  group_fd -1  flags 0x8 = 10
+  sys_perf_event_open: pid 10318  cpu 5  group_fd -1  flags 0x8 = 11
+  sys_perf_event_open: pid 10318  cpu 6  group_fd -1  flags 0x8 = 12
+  sys_perf_event_open: pid 10318  cpu 7  group_fd -1  flags 0x8 = 13
+  Opening: dummy:u
+  ------------------------------------------------------------
+  perf_event_attr:
+    type                             1 (PERF_TYPE_SOFTWARE)
+    size                             136
+    config                           0x9 (PERF_COUNT_SW_DUMMY)
+    { sample_period, sample_freq }   1
+    sample_type                      IP|TID|TIME|IDENTIFIER
+    read_format                      ID|LOST
+    disabled                         1
+    inherit                          1
+    exclude_kernel                   1
+    exclude_hv                       1
+    mmap                             1
+    comm                             1
+    enable_on_exec                   1
+    task                             1
+    sample_id_all                    1
+    exclude_guest                    1
+    mmap2                            1
+    comm_exec                        1
+    ksymbol                          1
+    bpf_event                        1
+  ------------------------------------------------------------
+  sys_perf_event_open: pid 10318  cpu 0  group_fd -1  flags 0x8 = 14
+  sys_perf_event_open: pid 10318  cpu 1  group_fd -1  flags 0x8 = 15
+  sys_perf_event_open: pid 10318  cpu 2  group_fd -1  flags 0x8 = 16
+  sys_perf_event_open: pid 10318  cpu 3  group_fd -1  flags 0x8 = 17
+  sys_perf_event_open: pid 10318  cpu 4  group_fd -1  flags 0x8 = 18
+  sys_perf_event_open: pid 10318  cpu 5  group_fd -1  flags 0x8 = 19
+  sys_perf_event_open: pid 10318  cpu 6  group_fd -1  flags 0x8 = 20
+  sys_perf_event_open: pid 10318  cpu 7  group_fd -1  flags 0x8 = 21
+  <SNIP>
+
+'perf test' needs to update base-record & system-wide-dummy attr expected values
+for test-record-C0:
+
+1. Because a dummy sideband event is added to the sampling of specified
+   CPUs. When evlist contains evsel of different sample_type,
+   evlist__config() will change the default PERF_SAMPLE_ID bit to
+   PERF_SAMPLE_IDENTIFICATION bit.
+   The attr sample_type expected value of base-record and system-wide-dummy
+   in test-record-C0 needs to be updated.
+
+2. The perf record uses evlist__add_aux_dummy() instead of
+   evlist__add_dummy() to add a dummy event.
+   The expected value of system-wide-dummy attr needs to be updated.
+
+The 'perf test' result is as follows:
+
+  # ./perf test list  2>&1 | grep 'Setup struct perf_event_attr'
+   17: Setup struct perf_event_attr
+  # ./perf test 17
+   17: Setup struct perf_event_attr                                    : Ok
+
+Signed-off-by: Yang Jihong <yangjihong1@huawei.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Tested-by: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Anshuman Khandual <anshuman.khandual@arm.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Richter <tmricht@linux.ibm.com>
+Link: https://lore.kernel.org/r/20230904023340.12707-4-yangjihong1@huawei.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: 792bc998baf9 ("perf record: Fix debug message placement for test consumption")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-record.c             | 59 ++++++++++++++++---------
+ tools/perf/tests/attr/system-wide-dummy | 14 +++---
+ tools/perf/tests/attr/test-record-C0    |  4 +-
+ 3 files changed, 47 insertions(+), 30 deletions(-)
+
+diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
+index 16e21a3e883a7..96a3e122655b7 100644
+--- a/tools/perf/builtin-record.c
++++ b/tools/perf/builtin-record.c
+@@ -906,6 +906,37 @@ static int record__config_off_cpu(struct record *rec)
+       return off_cpu_prepare(rec->evlist, &rec->opts.target, &rec->opts);
+ }
++static int record__config_tracking_events(struct record *rec)
++{
++      struct record_opts *opts = &rec->opts;
++      struct evlist *evlist = rec->evlist;
++      struct evsel *evsel;
++
++      /*
++       * For initial_delay, system wide or a hybrid system, we need to add
++       * tracking event so that we can track PERF_RECORD_MMAP to cover the
++       * delay of waiting or event synthesis.
++       */
++      if (opts->target.initial_delay || target__has_cpu(&opts->target) ||
++          perf_pmus__num_core_pmus() > 1) {
++              evsel = evlist__findnew_tracking_event(evlist, false);
++              if (!evsel)
++                      return -ENOMEM;
++
++              /*
++               * Enable the tracking event when the process is forked for
++               * initial_delay, immediately for system wide.
++               */
++              if (opts->target.initial_delay && !evsel->immediate &&
++                  !target__has_cpu(&opts->target))
++                      evsel->core.attr.enable_on_exec = 1;
++              else
++                      evsel->immediate = 1;
++      }
++
++      return 0;
++}
++
+ static bool record__kcore_readable(struct machine *machine)
+ {
+       char kcore[PATH_MAX];
+@@ -1286,28 +1317,6 @@ static int record__open(struct record *rec)
+       struct record_opts *opts = &rec->opts;
+       int rc = 0;
+-      /*
+-       * For initial_delay, system wide or a hybrid system, we need to add a
+-       * dummy event so that we can track PERF_RECORD_MMAP to cover the delay
+-       * of waiting or event synthesis.
+-       */
+-      if (opts->target.initial_delay || target__has_cpu(&opts->target) ||
+-          perf_pmus__num_core_pmus() > 1) {
+-              pos = evlist__findnew_tracking_event(evlist, false);
+-              if (!pos)
+-                      return -ENOMEM;
+-
+-              /*
+-               * Enable the dummy event when the process is forked for
+-               * initial_delay, immediately for system wide.
+-               */
+-              if (opts->target.initial_delay && !pos->immediate &&
+-                  !target__has_cpu(&opts->target))
+-                      pos->core.attr.enable_on_exec = 1;
+-              else
+-                      pos->immediate = 1;
+-      }
+-
+       evlist__config(evlist, opts, &callchain_param);
+       evlist__for_each_entry(evlist, pos) {
+@@ -4171,6 +4180,12 @@ int cmd_record(int argc, const char **argv)
+               goto out;
+       }
++      err = record__config_tracking_events(rec);
++      if (err) {
++              pr_err("record__config_tracking_events failed, error %d\n", err);
++              goto out;
++      }
++
+       err = record__init_thread_masks(rec);
+       if (err) {
+               pr_err("Failed to initialize parallel data streaming masks\n");
+diff --git a/tools/perf/tests/attr/system-wide-dummy b/tools/perf/tests/attr/system-wide-dummy
+index 2f3e3eb728eb4..a1e1d6a263bf1 100644
+--- a/tools/perf/tests/attr/system-wide-dummy
++++ b/tools/perf/tests/attr/system-wide-dummy
+@@ -9,8 +9,10 @@ flags=8
+ type=1
+ size=136
+ config=9
+-sample_period=4000
+-sample_type=455
++sample_period=1
++# PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME |
++# PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER
++sample_type=65671
+ read_format=4|20
+ # Event will be enabled right away.
+ disabled=0
+@@ -18,12 +20,12 @@ inherit=1
+ pinned=0
+ exclusive=0
+ exclude_user=0
+-exclude_kernel=0
+-exclude_hv=0
++exclude_kernel=1
++exclude_hv=1
+ exclude_idle=0
+ mmap=1
+ comm=1
+-freq=1
++freq=0
+ inherit_stat=0
+ enable_on_exec=0
+ task=1
+@@ -32,7 +34,7 @@ precise_ip=0
+ mmap_data=0
+ sample_id_all=1
+ exclude_host=0
+-exclude_guest=0
++exclude_guest=1
+ exclude_callchain_kernel=0
+ exclude_callchain_user=0
+ mmap2=1
+diff --git a/tools/perf/tests/attr/test-record-C0 b/tools/perf/tests/attr/test-record-C0
+index 317730b906dd3..198e8429a1bf8 100644
+--- a/tools/perf/tests/attr/test-record-C0
++++ b/tools/perf/tests/attr/test-record-C0
+@@ -10,9 +10,9 @@ cpu=0
+ enable_on_exec=0
+ # PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME |
+-# PERF_SAMPLE_ID | PERF_SAMPLE_PERIOD
++# PERF_SAMPLE_PERIOD | PERF_SAMPLE_IDENTIFIER
+ # + PERF_SAMPLE_CPU added by -C 0
+-sample_type=455
++sample_type=65927
+ # Dummy event handles mmaps, comm and task.
+ mmap=0
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-report-avoid-segv-in-report__setup_sample_type.patch b/queue-6.6/perf-report-avoid-segv-in-report__setup_sample_type.patch
new file mode 100644 (file)
index 0000000..65449e9
--- /dev/null
@@ -0,0 +1,47 @@
+From 2b3bf735077fcfa01a14b4e1d96caaac0faed4e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 20:53:00 -0700
+Subject: perf report: Avoid SEGV in report__setup_sample_type()
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 45b4f402a6b782352c4bafcff682bfb01da9ca05 ]
+
+In some cases evsel->name is lazily initialized in evsel__name(). If not
+initialized passing NULL to strstr() leads to a SEGV.
+
+Fixes: ccb17caecfbd542f ("perf report: Set PERF_SAMPLE_DATA_SRC bit for Arm SPE event")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linux.dev>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240508035301.1554434-4-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-report.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
+index 169c64e9a01a8..2a8889c6d7f97 100644
+--- a/tools/perf/builtin-report.c
++++ b/tools/perf/builtin-report.c
+@@ -426,7 +426,7 @@ static int report__setup_sample_type(struct report *rep)
+                * compatibility, set the bit if it's an old perf data file.
+                */
+               evlist__for_each_entry(session->evlist, evsel) {
+-                      if (strstr(evsel->name, "arm_spe") &&
++                      if (strstr(evsel__name(evsel), "arm_spe") &&
+                               !(sample_type & PERF_SAMPLE_DATA_SRC)) {
+                               evsel->core.attr.sample_type |= PERF_SAMPLE_DATA_SRC;
+                               sample_type |= PERF_SAMPLE_DATA_SRC;
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-report-convert-to-the-global-annotation_options.patch b/queue-6.6/perf-report-convert-to-the-global-annotation_options.patch
new file mode 100644 (file)
index 0000000..31c46de
--- /dev/null
@@ -0,0 +1,150 @@
+From 4aba2b1c5d353adcc6523106ba83ed2b1ea96591 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 09:54:35 -0800
+Subject: perf report: Convert to the global annotation_options
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit 14953f038d6b30e3dc9d1aa4d4584ac505e5a8ec ]
+
+Use the global option and drop the local copy.
+
+Reviewed-by: Ian Rogers <irogers@google.com>
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20231128175441.721579-3-namhyung@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-report.c | 33 ++++++++++++++++-----------------
+ 1 file changed, 16 insertions(+), 17 deletions(-)
+
+diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
+index 749246817aed3..00354d16adb43 100644
+--- a/tools/perf/builtin-report.c
++++ b/tools/perf/builtin-report.c
+@@ -98,7 +98,6 @@ struct report {
+       bool                    skip_empty;
+       int                     max_stack;
+       struct perf_read_values show_threads_values;
+-      struct annotation_options annotation_opts;
+       const char              *pretty_printing_style;
+       const char              *cpu_list;
+       const char              *symbol_filter_str;
+@@ -542,7 +541,7 @@ static int evlist__tui_block_hists_browse(struct evlist *evlist, struct report *
+               ret = report__browse_block_hists(&rep->block_reports[i++].hist,
+                                                rep->min_percent, pos,
+                                                &rep->session->header.env,
+-                                               &rep->annotation_opts);
++                                               &annotate_opts);
+               if (ret != 0)
+                       return ret;
+       }
+@@ -670,7 +669,7 @@ static int report__browse_hists(struct report *rep)
+               }
+               ret = evlist__tui_browse_hists(evlist, help, NULL, rep->min_percent,
+-                                             &session->header.env, true, &rep->annotation_opts);
++                                             &session->header.env, true, &annotate_opts);
+               /*
+                * Usually "ret" is the last pressed key, and we only
+                * care if the key notifies us to switch data file.
+@@ -730,7 +729,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg)
+       if (rep->symbol_ipc && sym && !sym->annotate2) {
+               struct evsel *evsel = hists_to_evsel(he->hists);
+-              symbol__annotate2(&he->ms, evsel, &rep->annotation_opts, NULL);
++              symbol__annotate2(&he->ms, evsel, &annotate_opts, NULL);
+       }
+       return 0;
+@@ -1326,15 +1325,15 @@ int cmd_report(int argc, const char **argv)
+                  "list of cpus to profile"),
+       OPT_BOOLEAN('I', "show-info", &report.show_full_info,
+                   "Display extended information about perf.data file"),
+-      OPT_BOOLEAN(0, "source", &report.annotation_opts.annotate_src,
++      OPT_BOOLEAN(0, "source", &annotate_opts.annotate_src,
+                   "Interleave source code with assembly code (default)"),
+-      OPT_BOOLEAN(0, "asm-raw", &report.annotation_opts.show_asm_raw,
++      OPT_BOOLEAN(0, "asm-raw", &annotate_opts.show_asm_raw,
+                   "Display raw encoding of assembly instructions (default)"),
+       OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
+                  "Specify disassembler style (e.g. -M intel for intel syntax)"),
+-      OPT_STRING(0, "prefix", &report.annotation_opts.prefix, "prefix",
++      OPT_STRING(0, "prefix", &annotate_opts.prefix, "prefix",
+                   "Add prefix to source file path names in programs (with --prefix-strip)"),
+-      OPT_STRING(0, "prefix-strip", &report.annotation_opts.prefix_strip, "N",
++      OPT_STRING(0, "prefix-strip", &annotate_opts.prefix_strip, "N",
+                   "Strip first N entries of source file path name in programs (with --prefix)"),
+       OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
+                   "Show a column with the sum of periods"),
+@@ -1386,7 +1385,7 @@ int cmd_report(int argc, const char **argv)
+                  "Time span of interest (start,stop)"),
+       OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
+                   "Show inline function"),
+-      OPT_CALLBACK(0, "percent-type", &report.annotation_opts, "local-period",
++      OPT_CALLBACK(0, "percent-type", &annotate_opts, "local-period",
+                    "Set percent type local/global-period/hits",
+                    annotate_parse_percent_type),
+       OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs, "Show times in nanosecs"),
+@@ -1418,7 +1417,7 @@ int cmd_report(int argc, const char **argv)
+        */
+       symbol_conf.keep_exited_threads = true;
+-      annotation_options__init(&report.annotation_opts);
++      annotation_options__init(&annotate_opts);
+       ret = perf_config(report__config, &report);
+       if (ret)
+@@ -1437,13 +1436,13 @@ int cmd_report(int argc, const char **argv)
+       }
+       if (disassembler_style) {
+-              report.annotation_opts.disassembler_style = strdup(disassembler_style);
+-              if (!report.annotation_opts.disassembler_style)
++              annotate_opts.disassembler_style = strdup(disassembler_style);
++              if (!annotate_opts.disassembler_style)
+                       return -ENOMEM;
+       }
+       if (objdump_path) {
+-              report.annotation_opts.objdump_path = strdup(objdump_path);
+-              if (!report.annotation_opts.objdump_path)
++              annotate_opts.objdump_path = strdup(objdump_path);
++              if (!annotate_opts.objdump_path)
+                       return -ENOMEM;
+       }
+       if (addr2line_path) {
+@@ -1452,7 +1451,7 @@ int cmd_report(int argc, const char **argv)
+                       return -ENOMEM;
+       }
+-      if (annotate_check_args(&report.annotation_opts) < 0) {
++      if (annotate_check_args(&annotate_opts) < 0) {
+               ret = -EINVAL;
+               goto exit;
+       }
+@@ -1684,7 +1683,7 @@ int cmd_report(int argc, const char **argv)
+                        */
+                       symbol_conf.priv_size += sizeof(u32);
+               }
+-              annotation_config__init(&report.annotation_opts);
++              annotation_config__init(&annotate_opts);
+       }
+       if (symbol__init(&session->header.env) < 0)
+@@ -1738,7 +1737,7 @@ int cmd_report(int argc, const char **argv)
+       zstd_fini(&(session->zstd_data));
+       perf_session__delete(session);
+ exit:
+-      annotation_options__exit(&report.annotation_opts);
++      annotation_options__exit(&annotate_opts);
+       free(sort_order_help);
+       free(field_order_help);
+       return ret;
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-stat-do-not-fail-on-metrics-on-s390-z-vm-system.patch b/queue-6.6/perf-stat-do-not-fail-on-metrics-on-s390-z-vm-system.patch
new file mode 100644 (file)
index 0000000..be0aca7
--- /dev/null
@@ -0,0 +1,176 @@
+From dc6f1a0e4ade3ae4e7d6e2cf74822a8f76e8ed8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Apr 2024 08:48:06 +0200
+Subject: perf stat: Do not fail on metrics on s390 z/VM systems
+
+From: Thomas Richter <tmricht@linux.ibm.com>
+
+[ Upstream commit c2f3d7dfc7373d53286f2a5c882d3397a5070adc ]
+
+On s390 z/VM virtual machines command 'perf list' also displays metrics:
+
+  # perf list | grep -A 20 'Metric Groups:'
+  Metric Groups:
+
+  No_group:
+   cpi
+        [Cycles per Instruction]
+   est_cpi
+        [Estimated Instruction Complexity CPI infinite Level 1]
+   finite_cpi
+        [Cycles per Instructions from Finite cache/memory]
+   l1mp
+        [Level One Miss per 100 Instructions]
+   l2p
+        [Percentage sourced from Level 2 cache]
+   l3p
+        [Percentage sourced from Level 3 on same chip cache]
+   l4lp
+        [Percentage sourced from Level 4 Local cache on same book]
+   l4rp
+        [Percentage sourced from Level 4 Remote cache on different book]
+   memp
+        [Percentage sourced from memory]
+   ....
+  #
+
+The command
+
+  # perf stat -M cpi -- true
+  event syntax error: '{CPU_CYCLES/metric-id=CPU_CYCLES/.....'
+                        \___ Bad event or PMU
+
+  Unable to find PMU or event on a PMU of 'CPU_CYCLES'
+
+   event syntax error: '{CPU_CYCLES/metric-id=CPU_CYCLES/...'
+                        \___ Cannot find PMU `CPU_CYCLES'.
+                             Missing kernel support?
+ #
+
+fails. 'perf stat' should not fail on metrics when the referenced CPU
+Counter Measurement PMU is not available.
+
+Output after:
+
+  # perf stat -M est_cpi -- sleep 1
+
+  Performance counter stats for 'sleep 1':
+
+     1,000,887,494 ns   duration_time   #     0.00 est_cpi
+
+       1.000887494 seconds time elapsed
+
+       0.000143000 seconds user
+       0.000662000 seconds sys
+
+ #
+
+Fixes: 7f76b31130680fb3 ("perf list: Add IBM z16 event description for s390")
+Suggested-by: Ian Rogers <irogers@google.com>
+Reviewed-by: Ian Rogers <irogers@google.com>
+Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
+Cc: Sven Schnelle <svens@linux.ibm.com>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Link: https://lore.kernel.org/r/20240404064806.1362876-2-tmricht@linux.ibm.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../arch/s390/cf_z16/transaction.json         | 28 +++++++++----------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json b/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json
+index ec2ff78e2b5f2..3ab1d3a6638c4 100644
+--- a/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json
++++ b/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json
+@@ -2,71 +2,71 @@
+   {
+     "BriefDescription": "Transaction count",
+     "MetricName": "transaction",
+-    "MetricExpr": "TX_C_TEND + TX_NC_TEND + TX_NC_TABORT + TX_C_TABORT_SPECIAL + TX_C_TABORT_NO_SPECIAL"
++    "MetricExpr": "TX_C_TEND + TX_NC_TEND + TX_NC_TABORT + TX_C_TABORT_SPECIAL + TX_C_TABORT_NO_SPECIAL if has_event(TX_C_TEND) else 0"
+   },
+   {
+     "BriefDescription": "Cycles per Instruction",
+     "MetricName": "cpi",
+-    "MetricExpr": "CPU_CYCLES / INSTRUCTIONS"
++    "MetricExpr": "CPU_CYCLES / INSTRUCTIONS if has_event(INSTRUCTIONS) else 0"
+   },
+   {
+     "BriefDescription": "Problem State Instruction Ratio",
+     "MetricName": "prbstate",
+-    "MetricExpr": "(PROBLEM_STATE_INSTRUCTIONS / INSTRUCTIONS) * 100"
++    "MetricExpr": "(PROBLEM_STATE_INSTRUCTIONS / INSTRUCTIONS) * 100 if has_event(INSTRUCTIONS) else 0"
+   },
+   {
+     "BriefDescription": "Level One Miss per 100 Instructions",
+     "MetricName": "l1mp",
+-    "MetricExpr": "((L1I_DIR_WRITES + L1D_DIR_WRITES) / INSTRUCTIONS) * 100"
++    "MetricExpr": "((L1I_DIR_WRITES + L1D_DIR_WRITES) / INSTRUCTIONS) * 100 if has_event(INSTRUCTIONS) else 0"
+   },
+   {
+     "BriefDescription": "Percentage sourced from Level 2 cache",
+     "MetricName": "l2p",
+-    "MetricExpr": "((DCW_REQ + DCW_REQ_IV + ICW_REQ + ICW_REQ_IV) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100"
++    "MetricExpr": "((DCW_REQ + DCW_REQ_IV + ICW_REQ + ICW_REQ_IV) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_REQ) else 0"
+   },
+   {
+     "BriefDescription": "Percentage sourced from Level 3 on same chip cache",
+     "MetricName": "l3p",
+-    "MetricExpr": "((DCW_REQ_CHIP_HIT + DCW_ON_CHIP + DCW_ON_CHIP_IV + DCW_ON_CHIP_CHIP_HIT + ICW_REQ_CHIP_HIT + ICW_ON_CHIP + ICW_ON_CHIP_IV + ICW_ON_CHIP_CHIP_HIT) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100"
++    "MetricExpr": "((DCW_REQ_CHIP_HIT + DCW_ON_CHIP + DCW_ON_CHIP_IV + DCW_ON_CHIP_CHIP_HIT + ICW_REQ_CHIP_HIT + ICW_ON_CHIP + ICW_ON_CHIP_IV + ICW_ON_CHIP_CHIP_HIT) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_REQ_CHIP_HIT) else 0"
+   },
+   {
+     "BriefDescription": "Percentage sourced from Level 4 Local cache on same book",
+     "MetricName": "l4lp",
+-    "MetricExpr": "((DCW_REQ_DRAWER_HIT + DCW_ON_CHIP_DRAWER_HIT + DCW_ON_MODULE + DCW_ON_DRAWER + IDCW_ON_MODULE_IV + IDCW_ON_MODULE_CHIP_HIT + IDCW_ON_MODULE_DRAWER_HIT + IDCW_ON_DRAWER_IV + IDCW_ON_DRAWER_CHIP_HIT + IDCW_ON_DRAWER_DRAWER_HIT + ICW_REQ_DRAWER_HIT + ICW_ON_CHIP_DRAWER_HIT + ICW_ON_MODULE + ICW_ON_DRAWER) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100"
++    "MetricExpr": "((DCW_REQ_DRAWER_HIT + DCW_ON_CHIP_DRAWER_HIT + DCW_ON_MODULE + DCW_ON_DRAWER + IDCW_ON_MODULE_IV + IDCW_ON_MODULE_CHIP_HIT + IDCW_ON_MODULE_DRAWER_HIT + IDCW_ON_DRAWER_IV + IDCW_ON_DRAWER_CHIP_HIT + IDCW_ON_DRAWER_DRAWER_HIT + ICW_REQ_DRAWER_HIT + ICW_ON_CHIP_DRAWER_HIT + ICW_ON_MODULE + ICW_ON_DRAWER) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_REQ_DRAWER_HIT) else 0"
+   },
+   {
+     "BriefDescription": "Percentage sourced from Level 4 Remote cache on different book",
+     "MetricName": "l4rp",
+-    "MetricExpr": "((DCW_OFF_DRAWER + IDCW_OFF_DRAWER_IV + IDCW_OFF_DRAWER_CHIP_HIT + IDCW_OFF_DRAWER_DRAWER_HIT + ICW_OFF_DRAWER) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100"
++    "MetricExpr": "((DCW_OFF_DRAWER + IDCW_OFF_DRAWER_IV + IDCW_OFF_DRAWER_CHIP_HIT + IDCW_OFF_DRAWER_DRAWER_HIT + ICW_OFF_DRAWER) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_OFF_DRAWER) else 0"
+   },
+   {
+     "BriefDescription": "Percentage sourced from memory",
+     "MetricName": "memp",
+-    "MetricExpr": "((DCW_ON_CHIP_MEMORY + DCW_ON_MODULE_MEMORY + DCW_ON_DRAWER_MEMORY + DCW_OFF_DRAWER_MEMORY + ICW_ON_CHIP_MEMORY + ICW_ON_MODULE_MEMORY + ICW_ON_DRAWER_MEMORY + ICW_OFF_DRAWER_MEMORY) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100"
++    "MetricExpr": "((DCW_ON_CHIP_MEMORY + DCW_ON_MODULE_MEMORY + DCW_ON_DRAWER_MEMORY + DCW_OFF_DRAWER_MEMORY + ICW_ON_CHIP_MEMORY + ICW_ON_MODULE_MEMORY + ICW_ON_DRAWER_MEMORY + ICW_OFF_DRAWER_MEMORY) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_ON_CHIP_MEMORY) else 0"
+   },
+   {
+     "BriefDescription": "Cycles per Instructions from Finite cache/memory",
+     "MetricName": "finite_cpi",
+-    "MetricExpr": "L1C_TLB2_MISSES / INSTRUCTIONS"
++    "MetricExpr": "L1C_TLB2_MISSES / INSTRUCTIONS if has_event(L1C_TLB2_MISSES) else 0"
+   },
+   {
+     "BriefDescription": "Estimated Instruction Complexity CPI infinite Level 1",
+     "MetricName": "est_cpi",
+-    "MetricExpr": "(CPU_CYCLES / INSTRUCTIONS) - (L1C_TLB2_MISSES / INSTRUCTIONS)"
++    "MetricExpr": "(CPU_CYCLES / INSTRUCTIONS) - (L1C_TLB2_MISSES / INSTRUCTIONS) if has_event(INSTRUCTIONS) else 0"
+   },
+   {
+     "BriefDescription": "Estimated Sourcing Cycles per Level 1 Miss",
+     "MetricName": "scpl1m",
+-    "MetricExpr": "L1C_TLB2_MISSES / (L1I_DIR_WRITES + L1D_DIR_WRITES)"
++    "MetricExpr": "L1C_TLB2_MISSES / (L1I_DIR_WRITES + L1D_DIR_WRITES) if has_event(L1C_TLB2_MISSES) else 0"
+   },
+   {
+     "BriefDescription": "Estimated TLB CPU percentage of Total CPU",
+     "MetricName": "tlb_percent",
+-    "MetricExpr": "((DTLB2_MISSES + ITLB2_MISSES) / CPU_CYCLES) * (L1C_TLB2_MISSES / (L1I_PENALTY_CYCLES + L1D_PENALTY_CYCLES)) * 100"
++    "MetricExpr": "((DTLB2_MISSES + ITLB2_MISSES) / CPU_CYCLES) * (L1C_TLB2_MISSES / (L1I_PENALTY_CYCLES + L1D_PENALTY_CYCLES)) * 100 if has_event(CPU_CYCLES) else 0"
+   },
+   {
+     "BriefDescription": "Estimated Cycles per TLB Miss",
+     "MetricName": "tlb_miss",
+-    "MetricExpr": "((DTLB2_MISSES + ITLB2_MISSES) / (DTLB2_WRITES + ITLB2_WRITES)) * (L1C_TLB2_MISSES / (L1I_PENALTY_CYCLES + L1D_PENALTY_CYCLES))"
++    "MetricExpr": "((DTLB2_MISSES + ITLB2_MISSES) / (DTLB2_WRITES + ITLB2_WRITES)) * (L1C_TLB2_MISSES / (L1I_PENALTY_CYCLES + L1D_PENALTY_CYCLES)) if has_event(DTLB2_MISSES) else 0"
+   }
+ ]
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-stat-don-t-display-metric-header-for-non-leader.patch b/queue-6.6/perf-stat-don-t-display-metric-header-for-non-leader.patch
new file mode 100644 (file)
index 0000000..198cad6
--- /dev/null
@@ -0,0 +1,90 @@
+From 26b461b5e22163a9d8bf3f26984fd168747526b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 May 2024 22:13:09 -0700
+Subject: perf stat: Don't display metric header for non-leader uncore events
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 193a9e30207f54777ff42d0d8be8389edc522277 ]
+
+On an Intel tigerlake laptop a metric like:
+
+    {
+        "BriefDescription": "Test",
+        "MetricExpr": "imc_free_running@data_read@ + imc_free_running@data_write@",
+        "MetricGroup": "Test",
+        "MetricName": "Test",
+        "ScaleUnit": "6.103515625e-5MiB"
+    },
+
+Will have 4 events:
+
+  uncore_imc_free_running_0/data_read/
+  uncore_imc_free_running_0/data_write/
+  uncore_imc_free_running_1/data_read/
+  uncore_imc_free_running_1/data_write/
+
+If aggregration is disabled with metric-only 2 column headers are
+needed:
+
+  $ perf stat -M test --metric-only -A -a sleep 1
+
+   Performance counter stats for 'system wide':
+
+                    MiB  Test            MiB  Test
+  CPU0                 1821.0               1820.5
+
+But when not, the counts aggregated in the metric leader and only 1
+column should be shown:
+
+  $ perf stat -M test --metric-only -a sleep 1
+   Performance counter stats for 'system wide':
+
+              MiB  Test
+                5909.4
+
+         1.001258915 seconds time elapsed
+
+Achieve this by skipping events that aren't metric leaders when
+printing column headers and aggregation isn't disabled.
+
+The bug is long standing, the fixes tag is set to a refactor as that
+is as far back as is reasonable to backport.
+
+Fixes: 088519f318be3a41 ("perf stat: Move the display functions to stat-display.c")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kaige Ye <ye@kaige.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: K Prateek Nayak <kprateek.nayak@amd.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Yicong Yang <yangyicong@hisilicon.com>
+Link: https://lore.kernel.org/r/20240510051309.2452468-1-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/stat-display.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
+index 969ce40096330..0abe35388ab15 100644
+--- a/tools/perf/util/stat-display.c
++++ b/tools/perf/util/stat-display.c
+@@ -1207,6 +1207,9 @@ static void print_metric_headers(struct perf_stat_config *config,
+       /* Print metrics headers only */
+       evlist__for_each_entry(evlist, counter) {
++              if (config->aggr_mode != AGGR_NONE && counter->metric_leader != counter)
++                      continue;
++
+               os.evsel = counter;
+               perf_stat__print_shadow_stats(config, counter, 0,
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-symbols-fix-ownership-of-string-in-dso__load_vm.patch b/queue-6.6/perf-symbols-fix-ownership-of-string-in-dso__load_vm.patch
new file mode 100644 (file)
index 0000000..205ab6d
--- /dev/null
@@ -0,0 +1,91 @@
+From 7fdeee90fbe6bc54656a6872f20dba60d87507d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 15:12:08 +0100
+Subject: perf symbols: Fix ownership of string in dso__load_vmlinux()
+
+From: James Clark <james.clark@arm.com>
+
+[ Upstream commit 25626e19ae6df34f336f235b6b3dbd1b566d2738 ]
+
+The linked commit updated dso__load_vmlinux() to call
+dso__set_long_name() before loading the symbols. Loading the symbols may
+not succeed but dso__set_long_name() takes ownership of the string. The
+two callers of this function free the string themselves on failure
+cases, resulting in the following error:
+
+  $ perf record -- ls
+  $ perf report
+
+  free(): double free detected in tcache 2
+
+Fix it by always taking ownership of the string, even on failure. This
+means the string is either freed at the very first early exit condition,
+or later when the dso is deleted or the long name is replaced. Now no
+special return value is needed to signify that the caller needs to
+free the string.
+
+Fixes: e59fea47f83e8a9a ("perf symbols: Fix DSO kernel load and symbol process to correctly map DSO to its long_name, type and adjust_symbols")
+Reviewed-by: Ian Rogers <irogers@google.com>
+Signed-off-by: James Clark <james.clark@arm.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240507141210.195939-5-james.clark@arm.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/symbol.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
+index 1976af974a371..ea24f21aafc3e 100644
+--- a/tools/perf/util/symbol.c
++++ b/tools/perf/util/symbol.c
+@@ -1935,6 +1935,10 @@ int dso__load(struct dso *dso, struct map *map)
+       return ret;
+ }
++/*
++ * Always takes ownership of vmlinux when vmlinux_allocated == true, even if
++ * it returns an error.
++ */
+ int dso__load_vmlinux(struct dso *dso, struct map *map,
+                     const char *vmlinux, bool vmlinux_allocated)
+ {
+@@ -1953,8 +1957,11 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
+       else
+               symtab_type = DSO_BINARY_TYPE__VMLINUX;
+-      if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type))
++      if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type)) {
++              if (vmlinux_allocated)
++                      free((char *) vmlinux);
+               return -1;
++      }
+       /*
+        * dso__load_sym() may copy 'dso' which will result in the copies having
+@@ -1997,7 +2004,6 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map)
+               err = dso__load_vmlinux(dso, map, filename, true);
+               if (err > 0)
+                       goto out;
+-              free(filename);
+       }
+ out:
+       return err;
+@@ -2149,7 +2155,6 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map)
+               err = dso__load_vmlinux(dso, map, filename, true);
+               if (err > 0)
+                       return err;
+-              free(filename);
+       }
+       if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-test-add-a-test-for-strcmp_cpuid_str-expression.patch b/queue-6.6/perf-test-add-a-test-for-strcmp_cpuid_str-expression.patch
new file mode 100644 (file)
index 0000000..18a51fb
--- /dev/null
@@ -0,0 +1,112 @@
+From 4f0d6f155e16e078677a79d54edee789f5829f61 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Sep 2023 10:50:46 +0100
+Subject: perf test: Add a test for strcmp_cpuid_str() expression
+
+From: James Clark <james.clark@arm.com>
+
+[ Upstream commit a1ebf7718ee31501d2d2ee3af1716e0084c81926 ]
+
+Test that the new expression builtin returns a match when the current
+escaped CPU ID is given, and that it doesn't match when "0x0" is given.
+
+The CPU ID in test__expr() has to be changed to perf_pmu__getcpuid()
+which returns the CPU ID string, rather than the raw CPU ID that
+get_cpuid() returns because that can't be used with strcmp_cpuid_str().
+It doesn't affect the is_intel test because both versions contain
+"Intel".
+
+Reviewed-by: Ian Rogers <irogers@google.com>
+Signed-off-by: James Clark <james.clark@arm.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Chen Zhongjin <chenzhongjin@huawei.com>
+Cc: Eduard Zingerman <eddyz87@gmail.com>
+Cc: Haixin Yu <yuhaixin.yhx@linux.alibaba.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: John Garry <john.g.garry@oracle.com>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mike Leach <mike.leach@linaro.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Yang Jihong <yangjihong1@huawei.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Link: https://lore.kernel.org/r/20230904095104.1162928-5-james.clark@arm.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/tests/expr.c | 31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
+index 81229fa4f1e96..b177d09078038 100644
+--- a/tools/perf/tests/expr.c
++++ b/tools/perf/tests/expr.c
+@@ -9,6 +9,7 @@
+ #include <math.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <string2.h>
+ #include <linux/zalloc.h>
+ static int test_ids_union(void)
+@@ -74,10 +75,13 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
+       int ret;
+       struct expr_parse_ctx *ctx;
+       bool is_intel = false;
+-      char buf[128];
++      char strcmp_cpuid_buf[256];
++      struct perf_pmu *pmu = pmu__find_core_pmu();
++      char *cpuid = perf_pmu__getcpuid(pmu);
++      char *escaped_cpuid1, *escaped_cpuid2;
+-      if (!get_cpuid(buf, sizeof(buf)))
+-              is_intel = strstr(buf, "Intel") != NULL;
++      TEST_ASSERT_VAL("get_cpuid", cpuid);
++      is_intel = strstr(cpuid, "Intel") != NULL;
+       TEST_ASSERT_EQUAL("ids_union", test_ids_union(), 0);
+@@ -257,9 +261,28 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
+       TEST_ASSERT_VAL("source count", hashmap__size(ctx->ids) == 1);
+       TEST_ASSERT_VAL("source count", hashmap__find(ctx->ids, "EVENT1", &val_ptr));
++
++      /* Test no cpuid match */
++      ret = test(ctx, "strcmp_cpuid_str(0x0)", 0);
++
++      /*
++       * Test cpuid match with current cpuid. Special chars have to be
++       * escaped.
++       */
++      escaped_cpuid1 = strreplace_chars('-', cpuid, "\\-");
++      free(cpuid);
++      escaped_cpuid2 = strreplace_chars(',', escaped_cpuid1, "\\,");
++      free(escaped_cpuid1);
++      escaped_cpuid1 = strreplace_chars('=', escaped_cpuid2, "\\=");
++      free(escaped_cpuid2);
++      scnprintf(strcmp_cpuid_buf, sizeof(strcmp_cpuid_buf),
++                "strcmp_cpuid_str(%s)", escaped_cpuid1);
++      free(escaped_cpuid1);
++      ret |= test(ctx, strcmp_cpuid_buf, 1);
++
+       /* has_event returns 1 when an event exists. */
+       expr__add_id_val(ctx, strdup("cycles"), 2);
+-      ret = test(ctx, "has_event(cycles)", 1);
++      ret |= test(ctx, "has_event(cycles)", 1);
+       expr__ctx_free(ctx);
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-test-shell-arm_coresight-increase-buffer-size-f.patch b/queue-6.6/perf-test-shell-arm_coresight-increase-buffer-size-f.patch
new file mode 100644 (file)
index 0000000..f1fd140
--- /dev/null
@@ -0,0 +1,58 @@
+From 0536e7f78d1cd83a4e2291059e3fa75c720176eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Mar 2024 11:37:49 +0000
+Subject: perf test shell arm_coresight: Increase buffer size for Coresight
+ basic tests
+
+From: James Clark <james.clark@arm.com>
+
+[ Upstream commit 10b6ee3b597b1b1b4dc390aaf9d589664af31df9 ]
+
+These tests record in a mode that includes kernel trace but look for
+samples of a userspace process. This makes them sensitive to any kernel
+compilation options that increase the amount of time spent in the
+kernel. If the trace buffer is completely filled before userspace is
+reached then the test will fail. Double the buffer size to fix this.
+
+The other tests in the same file aren't sensitive to this for various
+reasons, for example the iterate devices test filters by userspace trace
+only. But in order to keep coverage of all the modes, increase the
+buffer size rather than filtering by userspace for the basic tests.
+
+Fixes: d1efa4a0a696e487 ("perf cs-etm: Add separate decode paths for timeless and per-thread modes")
+Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Signed-off-by: James Clark <james.clark@arm.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mike Leach <mike.leach@linaro.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
+Link: https://lore.kernel.org/r/20240326113749.257250-1-james.clark@arm.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/tests/shell/test_arm_coresight.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh
+index f1bf5621160fb..4d4e685775303 100755
+--- a/tools/perf/tests/shell/test_arm_coresight.sh
++++ b/tools/perf/tests/shell/test_arm_coresight.sh
+@@ -186,7 +186,7 @@ arm_cs_etm_snapshot_test() {
+ arm_cs_etm_basic_test() {
+       echo "Recording trace with '$*'"
+-      perf record -o ${perfdata} "$@" -- ls > /dev/null 2>&1
++      perf record -o ${perfdata} "$@" -m,8M -- ls > /dev/null 2>&1
+       perf_script_branch_samples ls &&
+       perf_report_branch_samples ls &&
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-tests-apply-attributes-to-all-events-in-object-.patch b/queue-6.6/perf-tests-apply-attributes-to-all-events-in-object-.patch
new file mode 100644 (file)
index 0000000..029ab36
--- /dev/null
@@ -0,0 +1,70 @@
+From e50e5d8bef0881fd8a468045fad48be1ae1263d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Apr 2024 11:34:53 +0100
+Subject: perf tests: Apply attributes to all events in object code reading
+ test
+
+From: James Clark <james.clark@arm.com>
+
+[ Upstream commit 2dade41a533f337447b945239b87ff31a8857890 ]
+
+PERF_PMU_CAP_EXTENDED_HW_TYPE results in multiple events being opened on
+heterogeneous systems. Currently this test only sets its required
+attributes on the first event. Not disabling enable_on_exec on the other
+events causes the test to fail because the forked objdump processes are
+sampled. No tracking event is opened so Perf only knows about its own
+mappings causing the objdump samples to give the following error:
+
+  $ perf test -vvv "object code reading"
+
+  Reading object code for memory address: 0xffff9aaa55ec
+  thread__find_map failed
+  ---- end(-1) ----
+  24: Object code reading              : FAILED!
+
+Fixes: 251aa040244a3b17 ("perf parse-events: Wildcard most "numeric" events")
+Reviewed-by: Ian Rogers <irogers@google.com>
+Signed-off-by: James Clark <james.clark@arm.com>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linux.dev>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Spoorthy S <spoorts2@in.ibm.com>
+Link: https://lore.kernel.org/r/20240410103458.813656-3-james.clark@arm.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/tests/code-reading.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
+index ed3815163d1be..ff249555ca57a 100644
+--- a/tools/perf/tests/code-reading.c
++++ b/tools/perf/tests/code-reading.c
+@@ -657,11 +657,11 @@ static int do_test_code_reading(bool try_kcore)
+               evlist__config(evlist, &opts, NULL);
+-              evsel = evlist__first(evlist);
+-
+-              evsel->core.attr.comm = 1;
+-              evsel->core.attr.disabled = 1;
+-              evsel->core.attr.enable_on_exec = 0;
++              evlist__for_each_entry(evlist, evsel) {
++                      evsel->core.attr.comm = 1;
++                      evsel->core.attr.disabled = 1;
++                      evsel->core.attr.enable_on_exec = 0;
++              }
+               ret = evlist__open(evlist);
+               if (ret < 0) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-tests-make-test-data-symbol-more-robust-on-neov.patch b/queue-6.6/perf-tests-make-test-data-symbol-more-robust-on-neov.patch
new file mode 100644 (file)
index 0000000..b99faa2
--- /dev/null
@@ -0,0 +1,69 @@
+From 4dca0165c364d0c3c5e5d99b72d7d0953af4cbc3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Apr 2024 11:34:52 +0100
+Subject: perf tests: Make "test data symbol" more robust on Neoverse N1
+
+From: James Clark <james.clark@arm.com>
+
+[ Upstream commit 256ef072b3842273ce703db18b603b051aca95fe ]
+
+To prevent anyone from seeing a test failure appear as a regression and
+thinking that it was caused by their code change, insert some noise into
+the loop which makes it immune to sampling bias issues (errata 1694299).
+
+The "test data symbol" test can fail with any unrelated change that
+shifts the loop into an unfortunate position in the Perf binary which is
+almost impossible to debug as the root cause of the test failure.
+Ultimately it's caused by the referenced errata.
+
+Fixes: 60abedb8aa902b06 ("perf test: Introduce script for data symbol testing")
+Reviewed-by: Ian Rogers <irogers@google.com>
+Signed-off-by: James Clark <james.clark@arm.com>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linux.dev>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Spoorthy S <spoorts2@in.ibm.com>
+Link: https://lore.kernel.org/r/20240410103458.813656-2-james.clark@arm.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/tests/workloads/datasym.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/tools/perf/tests/workloads/datasym.c b/tools/perf/tests/workloads/datasym.c
+index ddd40bc63448a..8e08fc75a973e 100644
+--- a/tools/perf/tests/workloads/datasym.c
++++ b/tools/perf/tests/workloads/datasym.c
+@@ -16,6 +16,22 @@ static int datasym(int argc __maybe_unused, const char **argv __maybe_unused)
+ {
+       for (;;) {
+               buf1.data1++;
++              if (buf1.data1 == 123) {
++                      /*
++                       * Add some 'noise' in the loop to work around errata
++                       * 1694299 on Arm N1.
++                       *
++                       * Bias exists in SPE sampling which can cause the load
++                       * and store instructions to be skipped entirely. This
++                       * comes and goes randomly depending on the offset the
++                       * linker places the datasym loop at in the Perf binary.
++                       * With an extra branch in the middle of the loop that
++                       * isn't always taken, the instruction stream is no
++                       * longer a continuous repeating pattern that interacts
++                       * badly with the bias.
++                       */
++                      buf1.data1++;
++              }
+               buf1.data2 += buf1.data1;
+       }
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-thread-fixes-to-thread__new-related-to-initiali.patch b/queue-6.6/perf-thread-fixes-to-thread__new-related-to-initiali.patch
new file mode 100644 (file)
index 0000000..721562a
--- /dev/null
@@ -0,0 +1,80 @@
+From 83d16e13f9f534a6e9077f58a49501f83586fed4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 20:53:01 -0700
+Subject: perf thread: Fixes to thread__new() related to initializing comm
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 3536c2575e88a890cf696b4ccd3da36bc937853b ]
+
+Freeing the thread on failure won't work with reference count checking,
+use thread__delete().
+
+Don't allocate the comm_str, use a stack allocation instead.
+
+Fixes: f6005cafebab72f8 ("perf thread: Add reference count checking")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linux.dev>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240508035301.1554434-5-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/thread.c | 14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
+index fe5e6991ae4b4..61e9f449c7258 100644
+--- a/tools/perf/util/thread.c
++++ b/tools/perf/util/thread.c
+@@ -39,12 +39,13 @@ int thread__init_maps(struct thread *thread, struct machine *machine)
+ struct thread *thread__new(pid_t pid, pid_t tid)
+ {
+-      char *comm_str;
+-      struct comm *comm;
+       RC_STRUCT(thread) *_thread = zalloc(sizeof(*_thread));
+       struct thread *thread;
+       if (ADD_RC_CHK(thread, _thread) != NULL) {
++              struct comm *comm;
++              char comm_str[32];
++
+               thread__set_pid(thread, pid);
+               thread__set_tid(thread, tid);
+               thread__set_ppid(thread, -1);
+@@ -56,13 +57,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)
+               init_rwsem(thread__namespaces_lock(thread));
+               init_rwsem(thread__comm_lock(thread));
+-              comm_str = malloc(32);
+-              if (!comm_str)
+-                      goto err_thread;
+-
+-              snprintf(comm_str, 32, ":%d", tid);
++              snprintf(comm_str, sizeof(comm_str), ":%d", tid);
+               comm = comm__new(comm_str, 0, false);
+-              free(comm_str);
+               if (!comm)
+                       goto err_thread;
+@@ -76,7 +72,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
+       return thread;
+ err_thread:
+-      free(thread);
++      thread__delete(thread);
+       return NULL;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-tools-add-use-pmu-reverse-lookup-from-config-to.patch b/queue-6.6/perf-tools-add-use-pmu-reverse-lookup-from-config-to.patch
new file mode 100644 (file)
index 0000000..20a6da9
--- /dev/null
@@ -0,0 +1,149 @@
+From 043c6ac0b1810a9c81b9a6820bcc5f770a2a3a23 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Mar 2024 16:19:15 -0800
+Subject: perf tools: Add/use PMU reverse lookup from config to name
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 67ee8e71daabb8632931b7559e5c8a4b69a427f8 ]
+
+Add perf_pmu__name_from_config that does a reverse lookup from a
+config number to an alias name. The lookup is expensive as the config
+is computed for every alias by filling in a perf_event_attr, but this
+is only done when verbose output is enabled. The lookup also only
+considers config, and not config1, config2 or config3.
+
+An example of the output:
+
+  $ perf stat -vv -e data_read true
+  ...
+  perf_event_attr:
+    type                             24 (uncore_imc_free_running_0)
+    size                             136
+    config                           0x20ff (data_read)
+    sample_type                      IDENTIFIER
+    read_format                      TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
+    disabled                         1
+    inherit                          1
+    exclude_guest                    1
+  ...
+
+Committer notes:
+
+Fix the python binding build by adding dummies for not strictly
+needed perf_pmu__name_from_config() and perf_pmus__find_by_type().
+
+Signed-off-by: Ian Rogers <irogers@google.com>
+Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Tested-by: Kan Liang <kan.liang@linux.intel.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Yang Jihong <yangjihong1@huawei.com>
+Link: https://lore.kernel.org/r/20240308001915.4060155-7-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/perf_event_attr_fprintf.c | 10 ++++++++--
+ tools/perf/util/pmu.c                     | 18 ++++++++++++++++++
+ tools/perf/util/pmu.h                     |  1 +
+ tools/perf/util/python.c                  | 10 ++++++++++
+ 4 files changed, 37 insertions(+), 2 deletions(-)
+
+diff --git a/tools/perf/util/perf_event_attr_fprintf.c b/tools/perf/util/perf_event_attr_fprintf.c
+index f3c6db5f4182c..1c1582688f037 100644
+--- a/tools/perf/util/perf_event_attr_fprintf.c
++++ b/tools/perf/util/perf_event_attr_fprintf.c
+@@ -221,8 +221,14 @@ static void __p_config_tracepoint_id(char *buf, size_t size, u64 value)
+ }
+ #endif
+-static void __p_config_id(char *buf, size_t size, u32 type, u64 value)
++static void __p_config_id(struct perf_pmu *pmu, char *buf, size_t size, u32 type, u64 value)
+ {
++      const char *name = perf_pmu__name_from_config(pmu, value);
++
++      if (name) {
++              print_id_hex(name);
++              return;
++      }
+       switch (type) {
+       case PERF_TYPE_HARDWARE:
+               return __p_config_hw_id(buf, size, value);
+@@ -251,7 +257,7 @@ static void __p_config_id(char *buf, size_t size, u32 type, u64 value)
+ #define p_branch_sample_type(val) __p_branch_sample_type(buf, BUF_SIZE, val)
+ #define p_read_format(val)    __p_read_format(buf, BUF_SIZE, val)
+ #define p_type_id(val)                __p_type_id(pmu, buf, BUF_SIZE, val)
+-#define p_config_id(val)      __p_config_id(buf, BUF_SIZE, attr->type, val)
++#define p_config_id(val)      __p_config_id(pmu, buf, BUF_SIZE, attr->type, val)
+ #define PRINT_ATTRn(_n, _f, _p, _a)                   \
+ do {                                                  \
+diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
+index 64b605a6060e2..0b1c380fce901 100644
+--- a/tools/perf/util/pmu.c
++++ b/tools/perf/util/pmu.c
+@@ -2081,3 +2081,21 @@ void perf_pmu__delete(struct perf_pmu *pmu)
+       zfree(&pmu->id);
+       free(pmu);
+ }
++
++const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config)
++{
++      struct perf_pmu_alias *event;
++
++      if (!pmu)
++              return NULL;
++
++      pmu_add_cpu_aliases(pmu);
++      list_for_each_entry(event, &pmu->aliases, list) {
++              struct perf_event_attr attr = {.config = 0,};
++              int ret = perf_pmu__config(pmu, &attr, &event->terms, NULL);
++
++              if (ret == 0 && config == attr.config)
++                      return event->name;
++      }
++      return NULL;
++}
+diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
+index c4b4fabe16edc..ed6693f991867 100644
+--- a/tools/perf/util/pmu.h
++++ b/tools/perf/util/pmu.h
+@@ -266,5 +266,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
+ struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus);
+ void perf_pmu__delete(struct perf_pmu *pmu);
+ struct perf_pmu *perf_pmus__find_core_pmu(void);
++const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config);
+ #endif /* __PMU_H */
+diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
+index c29f5f0bb552c..b01b0e5510563 100644
+--- a/tools/perf/util/python.c
++++ b/tools/perf/util/python.c
+@@ -103,6 +103,16 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
+       return EOF;
+ }
++const char *perf_pmu__name_from_config(struct perf_pmu *pmu __maybe_unused, u64 config __maybe_unused)
++{
++      return NULL;
++}
++
++struct perf_pmu *perf_pmus__find_by_type(unsigned int type __maybe_unused)
++{
++      return NULL;
++}
++
+ int perf_pmus__num_core_pmus(void)
+ {
+       return 1;
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-tools-use-pmus-to-describe-type-from-attribute.patch b/queue-6.6/perf-tools-use-pmus-to-describe-type-from-attribute.patch
new file mode 100644 (file)
index 0000000..f93bd8a
--- /dev/null
@@ -0,0 +1,161 @@
+From 241d6cad1ca1ec68490c6fc79bebe8fd5f12fcfa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Mar 2024 16:19:14 -0800
+Subject: perf tools: Use pmus to describe type from attribute
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 7093882067e2e2f88d3449c35c5f0f3f566c8a26 ]
+
+When dumping a perf_event_attr, use pmus to find the PMU and its name
+by the type number. This allows dynamically added PMUs to be described.
+
+Before:
+
+  $ perf stat -vv -e data_read true
+  ...
+  perf_event_attr:
+    type                             24
+    size                             136
+    config                           0x20ff
+    sample_type                      IDENTIFIER
+    read_format                      TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
+    disabled                         1
+    inherit                          1
+    exclude_guest                    1
+  ...
+
+After:
+
+  $ perf stat -vv -e data_read true
+  ...
+  perf_event_attr:
+    type                             24 (uncore_imc_free_running_0)
+    size                             136
+    config                           0x20ff
+    sample_type                      IDENTIFIER
+    read_format                      TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
+    disabled                         1
+    inherit                          1
+    exclude_guest                    1
+  ...
+
+However, it also means that when we have a PMU name we prefer it to a
+hard coded name:
+
+Before:
+
+  $ perf stat -vv -e faults true
+  ...
+  perf_event_attr:
+    type                             1 (PERF_TYPE_SOFTWARE)
+    size                             136
+    config                           0x2 (PERF_COUNT_SW_PAGE_FAULTS)
+    sample_type                      IDENTIFIER
+    read_format                      TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
+    disabled                         1
+    inherit                          1
+    enable_on_exec                   1
+    exclude_guest                    1
+  ...
+
+After:
+
+  $ perf stat -vv -e faults true
+  ...
+  perf_event_attr:
+    type                             1 (software)
+    size                             136
+    config                           0x2 (PERF_COUNT_SW_PAGE_FAULTS)
+    sample_type                      IDENTIFIER
+    read_format                      TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
+    disabled                         1
+    inherit                          1
+    enable_on_exec                   1
+    exclude_guest                    1
+  ...
+
+It feels more consistent to do this, rather than only prefer a PMU
+name when a hard coded name isn't available.
+
+Signed-off-by: Ian Rogers <irogers@google.com>
+Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Tested-by: Kan Liang <kan.liang@linux.intel.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Yang Jihong <yangjihong1@huawei.com>
+Link: https://lore.kernel.org/r/20240308001915.4060155-6-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/perf_event_attr_fprintf.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/tools/perf/util/perf_event_attr_fprintf.c b/tools/perf/util/perf_event_attr_fprintf.c
+index 2247991451f3a..f3c6db5f4182c 100644
+--- a/tools/perf/util/perf_event_attr_fprintf.c
++++ b/tools/perf/util/perf_event_attr_fprintf.c
+@@ -7,6 +7,8 @@
+ #include <linux/types.h>
+ #include <linux/perf_event.h>
+ #include "util/evsel_fprintf.h"
++#include "util/pmu.h"
++#include "util/pmus.h"
+ #include "trace-event.h"
+ struct bit_names {
+@@ -74,9 +76,12 @@ static void __p_read_format(char *buf, size_t size, u64 value)
+ }
+ #define ENUM_ID_TO_STR_CASE(x) case x: return (#x);
+-static const char *stringify_perf_type_id(u64 value)
++static const char *stringify_perf_type_id(struct perf_pmu *pmu, u32 type)
+ {
+-      switch (value) {
++      if (pmu)
++              return pmu->name;
++
++      switch (type) {
+       ENUM_ID_TO_STR_CASE(PERF_TYPE_HARDWARE)
+       ENUM_ID_TO_STR_CASE(PERF_TYPE_SOFTWARE)
+       ENUM_ID_TO_STR_CASE(PERF_TYPE_TRACEPOINT)
+@@ -174,9 +179,9 @@ do {                                                               \
+ #define print_id_unsigned(_s) PRINT_ID(_s, "%"PRIu64)
+ #define print_id_hex(_s)      PRINT_ID(_s, "%#"PRIx64)
+-static void __p_type_id(char *buf, size_t size, u64 value)
++static void __p_type_id(struct perf_pmu *pmu, char *buf, size_t size, u64 value)
+ {
+-      print_id_unsigned(stringify_perf_type_id(value));
++      print_id_unsigned(stringify_perf_type_id(pmu, value));
+ }
+ static void __p_config_hw_id(char *buf, size_t size, u64 value)
+@@ -245,7 +250,7 @@ static void __p_config_id(char *buf, size_t size, u32 type, u64 value)
+ #define p_sample_type(val)    __p_sample_type(buf, BUF_SIZE, val)
+ #define p_branch_sample_type(val) __p_branch_sample_type(buf, BUF_SIZE, val)
+ #define p_read_format(val)    __p_read_format(buf, BUF_SIZE, val)
+-#define p_type_id(val)                __p_type_id(buf, BUF_SIZE, val)
++#define p_type_id(val)                __p_type_id(pmu, buf, BUF_SIZE, val)
+ #define p_config_id(val)      __p_config_id(buf, BUF_SIZE, attr->type, val)
+ #define PRINT_ATTRn(_n, _f, _p, _a)                   \
+@@ -261,6 +266,7 @@ do {                                                       \
+ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
+                            attr__fprintf_f attr__fprintf, void *priv)
+ {
++      struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type);
+       char buf[BUF_SIZE];
+       int ret = 0;
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-top-convert-to-the-global-annotation_options.patch b/queue-6.6/perf-top-convert-to-the-global-annotation_options.patch
new file mode 100644 (file)
index 0000000..c75ec8c
--- /dev/null
@@ -0,0 +1,188 @@
+From d30a20b4323b481d1a84f60de8fe221a884bf246 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Nov 2023 09:54:36 -0800
+Subject: perf top: Convert to the global annotation_options
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit c9a21a872c69032cb9a94ebc171649c0c28141d7 ]
+
+Use the global option and drop the local copy.
+
+Reviewed-by: Ian Rogers <irogers@google.com>
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20231128175441.721579-4-namhyung@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-top.c | 44 ++++++++++++++++++++--------------------
+ tools/perf/util/top.h    |  1 -
+ 2 files changed, 22 insertions(+), 23 deletions(-)
+
+diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
+index cd64ae44ccbde..ecf98169fd8fd 100644
+--- a/tools/perf/builtin-top.c
++++ b/tools/perf/builtin-top.c
+@@ -147,7 +147,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
+               return err;
+       }
+-      err = symbol__annotate(&he->ms, evsel, &top->annotation_opts, NULL);
++      err = symbol__annotate(&he->ms, evsel, &annotate_opts, NULL);
+       if (err == 0) {
+               top->sym_filter_entry = he;
+       } else {
+@@ -261,9 +261,9 @@ static void perf_top__show_details(struct perf_top *top)
+               goto out_unlock;
+       printf("Showing %s for %s\n", evsel__name(top->sym_evsel), symbol->name);
+-      printf("  Events  Pcnt (>=%d%%)\n", top->annotation_opts.min_pcnt);
++      printf("  Events  Pcnt (>=%d%%)\n", annotate_opts.min_pcnt);
+-      more = symbol__annotate_printf(&he->ms, top->sym_evsel, &top->annotation_opts);
++      more = symbol__annotate_printf(&he->ms, top->sym_evsel, &annotate_opts);
+       if (top->evlist->enabled) {
+               if (top->zero)
+@@ -450,7 +450,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top)
+       fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", top->count_filter);
+-      fprintf(stdout, "\t[F]     annotate display filter (percent). \t(%d%%)\n", top->annotation_opts.min_pcnt);
++      fprintf(stdout, "\t[F]     annotate display filter (percent). \t(%d%%)\n", annotate_opts.min_pcnt);
+       fprintf(stdout, "\t[s]     annotate symbol.                   \t(%s)\n", name?: "NULL");
+       fprintf(stdout, "\t[S]     stop annotation.\n");
+@@ -553,7 +553,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
+                       prompt_integer(&top->count_filter, "Enter display event count filter");
+                       break;
+               case 'F':
+-                      prompt_percent(&top->annotation_opts.min_pcnt,
++                      prompt_percent(&annotate_opts.min_pcnt,
+                                      "Enter details display event filter (percent)");
+                       break;
+               case 'K':
+@@ -647,7 +647,7 @@ static void *display_thread_tui(void *arg)
+       ret = evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent,
+                                      &top->session->header.env, !top->record_opts.overwrite,
+-                                     &top->annotation_opts);
++                                     &annotate_opts);
+       if (ret == K_RELOAD) {
+               top->zero = true;
+               goto repeat;
+@@ -1241,9 +1241,9 @@ static int __cmd_top(struct perf_top *top)
+       pthread_t thread, thread_process;
+       int ret;
+-      if (!top->annotation_opts.objdump_path) {
++      if (!annotate_opts.objdump_path) {
+               ret = perf_env__lookup_objdump(&top->session->header.env,
+-                                             &top->annotation_opts.objdump_path);
++                                             &annotate_opts.objdump_path);
+               if (ret)
+                       return ret;
+       }
+@@ -1537,9 +1537,9 @@ int cmd_top(int argc, const char **argv)
+                  "only consider symbols in these comms"),
+       OPT_STRING(0, "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
+                  "only consider these symbols"),
+-      OPT_BOOLEAN(0, "source", &top.annotation_opts.annotate_src,
++      OPT_BOOLEAN(0, "source", &annotate_opts.annotate_src,
+                   "Interleave source code with assembly code (default)"),
+-      OPT_BOOLEAN(0, "asm-raw", &top.annotation_opts.show_asm_raw,
++      OPT_BOOLEAN(0, "asm-raw", &annotate_opts.show_asm_raw,
+                   "Display raw encoding of assembly instructions (default)"),
+       OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
+                   "Enable kernel symbol demangling"),
+@@ -1550,9 +1550,9 @@ int cmd_top(int argc, const char **argv)
+                  "addr2line binary to use for line numbers"),
+       OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
+                  "Specify disassembler style (e.g. -M intel for intel syntax)"),
+-      OPT_STRING(0, "prefix", &top.annotation_opts.prefix, "prefix",
++      OPT_STRING(0, "prefix", &annotate_opts.prefix, "prefix",
+                   "Add prefix to source file path names in programs (with --prefix-strip)"),
+-      OPT_STRING(0, "prefix-strip", &top.annotation_opts.prefix_strip, "N",
++      OPT_STRING(0, "prefix-strip", &annotate_opts.prefix_strip, "N",
+                   "Strip first N entries of source file path name in programs (with --prefix)"),
+       OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
+       OPT_CALLBACK(0, "percent-limit", &top, "percent",
+@@ -1610,10 +1610,10 @@ int cmd_top(int argc, const char **argv)
+       if (status < 0)
+               return status;
+-      annotation_options__init(&top.annotation_opts);
++      annotation_options__init(&annotate_opts);
+-      top.annotation_opts.min_pcnt = 5;
+-      top.annotation_opts.context  = 4;
++      annotate_opts.min_pcnt = 5;
++      annotate_opts.context  = 4;
+       top.evlist = evlist__new();
+       if (top.evlist == NULL)
+@@ -1643,13 +1643,13 @@ int cmd_top(int argc, const char **argv)
+               usage_with_options(top_usage, options);
+       if (disassembler_style) {
+-              top.annotation_opts.disassembler_style = strdup(disassembler_style);
+-              if (!top.annotation_opts.disassembler_style)
++              annotate_opts.disassembler_style = strdup(disassembler_style);
++              if (!annotate_opts.disassembler_style)
+                       return -ENOMEM;
+       }
+       if (objdump_path) {
+-              top.annotation_opts.objdump_path = strdup(objdump_path);
+-              if (!top.annotation_opts.objdump_path)
++              annotate_opts.objdump_path = strdup(objdump_path);
++              if (!annotate_opts.objdump_path)
+                       return -ENOMEM;
+       }
+       if (addr2line_path) {
+@@ -1662,7 +1662,7 @@ int cmd_top(int argc, const char **argv)
+       if (status)
+               goto out_delete_evlist;
+-      if (annotate_check_args(&top.annotation_opts) < 0)
++      if (annotate_check_args(&annotate_opts) < 0)
+               goto out_delete_evlist;
+       if (!top.evlist->core.nr_entries) {
+@@ -1788,7 +1788,7 @@ int cmd_top(int argc, const char **argv)
+       if (status < 0)
+               goto out_delete_evlist;
+-      annotation_config__init(&top.annotation_opts);
++      annotation_config__init(&annotate_opts);
+       symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
+       status = symbol__init(NULL);
+@@ -1841,7 +1841,7 @@ int cmd_top(int argc, const char **argv)
+ out_delete_evlist:
+       evlist__delete(top.evlist);
+       perf_session__delete(top.session);
+-      annotation_options__exit(&top.annotation_opts);
++      annotation_options__exit(&annotate_opts);
+       return status;
+ }
+diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
+index a8b0d79bd96cf..4c5588dbb1317 100644
+--- a/tools/perf/util/top.h
++++ b/tools/perf/util/top.h
+@@ -21,7 +21,6 @@ struct perf_top {
+       struct perf_tool   tool;
+       struct evlist *evlist, *sb_evlist;
+       struct record_opts record_opts;
+-      struct annotation_options annotation_opts;
+       struct evswitch    evswitch;
+       /*
+        * Symbols will be added here in perf_event__process_sample and will
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-ui-browser-avoid-segv-on-title.patch b/queue-6.6/perf-ui-browser-avoid-segv-on-title.patch
new file mode 100644 (file)
index 0000000..a018ff4
--- /dev/null
@@ -0,0 +1,46 @@
+From 90f87e67a55f547f9dc9f5a05b602c8c42f55677 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 20:52:58 -0700
+Subject: perf ui browser: Avoid SEGV on title
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 90f01afb0dfafbc9b094bb61e61a4ac297d9d0d2 ]
+
+If the title is NULL then it can lead to a SEGV.
+
+Fixes: 769e6a1e15bdbbaf ("perf ui browser: Don't save pointer to stack memory")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linux.dev>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240508035301.1554434-2-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/ui/browser.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
+index c4cdf2ea69b72..19503e8387385 100644
+--- a/tools/perf/ui/browser.c
++++ b/tools/perf/ui/browser.c
+@@ -203,7 +203,7 @@ void ui_browser__refresh_dimensions(struct ui_browser *browser)
+ void ui_browser__handle_resize(struct ui_browser *browser)
+ {
+       ui__refresh_dimensions(false);
+-      ui_browser__show(browser, browser->title, ui_helpline__current);
++      ui_browser__show(browser, browser->title ?: "", ui_helpline__current);
+       ui_browser__refresh(browser);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-ui-browser-don-t-save-pointer-to-stack-memory.patch b/queue-6.6/perf-ui-browser-don-t-save-pointer-to-stack-memory.patch
new file mode 100644 (file)
index 0000000..b89ba6f
--- /dev/null
@@ -0,0 +1,143 @@
+From 37b0adfd2117bcf3f56c4c1ebb8c2d209046c9eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 11:35:38 -0700
+Subject: perf ui browser: Don't save pointer to stack memory
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit 769e6a1e15bdbbaf2b0d2f37c24f2c53268bd21f ]
+
+ui_browser__show() is capturing the input title that is stack allocated
+memory in hist_browser__run().
+
+Avoid a use after return by strdup-ing the string.
+
+Committer notes:
+
+Further explanation from Ian Rogers:
+
+My command line using tui is:
+$ sudo bash -c 'rm /tmp/asan.log*; export
+ASAN_OPTIONS="log_path=/tmp/asan.log"; /tmp/perf/perf mem record -a
+sleep 1; /tmp/perf/perf mem report'
+I then go to the perf annotate view and quit. This triggers the asan
+error (from the log file):
+```
+==1254591==ERROR: AddressSanitizer: stack-use-after-return on address
+0x7f2813331920 at pc 0x7f28180
+65991 bp 0x7fff0a21c750 sp 0x7fff0a21bf10
+READ of size 80 at 0x7f2813331920 thread T0
+    #0 0x7f2818065990 in __interceptor_strlen
+../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:461
+    #1 0x7f2817698251 in SLsmg_write_wrapped_string
+(/lib/x86_64-linux-gnu/libslang.so.2+0x98251)
+    #2 0x7f28176984b9 in SLsmg_write_nstring
+(/lib/x86_64-linux-gnu/libslang.so.2+0x984b9)
+    #3 0x55c94045b365 in ui_browser__write_nstring ui/browser.c:60
+    #4 0x55c94045c558 in __ui_browser__show_title ui/browser.c:266
+    #5 0x55c94045c776 in ui_browser__show ui/browser.c:288
+    #6 0x55c94045c06d in ui_browser__handle_resize ui/browser.c:206
+    #7 0x55c94047979b in do_annotate ui/browsers/hists.c:2458
+    #8 0x55c94047fb17 in evsel__hists_browse ui/browsers/hists.c:3412
+    #9 0x55c940480a0c in perf_evsel_menu__run ui/browsers/hists.c:3527
+    #10 0x55c940481108 in __evlist__tui_browse_hists ui/browsers/hists.c:3613
+    #11 0x55c9404813f7 in evlist__tui_browse_hists ui/browsers/hists.c:3661
+    #12 0x55c93ffa253f in report__browse_hists tools/perf/builtin-report.c:671
+    #13 0x55c93ffa58ca in __cmd_report tools/perf/builtin-report.c:1141
+    #14 0x55c93ffaf159 in cmd_report tools/perf/builtin-report.c:1805
+    #15 0x55c94000c05c in report_events tools/perf/builtin-mem.c:374
+    #16 0x55c94000d96d in cmd_mem tools/perf/builtin-mem.c:516
+    #17 0x55c9400e44ee in run_builtin tools/perf/perf.c:350
+    #18 0x55c9400e4a5a in handle_internal_command tools/perf/perf.c:403
+    #19 0x55c9400e4e22 in run_argv tools/perf/perf.c:447
+    #20 0x55c9400e53ad in main tools/perf/perf.c:561
+    #21 0x7f28170456c9 in __libc_start_call_main
+../sysdeps/nptl/libc_start_call_main.h:58
+    #22 0x7f2817045784 in __libc_start_main_impl ../csu/libc-start.c:360
+    #23 0x55c93ff544c0 in _start (/tmp/perf/perf+0x19a4c0) (BuildId:
+84899b0e8c7d3a3eaa67b2eb35e3d8b2f8cd4c93)
+
+Address 0x7f2813331920 is located in stack of thread T0 at offset 32 in frame
+    #0 0x55c94046e85e in hist_browser__run ui/browsers/hists.c:746
+
+  This frame has 1 object(s):
+    [32, 192) 'title' (line 747) <== Memory access at offset 32 is
+inside this variable
+HINT: this may be a false positive if your program uses some custom
+stack unwind mechanism, swapcontext or vfork
+```
+hist_browser__run isn't on the stack so the asan error looks legit.
+There's no clean init/exit on struct ui_browser so I may be trading a
+use-after-return for a memory leak, but that seems look a good trade
+anyway.
+
+Fixes: 05e8b0804ec4 ("perf ui browser: Stop using 'self'")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Ben Gainey <ben.gainey@arm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: K Prateek Nayak <kprateek.nayak@amd.com>
+Cc: Li Dong <lidong@vivo.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Oliver Upton <oliver.upton@linux.dev>
+Cc: Paran Lee <p4ranlee@gmail.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Sun Haiyong <sunhaiyong@loongson.cn>
+Cc: Tim Chen <tim.c.chen@linux.intel.com>
+Cc: Yanteng Si <siyanteng@loongson.cn>
+Cc: Yicong Yang <yangyicong@hisilicon.com>
+Link: https://lore.kernel.org/r/20240507183545.1236093-2-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/ui/browser.c | 4 +++-
+ tools/perf/ui/browser.h | 2 +-
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
+index 603d11283cbdc..c4cdf2ea69b72 100644
+--- a/tools/perf/ui/browser.c
++++ b/tools/perf/ui/browser.c
+@@ -287,7 +287,8 @@ int ui_browser__show(struct ui_browser *browser, const char *title,
+       mutex_lock(&ui__lock);
+       __ui_browser__show_title(browser, title);
+-      browser->title = title;
++      free(browser->title);
++      browser->title = strdup(title);
+       zfree(&browser->helpline);
+       va_start(ap, helpline);
+@@ -304,6 +305,7 @@ void ui_browser__hide(struct ui_browser *browser)
+       mutex_lock(&ui__lock);
+       ui_helpline__pop();
+       zfree(&browser->helpline);
++      zfree(&browser->title);
+       mutex_unlock(&ui__lock);
+ }
+diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
+index 510ce45540501..6e98d5f8f71cc 100644
+--- a/tools/perf/ui/browser.h
++++ b/tools/perf/ui/browser.h
+@@ -21,7 +21,7 @@ struct ui_browser {
+       u8            extra_title_lines;
+       int           current_color;
+       void          *priv;
+-      const char    *title;
++      char          *title;
+       char          *helpline;
+       const char    *no_samples_msg;
+       void          (*refresh_dimensions)(struct ui_browser *browser);
+-- 
+2.43.0
+
diff --git a/queue-6.6/phy-qcom-qmp-combo-fix-duplicate-return-in-qmp_v4_co.patch b/queue-6.6/phy-qcom-qmp-combo-fix-duplicate-return-in-qmp_v4_co.patch
new file mode 100644 (file)
index 0000000..e098e74
--- /dev/null
@@ -0,0 +1,38 @@
+From 43e494c60bee0a54ad8fb776161ec6ffd35953b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Feb 2024 18:05:13 +0100
+Subject: phy: qcom: qmp-combo: fix duplicate return in qmp_v4_configure_dp_phy
+
+From: Neil Armstrong <neil.armstrong@linaro.org>
+
+[ Upstream commit e298ae7caafcc429e0fc4b3779f1738c0acc5dac ]
+
+Remove duplicate "return 0" in qmp_v4_configure_dp_phy()
+
+Fixes: 186ad90aa49f ("phy: qcom: qmp-combo: reuse register layouts for even more registers")
+Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Link: https://lore.kernel.org/r/20240228-topic-sm8x50-upstream-phy-combo-fix-duplicate-return-v1-1-60027a37cab1@linaro.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+index dce002e232ee9..54fb5fca1c422 100644
+--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
++++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+@@ -2334,8 +2334,6 @@ static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp)
+       writel(0x20, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]);
+       return 0;
+-
+-      return 0;
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.6/pinctrl-qcom-pinctrl-sm7150-fix-sdc1-and-ufs-special.patch b/queue-6.6/pinctrl-qcom-pinctrl-sm7150-fix-sdc1-and-ufs-special.patch
new file mode 100644 (file)
index 0000000..40f8790
--- /dev/null
@@ -0,0 +1,81 @@
+From 3ef3c1744950befa4e82a96744733f61659b8b9d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Apr 2024 23:32:45 +0300
+Subject: pinctrl: qcom: pinctrl-sm7150: Fix sdc1 and ufs special pins regs
+
+From: Danila Tikhonov <danila@jiaxyga.com>
+
+[ Upstream commit 5ed79863fae5c06eb33f5cd6b6bdf22dd7089392 ]
+
+SDC1 and UFS_RESET special pins are located in the west memory bank.
+
+SDC1 have address 0x359a000:
+0x3500000 (TLMM BASE) + 0x0 (WEST) + 0x9a000 (SDC1_OFFSET) = 0x359a000
+
+UFS_RESET have address 0x359f000:
+0x3500000 (TLMM BASE) + 0x0 (WEST) + 0x9f000 (UFS_OFFSET) = 0x359a000
+
+Fixes: b915395c9e04 ("pinctrl: qcom: Add SM7150 pinctrl driver")
+Signed-off-by: Danila Tikhonov <danila@jiaxyga.com>
+Message-ID: <20240423203245.188480-1-danila@jiaxyga.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/qcom/pinctrl-sm7150.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/pinctrl/qcom/pinctrl-sm7150.c b/drivers/pinctrl/qcom/pinctrl-sm7150.c
+index 33657cf98fb9d..edb5984cd3519 100644
+--- a/drivers/pinctrl/qcom/pinctrl-sm7150.c
++++ b/drivers/pinctrl/qcom/pinctrl-sm7150.c
+@@ -65,7 +65,7 @@ enum {
+               .intr_detection_width = 2,              \
+       }
+-#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv)    \
++#define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \
+       {                                               \
+               .grp = PINCTRL_PINGROUP(#pg_name,       \
+                       pg_name##_pins,                 \
+@@ -75,7 +75,7 @@ enum {
+               .intr_cfg_reg = 0,                      \
+               .intr_status_reg = 0,                   \
+               .intr_target_reg = 0,                   \
+-              .tile = SOUTH,                          \
++              .tile = _tile,                          \
+               .mux_bit = -1,                          \
+               .pull_bit = pull,                       \
+               .drv_bit = drv,                         \
+@@ -101,7 +101,7 @@ enum {
+               .intr_cfg_reg = 0,                      \
+               .intr_status_reg = 0,                   \
+               .intr_target_reg = 0,                   \
+-              .tile = SOUTH,                          \
++              .tile = WEST,                           \
+               .mux_bit = -1,                          \
+               .pull_bit = 3,                          \
+               .drv_bit = 0,                           \
+@@ -1199,13 +1199,13 @@ static const struct msm_pingroup sm7150_groups[] = {
+       [117] = PINGROUP(117, NORTH, _, _, _, _, _, _, _, _, _),
+       [118] = PINGROUP(118, NORTH, _, _, _, _, _, _, _, _, _),
+       [119] = UFS_RESET(ufs_reset, 0x9f000),
+-      [120] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x9a000, 15, 0),
+-      [121] = SDC_QDSD_PINGROUP(sdc1_clk, 0x9a000, 13, 6),
+-      [122] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x9a000, 11, 3),
+-      [123] = SDC_QDSD_PINGROUP(sdc1_data, 0x9a000, 9, 0),
+-      [124] = SDC_QDSD_PINGROUP(sdc2_clk, 0x98000, 14, 6),
+-      [125] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x98000, 11, 3),
+-      [126] = SDC_QDSD_PINGROUP(sdc2_data, 0x98000, 9, 0),
++      [120] = SDC_QDSD_PINGROUP(sdc1_rclk, WEST, 0x9a000, 15, 0),
++      [121] = SDC_QDSD_PINGROUP(sdc1_clk, WEST, 0x9a000, 13, 6),
++      [122] = SDC_QDSD_PINGROUP(sdc1_cmd, WEST, 0x9a000, 11, 3),
++      [123] = SDC_QDSD_PINGROUP(sdc1_data, WEST, 0x9a000, 9, 0),
++      [124] = SDC_QDSD_PINGROUP(sdc2_clk, SOUTH, 0x98000, 14, 6),
++      [125] = SDC_QDSD_PINGROUP(sdc2_cmd, SOUTH, 0x98000, 11, 3),
++      [126] = SDC_QDSD_PINGROUP(sdc2_data, SOUTH, 0x98000, 9, 0),
+ };
+ static const struct msm_gpio_wakeirq_map sm7150_pdc_map[] = {
+-- 
+2.43.0
+
diff --git a/queue-6.6/ppdev-add-an-error-check-in-register_device.patch b/queue-6.6/ppdev-add-an-error-check-in-register_device.patch
new file mode 100644 (file)
index 0000000..5b9a36e
--- /dev/null
@@ -0,0 +1,72 @@
+From 15a8e21e6489bbaafde5290e71bea09b60eec446 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Apr 2024 16:38:40 +0800
+Subject: ppdev: Add an error check in register_device
+
+From: Huai-Yuan Liu <qq810974084@gmail.com>
+
+[ Upstream commit fbf740aeb86a4fe82ad158d26d711f2f3be79b3e ]
+
+In register_device, the return value of ida_simple_get is unchecked,
+in witch ida_simple_get will use an invalid index value.
+
+To address this issue, index should be checked after ida_simple_get. When
+the index value is abnormal, a warning message should be printed, the port
+should be dropped, and the value should be recorded.
+
+Fixes: 9a69645dde11 ("ppdev: fix registering same device name")
+Signed-off-by: Huai-Yuan Liu <qq810974084@gmail.com>
+Link: https://lore.kernel.org/r/20240412083840.234085-1-qq810974084@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/ppdev.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
+index ee951b265213f..58e9dcc2a3087 100644
+--- a/drivers/char/ppdev.c
++++ b/drivers/char/ppdev.c
+@@ -296,28 +296,35 @@ static int register_device(int minor, struct pp_struct *pp)
+       if (!port) {
+               pr_warn("%s: no associated port!\n", name);
+               rc = -ENXIO;
+-              goto err;
++              goto err_free_name;
+       }
+       index = ida_alloc(&ida_index, GFP_KERNEL);
++      if (index < 0) {
++              pr_warn("%s: failed to get index!\n", name);
++              rc = index;
++              goto err_put_port;
++      }
++
+       memset(&ppdev_cb, 0, sizeof(ppdev_cb));
+       ppdev_cb.irq_func = pp_irq;
+       ppdev_cb.flags = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0;
+       ppdev_cb.private = pp;
+       pdev = parport_register_dev_model(port, name, &ppdev_cb, index);
+-      parport_put_port(port);
+       if (!pdev) {
+               pr_warn("%s: failed to register device!\n", name);
+               rc = -ENXIO;
+               ida_free(&ida_index, index);
+-              goto err;
++              goto err_put_port;
+       }
+       pp->pdev = pdev;
+       pp->index = index;
+       dev_dbg(&pdev->dev, "registered pardevice\n");
+-err:
++err_put_port:
++      parport_put_port(port);
++err_free_name:
+       kfree(name);
+       return rc;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/ppdev-remove-usage-of-the-deprecated-ida_simple_xx-a.patch b/queue-6.6/ppdev-remove-usage-of-the-deprecated-ida_simple_xx-a.patch
new file mode 100644 (file)
index 0000000..fa7234c
--- /dev/null
@@ -0,0 +1,57 @@
+From a8a45d9c8085707ebe7744e9a8d97c1e7f6a71ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Dec 2023 06:01:47 +0100
+Subject: ppdev: Remove usage of the deprecated ida_simple_xx() API
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit d8407f71ebeaeb6f50bd89791837873e44609708 ]
+
+ida_alloc() and ida_free() should be preferred to the deprecated
+ida_simple_get() and ida_simple_remove().
+
+This is less verbose.
+
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Link: https://lore.kernel.org/r/ba9da12fdd5cdb2c28180b7160af5042447d803f.1702962092.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: fbf740aeb86a ("ppdev: Add an error check in register_device")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/ppdev.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
+index 4c188e9e477cd..ee951b265213f 100644
+--- a/drivers/char/ppdev.c
++++ b/drivers/char/ppdev.c
+@@ -299,7 +299,7 @@ static int register_device(int minor, struct pp_struct *pp)
+               goto err;
+       }
+-      index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL);
++      index = ida_alloc(&ida_index, GFP_KERNEL);
+       memset(&ppdev_cb, 0, sizeof(ppdev_cb));
+       ppdev_cb.irq_func = pp_irq;
+       ppdev_cb.flags = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0;
+@@ -310,7 +310,7 @@ static int register_device(int minor, struct pp_struct *pp)
+       if (!pdev) {
+               pr_warn("%s: failed to register device!\n", name);
+               rc = -ENXIO;
+-              ida_simple_remove(&ida_index, index);
++              ida_free(&ida_index, index);
+               goto err;
+       }
+@@ -750,7 +750,7 @@ static int pp_release(struct inode *inode, struct file *file)
+       if (pp->pdev) {
+               parport_unregister_device(pp->pdev);
+-              ida_simple_remove(&ida_index, pp->index);
++              ida_free(&ida_index, pp->index);
+               pp->pdev = NULL;
+               pr_debug(CHRDEV "%x: unregistered pardevice\n", minor);
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/pwm-rename-pwm_apply_state-to-pwm_apply_might_sleep.patch b/queue-6.6/pwm-rename-pwm_apply_state-to-pwm_apply_might_sleep.patch
new file mode 100644 (file)
index 0000000..848198b
--- /dev/null
@@ -0,0 +1,724 @@
+From c0b445a571d62ad3b49e04d9bd08f40dbc912ef6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Dec 2023 16:30:24 +0000
+Subject: pwm: Rename pwm_apply_state() to pwm_apply_might_sleep()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sean Young <sean@mess.org>
+
+[ Upstream commit c748a6d77c06a78651030e17da6beb278a1c9470 ]
+
+In order to introduce a pwm api which can be used from atomic context,
+we will need two functions for applying pwm changes:
+
+       int pwm_apply_might_sleep(struct pwm *, struct pwm_state *);
+       int pwm_apply_atomic(struct pwm *, struct pwm_state *);
+
+This commit just deals with renaming pwm_apply_state(), a following
+commit will introduce the pwm_apply_atomic() function.
+
+Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Acked-by: Guenter Roeck <linux@roeck-us.net>
+Acked-by: Mark Brown <broonie@kernel.org>
+Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> # for input
+Acked-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Jani Nikula <jani.nikula@intel.com>
+Acked-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
+Stable-dep-of: 974afccd3794 ("leds: pwm: Disable PWM when going to suspend")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/driver-api/pwm.rst              |  8 +++---
+ MAINTAINERS                                   |  2 +-
+ .../gpu/drm/i915/display/intel_backlight.c    |  6 ++--
+ drivers/gpu/drm/solomon/ssd130x.c             |  2 +-
+ drivers/hwmon/pwm-fan.c                       |  8 +++---
+ drivers/input/misc/da7280.c                   |  4 +--
+ drivers/input/misc/pwm-beeper.c               |  4 +--
+ drivers/input/misc/pwm-vibra.c                |  8 +++---
+ drivers/leds/leds-pwm.c                       |  2 +-
+ drivers/leds/rgb/leds-pwm-multicolor.c        |  4 +--
+ drivers/media/rc/ir-rx51.c                    |  4 +--
+ drivers/media/rc/pwm-ir-tx.c                  |  4 +--
+ drivers/platform/x86/lenovo-yogabook.c        |  2 +-
+ drivers/pwm/core.c                            | 18 ++++++------
+ drivers/pwm/pwm-twl-led.c                     |  2 +-
+ drivers/pwm/pwm-vt8500.c                      |  2 +-
+ drivers/pwm/sysfs.c                           | 10 +++----
+ drivers/regulator/pwm-regulator.c             |  4 +--
+ drivers/video/backlight/lm3630a_bl.c          |  2 +-
+ drivers/video/backlight/lp855x_bl.c           |  2 +-
+ drivers/video/backlight/pwm_bl.c              | 12 ++++----
+ drivers/video/fbdev/ssd1307fb.c               |  2 +-
+ include/linux/pwm.h                           | 28 +++++++++----------
+ 23 files changed, 70 insertions(+), 70 deletions(-)
+
+diff --git a/Documentation/driver-api/pwm.rst b/Documentation/driver-api/pwm.rst
+index 3fdc95f7a1d15..ed5ec98165381 100644
+--- a/Documentation/driver-api/pwm.rst
++++ b/Documentation/driver-api/pwm.rst
+@@ -41,7 +41,7 @@ the getter, devm_pwm_get() and devm_fwnode_pwm_get(), also exist.
+ After being requested, a PWM has to be configured using::
+-      int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state);
++      int pwm_apply_might_sleep(struct pwm_device *pwm, struct pwm_state *state);
+ This API controls both the PWM period/duty_cycle config and the
+ enable/disable state.
+@@ -57,13 +57,13 @@ If supported by the driver, the signal can be optimized, for example to improve
+ EMI by phase shifting the individual channels of a chip.
+ The pwm_config(), pwm_enable() and pwm_disable() functions are just wrappers
+-around pwm_apply_state() and should not be used if the user wants to change
++around pwm_apply_might_sleep() and should not be used if the user wants to change
+ several parameter at once. For example, if you see pwm_config() and
+ pwm_{enable,disable}() calls in the same function, this probably means you
+-should switch to pwm_apply_state().
++should switch to pwm_apply_might_sleep().
+ The PWM user API also allows one to query the PWM state that was passed to the
+-last invocation of pwm_apply_state() using pwm_get_state(). Note this is
++last invocation of pwm_apply_might_sleep() using pwm_get_state(). Note this is
+ different to what the driver has actually implemented if the request cannot be
+ satisfied exactly with the hardware in use. There is currently no way for
+ consumers to get the actually implemented settings.
+diff --git a/MAINTAINERS b/MAINTAINERS
+index b778fdbf744ae..f09415b2b3c5c 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -17388,7 +17388,7 @@ F:     drivers/video/backlight/pwm_bl.c
+ F:    include/dt-bindings/pwm/
+ F:    include/linux/pwm.h
+ F:    include/linux/pwm_backlight.h
+-K:    pwm_(config|apply_state|ops)
++K:    pwm_(config|apply_might_sleep|ops)
+ PXA GPIO DRIVER
+ M:    Robert Jarzmik <robert.jarzmik@free.fr>
+diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c
+index 2e8f17c045222..ff9b9918b0a13 100644
+--- a/drivers/gpu/drm/i915/display/intel_backlight.c
++++ b/drivers/gpu/drm/i915/display/intel_backlight.c
+@@ -274,7 +274,7 @@ static void ext_pwm_set_backlight(const struct drm_connector_state *conn_state,
+       struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
+       pwm_set_relative_duty_cycle(&panel->backlight.pwm_state, level, 100);
+-      pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state);
++      pwm_apply_might_sleep(panel->backlight.pwm, &panel->backlight.pwm_state);
+ }
+ static void
+@@ -427,7 +427,7 @@ static void ext_pwm_disable_backlight(const struct drm_connector_state *old_conn
+       intel_backlight_set_pwm_level(old_conn_state, level);
+       panel->backlight.pwm_state.enabled = false;
+-      pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state);
++      pwm_apply_might_sleep(panel->backlight.pwm, &panel->backlight.pwm_state);
+ }
+ void intel_backlight_disable(const struct drm_connector_state *old_conn_state)
+@@ -749,7 +749,7 @@ static void ext_pwm_enable_backlight(const struct intel_crtc_state *crtc_state,
+       pwm_set_relative_duty_cycle(&panel->backlight.pwm_state, level, 100);
+       panel->backlight.pwm_state.enabled = true;
+-      pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state);
++      pwm_apply_might_sleep(panel->backlight.pwm, &panel->backlight.pwm_state);
+ }
+ static void __intel_backlight_enable(const struct intel_crtc_state *crtc_state,
+diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
+index 78272b1f9d5b1..deec6acdcf646 100644
+--- a/drivers/gpu/drm/solomon/ssd130x.c
++++ b/drivers/gpu/drm/solomon/ssd130x.c
+@@ -267,7 +267,7 @@ static int ssd130x_pwm_enable(struct ssd130x_device *ssd130x)
+       pwm_init_state(ssd130x->pwm, &pwmstate);
+       pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
+-      pwm_apply_state(ssd130x->pwm, &pwmstate);
++      pwm_apply_might_sleep(ssd130x->pwm, &pwmstate);
+       /* Enable the PWM */
+       pwm_enable(ssd130x->pwm);
+diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
+index 6e4516c2ab894..b67bc9e833c01 100644
+--- a/drivers/hwmon/pwm-fan.c
++++ b/drivers/hwmon/pwm-fan.c
+@@ -151,7 +151,7 @@ static int pwm_fan_power_on(struct pwm_fan_ctx *ctx)
+       }
+       state->enabled = true;
+-      ret = pwm_apply_state(ctx->pwm, state);
++      ret = pwm_apply_might_sleep(ctx->pwm, state);
+       if (ret) {
+               dev_err(ctx->dev, "failed to enable PWM\n");
+               goto disable_regulator;
+@@ -181,7 +181,7 @@ static int pwm_fan_power_off(struct pwm_fan_ctx *ctx)
+       state->enabled = false;
+       state->duty_cycle = 0;
+-      ret = pwm_apply_state(ctx->pwm, state);
++      ret = pwm_apply_might_sleep(ctx->pwm, state);
+       if (ret) {
+               dev_err(ctx->dev, "failed to disable PWM\n");
+               return ret;
+@@ -207,7 +207,7 @@ static int  __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
+               period = state->period;
+               state->duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
+-              ret = pwm_apply_state(ctx->pwm, state);
++              ret = pwm_apply_might_sleep(ctx->pwm, state);
+               if (ret)
+                       return ret;
+               ret = pwm_fan_power_on(ctx);
+@@ -278,7 +278,7 @@ static int pwm_fan_update_enable(struct pwm_fan_ctx *ctx, long val)
+                                                   state,
+                                                   &enable_regulator);
+-                      pwm_apply_state(ctx->pwm, state);
++                      pwm_apply_might_sleep(ctx->pwm, state);
+                       pwm_fan_switch_power(ctx, enable_regulator);
+                       pwm_fan_update_state(ctx, 0);
+               }
+diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c
+index ce82548916bbc..c1fa75c0f970a 100644
+--- a/drivers/input/misc/da7280.c
++++ b/drivers/input/misc/da7280.c
+@@ -352,7 +352,7 @@ static int da7280_haptic_set_pwm(struct da7280_haptic *haptics, bool enabled)
+               state.duty_cycle = period_mag_multi;
+       }
+-      error = pwm_apply_state(haptics->pwm_dev, &state);
++      error = pwm_apply_might_sleep(haptics->pwm_dev, &state);
+       if (error)
+               dev_err(haptics->dev, "Failed to apply pwm state: %d\n", error);
+@@ -1175,7 +1175,7 @@ static int da7280_probe(struct i2c_client *client)
+               /* Sync up PWM state and ensure it is off. */
+               pwm_init_state(haptics->pwm_dev, &state);
+               state.enabled = false;
+-              error = pwm_apply_state(haptics->pwm_dev, &state);
++              error = pwm_apply_might_sleep(haptics->pwm_dev, &state);
+               if (error) {
+                       dev_err(dev, "Failed to apply PWM state: %d\n", error);
+                       return error;
+diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
+index 1e731d8397c6f..5b9aedf4362f4 100644
+--- a/drivers/input/misc/pwm-beeper.c
++++ b/drivers/input/misc/pwm-beeper.c
+@@ -39,7 +39,7 @@ static int pwm_beeper_on(struct pwm_beeper *beeper, unsigned long period)
+       state.period = period;
+       pwm_set_relative_duty_cycle(&state, 50, 100);
+-      error = pwm_apply_state(beeper->pwm, &state);
++      error = pwm_apply_might_sleep(beeper->pwm, &state);
+       if (error)
+               return error;
+@@ -138,7 +138,7 @@ static int pwm_beeper_probe(struct platform_device *pdev)
+       /* Sync up PWM state and ensure it is off. */
+       pwm_init_state(beeper->pwm, &state);
+       state.enabled = false;
+-      error = pwm_apply_state(beeper->pwm, &state);
++      error = pwm_apply_might_sleep(beeper->pwm, &state);
+       if (error) {
+               dev_err(dev, "failed to apply initial PWM state: %d\n",
+                       error);
+diff --git a/drivers/input/misc/pwm-vibra.c b/drivers/input/misc/pwm-vibra.c
+index acac79c488aa1..3e5ed685ed8f5 100644
+--- a/drivers/input/misc/pwm-vibra.c
++++ b/drivers/input/misc/pwm-vibra.c
+@@ -56,7 +56,7 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
+       pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff);
+       state.enabled = true;
+-      err = pwm_apply_state(vibrator->pwm, &state);
++      err = pwm_apply_might_sleep(vibrator->pwm, &state);
+       if (err) {
+               dev_err(pdev, "failed to apply pwm state: %d\n", err);
+               return err;
+@@ -67,7 +67,7 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
+               state.duty_cycle = vibrator->direction_duty_cycle;
+               state.enabled = true;
+-              err = pwm_apply_state(vibrator->pwm_dir, &state);
++              err = pwm_apply_might_sleep(vibrator->pwm_dir, &state);
+               if (err) {
+                       dev_err(pdev, "failed to apply dir-pwm state: %d\n", err);
+                       pwm_disable(vibrator->pwm);
+@@ -160,7 +160,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
+       /* Sync up PWM state and ensure it is off. */
+       pwm_init_state(vibrator->pwm, &state);
+       state.enabled = false;
+-      err = pwm_apply_state(vibrator->pwm, &state);
++      err = pwm_apply_might_sleep(vibrator->pwm, &state);
+       if (err) {
+               dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
+                       err);
+@@ -174,7 +174,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
+               /* Sync up PWM state and ensure it is off. */
+               pwm_init_state(vibrator->pwm_dir, &state);
+               state.enabled = false;
+-              err = pwm_apply_state(vibrator->pwm_dir, &state);
++              err = pwm_apply_might_sleep(vibrator->pwm_dir, &state);
+               if (err) {
+                       dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
+                               err);
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index 2b3bf1353b707..4e3936a39d0ed 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -54,7 +54,7 @@ static int led_pwm_set(struct led_classdev *led_cdev,
+       led_dat->pwmstate.duty_cycle = duty;
+       led_dat->pwmstate.enabled = true;
+-      return pwm_apply_state(led_dat->pwm, &led_dat->pwmstate);
++      return pwm_apply_might_sleep(led_dat->pwm, &led_dat->pwmstate);
+ }
+ __attribute__((nonnull))
+diff --git a/drivers/leds/rgb/leds-pwm-multicolor.c b/drivers/leds/rgb/leds-pwm-multicolor.c
+index 46cd062b8b24c..e1a81e0109e8a 100644
+--- a/drivers/leds/rgb/leds-pwm-multicolor.c
++++ b/drivers/leds/rgb/leds-pwm-multicolor.c
+@@ -51,8 +51,8 @@ static int led_pwm_mc_set(struct led_classdev *cdev,
+               priv->leds[i].state.duty_cycle = duty;
+               priv->leds[i].state.enabled = duty > 0;
+-              ret = pwm_apply_state(priv->leds[i].pwm,
+-                                    &priv->leds[i].state);
++              ret = pwm_apply_might_sleep(priv->leds[i].pwm,
++                                          &priv->leds[i].state);
+               if (ret)
+                       break;
+       }
+diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
+index 13e81bf8005df..39a7e2db63a78 100644
+--- a/drivers/media/rc/ir-rx51.c
++++ b/drivers/media/rc/ir-rx51.c
+@@ -34,13 +34,13 @@ struct ir_rx51 {
+ static inline void ir_rx51_on(struct ir_rx51 *ir_rx51)
+ {
+       ir_rx51->state.enabled = true;
+-      pwm_apply_state(ir_rx51->pwm, &ir_rx51->state);
++      pwm_apply_might_sleep(ir_rx51->pwm, &ir_rx51->state);
+ }
+ static inline void ir_rx51_off(struct ir_rx51 *ir_rx51)
+ {
+       ir_rx51->state.enabled = false;
+-      pwm_apply_state(ir_rx51->pwm, &ir_rx51->state);
++      pwm_apply_might_sleep(ir_rx51->pwm, &ir_rx51->state);
+ }
+ static int init_timing_params(struct ir_rx51 *ir_rx51)
+diff --git a/drivers/media/rc/pwm-ir-tx.c b/drivers/media/rc/pwm-ir-tx.c
+index 7732054c4621e..4a6fafe7a249e 100644
+--- a/drivers/media/rc/pwm-ir-tx.c
++++ b/drivers/media/rc/pwm-ir-tx.c
+@@ -67,7 +67,7 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
+       for (i = 0; i < count; i++) {
+               state.enabled = !(i % 2);
+-              pwm_apply_state(pwm, &state);
++              pwm_apply_might_sleep(pwm, &state);
+               edge = ktime_add_us(edge, txbuf[i]);
+               delta = ktime_us_delta(edge, ktime_get());
+@@ -76,7 +76,7 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
+       }
+       state.enabled = false;
+-      pwm_apply_state(pwm, &state);
++      pwm_apply_might_sleep(pwm, &state);
+       return count;
+ }
+diff --git a/drivers/platform/x86/lenovo-yogabook.c b/drivers/platform/x86/lenovo-yogabook.c
+index b8d0239192cbf..fd62bf746ebde 100644
+--- a/drivers/platform/x86/lenovo-yogabook.c
++++ b/drivers/platform/x86/lenovo-yogabook.c
+@@ -435,7 +435,7 @@ static int yogabook_pdev_set_kbd_backlight(struct yogabook_data *data, u8 level)
+               .enabled = level,
+       };
+-      pwm_apply_state(data->kbd_bl_pwm, &state);
++      pwm_apply_might_sleep(data->kbd_bl_pwm, &state);
+       gpiod_set_value(data->kbd_bl_led_enable, level ? 1 : 0);
+       return 0;
+ }
+diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
+index 0c8c63239adbf..a1a355ba23837 100644
+--- a/drivers/pwm/core.c
++++ b/drivers/pwm/core.c
+@@ -382,8 +382,8 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+ }
+ EXPORT_SYMBOL_GPL(pwm_request_from_chip);
+-static void pwm_apply_state_debug(struct pwm_device *pwm,
+-                                const struct pwm_state *state)
++static void pwm_apply_debug(struct pwm_device *pwm,
++                          const struct pwm_state *state)
+ {
+       struct pwm_state *last = &pwm->last;
+       struct pwm_chip *chip = pwm->chip;
+@@ -489,11 +489,11 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
+ }
+ /**
+- * pwm_apply_state() - atomically apply a new state to a PWM device
++ * pwm_apply_might_sleep() - atomically apply a new state to a PWM device
+  * @pwm: PWM device
+  * @state: new state to apply
+  */
+-int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
++int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state)
+ {
+       struct pwm_chip *chip;
+       int err;
+@@ -501,7 +501,7 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
+       /*
+        * Some lowlevel driver's implementations of .apply() make use of
+        * mutexes, also with some drivers only returning when the new
+-       * configuration is active calling pwm_apply_state() from atomic context
++       * configuration is active calling pwm_apply_might_sleep() from atomic context
+        * is a bad idea. So make it explicit that calling this function might
+        * sleep.
+        */
+@@ -531,11 +531,11 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
+        * only do this after pwm->state was applied as some
+        * implementations of .get_state depend on this
+        */
+-      pwm_apply_state_debug(pwm, state);
++      pwm_apply_debug(pwm, state);
+       return 0;
+ }
+-EXPORT_SYMBOL_GPL(pwm_apply_state);
++EXPORT_SYMBOL_GPL(pwm_apply_might_sleep);
+ /**
+  * pwm_capture() - capture and report a PWM signal
+@@ -593,7 +593,7 @@ int pwm_adjust_config(struct pwm_device *pwm)
+               state.period = pargs.period;
+               state.polarity = pargs.polarity;
+-              return pwm_apply_state(pwm, &state);
++              return pwm_apply_might_sleep(pwm, &state);
+       }
+       /*
+@@ -616,7 +616,7 @@ int pwm_adjust_config(struct pwm_device *pwm)
+               state.duty_cycle = state.period - state.duty_cycle;
+       }
+-      return pwm_apply_state(pwm, &state);
++      return pwm_apply_might_sleep(pwm, &state);
+ }
+ EXPORT_SYMBOL_GPL(pwm_adjust_config);
+diff --git a/drivers/pwm/pwm-twl-led.c b/drivers/pwm/pwm-twl-led.c
+index 8fb84b4418538..65205449ed79c 100644
+--- a/drivers/pwm/pwm-twl-led.c
++++ b/drivers/pwm/pwm-twl-led.c
+@@ -172,7 +172,7 @@ static int twl4030_pwmled_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+        * We cannot skip calling ->config even if state->period ==
+        * pwm->state.period && state->duty_cycle == pwm->state.duty_cycle
+        * because we might have exited early in the last call to
+-       * pwm_apply_state because of !state->enabled and so the two values in
++       * pwm_apply_might_sleep because of !state->enabled and so the two values in
+        * pwm->state might not be configured in hardware.
+        */
+       ret = twl4030_pwmled_config(pwm->chip, pwm,
+diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c
+index 6d46db51daacc..ba1204e18afbb 100644
+--- a/drivers/pwm/pwm-vt8500.c
++++ b/drivers/pwm/pwm-vt8500.c
+@@ -206,7 +206,7 @@ static int vt8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+        * We cannot skip calling ->config even if state->period ==
+        * pwm->state.period && state->duty_cycle == pwm->state.duty_cycle
+        * because we might have exited early in the last call to
+-       * pwm_apply_state because of !state->enabled and so the two values in
++       * pwm_apply_might_sleep because of !state->enabled and so the two values in
+        * pwm->state might not be configured in hardware.
+        */
+       err = vt8500_pwm_config(pwm->chip, pwm, state->duty_cycle, state->period);
+diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
+index 8d1254761e4dd..052ccadbdabfe 100644
+--- a/drivers/pwm/sysfs.c
++++ b/drivers/pwm/sysfs.c
+@@ -62,7 +62,7 @@ static ssize_t period_store(struct device *child,
+       mutex_lock(&export->lock);
+       pwm_get_state(pwm, &state);
+       state.period = val;
+-      ret = pwm_apply_state(pwm, &state);
++      ret = pwm_apply_might_sleep(pwm, &state);
+       mutex_unlock(&export->lock);
+       return ret ? : size;
+@@ -97,7 +97,7 @@ static ssize_t duty_cycle_store(struct device *child,
+       mutex_lock(&export->lock);
+       pwm_get_state(pwm, &state);
+       state.duty_cycle = val;
+-      ret = pwm_apply_state(pwm, &state);
++      ret = pwm_apply_might_sleep(pwm, &state);
+       mutex_unlock(&export->lock);
+       return ret ? : size;
+@@ -144,7 +144,7 @@ static ssize_t enable_store(struct device *child,
+               goto unlock;
+       }
+-      ret = pwm_apply_state(pwm, &state);
++      ret = pwm_apply_might_sleep(pwm, &state);
+ unlock:
+       mutex_unlock(&export->lock);
+@@ -194,7 +194,7 @@ static ssize_t polarity_store(struct device *child,
+       mutex_lock(&export->lock);
+       pwm_get_state(pwm, &state);
+       state.polarity = polarity;
+-      ret = pwm_apply_state(pwm, &state);
++      ret = pwm_apply_might_sleep(pwm, &state);
+       mutex_unlock(&export->lock);
+       return ret ? : size;
+@@ -401,7 +401,7 @@ static int pwm_class_apply_state(struct pwm_export *export,
+                                struct pwm_device *pwm,
+                                struct pwm_state *state)
+ {
+-      int ret = pwm_apply_state(pwm, state);
++      int ret = pwm_apply_might_sleep(pwm, state);
+       /* release lock taken in pwm_class_get_state */
+       mutex_unlock(&export->lock);
+diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
+index e33d10df7a763..226ca4c62673f 100644
+--- a/drivers/regulator/pwm-regulator.c
++++ b/drivers/regulator/pwm-regulator.c
+@@ -90,7 +90,7 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev,
+       pwm_set_relative_duty_cycle(&pstate,
+                       drvdata->duty_cycle_table[selector].dutycycle, 100);
+-      ret = pwm_apply_state(drvdata->pwm, &pstate);
++      ret = pwm_apply_might_sleep(drvdata->pwm, &pstate);
+       if (ret) {
+               dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
+               return ret;
+@@ -219,7 +219,7 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
+       pwm_set_relative_duty_cycle(&pstate, dutycycle, duty_unit);
+-      ret = pwm_apply_state(drvdata->pwm, &pstate);
++      ret = pwm_apply_might_sleep(drvdata->pwm, &pstate);
+       if (ret) {
+               dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
+               return ret;
+diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c
+index 7115d7bb2a141..26ff4178cc161 100644
+--- a/drivers/video/backlight/lm3630a_bl.c
++++ b/drivers/video/backlight/lm3630a_bl.c
+@@ -180,7 +180,7 @@ static int lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max)
+       pchip->pwmd_state.enabled = pchip->pwmd_state.duty_cycle ? true : false;
+-      return pwm_apply_state(pchip->pwmd, &pchip->pwmd_state);
++      return pwm_apply_might_sleep(pchip->pwmd, &pchip->pwmd_state);
+ }
+ /* update and get brightness */
+diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
+index da1f124db69c0..7075bfab59c4d 100644
+--- a/drivers/video/backlight/lp855x_bl.c
++++ b/drivers/video/backlight/lp855x_bl.c
+@@ -234,7 +234,7 @@ static int lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
+       state.duty_cycle = div_u64(br * state.period, max_br);
+       state.enabled = state.duty_cycle;
+-      return pwm_apply_state(lp->pwm, &state);
++      return pwm_apply_might_sleep(lp->pwm, &state);
+ }
+ static int lp855x_bl_update_status(struct backlight_device *bl)
+diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
+index 289bd9ce4d36d..35c716e9043c3 100644
+--- a/drivers/video/backlight/pwm_bl.c
++++ b/drivers/video/backlight/pwm_bl.c
+@@ -103,7 +103,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
+               pwm_get_state(pb->pwm, &state);
+               state.duty_cycle = compute_duty_cycle(pb, brightness, &state);
+               state.enabled = true;
+-              pwm_apply_state(pb->pwm, &state);
++              pwm_apply_might_sleep(pb->pwm, &state);
+               pwm_backlight_power_on(pb);
+       } else {
+@@ -120,7 +120,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
+                * inactive output.
+                */
+               state.enabled = !pb->power_supply && !pb->enable_gpio;
+-              pwm_apply_state(pb->pwm, &state);
++              pwm_apply_might_sleep(pb->pwm, &state);
+       }
+       if (pb->notify_after)
+@@ -528,7 +528,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
+       if (!state.period && (data->pwm_period_ns > 0))
+               state.period = data->pwm_period_ns;
+-      ret = pwm_apply_state(pb->pwm, &state);
++      ret = pwm_apply_might_sleep(pb->pwm, &state);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
+                       ret);
+@@ -633,7 +633,7 @@ static void pwm_backlight_remove(struct platform_device *pdev)
+       pwm_get_state(pb->pwm, &state);
+       state.duty_cycle = 0;
+       state.enabled = false;
+-      pwm_apply_state(pb->pwm, &state);
++      pwm_apply_might_sleep(pb->pwm, &state);
+       if (pb->exit)
+               pb->exit(&pdev->dev);
+@@ -649,7 +649,7 @@ static void pwm_backlight_shutdown(struct platform_device *pdev)
+       pwm_get_state(pb->pwm, &state);
+       state.duty_cycle = 0;
+       state.enabled = false;
+-      pwm_apply_state(pb->pwm, &state);
++      pwm_apply_might_sleep(pb->pwm, &state);
+ }
+ #ifdef CONFIG_PM_SLEEP
+@@ -673,7 +673,7 @@ static int pwm_backlight_suspend(struct device *dev)
+       pwm_get_state(pb->pwm, &state);
+       state.duty_cycle = 0;
+       state.enabled = false;
+-      pwm_apply_state(pb->pwm, &state);
++      pwm_apply_might_sleep(pb->pwm, &state);
+       if (pb->notify_after)
+               pb->notify_after(pb->dev, 0);
+diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
+index 5ae48e36fccb4..1a4f90ea7d5a8 100644
+--- a/drivers/video/fbdev/ssd1307fb.c
++++ b/drivers/video/fbdev/ssd1307fb.c
+@@ -347,7 +347,7 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
+               pwm_init_state(par->pwm, &pwmstate);
+               pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
+-              pwm_apply_state(par->pwm, &pwmstate);
++              pwm_apply_might_sleep(par->pwm, &pwmstate);
+               /* Enable the PWM */
+               pwm_enable(par->pwm);
+diff --git a/include/linux/pwm.h b/include/linux/pwm.h
+index fe0f38ce1bdee..63426d8255e4a 100644
+--- a/include/linux/pwm.h
++++ b/include/linux/pwm.h
+@@ -95,8 +95,8 @@ struct pwm_device {
+  * @state: state to fill with the current PWM state
+  *
+  * The returned PWM state represents the state that was applied by a previous call to
+- * pwm_apply_state(). Drivers may have to slightly tweak that state before programming it to
+- * hardware. If pwm_apply_state() was never called, this returns either the current hardware
++ * pwm_apply_might_sleep(). Drivers may have to slightly tweak that state before programming it to
++ * hardware. If pwm_apply_might_sleep() was never called, this returns either the current hardware
+  * state (if supported) or the default settings.
+  */
+ static inline void pwm_get_state(const struct pwm_device *pwm,
+@@ -160,20 +160,20 @@ static inline void pwm_get_args(const struct pwm_device *pwm,
+ }
+ /**
+- * pwm_init_state() - prepare a new state to be applied with pwm_apply_state()
++ * pwm_init_state() - prepare a new state to be applied with pwm_apply_might_sleep()
+  * @pwm: PWM device
+  * @state: state to fill with the prepared PWM state
+  *
+  * This functions prepares a state that can later be tweaked and applied
+- * to the PWM device with pwm_apply_state(). This is a convenient function
++ * to the PWM device with pwm_apply_might_sleep(). This is a convenient function
+  * that first retrieves the current PWM state and the replaces the period
+  * and polarity fields with the reference values defined in pwm->args.
+  * Once the function returns, you can adjust the ->enabled and ->duty_cycle
+- * fields according to your needs before calling pwm_apply_state().
++ * fields according to your needs before calling pwm_apply_might_sleep().
+  *
+  * ->duty_cycle is initially set to zero to avoid cases where the current
+  * ->duty_cycle value exceed the pwm_args->period one, which would trigger
+- * an error if the user calls pwm_apply_state() without adjusting ->duty_cycle
++ * an error if the user calls pwm_apply_might_sleep() without adjusting ->duty_cycle
+  * first.
+  */
+ static inline void pwm_init_state(const struct pwm_device *pwm,
+@@ -229,7 +229,7 @@ pwm_get_relative_duty_cycle(const struct pwm_state *state, unsigned int scale)
+  *
+  * pwm_init_state(pwm, &state);
+  * pwm_set_relative_duty_cycle(&state, 50, 100);
+- * pwm_apply_state(pwm, &state);
++ * pwm_apply_might_sleep(pwm, &state);
+  *
+  * This functions returns -EINVAL if @duty_cycle and/or @scale are
+  * inconsistent (@scale == 0 or @duty_cycle > @scale).
+@@ -309,7 +309,7 @@ struct pwm_chip {
+ #if IS_ENABLED(CONFIG_PWM)
+ /* PWM user APIs */
+-int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state);
++int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state);
+ int pwm_adjust_config(struct pwm_device *pwm);
+ /**
+@@ -337,7 +337,7 @@ static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
+       state.duty_cycle = duty_ns;
+       state.period = period_ns;
+-      return pwm_apply_state(pwm, &state);
++      return pwm_apply_might_sleep(pwm, &state);
+ }
+ /**
+@@ -358,7 +358,7 @@ static inline int pwm_enable(struct pwm_device *pwm)
+               return 0;
+       state.enabled = true;
+-      return pwm_apply_state(pwm, &state);
++      return pwm_apply_might_sleep(pwm, &state);
+ }
+ /**
+@@ -377,7 +377,7 @@ static inline void pwm_disable(struct pwm_device *pwm)
+               return;
+       state.enabled = false;
+-      pwm_apply_state(pwm, &state);
++      pwm_apply_might_sleep(pwm, &state);
+ }
+ /* PWM provider APIs */
+@@ -408,8 +408,8 @@ struct pwm_device *devm_fwnode_pwm_get(struct device *dev,
+                                      struct fwnode_handle *fwnode,
+                                      const char *con_id);
+ #else
+-static inline int pwm_apply_state(struct pwm_device *pwm,
+-                                const struct pwm_state *state)
++static inline int pwm_apply_might_sleep(struct pwm_device *pwm,
++                                      const struct pwm_state *state)
+ {
+       might_sleep();
+       return -ENOTSUPP;
+@@ -536,7 +536,7 @@ static inline void pwm_apply_args(struct pwm_device *pwm)
+       state.period = pwm->args.period;
+       state.usage_power = false;
+-      pwm_apply_state(pwm, &state);
++      pwm_apply_might_sleep(pwm, &state);
+ }
+ struct pwm_lookup {
+-- 
+2.43.0
+
diff --git a/queue-6.6/reapply-arm64-fpsimd-implement-lazy-restore-for-kern.patch b/queue-6.6/reapply-arm64-fpsimd-implement-lazy-restore-for-kern.patch
new file mode 100644 (file)
index 0000000..8d6230a
--- /dev/null
@@ -0,0 +1,74 @@
+From 87a7238bf9d1b72ed2f9a136b04d22d6e5db2781 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 May 2024 11:53:05 +0100
+Subject: Reapply "arm64: fpsimd: Implement lazy restore for kernel mode
+ FPSIMD"
+
+From: Will Deacon <will@kernel.org>
+
+[ Upstream commit f481bb32d60e45fb3d19ea68ce79c5629f3fc3a0 ]
+
+This reverts commit b8995a18417088bb53f87c49d200ec72a9dd4ec1.
+
+Ard managed to reproduce the dm-crypt corruption problem and got to the
+bottom of it, so re-apply the problematic patch in preparation for
+fixing things properly.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/processor.h |  1 +
+ arch/arm64/kernel/fpsimd.c         | 18 ++++++++++++++++++
+ 2 files changed, 19 insertions(+)
+
+diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
+index ce6eebd6c08bd..5b0a04810b236 100644
+--- a/arch/arm64/include/asm/processor.h
++++ b/arch/arm64/include/asm/processor.h
+@@ -169,6 +169,7 @@ struct thread_struct {
+       struct debug_info       debug;          /* debugging */
+       struct user_fpsimd_state        kernel_fpsimd_state;
++      unsigned int                    kernel_fpsimd_cpu;
+ #ifdef CONFIG_ARM64_PTR_AUTH
+       struct ptrauth_keys_user        keys_user;
+ #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
+diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
+index 55963fa64dec8..4c7bc3c01afc2 100644
+--- a/arch/arm64/kernel/fpsimd.c
++++ b/arch/arm64/kernel/fpsimd.c
+@@ -1552,12 +1552,30 @@ void do_fpsimd_exc(unsigned long esr, struct pt_regs *regs)
+ static void fpsimd_load_kernel_state(struct task_struct *task)
+ {
++      struct cpu_fp_state *last = this_cpu_ptr(&fpsimd_last_state);
++
++      /*
++       * Elide the load if this CPU holds the most recent kernel mode
++       * FPSIMD context of the current task.
++       */
++      if (last->st == &task->thread.kernel_fpsimd_state &&
++          task->thread.kernel_fpsimd_cpu == smp_processor_id())
++              return;
++
+       fpsimd_load_state(&task->thread.kernel_fpsimd_state);
+ }
+ static void fpsimd_save_kernel_state(struct task_struct *task)
+ {
++      struct cpu_fp_state cpu_fp_state = {
++              .st             = &task->thread.kernel_fpsimd_state,
++              .to_save        = FP_STATE_FPSIMD,
++      };
++
+       fpsimd_save_state(&task->thread.kernel_fpsimd_state);
++      fpsimd_bind_state_to_cpu(&cpu_fp_state);
++
++      task->thread.kernel_fpsimd_cpu = smp_processor_id();
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.6/remove-call_-read-write-_iter-functions.patch b/queue-6.6/remove-call_-read-write-_iter-functions.patch
new file mode 100644 (file)
index 0000000..da9bae8
--- /dev/null
@@ -0,0 +1,205 @@
+From 3c0ff2d825d714cd6539a14a5cefc8e9d20665d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Aug 2023 17:13:18 +0200
+Subject: remove call_{read,write}_iter() functions
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+[ Upstream commit 7c98f7cb8fda964fbc60b9307ad35e94735fa35f ]
+
+These have no clear purpose.  This is effectively a revert of commit
+bb7462b6fd64 ("vfs: use helpers for calling f_op->{read,write}_iter()").
+
+The patch was created with the help of a coccinelle script.
+
+Fixes: bb7462b6fd64 ("vfs: use helpers for calling f_op->{read,write}_iter()")
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/loop.c              |  4 ++--
+ drivers/target/target_core_file.c |  4 ++--
+ fs/aio.c                          |  4 ++--
+ fs/read_write.c                   | 12 ++++++------
+ fs/splice.c                       |  4 ++--
+ include/linux/fs.h                | 12 ------------
+ io_uring/rw.c                     |  4 ++--
+ 7 files changed, 16 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index 552f56a84a7eb..afa5d49ccab49 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -447,9 +447,9 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
+       cmd->iocb.ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0);
+       if (rw == ITER_SOURCE)
+-              ret = call_write_iter(file, &cmd->iocb, &iter);
++              ret = file->f_op->write_iter(&cmd->iocb, &iter);
+       else
+-              ret = call_read_iter(file, &cmd->iocb, &iter);
++              ret = file->f_op->read_iter(&cmd->iocb, &iter);
+       lo_rw_aio_do_completion(cmd);
+diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
+index 4e4cf6c34a775..e43eff09dc22a 100644
+--- a/drivers/target/target_core_file.c
++++ b/drivers/target/target_core_file.c
+@@ -299,9 +299,9 @@ fd_execute_rw_aio(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
+               aio_cmd->iocb.ki_flags |= IOCB_DSYNC;
+       if (is_write)
+-              ret = call_write_iter(file, &aio_cmd->iocb, &iter);
++              ret = file->f_op->write_iter(&aio_cmd->iocb, &iter);
+       else
+-              ret = call_read_iter(file, &aio_cmd->iocb, &iter);
++              ret = file->f_op->read_iter(&aio_cmd->iocb, &iter);
+       if (ret != -EIOCBQUEUED)
+               cmd_rw_aio_complete(&aio_cmd->iocb, ret);
+diff --git a/fs/aio.c b/fs/aio.c
+index 4a9b5e4719eea..7cbdf6cd6dd37 100644
+--- a/fs/aio.c
++++ b/fs/aio.c
+@@ -1559,7 +1559,7 @@ static int aio_read(struct kiocb *req, const struct iocb *iocb,
+               return ret;
+       ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter));
+       if (!ret)
+-              aio_rw_done(req, call_read_iter(file, req, &iter));
++              aio_rw_done(req, file->f_op->read_iter(req, &iter));
+       kfree(iovec);
+       return ret;
+ }
+@@ -1590,7 +1590,7 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb,
+               if (S_ISREG(file_inode(file)->i_mode))
+                       kiocb_start_write(req);
+               req->ki_flags |= IOCB_WRITE;
+-              aio_rw_done(req, call_write_iter(file, req, &iter));
++              aio_rw_done(req, file->f_op->write_iter(req, &iter));
+       }
+       kfree(iovec);
+       return ret;
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 9a56949f3b8d1..4a476bdda51d4 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -386,7 +386,7 @@ static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo
+       kiocb.ki_pos = (ppos ? *ppos : 0);
+       iov_iter_ubuf(&iter, ITER_DEST, buf, len);
+-      ret = call_read_iter(filp, &kiocb, &iter);
++      ret = filp->f_op->read_iter(&kiocb, &iter);
+       BUG_ON(ret == -EIOCBQUEUED);
+       if (ppos)
+               *ppos = kiocb.ki_pos;
+@@ -488,7 +488,7 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
+       kiocb.ki_pos = (ppos ? *ppos : 0);
+       iov_iter_ubuf(&iter, ITER_SOURCE, (void __user *)buf, len);
+-      ret = call_write_iter(filp, &kiocb, &iter);
++      ret = filp->f_op->write_iter(&kiocb, &iter);
+       BUG_ON(ret == -EIOCBQUEUED);
+       if (ret > 0 && ppos)
+               *ppos = kiocb.ki_pos;
+@@ -730,9 +730,9 @@ static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
+       kiocb.ki_pos = (ppos ? *ppos : 0);
+       if (type == READ)
+-              ret = call_read_iter(filp, &kiocb, iter);
++              ret = filp->f_op->read_iter(&kiocb, iter);
+       else
+-              ret = call_write_iter(filp, &kiocb, iter);
++              ret = filp->f_op->write_iter(&kiocb, iter);
+       BUG_ON(ret == -EIOCBQUEUED);
+       if (ppos)
+               *ppos = kiocb.ki_pos;
+@@ -821,7 +821,7 @@ ssize_t vfs_iocb_iter_read(struct file *file, struct kiocb *iocb,
+       if (ret < 0)
+               return ret;
+-      ret = call_read_iter(file, iocb, iter);
++      ret = file->f_op->read_iter(iocb, iter);
+ out:
+       if (ret >= 0)
+               fsnotify_access(file);
+@@ -890,7 +890,7 @@ ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
+               return ret;
+       kiocb_start_write(iocb);
+-      ret = call_write_iter(file, iocb, iter);
++      ret = file->f_op->write_iter(iocb, iter);
+       if (ret != -EIOCBQUEUED)
+               kiocb_end_write(iocb);
+       if (ret > 0)
+diff --git a/fs/splice.c b/fs/splice.c
+index a8f97c5e8cf0e..cc37369e02453 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -361,7 +361,7 @@ ssize_t copy_splice_read(struct file *in, loff_t *ppos,
+       iov_iter_bvec(&to, ITER_DEST, bv, npages, len);
+       init_sync_kiocb(&kiocb, in);
+       kiocb.ki_pos = *ppos;
+-      ret = call_read_iter(in, &kiocb, &to);
++      ret = in->f_op->read_iter(&kiocb, &to);
+       if (ret > 0) {
+               keep = DIV_ROUND_UP(ret, PAGE_SIZE);
+@@ -739,7 +739,7 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+               iov_iter_bvec(&from, ITER_SOURCE, array, n, sd.total_len - left);
+               init_sync_kiocb(&kiocb, out);
+               kiocb.ki_pos = sd.pos;
+-              ret = call_write_iter(out, &kiocb, &from);
++              ret = out->f_op->write_iter(&kiocb, &from);
+               sd.pos = kiocb.ki_pos;
+               if (ret <= 0)
+                       break;
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index ee5efad0d7801..2b2a49711aa2f 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2005,18 +2005,6 @@ struct inode_operations {
+       struct offset_ctx *(*get_offset_ctx)(struct inode *inode);
+ } ____cacheline_aligned;
+-static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio,
+-                                   struct iov_iter *iter)
+-{
+-      return file->f_op->read_iter(kio, iter);
+-}
+-
+-static inline ssize_t call_write_iter(struct file *file, struct kiocb *kio,
+-                                    struct iov_iter *iter)
+-{
+-      return file->f_op->write_iter(kio, iter);
+-}
+-
+ static inline int call_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+       return file->f_op->mmap(file, vma);
+diff --git a/io_uring/rw.c b/io_uring/rw.c
+index 0a0c1c9db0f90..e7a27edf3ab23 100644
+--- a/io_uring/rw.c
++++ b/io_uring/rw.c
+@@ -653,7 +653,7 @@ static inline int io_iter_do_read(struct io_rw *rw, struct iov_iter *iter)
+       struct file *file = rw->kiocb.ki_filp;
+       if (likely(file->f_op->read_iter))
+-              return call_read_iter(file, &rw->kiocb, iter);
++              return file->f_op->read_iter(&rw->kiocb, iter);
+       else if (file->f_op->read)
+               return loop_rw_iter(READ, rw, iter);
+       else
+@@ -918,7 +918,7 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags)
+       kiocb->ki_flags |= IOCB_WRITE;
+       if (likely(req->file->f_op->write_iter))
+-              ret2 = call_write_iter(req->file, kiocb, &s->iter);
++              ret2 = req->file->f_op->write_iter(kiocb, &s->iter);
+       else if (req->file->f_op->write)
+               ret2 = loop_rw_iter(WRITE, rw, &s->iter);
+       else
+-- 
+2.43.0
+
diff --git a/queue-6.6/revert-arm64-fpsimd-implement-lazy-restore-for-kerne.patch b/queue-6.6/revert-arm64-fpsimd-implement-lazy-restore-for-kerne.patch
new file mode 100644 (file)
index 0000000..01f50dd
--- /dev/null
@@ -0,0 +1,75 @@
+From b6fb5d8556512e9b817e4aa1fc270749c13feea4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 May 2024 12:55:55 +0100
+Subject: Revert "arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD"
+
+From: Will Deacon <will@kernel.org>
+
+[ Upstream commit b8995a18417088bb53f87c49d200ec72a9dd4ec1 ]
+
+This reverts commit 2632e25217696712681dd1f3ecc0d71624ea3b23.
+
+Johannes (and others) report data corruption with dm-crypt on Apple M1
+which has been bisected to this change. Revert the offending commit
+while we figure out what's going on.
+
+Cc: stable@vger.kernel.org
+Reported-by: Johannes Nixdorf <mixi@shadowice.org>
+Link: https://lore.kernel.org/all/D1B7GPIR9K1E.5JFV37G0YTIF@shadowice.org/
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/processor.h |  1 -
+ arch/arm64/kernel/fpsimd.c         | 18 ------------------
+ 2 files changed, 19 deletions(-)
+
+diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
+index 5b0a04810b236..ce6eebd6c08bd 100644
+--- a/arch/arm64/include/asm/processor.h
++++ b/arch/arm64/include/asm/processor.h
+@@ -169,7 +169,6 @@ struct thread_struct {
+       struct debug_info       debug;          /* debugging */
+       struct user_fpsimd_state        kernel_fpsimd_state;
+-      unsigned int                    kernel_fpsimd_cpu;
+ #ifdef CONFIG_ARM64_PTR_AUTH
+       struct ptrauth_keys_user        keys_user;
+ #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
+diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
+index 92cb6dd1cfc1a..aa695057c93dd 100644
+--- a/arch/arm64/kernel/fpsimd.c
++++ b/arch/arm64/kernel/fpsimd.c
+@@ -1552,30 +1552,12 @@ void do_fpsimd_exc(unsigned long esr, struct pt_regs *regs)
+ static void fpsimd_load_kernel_state(struct task_struct *task)
+ {
+-      struct cpu_fp_state *last = this_cpu_ptr(&fpsimd_last_state);
+-
+-      /*
+-       * Elide the load if this CPU holds the most recent kernel mode
+-       * FPSIMD context of the current task.
+-       */
+-      if (last->st == &task->thread.kernel_fpsimd_state &&
+-          task->thread.kernel_fpsimd_cpu == smp_processor_id())
+-              return;
+-
+       fpsimd_load_state(&task->thread.kernel_fpsimd_state);
+ }
+ static void fpsimd_save_kernel_state(struct task_struct *task)
+ {
+-      struct cpu_fp_state cpu_fp_state = {
+-              .st             = &task->thread.kernel_fpsimd_state,
+-              .to_save        = FP_STATE_FPSIMD,
+-      };
+-
+       fpsimd_save_state(&task->thread.kernel_fpsimd_state);
+-      fpsimd_bind_state_to_cpu(&cpu_fp_state);
+-
+-      task->thread.kernel_fpsimd_cpu = smp_processor_id();
+ }
+ void fpsimd_thread_switch(struct task_struct *next)
+-- 
+2.43.0
+
diff --git a/queue-6.6/risc-v-enable-cbo.zero-in-usermode.patch b/queue-6.6/risc-v-enable-cbo.zero-in-usermode.patch
new file mode 100644 (file)
index 0000000..6a62f0e
--- /dev/null
@@ -0,0 +1,169 @@
+From 225e330455f209634733314a13070234294a4e02 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Sep 2023 15:15:21 +0200
+Subject: RISC-V: Enable cbo.zero in usermode
+
+From: Andrew Jones <ajones@ventanamicro.com>
+
+[ Upstream commit 43c16d51a19b0ba2ed66978d5924d486ec1e42bc ]
+
+When Zicboz is present, enable its instruction (cbo.zero) in
+usermode by setting its respective senvcfg bit. We don't bother
+trying to set this bit per-task, which would also require an
+interface for tasks to request enabling and/or disabling. Instead,
+permanently set the bit for each hart which has the extension when
+bringing it online.
+
+This patch also introduces riscv_cpu_has_extension_[un]likely()
+functions to check a specific hart's ISA bitmap for extensions.
+Prior to checking the specific hart's bitmap in these functions
+we try the bitmap which represents the LCD of extensions, but only
+when we know it will use its optimized, alternatives path by gating
+its call on CONFIG_RISCV_ALTERNATIVE. When alternatives are used, the
+compiler ensures that the invocation of the LCD search becomes a
+constant true or false. When it's true, even the new functions will
+completely vanish from their callsites. OTOH, when the LCD check is
+false, we need to do a search of the hart's ISA bitmap. Had we also
+checked the LCD bitmap without the use of alternatives, then we would
+have ended up with two bitmap searches instead of one.
+
+Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
+Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
+Link: https://lore.kernel.org/r/20230918131518.56803-10-ajones@ventanamicro.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Stable-dep-of: 58661a30f1bc ("riscv: Flush the instruction cache during SMP bringup")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/include/asm/cpufeature.h |  1 +
+ arch/riscv/include/asm/csr.h        |  1 +
+ arch/riscv/include/asm/hwcap.h      | 16 ++++++++++++++++
+ arch/riscv/kernel/cpufeature.c      |  6 ++++++
+ arch/riscv/kernel/setup.c           |  4 ++++
+ arch/riscv/kernel/smpboot.c         |  4 ++++
+ 6 files changed, 32 insertions(+)
+
+diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h
+index d0345bd659c94..13b7d35648a9c 100644
+--- a/arch/riscv/include/asm/cpufeature.h
++++ b/arch/riscv/include/asm/cpufeature.h
+@@ -31,5 +31,6 @@ DECLARE_PER_CPU(long, misaligned_access_speed);
+ extern struct riscv_isainfo hart_isa[NR_CPUS];
+ void check_unaligned_access(int cpu);
++void riscv_user_isa_enable(void);
+ #endif
+diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
+index 777cb8299551c..5fba25db82d2a 100644
+--- a/arch/riscv/include/asm/csr.h
++++ b/arch/riscv/include/asm/csr.h
+@@ -275,6 +275,7 @@
+ #define CSR_SIE                       0x104
+ #define CSR_STVEC             0x105
+ #define CSR_SCOUNTEREN                0x106
++#define CSR_SENVCFG           0x10a
+ #define CSR_SSCRATCH          0x140
+ #define CSR_SEPC              0x141
+ #define CSR_SCAUSE            0x142
+diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
+index f4157034efa9c..e215d3399a179 100644
+--- a/arch/riscv/include/asm/hwcap.h
++++ b/arch/riscv/include/asm/hwcap.h
+@@ -70,6 +70,7 @@
+ #ifndef __ASSEMBLY__
+ #include <linux/jump_label.h>
++#include <asm/cpufeature.h>
+ unsigned long riscv_get_elf_hwcap(void);
+@@ -137,6 +138,21 @@ riscv_has_extension_unlikely(const unsigned long ext)
+       return true;
+ }
++static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext)
++{
++      if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_likely(ext))
++              return true;
++
++      return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
++}
++
++static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext)
++{
++      if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_unlikely(ext))
++              return true;
++
++      return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
++}
+ #endif
+ #endif /* _ASM_RISCV_HWCAP_H */
+diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
+index e39a905aca248..6754a922a844f 100644
+--- a/arch/riscv/kernel/cpufeature.c
++++ b/arch/riscv/kernel/cpufeature.c
+@@ -672,6 +672,12 @@ static int check_unaligned_access_boot_cpu(void)
+ arch_initcall(check_unaligned_access_boot_cpu);
++void riscv_user_isa_enable(void)
++{
++      if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_ZICBOZ))
++              csr_set(CSR_SENVCFG, ENVCFG_CBZE);
++}
++
+ #ifdef CONFIG_RISCV_ALTERNATIVE
+ /*
+  * Alternative patch sites consider 48 bits when determining when to patch
+diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
+index e600aab116a40..8fd6c02353d43 100644
+--- a/arch/riscv/kernel/setup.c
++++ b/arch/riscv/kernel/setup.c
+@@ -26,6 +26,7 @@
+ #include <asm/acpi.h>
+ #include <asm/alternative.h>
+ #include <asm/cacheflush.h>
++#include <asm/cpufeature.h>
+ #include <asm/cpu_ops.h>
+ #include <asm/early_ioremap.h>
+ #include <asm/pgtable.h>
+@@ -314,10 +315,13 @@ void __init setup_arch(char **cmdline_p)
+       riscv_fill_hwcap();
+       init_rt_signal_env();
+       apply_boot_alternatives();
++
+       if (IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM) &&
+           riscv_isa_extension_available(NULL, ZICBOM))
+               riscv_noncoherent_supported();
+       riscv_set_dma_cache_alignment();
++
++      riscv_user_isa_enable();
+ }
+ static int __init topology_init(void)
+diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
+index 1b8da4e40a4d6..d1b0a6fc3adfc 100644
+--- a/arch/riscv/kernel/smpboot.c
++++ b/arch/riscv/kernel/smpboot.c
+@@ -25,6 +25,8 @@
+ #include <linux/of.h>
+ #include <linux/sched/task_stack.h>
+ #include <linux/sched/mm.h>
++
++#include <asm/cpufeature.h>
+ #include <asm/cpu_ops.h>
+ #include <asm/cpufeature.h>
+ #include <asm/irq.h>
+@@ -253,6 +255,8 @@ asmlinkage __visible void smp_callin(void)
+                       elf_hwcap &= ~COMPAT_HWCAP_ISA_V;
+       }
++      riscv_user_isa_enable();
++
+       /*
+        * Remote TLB flushes are ignored while the CPU is offline, so emit
+        * a local TLB flush right now just in case.
+-- 
+2.43.0
+
diff --git a/queue-6.6/riscv-dts-starfive-visionfive-2-remove-non-existing-.patch b/queue-6.6/riscv-dts-starfive-visionfive-2-remove-non-existing-.patch
new file mode 100644 (file)
index 0000000..43e5d4a
--- /dev/null
@@ -0,0 +1,91 @@
+From 6739a77ecfc1fe901f2b68421f1c80fd398e7a9b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Apr 2024 14:50:32 +0200
+Subject: riscv: dts: starfive: visionfive 2: Remove non-existing TDM hardware
+
+From: Hannah Peuckmann <hannah.peuckmann@canonical.com>
+
+[ Upstream commit dcde4e97b122ac318aaa71e8bcd2857dc28a0d12 ]
+
+This partially reverts
+commit e7c304c0346d ("riscv: dts: starfive: jh7110: add the node and pins configuration for tdm")
+
+This added device tree nodes for TDM hardware that is not actually on the
+VisionFive 2 board, but connected on the 40pin header. Many different extension
+boards could be added on those pins, so this should be handled by overlays
+instead.
+This also conflicts with the I2S node which also attempts to grab GPIO 44:
+
+  starfive-jh7110-sys-pinctrl 13040000.pinctrl: pin GPIO44 already requested by 10090000.tdm; cannot claim for 120c0000.i2s
+
+Fixes: e7c304c0346d ("riscv: dts: starfive: jh7110: add the node and pins configuration for tdm")
+Signed-off-by: Hannah Peuckmann <hannah.peuckmann@canonical.com>
+Reviewed-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
+Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
+Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../jh7110-starfive-visionfive-2.dtsi         | 40 -------------------
+ 1 file changed, 40 deletions(-)
+
+diff --git a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+index 2c02358abd711..c9b212c0eaa8f 100644
+--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+@@ -440,40 +440,6 @@ GPOEN_ENABLE,
+               };
+       };
+-      tdm_pins: tdm-0 {
+-              tx-pins {
+-                      pinmux = <GPIOMUX(44, GPOUT_SYS_TDM_TXD,
+-                                            GPOEN_ENABLE,
+-                                            GPI_NONE)>;
+-                      bias-pull-up;
+-                      drive-strength = <2>;
+-                      input-disable;
+-                      input-schmitt-disable;
+-                      slew-rate = <0>;
+-              };
+-
+-              rx-pins {
+-                      pinmux = <GPIOMUX(61, GPOUT_HIGH,
+-                                            GPOEN_DISABLE,
+-                                            GPI_SYS_TDM_RXD)>;
+-                      input-enable;
+-              };
+-
+-              sync-pins {
+-                      pinmux = <GPIOMUX(63, GPOUT_HIGH,
+-                                            GPOEN_DISABLE,
+-                                            GPI_SYS_TDM_SYNC)>;
+-                      input-enable;
+-              };
+-
+-              pcmclk-pins {
+-                      pinmux = <GPIOMUX(38, GPOUT_HIGH,
+-                                            GPOEN_DISABLE,
+-                                            GPI_SYS_TDM_CLK)>;
+-                      input-enable;
+-              };
+-      };
+-
+       uart0_pins: uart0-0 {
+               tx-pins {
+                       pinmux = <GPIOMUX(5, GPOUT_SYS_UART0_TX,
+@@ -499,12 +465,6 @@ GPOEN_DISABLE,
+       };
+ };
+-&tdm {
+-      pinctrl-names = "default";
+-      pinctrl-0 = <&tdm_pins>;
+-      status = "okay";
+-};
+-
+ &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+-- 
+2.43.0
+
diff --git a/queue-6.6/riscv-flush-the-instruction-cache-during-smp-bringup.patch b/queue-6.6/riscv-flush-the-instruction-cache-during-smp-bringup.patch
new file mode 100644 (file)
index 0000000..39de245
--- /dev/null
@@ -0,0 +1,55 @@
+From fbf9c4c0b605c3d8182cc3f2e416ef2f3f89b44a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Mar 2024 21:49:42 -0700
+Subject: riscv: Flush the instruction cache during SMP bringup
+
+From: Samuel Holland <samuel.holland@sifive.com>
+
+[ Upstream commit 58661a30f1bcc748475ffd9be6d2fc9e4e6be679 ]
+
+Instruction cache flush IPIs are sent only to CPUs in cpu_online_mask,
+so they will not target a CPU until it calls set_cpu_online() earlier in
+smp_callin(). As a result, if instruction memory is modified between the
+CPU coming out of reset and that point, then its instruction cache may
+contain stale data. Therefore, the instruction cache must be flushed
+after the set_cpu_online() synchronization point.
+
+Fixes: 08f051eda33b ("RISC-V: Flush I$ when making a dirty page executable")
+Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
+Link: https://lore.kernel.org/r/20240327045035.368512-2-samuel.holland@sifive.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/kernel/smpboot.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
+index d1b0a6fc3adfc..b30aeed26b717 100644
+--- a/arch/riscv/kernel/smpboot.c
++++ b/arch/riscv/kernel/smpboot.c
+@@ -26,7 +26,7 @@
+ #include <linux/sched/task_stack.h>
+ #include <linux/sched/mm.h>
+-#include <asm/cpufeature.h>
++#include <asm/cacheflush.h>
+ #include <asm/cpu_ops.h>
+ #include <asm/cpufeature.h>
+ #include <asm/irq.h>
+@@ -258,9 +258,10 @@ asmlinkage __visible void smp_callin(void)
+       riscv_user_isa_enable();
+       /*
+-       * Remote TLB flushes are ignored while the CPU is offline, so emit
+-       * a local TLB flush right now just in case.
++       * Remote cache and TLB flushes are ignored while the CPU is offline,
++       * so flush them both right now just in case.
+        */
++      local_flush_icache_all();
+       local_flush_tlb_all();
+       complete(&cpu_running);
+       /*
+-- 
+2.43.0
+
diff --git a/queue-6.6/s390-boot-remove-alt_stfle_fac_list-from-decompresso.patch b/queue-6.6/s390-boot-remove-alt_stfle_fac_list-from-decompresso.patch
new file mode 100644 (file)
index 0000000..0bb6e49
--- /dev/null
@@ -0,0 +1,49 @@
+From 672554a1b3e14134d8afd10d929e53c8dae72808 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 May 2024 09:20:27 +0200
+Subject: s390/boot: Remove alt_stfle_fac_list from decompressor
+
+From: Sven Schnelle <svens@linux.ibm.com>
+
+[ Upstream commit e7dec0b7926f3cd493c697c4c389df77e8e8a34c ]
+
+It is nowhere used in the decompressor, therefore remove it.
+
+Fixes: 17e89e1340a3 ("s390/facilities: move stfl information from lowcore to global data")
+Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/boot/startup.c | 1 -
+ arch/s390/kernel/setup.c | 2 +-
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
+index d08db5df60913..655bbcff81ffd 100644
+--- a/arch/s390/boot/startup.c
++++ b/arch/s390/boot/startup.c
+@@ -31,7 +31,6 @@ unsigned long __bootdata_preserved(max_mappable);
+ unsigned long __bootdata(ident_map_size);
+ u64 __bootdata_preserved(stfle_fac_list[16]);
+-u64 __bootdata_preserved(alt_stfle_fac_list[16]);
+ struct oldmem_data __bootdata_preserved(oldmem_data);
+ struct machine_info machine;
+diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
+index de6ad0fb2328a..d48c7afe97e62 100644
+--- a/arch/s390/kernel/setup.c
++++ b/arch/s390/kernel/setup.c
+@@ -155,7 +155,7 @@ unsigned int __bootdata_preserved(zlib_dfltcc_support);
+ EXPORT_SYMBOL(zlib_dfltcc_support);
+ u64 __bootdata_preserved(stfle_fac_list[16]);
+ EXPORT_SYMBOL(stfle_fac_list);
+-u64 __bootdata_preserved(alt_stfle_fac_list[16]);
++u64 alt_stfle_fac_list[16];
+ struct oldmem_data __bootdata_preserved(oldmem_data);
+ unsigned long VMALLOC_START;
+-- 
+2.43.0
+
diff --git a/queue-6.6/s390-ipl-fix-incorrect-initialization-of-len-fields-.patch b/queue-6.6/s390-ipl-fix-incorrect-initialization-of-len-fields-.patch
new file mode 100644 (file)
index 0000000..828731b
--- /dev/null
@@ -0,0 +1,42 @@
+From 473c01f8e3b4a8cc34ab8a48a116416cc0502fef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 12:41:25 +0200
+Subject: s390/ipl: Fix incorrect initialization of len fields in nvme reipl
+ block
+
+From: Alexander Egorenkov <egorenar@linux.ibm.com>
+
+[ Upstream commit 9c922b73acaf39f867668d9cbe5dc69c23511f84 ]
+
+Use correct symbolic constants IPL_BP_NVME_LEN and IPL_BP0_NVME_LEN
+to initialize nvme reipl block when 'scp_data' sysfs attribute is
+being updated. This bug had not been detected before because
+the corresponding fcp and nvme symbolic constants are equal.
+
+Fixes: 23a457b8d57d ("s390: nvme reipl")
+Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kernel/ipl.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
+index 8d0b95c173129..14365773aac79 100644
+--- a/arch/s390/kernel/ipl.c
++++ b/arch/s390/kernel/ipl.c
+@@ -962,8 +962,8 @@ static ssize_t reipl_nvme_scpdata_write(struct file *filp, struct kobject *kobj,
+               scpdata_len += padding;
+       }
+-      reipl_block_nvme->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
+-      reipl_block_nvme->nvme.len = IPL_BP0_FCP_LEN + scpdata_len;
++      reipl_block_nvme->hdr.len = IPL_BP_NVME_LEN + scpdata_len;
++      reipl_block_nvme->nvme.len = IPL_BP0_NVME_LEN + scpdata_len;
+       reipl_block_nvme->nvme.scp_data_len = scpdata_len;
+       return count;
+-- 
+2.43.0
+
diff --git a/queue-6.6/s390-ipl-fix-incorrect-initialization-of-nvme-dump-b.patch b/queue-6.6/s390-ipl-fix-incorrect-initialization-of-nvme-dump-b.patch
new file mode 100644 (file)
index 0000000..f2294a4
--- /dev/null
@@ -0,0 +1,43 @@
+From f1764baf7970d08cc5524d634580e9223bd328d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 12:41:26 +0200
+Subject: s390/ipl: Fix incorrect initialization of nvme dump block
+
+From: Alexander Egorenkov <egorenar@linux.ibm.com>
+
+[ Upstream commit 7faacaeaf6ce12fae78751de5ad869d8f1e1cd7a ]
+
+Initialize the correct fields of the nvme dump block.
+This bug had not been detected before because first, the fcp and nvme fields
+of struct ipl_parameter_block are part of the same union and, therefore,
+overlap in memory and second, they are identical in structure and size.
+
+Fixes: d70e38cb1dee ("s390: nvme dump support")
+Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kernel/ipl.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
+index 14365773aac79..a3d3cb39b021a 100644
+--- a/arch/s390/kernel/ipl.c
++++ b/arch/s390/kernel/ipl.c
+@@ -1858,9 +1858,9 @@ static int __init dump_nvme_init(void)
+       }
+       dump_block_nvme->hdr.len = IPL_BP_NVME_LEN;
+       dump_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION;
+-      dump_block_nvme->fcp.len = IPL_BP0_NVME_LEN;
+-      dump_block_nvme->fcp.pbt = IPL_PBT_NVME;
+-      dump_block_nvme->fcp.opt = IPL_PB0_NVME_OPT_DUMP;
++      dump_block_nvme->nvme.len = IPL_BP0_NVME_LEN;
++      dump_block_nvme->nvme.pbt = IPL_PBT_NVME;
++      dump_block_nvme->nvme.opt = IPL_PB0_NVME_OPT_DUMP;
+       dump_capabilities |= DUMP_TYPE_NVME;
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/s390-vdso-create-.build-id-links-for-unstripped-vdso.patch b/queue-6.6/s390-vdso-create-.build-id-links-for-unstripped-vdso.patch
new file mode 100644 (file)
index 0000000..635b7e5
--- /dev/null
@@ -0,0 +1,45 @@
+From ac0d21783d63aa65f4b72d130749bb64118be4ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Apr 2024 17:02:53 +0200
+Subject: s390/vdso: Create .build-id links for unstripped vdso files
+
+From: Jens Remus <jremus@linux.ibm.com>
+
+[ Upstream commit fc2f5f10f9bc5e58d38e9fda7dae107ac04a799f ]
+
+Citing Andy Lutomirski from commit dda1e95cee38 ("x86/vdso: Create
+.build-id links for unstripped vdso files"):
+
+"With this change, doing 'make vdso_install' and telling gdb:
+
+set debug-file-directory /lib/modules/KVER/vdso
+
+will enable vdso debugging with symbols.  This is useful for
+testing, but kernel RPM builds will probably want to manually delete
+these symlinks or otherwise do something sensible when they strip
+the vdso/*.so files."
+
+Fixes: 4bff8cb54502 ("s390: convert to GENERIC_VDSO")
+Signed-off-by: Jens Remus <jremus@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/Makefile.vdsoinst | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/Makefile.vdsoinst b/scripts/Makefile.vdsoinst
+index c477d17b0aa5b..a81ca735003e4 100644
+--- a/scripts/Makefile.vdsoinst
++++ b/scripts/Makefile.vdsoinst
+@@ -21,7 +21,7 @@ $$(dest): $$(src) FORCE
+       $$(call cmd,install)
+ # Some architectures create .build-id symlinks
+-ifneq ($(filter arm sparc x86, $(SRCARCH)),)
++ifneq ($(filter arm s390 sparc x86, $(SRCARCH)),)
+ link := $(install-dir)/.build-id/$$(shell $(READELF) -n $$(src) | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p').debug
+ __default: $$(link)
+-- 
+2.43.0
+
diff --git a/queue-6.6/s390-vdso-generate-unwind-information-for-c-modules.patch b/queue-6.6/s390-vdso-generate-unwind-information-for-c-modules.patch
new file mode 100644 (file)
index 0000000..6ab7406
--- /dev/null
@@ -0,0 +1,55 @@
+From 1bcc6dbdbc10db3e3c582d6cadd977632abe1ce6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Apr 2024 17:02:52 +0200
+Subject: s390/vdso: Generate unwind information for C modules
+
+From: Jens Remus <jremus@linux.ibm.com>
+
+[ Upstream commit 10f70525365146046dddcc3d36bfaea2aee0376a ]
+
+GDB fails to unwind vDSO functions with error message "PC not saved",
+for instance when stepping through gettimeofday().
+
+Add -fasynchronous-unwind-tables to CFLAGS to generate .eh_frame
+DWARF unwind information for the vDSO C modules.
+
+Fixes: 4bff8cb54502 ("s390: convert to GENERIC_VDSO")
+Signed-off-by: Jens Remus <jremus@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kernel/vdso32/Makefile | 3 ++-
+ arch/s390/kernel/vdso64/Makefile | 3 ++-
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile
+index c4b14a8700d88..9793266245587 100644
+--- a/arch/s390/kernel/vdso32/Makefile
++++ b/arch/s390/kernel/vdso32/Makefile
+@@ -20,7 +20,8 @@ KBUILD_AFLAGS_32 += -m31 -s
+ KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
+ KBUILD_CFLAGS_32 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_32))
+-KBUILD_CFLAGS_32 += -m31 -fPIC -shared -fno-common -fno-builtin
++KBUILD_CFLAGS_32 := $(filter-out -fno-asynchronous-unwind-tables,$(KBUILD_CFLAGS_32))
++KBUILD_CFLAGS_32 += -m31 -fPIC -shared -fno-common -fno-builtin -fasynchronous-unwind-tables
+ LDFLAGS_vdso32.so.dbg += -shared -soname=linux-vdso32.so.1 \
+       --hash-style=both --build-id=sha1 -melf_s390 -T
+diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile
+index aa410a0a141cc..197fa382b58ab 100644
+--- a/arch/s390/kernel/vdso64/Makefile
++++ b/arch/s390/kernel/vdso64/Makefile
+@@ -26,7 +26,8 @@ KBUILD_AFLAGS_64 += -m64
+ KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
+ KBUILD_CFLAGS_64 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_64))
+ KBUILD_CFLAGS_64 := $(filter-out -munaligned-symbols,$(KBUILD_CFLAGS_64))
+-KBUILD_CFLAGS_64 += -m64 -fPIC -fno-common -fno-builtin
++KBUILD_CFLAGS_64 := $(filter-out -fno-asynchronous-unwind-tables,$(KBUILD_CFLAGS_64))
++KBUILD_CFLAGS_64 += -m64 -fPIC -fno-common -fno-builtin -fasynchronous-unwind-tables
+ ldflags-y := -shared -soname=linux-vdso64.so.1 \
+            --hash-style=both --build-id=sha1 -T
+-- 
+2.43.0
+
diff --git a/queue-6.6/s390-vdso-use-standard-stack-frame-layout.patch b/queue-6.6/s390-vdso-use-standard-stack-frame-layout.patch
new file mode 100644 (file)
index 0000000..951a466
--- /dev/null
@@ -0,0 +1,56 @@
+From 072e03b0e9afc4357c04699f0e7a7be78ef43895 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Apr 2024 14:28:43 +0200
+Subject: s390/vdso: Use standard stack frame layout
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+[ Upstream commit 185445c7c137822ad856aae91a41e199370cb534 ]
+
+By default user space is compiled with standard stack frame layout and not
+with the packed stack layout. The vdso code however inherited the
+-mpacked-stack compiler option from the kernel. Remove this option to make
+sure the vdso is compiled with standard stack frame layout.
+
+This makes sure that the stack frame backchain location for vdso generated
+stack frames is the same like for calling code (if compiled with default
+options). This allows to manually walk stack frames without DWARF
+information, like the kernel is doing it e.g. with arch_stack_walk_user().
+
+Fixes: 4bff8cb54502 ("s390: convert to GENERIC_VDSO")
+Reviewed-by: Jens Remus <jremus@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kernel/vdso32/Makefile | 1 +
+ arch/s390/kernel/vdso64/Makefile | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile
+index 9090c0e5de254..4800d80decee6 100644
+--- a/arch/s390/kernel/vdso32/Makefile
++++ b/arch/s390/kernel/vdso32/Makefile
+@@ -19,6 +19,7 @@ KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS))
+ KBUILD_AFLAGS_32 += -m31 -s
+ KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
++KBUILD_CFLAGS_32 := $(filter-out -mpacked-stack,$(KBUILD_CFLAGS))
+ KBUILD_CFLAGS_32 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 := $(filter-out -fno-asynchronous-unwind-tables,$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 += -m31 -fPIC -shared -fno-common -fno-builtin -fasynchronous-unwind-tables
+diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile
+index a44f51de1f1ea..2f2e4e997030c 100644
+--- a/arch/s390/kernel/vdso64/Makefile
++++ b/arch/s390/kernel/vdso64/Makefile
+@@ -24,6 +24,7 @@ KBUILD_AFLAGS_64 := $(filter-out -m64,$(KBUILD_AFLAGS))
+ KBUILD_AFLAGS_64 += -m64
+ KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
++KBUILD_CFLAGS_64 := $(filter-out -mpacked-stack,$(KBUILD_CFLAGS_64))
+ KBUILD_CFLAGS_64 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_64))
+ KBUILD_CFLAGS_64 := $(filter-out -munaligned-symbols,$(KBUILD_CFLAGS_64))
+ KBUILD_CFLAGS_64 := $(filter-out -fno-asynchronous-unwind-tables,$(KBUILD_CFLAGS_64))
+-- 
+2.43.0
+
diff --git a/queue-6.6/s390-vdso64-filter-out-munaligned-symbols-flag-for-v.patch b/queue-6.6/s390-vdso64-filter-out-munaligned-symbols-flag-for-v.patch
new file mode 100644 (file)
index 0000000..617f430
--- /dev/null
@@ -0,0 +1,56 @@
+From 662c1f2baa46ad30bcc8f8e92ddbd885de95d2a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Feb 2024 14:27:31 +0100
+Subject: s390/vdso64: filter out munaligned-symbols flag for vdso
+
+From: Sumanth Korikkar <sumanthk@linux.ibm.com>
+
+[ Upstream commit 8192a1b3807510d0ed5be1f8988c08f8d41cced9 ]
+
+Gcc recently implemented an optimization [1] for loading symbols without
+explicit alignment, aligning with the IBM Z ELF ABI. This ABI mandates
+symbols to reside on a 2-byte boundary, enabling the use of the larl
+instruction. However, kernel linker scripts may still generate unaligned
+symbols. To address this, a new -munaligned-symbols option has been
+introduced [2] in recent gcc versions.
+
+[1] https://gcc.gnu.org/pipermail/gcc-patches/2023-June/622872.html
+[2] https://gcc.gnu.org/pipermail/gcc-patches/2023-August/625986.html
+
+However, when -munaligned-symbols  is used in vdso code, it leads to the
+following compilation error:
+`.data.rel.ro.local' referenced in section `.text' of
+arch/s390/kernel/vdso64/vdso64_generic.o: defined in discarded section
+`.data.rel.ro.local' of arch/s390/kernel/vdso64/vdso64_generic.o
+
+vdso linker script discards .data section to make it lightweight.
+However, -munaligned-symbols in vdso object files references literal
+pool and accesses _vdso_data. Hence, compile vdso code without
+-munaligned-symbols.  This means in the future, vdso code should deal
+with alignment of newly introduced unaligned linker symbols.
+
+Acked-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
+Link: https://lore.kernel.org/r/20240219132734.22881-2-sumanthk@linux.ibm.com
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Stable-dep-of: 10f705253651 ("s390/vdso: Generate unwind information for C modules")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kernel/vdso64/Makefile | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile
+index 11f798e6cfea7..aa410a0a141cc 100644
+--- a/arch/s390/kernel/vdso64/Makefile
++++ b/arch/s390/kernel/vdso64/Makefile
+@@ -25,6 +25,7 @@ KBUILD_AFLAGS_64 += -m64
+ KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
+ KBUILD_CFLAGS_64 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_64))
++KBUILD_CFLAGS_64 := $(filter-out -munaligned-symbols,$(KBUILD_CFLAGS_64))
+ KBUILD_CFLAGS_64 += -m64 -fPIC -fno-common -fno-builtin
+ ldflags-y := -shared -soname=linux-vdso64.so.1 \
+            --hash-style=both --build-id=sha1 -T
+-- 
+2.43.0
+
diff --git a/queue-6.6/serial-max3100-fix-bitwise-types.patch b/queue-6.6/serial-max3100-fix-bitwise-types.patch
new file mode 100644 (file)
index 0000000..6bb3be0
--- /dev/null
@@ -0,0 +1,53 @@
+From 2e8ad634aae61ced99ebf90af123db849227cec2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Apr 2024 22:50:30 +0300
+Subject: serial: max3100: Fix bitwise types
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit e60955dbecb97f080848a57524827e2db29c70fd ]
+
+Sparse is not happy about misuse of bitwise types:
+
+  .../max3100.c:194:13: warning: incorrect type in assignment (different base types)
+  .../max3100.c:194:13:    expected unsigned short [addressable] [usertype] etx
+  .../max3100.c:194:13:    got restricted __be16 [usertype]
+  .../max3100.c:202:15: warning: cast to restricted __be16
+
+Fix this by choosing proper types for the respective variables.
+
+Fixes: 7831d56b0a35 ("tty: MAX3100")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20240402195306.269276-4-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/max3100.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
+index b3e63b6a402e1..3d2b83d6ab51a 100644
+--- a/drivers/tty/serial/max3100.c
++++ b/drivers/tty/serial/max3100.c
+@@ -45,6 +45,9 @@
+ #include <linux/freezer.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
++#include <linux/types.h>
++
++#include <asm/unaligned.h>
+ #include <linux/serial_max3100.h>
+@@ -191,7 +194,7 @@ static void max3100_timeout(struct timer_list *t)
+ static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx)
+ {
+       struct spi_message message;
+-      u16 etx, erx;
++      __be16 etx, erx;
+       int status;
+       struct spi_transfer tran = {
+               .tx_buf = &etx,
+-- 
+2.43.0
+
diff --git a/queue-6.6/serial-max3100-lock-port-lock-when-calling-uart_hand.patch b/queue-6.6/serial-max3100-lock-port-lock-when-calling-uart_hand.patch
new file mode 100644 (file)
index 0000000..8a0ef02
--- /dev/null
@@ -0,0 +1,66 @@
+From 85cfbbed1c9f5a8c8e6728d435e3147cb0c0c121 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Apr 2024 22:50:28 +0300
+Subject: serial: max3100: Lock port->lock when calling
+ uart_handle_cts_change()
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 77ab53371a2066fdf9b895246505f5ef5a4b5d47 ]
+
+uart_handle_cts_change() has to be called with port lock taken,
+Since we run it in a separate work, the lock may not be taken at
+the time of running. Make sure that it's taken by explicitly doing
+that. Without it we got a splat:
+
+  WARNING: CPU: 0 PID: 10 at drivers/tty/serial/serial_core.c:3491 uart_handle_cts_change+0xa6/0xb0
+  ...
+  Workqueue: max3100-0 max3100_work [max3100]
+  RIP: 0010:uart_handle_cts_change+0xa6/0xb0
+  ...
+   max3100_handlerx+0xc5/0x110 [max3100]
+   max3100_work+0x12a/0x340 [max3100]
+
+Fixes: 7831d56b0a35 ("tty: MAX3100")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20240402195306.269276-2-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/max3100.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
+index 5efb2b593be33..45022f2909f0a 100644
+--- a/drivers/tty/serial/max3100.c
++++ b/drivers/tty/serial/max3100.c
+@@ -213,7 +213,7 @@ static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx)
+       return 0;
+ }
+-static int max3100_handlerx(struct max3100_port *s, u16 rx)
++static int max3100_handlerx_unlocked(struct max3100_port *s, u16 rx)
+ {
+       unsigned int status = 0;
+       int ret = 0, cts;
+@@ -254,6 +254,17 @@ static int max3100_handlerx(struct max3100_port *s, u16 rx)
+       return ret;
+ }
++static int max3100_handlerx(struct max3100_port *s, u16 rx)
++{
++      unsigned long flags;
++      int ret;
++
++      uart_port_lock_irqsave(&s->port, &flags);
++      ret = max3100_handlerx_unlocked(s, rx);
++      uart_port_unlock_irqrestore(&s->port, flags);
++      return ret;
++}
++
+ static void max3100_work(struct work_struct *w)
+ {
+       struct max3100_port *s = container_of(w, struct max3100_port, work);
+-- 
+2.43.0
+
diff --git a/queue-6.6/serial-max3100-update-uart_driver_registered-on-driv.patch b/queue-6.6/serial-max3100-update-uart_driver_registered-on-driv.patch
new file mode 100644 (file)
index 0000000..bb92bf7
--- /dev/null
@@ -0,0 +1,73 @@
+From 2b8a64f5a6722eff6588fd3d1e7b931a98f21803 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Apr 2024 22:50:29 +0300
+Subject: serial: max3100: Update uart_driver_registered on driver removal
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 712a1fcb38dc7cac6da63ee79a88708fbf9c45ec ]
+
+The removal of the last MAX3100 device triggers the removal of
+the driver. However, code doesn't update the respective global
+variable and after insmod — rmmod — insmod cycle the kernel
+oopses:
+
+  max3100 spi-PRP0001:01: max3100_probe: adding port 0
+  BUG: kernel NULL pointer dereference, address: 0000000000000408
+  ...
+  RIP: 0010:serial_core_register_port+0xa0/0x840
+  ...
+   max3100_probe+0x1b6/0x280 [max3100]
+   spi_probe+0x8d/0xb0
+
+Update the actual state so next time UART driver will be registered
+again.
+
+Hugo also noticed, that the error path in the probe also affected
+by having the variable set, and not cleared. Instead of clearing it
+move the assignment after the successfull uart_register_driver() call.
+
+Fixes: 7831d56b0a35 ("tty: MAX3100")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Link: https://lore.kernel.org/r/20240402195306.269276-3-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/max3100.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
+index 45022f2909f0a..b3e63b6a402e1 100644
+--- a/drivers/tty/serial/max3100.c
++++ b/drivers/tty/serial/max3100.c
+@@ -749,13 +749,14 @@ static int max3100_probe(struct spi_device *spi)
+       mutex_lock(&max3100s_lock);
+       if (!uart_driver_registered) {
+-              uart_driver_registered = 1;
+               retval = uart_register_driver(&max3100_uart_driver);
+               if (retval) {
+                       printk(KERN_ERR "Couldn't register max3100 uart driver\n");
+                       mutex_unlock(&max3100s_lock);
+                       return retval;
+               }
++
++              uart_driver_registered = 1;
+       }
+       for (i = 0; i < MAX_MAX3100; i++)
+@@ -841,6 +842,7 @@ static void max3100_remove(struct spi_device *spi)
+               }
+       pr_debug("removing max3100 driver\n");
+       uart_unregister_driver(&max3100_uart_driver);
++      uart_driver_registered = 0;
+       mutex_unlock(&max3100s_lock);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/serial-sc16is7xx-add-proper-sched.h-include-for-sche.patch b/queue-6.6/serial-sc16is7xx-add-proper-sched.h-include-for-sche.patch
new file mode 100644 (file)
index 0000000..35dd8f8
--- /dev/null
@@ -0,0 +1,44 @@
+From 4819d331b3684a94497b0a3f84a9f72b753b85fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Apr 2024 11:42:49 -0400
+Subject: serial: sc16is7xx: add proper sched.h include for sched_set_fifo()
+
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+[ Upstream commit 2a8e4ab0c93fad30769479f86849e22d63cd0e12 ]
+
+Replace incorrect include with the proper one for sched_set_fifo()
+declaration.
+
+Fixes: 28d2f209cd16 ("sched,serial: Convert to sched_set_fifo()")
+Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Link: https://lore.kernel.org/r/20240409154253.3043822-2-hugo@hugovil.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/sc16is7xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
+index f75b8bceb8ca2..89eea1b8070fb 100644
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -18,6 +18,7 @@
+ #include <linux/module.h>
+ #include <linux/property.h>
+ #include <linux/regmap.h>
++#include <linux/sched.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+@@ -25,7 +26,6 @@
+ #include <linux/spi/spi.h>
+ #include <linux/uaccess.h>
+ #include <linux/units.h>
+-#include <uapi/linux/sched/types.h>
+ #define SC16IS7XX_NAME                        "sc16is7xx"
+ #define SC16IS7XX_MAX_DEVS            8
+-- 
+2.43.0
+
diff --git a/queue-6.6/serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch b/queue-6.6/serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch
new file mode 100644 (file)
index 0000000..1f65faa
--- /dev/null
@@ -0,0 +1,96 @@
+From 78095fcc3bc9b620e9d11f61380b4d75c75b11e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Apr 2024 16:04:30 -0400
+Subject: serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using
+ prescaler
+
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+[ Upstream commit 8492bd91aa055907c67ef04f2b56f6dadd1f44bf ]
+
+When using a high speed clock with a low baud rate, the 4x prescaler is
+automatically selected if required. In that case, sc16is7xx_set_baud()
+properly configures the chip registers, but returns an incorrect baud
+rate by not taking into account the prescaler value. This incorrect baud
+rate is then fed to uart_update_timeout().
+
+For example, with an input clock of 80MHz, and a selected baud rate of 50,
+sc16is7xx_set_baud() will return 200 instead of 50.
+
+Fix this by first changing the prescaler variable to hold the selected
+prescaler value instead of the MCR bitfield. Then properly take into
+account the selected prescaler value in the return value computation.
+
+Also add better documentation about the divisor value computation.
+
+Fixes: dfeae619d781 ("serial: sc16is7xx")
+Cc: stable@vger.kernel.org
+Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/20240430200431.4102923-1-hugo@hugovil.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/sc16is7xx.c | 23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
+index 26ab1f042f5b8..7a9924d9b294e 100644
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -482,16 +482,28 @@ static bool sc16is7xx_regmap_noinc(struct device *dev, unsigned int reg)
+       return reg == SC16IS7XX_RHR_REG;
+ }
++/*
++ * Configure programmable baud rate generator (divisor) according to the
++ * desired baud rate.
++ *
++ * From the datasheet, the divisor is computed according to:
++ *
++ *              XTAL1 input frequency
++ *             -----------------------
++ *                    prescaler
++ * divisor = ---------------------------
++ *            baud-rate x sampling-rate
++ */
+ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
+ {
+       struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
+       u8 lcr;
+-      u8 prescaler = 0;
++      unsigned int prescaler = 1;
+       unsigned long clk = port->uartclk, div = clk / 16 / baud;
+       if (div >= BIT(16)) {
+-              prescaler = SC16IS7XX_MCR_CLKSEL_BIT;
+-              div /= 4;
++              prescaler = 4;
++              div /= prescaler;
+       }
+       /* In an amazing feat of design, the Enhanced Features Register shares
+@@ -528,9 +540,10 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
+       mutex_unlock(&one->efr_lock);
++      /* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */
+       sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
+                             SC16IS7XX_MCR_CLKSEL_BIT,
+-                            prescaler);
++                            prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT);
+       /* Open the LCR divisors for configuration */
+       sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
+@@ -545,7 +558,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
+       /* Put LCR back to the normal mode */
+       sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
+-      return DIV_ROUND_CLOSEST(clk / 16, div);
++      return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div);
+ }
+ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
+-- 
+2.43.0
+
diff --git a/queue-6.6/serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch b/queue-6.6/serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch
new file mode 100644 (file)
index 0000000..9711441
--- /dev/null
@@ -0,0 +1,39 @@
+From 0e7ed75410858e06e83d7a5972d7198fd14f5baf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Dec 2023 18:18:19 -0500
+Subject: serial: sc16is7xx: replace hardcoded divisor value with BIT() macro
+
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+[ Upstream commit 2e57cefc4477659527f7adab1f87cdbf60ef1ae6 ]
+
+To better show why the limit is what it is, since we have only 16 bits for
+the divisor.
+
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Link: https://lore.kernel.org/r/20231221231823.2327894-13-hugo@hugovil.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 8492bd91aa05 ("serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/sc16is7xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
+index 89eea1b8070fb..26ab1f042f5b8 100644
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -489,7 +489,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
+       u8 prescaler = 0;
+       unsigned long clk = port->uartclk, div = clk / 16 / baud;
+-      if (div > 0xffff) {
++      if (div >= BIT(16)) {
+               prescaler = SC16IS7XX_MCR_CLKSEL_BIT;
+               div /= 4;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/serial-sh-sci-protect-invalidating-rxdma-on-shutdown.patch b/queue-6.6/serial-sh-sci-protect-invalidating-rxdma-on-shutdown.patch
new file mode 100644 (file)
index 0000000..808d9f0
--- /dev/null
@@ -0,0 +1,47 @@
+From 2209d59fec998d2808104e4599b979f78495d545 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 May 2024 13:40:17 +0200
+Subject: serial: sh-sci: protect invalidating RXDMA on shutdown
+
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+
+[ Upstream commit aae20f6e34cd0cbd67a1d0e5877561c40109a81b ]
+
+The to-be-fixed commit removed locking when invalidating the DMA RX
+descriptors on shutdown. It overlooked that there is still a rx_timer
+running which may still access the protected data. So, re-add the
+locking.
+
+Reported-by: Dirk Behme <dirk.behme@de.bosch.com>
+Closes: https://lore.kernel.org/r/ee6c9e16-9f29-450e-81da-4a8dceaa8fc7@de.bosch.com
+Fixes: 2c4ee23530ff ("serial: sh-sci: Postpone DMA release when falling back to PIO")
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Link: https://lore.kernel.org/r/20240506114016.30498-7-wsa+renesas@sang-engineering.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/sh-sci.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index a560b729fa3b7..f793624fd5018 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -1272,9 +1272,14 @@ static void sci_dma_rx_chan_invalidate(struct sci_port *s)
+ static void sci_dma_rx_release(struct sci_port *s)
+ {
+       struct dma_chan *chan = s->chan_rx_saved;
++      struct uart_port *port = &s->port;
++      unsigned long flags;
++      uart_port_lock_irqsave(port, &flags);
+       s->chan_rx_saved = NULL;
+       sci_dma_rx_chan_invalidate(s);
++      uart_port_unlock_irqrestore(port, flags);
++
+       dmaengine_terminate_sync(chan);
+       dma_free_coherent(chan->device->dev, s->buf_len_rx * 2, s->rx_buf[0],
+                         sg_dma_address(&s->sg_rx[0]));
+-- 
+2.43.0
+
index 5e9dddb866e6e9bf870be583a5b924fe2b5deaec..649a367f83770645aa12e421a17626195b996eed 100644 (file)
@@ -387,3 +387,179 @@ af_packet-do-not-call-packet_read_pending-from-tpack.patch
 sched-fair-allow-disabling-sched_balance_newidle-wit.patch
 sched-core-fix-incorrect-initialization-of-the-burst.patch
 net-wangxun-fix-to-change-rx-features.patch
+perf-record-delete-session-after-stopping-sideband-t.patch
+perf-probe-add-missing-libgen.h-header-needed-for-us.patch
+iio-core-leave-private-pointer-null-when-no-private-.patch
+greybus-lights-check-return-of-get_channel_from_mode.patch
+phy-qcom-qmp-combo-fix-duplicate-return-in-qmp_v4_co.patch
+f2fs-multidev-fix-to-recognize-valid-zero-block-addr.patch
+f2fs-fix-to-wait-on-page-writeback-in-__clone_blkadd.patch
+fpga-manager-add-owner-module-and-take-its-refcount.patch
+fpga-bridge-add-owner-module-and-take-its-refcount.patch
+counter-linux-counter.h-fix-excess-kernel-doc-descri.patch
+perf-annotate-get-rid-of-duplicate-group-option-item.patch
+usb-typec-ucsi-always-register-a-link-to-usb-pd-devi.patch
+usb-typec-ucsi-simplify-partner-s-pd-caps-registrati.patch
+perf-stat-do-not-fail-on-metrics-on-s390-z-vm-system.patch
+soundwire-cadence-fix-invalid-pdi-offset.patch
+dmaengine-idma64-add-check-for-dma_set_max_seg_size.patch
+firmware-dmi-id-add-a-release-callback-function.patch
+perf-record-lazy-load-kernel-symbols.patch
+perf-machine-thread-remove-exited-threads-by-default.patch
+perf-annotate-split-branch-stack-cycles-information-.patch
+perf-annotate-introduce-global-annotation_options.patch
+perf-report-convert-to-the-global-annotation_options.patch
+perf-top-convert-to-the-global-annotation_options.patch
+perf-annotate-use-global-annotation_options.patch
+perf-annotate-fix-annotation_calc_lines-to-pass-corr.patch
+serial-max3100-lock-port-lock-when-calling-uart_hand.patch
+serial-max3100-update-uart_driver_registered-on-driv.patch
+serial-max3100-fix-bitwise-types.patch
+greybus-arche-ctrl-move-device-table-to-its-right-lo.patch
+pci-tegra194-fix-probe-path-for-endpoint-mode.patch
+serial-sc16is7xx-add-proper-sched.h-include-for-sche.patch
+module-don-t-ignore-sysfs_create_link-failures.patch
+interconnect-qcom-qcm2290-fix-mas_snoc_bimc-qos-port.patch
+arm64-dts-meson-fix-s4-power-controller-node.patch
+perf-tests-make-test-data-symbol-more-robust-on-neov.patch
+perf-tests-apply-attributes-to-all-events-in-object-.patch
+perf-evlist-add-evlist__findnew_tracking_event-helpe.patch
+perf-record-move-setting-tracking-events-before-reco.patch
+perf-record-fix-debug-message-placement-for-test-con.patch
+dt-bindings-pci-rcar-pci-host-add-optional-regulator.patch
+dt-bindings-pci-rcar-pci-host-add-missing-iommu-prop.patch
+perf-bench-uprobe-remove-lib64-from-libc.so.6-binary.patch
+f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch
+f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch-466
+f2fs-fix-to-relocate-check-condition-in-f2fs_falloca.patch
+f2fs-fix-to-check-pinfile-flag-in-f2fs_move_file_ran.patch
+iio-adc-stm32-fixing-err-code-to-not-indicate-succes.patch
+riscv-dts-starfive-visionfive-2-remove-non-existing-.patch
+ovl-add-helper-ovl_file_modified.patch
+splice-remove-permission-hook-from-iter_file_splice_.patch
+fs-move-kiocb_start_write-into-vfs_iocb_iter_write.patch
+remove-call_-read-write-_iter-functions.patch
+coresight-etm4x-fix-unbalanced-pm_runtime_enable.patch
+perf-docs-document-bpf-event-modifier.patch
+perf-test-shell-arm_coresight-increase-buffer-size-f.patch
+iio-pressure-dps310-support-negative-temperature-val.patch
+iio-adc-ad9467-use-spi_get_device_match_data.patch
+iio-adc-ad9467-use-chip_info-variables-instead-of-ar.patch
+iio-adc-adi-axi-adc-convert-to-regmap.patch
+iio-buffer-dmaengine-export-buffer-alloc-and-free-fu.patch
+iio-add-the-iio-backend-framework.patch
+iio-adc-ad9467-convert-to-backend-framework.patch
+iio-adc-adi-axi-adc-move-to-backend-framework.patch
+iio-adc-adi-axi-adc-only-error-out-in-major-version-.patch
+coresight-etm4x-do-not-hardcode-iomem-access-for-reg.patch
+coresight-etm4x-do-not-save-restore-data-trace-contr.patch
+coresight-etm4x-safe-access-for-trcqcltr.patch
+coresight-etm4x-fix-access-to-resource-selector-regi.patch
+i915-make-inject_virtual_interrupt-void.patch
+vfio-pci-fix-potential-memory-leak-in-vfio_intx_enab.patch
+fpga-region-add-owner-module-and-take-its-refcount.patch
+udf-remove-gfp_nofs-allocation-in-udf_expand_file_ad.patch
+udf-convert-udf_expand_file_adinicb-to-use-a-folio.patch
+xfs-require-xfs_sb_feat_incompat_log_xattrs-for-attr.patch
+microblaze-remove-gcc-flag-for-non-existing-early_pr.patch
+microblaze-remove-early-printk-call-from-cpuinfo-sta.patch
+pci-wait-for-link-training-0-before-starting-link-re.patch
+perf-intel-pt-fix-unassigned-instruction-op-discover.patch
+xfs-match-lock-mode-in-xfs_buffered_write_iomap_begi.patch
+risc-v-enable-cbo.zero-in-usermode.patch
+riscv-flush-the-instruction-cache-during-smp-bringup.patch
+pwm-rename-pwm_apply_state-to-pwm_apply_might_sleep.patch
+leds-pwm-disable-pwm-when-going-to-suspend.patch
+ovl-remove-upper-umask-handling-from-ovl_create_uppe.patch
+pci-of_property-return-error-for-int_map-allocation-.patch
+vmci-fix-an-error-handling-path-in-vmci_guest_probe_.patch
+xfs-convert-kmem_free-for-kvmalloc-users-to-kvfree.patch
+xfs-fix-log-recovery-buffer-allocation-for-the-legac.patch
+xfs-upgrade-the-extent-counters-in-xfs_reflink_end_c.patch
+dt-bindings-pinctrl-mediatek-mt7622-fix-array-proper.patch
+pinctrl-qcom-pinctrl-sm7150-fix-sdc1-and-ufs-special.patch
+watchdog-cpu5wdt.c-fix-use-after-free-bug-caused-by-.patch
+watchdog-bd9576-drop-always-running-property.patch
+watchdog-sa1100-fix-ptr_err_or_zero-vs-null-check-in.patch
+dt-bindings-phy-qcom-sc8280xp-qmp-ufs-phy-fix-msm899.patch
+dt-bindings-phy-qcom-usb-snps-femto-v2-use-correct-f.patch
+dmaengine-idxd-avoid-unnecessary-destruction-of-file.patch
+usb-gadget-u_audio-fix-race-condition-use-of-control.patch
+usb-gadget-u_audio-clear-uac-pointer-when-freed.patch
+stm-class-fix-a-double-free-in-stm_register_device.patch
+ppdev-remove-usage-of-the-deprecated-ida_simple_xx-a.patch
+ppdev-add-an-error-check-in-register_device.patch
+i2c-cadence-avoid-fifo-clear-after-start.patch
+i2c-synquacer-fix-an-error-handling-path-in-synquace.patch
+perf-bench-internals-inject-build-id-fix-trap-divide.patch
+perf-ui-browser-don-t-save-pointer-to-stack-memory.patch
+extcon-max8997-select-irq_domain-instead-of-dependin.patch
+dt-bindings-spmi-hisilicon-hisi-spmi-controller-fix-.patch
+pci-edr-align-edr_port_dpc_enable_dsm-with-pci-firmw.patch
+pci-edr-align-edr_port_locate_dsm-with-pci-firmware-.patch
+f2fs-clean-up-errors-in-segment.h.patch
+f2fs-support-printk_ratelimited-in-f2fs_printk.patch
+f2fs-use-blks_per_seg-blks_per_sec-and-segs_per_sec.patch
+f2fs-separate-f2fs_gc_range-to-use-gc-for-a-range.patch
+f2fs-kill-heap-based-allocation.patch
+f2fs-support-file-pinning-for-zoned-devices.patch
+f2fs-fix-block-migration-when-section-is-not-aligned.patch
+perf-ui-browser-avoid-segv-on-title.patch
+perf-report-avoid-segv-in-report__setup_sample_type.patch
+perf-thread-fixes-to-thread__new-related-to-initiali.patch
+perf-maps-move-symbol-maps-functions-to-maps.c.patch
+perf-symbols-fix-ownership-of-string-in-dso__load_vm.patch
+f2fs-compress-fix-to-update-i_compr_blocks-correctly.patch
+f2fs-deprecate-io_bits.patch
+f2fs-introduce-get_available_block_count-for-cleanup.patch
+f2fs-compress-fix-error-path-of-inc_valid_block_coun.patch
+f2fs-compress-fix-to-cover-reserve-release-_compress.patch
+f2fs-fix-to-release-node-block-count-in-error-path-o.patch
+f2fs-compress-don-t-allow-unaligned-truncation-on-re.patch
+serial-sh-sci-protect-invalidating-rxdma-on-shutdown.patch
+libsubcmd-fix-parse-options-memory-leak.patch
+perf-daemon-fix-file-leak-in-daemon_session__control.patch
+f2fs-fix-to-add-missing-iput-in-gc_data_segment.patch
+usb-fotg210-add-missing-kernel-doc-description.patch
+perf-stat-don-t-display-metric-header-for-non-leader.patch
+perf-test-add-a-test-for-strcmp_cpuid_str-expression.patch
+perf-pmu-move-pmu__find_core_pmu-to-pmus.c.patch
+perf-pmu-compat-supports-regular-expression-matching.patch
+perf-tools-use-pmus-to-describe-type-from-attribute.patch
+perf-tools-add-use-pmu-reverse-lookup-from-config-to.patch
+perf-pmu-assume-sysfs-events-are-always-the-same-cas.patch
+perf-pmu-count-sys-and-cpuid-json-events-separately.patch
+loongarch-fix-callchain-parse-error-with-kernel-trac.patch
+s390-vdso64-filter-out-munaligned-symbols-flag-for-v.patch
+s390-vdso-generate-unwind-information-for-c-modules.patch
+kbuild-unify-vdso_install-rules.patch
+kbuild-fix-build-id-symlinks-to-installed-debug-vdso.patch
+s390-vdso-create-.build-id-links-for-unstripped-vdso.patch
+s390-vdso-use-standard-stack-frame-layout.patch
+s390-ipl-fix-incorrect-initialization-of-len-fields-.patch
+s390-ipl-fix-incorrect-initialization-of-nvme-dump-b.patch
+s390-boot-remove-alt_stfle_fac_list-from-decompresso.patch
+dt-bindings-pci-rockchip-rk3399-pcie-add-missing-max.patch
+gpiolib-acpi-fix-failed-in-acpi_gpiochip_find-by-add.patch
+drm-amd-display-remove-pixle-rate-limit-for-subvp.patch
+drm-amd-display-revert-remove-pixle-rate-limit-for-s.patch
+eventfs-do-not-differentiate-the-toplevel-events-dir.patch
+alsa-timer-set-lower-bound-of-start-tick-time.patch
+iio-accel-mxc4005-allow-module-autoloading-via-of-co.patch
+iio-accel-mxc4005-reset-chip-on-probe-and-resume.patch
+misc-pvpanic-deduplicate-common-code.patch
+misc-pvpanic-pci-register-attributes-via-pci_driver.patch
+arm64-fpsimd-drop-unneeded-busy-flag.patch
+arm64-fpsimd-preserve-restore-kernel-mode-neon-at-co.patch
+arm64-fpsimd-implement-lazy-restore-for-kernel-mode-.patch
+revert-arm64-fpsimd-implement-lazy-restore-for-kerne.patch
+arm64-fpsimd-avoid-erroneous-elide-of-user-state-rel.patch
+reapply-arm64-fpsimd-implement-lazy-restore-for-kern.patch
+serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch
+serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch
+eventfs-create-eventfs_root_inode-to-store-dentry.patch
+eventfs-tracing-add-callback-for-release-of-an-event.patch
+eventfs-free-all-of-the-eventfs_inode-after-rcu.patch
+eventfs-have-events-directory-get-permissions-from-i.patch
+dt-bindings-adc-axi-adc-update-bindings-for-backend-.patch
+dt-bindings-adc-axi-adc-add-clocks-property.patch
diff --git a/queue-6.6/soundwire-cadence-fix-invalid-pdi-offset.patch b/queue-6.6/soundwire-cadence-fix-invalid-pdi-offset.patch
new file mode 100644 (file)
index 0000000..5179e9b
--- /dev/null
@@ -0,0 +1,48 @@
+From bf80ff44be806a9356e3fe6c06964248ccabd901 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Mar 2024 09:01:16 +0000
+Subject: soundwire: cadence: fix invalid PDI offset
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit 8ee1b439b1540ae543149b15a2a61b9dff937d91 ]
+
+For some reason, we add an offset to the PDI, presumably to skip the
+PDI0 and PDI1 which are reserved for BPT.
+
+This code is however completely wrong and leads to an out-of-bounds
+access. We were just lucky so far since we used only a couple of PDIs
+and remained within the PDI array bounds.
+
+A Fixes: tag is not provided since there are no known platforms where
+the out-of-bounds would be accessed, and the initial code had problems
+as well.
+
+A follow-up patch completely removes this useless offset.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20240326090122.1051806-2-yung-chuan.liao@linux.intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soundwire/cadence_master.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
+index 0efc1c3bee5f5..3e7cf04aaf2a6 100644
+--- a/drivers/soundwire/cadence_master.c
++++ b/drivers/soundwire/cadence_master.c
+@@ -1880,7 +1880,7 @@ struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns,
+       /* check if we found a PDI, else find in bi-directional */
+       if (!pdi)
+-              pdi = cdns_find_pdi(cdns, 2, stream->num_bd, stream->bd,
++              pdi = cdns_find_pdi(cdns, 0, stream->num_bd, stream->bd,
+                                   dai_id);
+       if (pdi) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/splice-remove-permission-hook-from-iter_file_splice_.patch b/queue-6.6/splice-remove-permission-hook-from-iter_file_splice_.patch
new file mode 100644 (file)
index 0000000..cf55d48
--- /dev/null
@@ -0,0 +1,72 @@
+From 9519e9d1e625d4f01b3c8a1c32042e3f5da53b0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Nov 2023 18:51:44 +0100
+Subject: splice: remove permission hook from iter_file_splice_write()
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+[ Upstream commit d53471ba6f7ae97a4e223539029528108b705af1 ]
+
+All the callers of ->splice_write(), (e.g. do_splice_direct() and
+do_splice()) already check rw_verify_area() for the entire range
+and perform all the other checks that are in vfs_write_iter().
+
+Instead of creating another tiny helper for special caller, just
+open-code it.
+
+This is needed for fanotify "pre content" events.
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Link: https://lore.kernel.org/r/20231122122715.2561213-6-amir73il@gmail.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Stable-dep-of: 7c98f7cb8fda ("remove call_{read,write}_iter() functions")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/splice.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/fs/splice.c b/fs/splice.c
+index d983d375ff113..a8f97c5e8cf0e 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -673,10 +673,13 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+               .u.file = out,
+       };
+       int nbufs = pipe->max_usage;
+-      struct bio_vec *array = kcalloc(nbufs, sizeof(struct bio_vec),
+-                                      GFP_KERNEL);
++      struct bio_vec *array;
+       ssize_t ret;
++      if (!out->f_op->write_iter)
++              return -EINVAL;
++
++      array = kcalloc(nbufs, sizeof(struct bio_vec), GFP_KERNEL);
+       if (unlikely(!array))
+               return -ENOMEM;
+@@ -684,6 +687,7 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+       splice_from_pipe_begin(&sd);
+       while (sd.total_len) {
++              struct kiocb kiocb;
+               struct iov_iter from;
+               unsigned int head, tail, mask;
+               size_t left;
+@@ -733,7 +737,10 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+               }
+               iov_iter_bvec(&from, ITER_SOURCE, array, n, sd.total_len - left);
+-              ret = vfs_iter_write(out, &from, &sd.pos, 0);
++              init_sync_kiocb(&kiocb, out);
++              kiocb.ki_pos = sd.pos;
++              ret = call_write_iter(out, &kiocb, &from);
++              sd.pos = kiocb.ki_pos;
+               if (ret <= 0)
+                       break;
+-- 
+2.43.0
+
diff --git a/queue-6.6/stm-class-fix-a-double-free-in-stm_register_device.patch b/queue-6.6/stm-class-fix-a-double-free-in-stm_register_device.patch
new file mode 100644 (file)
index 0000000..1322dc4
--- /dev/null
@@ -0,0 +1,57 @@
+From c40f1b3c8771aac0d38b9769b916c380dba14f74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Apr 2024 16:01:05 +0300
+Subject: stm class: Fix a double free in stm_register_device()
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit 3df463865ba42b8f88a590326f4c9ea17a1ce459 ]
+
+The put_device(&stm->dev) call will trigger stm_device_release() which
+frees "stm" so the vfree(stm) on the next line is a double free.
+
+Fixes: 389b6699a2aa ("stm class: Fix stm device initialization order")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Reviewed-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Link: https://lore.kernel.org/r/20240429130119.1518073-2-alexander.shishkin@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/stm/core.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
+index 534fbefc7f6aa..20895d3915623 100644
+--- a/drivers/hwtracing/stm/core.c
++++ b/drivers/hwtracing/stm/core.c
+@@ -868,8 +868,11 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data,
+               return -ENOMEM;
+       stm->major = register_chrdev(0, stm_data->name, &stm_fops);
+-      if (stm->major < 0)
+-              goto err_free;
++      if (stm->major < 0) {
++              err = stm->major;
++              vfree(stm);
++              return err;
++      }
+       device_initialize(&stm->dev);
+       stm->dev.devt = MKDEV(stm->major, 0);
+@@ -913,10 +916,8 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data,
+ err_device:
+       unregister_chrdev(stm->major, stm_data->name);
+-      /* matches device_initialize() above */
++      /* calls stm_device_release() */
+       put_device(&stm->dev);
+-err_free:
+-      vfree(stm);
+       return err;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/udf-convert-udf_expand_file_adinicb-to-use-a-folio.patch b/queue-6.6/udf-convert-udf_expand_file_adinicb-to-use-a-folio.patch
new file mode 100644 (file)
index 0000000..c14065d
--- /dev/null
@@ -0,0 +1,85 @@
+From 5bff92a3c37ffb398a787fd5669e61ce40d9710f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Apr 2024 16:04:09 +0100
+Subject: udf: Convert udf_expand_file_adinicb() to use a folio
+
+From: Matthew Wilcox (Oracle) <willy@infradead.org>
+
+[ Upstream commit db6754090a4f99c67e05ae6b87343ba6e013531f ]
+
+Use the folio APIs throughout this function.
+
+Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Fixes: 1eeceaec794e ("udf: Convert udf_expand_file_adinicb() to avoid kmap_atomic()")
+Signed-off-by: Jan Kara <jack@suse.cz>
+Message-Id: <20240417150416.752929-4-willy@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/udf/inode.c | 27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index 7f7610dddcba1..1ff8c1f17f9e6 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -341,7 +341,7 @@ const struct address_space_operations udf_aops = {
+  */
+ int udf_expand_file_adinicb(struct inode *inode)
+ {
+-      struct page *page;
++      struct folio *folio;
+       struct udf_inode_info *iinfo = UDF_I(inode);
+       int err;
+@@ -357,12 +357,13 @@ int udf_expand_file_adinicb(struct inode *inode)
+               return 0;
+       }
+-      page = find_or_create_page(inode->i_mapping, 0, GFP_KERNEL);
+-      if (!page)
+-              return -ENOMEM;
++      folio = __filemap_get_folio(inode->i_mapping, 0,
++                      FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_KERNEL);
++      if (IS_ERR(folio))
++              return PTR_ERR(folio);
+-      if (!PageUptodate(page))
+-              udf_adinicb_readpage(page);
++      if (!folio_test_uptodate(folio))
++              udf_adinicb_readpage(&folio->page);
+       down_write(&iinfo->i_data_sem);
+       memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00,
+              iinfo->i_lenAlloc);
+@@ -371,22 +372,22 @@ int udf_expand_file_adinicb(struct inode *inode)
+               iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
+       else
+               iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
+-      set_page_dirty(page);
+-      unlock_page(page);
++      folio_mark_dirty(folio);
++      folio_unlock(folio);
+       up_write(&iinfo->i_data_sem);
+       err = filemap_fdatawrite(inode->i_mapping);
+       if (err) {
+               /* Restore everything back so that we don't lose data... */
+-              lock_page(page);
++              folio_lock(folio);
+               down_write(&iinfo->i_data_sem);
+-              memcpy_to_page(page, 0, iinfo->i_data + iinfo->i_lenEAttr,
+-                             inode->i_size);
+-              unlock_page(page);
++              memcpy_from_folio(iinfo->i_data + iinfo->i_lenEAttr,
++                              folio, 0, inode->i_size);
++              folio_unlock(folio);
+               iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
+               iinfo->i_lenAlloc = inode->i_size;
+               up_write(&iinfo->i_data_sem);
+       }
+-      put_page(page);
++      folio_put(folio);
+       mark_inode_dirty(inode);
+       return err;
+-- 
+2.43.0
+
diff --git a/queue-6.6/udf-remove-gfp_nofs-allocation-in-udf_expand_file_ad.patch b/queue-6.6/udf-remove-gfp_nofs-allocation-in-udf_expand_file_ad.patch
new file mode 100644 (file)
index 0000000..d119614
--- /dev/null
@@ -0,0 +1,39 @@
+From df0abc84020518da4e1437d3d088edaa59e484f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Jan 2024 11:15:43 +0100
+Subject: udf: Remove GFP_NOFS allocation in udf_expand_file_adinicb()
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit 38f8af2a7191e5da21c557210d810c6d0d34f6c4 ]
+
+udf_expand_file_adinicb() is called under inode->i_rwsem and
+mapping->invalidate_lock. i_rwsem is safe wrt fs reclaim,
+invalidate_lock on this inode is safe as well (we hold inode reference
+so reclaim will not touch it, furthermore even lockdep should not
+complain as invalidate_lock is acquired from udf_evict_inode() only when
+truncating inode which should not happen from fs reclaim).
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Stable-dep-of: db6754090a4f ("udf: Convert udf_expand_file_adinicb() to use a folio")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/udf/inode.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index a17a6184cc39e..7f7610dddcba1 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -357,7 +357,7 @@ int udf_expand_file_adinicb(struct inode *inode)
+               return 0;
+       }
+-      page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS);
++      page = find_or_create_page(inode->i_mapping, 0, GFP_KERNEL);
+       if (!page)
+               return -ENOMEM;
+-- 
+2.43.0
+
diff --git a/queue-6.6/usb-fotg210-add-missing-kernel-doc-description.patch b/queue-6.6/usb-fotg210-add-missing-kernel-doc-description.patch
new file mode 100644 (file)
index 0000000..0493df7
--- /dev/null
@@ -0,0 +1,40 @@
+From 6b35b6b35f2eab42d6f460e584a3ab999ed03f5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 18:26:22 +0300
+Subject: usb: fotg210: Add missing kernel doc description
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 4b653e82ae18f2dc91c7132b54f5785c4d56bab4 ]
+
+kernel-doc validator is not happy:
+
+  warning: Function parameter or struct member 'fotg' not described in 'fotg210_vbus'
+
+Add missing description.
+
+Fixes: 3e679bde529e ("usb: fotg210-udc: Implement VBUS session")
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Link: https://lore.kernel.org/r/20240510152641.2421298-1-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/fotg210/fotg210-core.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/usb/fotg210/fotg210-core.c b/drivers/usb/fotg210/fotg210-core.c
+index 958fc40eae86b..0655afe7f9779 100644
+--- a/drivers/usb/fotg210/fotg210-core.c
++++ b/drivers/usb/fotg210/fotg210-core.c
+@@ -95,6 +95,7 @@ static int fotg210_gemini_init(struct fotg210 *fotg, struct resource *res,
+ /**
+  * fotg210_vbus() - Called by gadget driver to enable/disable VBUS
++ * @fotg: pointer to a private fotg210 object
+  * @enable: true to enable VBUS, false to disable VBUS
+  */
+ void fotg210_vbus(struct fotg210 *fotg, bool enable)
+-- 
+2.43.0
+
diff --git a/queue-6.6/usb-gadget-u_audio-clear-uac-pointer-when-freed.patch b/queue-6.6/usb-gadget-u_audio-clear-uac-pointer-when-freed.patch
new file mode 100644 (file)
index 0000000..88ada2e
--- /dev/null
@@ -0,0 +1,40 @@
+From 6f223316238081c613ee78ba1c423668fe5f8c34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 15:20:20 +0000
+Subject: usb: gadget: u_audio: Clear uac pointer when freed.
+
+From: Chris Wulff <Chris.Wulff@biamp.com>
+
+[ Upstream commit a2cf936ebef291ef7395172b9e2f624779fb6dc0 ]
+
+This prevents use of a stale pointer if functions are called after
+g_cleanup that shouldn't be. This doesn't fix any races, but converts
+a possibly silent kernel memory corruption into an obvious NULL pointer
+dereference report.
+
+Fixes: eb9fecb9e69b ("usb: gadget: f_uac2: split out audio core")
+Signed-off-by: Chris Wulff <chris.wulff@biamp.com>
+Link: https://lore.kernel.org/stable/CO1PR17MB54194226DA08BFC9EBD8C163E1172%40CO1PR17MB5419.namprd17.prod.outlook.com
+Link: https://lore.kernel.org/r/CO1PR17MB54194226DA08BFC9EBD8C163E1172@CO1PR17MB5419.namprd17.prod.outlook.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/gadget/function/u_audio.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c
+index c8e8154c59f50..ec1dceb087293 100644
+--- a/drivers/usb/gadget/function/u_audio.c
++++ b/drivers/usb/gadget/function/u_audio.c
+@@ -1419,6 +1419,8 @@ void g_audio_cleanup(struct g_audio *g_audio)
+               return;
+       uac = g_audio->uac;
++      g_audio->uac = NULL;
++
+       card = uac->card;
+       if (card)
+               snd_card_free_when_closed(card);
+-- 
+2.43.0
+
diff --git a/queue-6.6/usb-gadget-u_audio-fix-race-condition-use-of-control.patch b/queue-6.6/usb-gadget-u_audio-fix-race-condition-use-of-control.patch
new file mode 100644 (file)
index 0000000..546d8a7
--- /dev/null
@@ -0,0 +1,110 @@
+From 34d6b8ffa32141b046c0c4a67ca2cc2c4d9adb80 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 15:18:01 +0000
+Subject: usb: gadget: u_audio: Fix race condition use of controls after free
+ during gadget unbind.
+
+From: Chris Wulff <Chris.Wulff@biamp.com>
+
+[ Upstream commit 1b739388aa3f8dfb63a9fca777e6dfa6912d0464 ]
+
+Hang on to the control IDs instead of pointers since those are correctly
+handled with locks.
+
+Fixes: 8fe9a03f4331 ("usb: gadget: u_audio: Rate ctl notifies about current srate (0=stopped)")
+Fixes: c565ad07ef35 ("usb: gadget: u_audio: Support multiple sampling rates")
+Fixes: 02de698ca812 ("usb: gadget: u_audio: add bi-directional volume and mute support")
+Signed-off-by: Chris Wulff <chris.wulff@biamp.com>
+Link: https://lore.kernel.org/stable/CO1PR17MB5419C2BF44D400E4E620C1ADE1172%40CO1PR17MB5419.namprd17.prod.outlook.com
+Link: https://lore.kernel.org/r/CO1PR17MB5419C2BF44D400E4E620C1ADE1172@CO1PR17MB5419.namprd17.prod.outlook.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/gadget/function/u_audio.c | 19 +++++++++----------
+ 1 file changed, 9 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c
+index 4a42574b4a7fe..c8e8154c59f50 100644
+--- a/drivers/usb/gadget/function/u_audio.c
++++ b/drivers/usb/gadget/function/u_audio.c
+@@ -57,13 +57,13 @@ struct uac_rtd_params {
+   /* Volume/Mute controls and their state */
+   int fu_id; /* Feature Unit ID */
+-  struct snd_kcontrol *snd_kctl_volume;
+-  struct snd_kcontrol *snd_kctl_mute;
++  struct snd_ctl_elem_id snd_kctl_volume_id;
++  struct snd_ctl_elem_id snd_kctl_mute_id;
+   s16 volume_min, volume_max, volume_res;
+   s16 volume;
+   int mute;
+-      struct snd_kcontrol *snd_kctl_rate; /* read-only current rate */
++      struct snd_ctl_elem_id snd_kctl_rate_id; /* read-only current rate */
+       int srate; /* selected samplerate */
+       int active; /* playback/capture running */
+@@ -494,14 +494,13 @@ static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep)
+ static void set_active(struct uac_rtd_params *prm, bool active)
+ {
+       // notifying through the Rate ctrl
+-      struct snd_kcontrol *kctl = prm->snd_kctl_rate;
+       unsigned long flags;
+       spin_lock_irqsave(&prm->lock, flags);
+       if (prm->active != active) {
+               prm->active = active;
+               snd_ctl_notify(prm->uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
+-                              &kctl->id);
++                              &prm->snd_kctl_rate_id);
+       }
+       spin_unlock_irqrestore(&prm->lock, flags);
+ }
+@@ -807,7 +806,7 @@ int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val)
+       if (change)
+               snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
+-                              &prm->snd_kctl_volume->id);
++                              &prm->snd_kctl_volume_id);
+       return 0;
+ }
+@@ -856,7 +855,7 @@ int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val)
+       if (change)
+               snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
+-                             &prm->snd_kctl_mute->id);
++                             &prm->snd_kctl_mute_id);
+       return 0;
+ }
+@@ -1331,7 +1330,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
+                       err = snd_ctl_add(card, kctl);
+                       if (err < 0)
+                               goto snd_fail;
+-                      prm->snd_kctl_mute = kctl;
++                      prm->snd_kctl_mute_id = kctl->id;
+                       prm->mute = 0;
+               }
+@@ -1359,7 +1358,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
+                       err = snd_ctl_add(card, kctl);
+                       if (err < 0)
+                               goto snd_fail;
+-                      prm->snd_kctl_volume = kctl;
++                      prm->snd_kctl_volume_id = kctl->id;
+                       prm->volume = fu->volume_max;
+                       prm->volume_max = fu->volume_max;
+                       prm->volume_min = fu->volume_min;
+@@ -1383,7 +1382,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
+               err = snd_ctl_add(card, kctl);
+               if (err < 0)
+                       goto snd_fail;
+-              prm->snd_kctl_rate = kctl;
++              prm->snd_kctl_rate_id = kctl->id;
+       }
+       strscpy(card->driver, card_name, sizeof(card->driver));
+-- 
+2.43.0
+
diff --git a/queue-6.6/usb-typec-ucsi-always-register-a-link-to-usb-pd-devi.patch b/queue-6.6/usb-typec-ucsi-always-register-a-link-to-usb-pd-devi.patch
new file mode 100644 (file)
index 0000000..e737551
--- /dev/null
@@ -0,0 +1,52 @@
+From 2e15f48fd3bdd4fe173ad481ef8c4e52e5ce023b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Mar 2024 08:15:36 +0200
+Subject: usb: typec: ucsi: always register a link to USB PD device
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit c0f66d78f42353d38b9608c05f211cf0773d93ac ]
+
+UCSI driver will attempt to set a USB PD device only if it was able to
+read PDOs from the firmware. This results in suboptimal behaviour, since
+the PD device will be created anyway. Move calls to
+typec_port_set_usb_power_delivery() out of conditional code and call it
+after reading capabilities.
+
+Fixes: b04e1747fbcc ("usb: typec: ucsi: Register USB Power Delivery Capabilities")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20240329-qcom-ucsi-fixes-v2-4-0f5d37ed04db@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
+index 7d2ca39ad7622..4aac2a719b7cd 100644
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -1297,7 +1297,6 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
+               }
+               con->port_source_caps = pd_cap;
+-              typec_port_set_usb_power_delivery(con->port, con->pd);
+       }
+       memset(&pd_caps, 0, sizeof(pd_caps));
+@@ -1314,9 +1313,10 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
+               }
+               con->port_sink_caps = pd_cap;
+-              typec_port_set_usb_power_delivery(con->port, con->pd);
+       }
++      typec_port_set_usb_power_delivery(con->port, con->pd);
++
+       /* Alternate modes */
+       ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_CON);
+       if (ret) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/usb-typec-ucsi-simplify-partner-s-pd-caps-registrati.patch b/queue-6.6/usb-typec-ucsi-simplify-partner-s-pd-caps-registrati.patch
new file mode 100644 (file)
index 0000000..c872a83
--- /dev/null
@@ -0,0 +1,63 @@
+From fd7f8414fdb48736563592cca2b2584ddfdf9c2a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Mar 2024 08:15:37 +0200
+Subject: usb: typec: ucsi: simplify partner's PD caps registration
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 41e1cd1401fcd1f1ae9e47574af2d9fc44a870b3 ]
+
+In a way similar to the previous commit, move
+typec_partner_set_usb_power_delivery() to be called after reading the PD
+caps. This also removes calls to
+usb_power_delivery_unregister_capabilities() from the error path. Keep
+all capabilities registered until they are cleared by
+ucsi_unregister_partner_pdos().
+
+Fixes: b04e1747fbcc ("usb: typec: ucsi: Register USB Power Delivery Capabilities")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20240329-qcom-ucsi-fixes-v2-5-0f5d37ed04db@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c | 14 +-------------
+ 1 file changed, 1 insertion(+), 13 deletions(-)
+
+diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
+index 4aac2a719b7cd..7f575b9b3debe 100644
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -694,12 +694,6 @@ static int ucsi_register_partner_pdos(struct ucsi_connector *con)
+                       return PTR_ERR(cap);
+               con->partner_source_caps = cap;
+-
+-              ret = typec_partner_set_usb_power_delivery(con->partner, con->partner_pd);
+-              if (ret) {
+-                      usb_power_delivery_unregister_capabilities(con->partner_source_caps);
+-                      return ret;
+-              }
+       }
+       ret = ucsi_get_pdos(con, TYPEC_SINK, 1, caps.pdo);
+@@ -714,15 +708,9 @@ static int ucsi_register_partner_pdos(struct ucsi_connector *con)
+                       return PTR_ERR(cap);
+               con->partner_sink_caps = cap;
+-
+-              ret = typec_partner_set_usb_power_delivery(con->partner, con->partner_pd);
+-              if (ret) {
+-                      usb_power_delivery_unregister_capabilities(con->partner_sink_caps);
+-                      return ret;
+-              }
+       }
+-      return 0;
++      return typec_partner_set_usb_power_delivery(con->partner, con->partner_pd);
+ }
+ static void ucsi_unregister_partner_pdos(struct ucsi_connector *con)
+-- 
+2.43.0
+
diff --git a/queue-6.6/vfio-pci-fix-potential-memory-leak-in-vfio_intx_enab.patch b/queue-6.6/vfio-pci-fix-potential-memory-leak-in-vfio_intx_enab.patch
new file mode 100644 (file)
index 0000000..b344cb6
--- /dev/null
@@ -0,0 +1,41 @@
+From 9fc0f4853c70f603ba7f9a8184a10ed6fba19cfa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Apr 2024 09:50:29 +0800
+Subject: vfio/pci: fix potential memory leak in vfio_intx_enable()
+
+From: Ye Bin <yebin10@huawei.com>
+
+[ Upstream commit 82b951e6fbd31d85ae7f4feb5f00ddd4c5d256e2 ]
+
+If vfio_irq_ctx_alloc() failed will lead to 'name' memory leak.
+
+Fixes: 18c198c96a81 ("vfio/pci: Create persistent INTx handler")
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Acked-by: Reinette Chatre <reinette.chatre@intel.com>
+Link: https://lore.kernel.org/r/20240415015029.3699844-1-yebin10@huawei.com
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/pci/vfio_pci_intrs.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
+index 99bbd647e5d81..620134041b488 100644
+--- a/drivers/vfio/pci/vfio_pci_intrs.c
++++ b/drivers/vfio/pci/vfio_pci_intrs.c
+@@ -277,8 +277,10 @@ static int vfio_intx_enable(struct vfio_pci_core_device *vdev,
+               return -ENOMEM;
+       ctx = vfio_irq_ctx_alloc(vdev, 0);
+-      if (!ctx)
++      if (!ctx) {
++              kfree(name);
+               return -ENOMEM;
++      }
+       ctx->name = name;
+       ctx->trigger = trigger;
+-- 
+2.43.0
+
diff --git a/queue-6.6/vmci-fix-an-error-handling-path-in-vmci_guest_probe_.patch b/queue-6.6/vmci-fix-an-error-handling-path-in-vmci_guest_probe_.patch
new file mode 100644 (file)
index 0000000..152550c
--- /dev/null
@@ -0,0 +1,66 @@
+From 7e28061e6f5f2da69dbde06c2f183480b0a43e34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Apr 2024 14:27:23 +0200
+Subject: VMCI: Fix an error handling path in vmci_guest_probe_device()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 73df3d6f2e9533e93a5039a33c40dd7216b81801 ]
+
+After a successful pci_iomap_range() call, pci_iounmap() should be called
+in the error handling path, as already done in the remove function.
+
+Add the missing call.
+
+The corresponding call was added in the remove function in commit
+5ee109828e73 ("VMCI: dma dg: allocate send and receive buffers for DMA
+datagrams")
+
+Fixes: e283a0e8b7ea ("VMCI: dma dg: add MMIO access to registers")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Acked-by: Vishnu Dasa <vishnu.dasa@broadcom.com>
+Link: https://lore.kernel.org/r/a35bbc3876ae1da70e49dafde4435750e1477be3.1713961553.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/vmw_vmci/vmci_guest.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c
+index 4f8d962bb5b2a..1300ccab3d21b 100644
+--- a/drivers/misc/vmw_vmci/vmci_guest.c
++++ b/drivers/misc/vmw_vmci/vmci_guest.c
+@@ -625,7 +625,8 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
+       if (!vmci_dev) {
+               dev_err(&pdev->dev,
+                       "Can't allocate memory for VMCI device\n");
+-              return -ENOMEM;
++              error = -ENOMEM;
++              goto err_unmap_mmio_base;
+       }
+       vmci_dev->dev = &pdev->dev;
+@@ -642,7 +643,8 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
+               if (!vmci_dev->tx_buffer) {
+                       dev_err(&pdev->dev,
+                               "Can't allocate memory for datagram tx buffer\n");
+-                      return -ENOMEM;
++                      error = -ENOMEM;
++                      goto err_unmap_mmio_base;
+               }
+               vmci_dev->data_buffer = dma_alloc_coherent(&pdev->dev, VMCI_DMA_DG_BUFFER_SIZE,
+@@ -893,6 +895,10 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
+ err_free_data_buffers:
+       vmci_free_dg_buffers(vmci_dev);
++err_unmap_mmio_base:
++      if (mmio_base != NULL)
++              pci_iounmap(pdev, mmio_base);
++
+       /* The rest are managed resources and will be freed by PCI core */
+       return error;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/watchdog-bd9576-drop-always-running-property.patch b/queue-6.6/watchdog-bd9576-drop-always-running-property.patch
new file mode 100644 (file)
index 0000000..77b81db
--- /dev/null
@@ -0,0 +1,84 @@
+From dc4ad41e9af8f3f3aeeb7a98767a1fee97fab5eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Apr 2024 13:02:31 +0300
+Subject: watchdog: bd9576: Drop "always-running" property
+
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+
+[ Upstream commit e3b3afd34d84efcbe4543deb966b1990f43584b8 ]
+
+The always-running (from linux,wdt-gpio.yaml) is abused by the BD9576
+watchdog driver. It's defined meaning is "the watchdog is always running
+and can not be stopped". The BD9576 watchdog driver has implemented it
+as "start watchdog when loading the module and prevent it from being
+stopped".
+
+Furthermore, the implementation does not set the WDOG_HW_RUNNING when
+enabling the watchdog due to the "always-running" at module loading.
+This will end up resulting a watchdog timeout if the device is not
+opened.
+
+The culprit was pointed out by Guenter, discussion can be found from
+https://lore.kernel.org/lkml/4fa3a64b-60fb-4e5e-8785-0f14da37eea2@roeck-us.net/
+
+Drop the invalid "always-running" handling.
+
+Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Fixes: b237bcac557a ("wdt: Support wdt on ROHM BD9576MUF and BD9573MUF")
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/ZhPAt76yaJMersXf@fedora
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/bd9576_wdt.c | 12 +-----------
+ 1 file changed, 1 insertion(+), 11 deletions(-)
+
+diff --git a/drivers/watchdog/bd9576_wdt.c b/drivers/watchdog/bd9576_wdt.c
+index 4a20e07fbb699..f00ea1b4e40b6 100644
+--- a/drivers/watchdog/bd9576_wdt.c
++++ b/drivers/watchdog/bd9576_wdt.c
+@@ -29,7 +29,6 @@ struct bd9576_wdt_priv {
+       struct gpio_desc        *gpiod_en;
+       struct device           *dev;
+       struct regmap           *regmap;
+-      bool                    always_running;
+       struct watchdog_device  wdd;
+ };
+@@ -62,10 +61,7 @@ static int bd9576_wdt_stop(struct watchdog_device *wdd)
+ {
+       struct bd9576_wdt_priv *priv = watchdog_get_drvdata(wdd);
+-      if (!priv->always_running)
+-              bd9576_wdt_disable(priv);
+-      else
+-              set_bit(WDOG_HW_RUNNING, &wdd->status);
++      bd9576_wdt_disable(priv);
+       return 0;
+ }
+@@ -264,9 +260,6 @@ static int bd9576_wdt_probe(struct platform_device *pdev)
+       if (ret)
+               return ret;
+-      priv->always_running = device_property_read_bool(dev->parent,
+-                                                       "always-running");
+-
+       watchdog_set_drvdata(&priv->wdd, priv);
+       priv->wdd.info                  = &bd957x_wdt_ident;
+@@ -281,9 +274,6 @@ static int bd9576_wdt_probe(struct platform_device *pdev)
+       watchdog_stop_on_reboot(&priv->wdd);
+-      if (priv->always_running)
+-              bd9576_wdt_start(&priv->wdd);
+-
+       return devm_watchdog_register_device(dev, &priv->wdd);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/watchdog-cpu5wdt.c-fix-use-after-free-bug-caused-by-.patch b/queue-6.6/watchdog-cpu5wdt.c-fix-use-after-free-bug-caused-by-.patch
new file mode 100644 (file)
index 0000000..9364218
--- /dev/null
@@ -0,0 +1,46 @@
+From bd1962df9b07dfb8f9e769d9c5838576e2bf6436 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 Mar 2024 22:04:44 +0800
+Subject: watchdog: cpu5wdt.c: Fix use-after-free bug caused by cpu5wdt_trigger
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+[ Upstream commit 573601521277119f2e2ba5f28ae6e87fc594f4d4 ]
+
+When the cpu5wdt module is removing, the origin code uses del_timer() to
+de-activate the timer. If the timer handler is running, del_timer() could
+not stop it and will return directly. If the port region is released by
+release_region() and then the timer handler cpu5wdt_trigger() calls outb()
+to write into the region that is released, the use-after-free bug will
+happen.
+
+Change del_timer() to timer_shutdown_sync() in order that the timer handler
+could be finished before the port region is released.
+
+Fixes: e09d9c3e9f85 ("watchdog: cpu5wdt.c: add missing del_timer call")
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20240324140444.119584-1-duoming@zju.edu.cn
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/cpu5wdt.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
+index 688b112e712ba..9f279c0e13a66 100644
+--- a/drivers/watchdog/cpu5wdt.c
++++ b/drivers/watchdog/cpu5wdt.c
+@@ -252,7 +252,7 @@ static void cpu5wdt_exit(void)
+       if (cpu5wdt_device.queue) {
+               cpu5wdt_device.queue = 0;
+               wait_for_completion(&cpu5wdt_device.stop);
+-              del_timer(&cpu5wdt_device.timer);
++              timer_shutdown_sync(&cpu5wdt_device.timer);
+       }
+       misc_deregister(&cpu5wdt_misc);
+-- 
+2.43.0
+
diff --git a/queue-6.6/watchdog-sa1100-fix-ptr_err_or_zero-vs-null-check-in.patch b/queue-6.6/watchdog-sa1100-fix-ptr_err_or_zero-vs-null-check-in.patch
new file mode 100644 (file)
index 0000000..3987ae6
--- /dev/null
@@ -0,0 +1,43 @@
+From cd47ecd8c750da433ffb447d422d7fc1390ec5bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Apr 2024 15:58:08 +0800
+Subject: watchdog: sa1100: Fix PTR_ERR_OR_ZERO() vs NULL check in
+ sa1100dog_probe()
+
+From: Chen Ni <nichen@iscas.ac.cn>
+
+[ Upstream commit 413bf4e857fd79617524d5dcd35f463e9aa2dd41 ]
+
+devm_ioremap() doesn't return error pointers, it returns NULL on error.
+Update the check accordingly.
+
+Fixes: e86bd43bcfc5 ("watchdog: sa1100: use platform device registration")
+Signed-off-by: Chen Ni <nichen@iscas.ac.cn>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20240426075808.1582678-1-nichen@iscas.ac.cn
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/sa1100_wdt.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c
+index 5d2df008b92a5..34a917221e316 100644
+--- a/drivers/watchdog/sa1100_wdt.c
++++ b/drivers/watchdog/sa1100_wdt.c
+@@ -191,9 +191,8 @@ static int sa1100dog_probe(struct platform_device *pdev)
+       if (!res)
+               return -ENXIO;
+       reg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+-      ret = PTR_ERR_OR_ZERO(reg_base);
+-      if (ret)
+-              return ret;
++      if (!reg_base)
++              return -ENOMEM;
+       clk = clk_get(NULL, "OSTIMER0");
+       if (IS_ERR(clk)) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/xfs-convert-kmem_free-for-kvmalloc-users-to-kvfree.patch b/queue-6.6/xfs-convert-kmem_free-for-kvmalloc-users-to-kvfree.patch
new file mode 100644 (file)
index 0000000..f1b18d1
--- /dev/null
@@ -0,0 +1,472 @@
+From e21ad7e6349c01a9b3145afd8c80f9e437666a08 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Jan 2024 09:59:42 +1100
+Subject: xfs: convert kmem_free() for kvmalloc users to kvfree()
+
+From: Dave Chinner <dchinner@redhat.com>
+
+[ Upstream commit 49292576136fd2a6b58a51677c53151cf4877fa6 ]
+
+Start getting rid of kmem_free() by converting all the cases where
+memory can come from vmalloc interfaces to calling kvfree()
+directly.
+
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
+Stable-dep-of: 45cf976008dd ("xfs: fix log recovery buffer allocation for the legacy h_size fixup")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_acl.c           |  4 ++--
+ fs/xfs/xfs_attr_item.c     |  4 ++--
+ fs/xfs/xfs_bmap_item.c     |  4 ++--
+ fs/xfs/xfs_buf_item.c      |  2 +-
+ fs/xfs/xfs_dquot.c         |  2 +-
+ fs/xfs/xfs_extfree_item.c  |  4 ++--
+ fs/xfs/xfs_icreate_item.c  |  2 +-
+ fs/xfs/xfs_inode_item.c    |  2 +-
+ fs/xfs/xfs_ioctl.c         |  2 +-
+ fs/xfs/xfs_log.c           |  4 ++--
+ fs/xfs/xfs_log_cil.c       |  2 +-
+ fs/xfs/xfs_log_recover.c   | 42 +++++++++++++++++++-------------------
+ fs/xfs/xfs_refcount_item.c |  4 ++--
+ fs/xfs/xfs_rmap_item.c     |  4 ++--
+ fs/xfs/xfs_rtalloc.c       |  6 +++---
+ 15 files changed, 44 insertions(+), 44 deletions(-)
+
+diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
+index 6b840301817a9..4bf69c9c088e2 100644
+--- a/fs/xfs/xfs_acl.c
++++ b/fs/xfs/xfs_acl.c
+@@ -167,7 +167,7 @@ xfs_get_acl(struct inode *inode, int type, bool rcu)
+               acl = ERR_PTR(error);
+       }
+-      kmem_free(args.value);
++      kvfree(args.value);
+       return acl;
+ }
+@@ -204,7 +204,7 @@ __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+       }
+       error = xfs_attr_change(&args);
+-      kmem_free(args.value);
++      kvfree(args.value);
+       /*
+        * If the attribute didn't exist to start with that's fine.
+diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c
+index ebf656aaf3012..fc164e8f7e483 100644
+--- a/fs/xfs/xfs_attr_item.c
++++ b/fs/xfs/xfs_attr_item.c
+@@ -110,7 +110,7 @@ STATIC void
+ xfs_attri_item_free(
+       struct xfs_attri_log_item       *attrip)
+ {
+-      kmem_free(attrip->attri_item.li_lv_shadow);
++      kvfree(attrip->attri_item.li_lv_shadow);
+       xfs_attri_log_nameval_put(attrip->attri_nameval);
+       kmem_cache_free(xfs_attri_cache, attrip);
+ }
+@@ -253,7 +253,7 @@ static inline struct xfs_attrd_log_item *ATTRD_ITEM(struct xfs_log_item *lip)
+ STATIC void
+ xfs_attrd_item_free(struct xfs_attrd_log_item *attrdp)
+ {
+-      kmem_free(attrdp->attrd_item.li_lv_shadow);
++      kvfree(attrdp->attrd_item.li_lv_shadow);
+       kmem_cache_free(xfs_attrd_cache, attrdp);
+ }
+diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
+index b6d63b8bdad5a..dc4c199fa7af2 100644
+--- a/fs/xfs/xfs_bmap_item.c
++++ b/fs/xfs/xfs_bmap_item.c
+@@ -40,7 +40,7 @@ STATIC void
+ xfs_bui_item_free(
+       struct xfs_bui_log_item *buip)
+ {
+-      kmem_free(buip->bui_item.li_lv_shadow);
++      kvfree(buip->bui_item.li_lv_shadow);
+       kmem_cache_free(xfs_bui_cache, buip);
+ }
+@@ -201,7 +201,7 @@ xfs_bud_item_release(
+       struct xfs_bud_log_item *budp = BUD_ITEM(lip);
+       xfs_bui_release(budp->bud_buip);
+-      kmem_free(budp->bud_item.li_lv_shadow);
++      kvfree(budp->bud_item.li_lv_shadow);
+       kmem_cache_free(xfs_bud_cache, budp);
+ }
+diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
+index 023d4e0385dd0..7d447fbcdd983 100644
+--- a/fs/xfs/xfs_buf_item.c
++++ b/fs/xfs/xfs_buf_item.c
+@@ -1044,7 +1044,7 @@ xfs_buf_item_free(
+       struct xfs_buf_log_item *bip)
+ {
+       xfs_buf_item_free_format(bip);
+-      kmem_free(bip->bli_item.li_lv_shadow);
++      kvfree(bip->bli_item.li_lv_shadow);
+       kmem_cache_free(xfs_buf_item_cache, bip);
+ }
+diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
+index a013b87ab8d5e..5c9fd69d75959 100644
+--- a/fs/xfs/xfs_dquot.c
++++ b/fs/xfs/xfs_dquot.c
+@@ -53,7 +53,7 @@ xfs_qm_dqdestroy(
+ {
+       ASSERT(list_empty(&dqp->q_lru));
+-      kmem_free(dqp->q_logitem.qli_item.li_lv_shadow);
++      kvfree(dqp->q_logitem.qli_item.li_lv_shadow);
+       mutex_destroy(&dqp->q_qlock);
+       XFS_STATS_DEC(dqp->q_mount, xs_qm_dquot);
+diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
+index c9908fb337657..8904242f4eb45 100644
+--- a/fs/xfs/xfs_extfree_item.c
++++ b/fs/xfs/xfs_extfree_item.c
+@@ -40,7 +40,7 @@ STATIC void
+ xfs_efi_item_free(
+       struct xfs_efi_log_item *efip)
+ {
+-      kmem_free(efip->efi_item.li_lv_shadow);
++      kvfree(efip->efi_item.li_lv_shadow);
+       if (efip->efi_format.efi_nextents > XFS_EFI_MAX_FAST_EXTENTS)
+               kmem_free(efip);
+       else
+@@ -229,7 +229,7 @@ static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip)
+ STATIC void
+ xfs_efd_item_free(struct xfs_efd_log_item *efdp)
+ {
+-      kmem_free(efdp->efd_item.li_lv_shadow);
++      kvfree(efdp->efd_item.li_lv_shadow);
+       if (efdp->efd_format.efd_nextents > XFS_EFD_MAX_FAST_EXTENTS)
+               kmem_free(efdp);
+       else
+diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c
+index b05314d48176f..4345db501714e 100644
+--- a/fs/xfs/xfs_icreate_item.c
++++ b/fs/xfs/xfs_icreate_item.c
+@@ -63,7 +63,7 @@ STATIC void
+ xfs_icreate_item_release(
+       struct xfs_log_item     *lip)
+ {
+-      kmem_free(ICR_ITEM(lip)->ic_item.li_lv_shadow);
++      kvfree(ICR_ITEM(lip)->ic_item.li_lv_shadow);
+       kmem_cache_free(xfs_icreate_cache, ICR_ITEM(lip));
+ }
+diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
+index 155a8b3128755..7c3f4a3da518b 100644
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -857,7 +857,7 @@ xfs_inode_item_destroy(
+       ASSERT(iip->ili_item.li_buf == NULL);
+       ip->i_itemp = NULL;
+-      kmem_free(iip->ili_item.li_lv_shadow);
++      kvfree(iip->ili_item.li_lv_shadow);
+       kmem_cache_free(xfs_ili_cache, iip);
+ }
+diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
+index 535f6d38cdb54..8d844c7d1c798 100644
+--- a/fs/xfs/xfs_ioctl.c
++++ b/fs/xfs/xfs_ioctl.c
+@@ -492,7 +492,7 @@ xfs_attrmulti_attr_get(
+               error = -EFAULT;
+ out_kfree:
+-      kmem_free(args.value);
++      kvfree(args.value);
+       return error;
+ }
+diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
+index a1650fc81382f..04327aaa5bf09 100644
+--- a/fs/xfs/xfs_log.c
++++ b/fs/xfs/xfs_log.c
+@@ -1661,7 +1661,7 @@ xlog_alloc_log(
+ out_free_iclog:
+       for (iclog = log->l_iclog; iclog; iclog = prev_iclog) {
+               prev_iclog = iclog->ic_next;
+-              kmem_free(iclog->ic_data);
++              kvfree(iclog->ic_data);
+               kmem_free(iclog);
+               if (prev_iclog == log->l_iclog)
+                       break;
+@@ -2118,7 +2118,7 @@ xlog_dealloc_log(
+       iclog = log->l_iclog;
+       for (i = 0; i < log->l_iclog_bufs; i++) {
+               next_iclog = iclog->ic_next;
+-              kmem_free(iclog->ic_data);
++              kvfree(iclog->ic_data);
+               kmem_free(iclog);
+               iclog = next_iclog;
+       }
+diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
+index 67a99d94701e5..d2ed2c38e2989 100644
+--- a/fs/xfs/xfs_log_cil.c
++++ b/fs/xfs/xfs_log_cil.c
+@@ -339,7 +339,7 @@ xlog_cil_alloc_shadow_bufs(
+                        * the buffer, only the log vector header and the iovec
+                        * storage.
+                        */
+-                      kmem_free(lip->li_lv_shadow);
++                      kvfree(lip->li_lv_shadow);
+                       lv = xlog_kvmalloc(buf_size);
+                       memset(lv, 0, xlog_cil_iovec_space(niovecs));
+diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
+index cc14cd1c2282f..f3fcd58349c16 100644
+--- a/fs/xfs/xfs_log_recover.c
++++ b/fs/xfs/xfs_log_recover.c
+@@ -361,7 +361,7 @@ xlog_find_verify_cycle(
+       *new_blk = -1;
+ out:
+-      kmem_free(buffer);
++      kvfree(buffer);
+       return error;
+ }
+@@ -477,7 +477,7 @@ xlog_find_verify_log_record(
+               *last_blk = i;
+ out:
+-      kmem_free(buffer);
++      kvfree(buffer);
+       return error;
+ }
+@@ -731,7 +731,7 @@ xlog_find_head(
+                       goto out_free_buffer;
+       }
+-      kmem_free(buffer);
++      kvfree(buffer);
+       if (head_blk == log_bbnum)
+               *return_head_blk = 0;
+       else
+@@ -745,7 +745,7 @@ xlog_find_head(
+       return 0;
+ out_free_buffer:
+-      kmem_free(buffer);
++      kvfree(buffer);
+       if (error)
+               xfs_warn(log->l_mp, "failed to find log head");
+       return error;
+@@ -999,7 +999,7 @@ xlog_verify_tail(
+               "Tail block (0x%llx) overwrite detected. Updated to 0x%llx",
+                        orig_tail, *tail_blk);
+ out:
+-      kmem_free(buffer);
++      kvfree(buffer);
+       return error;
+ }
+@@ -1046,7 +1046,7 @@ xlog_verify_head(
+       error = xlog_rseek_logrec_hdr(log, *head_blk, *tail_blk,
+                                     XLOG_MAX_ICLOGS, tmp_buffer,
+                                     &tmp_rhead_blk, &tmp_rhead, &tmp_wrapped);
+-      kmem_free(tmp_buffer);
++      kvfree(tmp_buffer);
+       if (error < 0)
+               return error;
+@@ -1365,7 +1365,7 @@ xlog_find_tail(
+               error = xlog_clear_stale_blocks(log, tail_lsn);
+ done:
+-      kmem_free(buffer);
++      kvfree(buffer);
+       if (error)
+               xfs_warn(log->l_mp, "failed to locate log tail");
+@@ -1399,6 +1399,7 @@ xlog_find_zeroed(
+       xfs_daddr_t     new_blk, last_blk, start_blk;
+       xfs_daddr_t     num_scan_bblks;
+       int             error, log_bbnum = log->l_logBBsize;
++      int             ret = 1;
+       *blk_no = 0;
+@@ -1413,8 +1414,7 @@ xlog_find_zeroed(
+       first_cycle = xlog_get_cycle(offset);
+       if (first_cycle == 0) {         /* completely zeroed log */
+               *blk_no = 0;
+-              kmem_free(buffer);
+-              return 1;
++              goto out_free_buffer;
+       }
+       /* check partially zeroed log */
+@@ -1424,8 +1424,8 @@ xlog_find_zeroed(
+       last_cycle = xlog_get_cycle(offset);
+       if (last_cycle != 0) {          /* log completely written to */
+-              kmem_free(buffer);
+-              return 0;
++              ret = 0;
++              goto out_free_buffer;
+       }
+       /* we have a partially zeroed log */
+@@ -1471,10 +1471,10 @@ xlog_find_zeroed(
+       *blk_no = last_blk;
+ out_free_buffer:
+-      kmem_free(buffer);
++      kvfree(buffer);
+       if (error)
+               return error;
+-      return 1;
++      return ret;
+ }
+ /*
+@@ -1583,7 +1583,7 @@ xlog_write_log_records(
+       }
+ out_free_buffer:
+-      kmem_free(buffer);
++      kvfree(buffer);
+       return error;
+ }
+@@ -2182,7 +2182,7 @@ xlog_recover_add_to_trans(
+               "bad number of regions (%d) in inode log format",
+                                 in_f->ilf_size);
+                       ASSERT(0);
+-                      kmem_free(ptr);
++                      kvfree(ptr);
+                       return -EFSCORRUPTED;
+               }
+@@ -2197,7 +2197,7 @@ xlog_recover_add_to_trans(
+       "log item region count (%d) overflowed size (%d)",
+                               item->ri_cnt, item->ri_total);
+               ASSERT(0);
+-              kmem_free(ptr);
++              kvfree(ptr);
+               return -EFSCORRUPTED;
+       }
+@@ -2227,7 +2227,7 @@ xlog_recover_free_trans(
+               /* Free the regions in the item. */
+               list_del(&item->ri_list);
+               for (i = 0; i < item->ri_cnt; i++)
+-                      kmem_free(item->ri_buf[i].i_addr);
++                      kvfree(item->ri_buf[i].i_addr);
+               /* Free the item itself */
+               kmem_free(item->ri_buf);
+               kmem_free(item);
+@@ -3023,7 +3023,7 @@ xlog_do_recovery_pass(
+               hblks = xlog_logrec_hblks(log, rhead);
+               if (hblks != 1) {
+-                      kmem_free(hbp);
++                      kvfree(hbp);
+                       hbp = xlog_alloc_buffer(log, hblks);
+               }
+       } else {
+@@ -3037,7 +3037,7 @@ xlog_do_recovery_pass(
+               return -ENOMEM;
+       dbp = xlog_alloc_buffer(log, BTOBB(h_size));
+       if (!dbp) {
+-              kmem_free(hbp);
++              kvfree(hbp);
+               return -ENOMEM;
+       }
+@@ -3198,9 +3198,9 @@ xlog_do_recovery_pass(
+       }
+  bread_err2:
+-      kmem_free(dbp);
++      kvfree(dbp);
+  bread_err1:
+-      kmem_free(hbp);
++      kvfree(hbp);
+       /*
+        * Submit buffers that have been added from the last record processed,
+diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
+index f1b2592238022..ea4daf3dc8f07 100644
+--- a/fs/xfs/xfs_refcount_item.c
++++ b/fs/xfs/xfs_refcount_item.c
+@@ -36,7 +36,7 @@ STATIC void
+ xfs_cui_item_free(
+       struct xfs_cui_log_item *cuip)
+ {
+-      kmem_free(cuip->cui_item.li_lv_shadow);
++      kvfree(cuip->cui_item.li_lv_shadow);
+       if (cuip->cui_format.cui_nextents > XFS_CUI_MAX_FAST_EXTENTS)
+               kmem_free(cuip);
+       else
+@@ -207,7 +207,7 @@ xfs_cud_item_release(
+       struct xfs_cud_log_item *cudp = CUD_ITEM(lip);
+       xfs_cui_release(cudp->cud_cuip);
+-      kmem_free(cudp->cud_item.li_lv_shadow);
++      kvfree(cudp->cud_item.li_lv_shadow);
+       kmem_cache_free(xfs_cud_cache, cudp);
+ }
+diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
+index 5e8a02d2b045d..dd0a562ec79cc 100644
+--- a/fs/xfs/xfs_rmap_item.c
++++ b/fs/xfs/xfs_rmap_item.c
+@@ -36,7 +36,7 @@ STATIC void
+ xfs_rui_item_free(
+       struct xfs_rui_log_item *ruip)
+ {
+-      kmem_free(ruip->rui_item.li_lv_shadow);
++      kvfree(ruip->rui_item.li_lv_shadow);
+       if (ruip->rui_format.rui_nextents > XFS_RUI_MAX_FAST_EXTENTS)
+               kmem_free(ruip);
+       else
+@@ -205,7 +205,7 @@ xfs_rud_item_release(
+       struct xfs_rud_log_item *rudp = RUD_ITEM(lip);
+       xfs_rui_release(rudp->rud_ruip);
+-      kmem_free(rudp->rud_item.li_lv_shadow);
++      kvfree(rudp->rud_item.li_lv_shadow);
+       kmem_cache_free(xfs_rud_cache, rudp);
+ }
+diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
+index 4bec890d93d2c..0ccadedfdb016 100644
+--- a/fs/xfs/xfs_rtalloc.c
++++ b/fs/xfs/xfs_rtalloc.c
+@@ -1185,10 +1185,10 @@ xfs_growfs_rt(
+        */
+       if (rsum_cache != mp->m_rsum_cache) {
+               if (error) {
+-                      kmem_free(mp->m_rsum_cache);
++                      kvfree(mp->m_rsum_cache);
+                       mp->m_rsum_cache = rsum_cache;
+               } else {
+-                      kmem_free(rsum_cache);
++                      kvfree(rsum_cache);
+               }
+       }
+@@ -1433,7 +1433,7 @@ void
+ xfs_rtunmount_inodes(
+       struct xfs_mount        *mp)
+ {
+-      kmem_free(mp->m_rsum_cache);
++      kvfree(mp->m_rsum_cache);
+       if (mp->m_rbmip)
+               xfs_irele(mp->m_rbmip);
+       if (mp->m_rsumip)
+-- 
+2.43.0
+
diff --git a/queue-6.6/xfs-fix-log-recovery-buffer-allocation-for-the-legac.patch b/queue-6.6/xfs-fix-log-recovery-buffer-allocation-for-the-legac.patch
new file mode 100644 (file)
index 0000000..7c9ec14
--- /dev/null
@@ -0,0 +1,76 @@
+From 6f069e2fd9f155e5face3c5aef5cf7bd1acf99ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Apr 2024 06:07:55 +0200
+Subject: xfs: fix log recovery buffer allocation for the legacy h_size fixup
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 45cf976008ddef4a9c9a30310c9b4fb2a9a6602a ]
+
+Commit a70f9fe52daa ("xfs: detect and handle invalid iclog size set by
+mkfs") added a fixup for incorrect h_size values used for the initial
+umount record in old xfsprogs versions.  Later commit 0c771b99d6c9
+("xfs: clean up calculation of LR header blocks") cleaned up the log
+reover buffer calculation, but stoped using the fixed up h_size value
+to size the log recovery buffer, which can lead to an out of bounds
+access when the incorrect h_size does not come from the old mkfs
+tool, but a fuzzer.
+
+Fix this by open coding xlog_logrec_hblks and taking the fixed h_size
+into account for this calculation.
+
+Fixes: 0c771b99d6c9 ("xfs: clean up calculation of LR header blocks")
+Reported-by: Sam Sun <samsun1006219@gmail.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_log_recover.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
+index f3fcd58349c16..d6cb097f63729 100644
+--- a/fs/xfs/xfs_log_recover.c
++++ b/fs/xfs/xfs_log_recover.c
+@@ -2965,7 +2965,7 @@ xlog_do_recovery_pass(
+       int                     error = 0, h_size, h_len;
+       int                     error2 = 0;
+       int                     bblks, split_bblks;
+-      int                     hblks, split_hblks, wrapped_hblks;
++      int                     hblks = 1, split_hblks, wrapped_hblks;
+       int                     i;
+       struct hlist_head       rhash[XLOG_RHASH_SIZE];
+       LIST_HEAD               (buffer_list);
+@@ -3021,14 +3021,22 @@ xlog_do_recovery_pass(
+               if (error)
+                       goto bread_err1;
+-              hblks = xlog_logrec_hblks(log, rhead);
+-              if (hblks != 1) {
+-                      kvfree(hbp);
+-                      hbp = xlog_alloc_buffer(log, hblks);
++              /*
++               * This open codes xlog_logrec_hblks so that we can reuse the
++               * fixed up h_size value calculated above.  Without that we'd
++               * still allocate the buffer based on the incorrect on-disk
++               * size.
++               */
++              if (h_size > XLOG_HEADER_CYCLE_SIZE &&
++                  (rhead->h_version & cpu_to_be32(XLOG_VERSION_2))) {
++                      hblks = DIV_ROUND_UP(h_size, XLOG_HEADER_CYCLE_SIZE);
++                      if (hblks > 1) {
++                              kvfree(hbp);
++                              hbp = xlog_alloc_buffer(log, hblks);
++                      }
+               }
+       } else {
+               ASSERT(log->l_sectBBsize == 1);
+-              hblks = 1;
+               hbp = xlog_alloc_buffer(log, 1);
+               h_size = XLOG_BIG_RECORD_BSIZE;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/xfs-match-lock-mode-in-xfs_buffered_write_iomap_begi.patch b/queue-6.6/xfs-match-lock-mode-in-xfs_buffered_write_iomap_begi.patch
new file mode 100644 (file)
index 0000000..15e455e
--- /dev/null
@@ -0,0 +1,70 @@
+From 2920cac12f7a637704199feef95f802f9692b7e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 21:13:27 +0800
+Subject: xfs: match lock mode in xfs_buffered_write_iomap_begin()
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit bb712842a85d595525e72f0e378c143e620b3ea2 ]
+
+Commit 1aa91d9c9933 ("xfs: Add async buffered write support") replace
+xfs_ilock(XFS_ILOCK_EXCL) with xfs_ilock_for_iomap() when locking the
+writing inode, and a new variable lockmode is used to indicate the lock
+mode. Although the lockmode should always be XFS_ILOCK_EXCL, it's still
+better to use this variable instead of useing XFS_ILOCK_EXCL directly
+when unlocking the inode.
+
+Fixes: 1aa91d9c9933 ("xfs: Add async buffered write support")
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_iomap.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
+index 18c8f168b1532..ccf83e72d8ca8 100644
+--- a/fs/xfs/xfs_iomap.c
++++ b/fs/xfs/xfs_iomap.c
+@@ -1149,13 +1149,13 @@ xfs_buffered_write_iomap_begin(
+        * them out if the write happens to fail.
+        */
+       seq = xfs_iomap_inode_sequence(ip, IOMAP_F_NEW);
+-      xfs_iunlock(ip, XFS_ILOCK_EXCL);
++      xfs_iunlock(ip, lockmode);
+       trace_xfs_iomap_alloc(ip, offset, count, allocfork, &imap);
+       return xfs_bmbt_to_iomap(ip, iomap, &imap, flags, IOMAP_F_NEW, seq);
+ found_imap:
+       seq = xfs_iomap_inode_sequence(ip, 0);
+-      xfs_iunlock(ip, XFS_ILOCK_EXCL);
++      xfs_iunlock(ip, lockmode);
+       return xfs_bmbt_to_iomap(ip, iomap, &imap, flags, 0, seq);
+ found_cow:
+@@ -1165,17 +1165,17 @@ xfs_buffered_write_iomap_begin(
+               if (error)
+                       goto out_unlock;
+               seq = xfs_iomap_inode_sequence(ip, IOMAP_F_SHARED);
+-              xfs_iunlock(ip, XFS_ILOCK_EXCL);
++              xfs_iunlock(ip, lockmode);
+               return xfs_bmbt_to_iomap(ip, iomap, &cmap, flags,
+                                        IOMAP_F_SHARED, seq);
+       }
+       xfs_trim_extent(&cmap, offset_fsb, imap.br_startoff - offset_fsb);
+-      xfs_iunlock(ip, XFS_ILOCK_EXCL);
++      xfs_iunlock(ip, lockmode);
+       return xfs_bmbt_to_iomap(ip, iomap, &cmap, flags, 0, seq);
+ out_unlock:
+-      xfs_iunlock(ip, XFS_ILOCK_EXCL);
++      xfs_iunlock(ip, lockmode);
+       return error;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/xfs-require-xfs_sb_feat_incompat_log_xattrs-for-attr.patch b/queue-6.6/xfs-require-xfs_sb_feat_incompat_log_xattrs-for-attr.patch
new file mode 100644 (file)
index 0000000..08a5566
--- /dev/null
@@ -0,0 +1,48 @@
+From e90f2ae615227c6ca739c3ba286b060744dc04fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Apr 2024 09:47:24 -0700
+Subject: xfs: require XFS_SB_FEAT_INCOMPAT_LOG_XATTRS for attr log intent item
+ recovery
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+[ Upstream commit 8ef1d96a985e4dc07ffbd71bd7fc5604a80cc644 ]
+
+The XFS_SB_FEAT_INCOMPAT_LOG_XATTRS feature bit protects a filesystem
+from old kernels that do not know how to recover extended attribute log
+intent items.  Make this check mandatory instead of a debugging assert.
+
+Fixes: fd920008784ea ("xfs: Set up infrastructure for log attribute replay")
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_attr_item.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c
+index 82775e9537df8..ebf656aaf3012 100644
+--- a/fs/xfs/xfs_attr_item.c
++++ b/fs/xfs/xfs_attr_item.c
+@@ -510,6 +510,9 @@ xfs_attri_validate(
+       unsigned int                    op = attrp->alfi_op_flags &
+                                            XFS_ATTRI_OP_FLAGS_TYPE_MASK;
++      if (!xfs_sb_version_haslogxattrs(&mp->m_sb))
++              return false;
++
+       if (attrp->__pad != 0)
+               return false;
+@@ -602,8 +605,6 @@ xfs_attri_item_recover(
+       args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT |
+                        XFS_DA_OP_LOGGED;
+-      ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb));
+-
+       switch (attr->xattri_op_flags) {
+       case XFS_ATTRI_OP_FLAGS_SET:
+       case XFS_ATTRI_OP_FLAGS_REPLACE:
+-- 
+2.43.0
+
diff --git a/queue-6.6/xfs-upgrade-the-extent-counters-in-xfs_reflink_end_c.patch b/queue-6.6/xfs-upgrade-the-extent-counters-in-xfs_reflink_end_c.patch
new file mode 100644 (file)
index 0000000..ab2e766
--- /dev/null
@@ -0,0 +1,60 @@
+From 59d442e43f2bda5291d8d7df5c82fe8940aa8c60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 May 2024 09:33:53 +0200
+Subject: xfs: upgrade the extent counters in xfs_reflink_end_cow_extent later
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 99fb6b7ad1f2fb83d8df2c1382be63a1f50b1ae0 ]
+
+Defer the extent counter size upgrade until we know we're going to
+modify the extent mapping.  This also defers dirtying the transaction
+and will allow us safely back out later in the function in later
+changes.
+
+Fixes: 4f86bb4b66c9 ("xfs: Conditionally upgrade existing inodes to use large extent counters")
+Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_reflink.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
+index e5b62dc284664..2322d45ac5e78 100644
+--- a/fs/xfs/xfs_reflink.c
++++ b/fs/xfs/xfs_reflink.c
+@@ -750,14 +750,6 @@ xfs_reflink_end_cow_extent(
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, ip, 0);
+-      error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
+-                      XFS_IEXT_REFLINK_END_COW_CNT);
+-      if (error == -EFBIG)
+-              error = xfs_iext_count_upgrade(tp, ip,
+-                              XFS_IEXT_REFLINK_END_COW_CNT);
+-      if (error)
+-              goto out_cancel;
+-
+       /*
+        * In case of racing, overlapping AIO writes no COW extents might be
+        * left by the time I/O completes for the loser of the race.  In that
+@@ -786,6 +778,14 @@ xfs_reflink_end_cow_extent(
+       del = got;
+       xfs_trim_extent(&del, *offset_fsb, end_fsb - *offset_fsb);
++      error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
++                      XFS_IEXT_REFLINK_END_COW_CNT);
++      if (error == -EFBIG)
++              error = xfs_iext_count_upgrade(tp, ip,
++                              XFS_IEXT_REFLINK_END_COW_CNT);
++      if (error)
++              goto out_cancel;
++
+       /* Grab the corresponding mapping in the data fork. */
+       nmaps = 1;
+       error = xfs_bmapi_read(ip, del.br_startoff, del.br_blockcount, &data,
+-- 
+2.43.0
+