From 289c1f40a52805af9badd530c2f3f92e0fe5f3ce Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 30 May 2024 14:48:11 -0400 Subject: [PATCH] Fixes for 6.6 Signed-off-by: Sasha Levin --- ...r-set-lower-bound-of-start-tick-time.patch | 52 + ...s-meson-fix-s4-power-controller-node.patch | 49 + ...id-erroneous-elide-of-user-state-rel.patch | 127 +++ ...arm64-fpsimd-drop-unneeded-busy-flag.patch | 218 ++++ ...lement-lazy-restore-for-kernel-mode-.patch | 86 ++ ...serve-restore-kernel-mode-neon-at-co.patch | 251 +++++ ...do-not-hardcode-iomem-access-for-reg.patch | 44 + ...do-not-save-restore-data-trace-contr.patch | 119 +++ ...fix-access-to-resource-selector-regi.patch | 51 + ...m4x-fix-unbalanced-pm_runtime_enable.patch | 66 ++ ...sight-etm4x-safe-access-for-trcqcltr.patch | 90 ++ ...unter.h-fix-excess-kernel-doc-descri.patch | 37 + ...4-add-check-for-dma_set_max_seg_size.patch | 40 + ...void-unnecessary-destruction-of-file.patch | 46 + ...ay-remove-pixle-rate-limit-for-subvp.patch | 39 + ...revert-remove-pixle-rate-limit-for-s.patch | 48 + ...ings-adc-axi-adc-add-clocks-property.patch | 60 ++ ...axi-adc-update-bindings-for-backend-.patch | 65 ++ ...rcar-pci-host-add-missing-iommu-prop.patch | 47 + ...rcar-pci-host-add-optional-regulator.patch | 57 + ...rockchip-rk3399-pcie-add-missing-max.patch | 42 + ...qcom-sc8280xp-qmp-ufs-phy-fix-msm899.patch | 61 ++ ...qcom-usb-snps-femto-v2-use-correct-f.patch | 48 + ...trl-mediatek-mt7622-fix-array-proper.patch | 168 +++ ...-hisilicon-hisi-spmi-controller-fix-.patch | 51 + ...e-eventfs_root_inode-to-store-dentry.patch | 195 ++++ ...ifferentiate-the-toplevel-events-dir.patch | 150 +++ ...e-all-of-the-eventfs_inode-after-rcu.patch | 84 ++ ...nts-directory-get-permissions-from-i.patch | 133 +++ ...add-callback-for-release-of-an-event.patch | 199 ++++ ...elect-irq_domain-instead-of-dependin.patch | 47 + .../f2fs-clean-up-errors-in-segment.h.patch | 43 + ...n-t-allow-unaligned-truncation-on-re.patch | 65 ++ ...x-error-path-of-inc_valid_block_coun.patch | 71 ++ ...x-to-cover-reserve-release-_compress.patch | 75 ++ ...x-to-relocate-check-condition-in-f2f.patch | 70 ++ ...-relocate-check-condition-in-f2f.patch-466 | 70 ++ ...x-to-update-i_compr_blocks-correctly.patch | 82 ++ queue-6.6/f2fs-deprecate-io_bits.patch | 556 ++++++++++ ...igration-when-section-is-not-aligned.patch | 62 ++ ...-add-missing-iput-in-gc_data_segment.patch | 46 + ...k-pinfile-flag-in-f2fs_move_file_ran.patch | 37 + ...ase-node-block-count-in-error-path-o.patch | 44 + ...cate-check-condition-in-f2fs_falloca.patch | 62 ++ ...-on-page-writeback-in-__clone_blkadd.patch | 53 + ...et_available_block_count-for-cleanup.patch | 110 ++ .../f2fs-kill-heap-based-allocation.patch | 229 ++++ ...x-to-recognize-valid-zero-block-addr.patch | 119 +++ ...-f2fs_gc_range-to-use-gc-for-a-range.patch | 92 ++ ...pport-file-pinning-for-zoned-devices.patch | 472 +++++++++ ...rt-printk_ratelimited-in-f2fs_printk.patch | 165 +++ ...er_seg-blks_per_sec-and-segs_per_sec.patch | 982 ++++++++++++++++++ ...i-id-add-a-release-callback-function.patch | 50 + ...d-owner-module-and-take-its-refcount.patch | 251 +++++ ...d-owner-module-and-take-its-refcount.patch | 408 ++++++++ ...d-owner-module-and-take-its-refcount.patch | 210 ++++ ...start_write-into-vfs_iocb_iter_write.patch | 124 +++ ...-failed-in-acpi_gpiochip_find-by-add.patch | 84 ++ ...rl-move-device-table-to-its-right-lo.patch | 66 ++ ...heck-return-of-get_channel_from_mode.patch | 59 ++ ...cadence-avoid-fifo-clear-after-start.patch | 39 + ...x-an-error-handling-path-in-synquace.patch | 69 ++ ...5-make-inject_virtual_interrupt-void.patch | 67 ++ ...5-allow-module-autoloading-via-of-co.patch | 51 + ...c4005-reset-chip-on-probe-and-resume.patch | 157 +++ ...-ad9467-convert-to-backend-framework.patch | 515 +++++++++ ...se-chip_info-variables-instead-of-ar.patch | 147 +++ ...ad9467-use-spi_get_device_match_data.patch | 39 + ...io-adc-adi-axi-adc-convert-to-regmap.patch | 198 ++++ ...di-axi-adc-move-to-backend-framework.patch | 620 +++++++++++ ...adc-only-error-out-in-major-version-.patch | 44 + ...xing-err-code-to-not-indicate-succes.patch | 36 + .../iio-add-the-iio-backend-framework.patch | 593 +++++++++++ ...gine-export-buffer-alloc-and-free-fu.patch | 104 ++ ...rivate-pointer-null-when-no-private-.patch | 43 + ...310-support-negative-temperature-val.patch | 67 ++ ...m-qcm2290-fix-mas_snoc_bimc-qos-port.patch | 37 + ...-id-symlinks-to-installed-debug-vdso.patch | 36 + .../kbuild-unify-vdso_install-rules.patch | 585 +++++++++++ ...wm-disable-pwm-when-going-to-suspend.patch | 48 + ...subcmd-fix-parse-options-memory-leak.patch | 61 ++ ...llchain-parse-error-with-kernel-trac.patch | 71 ++ ...e-early-printk-call-from-cpuinfo-sta.patch | 37 + ...e-gcc-flag-for-non-existing-early_pr.patch | 36 + ...misc-pvpanic-deduplicate-common-code.patch | 328 ++++++ ...i-register-attributes-via-pci_driver.patch | 48 + ...-t-ignore-sysfs_create_link-failures.patch | 155 +++ .../ovl-add-helper-ovl_file_modified.patch | 87 ++ ...-umask-handling-from-ovl_create_uppe.patch | 39 + ...r_port_dpc_enable_dsm-with-pci-firmw.patch | 71 ++ ...r_port_locate_dsm-with-pci-firmware-.patch | 65 ++ ...return-error-for-int_map-allocation-.patch | 38 + ...194-fix-probe-path-for-endpoint-mode.patch | 48 + ...k-training-0-before-starting-link-re.patch | 82 ++ ...x-annotation_calc_lines-to-pass-corr.patch | 81 ++ ...t-rid-of-duplicate-group-option-item.patch | 48 + ...-introduce-global-annotation_options.patch | 210 ++++ ...lit-branch-stack-cycles-information-.patch | 234 +++++ ...notate-use-global-annotation_options.patch | 642 ++++++++++++ ...nals-inject-build-id-fix-trap-divide.patch | 55 + ...e-remove-lib64-from-libc.so.6-binary.patch | 48 + ...file-leak-in-daemon_session__control.patch | 59 ++ ...erf-docs-document-bpf-event-modifier.patch | 48 + ...evlist__findnew_tracking_event-helpe.patch | 108 ++ ...x-unassigned-instruction-op-discover.patch | 73 ++ ...ead-remove-exited-threads-by-default.patch | 181 ++++ ...move-symbol-maps-functions-to-maps.c.patch | 634 +++++++++++ ...sysfs-events-are-always-the-same-cas.patch | 126 +++ ...supports-regular-expression-matching.patch | 110 ++ ...sys-and-cpuid-json-events-separately.patch | 202 ++++ ...mu-move-pmu__find_core_pmu-to-pmus.c.patch | 198 ++++ ...issing-libgen.h-header-needed-for-us.patch | 53 + ...te-session-after-stopping-sideband-t.patch | 83 ++ ...debug-message-placement-for-test-con.patch | 57 + ...perf-record-lazy-load-kernel-symbols.patch | 129 +++ ...-setting-tracking-events-before-reco.patch | 272 +++++ ...id-segv-in-report__setup_sample_type.patch | 47 + ...ert-to-the-global-annotation_options.patch | 150 +++ ...-fail-on-metrics-on-s390-z-vm-system.patch | 176 ++++ ...display-metric-header-for-non-leader.patch | 90 ++ ...-ownership-of-string-in-dso__load_vm.patch | 91 ++ ...test-for-strcmp_cpuid_str-expression.patch | 112 ++ ...arm_coresight-increase-buffer-size-f.patch | 58 ++ ...-attributes-to-all-events-in-object-.patch | 70 ++ ...test-data-symbol-more-robust-on-neov.patch | 69 ++ ...s-to-thread__new-related-to-initiali.patch | 80 ++ ...se-pmu-reverse-lookup-from-config-to.patch | 149 +++ ...pmus-to-describe-type-from-attribute.patch | 161 +++ ...ert-to-the-global-annotation_options.patch | 188 ++++ .../perf-ui-browser-avoid-segv-on-title.patch | 46 + ...r-don-t-save-pointer-to-stack-memory.patch | 143 +++ ...bo-fix-duplicate-return-in-qmp_v4_co.patch | 38 + ...ctrl-sm7150-fix-sdc1-and-ufs-special.patch | 81 ++ ...dd-an-error-check-in-register_device.patch | 72 ++ ...ge-of-the-deprecated-ida_simple_xx-a.patch | 57 + ...apply_state-to-pwm_apply_might_sleep.patch | 724 +++++++++++++ ...simd-implement-lazy-restore-for-kern.patch | 74 ++ ...ove-call_-read-write-_iter-functions.patch | 205 ++++ ...imd-implement-lazy-restore-for-kerne.patch | 75 ++ .../risc-v-enable-cbo.zero-in-usermode.patch | 169 +++ ...ve-visionfive-2-remove-non-existing-.patch | 91 ++ ...instruction-cache-during-smp-bringup.patch | 55 + ...-alt_stfle_fac_list-from-decompresso.patch | 49 + ...orrect-initialization-of-len-fields-.patch | 42 + ...orrect-initialization-of-nvme-dump-b.patch | 43 + ...-.build-id-links-for-unstripped-vdso.patch | 45 + ...ate-unwind-information-for-c-modules.patch | 55 + ...vdso-use-standard-stack-frame-layout.patch | 56 + ...er-out-munaligned-symbols-flag-for-v.patch | 56 + .../serial-max3100-fix-bitwise-types.patch | 53 + ...ock-port-lock-when-calling-uart_hand.patch | 66 ++ ...pdate-uart_driver_registered-on-driv.patch | 73 ++ ...-add-proper-sched.h-include-for-sche.patch | 44 + ...-fix-bug-in-sc16is7xx_set_baud-when-.patch | 96 ++ ...-replace-hardcoded-divisor-value-wit.patch | 39 + ...otect-invalidating-rxdma-on-shutdown.patch | 47 + queue-6.6/series | 176 ++++ ...dwire-cadence-fix-invalid-pdi-offset.patch | 48 + ...rmission-hook-from-iter_file_splice_.patch | 72 ++ ...a-double-free-in-stm_register_device.patch | 57 + ...f_expand_file_adinicb-to-use-a-folio.patch | 85 ++ ...ofs-allocation-in-udf_expand_file_ad.patch | 39 + ...0-add-missing-kernel-doc-description.patch | 40 + ...u_audio-clear-uac-pointer-when-freed.patch | 40 + ...io-fix-race-condition-use-of-control.patch | 110 ++ ...lways-register-a-link-to-usb-pd-devi.patch | 52 + ...implify-partner-s-pd-caps-registrati.patch | 63 ++ ...ential-memory-leak-in-vfio_intx_enab.patch | 41 + ...r-handling-path-in-vmci_guest_probe_.patch | 66 ++ ...-bd9576-drop-always-running-property.patch | 84 ++ ....c-fix-use-after-free-bug-caused-by-.patch | 46 + ...fix-ptr_err_or_zero-vs-null-check-in.patch | 43 + ...em_free-for-kvmalloc-users-to-kvfree.patch | 472 +++++++++ ...very-buffer-allocation-for-the-legac.patch | 76 ++ ...ode-in-xfs_buffered_write_iomap_begi.patch | 70 ++ ...sb_feat_incompat_log_xattrs-for-attr.patch | 48 + ...extent-counters-in-xfs_reflink_end_c.patch | 60 ++ 177 files changed, 21662 insertions(+) create mode 100644 queue-6.6/alsa-timer-set-lower-bound-of-start-tick-time.patch create mode 100644 queue-6.6/arm64-dts-meson-fix-s4-power-controller-node.patch create mode 100644 queue-6.6/arm64-fpsimd-avoid-erroneous-elide-of-user-state-rel.patch create mode 100644 queue-6.6/arm64-fpsimd-drop-unneeded-busy-flag.patch create mode 100644 queue-6.6/arm64-fpsimd-implement-lazy-restore-for-kernel-mode-.patch create mode 100644 queue-6.6/arm64-fpsimd-preserve-restore-kernel-mode-neon-at-co.patch create mode 100644 queue-6.6/coresight-etm4x-do-not-hardcode-iomem-access-for-reg.patch create mode 100644 queue-6.6/coresight-etm4x-do-not-save-restore-data-trace-contr.patch create mode 100644 queue-6.6/coresight-etm4x-fix-access-to-resource-selector-regi.patch create mode 100644 queue-6.6/coresight-etm4x-fix-unbalanced-pm_runtime_enable.patch create mode 100644 queue-6.6/coresight-etm4x-safe-access-for-trcqcltr.patch create mode 100644 queue-6.6/counter-linux-counter.h-fix-excess-kernel-doc-descri.patch create mode 100644 queue-6.6/dmaengine-idma64-add-check-for-dma_set_max_seg_size.patch create mode 100644 queue-6.6/dmaengine-idxd-avoid-unnecessary-destruction-of-file.patch create mode 100644 queue-6.6/drm-amd-display-remove-pixle-rate-limit-for-subvp.patch create mode 100644 queue-6.6/drm-amd-display-revert-remove-pixle-rate-limit-for-s.patch create mode 100644 queue-6.6/dt-bindings-adc-axi-adc-add-clocks-property.patch create mode 100644 queue-6.6/dt-bindings-adc-axi-adc-update-bindings-for-backend-.patch create mode 100644 queue-6.6/dt-bindings-pci-rcar-pci-host-add-missing-iommu-prop.patch create mode 100644 queue-6.6/dt-bindings-pci-rcar-pci-host-add-optional-regulator.patch create mode 100644 queue-6.6/dt-bindings-pci-rockchip-rk3399-pcie-add-missing-max.patch create mode 100644 queue-6.6/dt-bindings-phy-qcom-sc8280xp-qmp-ufs-phy-fix-msm899.patch create mode 100644 queue-6.6/dt-bindings-phy-qcom-usb-snps-femto-v2-use-correct-f.patch create mode 100644 queue-6.6/dt-bindings-pinctrl-mediatek-mt7622-fix-array-proper.patch create mode 100644 queue-6.6/dt-bindings-spmi-hisilicon-hisi-spmi-controller-fix-.patch create mode 100644 queue-6.6/eventfs-create-eventfs_root_inode-to-store-dentry.patch create mode 100644 queue-6.6/eventfs-do-not-differentiate-the-toplevel-events-dir.patch create mode 100644 queue-6.6/eventfs-free-all-of-the-eventfs_inode-after-rcu.patch create mode 100644 queue-6.6/eventfs-have-events-directory-get-permissions-from-i.patch create mode 100644 queue-6.6/eventfs-tracing-add-callback-for-release-of-an-event.patch create mode 100644 queue-6.6/extcon-max8997-select-irq_domain-instead-of-dependin.patch create mode 100644 queue-6.6/f2fs-clean-up-errors-in-segment.h.patch create mode 100644 queue-6.6/f2fs-compress-don-t-allow-unaligned-truncation-on-re.patch create mode 100644 queue-6.6/f2fs-compress-fix-error-path-of-inc_valid_block_coun.patch create mode 100644 queue-6.6/f2fs-compress-fix-to-cover-reserve-release-_compress.patch create mode 100644 queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch create mode 100644 queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch-466 create mode 100644 queue-6.6/f2fs-compress-fix-to-update-i_compr_blocks-correctly.patch create mode 100644 queue-6.6/f2fs-deprecate-io_bits.patch create mode 100644 queue-6.6/f2fs-fix-block-migration-when-section-is-not-aligned.patch create mode 100644 queue-6.6/f2fs-fix-to-add-missing-iput-in-gc_data_segment.patch create mode 100644 queue-6.6/f2fs-fix-to-check-pinfile-flag-in-f2fs_move_file_ran.patch create mode 100644 queue-6.6/f2fs-fix-to-release-node-block-count-in-error-path-o.patch create mode 100644 queue-6.6/f2fs-fix-to-relocate-check-condition-in-f2fs_falloca.patch create mode 100644 queue-6.6/f2fs-fix-to-wait-on-page-writeback-in-__clone_blkadd.patch create mode 100644 queue-6.6/f2fs-introduce-get_available_block_count-for-cleanup.patch create mode 100644 queue-6.6/f2fs-kill-heap-based-allocation.patch create mode 100644 queue-6.6/f2fs-multidev-fix-to-recognize-valid-zero-block-addr.patch create mode 100644 queue-6.6/f2fs-separate-f2fs_gc_range-to-use-gc-for-a-range.patch create mode 100644 queue-6.6/f2fs-support-file-pinning-for-zoned-devices.patch create mode 100644 queue-6.6/f2fs-support-printk_ratelimited-in-f2fs_printk.patch create mode 100644 queue-6.6/f2fs-use-blks_per_seg-blks_per_sec-and-segs_per_sec.patch create mode 100644 queue-6.6/firmware-dmi-id-add-a-release-callback-function.patch create mode 100644 queue-6.6/fpga-bridge-add-owner-module-and-take-its-refcount.patch create mode 100644 queue-6.6/fpga-manager-add-owner-module-and-take-its-refcount.patch create mode 100644 queue-6.6/fpga-region-add-owner-module-and-take-its-refcount.patch create mode 100644 queue-6.6/fs-move-kiocb_start_write-into-vfs_iocb_iter_write.patch create mode 100644 queue-6.6/gpiolib-acpi-fix-failed-in-acpi_gpiochip_find-by-add.patch create mode 100644 queue-6.6/greybus-arche-ctrl-move-device-table-to-its-right-lo.patch create mode 100644 queue-6.6/greybus-lights-check-return-of-get_channel_from_mode.patch create mode 100644 queue-6.6/i2c-cadence-avoid-fifo-clear-after-start.patch create mode 100644 queue-6.6/i2c-synquacer-fix-an-error-handling-path-in-synquace.patch create mode 100644 queue-6.6/i915-make-inject_virtual_interrupt-void.patch create mode 100644 queue-6.6/iio-accel-mxc4005-allow-module-autoloading-via-of-co.patch create mode 100644 queue-6.6/iio-accel-mxc4005-reset-chip-on-probe-and-resume.patch create mode 100644 queue-6.6/iio-adc-ad9467-convert-to-backend-framework.patch create mode 100644 queue-6.6/iio-adc-ad9467-use-chip_info-variables-instead-of-ar.patch create mode 100644 queue-6.6/iio-adc-ad9467-use-spi_get_device_match_data.patch create mode 100644 queue-6.6/iio-adc-adi-axi-adc-convert-to-regmap.patch create mode 100644 queue-6.6/iio-adc-adi-axi-adc-move-to-backend-framework.patch create mode 100644 queue-6.6/iio-adc-adi-axi-adc-only-error-out-in-major-version-.patch create mode 100644 queue-6.6/iio-adc-stm32-fixing-err-code-to-not-indicate-succes.patch create mode 100644 queue-6.6/iio-add-the-iio-backend-framework.patch create mode 100644 queue-6.6/iio-buffer-dmaengine-export-buffer-alloc-and-free-fu.patch create mode 100644 queue-6.6/iio-core-leave-private-pointer-null-when-no-private-.patch create mode 100644 queue-6.6/iio-pressure-dps310-support-negative-temperature-val.patch create mode 100644 queue-6.6/interconnect-qcom-qcm2290-fix-mas_snoc_bimc-qos-port.patch create mode 100644 queue-6.6/kbuild-fix-build-id-symlinks-to-installed-debug-vdso.patch create mode 100644 queue-6.6/kbuild-unify-vdso_install-rules.patch create mode 100644 queue-6.6/leds-pwm-disable-pwm-when-going-to-suspend.patch create mode 100644 queue-6.6/libsubcmd-fix-parse-options-memory-leak.patch create mode 100644 queue-6.6/loongarch-fix-callchain-parse-error-with-kernel-trac.patch create mode 100644 queue-6.6/microblaze-remove-early-printk-call-from-cpuinfo-sta.patch create mode 100644 queue-6.6/microblaze-remove-gcc-flag-for-non-existing-early_pr.patch create mode 100644 queue-6.6/misc-pvpanic-deduplicate-common-code.patch create mode 100644 queue-6.6/misc-pvpanic-pci-register-attributes-via-pci_driver.patch create mode 100644 queue-6.6/module-don-t-ignore-sysfs_create_link-failures.patch create mode 100644 queue-6.6/ovl-add-helper-ovl_file_modified.patch create mode 100644 queue-6.6/ovl-remove-upper-umask-handling-from-ovl_create_uppe.patch create mode 100644 queue-6.6/pci-edr-align-edr_port_dpc_enable_dsm-with-pci-firmw.patch create mode 100644 queue-6.6/pci-edr-align-edr_port_locate_dsm-with-pci-firmware-.patch create mode 100644 queue-6.6/pci-of_property-return-error-for-int_map-allocation-.patch create mode 100644 queue-6.6/pci-tegra194-fix-probe-path-for-endpoint-mode.patch create mode 100644 queue-6.6/pci-wait-for-link-training-0-before-starting-link-re.patch create mode 100644 queue-6.6/perf-annotate-fix-annotation_calc_lines-to-pass-corr.patch create mode 100644 queue-6.6/perf-annotate-get-rid-of-duplicate-group-option-item.patch create mode 100644 queue-6.6/perf-annotate-introduce-global-annotation_options.patch create mode 100644 queue-6.6/perf-annotate-split-branch-stack-cycles-information-.patch create mode 100644 queue-6.6/perf-annotate-use-global-annotation_options.patch create mode 100644 queue-6.6/perf-bench-internals-inject-build-id-fix-trap-divide.patch create mode 100644 queue-6.6/perf-bench-uprobe-remove-lib64-from-libc.so.6-binary.patch create mode 100644 queue-6.6/perf-daemon-fix-file-leak-in-daemon_session__control.patch create mode 100644 queue-6.6/perf-docs-document-bpf-event-modifier.patch create mode 100644 queue-6.6/perf-evlist-add-evlist__findnew_tracking_event-helpe.patch create mode 100644 queue-6.6/perf-intel-pt-fix-unassigned-instruction-op-discover.patch create mode 100644 queue-6.6/perf-machine-thread-remove-exited-threads-by-default.patch create mode 100644 queue-6.6/perf-maps-move-symbol-maps-functions-to-maps.c.patch create mode 100644 queue-6.6/perf-pmu-assume-sysfs-events-are-always-the-same-cas.patch create mode 100644 queue-6.6/perf-pmu-compat-supports-regular-expression-matching.patch create mode 100644 queue-6.6/perf-pmu-count-sys-and-cpuid-json-events-separately.patch create mode 100644 queue-6.6/perf-pmu-move-pmu__find_core_pmu-to-pmus.c.patch create mode 100644 queue-6.6/perf-probe-add-missing-libgen.h-header-needed-for-us.patch create mode 100644 queue-6.6/perf-record-delete-session-after-stopping-sideband-t.patch create mode 100644 queue-6.6/perf-record-fix-debug-message-placement-for-test-con.patch create mode 100644 queue-6.6/perf-record-lazy-load-kernel-symbols.patch create mode 100644 queue-6.6/perf-record-move-setting-tracking-events-before-reco.patch create mode 100644 queue-6.6/perf-report-avoid-segv-in-report__setup_sample_type.patch create mode 100644 queue-6.6/perf-report-convert-to-the-global-annotation_options.patch create mode 100644 queue-6.6/perf-stat-do-not-fail-on-metrics-on-s390-z-vm-system.patch create mode 100644 queue-6.6/perf-stat-don-t-display-metric-header-for-non-leader.patch create mode 100644 queue-6.6/perf-symbols-fix-ownership-of-string-in-dso__load_vm.patch create mode 100644 queue-6.6/perf-test-add-a-test-for-strcmp_cpuid_str-expression.patch create mode 100644 queue-6.6/perf-test-shell-arm_coresight-increase-buffer-size-f.patch create mode 100644 queue-6.6/perf-tests-apply-attributes-to-all-events-in-object-.patch create mode 100644 queue-6.6/perf-tests-make-test-data-symbol-more-robust-on-neov.patch create mode 100644 queue-6.6/perf-thread-fixes-to-thread__new-related-to-initiali.patch create mode 100644 queue-6.6/perf-tools-add-use-pmu-reverse-lookup-from-config-to.patch create mode 100644 queue-6.6/perf-tools-use-pmus-to-describe-type-from-attribute.patch create mode 100644 queue-6.6/perf-top-convert-to-the-global-annotation_options.patch create mode 100644 queue-6.6/perf-ui-browser-avoid-segv-on-title.patch create mode 100644 queue-6.6/perf-ui-browser-don-t-save-pointer-to-stack-memory.patch create mode 100644 queue-6.6/phy-qcom-qmp-combo-fix-duplicate-return-in-qmp_v4_co.patch create mode 100644 queue-6.6/pinctrl-qcom-pinctrl-sm7150-fix-sdc1-and-ufs-special.patch create mode 100644 queue-6.6/ppdev-add-an-error-check-in-register_device.patch create mode 100644 queue-6.6/ppdev-remove-usage-of-the-deprecated-ida_simple_xx-a.patch create mode 100644 queue-6.6/pwm-rename-pwm_apply_state-to-pwm_apply_might_sleep.patch create mode 100644 queue-6.6/reapply-arm64-fpsimd-implement-lazy-restore-for-kern.patch create mode 100644 queue-6.6/remove-call_-read-write-_iter-functions.patch create mode 100644 queue-6.6/revert-arm64-fpsimd-implement-lazy-restore-for-kerne.patch create mode 100644 queue-6.6/risc-v-enable-cbo.zero-in-usermode.patch create mode 100644 queue-6.6/riscv-dts-starfive-visionfive-2-remove-non-existing-.patch create mode 100644 queue-6.6/riscv-flush-the-instruction-cache-during-smp-bringup.patch create mode 100644 queue-6.6/s390-boot-remove-alt_stfle_fac_list-from-decompresso.patch create mode 100644 queue-6.6/s390-ipl-fix-incorrect-initialization-of-len-fields-.patch create mode 100644 queue-6.6/s390-ipl-fix-incorrect-initialization-of-nvme-dump-b.patch create mode 100644 queue-6.6/s390-vdso-create-.build-id-links-for-unstripped-vdso.patch create mode 100644 queue-6.6/s390-vdso-generate-unwind-information-for-c-modules.patch create mode 100644 queue-6.6/s390-vdso-use-standard-stack-frame-layout.patch create mode 100644 queue-6.6/s390-vdso64-filter-out-munaligned-symbols-flag-for-v.patch create mode 100644 queue-6.6/serial-max3100-fix-bitwise-types.patch create mode 100644 queue-6.6/serial-max3100-lock-port-lock-when-calling-uart_hand.patch create mode 100644 queue-6.6/serial-max3100-update-uart_driver_registered-on-driv.patch create mode 100644 queue-6.6/serial-sc16is7xx-add-proper-sched.h-include-for-sche.patch create mode 100644 queue-6.6/serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch create mode 100644 queue-6.6/serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch create mode 100644 queue-6.6/serial-sh-sci-protect-invalidating-rxdma-on-shutdown.patch create mode 100644 queue-6.6/soundwire-cadence-fix-invalid-pdi-offset.patch create mode 100644 queue-6.6/splice-remove-permission-hook-from-iter_file_splice_.patch create mode 100644 queue-6.6/stm-class-fix-a-double-free-in-stm_register_device.patch create mode 100644 queue-6.6/udf-convert-udf_expand_file_adinicb-to-use-a-folio.patch create mode 100644 queue-6.6/udf-remove-gfp_nofs-allocation-in-udf_expand_file_ad.patch create mode 100644 queue-6.6/usb-fotg210-add-missing-kernel-doc-description.patch create mode 100644 queue-6.6/usb-gadget-u_audio-clear-uac-pointer-when-freed.patch create mode 100644 queue-6.6/usb-gadget-u_audio-fix-race-condition-use-of-control.patch create mode 100644 queue-6.6/usb-typec-ucsi-always-register-a-link-to-usb-pd-devi.patch create mode 100644 queue-6.6/usb-typec-ucsi-simplify-partner-s-pd-caps-registrati.patch create mode 100644 queue-6.6/vfio-pci-fix-potential-memory-leak-in-vfio_intx_enab.patch create mode 100644 queue-6.6/vmci-fix-an-error-handling-path-in-vmci_guest_probe_.patch create mode 100644 queue-6.6/watchdog-bd9576-drop-always-running-property.patch create mode 100644 queue-6.6/watchdog-cpu5wdt.c-fix-use-after-free-bug-caused-by-.patch create mode 100644 queue-6.6/watchdog-sa1100-fix-ptr_err_or_zero-vs-null-check-in.patch create mode 100644 queue-6.6/xfs-convert-kmem_free-for-kvmalloc-users-to-kvfree.patch create mode 100644 queue-6.6/xfs-fix-log-recovery-buffer-allocation-for-the-legac.patch create mode 100644 queue-6.6/xfs-match-lock-mode-in-xfs_buffered_write_iomap_begi.patch create mode 100644 queue-6.6/xfs-require-xfs_sb_feat_incompat_log_xattrs-for-attr.patch create mode 100644 queue-6.6/xfs-upgrade-the-extent-counters-in-xfs_reflink_end_c.patch 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 index 00000000000..babb871f201 --- /dev/null +++ b/queue-6.6/alsa-timer-set-lower-bound-of-start-tick-time.patch @@ -0,0 +1,52 @@ +From 7135223dedc8c3395286133970ddecae77b2a9d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 May 2024 20:27:36 +0200 +Subject: ALSA: timer: Set lower bound of start tick time + +From: Takashi Iwai + +[ 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: +Link: https://lore.kernel.org/r/20240514182745.4015-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f76bea3288b --- /dev/null +++ b/queue-6.6/arm64-dts-meson-fix-s4-power-controller-node.patch @@ -0,0 +1,49 @@ +From 7c31198635b5c27e2c9ecb3fbfdcfba0d152ea3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Apr 2024 16:42:30 +0800 +Subject: arm64: dts: meson: fix S4 power-controller node + +From: Xianwei Zhao + +[ 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 +Reviewed-by: Neil Armstrong +Link: https://lore.kernel.org/r/20240412-fix-secpwr-s4-v2-1-3802fd936d77@amlogic.com +Signed-off-by: Neil Armstrong +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..587a6786c69 --- /dev/null +++ b/queue-6.6/arm64-fpsimd-avoid-erroneous-elide-of-user-state-rel.patch @@ -0,0 +1,127 @@ +From 0180bc16b0f2c38cf9215f40fdca39302bc242da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 11:13:36 +0200 +Subject: arm64/fpsimd: Avoid erroneous elide of user state reload + +From: Ard Biesheuvel + +[ 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 +Fixes: aefbab8e77eb ("arm64: fpsimd: Preserve/restore kernel mode NEON at context switch") +Cc: Mark Brown +Cc: Dave Martin +Cc: Janne Grunau +Cc: stable@vger.kernel.org +Signed-off-by: Ard Biesheuvel +Tested-by: Janne Grunau +Tested-by: Johannes Nixdorf +Reviewed-by: Mark Brown +Link: https://lore.kernel.org/r/20240522091335.335346-2-ardb+git@google.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bb2e8c893d9 --- /dev/null +++ b/queue-6.6/arm64-fpsimd-drop-unneeded-busy-flag.patch @@ -0,0 +1,218 @@ +From 37f2773a1ef05374538d5e4ed26cbacebe363241 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Dec 2023 12:32:20 +0100 +Subject: arm64: fpsimd: Drop unneeded 'busy' flag + +From: Ard Biesheuvel + +[ 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 +Reviewed-by: Mark Brown +Tested-by: Geert Uytterhoeven +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 +Stable-dep-of: b8995a184170 ("Revert "arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD"") +Signed-off-by: Sasha Levin +--- + 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 + #include + +-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 index 00000000000..b23abe85fe2 --- /dev/null +++ b/queue-6.6/arm64-fpsimd-implement-lazy-restore-for-kernel-mode-.patch @@ -0,0 +1,86 @@ +From afeeeb2dbfdded9651e5b4e01083c2d1c114ea82 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Dec 2023 12:32:22 +0100 +Subject: arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD + +From: Ard Biesheuvel + +[ 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 +Reviewed-by: Mark Brown +Acked-by: Mark Rutland +Link: https://lore.kernel.org/r/20231208113218.3001940-9-ardb@google.com +Signed-off-by: Will Deacon +Stable-dep-of: b8995a184170 ("Revert "arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD"") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..dca376b7bea --- /dev/null +++ b/queue-6.6/arm64-fpsimd-preserve-restore-kernel-mode-neon-at-co.patch @@ -0,0 +1,251 @@ +From bf3880ed007142c4d7ff620fb293c8c2becd58ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Dec 2023 12:32:21 +0100 +Subject: arm64: fpsimd: Preserve/restore kernel mode NEON at context switch + +From: Ard Biesheuvel + +[ 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 +Reviewed-by: Mark Brown +Reviewed-by: Mark Rutland +Link: https://lore.kernel.org/r/20231208113218.3001940-8-ardb@google.com +Signed-off-by: Will Deacon +Stable-dep-of: b8995a184170 ("Revert "arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD"") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f05011c85c4 --- /dev/null +++ b/queue-6.6/coresight-etm4x-do-not-hardcode-iomem-access-for-reg.patch @@ -0,0 +1,44 @@ +From 59860d678e1c04295013eec8d29a0ccc2d6d3632 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Apr 2024 15:26:59 +0100 +Subject: coresight: etm4x: Do not hardcode IOMEM access for register restore + +From: Suzuki K Poulose + +[ 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 +Reviewed-by: Mike Leach +Signed-off-by: Suzuki K Poulose +Tested-by: Yabin Cui +Link: https://lore.kernel.org/r/20240412142702.2882478-2-suzuki.poulose@arm.com +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..72b53a28ced --- /dev/null +++ b/queue-6.6/coresight-etm4x-do-not-save-restore-data-trace-contr.patch @@ -0,0 +1,119 @@ +From 579f6a62807f9f21231a2b1715bb45dcfb4f9cbb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Apr 2024 15:27:00 +0100 +Subject: coresight: etm4x: Do not save/restore Data trace control registers + +From: Suzuki K Poulose + +[ 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 +Reviewed-by: Mike Leach +Signed-off-by: Suzuki K Poulose +Tested-by: Yabin Cui +Link: https://lore.kernel.org/r/20240412142702.2882478-3-suzuki.poulose@arm.com +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..278aa6efc5b --- /dev/null +++ b/queue-6.6/coresight-etm4x-fix-access-to-resource-selector-regi.patch @@ -0,0 +1,51 @@ +From a0ce376526dcb538277f4a3a4011f6060e64bd13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Apr 2024 15:27:02 +0100 +Subject: coresight: etm4x: Fix access to resource selector registers + +From: Suzuki K Poulose + +[ 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 +Fixes: f188b5e76aae ("coresight: etm4x: Save/restore state across CPU low power states") +Signed-off-by: Suzuki K Poulose +Tested-by: Yabin Cui +Reviewed-by: Mike Leach +Link: https://lore.kernel.org/r/20240412142702.2882478-5-suzuki.poulose@arm.com +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1068825b269 --- /dev/null +++ b/queue-6.6/coresight-etm4x-fix-unbalanced-pm_runtime_enable.patch @@ -0,0 +1,66 @@ +From 5f219d57184fe676e237174f3738e17e6de28b54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Mar 2024 11:28:33 +0530 +Subject: coresight: etm4x: Fix unbalanced pm_runtime_enable() + +From: Anshuman Khandual + +[ 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 +Cc: Hanjun Guo +Cc: Sudeep Holla +Cc: "Rafael J. Wysocki" +Cc: Len Brown +Cc: Suzuki K Poulose +Cc: Mike Leach +Cc: James Clark +Cc: Leo Yan +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 +Signed-off-by: Anshuman Khandual +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20240314055843.2625883-2-anshuman.khandual@arm.com +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5a6f3693962 --- /dev/null +++ b/queue-6.6/coresight-etm4x-safe-access-for-trcqcltr.patch @@ -0,0 +1,90 @@ +From c12501a4fa3d1b6121d1f36c73afd512a8f42749 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Apr 2024 15:27:01 +0100 +Subject: coresight: etm4x: Safe access for TRCQCLTR + +From: Suzuki K Poulose + +[ 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 +Reviewed-by: Mike Leach +Signed-off-by: Suzuki K Poulose +Tested-by: Yabin Cui +Link: https://lore.kernel.org/r/20240412142702.2882478-4-suzuki.poulose@arm.com +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..7d75f1b60aa --- /dev/null +++ b/queue-6.6/counter-linux-counter.h-fix-excess-kernel-doc-descri.patch @@ -0,0 +1,37 @@ +From 30e80f5c5db3ce5919ee3701cb35419af3586e27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Dec 2023 21:05:11 -0800 +Subject: counter: linux/counter.h: fix Excess kernel-doc description warning + +From: Randy Dunlap + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..90432d47147 --- /dev/null +++ b/queue-6.6/dmaengine-idma64-add-check-for-dma_set_max_seg_size.patch @@ -0,0 +1,40 @@ +From 5bc3b03a14281f9ee397826e154a9d7089c8f4e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Apr 2024 02:49:32 +0000 +Subject: dmaengine: idma64: Add check for dma_set_max_seg_size + +From: Chen Ni + +[ 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 +Acked-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20240403024932.3342606-1-nichen@iscas.ac.cn +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..cc6b0083e28 --- /dev/null +++ b/queue-6.6/dmaengine-idxd-avoid-unnecessary-destruction-of-file.patch @@ -0,0 +1,46 @@ +From 3103ab70c738b7ae28abb12b0c39efbb2454be87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Jan 2024 17:39:54 -0800 +Subject: dmaengine: idxd: Avoid unnecessary destruction of file_ida + +From: Fenghua Yu + +[ 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 +Signed-off-by: Fenghua Yu +Reviewed-by: Dave Jiang +Link: https://lore.kernel.org/r/20240130013954.2024231-1-fenghua.yu@intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ed9e1068bf2 --- /dev/null +++ b/queue-6.6/drm-amd-display-remove-pixle-rate-limit-for-subvp.patch @@ -0,0 +1,39 @@ +From 3d8437b947cfb87b486dfbdf336ac40b5fe2b60f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Feb 2024 10:40:36 -0500 +Subject: drm/amd/display: Remove pixle rate limit for subvp + +From: Alvin Lee + +[ 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 +Reviewed-by: Chaitanya Dhere +Acked-by: Rodrigo Siqueira +Tested-by: Daniel Wheeler +Signed-off-by: Alvin Lee +Signed-off-by: Alex Deucher +Stable-dep-of: cf8c498694a4 ("drm/amd/display: Revert Remove pixle rate limit for subvp") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..421de19007c --- /dev/null +++ b/queue-6.6/drm-amd-display-revert-remove-pixle-rate-limit-for-s.patch @@ -0,0 +1,48 @@ +From c6e80daf894af5870d141f1b3ec5e2561d02ef85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 11:20:27 -0500 +Subject: drm/amd/display: Revert Remove pixle rate limit for subvp + +From: Wenjing Liu + +[ 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 +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Reviewed-by: Chaitanya Dhere +Reviewed-by: Martin Leung +Acked-by: Wayne Lin +Signed-off-by: Wenjing Liu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..81882fa6181 --- /dev/null +++ b/queue-6.6/dt-bindings-adc-axi-adc-add-clocks-property.patch @@ -0,0 +1,60 @@ +From aeddb3e106079974f48cbea958a3c6149b093763 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Apr 2024 17:42:12 +0200 +Subject: dt-bindings: adc: axi-adc: add clocks property + +From: Nuno Sa + +[ 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 +Fixes: 96553a44e96d ("dt-bindings: iio: adc: add bindings doc for AXI ADC driver") +Signed-off-by: Nuno Sa +Link: https://lore.kernel.org/r/20240426-ad9467-new-features-v2-3-6361fc3ba1cc@analog.com +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f3dcae59bec --- /dev/null +++ b/queue-6.6/dt-bindings-adc-axi-adc-update-bindings-for-backend-.patch @@ -0,0 +1,65 @@ +From 5a3e337fac251434c04e8a0af8719f67c3c321d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Feb 2024 21:57:14 +0100 +Subject: dt-bindings: adc: axi-adc: update bindings for backend framework + +From: Nuno Sa + +[ 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 +Signed-off-by: Nuno Sa +Link: https://lore.kernel.org/r/20240210-iio-backend-v11-2-f5242a5fb42a@analog.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: 19fb11d7220b ("dt-bindings: adc: axi-adc: add clocks property") +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..f45b02d4ec6 --- /dev/null +++ b/queue-6.6/dt-bindings-pci-rcar-pci-host-add-missing-iommu-prop.patch @@ -0,0 +1,47 @@ +From 8c66b6e330e76a6816aae8edc696e72d1bb22046 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Krzysztof Wilczyński +Acked-by: Conor Dooley +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c3ae50a56b2 --- /dev/null +++ b/queue-6.6/dt-bindings-pci-rcar-pci-host-add-optional-regulator.patch @@ -0,0 +1,57 @@ +From 49b2ba213754cdfc3041073aee3a4d080c323ddd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: Geert Uytterhoeven +Acked-by: Krzysztof Kozlowski +Stable-dep-of: 78d212851f0e ("dt-bindings: PCI: rcar-pci-host: Add missing IOMMU properties") +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..686a5990f4f --- /dev/null +++ b/queue-6.6/dt-bindings-pci-rockchip-rk3399-pcie-add-missing-max.patch @@ -0,0 +1,42 @@ +From 0d1229515c8f504b64e178cdedeb6a9bb6be96e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Krzysztof Wilczyński +Acked-by: Conor Dooley +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9dfbd31cc87 --- /dev/null +++ b/queue-6.6/dt-bindings-phy-qcom-sc8280xp-qmp-ufs-phy-fix-msm899.patch @@ -0,0 +1,61 @@ +From ea6e02d5cc98a6fba22e4107b49ea6061f0a5c4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20240501-qcom-phy-fixes-v1-2-f1fd15c33fb3@linaro.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..d251ac659fd --- /dev/null +++ b/queue-6.6/dt-bindings-phy-qcom-usb-snps-femto-v2-use-correct-f.patch @@ -0,0 +1,48 @@ +From 34e61e48c9e39ecaf1c90d713aa4ce99ce943c50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20240501-qcom-phy-fixes-v1-3-f1fd15c33fb3@linaro.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..027345b354b --- /dev/null +++ b/queue-6.6/dt-bindings-pinctrl-mediatek-mt7622-fix-array-proper.patch @@ -0,0 +1,168 @@ +From 33ff4eb014f64b42c041e3efaa4b7ac68daa9a4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Rob Herring +Message-ID: <20240423045502.7778-1-zajec5@gmail.com> +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..63598f94f0f --- /dev/null +++ b/queue-6.6/dt-bindings-spmi-hisilicon-hisi-spmi-controller-fix-.patch @@ -0,0 +1,51 @@ +From 3d067de7036452a3627d1e9fe23b627402742079 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 14:07:39 -0700 +Subject: dt-bindings: spmi: hisilicon,hisi-spmi-controller: fix binding + references + +From: Johan Hovold + +[ 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 +Link: https://lore.kernel.org/r/20231130173757.13011-2-johan+linaro@kernel.org +Acked-by: Krzysztof Kozlowski +Signed-off-by: Stephen Boyd +Link: https://lore.kernel.org/r/20240507210809.3479953-3-sboyd@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..89c7df976c4 --- /dev/null +++ b/queue-6.6/eventfs-create-eventfs_root_inode-to-store-dentry.patch @@ -0,0 +1,195 @@ +From e8922e6166b250e9020a99dfa7e20ebd93ded2f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Feb 2024 10:34:52 -0500 +Subject: eventfs: Create eventfs_root_inode to store dentry + +From: Steven Rostedt (Google) + +[ 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 +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Christian Brauner +Cc: Al Viro +Cc: Ajay Kaher +Signed-off-by: Steven Rostedt (Google) +Stable-dep-of: b63db58e2fa5 ("eventfs/tracing: Add callback for release of an eventfs_inode") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f68695d2d4d --- /dev/null +++ b/queue-6.6/eventfs-do-not-differentiate-the-toplevel-events-dir.patch @@ -0,0 +1,150 @@ +From 50b530a0f377c2ddba3da0a33f7bd05bb4fdb658 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 May 2024 16:08:25 -0400 +Subject: eventfs: Do not differentiate the toplevel events directory + +From: Steven Rostedt (Google) + +[ 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 +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Fixes: 8186fff7ab649 ("tracefs/eventfs: Use root and instance inodes as default ownership") +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c451ecc9cb4 --- /dev/null +++ b/queue-6.6/eventfs-free-all-of-the-eventfs_inode-after-rcu.patch @@ -0,0 +1,84 @@ +From bf38d7f5807027bef3401ff9dd0c352a713940a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 May 2024 16:08:22 -0400 +Subject: eventfs: Free all of the eventfs_inode after RCU + +From: Steven Rostedt (Google) + +[ 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 +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Fixes: 43aa6f97c2d03 ("eventfs: Get rid of dentry pointers without refcounts") +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..449417ac362 --- /dev/null +++ b/queue-6.6/eventfs-have-events-directory-get-permissions-from-i.patch @@ -0,0 +1,133 @@ +From d9e4cb4bc552444ea539694561eb74a2a954f485 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 May 2024 16:08:27 -0400 +Subject: eventfs: Have "events" directory get permissions from its parent + +From: Steven Rostedt (Google) + +[ 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 +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Fixes: 8186fff7ab649 ("tracefs/eventfs: Use root and instance inodes as default ownership") +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..843cb0d70e4 --- /dev/null +++ b/queue-6.6/eventfs-tracing-add-callback-for-release-of-an-event.patch @@ -0,0 +1,199 @@ +From 64ff8ab11760417874c0519e144cb7a681af3c63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Cc: Mathieu Desnoyers +Fixes: 5790b1fb3d672 ("eventfs: Remove eventfs_file and just use eventfs_inode") +Reported-by: Tze-nan wu +Tested-by: Tze-nan Wu (吳澤南) +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..97a1e7fae4a --- /dev/null +++ b/queue-6.6/extcon-max8997-select-irq_domain-instead-of-dependin.patch @@ -0,0 +1,47 @@ +From 40e2dbecc624250de675f25ecfb6d09181ad2f5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Feb 2024 22:00:28 -0800 +Subject: extcon: max8997: select IRQ_DOMAIN instead of depending on it + +From: Randy Dunlap + +[ 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 +Acked-by: Arnd Bergmann +Signed-off-by: Chanwoo Choi +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2c4ab460a11 --- /dev/null +++ b/queue-6.6/f2fs-clean-up-errors-in-segment.h.patch @@ -0,0 +1,43 @@ +From 54203fa23517a6a6ca298cba950126b42ecc3018 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Oct 2023 14:45:42 +0800 +Subject: f2fs: Clean up errors in segment.h + +From: KaiLong Wang + +[ Upstream commit 37768434b7a7d00ac5a08b2c1d31aa7aaa0846a0 ] + +Fix the following errors reported by checkpatch: + +ERROR: spaces required around that ':' (ctx:VxW) + +Signed-off-by: KaiLong Wang +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..267873b41a2 --- /dev/null +++ b/queue-6.6/f2fs-compress-don-t-allow-unaligned-truncation-on-re.patch @@ -0,0 +1,65 @@ +From bcd7980ca7cfe5489347b65936ded080d6db5b0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 May 2024 11:33:39 +0800 +Subject: f2fs: compress: don't allow unaligned truncation on released compress + inode + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..94df37109bf --- /dev/null +++ b/queue-6.6/f2fs-compress-fix-error-path-of-inc_valid_block_coun.patch @@ -0,0 +1,71 @@ +From 96c3fba9d7993cbc866c99258a8d77fe8755cffe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 May 2024 18:41:37 +0800 +Subject: f2fs: compress: fix error path of inc_valid_block_count() + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..80363b96e6f --- /dev/null +++ b/queue-6.6/f2fs-compress-fix-to-cover-reserve-release-_compress.patch @@ -0,0 +1,75 @@ +From a5e5af37ced2348a0f75e1ec44bdea87d6a9931e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..854b3bed812 --- /dev/null +++ b/queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch @@ -0,0 +1,70 @@ +From ce6baf48fe8951884b1a600116e2d16315eb39b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://lore.kernel.org/linux-f2fs-devel/CAHJ8P3LdZXLc2rqeYjvymgYHr2+YLuJ0sLG9DdsJZmwO7deuhw@mail.gmail.com +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d2c521981b5 --- /dev/null +++ b/queue-6.6/f2fs-compress-fix-to-relocate-check-condition-in-f2f.patch-466 @@ -0,0 +1,70 @@ +From ffcaaece3b29fd183a50d8b38b0c564a1b92f92b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://lore.kernel.org/linux-f2fs-devel/CAHJ8P3LdZXLc2rqeYjvymgYHr2+YLuJ0sLG9DdsJZmwO7deuhw@mail.gmail.com +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..49f0a5eff79 --- /dev/null +++ b/queue-6.6/f2fs-compress-fix-to-update-i_compr_blocks-correctly.patch @@ -0,0 +1,82 @@ +From 9269a0dc033b512ea0ac028c2ae6f580f7ecaacc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 May 2024 18:41:36 +0800 +Subject: f2fs: compress: fix to update i_compr_blocks correctly + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5a818de3a99 --- /dev/null +++ b/queue-6.6/f2fs-deprecate-io_bits.patch @@ -0,0 +1,556 @@ +From 70f45ea8dd75472b68ba8a0a76fc35f918bfc193 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Feb 2024 11:21:00 -0800 +Subject: f2fs: deprecate io_bits + +From: Jaegeuk Kim + +[ Upstream commit 87161a2b0aed9e9b614bbf6fe8697ad560ceb0cb ] + +Let's deprecate an unused io_bits feature to save CPU cycles and memory. + +Reviewed-by: Daeho Jeong +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 043c832371cd ("f2fs: compress: fix error path of inc_valid_block_count()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d75d70b3e4d --- /dev/null +++ b/queue-6.6/f2fs-fix-block-migration-when-section-is-not-aligned.patch @@ -0,0 +1,62 @@ +From fc6119b710db1b40a90569bdb44b9fa0f63065d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 28 Apr 2024 21:51:42 -0600 +Subject: f2fs: fix block migration when section is not aligned to pow2 + +From: Wu Bo + +[ 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 +Signed-off-by: Wu Bo +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..47bdafc3a47 --- /dev/null +++ b/queue-6.6/f2fs-fix-to-add-missing-iput-in-gc_data_segment.patch @@ -0,0 +1,46 @@ +From 8928bd3793b0708c8181bc47a39e7669c577dbcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 May 2024 11:43:33 +0800 +Subject: f2fs: fix to add missing iput() in gc_data_segment() + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9c00223d3c8 --- /dev/null +++ b/queue-6.6/f2fs-fix-to-check-pinfile-flag-in-f2fs_move_file_ran.patch @@ -0,0 +1,37 @@ +From c76afe1cc5d3e22dbae960e334dd4f7ab6059804 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Apr 2024 22:24:20 +0800 +Subject: f2fs: fix to check pinfile flag in f2fs_move_file_range() + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5b2542e763d --- /dev/null +++ b/queue-6.6/f2fs-fix-to-release-node-block-count-in-error-path-o.patch @@ -0,0 +1,44 @@ +From ccfd934e6a7e05d809249ea7078f575444a90b4a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b2ab709a4a1 --- /dev/null +++ b/queue-6.6/f2fs-fix-to-relocate-check-condition-in-f2fs_falloca.patch @@ -0,0 +1,62 @@ +From afb6a7e47cf1d857621652fb1353b928f77f910f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Apr 2024 22:24:19 +0800 +Subject: f2fs: fix to relocate check condition in f2fs_fallocate() + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..41c0855a193 --- /dev/null +++ b/queue-6.6/f2fs-fix-to-wait-on-page-writeback-in-__clone_blkadd.patch @@ -0,0 +1,53 @@ +From 84cf7134c45ec0d668dfbad1dca3527cc2a87771 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Mar 2024 19:28:45 +0800 +Subject: f2fs: fix to wait on page writeback in __clone_blkaddrs() + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f435e4ae87b --- /dev/null +++ b/queue-6.6/f2fs-introduce-get_available_block_count-for-cleanup.patch @@ -0,0 +1,110 @@ +From b6bde298f3c504aca681c279e9140ef510df4684 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Feb 2024 11:15:15 +0800 +Subject: f2fs: introduce get_available_block_count() for cleanup + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 043c832371cd ("f2fs: compress: fix error path of inc_valid_block_count()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..938af41c25d --- /dev/null +++ b/queue-6.6/f2fs-kill-heap-based-allocation.patch @@ -0,0 +1,229 @@ +From 4ea2c31297553ba66b1a27ece8fddac6514c1cd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Feb 2024 12:48:44 -0800 +Subject: f2fs: kill heap-based allocation + +From: Jaegeuk Kim + +[ Upstream commit 4e0197f9932f70cc7be8744aa0ed4dd9b5d97d85 ] + +No one uses this feature. Let's kill it. + +Reviewed-by: Daeho Jeong +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..8d91b99766a --- /dev/null +++ b/queue-6.6/f2fs-multidev-fix-to-recognize-valid-zero-block-addr.patch @@ -0,0 +1,119 @@ +From e8bb2c79bda202887df44572cead17adb03338d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Mar 2024 15:42:23 +0800 +Subject: f2fs: multidev: fix to recognize valid zero block address + +From: Chao Yu + +[ 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: + + __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 +Closes: https://lore.kernel.org/linux-f2fs-devel/CAHj4cs-kfojYC9i0G73PRkYzcxCTex=-vugRFeP40g_URGvnfQ@mail.gmail.com/ +Tested-by: Shin'ichiro Kawasaki +Tested-by: Yi Zhang +Fixes: 1517c1a7a445 ("f2fs: implement iomap operations") +Fixes: 8d3c1fa3fa5e ("f2fs: don't rely on F2FS_MAP_* in f2fs_iomap_begin") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a0a22ac9376 --- /dev/null +++ b/queue-6.6/f2fs-separate-f2fs_gc_range-to-use-gc-for-a-range.patch @@ -0,0 +1,92 @@ +From 3071e9c718db22aeb12b3bd10c573392afeafa8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Feb 2024 14:32:55 -0800 +Subject: f2fs: separate f2fs_gc_range() to use GC for a range + +From: Daeho Jeong + +[ Upstream commit 2f0209f579d12bd0ea43a01a8696e30a8eeec1da ] + +Make f2fs_gc_range() an extenal function to use it for GC for a range. + +Signed-off-by: Daeho Jeong +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..85a1fb73ddf --- /dev/null +++ b/queue-6.6/f2fs-support-file-pinning-for-zoned-devices.patch @@ -0,0 +1,472 @@ +From 01660f99fd3ecf76b21b8c2db069abda71d6f715 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Feb 2024 09:38:12 -0800 +Subject: f2fs: support file pinning for zoned devices + +From: Daeho Jeong + +[ Upstream commit 9703d69d9d153bb230711d0d577454552aeb13d4 ] + +Support file pinning with conventional storage area for zoned devices + +Signed-off-by: Daeho Jeong +Signed-off-by: Jaegeuk Kim +Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e93c66cd261 --- /dev/null +++ b/queue-6.6/f2fs-support-printk_ratelimited-in-f2fs_printk.patch @@ -0,0 +1,165 @@ +From 2355d2363e9d0c799cb42049661c3c8566c42b37 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Jan 2024 23:19:16 +0800 +Subject: f2fs: support printk_ratelimited() in f2fs_printk() + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..60c307ef0d1 --- /dev/null +++ b/queue-6.6/f2fs-use-blks_per_seg-blks_per_sec-and-segs_per_sec.patch @@ -0,0 +1,982 @@ +From 79bec982bab2fb9b8cee04071c4e8911d06c8a05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ Upstream commit a60108f7dfb5867da1ad9c777d2fbbe47e4dbdd7 ] + +No functional change. + +Reviewed-by: Daeho Jeong +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: aa4074e8fec4 ("f2fs: fix block migration when section is not aligned to pow2") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f87e63280d4 --- /dev/null +++ b/queue-6.6/firmware-dmi-id-add-a-release-callback-function.patch @@ -0,0 +1,50 @@ +From 0b8801f4dca18e58258b915abfdd3053eae46f21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Apr 2024 09:34:24 +0200 +Subject: firmware: dmi-id: add a release callback function + +From: Arnd Bergmann + +[ 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 +Signed-off-by: Jean Delvare +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d9d285c02f0 --- /dev/null +++ b/queue-6.6/fpga-bridge-add-owner-module-and-take-its-refcount.patch @@ -0,0 +1,251 @@ +From a90e3cedea2ee526844c12b307d1ba9f73ce09c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Mar 2024 18:18:37 +0100 +Subject: fpga: bridge: add owner module and take its refcount + +From: Marco Pagani + +[ 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 +Suggested-by: Xu Yilun +Reviewed-by: Russ Weight +Signed-off-by: Marco Pagani +Acked-by: Xu Yilun +Link: https://lore.kernel.org/r/20240322171839.233864-1-marpagan@redhat.com +Signed-off-by: Xu Yilun +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..fd9a0ca2c3a --- /dev/null +++ b/queue-6.6/fpga-manager-add-owner-module-and-take-its-refcount.patch @@ -0,0 +1,408 @@ +From f4b46ce83316c006254fd5a4155a4752f68d12aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Mar 2024 20:29:26 +0100 +Subject: fpga: manager: add owner module and take its refcount + +From: Marco Pagani + +[ 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 +Suggested-by: Xu Yilun +Signed-off-by: Marco Pagani +Acked-by: Xu Yilun +Link: https://lore.kernel.org/r/20240305192926.84886-1-marpagan@redhat.com +Signed-off-by: Xu Yilun +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..794230fa7cd --- /dev/null +++ b/queue-6.6/fpga-region-add-owner-module-and-take-its-refcount.patch @@ -0,0 +1,210 @@ +From e448309464a231f0a26946c37eea42779a31be01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Apr 2024 10:35:59 +0200 +Subject: fpga: region: add owner module and take its refcount + +From: Marco Pagani + +[ 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 +Suggested-by: Xu Yilun +Reviewed-by: Russ Weight +Signed-off-by: Marco Pagani +Acked-by: Xu Yilun +Link: https://lore.kernel.org/r/20240419083601.77403-1-marpagan@redhat.com +Signed-off-by: Xu Yilun +Signed-off-by: Sasha Levin +--- + 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(®ion->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(®ion->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(®ion->mutex); + INIT_LIST_HEAD(®ion->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 index 00000000000..aa2caff5138 --- /dev/null +++ b/queue-6.6/fs-move-kiocb_start_write-into-vfs_iocb_iter_write.patch @@ -0,0 +1,124 @@ +From 17f38d69e7960a2b346db04750b0e4ba867c0b83 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Nov 2023 14:27:12 +0200 +Subject: fs: move kiocb_start_write() into vfs_iocb_iter_write() + +From: Amir Goldstein + +[ 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 +Suggested-by: Josef Bacik +Signed-off-by: Amir Goldstein +Link: https://lore.kernel.org/r/20231122122715.2561213-14-amir73il@gmail.com +Reviewed-by: Josef Bacik +Reviewed-by: Jan Kara +Signed-off-by: Christian Brauner +Stable-dep-of: 7c98f7cb8fda ("remove call_{read,write}_iter() functions") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c15f170dbf8 --- /dev/null +++ b/queue-6.6/gpiolib-acpi-fix-failed-in-acpi_gpiochip_find-by-add.patch @@ -0,0 +1,84 @@ +From eb920a49d7241aa61732a1a9a086ae7918d74fe3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Mika Westerberg +Tested-by: Benjamin Tissoires +Signed-off-by: Andy Shevchenko +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e80d0711623 --- /dev/null +++ b/queue-6.6/greybus-arche-ctrl-move-device-table-to-its-right-lo.patch @@ -0,0 +1,66 @@ +From 06c24eea0b36ec38cf2271c1367ab97973fd55f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Apr 2024 10:06:35 +0200 +Subject: greybus: arche-ctrl: move device table to its right location + +From: Arnd Bergmann + +[ 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 +Link: https://lore.kernel.org/r/20240403080702.3509288-18-arnd@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..13626d7497d --- /dev/null +++ b/queue-6.6/greybus-lights-check-return-of-get_channel_from_mode.patch @@ -0,0 +1,59 @@ +From 2928cc9c487100622fe61916e81935726560a001 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Mar 2024 22:09:55 +0000 +Subject: greybus: lights: check return of get_channel_from_mode + +From: Rui Miguel Silva + +[ 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 +Suggested-by: Mikhail Lobanov +Suggested-by: Alex Elder +Signed-off-by: Rui Miguel Silva +Link: https://lore.kernel.org/r/20240325221549.2185265-1-rmfrfs@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1cf16c5177e --- /dev/null +++ b/queue-6.6/i2c-cadence-avoid-fifo-clear-after-start.patch @@ -0,0 +1,39 @@ +From ec8cff744bbcacfc5c9683e2391a2c9564760b5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 May 2024 15:12:08 +0530 +Subject: i2c: cadence: Avoid fifo clear after start + +From: Sai Pavan Boddu + +[ 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 +Acked-by: Michal Simek +Signed-off-by: Andi Shyti +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..108290785b9 --- /dev/null +++ b/queue-6.6/i2c-synquacer-fix-an-error-handling-path-in-synquace.patch @@ -0,0 +1,69 @@ +From 69dbca8f3b255c5fb15b984ee0fb7dafcd49f493 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Jan 2024 13:48:24 +0100 +Subject: i2c: synquacer: Fix an error handling path in synquacer_i2c_probe() + +From: Christophe JAILLET + +[ 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 +Acked-by: Ard Biesheuvel +Signed-off-by: Andi Shyti +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b54b8f55103 --- /dev/null +++ b/queue-6.6/i915-make-inject_virtual_interrupt-void.patch @@ -0,0 +1,67 @@ +From 01670f96015fe9de702a40cc6213190f41bc262f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Nov 2023 13:48:22 +0100 +Subject: i915: make inject_virtual_interrupt() void + +From: Christian Brauner + +[ 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 +Reviewed-by: Zhenyu Wang +Reviewed-by: Jens Axboe +Signed-off-by: Christian Brauner +Stable-dep-of: 82b951e6fbd3 ("vfio/pci: fix potential memory leak in vfio_intx_enable()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e9866764eb6 --- /dev/null +++ b/queue-6.6/iio-accel-mxc4005-allow-module-autoloading-via-of-co.patch @@ -0,0 +1,51 @@ +From b9747a492b4e0bfdbc6c2d1ee29a820d5a047e98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Oct 2023 18:39:28 +0200 +Subject: iio: accel: mxc4005: allow module autoloading via OF compatible + +From: Luca Ceresoli + +[ Upstream commit 4d7c16d08d248952c116f2eb9b7b5abc43a19688 ] + +Add OF device table with compatible strings to allow automatic module +loading. + +Signed-off-by: Luca Ceresoli +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20231004-mxc4005-device-tree-support-v1-2-e7c0faea72e4@bootlin.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: 6b8cffdc4a31 ("iio: accel: mxc4005: Reset chip on probe() and resume()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..581afbd67bd --- /dev/null +++ b/queue-6.6/iio-accel-mxc4005-reset-chip-on-probe-and-resume.patch @@ -0,0 +1,157 @@ +From dd372280e1259450dc919caf5f1cd84787bf9e75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Mar 2024 12:37:00 +0100 +Subject: iio: accel: mxc4005: Reset chip on probe() and resume() + +From: Hans de Goede + +[ 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 +Link: https://lore.kernel.org/r/20240326113700.56725-3-hdegoede@redhat.com +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 + #include + #include + #include +@@ -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 index 00000000000..a05b0784aec --- /dev/null +++ b/queue-6.6/iio-adc-ad9467-convert-to-backend-framework.patch @@ -0,0 +1,515 @@ +From 16a32525a438c8d778b3eb90afa0d1c08899c829 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Feb 2024 21:57:18 +0100 +Subject: iio: adc: ad9467: convert to backend framework + +From: Nuno Sa + +[ 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 +Link: https://lore.kernel.org/r/20240210-iio-backend-v11-6-f5242a5fb42a@analog.com +Reviewed-by: Andy Shevchenko +Signed-off-by: Jonathan Cameron +Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch") +Signed-off-by: Sasha Levin +--- + 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 + + ++#include + #include + #include + + #include + +-#include +- + /* + * 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 "); + 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 index 00000000000..65e83f8310f --- /dev/null +++ b/queue-6.6/iio-adc-ad9467-use-chip_info-variables-instead-of-ar.patch @@ -0,0 +1,147 @@ +From 999c318872e13c5bb2e12d8b3bfd07831b7cd42b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Dec 2023 13:39:29 +0100 +Subject: iio: adc: ad9467: use chip_info variables instead of array + +From: Nuno Sa + +[ 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 +Signed-off-by: Nuno Sa +Link: https://lore.kernel.org/r/20231207-iio-backend-prep-v2-6-a4a33bc4d70e@analog.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c44e6e5499e --- /dev/null +++ b/queue-6.6/iio-adc-ad9467-use-spi_get_device_match_data.patch @@ -0,0 +1,39 @@ +From 8399e245f2b68c0bf17e2055e79ae1974eaa11c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Dec 2023 13:39:28 +0100 +Subject: iio: adc: ad9467: use spi_get_device_match_data() + +From: Nuno Sa + +[ Upstream commit b67cc85d45d5d2894d0e2812bba27d7b23befbe6 ] + +Make use of spi_get_device_match_data() to simplify things. + +Reviewed-by: David Lechner +Signed-off-by: Nuno Sa +Link: https://lore.kernel.org/r/20231207-iio-backend-prep-v2-5-a4a33bc4d70e@analog.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bcf06738988 --- /dev/null +++ b/queue-6.6/iio-adc-adi-axi-adc-convert-to-regmap.patch @@ -0,0 +1,198 @@ +From eaadea3f007de9d8ee0bc0a5abacd8197ca12e78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Dec 2023 13:39:31 +0100 +Subject: iio: adc: adi-axi-adc: convert to regmap + +From: Nuno Sa + +[ Upstream commit 21aa971d3e295c2c81d0887f8a3e85a95dd687c5 ] + +Use MMIO regmap interface. It makes things easier for manipulating bits. + +Reviewed-by: David Lechner +Signed-off-by: Nuno Sa +Link: https://lore.kernel.org/r/20231207-iio-backend-prep-v2-8-a4a33bc4d70e@analog.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + + #include +@@ -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 index 00000000000..3d75c952c1e --- /dev/null +++ b/queue-6.6/iio-adc-adi-axi-adc-move-to-backend-framework.patch @@ -0,0 +1,620 @@ +From 6ce26f79e73e192921feffabccd014737a948c26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Feb 2024 21:57:19 +0100 +Subject: iio: adc: adi-axi-adc: move to backend framework + +From: Nuno Sa + +[ 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 +Link: https://lore.kernel.org/r/20240210-iio-backend-v11-7-f5242a5fb42a@analog.com +Reviewed-by: Andy Shevchenko +Signed-off-by: Jonathan Cameron +Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch") +Signed-off-by: Sasha Levin +--- + 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 + #include ++#include + #include + #include + #include +@@ -17,13 +18,12 @@ + #include + #include + +-#include +-#include +-#include +-#include +- + #include +-#include ++ ++#include ++#include ++#include ++#include + + /* + * 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(®istered_clients_lock); +- +- cl->dev = get_device(dev); +- +- list_add_tail(&cl->entry, ®istered_clients); +- +- mutex_unlock(®istered_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(®istered_clients_lock); +- +- list_del(&cl->entry); +- put_device(cl->dev); ++ struct adi_axi_adc_state *st = iio_backend_get_priv(back); + +- mutex_unlock(®istered_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(®istered_clients_lock); +- +- list_for_each_entry(cl, ®istered_clients, entry) { +- if (!cl->dev) +- continue; +- +- if (cl->dev->of_node != cln) +- continue; +- +- if (!try_module_get(cl->dev->driver->owner)) { +- mutex_unlock(®istered_clients_lock); +- of_node_put(cln); +- return ERR_PTR(-ENODEV); +- } +- +- get_device(cl->dev); +- cl->info = info; +- mutex_unlock(®istered_clients_lock); +- of_node_put(cln); +- return cl; +- } ++ struct adi_axi_adc_state *st = iio_backend_get_priv(back); + +- mutex_unlock(®istered_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 "); + 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 index 00000000000..e90fa521eb9 --- /dev/null +++ b/queue-6.6/iio-adc-adi-axi-adc-only-error-out-in-major-version-.patch @@ -0,0 +1,44 @@ +From 530f9ea9d9e7188717b73f3ab2cf7050e4427abb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20240419-ad9467-new-features-v1-2-3e7628ff6d5e@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0a01c47a7a5 --- /dev/null +++ b/queue-6.6/iio-adc-stm32-fixing-err-code-to-not-indicate-succes.patch @@ -0,0 +1,36 @@ +From 30e8a4f91d02af3ddf27f0dcbb20c94ce74a13c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 Mar 2024 18:53:00 +0000 +Subject: iio: adc: stm32: Fixing err code to not indicate success + +From: Jonathan Cameron + +[ Upstream commit 3735ca0b072656c3aa2cedc617a5e639b583a472 ] + +This path would result in returning 0 / success on an error path. + +Cc: Olivier Moysan +Fixes: 95bc818404b2 ("iio: adc: stm32-adc: add support of generic channels binding") +Reviewed-by: Fabrice Gasnier +Link: https://lore.kernel.org/r/20240330185305.1319844-4-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bbb27e09b8e --- /dev/null +++ b/queue-6.6/iio-add-the-iio-backend-framework.patch @@ -0,0 +1,593 @@ +From de741f603752ff97aa7be0c23eb331db0e1a84f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Feb 2024 21:57:17 +0100 +Subject: iio: add the IIO backend framework + +From: Nuno Sa + +[ 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 +Link: https://lore.kernel.org/r/20240210-iio-backend-v11-5-f5242a5fb42a@analog.com +Reviewed-by: Andy Shevchenko +Signed-off-by: Jonathan Cameron +Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch") +Signed-off-by: Sasha Levin +--- + 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 ++R: Olivier Moysan ++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 + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++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 "); ++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 ++ ++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 index 00000000000..96ad6247208 --- /dev/null +++ b/queue-6.6/iio-buffer-dmaengine-export-buffer-alloc-and-free-fu.patch @@ -0,0 +1,104 @@ +From b7d7abce88c267b7ba6c7b091f7dad6abb2c0d97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Feb 2024 21:57:16 +0100 +Subject: iio: buffer-dmaengine: export buffer alloc and free functions + +From: Nuno Sa + +[ 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 +Link: https://lore.kernel.org/r/20240210-iio-backend-v11-4-f5242a5fb42a@analog.com +Reviewed-by: Andy Shevchenko +Signed-off-by: Jonathan Cameron +Stable-dep-of: cf1c833f89e7 ("iio: adc: adi-axi-adc: only error out in major version mismatch") +Signed-off-by: Sasha Levin +--- + 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 "); + 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 "); + 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 index 00000000000..6913f3717bf --- /dev/null +++ b/queue-6.6/iio-core-leave-private-pointer-null-when-no-private-.patch @@ -0,0 +1,43 @@ +From bcbce9fa71948dfafc2069f5163c0090ffcc70db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:04:32 +0200 +Subject: iio: core: Leave private pointer NULL when no private data supplied + +From: Andy Shevchenko + +[ 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 +Reviewed-by: David Lechner +Link: https://lore.kernel.org/r/20240304140650.977784-2-andriy.shevchenko@linux.intel.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bf5170a7378 --- /dev/null +++ b/queue-6.6/iio-pressure-dps310-support-negative-temperature-val.patch @@ -0,0 +1,67 @@ +From 1317c9ddd386f387fac0a13b40445b9801aec4ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Apr 2024 12:50:27 +0200 +Subject: iio: pressure: dps310: support negative temperature values + +From: Thomas Haemmerle + +[ 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 +Link: https://lore.kernel.org/r/20240415105030.1161770-2-thomas.haemmerle@leica-geosystems.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..7a8e0e0b7ec --- /dev/null +++ b/queue-6.6/interconnect-qcom-qcm2290-fix-mas_snoc_bimc-qos-port.patch @@ -0,0 +1,37 @@ +From 4efd84feb4acec66b6ba3000d6e169f3e542ca9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Mar 2024 20:42:33 +0100 +Subject: interconnect: qcom: qcm2290: Fix mas_snoc_bimc QoS port assignment + +From: Konrad Dybcio + +[ 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 +Link: https://lore.kernel.org/r/20240326-topic-rpm_icc_qos_cleanup-v1-2-357e736792be@linaro.org +Signed-off-by: Georgi Djakov +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..05f61d18cda --- /dev/null +++ b/queue-6.6/kbuild-fix-build-id-symlinks-to-installed-debug-vdso.patch @@ -0,0 +1,36 @@ +From 6f1d3fc1dc174ebbd6f5501deccc341d2632dd9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Dec 2023 17:18:33 +0900 +Subject: kbuild: fix build ID symlinks to installed debug VDSO files + +From: Masahiro Yamada + +[ 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 +Stable-dep-of: fc2f5f10f9bc ("s390/vdso: Create .build-id links for unstripped vdso files") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5d34331b05e --- /dev/null +++ b/queue-6.6/kbuild-unify-vdso_install-rules.patch @@ -0,0 +1,585 @@ +From 05cbe0332166d35c0e5675fc548ce02a64881a2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Oct 2023 19:54:35 +0900 +Subject: kbuild: unify vdso_install rules + +From: Masahiro Yamada + +[ 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 +Acked-by: Sven Schnelle # s390 +Reviewed-by: Nicolas Schier +Reviewed-by: Guo Ren +Acked-by: Helge Deller # parisc +Acked-by: Catalin Marinas +Acked-by: Russell King (Oracle) +Stable-dep-of: fc2f5f10f9bc ("s390/vdso: Create .build-id links for unstripped vdso files") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e6b5ee908dc --- /dev/null +++ b/queue-6.6/leds-pwm-disable-pwm-when-going-to-suspend.patch @@ -0,0 +1,48 @@ +From 006dc0cc9d8bb22dbb9e12db431c23223a11b1aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20240417153846.271751-2-u.kleine-koenig@pengutronix.de +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..73e09f9293a --- /dev/null +++ b/queue-6.6/libsubcmd-fix-parse-options-memory-leak.patch @@ -0,0 +1,61 @@ +From a5ed2fd4a0f8a8171dc5d67244260816bb42c24d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 May 2024 22:20:15 -0700 +Subject: libsubcmd: Fix parse-options memory leak + +From: Ian Rogers + +[ 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 +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Josh Poimboeuf +Cc: Kan Liang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240509052015.1914670-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 [] {", 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 index 00000000000..7795abc2f26 --- /dev/null +++ b/queue-6.6/loongarch-fix-callchain-parse-error-with-kernel-trac.patch @@ -0,0 +1,71 @@ +From 1a0acc8af7058fb614cd54502cbfb87b1f36b766 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 May 2024 12:24:18 +0800 +Subject: LoongArch: Fix callchain parse error with kernel tracepoint events + again + +From: Huacai Chen + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..3c7d2639ba5 --- /dev/null +++ b/queue-6.6/microblaze-remove-early-printk-call-from-cpuinfo-sta.patch @@ -0,0 +1,37 @@ +From 37c647c2b4fdd3e1ed48d1e46de675844e6068a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Apr 2024 10:27:21 +0200 +Subject: microblaze: Remove early printk call from cpuinfo-static.c + +From: Michal Simek + +[ 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 +Link: https://lore.kernel.org/r/2f10db506be8188fa07b6ec331caca01af1b10f8.1712824039.git.michal.simek@amd.com +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1e5e65eee4d --- /dev/null +++ b/queue-6.6/microblaze-remove-gcc-flag-for-non-existing-early_pr.patch @@ -0,0 +1,36 @@ +From 8a7b902f8b04317aa6f555320b05ec0681c33291 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Apr 2024 10:21:44 +0200 +Subject: microblaze: Remove gcc flag for non existing early_printk.c file + +From: Michal Simek + +[ 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 +Link: https://lore.kernel.org/r/5493467419cd2510a32854e2807bcd263de981a0.1712823702.git.michal.simek@amd.com +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9380de3a59e --- /dev/null +++ b/queue-6.6/misc-pvpanic-deduplicate-common-code.patch @@ -0,0 +1,328 @@ +From 020cdcbd234bab8e7b0a465342e63e8635f9dd39 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20231011-pvpanic-cleanup-v2-1-4b21d56f779f@weissschuh.net +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: ee59be35d7a8 ("misc/pvpanic-pci: register attributes via pci_driver") +Signed-off-by: Sasha Levin +--- + 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 "); + 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 "); + 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 + #include + #include + #include +@@ -26,6 +27,13 @@ MODULE_AUTHOR("Mihai Carabas "); + 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 index 00000000000..bb2cda1b87d --- /dev/null +++ b/queue-6.6/misc-pvpanic-pci-register-attributes-via-pci_driver.patch @@ -0,0 +1,48 @@ +From 5e4eee9befaab077cf4ff5aa091dc21e7c5f9f6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5e31bd0bbae --- /dev/null +++ b/queue-6.6/module-don-t-ignore-sysfs_create_link-failures.patch @@ -0,0 +1,155 @@ +From aaef27c7eded764bf04dab56a3508f9d21caa6b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Apr 2024 10:05:58 +0200 +Subject: module: don't ignore sysfs_create_link() failures + +From: Arnd Bergmann + +[ 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 +Reviewed-by: Luis Chamberlain +Link: https://lore.kernel.org/r/20240408080616.3911573-1-arnd@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..df655ced532 --- /dev/null +++ b/queue-6.6/ovl-add-helper-ovl_file_modified.patch @@ -0,0 +1,87 @@ +From f87db32c0cdadc7eea4a37560867da0bd0bb87e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Sep 2023 13:43:44 +0300 +Subject: ovl: add helper ovl_file_modified() + +From: Amir Goldstein + +[ Upstream commit c002728f608183449673818076380124935e6b9b ] + +A simple wrapper for updating ovl inode size/mtime, to conform +with ovl_file_accessed(). + +Signed-off-by: Amir Goldstein +Stable-dep-of: 7c98f7cb8fda ("remove call_{read,write}_iter() functions") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bfa011cbd50 --- /dev/null +++ b/queue-6.6/ovl-remove-upper-umask-handling-from-ovl_create_uppe.patch @@ -0,0 +1,39 @@ +From eefabf053819ee36e788a325c1d982817e0aa7e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 May 2024 20:35:57 +0200 +Subject: ovl: remove upper umask handling from ovl_create_upper() + +From: Miklos Szeredi + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e934fe4a31a --- /dev/null +++ b/queue-6.6/pci-edr-align-edr_port_dpc_enable_dsm-with-pci-firmw.patch @@ -0,0 +1,71 @@ +From 32d945bc6b46b361b7c9d212a97d44651a503d6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +[bhelgaas: split into two patches, update commit log] +Signed-off-by: Bjorn Helgaas +Tested-by: Satish Thatchanamurthy # one platform +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..82d04b17233 --- /dev/null +++ b/queue-6.6/pci-edr-align-edr_port_locate_dsm-with-pci-firmware-.patch @@ -0,0 +1,65 @@ +From a3b0fd0fe41d303ae61c2450c399947f61ef3434 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +[bhelgaas: split into two patches, update commit log] +Signed-off-by: Bjorn Helgaas +Tested-by: Satish Thatchanamurthy # one platform +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0eed8f0257e --- /dev/null +++ b/queue-6.6/pci-of_property-return-error-for-int_map-allocation-.patch @@ -0,0 +1,38 @@ +From 67d99de2108ef99e2096314e41ed275613abe845 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Mar 2024 18:57:29 +0800 +Subject: PCI: of_property: Return error for int_map allocation failure + +From: Duoming Zhou + +[ 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 +[bhelgaas: commit log] +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ab1e7e3fc74 --- /dev/null +++ b/queue-6.6/pci-tegra194-fix-probe-path-for-endpoint-mode.patch @@ -0,0 +1,48 @@ +From 14163ded942d908a806818b9b180bc822fc4cb70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: Jon Hunter +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..4f4efae0548 --- /dev/null +++ b/queue-6.6/pci-wait-for-link-training-0-before-starting-link-re.patch @@ -0,0 +1,82 @@ +From 07faec99bd306a67ff17c8013d46e0d1da15ab88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..632f96b2a7c --- /dev/null +++ b/queue-6.6/perf-annotate-fix-annotation_calc_lines-to-pass-corr.patch @@ -0,0 +1,81 @@ +From fc445b12febe61f4639b0b5244c87dc66358246a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Adrian Hunter +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240404175716.1225482-2-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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, ¬es->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 index 00000000000..4053f70fa51 --- /dev/null +++ b/queue-6.6/perf-annotate-get-rid-of-duplicate-group-option-item.patch @@ -0,0 +1,48 @@ +From 138e4f319cb2314e08af03f90b8273f0d1610928 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Mar 2024 15:43:12 -0700 +Subject: perf annotate: Get rid of duplicate --group option item + +From: Namhyung Kim + +[ 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 +Signed-off-by: Namhyung Kim +Cc: Adrian Hunter +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jin Yao +Cc: Jiri Olsa +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240322224313.423181-1-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9f7af7e8ec8 --- /dev/null +++ b/queue-6.6/perf-annotate-introduce-global-annotation_options.patch @@ -0,0 +1,210 @@ +From 7ddd424c59b675f91377b763da321eef7ed0ca2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 09:54:34 -0800 +Subject: perf annotate: Introduce global annotation_options + +From: Namhyung Kim + +[ 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 +Signed-off-by: Namhyung Kim +Cc: Adrian Hunter +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20231128175441.721579-2-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()") +Signed-off-by: Sasha Levin +--- + 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 + ++/* 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 index 00000000000..3b2054106d4 --- /dev/null +++ b/queue-6.6/perf-annotate-split-branch-stack-cycles-information-.patch @@ -0,0 +1,234 @@ +From b2dcf23780b6179d0eb4bfbb4dfd8bc4ca199826 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Adrian Hunter +Cc: Christophe JAILLET +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20231103191907.54531-2-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()") +Signed-off-by: Sasha Levin +--- + 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 = ¬es->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 index 00000000000..204fedf3dd5 --- /dev/null +++ b/queue-6.6/perf-annotate-use-global-annotation_options.patch @@ -0,0 +1,642 @@ +From 8f7406f148b75d1ceacb7e863e5dbaa1e0e2c9fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 09:54:37 -0800 +Subject: perf annotate: Use global annotation_options + +From: Namhyung Kim + +[ Upstream commit 41fd3cacd29f47f6b9c6474b27c5b0513786c4e9 ] + +Now it can directly use the global options and no need to pass it as an +argument. + +Reviewed-by: Ian Rogers +Signed-off-by: Namhyung Kim +Cc: Adrian Hunter +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20231128175441.721579-5-namhyung@kernel.org +[ Fixup build with GTK2=1 ] +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()") +Signed-off-by: Sasha Levin +--- + 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, ¬es->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 index 00000000000..a000e188cfb --- /dev/null +++ b/queue-6.6/perf-bench-internals-inject-build-id-fix-trap-divide.patch @@ -0,0 +1,55 @@ +From 510a7a9cb3d5046218eed8eaf114bb5a3b111b45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 0bf02a0d80427f26 ("perf bench: Add build-id injection benchmark") +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Link: https://lore.kernel.org/r/20240507065026.2652929-1-zhe.he@windriver.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9822b9709f4 --- /dev/null +++ b/queue-6.6/perf-bench-uprobe-remove-lib64-from-libc.so.6-binary.patch @@ -0,0 +1,48 @@ +From 6feb6de0bcddd02b17b5e461dcfa0c05e7d5128f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Apr 2024 21:09:10 -0700 +Subject: perf bench uprobe: Remove lib64 from libc.so.6 binary path + +From: Ian Rogers + +[ 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 +Acked-by: Jiri Olsa +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andrei Vagin +Cc: Ingo Molnar +Cc: Kan Liang +Cc: Kees Kook +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240406040911.1603801-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..af61b227964 --- /dev/null +++ b/queue-6.6/perf-daemon-fix-file-leak-in-daemon_session__control.patch @@ -0,0 +1,59 @@ +From c14a1f9ba027b95d7821fa8e307a9a08ebcb8269 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 May 2024 17:34:24 -0700 +Subject: perf daemon: Fix file leak in daemon_session__control + +From: Samasth Norway Ananda + +[ 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 +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240510003424.2016914-1-samasth.norway.ananda@oracle.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a47ab9717c8 --- /dev/null +++ b/queue-6.6/perf-docs-document-bpf-event-modifier.patch @@ -0,0 +1,48 @@ +From dd37882c5ee844cff813eb64bae6956a9e67cb2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Apr 2024 10:00:13 -0700 +Subject: perf docs: Document bpf event modifier + +From: Ian Rogers + +[ 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 +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Athira Rajeev +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Song Liu +Cc: Thomas Richter +Link: https://lore.kernel.org/r/20240416170014.985191-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..220ee09582b --- /dev/null +++ b/queue-6.6/perf-evlist-add-evlist__findnew_tracking_event-helpe.patch @@ -0,0 +1,108 @@ +From c88ce46ef805a1aa622e586f90949ddfd2784c56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Sep 2023 02:33:36 +0000 +Subject: perf evlist: Add evlist__findnew_tracking_event() helper + +From: Yang Jihong + +[ 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 +Acked-by: Adrian Hunter +Tested-by: Ravi Bangoria +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Anshuman Khandual +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Thomas Richter +Link: https://lore.kernel.org/r/20230904023340.12707-3-yangjihong1@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: 792bc998baf9 ("perf record: Fix debug message placement for test consumption") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..847cb0b424c --- /dev/null +++ b/queue-6.6/perf-intel-pt-fix-unassigned-instruction-op-discover.patch @@ -0,0 +1,73 @@ +From 85026bb9282a2593c3480c4f551aa48bf1cbc058 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Mar 2024 10:32:23 +0200 +Subject: perf intel-pt: Fix unassigned instruction op (discovered by + MemorySanitizer) + +From: Adrian Hunter + +[ 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 +Signed-off-by: Adrian Hunter +Tested-by: Ian Rogers +Cc: Jiri Olsa +Cc: Namhyung Kim +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..da8f83d6648 --- /dev/null +++ b/queue-6.6/perf-machine-thread-remove-exited-threads-by-default.patch @@ -0,0 +1,181 @@ +From aa5943e4c689dd47af5ce3976c039907b9f0e193 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Nov 2023 10:56:47 -0700 +Subject: perf machine thread: Remove exited threads by default + +From: Ian Rogers + +[ 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 +Signed-off-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Athira Jajeev +Cc: Changbin Du +Cc: Colin Ian King +Cc: Dmitrii Dolgov <9erthalion6@gmail.com> +Cc: German Gomez +Cc: Huacai Chen +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: K Prateek Nayak +Cc: Kajol Jain +Cc: Kan Liang +Cc: Leo Yan +Cc: Li Dong +Cc: Liam Howlett +Cc: Mark Rutland +Cc: Masami Hiramatsu +Cc: Miguel Ojeda +Cc: Ming Wang +Cc: Namhyung Kim +Cc: Nick Terrell +Cc: Paolo Bonzini +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Sandipan Das +Cc: Sean Christopherson +Cc: Steinar H. Gunderson +Cc: Vincent Whitchurch +Cc: Wenyu Liu +Cc: Yang Jihong +Link: https://lore.kernel.org/r/20231102175735.2272696-6-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9bafec3b965 --- /dev/null +++ b/queue-6.6/perf-maps-move-symbol-maps-functions-to-maps.c.patch @@ -0,0 +1,634 @@ +From 8776761fe4c1cbbdb3f9c216aed63de509f6649e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Nov 2023 14:08:25 -0800 +Subject: perf maps: Move symbol maps functions to maps.c + +From: Ian Rogers + +[ Upstream commit 0f6ab6a3fb7e380a1277f8288f315724ed517114 ] + +Move the find and certain other symbol maps__* functions to maps.c for +better abstraction. + +Signed-off-by: Ian Rogers +Acked-by: Namhyung Kim +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Athira Jajeev +Cc: Changbin Du +Cc: Colin Ian King +Cc: Dmitrii Dolgov <9erthalion6@gmail.com> +Cc: German Gomez +Cc: Guilherme Amadio +Cc: Huacai Chen +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: K Prateek Nayak +Cc: Kajol Jain +Cc: Kan Liang +Cc: Leo Yan +Cc: Li Dong +Cc: Liam Howlett +Cc: Mark Rutland +Cc: Masami Hiramatsu (Google) +Cc: Miguel Ojeda +Cc: Ming Wang +Cc: Nick Terrell +Cc: Paolo Bonzini +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Sandipan Das +Cc: Sean Christopherson +Cc: Steinar H. Gunderson +Cc: Vincent Whitchurch +Cc: Wenyu Liu +Cc: Yang Jihong +Link: https://lore.kernel.org/r/20231127220902.1315692-14-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: 25626e19ae6d ("perf symbols: Fix ownership of string in dso__load_vmlinux()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..448fdb853e3 --- /dev/null +++ b/queue-6.6/perf-pmu-assume-sysfs-events-are-always-the-same-cas.patch @@ -0,0 +1,126 @@ +From db4d1851701d20df07c47e81fcef09deb86df93b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 May 2024 14:35:07 -0700 +Subject: perf pmu: Assume sysfs events are always the same case + +From: Ian Rogers + +[ 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 +Signed-off-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Bjorn Helgaas +Cc: Ingo Molnar +Cc: James Clark +Cc: Jing Zhang +Cc: Jiri Olsa +Cc: Jonathan Corbet +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Randy Dunlap +Cc: Ravi Bangoria +Cc: Thomas Richter +Link: https://lore.kernel.org/r/20240502213507.2339733-7-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1cd94a4edd9 --- /dev/null +++ b/queue-6.6/perf-pmu-compat-supports-regular-expression-matching.patch @@ -0,0 +1,110 @@ +From 7412db8257d232300a3fd93c28bc7b5291268542 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Sep 2023 13:59:45 +0800 +Subject: perf pmu: "Compat" supports regular expression matching identifiers + +From: Jing Zhang + +[ 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 +Reviewed-by: Ian Rogers +Tested-by: Ian Rogers +Cc: James Clark +Cc: Will Deacon +Cc: Leo Yan +Cc: Mike Leach +Cc: Shuai Xue +Cc: Zhuo Song +Cc: John Garry +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 +Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately") +Signed-off-by: Sasha Levin +--- + 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 + + 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 index 00000000000..737b947812c --- /dev/null +++ b/queue-6.6/perf-pmu-count-sys-and-cpuid-json-events-separately.patch @@ -0,0 +1,202 @@ +From 4b4468c46d40c7374636e4324434ad6076f17ff8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 May 2024 17:36:01 -0700 +Subject: perf pmu: Count sys and cpuid JSON events separately + +From: Ian Rogers + +[ 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 +Signed-off-by: Ian Rogers +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: John Garry +Cc: Kan Liang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240511003601.2666907-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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//events. */ ++ EVENT_SRC_SYSFS, ++ /* An event loaded from a CPUID matched json file. */ ++ EVENT_SRC_CPU_JSON, ++ /* ++ * An event loaded from a /sys/devices//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 index 00000000000..542aebd8bb2 --- /dev/null +++ b/queue-6.6/perf-pmu-move-pmu__find_core_pmu-to-pmus.c.patch @@ -0,0 +1,198 @@ +From 033b5433f23258485ef92495ca7d6b6e1bbe163e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 16:33:48 +0100 +Subject: perf pmu: Move pmu__find_core_pmu() to pmus.c + +From: James Clark + +[ 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 +Reviewed-by: Ian Rogers +Reviewed-by: John Garry +Cc: Ravi Bangoria +Cc: Eduard Zingerman +Cc: Will Deacon +Cc: Leo Yan +Cc: Mike Leach +Cc: Jing Zhang +Cc: Haixin Yu +Cc: Kan Liang +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 +Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#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 index 00000000000..fe03efcd7d0 --- /dev/null +++ b/queue-6.6/perf-probe-add-missing-libgen.h-header-needed-for-us.patch @@ -0,0 +1,53 @@ +From 74fcaddc6d1c6a2ca131224e5cbadab427c9826f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Adrian Hunter +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Namhyung Kim +Link: https://lore.kernel.org/lkml/ +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +-- +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 index 00000000000..6bdaa9369eb --- /dev/null +++ b/queue-6.6/perf-record-delete-session-after-stopping-sideband-t.patch @@ -0,0 +1,83 @@ +From d313e8e6b6b0467ae2a2e861c47bad3d2e927d26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 23:46:36 -0800 +Subject: perf record: Delete session after stopping sideband thread + +From: Ian Rogers + +[ 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 +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Athira Rajeev +Cc: Christian Brauner +Cc: Disha Goel +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Kajol Jain +Cc: Kan Liang +Cc: K Prateek Nayak +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Song Liu +Cc: Tim Chen +Cc: Yicong Yang +Link: https://lore.kernel.org/r/20240301074639.2260708-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b8bde8f77ca --- /dev/null +++ b/queue-6.6/perf-record-fix-debug-message-placement-for-test-con.patch @@ -0,0 +1,57 @@ +From 958d96e8b1a3c7a7adc5cbba51cebeb9fff48f7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Apr 2024 10:54:47 +0300 +Subject: perf record: Fix debug message placement for test consumption + +From: Adrian Hunter + +[ 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 +Signed-off-by: Adrian Hunter +Tested-by: Arnaldo Carvalho de Melo +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Namhyung Kim +Link: https://lore.kernel.org/r/20240411075447.17306-1-adrian.hunter@intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1b4bb1fc879 --- /dev/null +++ b/queue-6.6/perf-record-lazy-load-kernel-symbols.patch @@ -0,0 +1,129 @@ +From 2ac5c718173e7a88dc3c2ab2ef77339cb40e3550 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Nov 2023 10:56:44 -0700 +Subject: perf record: Lazy load kernel symbols + +From: Ian Rogers + +[ 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 +Signed-off-by: Ian Rogers +Acked-by: Namhyung Kim +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Athira Jajeev +Cc: Changbin Du +Cc: Colin Ian King +Cc: Dmitrii Dolgov <9erthalion6@gmail.com> +Cc: German Gomez +Cc: Huacai Chen +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: K Prateek Nayak +Cc: Kajol Jain +Cc: Kan Liang +Cc: Leo Yan +Cc: Li Dong +Cc: Liam Howlett +Cc: Mark Rutland +Cc: Masami Hiramatsu +Cc: Miguel Ojeda +Cc: Ming Wang +Cc: Nick Terrell +Cc: Paolo Bonzini +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Sandipan Das +Cc: Sean Christopherson +Cc: Steinar H. Gunderson +Cc: Vincent Whitchurch +Cc: Wenyu Liu +Cc: Yang Jihong +Link: https://lore.kernel.org/r/20231102175735.2272696-3-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()") +Signed-off-by: Sasha Levin +--- + 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 []", + 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 index 00000000000..9a310ce313e --- /dev/null +++ b/queue-6.6/perf-record-move-setting-tracking-events-before-reco.patch @@ -0,0 +1,272 @@ +From 4c5f79c4f9c3168f0f72899a5b41905bca175657 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Sep 2023 02:33:37 +0000 +Subject: perf record: Move setting tracking events before + record__init_thread_masks() + +From: Yang Jihong + +[ 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 + + 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 + + +'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 +Acked-by: Adrian Hunter +Tested-by: Ravi Bangoria +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Anshuman Khandual +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Thomas Richter +Link: https://lore.kernel.org/r/20230904023340.12707-4-yangjihong1@huawei.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: 792bc998baf9 ("perf record: Fix debug message placement for test consumption") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..65449e97978 --- /dev/null +++ b/queue-6.6/perf-report-avoid-segv-in-report__setup_sample_type.patch @@ -0,0 +1,47 @@ +From 2b3bf735077fcfa01a14b4e1d96caaac0faed4e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 20:53:00 -0700 +Subject: perf report: Avoid SEGV in report__setup_sample_type() + +From: Ian Rogers + +[ 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 +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240508035301.1554434-4-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..31c46de53d5 --- /dev/null +++ b/queue-6.6/perf-report-convert-to-the-global-annotation_options.patch @@ -0,0 +1,150 @@ +From 4aba2b1c5d353adcc6523106ba83ed2b1ea96591 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 09:54:35 -0800 +Subject: perf report: Convert to the global annotation_options + +From: Namhyung Kim + +[ Upstream commit 14953f038d6b30e3dc9d1aa4d4584ac505e5a8ec ] + +Use the global option and drop the local copy. + +Reviewed-by: Ian Rogers +Signed-off-by: Namhyung Kim +Cc: Adrian Hunter +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20231128175441.721579-3-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..be0aca7c59d --- /dev/null +++ b/queue-6.6/perf-stat-do-not-fail-on-metrics-on-s390-z-vm-system.patch @@ -0,0 +1,176 @@ +From dc6f1a0e4ade3ae4e7d6e2cf74822a8f76e8ed8a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Ian Rogers +Signed-off-by: Thomas Richter +Cc: Heiko Carstens +Cc: Namhyung Kim +Cc: Sumanth Korikkar +Cc: Sven Schnelle +Cc: Vasily Gorbik +Link: https://lore.kernel.org/r/20240404064806.1362876-2-tmricht@linux.ibm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..198cad60cbb --- /dev/null +++ b/queue-6.6/perf-stat-don-t-display-metric-header-for-non-leader.patch @@ -0,0 +1,90 @@ +From 26b461b5e22163a9d8bf3f26984fd168747526b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Kaige Ye +Cc: Kan Liang +Cc: K Prateek Nayak +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Yicong Yang +Link: https://lore.kernel.org/r/20240510051309.2452468-1-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..205ab6d1c0e --- /dev/null +++ b/queue-6.6/perf-symbols-fix-ownership-of-string-in-dso__load_vm.patch @@ -0,0 +1,91 @@ +From 7fdeee90fbe6bc54656a6872f20dba60d87507d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 15:12:08 +0100 +Subject: perf symbols: Fix ownership of string in dso__load_vmlinux() + +From: James Clark + +[ 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 +Signed-off-by: James Clark +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Athira Rajeev +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240507141210.195939-5-james.clark@arm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..18a51fb6705 --- /dev/null +++ b/queue-6.6/perf-test-add-a-test-for-strcmp_cpuid_str-expression.patch @@ -0,0 +1,112 @@ +From 4f0d6f155e16e078677a79d54edee789f5829f61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Sep 2023 10:50:46 +0100 +Subject: perf test: Add a test for strcmp_cpuid_str() expression + +From: James Clark + +[ 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 +Signed-off-by: James Clark +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Chen Zhongjin +Cc: Eduard Zingerman +Cc: Haixin Yu +Cc: Ingo Molnar +Cc: Jing Zhang +Cc: Jiri Olsa +Cc: John Garry +Cc: Kajol Jain +Cc: Kan Liang +Cc: Leo Yan +Cc: Liam Howlett +Cc: Madhavan Srinivasan +Cc: Mark Rutland +Cc: Mike Leach +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Will Deacon +Cc: Yang Jihong +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 +Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + + 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 index 00000000000..f1fd1405413 --- /dev/null +++ b/queue-6.6/perf-test-shell-arm_coresight-increase-buffer-size-f.patch @@ -0,0 +1,58 @@ +From 0536e7f78d1cd83a4e2291059e3fa75c720176eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: James Clark +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Mike Leach +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Suzuki Poulouse +Link: https://lore.kernel.org/r/20240326113749.257250-1-james.clark@arm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..029ab36e6b5 --- /dev/null +++ b/queue-6.6/perf-tests-apply-attributes-to-all-events-in-object-.patch @@ -0,0 +1,70 @@ +From e50e5d8bef0881fd8a468045fad48be1ae1263d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: James Clark +Acked-by: Namhyung Kim +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Athira Rajeev +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Spoorthy S +Link: https://lore.kernel.org/r/20240410103458.813656-3-james.clark@arm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b99faa2005b --- /dev/null +++ b/queue-6.6/perf-tests-make-test-data-symbol-more-robust-on-neov.patch @@ -0,0 +1,69 @@ +From 4dca0165c364d0c3c5e5d99b72d7d0953af4cbc3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Apr 2024 11:34:52 +0100 +Subject: perf tests: Make "test data symbol" more robust on Neoverse N1 + +From: James Clark + +[ 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 +Signed-off-by: James Clark +Acked-by: Namhyung Kim +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Athira Rajeev +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Peter Zijlstra +Cc: Spoorthy S +Link: https://lore.kernel.org/r/20240410103458.813656-2-james.clark@arm.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..721562a5fb3 --- /dev/null +++ b/queue-6.6/perf-thread-fixes-to-thread__new-related-to-initiali.patch @@ -0,0 +1,80 @@ +From 83d16e13f9f534a6e9077f58a49501f83586fed4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 20:53:01 -0700 +Subject: perf thread: Fixes to thread__new() related to initializing comm + +From: Ian Rogers + +[ 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 +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240508035301.1554434-5-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..20a6da9cadd --- /dev/null +++ b/queue-6.6/perf-tools-add-use-pmu-reverse-lookup-from-config-to.patch @@ -0,0 +1,149 @@ +From 043c6ac0b1810a9c81b9a6820bcc5f770a2a3a23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Mar 2024 16:19:15 -0800 +Subject: perf tools: Add/use PMU reverse lookup from config to name + +From: Ian Rogers + +[ 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 +Tested-by: Arnaldo Carvalho de Melo +Tested-by: Kan Liang +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Yang Jihong +Link: https://lore.kernel.org/r/20240308001915.4060155-7-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f93bd8a846e --- /dev/null +++ b/queue-6.6/perf-tools-use-pmus-to-describe-type-from-attribute.patch @@ -0,0 +1,161 @@ +From 241d6cad1ca1ec68490c6fc79bebe8fd5f12fcfa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Mar 2024 16:19:14 -0800 +Subject: perf tools: Use pmus to describe type from attribute + +From: Ian Rogers + +[ 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 +Tested-by: Arnaldo Carvalho de Melo +Tested-by: Kan Liang +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Yang Jihong +Link: https://lore.kernel.org/r/20240308001915.4060155-6-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: d9c5f5f94c2d ("perf pmu: Count sys and cpuid JSON events separately") +Signed-off-by: Sasha Levin +--- + 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 + #include + #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 index 00000000000..c75ec8cf4ac --- /dev/null +++ b/queue-6.6/perf-top-convert-to-the-global-annotation_options.patch @@ -0,0 +1,188 @@ +From d30a20b4323b481d1a84f60de8fe221a884bf246 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 09:54:36 -0800 +Subject: perf top: Convert to the global annotation_options + +From: Namhyung Kim + +[ Upstream commit c9a21a872c69032cb9a94ebc171649c0c28141d7 ] + +Use the global option and drop the local copy. + +Reviewed-by: Ian Rogers +Signed-off-by: Namhyung Kim +Cc: Adrian Hunter +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20231128175441.721579-4-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: aaf494cf483a ("perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a018ff4594b --- /dev/null +++ b/queue-6.6/perf-ui-browser-avoid-segv-on-title.patch @@ -0,0 +1,46 @@ +From 90f87e67a55f547f9dc9f5a05b602c8c42f55677 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 20:52:58 -0700 +Subject: perf ui browser: Avoid SEGV on title + +From: Ian Rogers + +[ 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 +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20240508035301.1554434-2-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b89ba6fb52c --- /dev/null +++ b/queue-6.6/perf-ui-browser-don-t-save-pointer-to-stack-memory.patch @@ -0,0 +1,143 @@ +From 37b0adfd2117bcf3f56c4c1ebb8c2d209046c9eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 11:35:38 -0700 +Subject: perf ui browser: Don't save pointer to stack memory + +From: Ian Rogers + +[ 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 +Cc: Adrian Hunter +Cc: Alexander Shishkin +Cc: Andi Kleen +Cc: Athira Rajeev +Cc: Ben Gainey +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Kajol Jain +Cc: Kan Liang +Cc: K Prateek Nayak +Cc: Li Dong +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Oliver Upton +Cc: Paran Lee +Cc: Peter Zijlstra +Cc: Ravi Bangoria +Cc: Sun Haiyong +Cc: Tim Chen +Cc: Yanteng Si +Cc: Yicong Yang +Link: https://lore.kernel.org/r/20240507183545.1236093-2-irogers@google.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e098e745d84 --- /dev/null +++ b/queue-6.6/phy-qcom-qmp-combo-fix-duplicate-return-in-qmp_v4_co.patch @@ -0,0 +1,38 @@ +From 43e494c60bee0a54ad8fb776161ec6ffd35953b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Konrad Dybcio +Reviewed-by: Abhinav Kumar +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..40f8790f9ba --- /dev/null +++ b/queue-6.6/pinctrl-qcom-pinctrl-sm7150-fix-sdc1-and-ufs-special.patch @@ -0,0 +1,81 @@ +From 3ef3c1744950befa4e82a96744733f61659b8b9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Apr 2024 23:32:45 +0300 +Subject: pinctrl: qcom: pinctrl-sm7150: Fix sdc1 and ufs special pins regs + +From: Danila Tikhonov + +[ 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 +Message-ID: <20240423203245.188480-1-danila@jiaxyga.com> +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5b9a36e5e96 --- /dev/null +++ b/queue-6.6/ppdev-add-an-error-check-in-register_device.patch @@ -0,0 +1,72 @@ +From 15a8e21e6489bbaafde5290e71bea09b60eec446 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Apr 2024 16:38:40 +0800 +Subject: ppdev: Add an error check in register_device + +From: Huai-Yuan Liu + +[ 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 +Link: https://lore.kernel.org/r/20240412083840.234085-1-qq810974084@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..fa7234c1c51 --- /dev/null +++ b/queue-6.6/ppdev-remove-usage-of-the-deprecated-ida_simple_xx-a.patch @@ -0,0 +1,57 @@ +From a8a45d9c8085707ebe7744e9a8d97c1e7f6a71ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 06:01:47 +0100 +Subject: ppdev: Remove usage of the deprecated ida_simple_xx() API + +From: Christophe JAILLET + +[ 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 +Link: https://lore.kernel.org/r/ba9da12fdd5cdb2c28180b7160af5042447d803f.1702962092.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: fbf740aeb86a ("ppdev: Add an error check in register_device") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..848198bea86 --- /dev/null +++ b/queue-6.6/pwm-rename-pwm_apply_state-to-pwm_apply_might_sleep.patch @@ -0,0 +1,724 @@ +From c0b445a571d62ad3b49e04d9bd08f40dbc912ef6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Guenter Roeck +Acked-by: Mark Brown +Acked-by: Dmitry Torokhov # for input +Acked-by: Hans de Goede +Acked-by: Jani Nikula +Acked-by: Lee Jones +Signed-off-by: Sean Young +Signed-off-by: Thierry Reding +Stable-dep-of: 974afccd3794 ("leds: pwm: Disable PWM when going to suspend") +Signed-off-by: Sasha Levin +--- + 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 +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 index 00000000000..8d6230a128c --- /dev/null +++ b/queue-6.6/reapply-arm64-fpsimd-implement-lazy-restore-for-kern.patch @@ -0,0 +1,74 @@ +From 87a7238bf9d1b72ed2f9a136b04d22d6e5db2781 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 11:53:05 +0100 +Subject: Reapply "arm64: fpsimd: Implement lazy restore for kernel mode + FPSIMD" + +From: Will Deacon + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..da9bae8a145 --- /dev/null +++ b/queue-6.6/remove-call_-read-write-_iter-functions.patch @@ -0,0 +1,205 @@ +From 3c0ff2d825d714cd6539a14a5cefc8e9d20665d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Aug 2023 17:13:18 +0200 +Subject: remove call_{read,write}_iter() functions + +From: Miklos Szeredi + +[ 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 +Signed-off-by: Miklos Szeredi +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..01f50dd5911 --- /dev/null +++ b/queue-6.6/revert-arm64-fpsimd-implement-lazy-restore-for-kerne.patch @@ -0,0 +1,75 @@ +From b6fb5d8556512e9b817e4aa1fc270749c13feea4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 May 2024 12:55:55 +0100 +Subject: Revert "arm64: fpsimd: Implement lazy restore for kernel mode FPSIMD" + +From: Will Deacon + +[ 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 +Link: https://lore.kernel.org/all/D1B7GPIR9K1E.5JFV37G0YTIF@shadowice.org/ +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6a62f0ef724 --- /dev/null +++ b/queue-6.6/risc-v-enable-cbo.zero-in-usermode.patch @@ -0,0 +1,169 @@ +From 225e330455f209634733314a13070234294a4e02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Sep 2023 15:15:21 +0200 +Subject: RISC-V: Enable cbo.zero in usermode + +From: Andrew Jones + +[ 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 +Reviewed-by: Conor Dooley +Link: https://lore.kernel.org/r/20230918131518.56803-10-ajones@ventanamicro.com +Signed-off-by: Palmer Dabbelt +Stable-dep-of: 58661a30f1bc ("riscv: Flush the instruction cache during SMP bringup") +Signed-off-by: Sasha Levin +--- + 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 ++#include + + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++ ++#include + #include + #include + #include +@@ -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 index 00000000000..43e5d4a55fb --- /dev/null +++ b/queue-6.6/riscv-dts-starfive-visionfive-2-remove-non-existing-.patch @@ -0,0 +1,91 @@ +From 6739a77ecfc1fe901f2b68421f1c80fd398e7a9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Apr 2024 14:50:32 +0200 +Subject: riscv: dts: starfive: visionfive 2: Remove non-existing TDM hardware + +From: Hannah Peuckmann + +[ 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 +Reviewed-by: Emil Renner Berthing +Tested-by: Emil Renner Berthing +Signed-off-by: Conor Dooley +Signed-off-by: Sasha Levin +--- + .../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 = ; +- bias-pull-up; +- drive-strength = <2>; +- input-disable; +- input-schmitt-disable; +- slew-rate = <0>; +- }; +- +- rx-pins { +- pinmux = ; +- input-enable; +- }; +- +- sync-pins { +- pinmux = ; +- input-enable; +- }; +- +- pcmclk-pins { +- pinmux = ; +- input-enable; +- }; +- }; +- + uart0_pins: uart0-0 { + tx-pins { + pinmux = ; +- 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 index 00000000000..39de2451bca --- /dev/null +++ b/queue-6.6/riscv-flush-the-instruction-cache-during-smp-bringup.patch @@ -0,0 +1,55 @@ +From fbf9c4c0b605c3d8182cc3f2e416ef2f3f89b44a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Mar 2024 21:49:42 -0700 +Subject: riscv: Flush the instruction cache during SMP bringup + +From: Samuel Holland + +[ 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 +Signed-off-by: Samuel Holland +Link: https://lore.kernel.org/r/20240327045035.368512-2-samuel.holland@sifive.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + 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 + #include + +-#include ++#include + #include + #include + #include +@@ -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 index 00000000000..0bb6e4909cf --- /dev/null +++ b/queue-6.6/s390-boot-remove-alt_stfle_fac_list-from-decompresso.patch @@ -0,0 +1,49 @@ +From 672554a1b3e14134d8afd10d929e53c8dae72808 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 May 2024 09:20:27 +0200 +Subject: s390/boot: Remove alt_stfle_fac_list from decompressor + +From: Sven Schnelle + +[ 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 +Signed-off-by: Sven Schnelle +Signed-off-by: Heiko Carstens +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..828731b1999 --- /dev/null +++ b/queue-6.6/s390-ipl-fix-incorrect-initialization-of-len-fields-.patch @@ -0,0 +1,42 @@ +From 473c01f8e3b4a8cc34ab8a48a116416cc0502fef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Alexander Egorenkov +Signed-off-by: Alexander Gordeev +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f2294a45d20 --- /dev/null +++ b/queue-6.6/s390-ipl-fix-incorrect-initialization-of-nvme-dump-b.patch @@ -0,0 +1,43 @@ +From f1764baf7970d08cc5524d634580e9223bd328d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 May 2024 12:41:26 +0200 +Subject: s390/ipl: Fix incorrect initialization of nvme dump block + +From: Alexander Egorenkov + +[ 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 +Signed-off-by: Alexander Egorenkov +Signed-off-by: Alexander Gordeev +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..635b7e5b502 --- /dev/null +++ b/queue-6.6/s390-vdso-create-.build-id-links-for-unstripped-vdso.patch @@ -0,0 +1,45 @@ +From ac0d21783d63aa65f4b72d130749bb64118be4ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Apr 2024 17:02:53 +0200 +Subject: s390/vdso: Create .build-id links for unstripped vdso files + +From: Jens Remus + +[ 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 +Signed-off-by: Alexander Gordeev +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6ab74064408 --- /dev/null +++ b/queue-6.6/s390-vdso-generate-unwind-information-for-c-modules.patch @@ -0,0 +1,55 @@ +From 1bcc6dbdbc10db3e3c582d6cadd977632abe1ce6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Apr 2024 17:02:52 +0200 +Subject: s390/vdso: Generate unwind information for C modules + +From: Jens Remus + +[ 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 +Signed-off-by: Alexander Gordeev +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..951a4667e8e --- /dev/null +++ b/queue-6.6/s390-vdso-use-standard-stack-frame-layout.patch @@ -0,0 +1,56 @@ +From 072e03b0e9afc4357c04699f0e7a7be78ef43895 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Apr 2024 14:28:43 +0200 +Subject: s390/vdso: Use standard stack frame layout + +From: Heiko Carstens + +[ 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 +Signed-off-by: Heiko Carstens +Signed-off-by: Alexander Gordeev +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..617f430c5d0 --- /dev/null +++ b/queue-6.6/s390-vdso64-filter-out-munaligned-symbols-flag-for-v.patch @@ -0,0 +1,56 @@ +From 662c1f2baa46ad30bcc8f8e92ddbd885de95d2a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Feb 2024 14:27:31 +0100 +Subject: s390/vdso64: filter out munaligned-symbols flag for vdso + +From: Sumanth Korikkar + +[ 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 +Signed-off-by: Sumanth Korikkar +Link: https://lore.kernel.org/r/20240219132734.22881-2-sumanthk@linux.ibm.com +Signed-off-by: Heiko Carstens +Stable-dep-of: 10f705253651 ("s390/vdso: Generate unwind information for C modules") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6bb3be06a52 --- /dev/null +++ b/queue-6.6/serial-max3100-fix-bitwise-types.patch @@ -0,0 +1,53 @@ +From 2e8ad634aae61ced99ebf90af123db849227cec2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Apr 2024 22:50:30 +0300 +Subject: serial: max3100: Fix bitwise types + +From: Andy Shevchenko + +[ 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 +Link: https://lore.kernel.org/r/20240402195306.269276-4-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++ ++#include + + #include + +@@ -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 index 00000000000..8a0ef02e87d --- /dev/null +++ b/queue-6.6/serial-max3100-lock-port-lock-when-calling-uart_hand.patch @@ -0,0 +1,66 @@ +From 85cfbbed1c9f5a8c8e6728d435e3147cb0c0c121 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Apr 2024 22:50:28 +0300 +Subject: serial: max3100: Lock port->lock when calling + uart_handle_cts_change() + +From: Andy Shevchenko + +[ 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 +Link: https://lore.kernel.org/r/20240402195306.269276-2-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bb92bf7e74a --- /dev/null +++ b/queue-6.6/serial-max3100-update-uart_driver_registered-on-driv.patch @@ -0,0 +1,73 @@ +From 2b8a64f5a6722eff6588fd3d1e7b931a98f21803 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Hugo Villeneuve +Link: https://lore.kernel.org/r/20240402195306.269276-3-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..35dd8f8e6fa --- /dev/null +++ b/queue-6.6/serial-sc16is7xx-add-proper-sched.h-include-for-sche.patch @@ -0,0 +1,44 @@ +From 4819d331b3684a94497b0a3f84a9f72b753b85fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Apr 2024 11:42:49 -0400 +Subject: serial: sc16is7xx: add proper sched.h include for sched_set_fifo() + +From: Hugo Villeneuve + +[ 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 +Link: https://lore.kernel.org/r/20240409154253.3043822-2-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -25,7 +26,6 @@ + #include + #include + #include +-#include + + #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 index 00000000000..1f65faab88a --- /dev/null +++ b/queue-6.6/serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch @@ -0,0 +1,96 @@ +From 78095fcc3bc9b620e9d11f61380b4d75c75b11e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Apr 2024 16:04:30 -0400 +Subject: serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using + prescaler + +From: Hugo Villeneuve + +[ 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 +Reviewed-by: Jiri Slaby +Link: https://lore.kernel.org/r/20240430200431.4102923-1-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9711441d682 --- /dev/null +++ b/queue-6.6/serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch @@ -0,0 +1,39 @@ +From 0e7ed75410858e06e83d7a5972d7198fd14f5baf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Dec 2023 18:18:19 -0500 +Subject: serial: sc16is7xx: replace hardcoded divisor value with BIT() macro + +From: Hugo Villeneuve + +[ 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 +Suggested-by: Andy Shevchenko +Signed-off-by: Hugo Villeneuve +Link: https://lore.kernel.org/r/20231221231823.2327894-13-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 8492bd91aa05 ("serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..808d9f00091 --- /dev/null +++ b/queue-6.6/serial-sh-sci-protect-invalidating-rxdma-on-shutdown.patch @@ -0,0 +1,47 @@ +From 2209d59fec998d2808104e4599b979f78495d545 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 May 2024 13:40:17 +0200 +Subject: serial: sh-sci: protect invalidating RXDMA on shutdown + +From: Wolfram Sang + +[ 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 +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 +Link: https://lore.kernel.org/r/20240506114016.30498-7-wsa+renesas@sang-engineering.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/series b/queue-6.6/series index 5e9dddb866e..649a367f837 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -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 index 00000000000..5179e9bc58d --- /dev/null +++ b/queue-6.6/soundwire-cadence-fix-invalid-pdi-offset.patch @@ -0,0 +1,48 @@ +From bf80ff44be806a9356e3fe6c06964248ccabd901 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Mar 2024 09:01:16 +0000 +Subject: soundwire: cadence: fix invalid PDI offset + +From: Pierre-Louis Bossart + +[ 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 +Reviewed-by: Rander Wang +Signed-off-by: Bard Liao +Link: https://lore.kernel.org/r/20240326090122.1051806-2-yung-chuan.liao@linux.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..cf55d485676 --- /dev/null +++ b/queue-6.6/splice-remove-permission-hook-from-iter_file_splice_.patch @@ -0,0 +1,72 @@ +From 9519e9d1e625d4f01b3c8a1c32042e3f5da53b0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Nov 2023 18:51:44 +0100 +Subject: splice: remove permission hook from iter_file_splice_write() + +From: Amir Goldstein + +[ 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 +Reviewed-by: Josef Bacik +Signed-off-by: Amir Goldstein +Link: https://lore.kernel.org/r/20231122122715.2561213-6-amir73il@gmail.com +Signed-off-by: Christian Brauner +Stable-dep-of: 7c98f7cb8fda ("remove call_{read,write}_iter() functions") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1322dc41b8a --- /dev/null +++ b/queue-6.6/stm-class-fix-a-double-free-in-stm_register_device.patch @@ -0,0 +1,57 @@ +From c40f1b3c8771aac0d38b9769b916c380dba14f74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Apr 2024 16:01:05 +0300 +Subject: stm class: Fix a double free in stm_register_device() + +From: Dan Carpenter + +[ 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 +Reviewed-by: Amelie Delaunay +Reviewed-by: Andy Shevchenko +Signed-off-by: Alexander Shishkin +Link: https://lore.kernel.org/r/20240429130119.1518073-2-alexander.shishkin@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c14065dac59 --- /dev/null +++ b/queue-6.6/udf-convert-udf_expand_file_adinicb-to-use-a-folio.patch @@ -0,0 +1,85 @@ +From 5bff92a3c37ffb398a787fd5669e61ce40d9710f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Apr 2024 16:04:09 +0100 +Subject: udf: Convert udf_expand_file_adinicb() to use a folio + +From: Matthew Wilcox (Oracle) + +[ Upstream commit db6754090a4f99c67e05ae6b87343ba6e013531f ] + +Use the folio APIs throughout this function. + +Signed-off-by: Matthew Wilcox (Oracle) +Fixes: 1eeceaec794e ("udf: Convert udf_expand_file_adinicb() to avoid kmap_atomic()") +Signed-off-by: Jan Kara +Message-Id: <20240417150416.752929-4-willy@infradead.org> +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d11961422f9 --- /dev/null +++ b/queue-6.6/udf-remove-gfp_nofs-allocation-in-udf_expand_file_ad.patch @@ -0,0 +1,39 @@ +From df0abc84020518da4e1437d3d088edaa59e484f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jan 2024 11:15:43 +0100 +Subject: udf: Remove GFP_NOFS allocation in udf_expand_file_adinicb() + +From: Jan Kara + +[ 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 +Stable-dep-of: db6754090a4f ("udf: Convert udf_expand_file_adinicb() to use a folio") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0493df74615 --- /dev/null +++ b/queue-6.6/usb-fotg210-add-missing-kernel-doc-description.patch @@ -0,0 +1,40 @@ +From 6b35b6b35f2eab42d6f460e584a3ab999ed03f5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 May 2024 18:26:22 +0300 +Subject: usb: fotg210: Add missing kernel doc description + +From: Andy Shevchenko + +[ 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 +Reviewed-by: Linus Walleij +Link: https://lore.kernel.org/r/20240510152641.2421298-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..88ada2e230b --- /dev/null +++ b/queue-6.6/usb-gadget-u_audio-clear-uac-pointer-when-freed.patch @@ -0,0 +1,40 @@ +From 6f223316238081c613ee78ba1c423668fe5f8c34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Apr 2024 15:20:20 +0000 +Subject: usb: gadget: u_audio: Clear uac pointer when freed. + +From: Chris Wulff + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..546d8a755af --- /dev/null +++ b/queue-6.6/usb-gadget-u_audio-fix-race-condition-use-of-control.patch @@ -0,0 +1,110 @@ +From 34d6b8ffa32141b046c0c4a67ca2cc2c4d9adb80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e7375516e0f --- /dev/null +++ b/queue-6.6/usb-typec-ucsi-always-register-a-link-to-usb-pd-devi.patch @@ -0,0 +1,52 @@ +From 2e15f48fd3bdd4fe173ad481ef8c4e52e5ce023b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Mar 2024 08:15:36 +0200 +Subject: usb: typec: ucsi: always register a link to USB PD device + +From: Dmitry Baryshkov + +[ 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 +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20240329-qcom-ucsi-fixes-v2-4-0f5d37ed04db@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c872a83b148 --- /dev/null +++ b/queue-6.6/usb-typec-ucsi-simplify-partner-s-pd-caps-registrati.patch @@ -0,0 +1,63 @@ +From fd7f8414fdb48736563592cca2b2584ddfdf9c2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Mar 2024 08:15:37 +0200 +Subject: usb: typec: ucsi: simplify partner's PD caps registration + +From: Dmitry Baryshkov + +[ 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 +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20240329-qcom-ucsi-fixes-v2-5-0f5d37ed04db@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b344cb6af3c --- /dev/null +++ b/queue-6.6/vfio-pci-fix-potential-memory-leak-in-vfio_intx_enab.patch @@ -0,0 +1,41 @@ +From 9fc0f4853c70f603ba7f9a8184a10ed6fba19cfa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Apr 2024 09:50:29 +0800 +Subject: vfio/pci: fix potential memory leak in vfio_intx_enable() + +From: Ye Bin + +[ 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 +Reviewed-by: Kevin Tian +Acked-by: Reinette Chatre +Link: https://lore.kernel.org/r/20240415015029.3699844-1-yebin10@huawei.com +Signed-off-by: Alex Williamson +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..152550c4d60 --- /dev/null +++ b/queue-6.6/vmci-fix-an-error-handling-path-in-vmci_guest_probe_.patch @@ -0,0 +1,66 @@ +From 7e28061e6f5f2da69dbde06c2f183480b0a43e34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Apr 2024 14:27:23 +0200 +Subject: VMCI: Fix an error handling path in vmci_guest_probe_device() + +From: Christophe JAILLET + +[ 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 +Acked-by: Vishnu Dasa +Link: https://lore.kernel.org/r/a35bbc3876ae1da70e49dafde4435750e1477be3.1713961553.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..77b81dbe143 --- /dev/null +++ b/queue-6.6/watchdog-bd9576-drop-always-running-property.patch @@ -0,0 +1,84 @@ +From dc4ad41e9af8f3f3aeeb7a98767a1fee97fab5eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Apr 2024 13:02:31 +0300 +Subject: watchdog: bd9576: Drop "always-running" property + +From: Matti Vaittinen + +[ 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 +Reported-by: Guenter Roeck +Fixes: b237bcac557a ("wdt: Support wdt on ROHM BD9576MUF and BD9573MUF") +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/ZhPAt76yaJMersXf@fedora +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9364218677e --- /dev/null +++ b/queue-6.6/watchdog-cpu5wdt.c-fix-use-after-free-bug-caused-by-.patch @@ -0,0 +1,46 @@ +From bd1962df9b07dfb8f9e769d9c5838576e2bf6436 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20240324140444.119584-1-duoming@zju.edu.cn +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..3987ae6129e --- /dev/null +++ b/queue-6.6/watchdog-sa1100-fix-ptr_err_or_zero-vs-null-check-in.patch @@ -0,0 +1,43 @@ +From cd47ecd8c750da433ffb447d422d7fc1390ec5bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20240426075808.1582678-1-nichen@iscas.ac.cn +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f1b18d14317 --- /dev/null +++ b/queue-6.6/xfs-convert-kmem_free-for-kvmalloc-users-to-kvfree.patch @@ -0,0 +1,472 @@ +From e21ad7e6349c01a9b3145afd8c80f9e437666a08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jan 2024 09:59:42 +1100 +Subject: xfs: convert kmem_free() for kvmalloc users to kvfree() + +From: Dave Chinner + +[ 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 +Reviewed-by: "Darrick J. Wong" +Signed-off-by: Chandan Babu R +Stable-dep-of: 45cf976008dd ("xfs: fix log recovery buffer allocation for the legacy h_size fixup") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..7c9ec1420ce --- /dev/null +++ b/queue-6.6/xfs-fix-log-recovery-buffer-allocation-for-the-legac.patch @@ -0,0 +1,76 @@ +From 6f069e2fd9f155e5face3c5aef5cf7bd1acf99ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Christoph Hellwig +Reviewed-by: Brian Foster +Reviewed-by: "Darrick J. Wong" +Signed-off-by: Chandan Babu R +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..15e455ed26f --- /dev/null +++ b/queue-6.6/xfs-match-lock-mode-in-xfs_buffered_write_iomap_begi.patch @@ -0,0 +1,70 @@ +From 2920cac12f7a637704199feef95f802f9692b7e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Apr 2024 21:13:27 +0800 +Subject: xfs: match lock mode in xfs_buffered_write_iomap_begin() + +From: Zhang Yi + +[ 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 +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Christoph Hellwig +Signed-off-by: Chandan Babu R +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..08a55665ac3 --- /dev/null +++ b/queue-6.6/xfs-require-xfs_sb_feat_incompat_log_xattrs-for-attr.patch @@ -0,0 +1,48 @@ +From e90f2ae615227c6ca739c3ba286b060744dc04fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ab2e76611ce --- /dev/null +++ b/queue-6.6/xfs-upgrade-the-extent-counters-in-xfs_reflink_end_c.patch @@ -0,0 +1,60 @@ +From 59d442e43f2bda5291d8d7df5c82fe8940aa8c60 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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" +Signed-off-by: Christoph Hellwig +Signed-off-by: Chandan Babu R +Signed-off-by: Sasha Levin +--- + 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 + -- 2.47.3