]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.11
authorSasha Levin <sashal@kernel.org>
Sun, 6 Oct 2024 15:11:21 +0000 (11:11 -0400)
committerSasha Levin <sashal@kernel.org>
Sun, 6 Oct 2024 15:11:21 +0000 (11:11 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
232 files changed:
queue-6.11/acpi-cppc-add-support-for-setting-epp-register-in-ff.patch [new file with mode: 0644]
queue-6.11/acpi-ec-do-not-release-locks-during-operation-region.patch [new file with mode: 0644]
queue-6.11/acpi-pad-fix-crash-in-exit_round_robin.patch [new file with mode: 0644]
queue-6.11/acpi-resource-skip-irq-override-on-asus-vivobook-go-.patch [new file with mode: 0644]
queue-6.11/acpi-video-add-force_vendor-quirk-for-panasonic-toug.patch [new file with mode: 0644]
queue-6.11/acpica-check-null-return-of-acpi_allocate_zeroed-in-.patch [new file with mode: 0644]
queue-6.11/acpica-fix-memory-leak-if-acpi_ps_get_next_field-fai.patch [new file with mode: 0644]
queue-6.11/acpica-fix-memory-leak-if-acpi_ps_get_next_namepath-.patch [new file with mode: 0644]
queue-6.11/acpica-iasl-handle-empty-connection_node.patch [new file with mode: 0644]
queue-6.11/alsa-asihpi-fix-potential-oob-array-access.patch [new file with mode: 0644]
queue-6.11/alsa-control-take-power_ref-lock-primarily.patch [new file with mode: 0644]
queue-6.11/alsa-hda-realtek-refactor-and-simplify-samsung-galax.patch [new file with mode: 0644]
queue-6.11/alsa-hdsp-break-infinite-midi-input-flush-loop.patch [new file with mode: 0644]
queue-6.11/alsa-usb-audio-add-input-value-sanity-checks-for-sta.patch [new file with mode: 0644]
queue-6.11/alsa-usb-audio-add-logitech-audio-profile-quirk.patch [new file with mode: 0644]
queue-6.11/alsa-usb-audio-add-mixer-quirk-for-rme-digiface-usb.patch [new file with mode: 0644]
queue-6.11/alsa-usb-audio-add-quirk-for-rme-digiface-usb.patch [new file with mode: 0644]
queue-6.11/alsa-usb-audio-define-macros-for-quirk-table-entries.patch [new file with mode: 0644]
queue-6.11/alsa-usb-audio-replace-complex-quirk-lines-with-macr.patch [new file with mode: 0644]
queue-6.11/alsa-usb-audio-support-multiple-control-interfaces.patch [new file with mode: 0644]
queue-6.11/arm64-trans_pgd-mark-ptes-entries-as-valid-to-avoid-.patch [new file with mode: 0644]
queue-6.11/asoc-codecs-wsa883x-handle-reading-version-failure.patch [new file with mode: 0644]
queue-6.11/asoc-intel-boards-always-check-the-result-of-acpi_de.patch [new file with mode: 0644]
queue-6.11/ata-pata_serverworks-do-not-use-the-term-blacklist.patch [new file with mode: 0644]
queue-6.11/ata-sata_sil-rename-sil_blacklist-to-sil_quirks.patch [new file with mode: 0644]
queue-6.11/blk_iocost-fix-more-out-of-bound-shifts.patch [new file with mode: 0644]
queue-6.11/block-fix-integer-overflow-in-blksecdiscard.patch [new file with mode: 0644]
queue-6.11/bluetooth-btrtl-set-msft-ext-address-filter-quirk-fo.patch [new file with mode: 0644]
queue-6.11/bluetooth-btusb-add-realtek-rtl8852c-support-id-0x04.patch [new file with mode: 0644]
queue-6.11/bnxt_en-extend-maximum-length-of-version-string-by-1.patch [new file with mode: 0644]
queue-6.11/bpf-fix-a-sdiv-overflow-issue.patch [new file with mode: 0644]
queue-6.11/bpf-make-the-pointer-returned-by-iter-next-method-va.patch [new file with mode: 0644]
queue-6.11/bpftool-fix-undefined-behavior-caused-by-shifting-in.patch [new file with mode: 0644]
queue-6.11/bpftool-fix-undefined-behavior-in-qsort-null-0.patch [new file with mode: 0644]
queue-6.11/btrfs-don-t-readahead-the-relocation-inode-on-rst.patch [new file with mode: 0644]
queue-6.11/can-netlink-avoid-call-to-do_set_data_bittiming-call.patch [new file with mode: 0644]
queue-6.11/cgroup-disallow-mounting-v1-hierarchies-without-cont.patch [new file with mode: 0644]
queue-6.11/coredump-standartize-and-fix-logging.patch [new file with mode: 0644]
queue-6.11/cpufreq-amd-pstate-add-check-for-cpufreq_cpu_get-s-r.patch [new file with mode: 0644]
queue-6.11/cpufreq-loongson3-use-raw_smp_processor_id-in-do_ser.patch [new file with mode: 0644]
queue-6.11/crypto-hisilicon-fix-missed-error-branch.patch [new file with mode: 0644]
queue-6.11/crypto-octeontx-fix-authenc-setkey.patch [new file with mode: 0644]
queue-6.11/crypto-octeontx2-fix-authenc-setkey.patch [new file with mode: 0644]
queue-6.11/crypto-simd-do-not-call-crypto_alloc_tfm-during-regi.patch [new file with mode: 0644]
queue-6.11/crypto-x86-sha256-add-parentheses-around-macros-sing.patch [new file with mode: 0644]
queue-6.11/drivers-perf-arm_spe-use-perf_allow_kernel-for-permi.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-afb-in-amdgpu_dm_.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-afb-in-amdgpu_dm_.patch-8577 [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-clk_mgr-and-clk_m.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-clk_mgr-and-clk_m.patch-5210 [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-clk_mgr-in-dcn32_.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-function-pointer-.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-function-pointer-.patch-16350 [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-function-pointer-.patch-4383 [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-head_pipe-in-dcn2.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-head_pipe-in-dcn3.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-pipe_ctx-plane_st.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-add-null-check-for-top_pipe_to_progr.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-avoid-overflow-assignment-in-link_dp.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-check-null-initialized-variables.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-check-null-pointer-before-try-to-acc.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-check-null-pointers-before-multiple-.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-check-null-pointers-before-used.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-check-null-pointers-before-using-dc-.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-check-null-pointers-before-using-the.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-check-phantom_stream-before-it-is-us.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-check-stream-before-comparing-them.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-check-stream_status-before-it-is-use.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-deallocate-dml-memory-if-allocation-.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-fix-a-ubsan-warning-in-dml2.1.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-fix-double-free-issue-during-amdgpu-.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-fix-index-out-of-bounds-in-dcn30-col.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-fix-index-out-of-bounds-in-dcn30-deg.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-fix-index-out-of-bounds-in-degamma-h.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-fix-possible-overflow-in-integer-mul.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-force-enable-3dlut-dma-check-for-dcn.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-guard-write-a-0-post_divider-value-t.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-handle-null-stream_status-in-planes_.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-implement-bounds-check-for-stream-en.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-increase-array-size-of-dummy_boolean.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-initialize-denominators-default-to-1.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-initialize-get_bytes_per_element-s-d.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-pass-non-null-to-dcn20_validate_appl.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-underflow-seen-on-dcn401-egpu.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-unlock-pipes-based-on-det-allocation.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-use-gpuvm_min_page_size_kbytes-for-d.patch [new file with mode: 0644]
queue-6.11/drm-amd-pm-ensure-the-fw_info-is-not-null-before-usi.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-add-list-empty-check-to-avoid-null-pointe.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-add-raven1-gfxoff-quirk.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-block-mmr_read-ioctl-in-reset.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-disallow-multiple-bo_handles-chunks-in-on.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-enable-gfxoff-quirk-on-hp-705g4.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-fix-ptr-check-warning-in-gfx10-ip_dump.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-fix-ptr-check-warning-in-gfx11-ip_dump.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-fix-ptr-check-warning-in-gfx9-ip_dump.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-fix-unchecked-return-value-warning-for-am.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-fix-unchecked-return-value-warning-for-am.patch-17138 [new file with mode: 0644]
queue-6.11/drm-amdgpu-gfx10-use-rlc-safe-mode-for-soft-recovery.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-gfx11-enter-safe-mode-before-touching-cp_.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-gfx11-use-rlc-safe-mode-for-soft-recovery.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-gfx12-properly-handle-error-ints-on-all-p.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-gfx12-use-rlc-safe-mode-for-soft-recovery.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-gfx9-properly-handle-error-ints-on-all-pi.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-gfx9-use-rlc-safe-mode-for-soft-recovery.patch [new file with mode: 0644]
queue-6.11/drm-amdkfd-amdkfd_free_gtt_mem-clear-the-correct-poi.patch [new file with mode: 0644]
queue-6.11/drm-amdkfd-check-int-source-id-for-utcl2-poison-even.patch [new file with mode: 0644]
queue-6.11/drm-amdkfd-fix-resource-leak-in-criu-restore-queue.patch [new file with mode: 0644]
queue-6.11/drm-msm-adreno-assign-msm_gpu-pdev-earlier-to-avoid-.patch [new file with mode: 0644]
queue-6.11/drm-printer-allow-null-data-in-devcoredump-printer.patch [new file with mode: 0644]
queue-6.11/drm-radeon-r100-handle-unknown-family-in-r100_cp_ini.patch [new file with mode: 0644]
queue-6.11/drm-stm-avoid-use-after-free-issues-with-crtc-and-pl.patch [new file with mode: 0644]
queue-6.11/drm-stm-ltdc-reset-plane-transparency-after-plane-di.patch [new file with mode: 0644]
queue-6.11/drm-xe-add-timeout-to-preempt-fences.patch [new file with mode: 0644]
queue-6.11/drm-xe-drop-warn-on-xe_guc_pc_gucrc_disable-in-guc-p.patch [new file with mode: 0644]
queue-6.11/drm-xe-fbdev-limit-the-usage-of-stolen-for-lnl.patch [new file with mode: 0644]
queue-6.11/drm-xe-hdcp-check-gsc-structure-validity.patch [new file with mode: 0644]
queue-6.11/drm-xe-name-and-document-wa_14019789679.patch [new file with mode: 0644]
queue-6.11/drm-xe-use-topology-to-determine-page-fault-queue-si.patch [new file with mode: 0644]
queue-6.11/exec-don-t-warn-for-racy-path_noexec-check.patch [new file with mode: 0644]
queue-6.11/ext4-avoid-use-after-free-in-ext4_ext_show_leaf.patch [new file with mode: 0644]
queue-6.11/ext4-don-t-set-sb_rdonly-after-filesystem-errors.patch [new file with mode: 0644]
queue-6.11/ext4-ext4_search_dir-should-return-a-proper-error.patch [new file with mode: 0644]
queue-6.11/ext4-filesystems-without-casefold-feature-cannot-be-.patch [new file with mode: 0644]
queue-6.11/ext4-fix-i_data_sem-unlock-order-in-ext4_ind_migrate.patch [new file with mode: 0644]
queue-6.11/fbdev-efifb-register-sysfs-groups-through-driver-cor.patch [new file with mode: 0644]
queue-6.11/fbdev-pxafb-fix-possible-use-after-free-in-pxafb_tas.patch [new file with mode: 0644]
queue-6.11/fs-inode-prevent-dump_mapping-accessing-invalid-dent.patch [new file with mode: 0644]
queue-6.11/hid-i2c-hid-ensure-various-commands-do-not-interfere.patch [new file with mode: 0644]
queue-6.11/hid-ignore-battery-for-all-elan-i2c-hid-devices.patch [new file with mode: 0644]
queue-6.11/hid-multitouch-add-support-for-thinkpad-x12-gen-2-kb.patch [new file with mode: 0644]
queue-6.11/hwmon-nct6775-add-g15cf-to-asus-wmi-monitoring-list.patch [new file with mode: 0644]
queue-6.11/ice-adjust-over-allocation-of-memory-in-ice_sched_ad.patch [new file with mode: 0644]
queue-6.11/intel_idle-disable-promotion-to-c1e-on-jasper-lake-a.patch [new file with mode: 0644]
queue-6.11/iomap-handle-a-post-direct-i-o-invalidate-race-in-io.patch [new file with mode: 0644]
queue-6.11/iommu-arm-smmu-v3-do-not-use-devm-for-the-cd-table-a.patch [new file with mode: 0644]
queue-6.11/iommu-arm-smmu-v3-match-stall-behaviour-for-s2.patch [new file with mode: 0644]
queue-6.11/iommu-vt-d-always-reserve-a-domain-id-for-identity-s.patch [new file with mode: 0644]
queue-6.11/iommu-vt-d-fix-potential-lockup-if-qi_submit_sync-ca.patch [new file with mode: 0644]
queue-6.11/iommu-vt-d-unconditionally-flush-device-tlb-for-pasi.patch [new file with mode: 0644]
queue-6.11/ipv4-check-in_dev-earlier-for-ioctl-siocsifaddr.patch [new file with mode: 0644]
queue-6.11/ipv4-mask-upper-dscp-bits-and-ecn-bits-in-netlink_fi.patch [new file with mode: 0644]
queue-6.11/jfs-check-if-leafidx-greater-than-num-leaves-per-dma.patch [new file with mode: 0644]
queue-6.11/jfs-fix-uaf-in-dbfreebits.patch [new file with mode: 0644]
queue-6.11/jfs-fix-uninit-value-access-of-new_ea-in-ea_buffer.patch [new file with mode: 0644]
queue-6.11/jfs-ubsan-shift-out-of-bounds-in-dbfindbits.patch [new file with mode: 0644]
queue-6.11/ksmbd-add-refcnt-to-ksmbd_conn-struct.patch [new file with mode: 0644]
queue-6.11/l2tp-free-sessions-using-rcu.patch [new file with mode: 0644]
queue-6.11/l2tp-prevent-possible-tunnel-refcount-underflow.patch [new file with mode: 0644]
queue-6.11/l2tp-use-rcu-list-add-del-when-updating-lists.patch [new file with mode: 0644]
queue-6.11/net-atlantic-avoid-warning-about-potential-string-tr.patch [new file with mode: 0644]
queue-6.11/net-hisilicon-hip04-fix-of-node-leak-in-probe.patch [new file with mode: 0644]
queue-6.11/net-hisilicon-hns_dsaf_mac-fix-of-node-leak-in-hns_m.patch [new file with mode: 0644]
queue-6.11/net-hisilicon-hns_mdio-fix-of-node-leak-in-probe.patch [new file with mode: 0644]
queue-6.11/net-mvpp2-increase-size-of-queue_name-buffer.patch [new file with mode: 0644]
queue-6.11/net-napi-prevent-overflow-of-napi_defer_hard_irqs.patch [new file with mode: 0644]
queue-6.11/net-phy-check-for-read-errors-in-siocgmiireg.patch [new file with mode: 0644]
queue-6.11/net-sched-consistently-use-rcu_replace_pointer-in-ta.patch [new file with mode: 0644]
queue-6.11/net-skbuff-sprinkle-more-__gfp_nowarn-on-ingress-all.patch [new file with mode: 0644]
queue-6.11/net-xen-netback-prevent-uaf-in-xenvif_flush_hash.patch [new file with mode: 0644]
queue-6.11/netdev-genl-set-extack-and-fix-error-on-napi-get.patch [new file with mode: 0644]
queue-6.11/netfilter-nf_tables-do-not-remove-elements-if-set-ba.patch [new file with mode: 0644]
queue-6.11/netfs-cancel-dirty-folios-that-have-no-storage-desti.patch [new file with mode: 0644]
queue-6.11/netpoll-ensure-clean-state-on-setup-failures.patch [new file with mode: 0644]
queue-6.11/nfp-use-irqf_no_autoen-flag-in-request_irq.patch [new file with mode: 0644]
queue-6.11/nvme-fix-metadata-handling-in-nvme-passthrough.patch [new file with mode: 0644]
queue-6.11/nvme-keyring-restrict-match-length-for-version-1-ide.patch [new file with mode: 0644]
queue-6.11/nvme-tcp-check-for-invalidated-or-revoked-key.patch [new file with mode: 0644]
queue-6.11/nvme-tcp-sanitize-tls-key-handling.patch [new file with mode: 0644]
queue-6.11/of-irq-refer-to-actual-buffer-size-in-of_irq_parse_o.patch [new file with mode: 0644]
queue-6.11/ovl-fsync-after-metadata-copy-up.patch [new file with mode: 0644]
queue-6.11/perf-fix-event_function_call-locking.patch [new file with mode: 0644]
queue-6.11/perf-x86-avoid-missing-caller-address-in-stack-trace.patch [new file with mode: 0644]
queue-6.11/platform-mellanox-mlxbf-pmc-fix-lockdep-warning.patch [new file with mode: 0644]
queue-6.11/platform-x86-amd-pmf-add-quirk-for-tuf-gaming-a14.patch [new file with mode: 0644]
queue-6.11/platform-x86-lenovo-ymc-ignore-the-0x0-state.patch [new file with mode: 0644]
queue-6.11/platform-x86-touchscreen_dmi-add-nanote-next-quirk.patch [new file with mode: 0644]
queue-6.11/platform-x86-x86-android-tablets-adjust-xiaomi-pad-2.patch [new file with mode: 0644]
queue-6.11/pmdomain-core-don-t-hold-the-genpd-lock-when-calling.patch [new file with mode: 0644]
queue-6.11/pmdomain-core-use-dev_name-instead-of-kobject_get_pa.patch [new file with mode: 0644]
queue-6.11/power-reset-brcmstb-do-not-go-into-infinite-loop-if-.patch [new file with mode: 0644]
queue-6.11/powerpc-pseries-use-correct-data-types-from-pseries_.patch [new file with mode: 0644]
queue-6.11/proc-add-config-param-to-block-forcing-mem-writes.patch [new file with mode: 0644]
queue-6.11/rcu-tasks-fix-access-non-existent-percpu-rtpcp-varia.patch [new file with mode: 0644]
queue-6.11/rcuscale-provide-clear-error-when-async-specified-wi.patch [new file with mode: 0644]
queue-6.11/scsi-aacraid-rearrange-order-of-struct-aac_srb_unit.patch [new file with mode: 0644]
queue-6.11/scsi-lpfc-fix-unsolicited-flogi-kref-imbalance-when-.patch [new file with mode: 0644]
queue-6.11/scsi-lpfc-update-prlo-handling-in-direct-attached-to.patch [new file with mode: 0644]
queue-6.11/scsi-lpfc-validate-hdwq-pointers-before-dereferencin.patch [new file with mode: 0644]
queue-6.11/scsi-ncr5380-initialize-buffer-for-msg-in-and-status.patch [new file with mode: 0644]
queue-6.11/scsi-smartpqi-add-new-controller-pci-ids.patch [new file with mode: 0644]
queue-6.11/scsi-smartpqi-add-new-controller-pci-ids.patch-30880 [new file with mode: 0644]
queue-6.11/scsi-smartpqi-correct-stream-detection.patch [new file with mode: 0644]
queue-6.11/selftests-bpf-fix-uprobe.path-leak-in-bpf_testmod.patch [new file with mode: 0644]
queue-6.11/selftests-nolibc-avoid-passing-null-to-printf-s.patch [new file with mode: 0644]
queue-6.11/series
queue-6.11/tcp-avoid-reusing-fin_wait2-when-trying-to-find-port.patch [new file with mode: 0644]
queue-6.11/tipc-guard-against-string-buffer-overrun.patch [new file with mode: 0644]
queue-6.11/tools-hv-add-memory-allocation-check-in-hv_fcopy_sta.patch [new file with mode: 0644]
queue-6.11/tools-nolibc-powerpc-limit-stack-protector-workaroun.patch [new file with mode: 0644]
queue-6.11/tools-x86-kcpuid-protect-against-faulty-max-subleaf-.patch [new file with mode: 0644]
queue-6.11/vfs-use-rcu-in-ilookup.patch [new file with mode: 0644]
queue-6.11/virt-sev-guest-ensure-the-snp-guest-messages-do-not-.patch [new file with mode: 0644]
queue-6.11/wifi-ath11k-fix-array-out-of-bound-access-in-soc-sta.patch [new file with mode: 0644]
queue-6.11/wifi-ath12k-fix-array-out-of-bound-access-in-soc-sta.patch [new file with mode: 0644]
queue-6.11/wifi-ath9k-fix-possible-integer-overflow-in-ath9k_ge.patch [new file with mode: 0644]
queue-6.11/wifi-ath9k_htc-use-__skb_set_length-for-resetting-ur.patch [new file with mode: 0644]
queue-6.11/wifi-cfg80211-set-correct-chandef-when-starting-cac.patch [new file with mode: 0644]
queue-6.11/wifi-iwlwifi-allow-only-cn-mcc-from-wrdd.patch [new file with mode: 0644]
queue-6.11/wifi-iwlwifi-mvm-avoid-null-pointer-dereference.patch [new file with mode: 0644]
queue-6.11/wifi-iwlwifi-mvm-drop-wrong-sta-selection-in-tx.patch [new file with mode: 0644]
queue-6.11/wifi-iwlwifi-mvm-fix-a-race-in-scan-abort-flow.patch [new file with mode: 0644]
queue-6.11/wifi-iwlwifi-mvm-use-correct-key-iteration.patch [new file with mode: 0644]
queue-6.11/wifi-mac80211-fix-rcu-list-iterations.patch [new file with mode: 0644]
queue-6.11/wifi-mt76-mt7915-add-dummy-hw-offload-of-ieee-802.11.patch [new file with mode: 0644]
queue-6.11/wifi-mt76-mt7915-disable-tx-worker-during-tx-ba-sess.patch [new file with mode: 0644]
queue-6.11/wifi-mt76-mt7915-hold-dev-mt76.mutex-while-disabling.patch [new file with mode: 0644]
queue-6.11/wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch [new file with mode: 0644]
queue-6.11/wifi-rtw88-select-want_dev_coredump.patch [new file with mode: 0644]
queue-6.11/wifi-rtw89-885xb-reset-idmem-mode-to-prevent-downloa.patch [new file with mode: 0644]
queue-6.11/wifi-rtw89-avoid-reading-out-of-bounds-when-loading-.patch [new file with mode: 0644]
queue-6.11/wifi-rtw89-avoid-to-add-interface-to-list-twice-when.patch [new file with mode: 0644]
queue-6.11/wifi-rtw89-correct-base-ht-rate-mask-for-firmware.patch [new file with mode: 0644]
queue-6.11/wifi-wilc1000-do-not-operate-uninitialized-hardware-.patch [new file with mode: 0644]
queue-6.11/x86-apic-remove-logical-destination-mode-for-64-bit.patch [new file with mode: 0644]
queue-6.11/x86-bugs-add-missing-no_ssb-flag.patch [new file with mode: 0644]
queue-6.11/x86-bugs-fix-handling-when-srso-mitigation-is-disabl.patch [new file with mode: 0644]
queue-6.11/x86-ioapic-handle-allocation-failures-gracefully.patch [new file with mode: 0644]
queue-6.11/x86-kexec-add-efi-config-table-identity-mapping-for-.patch [new file with mode: 0644]
queue-6.11/x86-mm-ident_map-use-gbpages-only-where-full-gb-page.patch [new file with mode: 0644]
queue-6.11/x86-pkeys-add-pkru-as-a-parameter-in-signal-handling.patch [new file with mode: 0644]
queue-6.11/x86-pkeys-restore-altstack-access-in-sigreturn.patch [new file with mode: 0644]
queue-6.11/x86-syscall-avoid-memcpy-for-ia32-syscall_get_argume.patch [new file with mode: 0644]

diff --git a/queue-6.11/acpi-cppc-add-support-for-setting-epp-register-in-ff.patch b/queue-6.11/acpi-cppc-add-support-for-setting-epp-register-in-ff.patch
new file mode 100644 (file)
index 0000000..e4b0377
--- /dev/null
@@ -0,0 +1,74 @@
+From 8f87095563a6c42b844c4f3dc7be0da480bb5b36 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Sep 2024 22:15:24 -0500
+Subject: ACPI: CPPC: Add support for setting EPP register in FFH
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit aaf21ac93909e08a12931173336bdb52ac8499f1 ]
+
+Some Asus AMD systems are reported to not be able to change EPP values
+because the BIOS doesn't advertise support for the CPPC MSR and the PCC
+region is not configured.
+
+However the ACPI 6.2 specification allows CPC registers to be declared
+in FFH:
+```
+Starting with ACPI Specification 6.2, all _CPC registers can be in
+PCC, System Memory, System IO, or Functional Fixed Hardware address
+spaces. OSPM support for this more flexible register space scheme
+is indicated by the “Flexible Address Space for CPPC Registers” _OSC
+bit.
+```
+
+If this _OSC has been set allow using FFH to configure EPP.
+
+Reported-by: al0uette@outlook.com
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218686
+Suggested-by: al0uette@outlook.com
+Tested-by: vderp@icloud.com
+Tested-by: al0uette@outlook.com
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Link: https://patch.msgid.link/20240910031524.106387-1-superm1@kernel.org
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/cppc_acpi.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
+index 28adea68e1cd6..5b06e236aabef 100644
+--- a/drivers/acpi/cppc_acpi.c
++++ b/drivers/acpi/cppc_acpi.c
+@@ -103,6 +103,11 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
+                               (cpc)->cpc_entry.reg.space_id ==        \
+                               ACPI_ADR_SPACE_PLATFORM_COMM)
++/* Check if a CPC register is in FFH */
++#define CPC_IN_FFH(cpc) ((cpc)->type == ACPI_TYPE_BUFFER &&           \
++                              (cpc)->cpc_entry.reg.space_id ==        \
++                              ACPI_ADR_SPACE_FIXED_HARDWARE)
++
+ /* Check if a CPC register is in SystemMemory */
+ #define CPC_IN_SYSTEM_MEMORY(cpc) ((cpc)->type == ACPI_TYPE_BUFFER && \
+                               (cpc)->cpc_entry.reg.space_id ==        \
+@@ -1521,9 +1526,12 @@ int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable)
+               /* after writing CPC, transfer the ownership of PCC to platform */
+               ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE);
+               up_write(&pcc_ss_data->pcc_lock);
++      } else if (osc_cpc_flexible_adr_space_confirmed &&
++                 CPC_SUPPORTED(epp_set_reg) && CPC_IN_FFH(epp_set_reg)) {
++              ret = cpc_write(cpu, epp_set_reg, perf_ctrls->energy_perf);
+       } else {
+               ret = -ENOTSUPP;
+-              pr_debug("_CPC in PCC is not supported\n");
++              pr_debug("_CPC in PCC and _CPC in FFH are not supported\n");
+       }
+       return ret;
+-- 
+2.43.0
+
diff --git a/queue-6.11/acpi-ec-do-not-release-locks-during-operation-region.patch b/queue-6.11/acpi-ec-do-not-release-locks-during-operation-region.patch
new file mode 100644 (file)
index 0000000..afc3697
--- /dev/null
@@ -0,0 +1,166 @@
+From 8b14fbdbe1ffc56ae011c56c76fa0cba2f1f2a84 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jul 2024 18:26:54 +0200
+Subject: ACPI: EC: Do not release locks during operation region accesses
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit dc171114926ec390ab90f46534545420ec03e458 ]
+
+It is not particularly useful to release locks (the EC mutex and the
+ACPI global lock, if present) and re-acquire them immediately thereafter
+during EC address space accesses in acpi_ec_space_handler().
+
+First, releasing them for a while before grabbing them again does not
+really help anyone because there may not be enough time for another
+thread to acquire them.
+
+Second, if another thread successfully acquires them and carries out
+a new EC write or read in the middle if an operation region access in
+progress, it may confuse the EC firmware, especially after the burst
+mode has been enabled.
+
+Finally, manipulating the locks after writing or reading every single
+byte of data is overhead that it is better to avoid.
+
+Accordingly, modify the code to carry out EC address space accesses
+entirely without releasing the locks.
+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patch.msgid.link/12473338.O9o76ZdvQC@rjwysocki.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/ec.c | 55 +++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 49 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index 38d2f6e6b12b4..25399f6dde7e2 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -783,6 +783,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
+       unsigned long tmp;
+       int ret = 0;
++      if (t->rdata)
++              memset(t->rdata, 0, t->rlen);
++
+       /* start transaction */
+       spin_lock_irqsave(&ec->lock, tmp);
+       /* Enable GPE for command processing (IBF=0/OBF=1) */
+@@ -819,8 +822,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
+       if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
+               return -EINVAL;
+-      if (t->rdata)
+-              memset(t->rdata, 0, t->rlen);
+       mutex_lock(&ec->mutex);
+       if (ec->global_lock) {
+@@ -847,7 +848,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec)
+                               .wdata = NULL, .rdata = &d,
+                               .wlen = 0, .rlen = 1};
+-      return acpi_ec_transaction(ec, &t);
++      return acpi_ec_transaction_unlocked(ec, &t);
+ }
+ static int acpi_ec_burst_disable(struct acpi_ec *ec)
+@@ -857,7 +858,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
+                               .wlen = 0, .rlen = 0};
+       return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
+-                              acpi_ec_transaction(ec, &t) : 0;
++                              acpi_ec_transaction_unlocked(ec, &t) : 0;
+ }
+ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
+@@ -873,6 +874,19 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
+       return result;
+ }
++static int acpi_ec_read_unlocked(struct acpi_ec *ec, u8 address, u8 *data)
++{
++      int result;
++      u8 d;
++      struct transaction t = {.command = ACPI_EC_COMMAND_READ,
++                              .wdata = &address, .rdata = &d,
++                              .wlen = 1, .rlen = 1};
++
++      result = acpi_ec_transaction_unlocked(ec, &t);
++      *data = d;
++      return result;
++}
++
+ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
+ {
+       u8 wdata[2] = { address, data };
+@@ -883,6 +897,16 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
+       return acpi_ec_transaction(ec, &t);
+ }
++static int acpi_ec_write_unlocked(struct acpi_ec *ec, u8 address, u8 data)
++{
++      u8 wdata[2] = { address, data };
++      struct transaction t = {.command = ACPI_EC_COMMAND_WRITE,
++                              .wdata = wdata, .rdata = NULL,
++                              .wlen = 2, .rlen = 0};
++
++      return acpi_ec_transaction_unlocked(ec, &t);
++}
++
+ int ec_read(u8 addr, u8 *val)
+ {
+       int err;
+@@ -1323,6 +1347,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
+       struct acpi_ec *ec = handler_context;
+       int result = 0, i, bytes = bits / 8;
+       u8 *value = (u8 *)value64;
++      u32 glk;
+       if ((address > 0xFF) || !value || !handler_context)
+               return AE_BAD_PARAMETER;
+@@ -1330,13 +1355,25 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
+       if (function != ACPI_READ && function != ACPI_WRITE)
+               return AE_BAD_PARAMETER;
++      mutex_lock(&ec->mutex);
++
++      if (ec->global_lock) {
++              acpi_status status;
++
++              status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
++              if (ACPI_FAILURE(status)) {
++                      result = -ENODEV;
++                      goto unlock;
++              }
++      }
++
+       if (ec->busy_polling || bits > 8)
+               acpi_ec_burst_enable(ec);
+       for (i = 0; i < bytes; ++i, ++address, ++value) {
+               result = (function == ACPI_READ) ?
+-                      acpi_ec_read(ec, address, value) :
+-                      acpi_ec_write(ec, address, *value);
++                      acpi_ec_read_unlocked(ec, address, value) :
++                      acpi_ec_write_unlocked(ec, address, *value);
+               if (result < 0)
+                       break;
+       }
+@@ -1344,6 +1381,12 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
+       if (ec->busy_polling || bits > 8)
+               acpi_ec_burst_disable(ec);
++      if (ec->global_lock)
++              acpi_release_global_lock(glk);
++
++unlock:
++      mutex_unlock(&ec->mutex);
++
+       switch (result) {
+       case -EINVAL:
+               return AE_BAD_PARAMETER;
+-- 
+2.43.0
+
diff --git a/queue-6.11/acpi-pad-fix-crash-in-exit_round_robin.patch b/queue-6.11/acpi-pad-fix-crash-in-exit_round_robin.patch
new file mode 100644 (file)
index 0000000..2f845c0
--- /dev/null
@@ -0,0 +1,96 @@
+From 27877420df13b292e6c8ecd873b32d5f6c00b0e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 25 Aug 2024 23:13:52 +0900
+Subject: ACPI: PAD: fix crash in exit_round_robin()
+
+From: Seiji Nishikawa <snishika@redhat.com>
+
+[ Upstream commit 0a2ed70a549e61c5181bad5db418d223b68ae932 ]
+
+The kernel occasionally crashes in cpumask_clear_cpu(), which is called
+within exit_round_robin(), because when executing clear_bit(nr, addr) with
+nr set to 0xffffffff, the address calculation may cause misalignment within
+the memory, leading to access to an invalid memory address.
+
+----------
+BUG: unable to handle kernel paging request at ffffffffe0740618
+        ...
+CPU: 3 PID: 2919323 Comm: acpi_pad/14 Kdump: loaded Tainted: G           OE  X --------- -  - 4.18.0-425.19.2.el8_7.x86_64 #1
+        ...
+RIP: 0010:power_saving_thread+0x313/0x411 [acpi_pad]
+Code: 89 cd 48 89 d3 eb d1 48 c7 c7 55 70 72 c0 e8 64 86 b0 e4 c6 05 0d a1 02 00 01 e9 bc fd ff ff 45 89 e4 42 8b 04 a5 20 82 72 c0 <f0> 48 0f b3 05 f4 9c 01 00 42 c7 04 a5 20 82 72 c0 ff ff ff ff 31
+RSP: 0018:ff72a5d51fa77ec8 EFLAGS: 00010202
+RAX: 00000000ffffffff RBX: ff462981e5d8cb80 RCX: 0000000000000000
+RDX: 0000000000000000 RSI: 0000000000000246 RDI: 0000000000000246
+RBP: ff46297556959d80 R08: 0000000000000382 R09: ff46297c8d0f38d8
+R10: 0000000000000000 R11: 0000000000000001 R12: 000000000000000e
+R13: 0000000000000000 R14: ffffffffffffffff R15: 000000000000000e
+FS:  0000000000000000(0000) GS:ff46297a800c0000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: ffffffffe0740618 CR3: 0000007e20410004 CR4: 0000000000771ee0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+PKRU: 55555554
+Call Trace:
+ ? acpi_pad_add+0x120/0x120 [acpi_pad]
+ kthread+0x10b/0x130
+ ? set_kthread_struct+0x50/0x50
+ ret_from_fork+0x1f/0x40
+        ...
+CR2: ffffffffe0740618
+
+crash> dis -lr ffffffffc0726923
+        ...
+/usr/src/debug/kernel-4.18.0-425.19.2.el8_7/linux-4.18.0-425.19.2.el8_7.x86_64/./include/linux/cpumask.h: 114
+0xffffffffc0726918 <power_saving_thread+776>:  mov    %r12d,%r12d
+/usr/src/debug/kernel-4.18.0-425.19.2.el8_7/linux-4.18.0-425.19.2.el8_7.x86_64/./include/linux/cpumask.h: 325
+0xffffffffc072691b <power_saving_thread+779>:  mov    -0x3f8d7de0(,%r12,4),%eax
+/usr/src/debug/kernel-4.18.0-425.19.2.el8_7/linux-4.18.0-425.19.2.el8_7.x86_64/./arch/x86/include/asm/bitops.h: 80
+0xffffffffc0726923 <power_saving_thread+787>:  lock btr %rax,0x19cf4(%rip)        # 0xffffffffc0740620 <pad_busy_cpus_bits>
+
+crash> px tsk_in_cpu[14]
+$66 = 0xffffffff
+
+crash> px 0xffffffffc072692c+0x19cf4
+$99 = 0xffffffffc0740620
+
+crash> sym 0xffffffffc0740620
+ffffffffc0740620 (b) pad_busy_cpus_bits [acpi_pad]
+
+crash> px pad_busy_cpus_bits[0]
+$42 = 0xfffc0
+----------
+
+To fix this, ensure that tsk_in_cpu[tsk_index] != -1 before calling
+cpumask_clear_cpu() in exit_round_robin(), just as it is done in
+round_robin_cpu().
+
+Signed-off-by: Seiji Nishikawa <snishika@redhat.com>
+Link: https://patch.msgid.link/20240825141352.25280-1-snishika@redhat.com
+[ rjw: Subject edit, avoid updates to the same value ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpi_pad.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
+index 350d3a8928896..e84720f0246e8 100644
+--- a/drivers/acpi/acpi_pad.c
++++ b/drivers/acpi/acpi_pad.c
+@@ -136,8 +136,10 @@ static void exit_round_robin(unsigned int tsk_index)
+ {
+       struct cpumask *pad_busy_cpus = to_cpumask(pad_busy_cpus_bits);
+-      cpumask_clear_cpu(tsk_in_cpu[tsk_index], pad_busy_cpus);
+-      tsk_in_cpu[tsk_index] = -1;
++      if (tsk_in_cpu[tsk_index] != -1) {
++              cpumask_clear_cpu(tsk_in_cpu[tsk_index], pad_busy_cpus);
++              tsk_in_cpu[tsk_index] = -1;
++      }
+ }
+ static unsigned int idle_pct = 5; /* percentage */
+-- 
+2.43.0
+
diff --git a/queue-6.11/acpi-resource-skip-irq-override-on-asus-vivobook-go-.patch b/queue-6.11/acpi-resource-skip-irq-override-on-asus-vivobook-go-.patch
new file mode 100644 (file)
index 0000000..a1f0ecd
--- /dev/null
@@ -0,0 +1,48 @@
+From 2cbb180a7e89e2696b387b738aa860284f27e956 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Sep 2024 21:43:05 -0400
+Subject: ACPI: resource: Skip IRQ override on Asus Vivobook Go E1404GAB
+
+From: Tamim Khan <tamim@fusetak.com>
+
+[ Upstream commit 49e9cc315604972cc14868cb67831e3e8c3f1470 ]
+
+Like other Asus Vivobooks, the Asus Vivobook Go E1404GAB has a DSDT
+that describes IRQ 1 as ActiveLow, while the kernel overrides to Edge_High.
+
+This override prevents the internal keyboard from working.
+
+Fix the problem by adding this laptop to the table that prevents the kernel
+from overriding the IRQ.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=219212
+Signed-off-by: Tamim Khan <tamim@fusetak.com>
+Link: https://patch.msgid.link/20240903014317.38858-1-tamim@fusetak.com
+[ rjw: Changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/resource.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+index cb2aacbb93357..8a4726e2eb693 100644
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -503,6 +503,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
+                       DMI_MATCH(DMI_BOARD_NAME, "B2502FBA"),
+               },
+       },
++      {
++              /* Asus Vivobook Go E1404GAB */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_BOARD_NAME, "E1404GAB"),
++              },
++      },
+       {
+               /* Asus Vivobook E1504GA */
+               .matches = {
+-- 
+2.43.0
+
diff --git a/queue-6.11/acpi-video-add-force_vendor-quirk-for-panasonic-toug.patch b/queue-6.11/acpi-video-add-force_vendor-quirk-for-panasonic-toug.patch
new file mode 100644 (file)
index 0000000..a5a0057
--- /dev/null
@@ -0,0 +1,45 @@
+From 6ab9b5945ec8d02760e3687cb9a919f351f663d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Sep 2024 14:44:19 +0200
+Subject: ACPI: video: Add force_vendor quirk for Panasonic Toughbook CF-18
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit eb7b0f12e13ba99e64e3a690c2166895ed63b437 ]
+
+The Panasonic Toughbook CF-18 advertises both native and vendor backlight
+control interfaces. But only the vendor one actually works.
+
+acpi_video_get_backlight_type() will pick the non working native backlight
+by default, add a quirk to select the working vendor backlight instead.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patch.msgid.link/20240907124419.21195-1-hdegoede@redhat.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/video_detect.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
+index 75a5f559402f8..428a7399fe04a 100644
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -254,6 +254,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
+               DMI_MATCH(DMI_PRODUCT_NAME, "PCG-FRV35"),
+               },
+       },
++      {
++       .callback = video_detect_force_vendor,
++       /* Panasonic Toughbook CF-18 */
++       .matches = {
++              DMI_MATCH(DMI_SYS_VENDOR, "Matsushita Electric Industrial"),
++              DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
++              },
++      },
+       /*
+        * Toshiba models with Transflective display, these need to use
+-- 
+2.43.0
+
diff --git a/queue-6.11/acpica-check-null-return-of-acpi_allocate_zeroed-in-.patch b/queue-6.11/acpica-check-null-return-of-acpi_allocate_zeroed-in-.patch
new file mode 100644 (file)
index 0000000..52a0283
--- /dev/null
@@ -0,0 +1,41 @@
+From 65e34a24ce8b3f59b943825579bd202a622e6e29 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jul 2024 14:05:48 +0800
+Subject: ACPICA: check null return of ACPI_ALLOCATE_ZEROED() in
+ acpi_db_convert_to_package()
+
+From: Pei Xiao <xiaopei01@kylinos.cn>
+
+[ Upstream commit a5242874488eba2b9062985bf13743c029821330 ]
+
+ACPICA commit 4d4547cf13cca820ff7e0f859ba83e1a610b9fd0
+
+ACPI_ALLOCATE_ZEROED() may fail, elements might be NULL and will cause
+NULL pointer dereference later.
+
+Link: https://github.com/acpica/acpica/commit/4d4547cf
+Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn>
+Link: https://patch.msgid.link/tencent_4A21A2865B8B0A0D12CAEBEB84708EDDB505@qq.com
+[ rjw: Subject and changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/dbconvert.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/acpi/acpica/dbconvert.c b/drivers/acpi/acpica/dbconvert.c
+index 2b84ac093698a..8dbab69320499 100644
+--- a/drivers/acpi/acpica/dbconvert.c
++++ b/drivers/acpi/acpica/dbconvert.c
+@@ -174,6 +174,8 @@ acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object)
+       elements =
+           ACPI_ALLOCATE_ZEROED(DB_DEFAULT_PKG_ELEMENTS *
+                                sizeof(union acpi_object));
++      if (!elements)
++              return (AE_NO_MEMORY);
+       this = string;
+       for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/acpica-fix-memory-leak-if-acpi_ps_get_next_field-fai.patch b/queue-6.11/acpica-fix-memory-leak-if-acpi_ps_get_next_field-fai.patch
new file mode 100644 (file)
index 0000000..f888a7c
--- /dev/null
@@ -0,0 +1,90 @@
+From 18094129ab40677586b3c9b08c247c8ae006448c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Apr 2024 21:50:33 +0200
+Subject: ACPICA: Fix memory leak if acpi_ps_get_next_field() fails
+
+From: Armin Wolf <W_Armin@gmx.de>
+
+[ Upstream commit e6169a8ffee8a012badd8c703716e761ce851b15 ]
+
+ACPICA commit 1280045754264841b119a5ede96cd005bc09b5a7
+
+If acpi_ps_get_next_field() fails, the previously created field list
+needs to be properly disposed before returning the status code.
+
+Link: https://github.com/acpica/acpica/commit/12800457
+Signed-off-by: Armin Wolf <W_Armin@gmx.de>
+[ rjw: Rename local variable to avoid compiler confusion ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/psargs.c | 39 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+
+diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
+index 7debfd5ce0d86..28582adfc0aca 100644
+--- a/drivers/acpi/acpica/psargs.c
++++ b/drivers/acpi/acpica/psargs.c
+@@ -25,6 +25,8 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state);
+ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
+                                                      *parser_state);
++static void acpi_ps_free_field_list(union acpi_parse_object *start);
++
+ /*******************************************************************************
+  *
+  * FUNCTION:    acpi_ps_get_next_package_length
+@@ -683,6 +685,39 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
+       return_PTR(field);
+ }
++/*******************************************************************************
++ *
++ * FUNCTION:    acpi_ps_free_field_list
++ *
++ * PARAMETERS:  start               - First Op in field list
++ *
++ * RETURN:      None.
++ *
++ * DESCRIPTION: Free all Op objects inside a field list.
++ *
++ ******************************************************************************/
++
++static void acpi_ps_free_field_list(union acpi_parse_object *start)
++{
++      union acpi_parse_object *cur = start;
++      union acpi_parse_object *next;
++      union acpi_parse_object *arg;
++
++      while (cur) {
++              next = cur->common.next;
++
++              /* AML_INT_CONNECTION_OP can have a single argument */
++
++              arg = acpi_ps_get_arg(cur, 0);
++              if (arg) {
++                      acpi_ps_free_op(arg);
++              }
++
++              acpi_ps_free_op(cur);
++              cur = next;
++      }
++}
++
+ /*******************************************************************************
+  *
+  * FUNCTION:    acpi_ps_get_next_arg
+@@ -751,6 +786,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
+                       while (parser_state->aml < parser_state->pkg_end) {
+                               field = acpi_ps_get_next_field(parser_state);
+                               if (!field) {
++                                      if (arg) {
++                                              acpi_ps_free_field_list(arg);
++                                      }
++
+                                       return_ACPI_STATUS(AE_NO_MEMORY);
+                               }
+-- 
+2.43.0
+
diff --git a/queue-6.11/acpica-fix-memory-leak-if-acpi_ps_get_next_namepath-.patch b/queue-6.11/acpica-fix-memory-leak-if-acpi_ps_get_next_namepath-.patch
new file mode 100644 (file)
index 0000000..136eb24
--- /dev/null
@@ -0,0 +1,55 @@
+From 97dbd57c710adf833b85ad2aba0f93ad6888bb0c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Apr 2024 20:50:11 +0200
+Subject: ACPICA: Fix memory leak if acpi_ps_get_next_namepath() fails
+
+From: Armin Wolf <W_Armin@gmx.de>
+
+[ Upstream commit 5accb265f7a1b23e52b0ec42313d1e12895552f4 ]
+
+ACPICA commit 2802af722bbde7bf1a7ac68df68e179e2555d361
+
+If acpi_ps_get_next_namepath() fails, the previously allocated
+union acpi_parse_object needs to be freed before returning the
+status code.
+
+The issue was first being reported on the Linux ACPI mailing list:
+
+Link: https://lore.kernel.org/linux-acpi/56f94776-484f-48c0-8855-dba8e6a7793b@yandex.ru/T/
+Link: https://github.com/acpica/acpica/commit/2802af72
+Signed-off-by: Armin Wolf <W_Armin@gmx.de>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/psargs.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
+index 422c074ed2897..7debfd5ce0d86 100644
+--- a/drivers/acpi/acpica/psargs.c
++++ b/drivers/acpi/acpica/psargs.c
+@@ -820,6 +820,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
+                           acpi_ps_get_next_namepath(walk_state, parser_state,
+                                                     arg,
+                                                     ACPI_NOT_METHOD_CALL);
++                      if (ACPI_FAILURE(status)) {
++                              acpi_ps_free_op(arg);
++                              return_ACPI_STATUS(status);
++                      }
+               } else {
+                       /* Single complex argument, nothing returned */
+@@ -854,6 +858,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
+                           acpi_ps_get_next_namepath(walk_state, parser_state,
+                                                     arg,
+                                                     ACPI_POSSIBLE_METHOD_CALL);
++                      if (ACPI_FAILURE(status)) {
++                              acpi_ps_free_op(arg);
++                              return_ACPI_STATUS(status);
++                      }
+                       if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/acpica-iasl-handle-empty-connection_node.patch b/queue-6.11/acpica-iasl-handle-empty-connection_node.patch
new file mode 100644 (file)
index 0000000..adcd602
--- /dev/null
@@ -0,0 +1,36 @@
+From 5acc27efe63384e688d4059802fe20ffb588876a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 11 Aug 2024 23:33:44 +0200
+Subject: ACPICA: iasl: handle empty connection_node
+
+From: Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
+
+[ Upstream commit a0a2459b79414584af6c46dd8c6f866d8f1aa421 ]
+
+ACPICA commit 6c551e2c9487067d4b085333e7fe97e965a11625
+
+Link: https://github.com/acpica/acpica/commit/6c551e2c
+Signed-off-by: Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/exprep.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
+index 08196fa17080e..82b1fa2d201fe 100644
+--- a/drivers/acpi/acpica/exprep.c
++++ b/drivers/acpi/acpica/exprep.c
+@@ -437,6 +437,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
+               if (info->connection_node) {
+                       second_desc = info->connection_node->object;
++                      if (second_desc == NULL) {
++                              break;
++                      }
+                       if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) {
+                               status =
+                                   acpi_ds_get_buffer_arguments(second_desc);
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-asihpi-fix-potential-oob-array-access.patch b/queue-6.11/alsa-asihpi-fix-potential-oob-array-access.patch
new file mode 100644 (file)
index 0000000..8c02315
--- /dev/null
@@ -0,0 +1,39 @@
+From b81ca390e57e8565a95492715ad690d40d8fefbd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Aug 2024 11:14:42 +0200
+Subject: ALSA: asihpi: Fix potential OOB array access
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 7b986c7430a6bb68d523dac7bfc74cbd5b44ef96 ]
+
+ASIHPI driver stores some values in the static array upon a response
+from the driver, and its index depends on the firmware.  We shouldn't
+trust it blindly.
+
+This patch adds a sanity check of the array index to fit in the array
+size.
+
+Link: https://patch.msgid.link/20240808091454.30846-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/asihpi/hpimsgx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c
+index d0caef2994818..b68e6bfbbfbab 100644
+--- a/sound/pci/asihpi/hpimsgx.c
++++ b/sound/pci/asihpi/hpimsgx.c
+@@ -708,7 +708,7 @@ static u16 HPIMSGX__init(struct hpi_message *phm,
+               phr->error = HPI_ERROR_PROCESSING_MESSAGE;
+               return phr->error;
+       }
+-      if (hr.error == 0) {
++      if (hr.error == 0 && hr.u.s.adapter_index < HPI_MAX_ADAPTERS) {
+               /* the adapter was created successfully
+                  save the mapping for future use */
+               hpi_entry_points[hr.u.s.adapter_index] = entry_point_func;
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-control-take-power_ref-lock-primarily.patch b/queue-6.11/alsa-control-take-power_ref-lock-primarily.patch
new file mode 100644 (file)
index 0000000..3cf4094
--- /dev/null
@@ -0,0 +1,182 @@
+From 961025669b27e0ee589422f7c723ee818a018a60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 18:06:58 +0200
+Subject: ALSA: control: Take power_ref lock primarily
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit fcc62b19104a67b9a2941513771e09389b75bd95 ]
+
+The code path for kcontrol accesses have often nested locks of both
+card's controls_rwsem and power_ref, and applies in that order.
+However, what could take much longer is the latter, power_ref; it
+waits for the power state of the device, and it pretty much depends on
+the user's action.
+
+This patch swaps the locking order of those locks to a more natural
+way, namely, power_ref -> controls_rwsem, in order to shorten the time
+of possible nested locks.  For consistency, power_ref is taken always
+in the top-level caller side (that is, *_user() functions and the
+ioctl handler itself).
+
+Link: https://patch.msgid.link/20240729160659.4516-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/core/control.c | 54 ++++++++++++++++++++++++++++----------------
+ 1 file changed, 34 insertions(+), 20 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index f64a555f404f0..96a2c088a460e 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1167,9 +1167,7 @@ static int __snd_ctl_elem_info(struct snd_card *card,
+ #ifdef CONFIG_SND_DEBUG
+       info->access = 0;
+ #endif
+-      result = snd_power_ref_and_wait(card);
+-      if (!result)
+-              result = kctl->info(kctl, info);
++      result = kctl->info(kctl, info);
+       snd_power_unref(card);
+       if (result >= 0) {
+               snd_BUG_ON(info->access);
+@@ -1208,12 +1206,17 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
+ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
+                                 struct snd_ctl_elem_info __user *_info)
+ {
++      struct snd_card *card = ctl->card;
+       struct snd_ctl_elem_info info;
+       int result;
+       if (copy_from_user(&info, _info, sizeof(info)))
+               return -EFAULT;
++      result = snd_power_ref_and_wait(card);
++      if (result)
++              return result;
+       result = snd_ctl_elem_info(ctl, &info);
++      snd_power_unref(card);
+       if (result < 0)
+               return result;
+       /* drop internal access flags */
+@@ -1257,10 +1260,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
+       if (!snd_ctl_skip_validation(&info))
+               fill_remaining_elem_value(control, &info, pattern);
+-      ret = snd_power_ref_and_wait(card);
+-      if (!ret)
+-              ret = kctl->get(kctl, control);
+-      snd_power_unref(card);
++      ret = kctl->get(kctl, control);
+       if (ret < 0)
+               return ret;
+       if (!snd_ctl_skip_validation(&info) &&
+@@ -1285,7 +1285,11 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
+       if (IS_ERR(control))
+               return PTR_ERR(no_free_ptr(control));
++      result = snd_power_ref_and_wait(card);
++      if (result)
++              return result;
+       result = snd_ctl_elem_read(card, control);
++      snd_power_unref(card);
+       if (result < 0)
+               return result;
+@@ -1300,7 +1304,7 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
+       struct snd_kcontrol *kctl;
+       struct snd_kcontrol_volatile *vd;
+       unsigned int index_offset;
+-      int result;
++      int result = 0;
+       down_write(&card->controls_rwsem);
+       kctl = snd_ctl_find_id_locked(card, &control->id);
+@@ -1318,9 +1322,8 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
+       }
+       snd_ctl_build_ioff(&control->id, kctl, index_offset);
+-      result = snd_power_ref_and_wait(card);
+       /* validate input values */
+-      if (IS_ENABLED(CONFIG_SND_CTL_INPUT_VALIDATION) && !result) {
++      if (IS_ENABLED(CONFIG_SND_CTL_INPUT_VALIDATION)) {
+               struct snd_ctl_elem_info info;
+               memset(&info, 0, sizeof(info));
+@@ -1332,7 +1335,6 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
+       }
+       if (!result)
+               result = kctl->put(kctl, control);
+-      snd_power_unref(card);
+       if (result < 0) {
+               up_write(&card->controls_rwsem);
+               return result;
+@@ -1361,7 +1363,11 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
+               return PTR_ERR(no_free_ptr(control));
+       card = file->card;
++      result = snd_power_ref_and_wait(card);
++      if (result < 0)
++              return result;
+       result = snd_ctl_elem_write(card, file, control);
++      snd_power_unref(card);
+       if (result < 0)
+               return result;
+@@ -1830,7 +1836,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
+               {SNDRV_CTL_TLV_OP_CMD,   SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
+       };
+       struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
+-      int i, ret;
++      int i;
+       /* Check support of the request for this element. */
+       for (i = 0; i < ARRAY_SIZE(pairs); ++i) {
+@@ -1848,11 +1854,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
+           vd->owner != NULL && vd->owner != file)
+               return -EPERM;
+-      ret = snd_power_ref_and_wait(file->card);
+-      if (!ret)
+-              ret = kctl->tlv.c(kctl, op_flag, size, buf);
+-      snd_power_unref(file->card);
+-      return ret;
++      return kctl->tlv.c(kctl, op_flag, size, buf);
+ }
+ static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
+@@ -1965,16 +1967,28 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
+       case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
+               return snd_ctl_subscribe_events(ctl, ip);
+       case SNDRV_CTL_IOCTL_TLV_READ:
+-              scoped_guard(rwsem_read, &ctl->card->controls_rwsem)
++              err = snd_power_ref_and_wait(card);
++              if (err < 0)
++                      return err;
++              scoped_guard(rwsem_read, &card->controls_rwsem)
+                       err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
++              snd_power_unref(card);
+               return err;
+       case SNDRV_CTL_IOCTL_TLV_WRITE:
+-              scoped_guard(rwsem_write, &ctl->card->controls_rwsem)
++              err = snd_power_ref_and_wait(card);
++              if (err < 0)
++                      return err;
++              scoped_guard(rwsem_write, &card->controls_rwsem)
+                       err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
++              snd_power_unref(card);
+               return err;
+       case SNDRV_CTL_IOCTL_TLV_COMMAND:
+-              scoped_guard(rwsem_write, &ctl->card->controls_rwsem)
++              err = snd_power_ref_and_wait(card);
++              if (err < 0)
++                      return err;
++              scoped_guard(rwsem_write, &card->controls_rwsem)
+                       err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
++              snd_power_unref(card);
+               return err;
+       case SNDRV_CTL_IOCTL_POWER:
+               return -ENOPROTOOPT;
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-hda-realtek-refactor-and-simplify-samsung-galax.patch b/queue-6.11/alsa-hda-realtek-refactor-and-simplify-samsung-galax.patch
new file mode 100644 (file)
index 0000000..ef0827c
--- /dev/null
@@ -0,0 +1,581 @@
+From e2f577444abb8be078072eab1e447641f0c8f482 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Sep 2024 21:30:00 +0200
+Subject: ALSA: hda/realtek: Refactor and simplify Samsung Galaxy Book init
+
+From: Joshua Grisham <josh@joshuagrisham.com>
+
+[ Upstream commit 7e4d4b32ab9532bd1babcd5d0763d727ebb04be0 ]
+
+I have done a lot of analysis for these type of devices and collaborated
+quite a bit with Nick Weihs (author of the first patch submitted for this
+including adding samsung_helper.c). More information can be found in the
+issue on Github [1] including additional rationale and testing.
+
+The existing implementation includes a large number of equalizer coef
+values that are not necessary to actually init and enable the speaker
+amps, as well as create a somewhat worse sound profile. Users have
+reported "muffled" or "muddy" sound; more information about this including
+my analysis of the differences can be found in the linked Github issue.
+
+This patch refactors the "v2" version of ALC298_FIXUP_SAMSUNG_AMP to a much
+simpler implementation which removes the new samsung_helper.c, reuses more
+of the existing patch_realtek.c, and sends significantly fewer unnecessary
+coef values (including removing all of these EQ-specific coef values).
+
+A pcm_playback_hook is used to dynamically enable and disable the speaker
+amps only when there will be audio playback; this is to match the behavior
+of how the driver for these devices is working in Windows, and is
+suspected but not yet tested or confirmed to help with power consumption.
+
+Support for models with 2 speaker amps vs 4 speaker amps is controlled by
+a specific quirk name for both types. A new int num_speaker_amps has been
+added to alc_spec so that the hooks can know how many speaker amps to
+enable or disable. This design was chosen to limit the number of places
+that subsystem ids will need to be maintained: like this, they can be
+maintained only once in the quirk table and there will not be another
+separate list of subsystem ids to maintain elsewhere in the code.
+
+Also updated the quirk name from ALC298_FIXUP_SAMSUNG_AMP2 to
+ALC298_FIXUP_SAMSUNG_AMP_V2_.. as this is not a quirk for "Amp #2" on
+ALC298 but is instead a different version of how to handle it.
+
+More devices have been added (see Github issue for testing confirmation),
+as well as a small cleanup to existing names.
+
+[1]: https://github.com/thesofproject/linux/issues/4055#issuecomment-2323411911
+
+Signed-off-by: Joshua Grisham <josh@joshuagrisham.com>
+Link: https://patch.msgid.link/20240909193000.838815-1-josh@joshuagrisham.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c  | 151 +++++++++++++++-
+ sound/pci/hda/samsung_helper.c | 310 ---------------------------------
+ 2 files changed, 144 insertions(+), 317 deletions(-)
+ delete mode 100644 sound/pci/hda/samsung_helper.c
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 4035ec31e1baf..b1bf061b3edbe 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -125,6 +125,7 @@ struct alc_spec {
+       unsigned int has_hs_key:1;
+       unsigned int no_internal_mic_pin:1;
+       unsigned int en_3kpull_low:1;
++      int num_speaker_amps;
+       /* for PLL fix */
+       hda_nid_t pll_nid;
+@@ -4803,7 +4804,133 @@ static void alc298_fixup_samsung_amp(struct hda_codec *codec,
+       }
+ }
+-#include "samsung_helper.c"
++struct alc298_samsung_v2_amp_desc {
++      unsigned short nid;
++      int init_seq_size;
++      unsigned short init_seq[18][2];
++};
++
++static const struct alc298_samsung_v2_amp_desc
++alc298_samsung_v2_amp_desc_tbl[] = {
++      { 0x38, 18, {
++              { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
++              { 0x201b, 0x0001 }, { 0x201d, 0x0001 }, { 0x201f, 0x00fe },
++              { 0x2021, 0x0000 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
++              { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
++              { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x2399, 0x0003 },
++              { 0x23a4, 0x00b5 }, { 0x23a5, 0x0001 }, { 0x23ba, 0x0094 }
++      }},
++      { 0x39, 18, {
++              { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
++              { 0x201b, 0x0002 }, { 0x201d, 0x0002 }, { 0x201f, 0x00fd },
++              { 0x2021, 0x0001 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
++              { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
++              { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x2399, 0x0003 },
++              { 0x23a4, 0x00b5 }, { 0x23a5, 0x0001 }, { 0x23ba, 0x0094 }
++      }},
++      { 0x3c, 15, {
++              { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
++              { 0x201b, 0x0001 }, { 0x201d, 0x0001 }, { 0x201f, 0x00fe },
++              { 0x2021, 0x0000 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
++              { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
++              { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x23ba, 0x008d }
++      }},
++      { 0x3d, 15, {
++              { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
++              { 0x201b, 0x0002 }, { 0x201d, 0x0002 }, { 0x201f, 0x00fd },
++              { 0x2021, 0x0001 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
++              { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
++              { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x23ba, 0x008d }
++      }}
++};
++
++static void alc298_samsung_v2_enable_amps(struct hda_codec *codec)
++{
++      struct alc_spec *spec = codec->spec;
++      static const unsigned short enable_seq[][2] = {
++              { 0x203a, 0x0081 }, { 0x23ff, 0x0001 },
++      };
++      int i, j;
++
++      for (i = 0; i < spec->num_speaker_amps; i++) {
++              alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
++              for (j = 0; j < ARRAY_SIZE(enable_seq); j++)
++                      alc298_samsung_write_coef_pack(codec, enable_seq[j]);
++              codec_dbg(codec, "alc298_samsung_v2: Enabled speaker amp 0x%02x\n",
++                              alc298_samsung_v2_amp_desc_tbl[i].nid);
++      }
++}
++
++static void alc298_samsung_v2_disable_amps(struct hda_codec *codec)
++{
++      struct alc_spec *spec = codec->spec;
++      static const unsigned short disable_seq[][2] = {
++              { 0x23ff, 0x0000 }, { 0x203a, 0x0080 },
++      };
++      int i, j;
++
++      for (i = 0; i < spec->num_speaker_amps; i++) {
++              alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
++              for (j = 0; j < ARRAY_SIZE(disable_seq); j++)
++                      alc298_samsung_write_coef_pack(codec, disable_seq[j]);
++              codec_dbg(codec, "alc298_samsung_v2: Disabled speaker amp 0x%02x\n",
++                              alc298_samsung_v2_amp_desc_tbl[i].nid);
++      }
++}
++
++static void alc298_samsung_v2_playback_hook(struct hda_pcm_stream *hinfo,
++                              struct hda_codec *codec,
++                              struct snd_pcm_substream *substream,
++                              int action)
++{
++      /* Dynamically enable/disable speaker amps before and after playback */
++      if (action == HDA_GEN_PCM_ACT_OPEN)
++              alc298_samsung_v2_enable_amps(codec);
++      if (action == HDA_GEN_PCM_ACT_CLOSE)
++              alc298_samsung_v2_disable_amps(codec);
++}
++
++static void alc298_samsung_v2_init_amps(struct hda_codec *codec,
++                              int num_speaker_amps)
++{
++      struct alc_spec *spec = codec->spec;
++      int i, j;
++
++      /* Set spec's num_speaker_amps before doing anything else */
++      spec->num_speaker_amps = num_speaker_amps;
++
++      /* Disable speaker amps before init to prevent any physical damage */
++      alc298_samsung_v2_disable_amps(codec);
++
++      /* Initialize the speaker amps */
++      for (i = 0; i < spec->num_speaker_amps; i++) {
++              alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
++              for (j = 0; j < alc298_samsung_v2_amp_desc_tbl[i].init_seq_size; j++) {
++                      alc298_samsung_write_coef_pack(codec,
++                                      alc298_samsung_v2_amp_desc_tbl[i].init_seq[j]);
++              }
++              alc_write_coef_idx(codec, 0x89, 0x0);
++              codec_dbg(codec, "alc298_samsung_v2: Initialized speaker amp 0x%02x\n",
++                              alc298_samsung_v2_amp_desc_tbl[i].nid);
++      }
++
++      /* register hook to enable speaker amps only when they are needed */
++      spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook;
++}
++
++static void alc298_fixup_samsung_amp_v2_2_amps(struct hda_codec *codec,
++                              const struct hda_fixup *fix, int action)
++{
++      if (action == HDA_FIXUP_ACT_PROBE)
++              alc298_samsung_v2_init_amps(codec, 2);
++}
++
++static void alc298_fixup_samsung_amp_v2_4_amps(struct hda_codec *codec,
++                              const struct hda_fixup *fix, int action)
++{
++      if (action == HDA_FIXUP_ACT_PROBE)
++              alc298_samsung_v2_init_amps(codec, 4);
++}
+ #if IS_REACHABLE(CONFIG_INPUT)
+ static void gpio2_mic_hotkey_event(struct hda_codec *codec,
+@@ -7541,7 +7668,8 @@ enum {
+       ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
+       ALC236_FIXUP_LENOVO_INV_DMIC,
+       ALC298_FIXUP_SAMSUNG_AMP,
+-      ALC298_FIXUP_SAMSUNG_AMP2,
++      ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS,
++      ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS,
+       ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
+       ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
+       ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
+@@ -9176,9 +9304,13 @@ static const struct hda_fixup alc269_fixups[] = {
+               .chained = true,
+               .chain_id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET
+       },
+-      [ALC298_FIXUP_SAMSUNG_AMP2] = {
++      [ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS] = {
++              .type = HDA_FIXUP_FUNC,
++              .v.func = alc298_fixup_samsung_amp_v2_2_amps
++      },
++      [ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS] = {
+               .type = HDA_FIXUP_FUNC,
+-              .v.func = alc298_fixup_samsung_amp2
++              .v.func = alc298_fixup_samsung_amp_v2_4_amps
+       },
+       [ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
+               .type = HDA_FIXUP_VERBS,
+@@ -10558,8 +10690,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+       SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP),
+       SND_PCI_QUIRK(0x144d, 0xc868, "Samsung Galaxy Book2 Pro (NP930XED)", ALC298_FIXUP_SAMSUNG_AMP),
+-      SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG-KB1US)", ALC298_FIXUP_SAMSUNG_AMP2),
+-      SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH-XD92G))", ALC298_FIXUP_SAMSUNG_AMP2),
++      SND_PCI_QUIRK(0x144d, 0xc870, "Samsung Galaxy Book2 Pro (NP950XED)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
++      SND_PCI_QUIRK(0x144d, 0xc886, "Samsung Galaxy Book3 Pro (NP964XFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
++      SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
++      SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
+       SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
+@@ -10790,6 +10924,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1849, 0xa233, "Positivo Master C6300", ALC269_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1854, 0x0440, "LG CQ6", ALC256_FIXUP_HEADPHONE_AMP_VOL),
+       SND_PCI_QUIRK(0x1854, 0x0441, "LG CQ6 AIO", ALC256_FIXUP_HEADPHONE_AMP_VOL),
++      SND_PCI_QUIRK(0x1854, 0x0488, "LG gram 16 (16Z90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
++      SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
+       SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
+       SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
+@@ -11000,7 +11136,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
+       {.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
+       {.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
+       {.id = ALC298_FIXUP_SAMSUNG_AMP, .name = "alc298-samsung-amp"},
+-      {.id = ALC298_FIXUP_SAMSUNG_AMP2, .name = "alc298-samsung-amp2"},
++      {.id = ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS, .name = "alc298-samsung-amp-v2-2-amps"},
++      {.id = ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS, .name = "alc298-samsung-amp-v2-4-amps"},
+       {.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
+       {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
+       {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
+diff --git a/sound/pci/hda/samsung_helper.c b/sound/pci/hda/samsung_helper.c
+deleted file mode 100644
+index a40175b690157..0000000000000
+--- a/sound/pci/hda/samsung_helper.c
++++ /dev/null
+@@ -1,310 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-/* Helper functions for Samsung Galaxy Book3 audio initialization */
+-
+-struct alc298_samsung_coeff_fixup_desc {
+-      unsigned char coeff_idx;
+-      unsigned short coeff_value;
+-};
+-
+-struct alc298_samsung_coeff_seq_desc {
+-      unsigned short coeff_0x23;
+-      unsigned short coeff_0x24;
+-      unsigned short coeff_0x25;
+-      unsigned short coeff_0x26;
+-};
+-
+-
+-static inline void alc298_samsung_write_coef_pack2(struct hda_codec *codec,
+-                                                 const struct alc298_samsung_coeff_seq_desc *seq)
+-{
+-      int i;
+-
+-      for (i = 0; i < 100; i++) {
+-              if ((alc_read_coef_idx(codec, 0x26) & 0x0010) == 0)
+-                      break;
+-
+-              usleep_range(500, 1000);
+-      }
+-
+-      alc_write_coef_idx(codec, 0x23, seq->coeff_0x23);
+-      alc_write_coef_idx(codec, 0x24, seq->coeff_0x24);
+-      alc_write_coef_idx(codec, 0x25, seq->coeff_0x25);
+-      alc_write_coef_idx(codec, 0x26, seq->coeff_0x26);
+-}
+-
+-static inline void alc298_samsung_write_coef_pack_seq(
+-                                              struct hda_codec *codec,
+-                                              unsigned char target,
+-                                              const struct alc298_samsung_coeff_seq_desc seq[],
+-                                              int count)
+-{
+-      alc_write_coef_idx(codec, 0x22, target);
+-      for (int i = 0; i < count; i++)
+-              alc298_samsung_write_coef_pack2(codec, &seq[i]);
+-}
+-
+-static void alc298_fixup_samsung_amp2(struct hda_codec *codec,
+-                                    const struct hda_fixup *fix, int action)
+-{
+-      int i;
+-      static const struct alc298_samsung_coeff_fixup_desc fixups1[] = {
+-              { 0x99, 0x8000 }, { 0x82, 0x4408 }, { 0x32, 0x3f00 }, { 0x0e, 0x6f80 },
+-              { 0x10, 0x0e21 }, { 0x55, 0x8000 }, { 0x08, 0x2fcf }, { 0x08, 0x2fcf },
+-              { 0x2d, 0xc020 }, { 0x19, 0x0017 }, { 0x50, 0x1000 }, { 0x0e, 0x6f80 },
+-              { 0x08, 0x2fcf }, { 0x80, 0x0011 }, { 0x2b, 0x0c10 }, { 0x2d, 0xc020 },
+-              { 0x03, 0x0042 }, { 0x0f, 0x0062 }, { 0x08, 0x2fcf },
+-      };
+-
+-      static const struct alc298_samsung_coeff_seq_desc amp_0x38[] = {
+-              { 0x2000, 0x0000, 0x0001, 0xb011 }, { 0x23ff, 0x0000, 0x0000, 0xb011 },
+-              { 0x203a, 0x0000, 0x0080, 0xb011 }, { 0x23e1, 0x0000, 0x0000, 0xb011 },
+-              { 0x2012, 0x0000, 0x006f, 0xb011 }, { 0x2014, 0x0000, 0x0000, 0xb011 },
+-              { 0x201b, 0x0000, 0x0001, 0xb011 }, { 0x201d, 0x0000, 0x0001, 0xb011 },
+-              { 0x201f, 0x0000, 0x00fe, 0xb011 }, { 0x2021, 0x0000, 0x0000, 0xb011 },
+-              { 0x2022, 0x0000, 0x0010, 0xb011 }, { 0x203d, 0x0000, 0x0005, 0xb011 },
+-              { 0x203f, 0x0000, 0x0003, 0xb011 }, { 0x2050, 0x0000, 0x002c, 0xb011 },
+-              { 0x2076, 0x0000, 0x000e, 0xb011 }, { 0x207c, 0x0000, 0x004a, 0xb011 },
+-              { 0x2081, 0x0000, 0x0003, 0xb011 }, { 0x2399, 0x0000, 0x0003, 0xb011 },
+-              { 0x23a4, 0x0000, 0x00b5, 0xb011 }, { 0x23a5, 0x0000, 0x0001, 0xb011 },
+-              { 0x23ba, 0x0000, 0x0094, 0xb011 }, { 0x2100, 0x00d0, 0x950e, 0xb017 },
+-              { 0x2104, 0x0061, 0xd4e2, 0xb017 }, { 0x2108, 0x00d0, 0x950e, 0xb017 },
+-              { 0x210c, 0x0075, 0xf4e2, 0xb017 }, { 0x2110, 0x00b4, 0x4b0d, 0xb017 },
+-              { 0x2114, 0x000a, 0x1000, 0xb017 }, { 0x2118, 0x0015, 0x2000, 0xb017 },
+-              { 0x211c, 0x000a, 0x1000, 0xb017 }, { 0x2120, 0x0075, 0xf4e2, 0xb017 },
+-              { 0x2124, 0x00b4, 0x4b0d, 0xb017 }, { 0x2128, 0x0000, 0x0010, 0xb017 },
+-              { 0x212c, 0x0000, 0x0000, 0xb017 }, { 0x2130, 0x0000, 0x0000, 0xb017 },
+-              { 0x2134, 0x0000, 0x0000, 0xb017 }, { 0x2138, 0x0000, 0x0000, 0xb017 },
+-              { 0x213c, 0x0000, 0x0010, 0xb017 }, { 0x2140, 0x0000, 0x0000, 0xb017 },
+-              { 0x2144, 0x0000, 0x0000, 0xb017 }, { 0x2148, 0x0000, 0x0000, 0xb017 },
+-              { 0x214c, 0x0000, 0x0000, 0xb017 }, { 0x2150, 0x0000, 0x0010, 0xb017 },
+-              { 0x2154, 0x0000, 0x0000, 0xb017 }, { 0x2158, 0x0000, 0x0000, 0xb017 },
+-              { 0x215c, 0x0000, 0x0000, 0xb017 }, { 0x2160, 0x0000, 0x0000, 0xb017 },
+-              { 0x2164, 0x0000, 0x0010, 0xb017 }, { 0x2168, 0x0000, 0x0000, 0xb017 },
+-              { 0x216c, 0x0000, 0x0000, 0xb017 }, { 0x2170, 0x0000, 0x0000, 0xb017 },
+-              { 0x2174, 0x0000, 0x0000, 0xb017 }, { 0x2178, 0x0000, 0x0010, 0xb017 },
+-              { 0x217c, 0x0000, 0x0000, 0xb017 }, { 0x2180, 0x0000, 0x0000, 0xb017 },
+-              { 0x2184, 0x0000, 0x0000, 0xb017 }, { 0x2188, 0x0000, 0x0000, 0xb017 },
+-              { 0x218c, 0x0064, 0x5800, 0xb017 }, { 0x2190, 0x00c8, 0xb000, 0xb017 },
+-              { 0x2194, 0x0064, 0x5800, 0xb017 }, { 0x2198, 0x003d, 0x5be7, 0xb017 },
+-              { 0x219c, 0x0054, 0x060a, 0xb017 }, { 0x21a0, 0x00c8, 0xa310, 0xb017 },
+-              { 0x21a4, 0x0029, 0x4de5, 0xb017 }, { 0x21a8, 0x0032, 0x420c, 0xb017 },
+-              { 0x21ac, 0x0029, 0x4de5, 0xb017 }, { 0x21b0, 0x00fa, 0xe50c, 0xb017 },
+-              { 0x21b4, 0x0000, 0x0010, 0xb017 }, { 0x21b8, 0x0000, 0x0000, 0xb017 },
+-              { 0x21bc, 0x0000, 0x0000, 0xb017 }, { 0x21c0, 0x0000, 0x0000, 0xb017 },
+-              { 0x21c4, 0x0000, 0x0000, 0xb017 }, { 0x21c8, 0x0056, 0xc50f, 0xb017 },
+-              { 0x21cc, 0x007b, 0xd7e1, 0xb017 }, { 0x21d0, 0x0077, 0xa70e, 0xb017 },
+-              { 0x21d4, 0x00e0, 0xbde1, 0xb017 }, { 0x21d8, 0x0032, 0x530e, 0xb017 },
+-              { 0x2204, 0x00fb, 0x7e0f, 0xb017 }, { 0x2208, 0x000b, 0x02e1, 0xb017 },
+-              { 0x220c, 0x00fb, 0x7e0f, 0xb017 }, { 0x2210, 0x00d5, 0x17e1, 0xb017 },
+-              { 0x2214, 0x00c0, 0x130f, 0xb017 }, { 0x2218, 0x00e5, 0x0a00, 0xb017 },
+-              { 0x221c, 0x00cb, 0x1500, 0xb017 }, { 0x2220, 0x00e5, 0x0a00, 0xb017 },
+-              { 0x2224, 0x00d5, 0x17e1, 0xb017 }, { 0x2228, 0x00c0, 0x130f, 0xb017 },
+-              { 0x222c, 0x00f5, 0xdb0e, 0xb017 }, { 0x2230, 0x0017, 0x48e2, 0xb017 },
+-              { 0x2234, 0x00f5, 0xdb0e, 0xb017 }, { 0x2238, 0x00ef, 0x5ce2, 0xb017 },
+-              { 0x223c, 0x00c1, 0xcc0d, 0xb017 }, { 0x2240, 0x00f5, 0xdb0e, 0xb017 },
+-              { 0x2244, 0x0017, 0x48e2, 0xb017 }, { 0x2248, 0x00f5, 0xdb0e, 0xb017 },
+-              { 0x224c, 0x00ef, 0x5ce2, 0xb017 }, { 0x2250, 0x00c1, 0xcc0d, 0xb017 },
+-              { 0x2254, 0x00f5, 0xdb0e, 0xb017 }, { 0x2258, 0x0017, 0x48e2, 0xb017 },
+-              { 0x225c, 0x00f5, 0xdb0e, 0xb017 }, { 0x2260, 0x00ef, 0x5ce2, 0xb017 },
+-              { 0x2264, 0x00c1, 0xcc0d, 0xb017 }, { 0x2268, 0x00f5, 0xdb0e, 0xb017 },
+-              { 0x226c, 0x0017, 0x48e2, 0xb017 }, { 0x2270, 0x00f5, 0xdb0e, 0xb017 },
+-              { 0x2274, 0x00ef, 0x5ce2, 0xb017 }, { 0x2278, 0x00c1, 0xcc0d, 0xb017 },
+-              { 0x227c, 0x00f5, 0xdb0e, 0xb017 }, { 0x2280, 0x0017, 0x48e2, 0xb017 },
+-              { 0x2284, 0x00f5, 0xdb0e, 0xb017 }, { 0x2288, 0x00ef, 0x5ce2, 0xb017 },
+-              { 0x228c, 0x00c1, 0xcc0d, 0xb017 }, { 0x22cc, 0x00e8, 0x8d00, 0xb017 },
+-              { 0x22d0, 0x0000, 0x0000, 0xb017 }, { 0x22d4, 0x0018, 0x72ff, 0xb017 },
+-              { 0x22d8, 0x00ce, 0x25e1, 0xb017 }, { 0x22dc, 0x002f, 0xe40e, 0xb017 },
+-              { 0x238e, 0x0000, 0x0099, 0xb011 }, { 0x238f, 0x0000, 0x0011, 0xb011 },
+-              { 0x2390, 0x0000, 0x0056, 0xb011 }, { 0x2391, 0x0000, 0x0004, 0xb011 },
+-              { 0x2392, 0x0000, 0x00bb, 0xb011 }, { 0x2393, 0x0000, 0x006d, 0xb011 },
+-              { 0x2394, 0x0000, 0x0010, 0xb011 }, { 0x2395, 0x0000, 0x0064, 0xb011 },
+-              { 0x2396, 0x0000, 0x00b6, 0xb011 }, { 0x2397, 0x0000, 0x0028, 0xb011 },
+-              { 0x2398, 0x0000, 0x000b, 0xb011 }, { 0x239a, 0x0000, 0x0099, 0xb011 },
+-              { 0x239b, 0x0000, 0x000d, 0xb011 }, { 0x23a6, 0x0000, 0x0064, 0xb011 },
+-              { 0x23a7, 0x0000, 0x0078, 0xb011 }, { 0x23b9, 0x0000, 0x0000, 0xb011 },
+-              { 0x23e0, 0x0000, 0x0021, 0xb011 }, { 0x23e1, 0x0000, 0x0001, 0xb011 },
+-      };
+-
+-      static const struct alc298_samsung_coeff_seq_desc amp_0x39[] = {
+-              { 0x2000, 0x0000, 0x0001, 0xb011 }, { 0x23ff, 0x0000, 0x0000, 0xb011 },
+-              { 0x203a, 0x0000, 0x0080, 0xb011 }, { 0x23e1, 0x0000, 0x0000, 0xb011 },
+-              { 0x2012, 0x0000, 0x006f, 0xb011 }, { 0x2014, 0x0000, 0x0000, 0xb011 },
+-              { 0x201b, 0x0000, 0x0002, 0xb011 }, { 0x201d, 0x0000, 0x0002, 0xb011 },
+-              { 0x201f, 0x0000, 0x00fd, 0xb011 }, { 0x2021, 0x0000, 0x0001, 0xb011 },
+-              { 0x2022, 0x0000, 0x0010, 0xb011 }, { 0x203d, 0x0000, 0x0005, 0xb011 },
+-              { 0x203f, 0x0000, 0x0003, 0xb011 }, { 0x2050, 0x0000, 0x002c, 0xb011 },
+-              { 0x2076, 0x0000, 0x000e, 0xb011 }, { 0x207c, 0x0000, 0x004a, 0xb011 },
+-              { 0x2081, 0x0000, 0x0003, 0xb011 }, { 0x2399, 0x0000, 0x0003, 0xb011 },
+-              { 0x23a4, 0x0000, 0x00b5, 0xb011 }, { 0x23a5, 0x0000, 0x0001, 0xb011 },
+-              { 0x23ba, 0x0000, 0x0094, 0xb011 }, { 0x2100, 0x00d0, 0x950e, 0xb017 },
+-              { 0x2104, 0x0061, 0xd4e2, 0xb017 }, { 0x2108, 0x00d0, 0x950e, 0xb017 },
+-              { 0x210c, 0x0075, 0xf4e2, 0xb017 }, { 0x2110, 0x00b4, 0x4b0d, 0xb017 },
+-              { 0x2114, 0x000a, 0x1000, 0xb017 }, { 0x2118, 0x0015, 0x2000, 0xb017 },
+-              { 0x211c, 0x000a, 0x1000, 0xb017 }, { 0x2120, 0x0075, 0xf4e2, 0xb017 },
+-              { 0x2124, 0x00b4, 0x4b0d, 0xb017 }, { 0x2128, 0x0000, 0x0010, 0xb017 },
+-              { 0x212c, 0x0000, 0x0000, 0xb017 }, { 0x2130, 0x0000, 0x0000, 0xb017 },
+-              { 0x2134, 0x0000, 0x0000, 0xb017 }, { 0x2138, 0x0000, 0x0000, 0xb017 },
+-              { 0x213c, 0x0000, 0x0010, 0xb017 }, { 0x2140, 0x0000, 0x0000, 0xb017 },
+-              { 0x2144, 0x0000, 0x0000, 0xb017 }, { 0x2148, 0x0000, 0x0000, 0xb017 },
+-              { 0x214c, 0x0000, 0x0000, 0xb017 }, { 0x2150, 0x0000, 0x0010, 0xb017 },
+-              { 0x2154, 0x0000, 0x0000, 0xb017 }, { 0x2158, 0x0000, 0x0000, 0xb017 },
+-              { 0x215c, 0x0000, 0x0000, 0xb017 }, { 0x2160, 0x0000, 0x0000, 0xb017 },
+-              { 0x2164, 0x0000, 0x0010, 0xb017 }, { 0x2168, 0x0000, 0x0000, 0xb017 },
+-              { 0x216c, 0x0000, 0x0000, 0xb017 }, { 0x2170, 0x0000, 0x0000, 0xb017 },
+-              { 0x2174, 0x0000, 0x0000, 0xb017 }, { 0x2178, 0x0000, 0x0010, 0xb017 },
+-              { 0x217c, 0x0000, 0x0000, 0xb017 }, { 0x2180, 0x0000, 0x0000, 0xb017 },
+-              { 0x2184, 0x0000, 0x0000, 0xb017 }, { 0x2188, 0x0000, 0x0000, 0xb017 },
+-              { 0x218c, 0x0064, 0x5800, 0xb017 }, { 0x2190, 0x00c8, 0xb000, 0xb017 },
+-              { 0x2194, 0x0064, 0x5800, 0xb017 }, { 0x2198, 0x003d, 0x5be7, 0xb017 },
+-              { 0x219c, 0x0054, 0x060a, 0xb017 }, { 0x21a0, 0x00c8, 0xa310, 0xb017 },
+-              { 0x21a4, 0x0029, 0x4de5, 0xb017 }, { 0x21a8, 0x0032, 0x420c, 0xb017 },
+-              { 0x21ac, 0x0029, 0x4de5, 0xb017 }, { 0x21b0, 0x00fa, 0xe50c, 0xb017 },
+-              { 0x21b4, 0x0000, 0x0010, 0xb017 }, { 0x21b8, 0x0000, 0x0000, 0xb017 },
+-              { 0x21bc, 0x0000, 0x0000, 0xb017 }, { 0x21c0, 0x0000, 0x0000, 0xb017 },
+-              { 0x21c4, 0x0000, 0x0000, 0xb017 }, { 0x21c8, 0x0056, 0xc50f, 0xb017 },
+-              { 0x21cc, 0x007b, 0xd7e1, 0xb017 }, { 0x21d0, 0x0077, 0xa70e, 0xb017 },
+-              { 0x21d4, 0x00e0, 0xbde1, 0xb017 }, { 0x21d8, 0x0032, 0x530e, 0xb017 },
+-              { 0x2204, 0x00fb, 0x7e0f, 0xb017 }, { 0x2208, 0x000b, 0x02e1, 0xb017 },
+-              { 0x220c, 0x00fb, 0x7e0f, 0xb017 }, { 0x2210, 0x00d5, 0x17e1, 0xb017 },
+-              { 0x2214, 0x00c0, 0x130f, 0xb017 }, { 0x2218, 0x00e5, 0x0a00, 0xb017 },
+-              { 0x221c, 0x00cb, 0x1500, 0xb017 }, { 0x2220, 0x00e5, 0x0a00, 0xb017 },
+-              { 0x2224, 0x00d5, 0x17e1, 0xb017 }, { 0x2228, 0x00c0, 0x130f, 0xb017 },
+-              { 0x222c, 0x00f5, 0xdb0e, 0xb017 }, { 0x2230, 0x0017, 0x48e2, 0xb017 },
+-              { 0x2234, 0x00f5, 0xdb0e, 0xb017 }, { 0x2238, 0x00ef, 0x5ce2, 0xb017 },
+-              { 0x223c, 0x00c1, 0xcc0d, 0xb017 }, { 0x2240, 0x00f5, 0xdb0e, 0xb017 },
+-              { 0x2244, 0x0017, 0x48e2, 0xb017 }, { 0x2248, 0x00f5, 0xdb0e, 0xb017 },
+-              { 0x224c, 0x00ef, 0x5ce2, 0xb017 }, { 0x2250, 0x00c1, 0xcc0d, 0xb017 },
+-              { 0x2254, 0x00f5, 0xdb0e, 0xb017 }, { 0x2258, 0x0017, 0x48e2, 0xb017 },
+-              { 0x225c, 0x00f5, 0xdb0e, 0xb017 }, { 0x2260, 0x00ef, 0x5ce2, 0xb017 },
+-              { 0x2264, 0x00c1, 0xcc0d, 0xb017 }, { 0x2268, 0x00f5, 0xdb0e, 0xb017 },
+-              { 0x226c, 0x0017, 0x48e2, 0xb017 }, { 0x2270, 0x00f5, 0xdb0e, 0xb017 },
+-              { 0x2274, 0x00ef, 0x5ce2, 0xb017 }, { 0x2278, 0x00c1, 0xcc0d, 0xb017 },
+-              { 0x227c, 0x00f5, 0xdb0e, 0xb017 }, { 0x2280, 0x0017, 0x48e2, 0xb017 },
+-              { 0x2284, 0x00f5, 0xdb0e, 0xb017 }, { 0x2288, 0x00ef, 0x5ce2, 0xb017 },
+-              { 0x228c, 0x00c1, 0xcc0d, 0xb017 }, { 0x22cc, 0x00e8, 0x8d00, 0xb017 },
+-              { 0x22d0, 0x0000, 0x0000, 0xb017 }, { 0x22d4, 0x0018, 0x72ff, 0xb017 },
+-              { 0x22d8, 0x00ce, 0x25e1, 0xb017 }, { 0x22dc, 0x002f, 0xe40e, 0xb017 },
+-              { 0x238e, 0x0000, 0x0099, 0xb011 }, { 0x238f, 0x0000, 0x0011, 0xb011 },
+-              { 0x2390, 0x0000, 0x0056, 0xb011 }, { 0x2391, 0x0000, 0x0004, 0xb011 },
+-              { 0x2392, 0x0000, 0x00bb, 0xb011 }, { 0x2393, 0x0000, 0x006d, 0xb011 },
+-              { 0x2394, 0x0000, 0x0010, 0xb011 }, { 0x2395, 0x0000, 0x0064, 0xb011 },
+-              { 0x2396, 0x0000, 0x00b6, 0xb011 }, { 0x2397, 0x0000, 0x0028, 0xb011 },
+-              { 0x2398, 0x0000, 0x000b, 0xb011 }, { 0x239a, 0x0000, 0x0099, 0xb011 },
+-              { 0x239b, 0x0000, 0x000d, 0xb011 }, { 0x23a6, 0x0000, 0x0064, 0xb011 },
+-              { 0x23a7, 0x0000, 0x0078, 0xb011 }, { 0x23b9, 0x0000, 0x0000, 0xb011 },
+-              { 0x23e0, 0x0000, 0x0021, 0xb011 }, { 0x23e1, 0x0000, 0x0001, 0xb011 },
+-      };
+-
+-      static const struct alc298_samsung_coeff_seq_desc amp_0x3c[] = {
+-              { 0x2000, 0x0000, 0x0001, 0xb011 }, { 0x23ff, 0x0000, 0x0000, 0xb011 },
+-              { 0x203a, 0x0000, 0x0080, 0xb011 }, { 0x23e1, 0x0000, 0x0000, 0xb011 },
+-              { 0x2012, 0x0000, 0x006f, 0xb011 }, { 0x2014, 0x0000, 0x0000, 0xb011 },
+-              { 0x201b, 0x0000, 0x0001, 0xb011 }, { 0x201d, 0x0000, 0x0001, 0xb011 },
+-              { 0x201f, 0x0000, 0x00fe, 0xb011 }, { 0x2021, 0x0000, 0x0000, 0xb011 },
+-              { 0x2022, 0x0000, 0x0010, 0xb011 }, { 0x203d, 0x0000, 0x0005, 0xb011 },
+-              { 0x203f, 0x0000, 0x0003, 0xb011 }, { 0x2050, 0x0000, 0x002c, 0xb011 },
+-              { 0x2076, 0x0000, 0x000e, 0xb011 }, { 0x207c, 0x0000, 0x004a, 0xb011 },
+-              { 0x2081, 0x0000, 0x0003, 0xb011 }, { 0x23ba, 0x0000, 0x008d, 0xb011 },
+-              { 0x2128, 0x0005, 0x460d, 0xb017 }, { 0x212c, 0x00f6, 0x73e5, 0xb017 },
+-              { 0x2130, 0x0005, 0x460d, 0xb017 }, { 0x2134, 0x00c0, 0xe9e5, 0xb017 },
+-              { 0x2138, 0x00d5, 0x010b, 0xb017 }, { 0x213c, 0x009d, 0x7809, 0xb017 },
+-              { 0x2140, 0x00c5, 0x0eed, 0xb017 }, { 0x2144, 0x009d, 0x7809, 0xb017 },
+-              { 0x2148, 0x00c4, 0x4ef0, 0xb017 }, { 0x214c, 0x003a, 0x3106, 0xb017 },
+-              { 0x2150, 0x00af, 0x750e, 0xb017 }, { 0x2154, 0x008c, 0x1ff1, 0xb017 },
+-              { 0x2158, 0x009e, 0x360c, 0xb017 }, { 0x215c, 0x008c, 0x1ff1, 0xb017 },
+-              { 0x2160, 0x004d, 0xac0a, 0xb017 }, { 0x2164, 0x007d, 0xa00f, 0xb017 },
+-              { 0x2168, 0x00e1, 0x9ce3, 0xb017 }, { 0x216c, 0x00e8, 0x590e, 0xb017 },
+-              { 0x2170, 0x00e1, 0x9ce3, 0xb017 }, { 0x2174, 0x0066, 0xfa0d, 0xb017 },
+-              { 0x2178, 0x0000, 0x0010, 0xb017 }, { 0x217c, 0x0000, 0x0000, 0xb017 },
+-              { 0x2180, 0x0000, 0x0000, 0xb017 }, { 0x2184, 0x0000, 0x0000, 0xb017 },
+-              { 0x2188, 0x0000, 0x0000, 0xb017 }, { 0x218c, 0x0000, 0x0010, 0xb017 },
+-              { 0x2190, 0x0000, 0x0000, 0xb017 }, { 0x2194, 0x0000, 0x0000, 0xb017 },
+-              { 0x2198, 0x0000, 0x0000, 0xb017 }, { 0x219c, 0x0000, 0x0000, 0xb017 },
+-              { 0x21a0, 0x0000, 0x0010, 0xb017 }, { 0x21a4, 0x0000, 0x0000, 0xb017 },
+-              { 0x21a8, 0x0000, 0x0000, 0xb017 }, { 0x21ac, 0x0000, 0x0000, 0xb017 },
+-              { 0x21b0, 0x0000, 0x0000, 0xb017 }, { 0x21b4, 0x0000, 0x0010, 0xb017 },
+-              { 0x21b8, 0x0000, 0x0000, 0xb017 }, { 0x21bc, 0x0000, 0x0000, 0xb017 },
+-              { 0x21c0, 0x0000, 0x0000, 0xb017 }, { 0x21c4, 0x0000, 0x0000, 0xb017 },
+-              { 0x23b9, 0x0000, 0x0000, 0xb011 }, { 0x23e0, 0x0000, 0x0020, 0xb011 },
+-              { 0x23e1, 0x0000, 0x0001, 0xb011 },
+-      };
+-
+-      static const struct alc298_samsung_coeff_seq_desc amp_0x3d[] = {
+-              { 0x2000, 0x0000, 0x0001, 0xb011 }, { 0x23ff, 0x0000, 0x0000, 0xb011 },
+-              { 0x203a, 0x0000, 0x0080, 0xb011 }, { 0x23e1, 0x0000, 0x0000, 0xb011 },
+-              { 0x2012, 0x0000, 0x006f, 0xb011 }, { 0x2014, 0x0000, 0x0000, 0xb011 },
+-              { 0x201b, 0x0000, 0x0002, 0xb011 }, { 0x201d, 0x0000, 0x0002, 0xb011 },
+-              { 0x201f, 0x0000, 0x00fd, 0xb011 }, { 0x2021, 0x0000, 0x0001, 0xb011 },
+-              { 0x2022, 0x0000, 0x0010, 0xb011 }, { 0x203d, 0x0000, 0x0005, 0xb011 },
+-              { 0x203f, 0x0000, 0x0003, 0xb011 }, { 0x2050, 0x0000, 0x002c, 0xb011 },
+-              { 0x2076, 0x0000, 0x000e, 0xb011 }, { 0x207c, 0x0000, 0x004a, 0xb011 },
+-              { 0x2081, 0x0000, 0x0003, 0xb011 }, { 0x23ba, 0x0000, 0x008d, 0xb011 },
+-              { 0x2128, 0x0005, 0x460d, 0xb017 }, { 0x212c, 0x00f6, 0x73e5, 0xb017 },
+-              { 0x2130, 0x0005, 0x460d, 0xb017 }, { 0x2134, 0x00c0, 0xe9e5, 0xb017 },
+-              { 0x2138, 0x00d5, 0x010b, 0xb017 }, { 0x213c, 0x009d, 0x7809, 0xb017 },
+-              { 0x2140, 0x00c5, 0x0eed, 0xb017 }, { 0x2144, 0x009d, 0x7809, 0xb017 },
+-              { 0x2148, 0x00c4, 0x4ef0, 0xb017 }, { 0x214c, 0x003a, 0x3106, 0xb017 },
+-              { 0x2150, 0x00af, 0x750e, 0xb017 }, { 0x2154, 0x008c, 0x1ff1, 0xb017 },
+-              { 0x2158, 0x009e, 0x360c, 0xb017 }, { 0x215c, 0x008c, 0x1ff1, 0xb017 },
+-              { 0x2160, 0x004d, 0xac0a, 0xb017 }, { 0x2164, 0x007d, 0xa00f, 0xb017 },
+-              { 0x2168, 0x00e1, 0x9ce3, 0xb017 }, { 0x216c, 0x00e8, 0x590e, 0xb017 },
+-              { 0x2170, 0x00e1, 0x9ce3, 0xb017 }, { 0x2174, 0x0066, 0xfa0d, 0xb017 },
+-              { 0x2178, 0x0000, 0x0010, 0xb017 }, { 0x217c, 0x0000, 0x0000, 0xb017 },
+-              { 0x2180, 0x0000, 0x0000, 0xb017 }, { 0x2184, 0x0000, 0x0000, 0xb017 },
+-              { 0x2188, 0x0000, 0x0000, 0xb017 }, { 0x218c, 0x0000, 0x0010, 0xb017 },
+-              { 0x2190, 0x0000, 0x0000, 0xb017 }, { 0x2194, 0x0000, 0x0000, 0xb017 },
+-              { 0x2198, 0x0000, 0x0000, 0xb017 }, { 0x219c, 0x0000, 0x0000, 0xb017 },
+-              { 0x21a0, 0x0000, 0x0010, 0xb017 }, { 0x21a4, 0x0000, 0x0000, 0xb017 },
+-              { 0x21a8, 0x0000, 0x0000, 0xb017 }, { 0x21ac, 0x0000, 0x0000, 0xb017 },
+-              { 0x21b0, 0x0000, 0x0000, 0xb017 }, { 0x21b4, 0x0000, 0x0010, 0xb017 },
+-              { 0x21b8, 0x0000, 0x0000, 0xb017 }, { 0x21bc, 0x0000, 0x0000, 0xb017 },
+-              { 0x21c0, 0x0000, 0x0000, 0xb017 }, { 0x21c4, 0x0000, 0x0000, 0xb017 },
+-              { 0x23b9, 0x0000, 0x0000, 0xb011 }, { 0x23e0, 0x0000, 0x0020, 0xb011 },
+-              { 0x23e1, 0x0000, 0x0001, 0xb011 },
+-      };
+-
+-      static const struct alc298_samsung_coeff_seq_desc amp_seq1[] = {
+-              { 0x23ff, 0x0000, 0x0000, 0xb011 }, { 0x203a, 0x0000, 0x0080, 0xb011 },
+-      };
+-
+-      static const struct alc298_samsung_coeff_fixup_desc fixups2[] = {
+-              { 0x4f, 0xb029 }, { 0x05, 0x2be0 }, { 0x30, 0x2421 },
+-      };
+-
+-
+-      static const struct alc298_samsung_coeff_seq_desc amp_seq2[] = {
+-              { 0x203a, 0x0000, 0x0081, 0xb011 }, { 0x23ff, 0x0000, 0x0001, 0xb011 },
+-      };
+-
+-      if (action != HDA_FIXUP_ACT_INIT)
+-              return;
+-
+-      // First set of fixups
+-      for (i = 0; i < ARRAY_SIZE(fixups1); i++)
+-              alc_write_coef_idx(codec, fixups1[i].coeff_idx, fixups1[i].coeff_value);
+-
+-      // First set of writes
+-      alc298_samsung_write_coef_pack_seq(codec, 0x38, amp_0x38, ARRAY_SIZE(amp_0x38));
+-      alc298_samsung_write_coef_pack_seq(codec, 0x39, amp_0x39, ARRAY_SIZE(amp_0x39));
+-      alc298_samsung_write_coef_pack_seq(codec, 0x3c, amp_0x3c, ARRAY_SIZE(amp_0x3c));
+-      alc298_samsung_write_coef_pack_seq(codec, 0x3d, amp_0x3d, ARRAY_SIZE(amp_0x3d));
+-
+-      // Second set of writes
+-      alc298_samsung_write_coef_pack_seq(codec, 0x38, amp_seq1, ARRAY_SIZE(amp_seq1));
+-      alc298_samsung_write_coef_pack_seq(codec, 0x39, amp_seq1, ARRAY_SIZE(amp_seq1));
+-      alc298_samsung_write_coef_pack_seq(codec, 0x3c, amp_seq1, ARRAY_SIZE(amp_seq1));
+-      alc298_samsung_write_coef_pack_seq(codec, 0x3d, amp_seq1, ARRAY_SIZE(amp_seq1));
+-
+-      // Second set of fixups
+-      for (i = 0; i < ARRAY_SIZE(fixups2); i++)
+-              alc_write_coef_idx(codec, fixups2[i].coeff_idx, fixups2[i].coeff_value);
+-
+-      // Third set of writes
+-      alc298_samsung_write_coef_pack_seq(codec, 0x38, amp_seq2, ARRAY_SIZE(amp_seq2));
+-      alc298_samsung_write_coef_pack_seq(codec, 0x39, amp_seq2, ARRAY_SIZE(amp_seq2));
+-      alc298_samsung_write_coef_pack_seq(codec, 0x3c, amp_seq2, ARRAY_SIZE(amp_seq2));
+-      alc298_samsung_write_coef_pack_seq(codec, 0x3d, amp_seq2, ARRAY_SIZE(amp_seq2));
+-
+-      // Final fixup
+-      alc_write_coef_idx(codec, 0x10, 0x0F21);
+-}
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-hdsp-break-infinite-midi-input-flush-loop.patch b/queue-6.11/alsa-hdsp-break-infinite-midi-input-flush-loop.patch
new file mode 100644 (file)
index 0000000..4c1af27
--- /dev/null
@@ -0,0 +1,60 @@
+From a68666758224a33e66afd8deeca56d47424f0b8e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Aug 2024 11:15:12 +0200
+Subject: ALSA: hdsp: Break infinite MIDI input flush loop
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit c01f3815453e2d5f699ccd8c8c1f93a5b8669e59 ]
+
+The current MIDI input flush on HDSP and HDSPM drivers relies on the
+hardware reporting the right value.  If the hardware doesn't give the
+proper value but returns -1, it may be stuck at an infinite loop.
+
+Add a counter and break if the loop is unexpectedly too long.
+
+Link: https://patch.msgid.link/20240808091513.31380-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/rme9652/hdsp.c  | 6 ++++--
+ sound/pci/rme9652/hdspm.c | 6 ++++--
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
+index e7d1b43471a29..713ca262a0e97 100644
+--- a/sound/pci/rme9652/hdsp.c
++++ b/sound/pci/rme9652/hdsp.c
+@@ -1298,8 +1298,10 @@ static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id)
+ static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id)
+ {
+-      while (snd_hdsp_midi_input_available (hdsp, id))
+-              snd_hdsp_midi_read_byte (hdsp, id);
++      int count = 256;
++
++      while (snd_hdsp_midi_input_available(hdsp, id) && --count)
++              snd_hdsp_midi_read_byte(hdsp, id);
+ }
+ static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi)
+diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
+index 267c7848974ae..74215f57f4fc9 100644
+--- a/sound/pci/rme9652/hdspm.c
++++ b/sound/pci/rme9652/hdspm.c
+@@ -1838,8 +1838,10 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
+ static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
+ {
+-      while (snd_hdspm_midi_input_available (hdspm, id))
+-              snd_hdspm_midi_read_byte (hdspm, id);
++      int count = 256;
++
++      while (snd_hdspm_midi_input_available(hdspm, id) && --count)
++              snd_hdspm_midi_read_byte(hdspm, id);
+ }
+ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-usb-audio-add-input-value-sanity-checks-for-sta.patch b/queue-6.11/alsa-usb-audio-add-input-value-sanity-checks-for-sta.patch
new file mode 100644 (file)
index 0000000..6926c7c
--- /dev/null
@@ -0,0 +1,140 @@
+From 2280a3daa8113dfa555d20fcbc548ed13891965e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 14:46:50 +0200
+Subject: ALSA: usb-audio: Add input value sanity checks for standard types
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 901e85677ec0bb9a69fb9eab1feafe0c4eb7d07e ]
+
+For an invalid input value that is out of the given range, currently
+USB-audio driver corrects the value silently and accepts without
+errors.  This is no wrong behavior, per se, but the recent kselftest
+rather wants to have an error in such a case, hence a different
+behavior is expected now.
+
+This patch adds a sanity check at each control put for the standard
+mixer types and returns an error if an invalid value is given.
+
+Note that this covers only the standard mixer types.  The mixer quirks
+that have own control callbacks would need different coverage.
+
+Link: https://patch.msgid.link/20240806124651.28203-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer.c | 35 +++++++++++++++++++++++++++--------
+ sound/usb/mixer.h |  1 +
+ 2 files changed, 28 insertions(+), 8 deletions(-)
+
+diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
+index f7ce8e8c3c3ea..2d27d729c3bea 100644
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -1377,6 +1377,19 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
+ #define get_min_max(cval, def)        get_min_max_with_quirks(cval, def, NULL)
++/* get the max value advertised via control API */
++static int get_max_exposed(struct usb_mixer_elem_info *cval)
++{
++      if (!cval->max_exposed) {
++              if (cval->res)
++                      cval->max_exposed =
++                              DIV_ROUND_UP(cval->max - cval->min, cval->res);
++              else
++                      cval->max_exposed = cval->max - cval->min;
++      }
++      return cval->max_exposed;
++}
++
+ /* get a feature/mixer unit info */
+ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_info *uinfo)
+@@ -1389,11 +1402,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
+       else
+               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = cval->channels;
+-      if (cval->val_type == USB_MIXER_BOOLEAN ||
+-          cval->val_type == USB_MIXER_INV_BOOLEAN) {
+-              uinfo->value.integer.min = 0;
+-              uinfo->value.integer.max = 1;
+-      } else {
++      if (cval->val_type != USB_MIXER_BOOLEAN &&
++          cval->val_type != USB_MIXER_INV_BOOLEAN) {
+               if (!cval->initialized) {
+                       get_min_max_with_quirks(cval, 0, kcontrol);
+                       if (cval->initialized && cval->dBmin >= cval->dBmax) {
+@@ -1405,10 +1415,10 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
+                                              &kcontrol->id);
+                       }
+               }
+-              uinfo->value.integer.min = 0;
+-              uinfo->value.integer.max =
+-                      DIV_ROUND_UP(cval->max - cval->min, cval->res);
+       }
++
++      uinfo->value.integer.min = 0;
++      uinfo->value.integer.max = get_max_exposed(cval);
+       return 0;
+ }
+@@ -1449,6 +1459,7 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+ {
+       struct usb_mixer_elem_info *cval = kcontrol->private_data;
++      int max_val = get_max_exposed(cval);
+       int c, cnt, val, oval, err;
+       int changed = 0;
+@@ -1461,6 +1472,8 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
+                       if (err < 0)
+                               return filter_error(cval, err);
+                       val = ucontrol->value.integer.value[cnt];
++                      if (val < 0 || val > max_val)
++                              return -EINVAL;
+                       val = get_abs_value(cval, val);
+                       if (oval != val) {
+                               snd_usb_set_cur_mix_value(cval, c + 1, cnt, val);
+@@ -1474,6 +1487,8 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
+               if (err < 0)
+                       return filter_error(cval, err);
+               val = ucontrol->value.integer.value[0];
++              if (val < 0 || val > max_val)
++                      return -EINVAL;
+               val = get_abs_value(cval, val);
+               if (val != oval) {
+                       snd_usb_set_cur_mix_value(cval, 0, 0, val);
+@@ -2337,6 +2352,8 @@ static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol,
+       if (err < 0)
+               return filter_error(cval, err);
+       val = ucontrol->value.integer.value[0];
++      if (val < 0 || val > get_max_exposed(cval))
++              return -EINVAL;
+       val = get_abs_value(cval, val);
+       if (val != oval) {
+               set_cur_ctl_value(cval, cval->control << 8, val);
+@@ -2699,6 +2716,8 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol,
+       if (err < 0)
+               return filter_error(cval, err);
+       val = ucontrol->value.enumerated.item[0];
++      if (val < 0 || val >= cval->max) /* here cval->max = # elements */
++              return -EINVAL;
+       val = get_abs_value(cval, val);
+       if (val != oval) {
+               set_cur_ctl_value(cval, cval->control << 8, val);
+diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
+index d43895c1ae5c6..167fbfcf01ace 100644
+--- a/sound/usb/mixer.h
++++ b/sound/usb/mixer.h
+@@ -88,6 +88,7 @@ struct usb_mixer_elem_info {
+       int channels;
+       int val_type;
+       int min, max, res;
++      int max_exposed; /* control API exposes the value in 0..max_exposed */
+       int dBmin, dBmax;
+       int cached;
+       int cache_val[MAX_CHANNELS];
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-usb-audio-add-logitech-audio-profile-quirk.patch b/queue-6.11/alsa-usb-audio-add-logitech-audio-profile-quirk.patch
new file mode 100644 (file)
index 0000000..ecb2786
--- /dev/null
@@ -0,0 +1,40 @@
+From 0415da05540333031170efcadcd55a77c12636ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Sep 2024 15:26:28 +0000
+Subject: ALSA: usb-audio: Add logitech Audio profile quirk
+
+From: Joshua Pius <joshuapius@chromium.org>
+
+[ Upstream commit a51c925c11d7b855167e64b63eb4378e5adfc11d ]
+
+Specify shortnames for the following Logitech Devices: Rally bar, Rally
+bar mini, Tap, MeetUp and Huddle.
+
+Signed-off-by: Joshua Pius <joshuapius@chromium.org>
+Link: https://patch.msgid.link/20240912152635.1859737-1-joshuapius@google.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/card.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/sound/usb/card.c b/sound/usb/card.c
+index 778de9244f1e7..9c411b82a218d 100644
+--- a/sound/usb/card.c
++++ b/sound/usb/card.c
+@@ -384,6 +384,12 @@ static const struct usb_audio_device_name usb_audio_names[] = {
+       /* Creative/Toshiba Multimedia Center SB-0500 */
+       DEVICE_NAME(0x041e, 0x3048, "Toshiba", "SB-0500"),
++      /* Logitech Audio Devices */
++      DEVICE_NAME(0x046d, 0x0867, "Logitech, Inc.", "Logi-MeetUp"),
++      DEVICE_NAME(0x046d, 0x0874, "Logitech, Inc.", "Logi-Tap-Audio"),
++      DEVICE_NAME(0x046d, 0x087c, "Logitech, Inc.", "Logi-Huddle"),
++      DEVICE_NAME(0x046d, 0x0898, "Logitech, Inc.", "Logi-RB-Audio"),
++      DEVICE_NAME(0x046d, 0x08d2, "Logitech, Inc.", "Logi-RBM-Audio"),
+       DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
+       DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"),
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-usb-audio-add-mixer-quirk-for-rme-digiface-usb.patch b/queue-6.11/alsa-usb-audio-add-mixer-quirk-for-rme-digiface-usb.patch
new file mode 100644 (file)
index 0000000..d98edf5
--- /dev/null
@@ -0,0 +1,482 @@
+From 7295ca7412d1d1c13617fda53b0227753c042fb8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Sep 2024 19:52:30 +0900
+Subject: ALSA: usb-audio: Add mixer quirk for RME Digiface USB
+
+From: Asahi Lina <lina@asahilina.net>
+
+[ Upstream commit 611a96f6acf2e74fe28cb90908a9c183862348ce ]
+
+Implement sync, output format, and input status mixer controls, to allow
+the interface to be used as a straight ADAT/SPDIF (+ Headphones) I/O
+interface.
+
+This does not implement the matrix mixer, output gain controls, or input
+level meter feedback. The full mixer interface is only really usable
+using a dedicated userspace control app (there are too many mixer nodes
+for alsamixer to be usable), so for now we leave it up to userspace to
+directly control these features using raw USB control messages. This is
+similar to how it's done with some FireWire interfaces (ffado-mixer).
+
+Signed-off-by: Asahi Lina <lina@asahilina.net>
+Link: https://patch.msgid.link/20240903-rme-digiface-v2-2-71b06c912e97@asahilina.net
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer_quirks.c | 413 +++++++++++++++++++++++++++++++++++++++
+ sound/usb/quirks-table.h |   1 +
+ 2 files changed, 414 insertions(+)
+
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index 8cbfb65846047..74abc44be77ca 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -14,6 +14,7 @@
+  *        Przemek Rudy (prudy1@o2.pl)
+  */
++#include <linux/bitfield.h>
+ #include <linux/hid.h>
+ #include <linux/init.h>
+ #include <linux/math64.h>
+@@ -2926,6 +2927,415 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
+       return 0;
+ }
++/*
++ * RME Digiface USB
++ */
++
++#define RME_DIGIFACE_READ_STATUS 17
++#define RME_DIGIFACE_STATUS_REG0L 0
++#define RME_DIGIFACE_STATUS_REG0H 1
++#define RME_DIGIFACE_STATUS_REG1L 2
++#define RME_DIGIFACE_STATUS_REG1H 3
++#define RME_DIGIFACE_STATUS_REG2L 4
++#define RME_DIGIFACE_STATUS_REG2H 5
++#define RME_DIGIFACE_STATUS_REG3L 6
++#define RME_DIGIFACE_STATUS_REG3H 7
++
++#define RME_DIGIFACE_CTL_REG1 16
++#define RME_DIGIFACE_CTL_REG2 18
++
++/* Reg is overloaded, 0-7 for status halfwords or 16 or 18 for control registers */
++#define RME_DIGIFACE_REGISTER(reg, mask) (((reg) << 16) | (mask))
++#define RME_DIGIFACE_INVERT BIT(31)
++
++/* Nonconst helpers */
++#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
++#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
++
++static int snd_rme_digiface_write_reg(struct snd_kcontrol *kcontrol, int item, u16 mask, u16 val)
++{
++      struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
++      struct snd_usb_audio *chip = list->mixer->chip;
++      struct usb_device *dev = chip->dev;
++      int err;
++
++      err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
++                            item,
++                            USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++                            val, mask, NULL, 0);
++      if (err < 0)
++              dev_err(&dev->dev,
++                      "unable to issue control set request %d (ret = %d)",
++                      item, err);
++      return err;
++}
++
++static int snd_rme_digiface_read_status(struct snd_kcontrol *kcontrol, u32 status[4])
++{
++      struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
++      struct snd_usb_audio *chip = list->mixer->chip;
++      struct usb_device *dev = chip->dev;
++      __le32 buf[4];
++      int err;
++
++      err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
++                            RME_DIGIFACE_READ_STATUS,
++                            USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++                            0, 0,
++                            buf, sizeof(buf));
++      if (err < 0) {
++              dev_err(&dev->dev,
++                      "unable to issue status read request (ret = %d)",
++                      err);
++      } else {
++              for (int i = 0; i < ARRAY_SIZE(buf); i++)
++                      status[i] = le32_to_cpu(buf[i]);
++      }
++      return err;
++}
++
++static int snd_rme_digiface_get_status_val(struct snd_kcontrol *kcontrol)
++{
++      int err;
++      u32 status[4];
++      bool invert = kcontrol->private_value & RME_DIGIFACE_INVERT;
++      u8 reg = (kcontrol->private_value >> 16) & 0xff;
++      u16 mask = kcontrol->private_value & 0xffff;
++      u16 val;
++
++      err = snd_rme_digiface_read_status(kcontrol, status);
++      if (err < 0)
++              return err;
++
++      switch (reg) {
++      /* Status register halfwords */
++      case RME_DIGIFACE_STATUS_REG0L ... RME_DIGIFACE_STATUS_REG3H:
++              break;
++      case RME_DIGIFACE_CTL_REG1: /* Control register 1, present in halfword 3L */
++              reg = RME_DIGIFACE_STATUS_REG3L;
++              break;
++      case RME_DIGIFACE_CTL_REG2: /* Control register 2, present in halfword 3H */
++              reg = RME_DIGIFACE_STATUS_REG3H;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      if (reg & 1)
++              val = status[reg >> 1] >> 16;
++      else
++              val = status[reg >> 1] & 0xffff;
++
++      if (invert)
++              val ^= mask;
++
++      return field_get(mask, val);
++}
++
++static int snd_rme_digiface_rate_get(struct snd_kcontrol *kcontrol,
++                                   struct snd_ctl_elem_value *ucontrol)
++{
++      int freq = snd_rme_digiface_get_status_val(kcontrol);
++
++      if (freq < 0)
++              return freq;
++      if (freq >= ARRAY_SIZE(snd_rme_rate_table))
++              return -EIO;
++
++      ucontrol->value.integer.value[0] = snd_rme_rate_table[freq];
++      return 0;
++}
++
++static int snd_rme_digiface_enum_get(struct snd_kcontrol *kcontrol,
++                                   struct snd_ctl_elem_value *ucontrol)
++{
++      int val = snd_rme_digiface_get_status_val(kcontrol);
++
++      if (val < 0)
++              return val;
++
++      ucontrol->value.enumerated.item[0] = val;
++      return 0;
++}
++
++static int snd_rme_digiface_enum_put(struct snd_kcontrol *kcontrol,
++                                   struct snd_ctl_elem_value *ucontrol)
++{
++      bool invert = kcontrol->private_value & RME_DIGIFACE_INVERT;
++      u8 reg = (kcontrol->private_value >> 16) & 0xff;
++      u16 mask = kcontrol->private_value & 0xffff;
++      u16 val = field_prep(mask, ucontrol->value.enumerated.item[0]);
++
++      if (invert)
++              val ^= mask;
++
++      return snd_rme_digiface_write_reg(kcontrol, reg, mask, val);
++}
++
++static int snd_rme_digiface_current_sync_get(struct snd_kcontrol *kcontrol,
++                                   struct snd_ctl_elem_value *ucontrol)
++{
++      int ret = snd_rme_digiface_enum_get(kcontrol, ucontrol);
++
++      /* 7 means internal for current sync */
++      if (ucontrol->value.enumerated.item[0] == 7)
++              ucontrol->value.enumerated.item[0] = 0;
++
++      return ret;
++}
++
++static int snd_rme_digiface_sync_state_get(struct snd_kcontrol *kcontrol,
++                                         struct snd_ctl_elem_value *ucontrol)
++{
++      u32 status[4];
++      int err;
++      bool valid, sync;
++
++      err = snd_rme_digiface_read_status(kcontrol, status);
++      if (err < 0)
++              return err;
++
++      valid = status[0] & BIT(kcontrol->private_value);
++      sync = status[0] & BIT(5 + kcontrol->private_value);
++
++      if (!valid)
++              ucontrol->value.enumerated.item[0] = SND_RME_CLOCK_NOLOCK;
++      else if (!sync)
++              ucontrol->value.enumerated.item[0] = SND_RME_CLOCK_LOCK;
++      else
++              ucontrol->value.enumerated.item[0] = SND_RME_CLOCK_SYNC;
++      return 0;
++}
++
++
++static int snd_rme_digiface_format_info(struct snd_kcontrol *kcontrol,
++                                      struct snd_ctl_elem_info *uinfo)
++{
++      static const char *const format[] = {
++              "ADAT", "S/PDIF"
++      };
++
++      return snd_ctl_enum_info(uinfo, 1,
++                               ARRAY_SIZE(format), format);
++}
++
++
++static int snd_rme_digiface_sync_source_info(struct snd_kcontrol *kcontrol,
++                                           struct snd_ctl_elem_info *uinfo)
++{
++      static const char *const sync_sources[] = {
++              "Internal", "Input 1", "Input 2", "Input 3", "Input 4"
++      };
++
++      return snd_ctl_enum_info(uinfo, 1,
++                               ARRAY_SIZE(sync_sources), sync_sources);
++}
++
++static int snd_rme_digiface_rate_info(struct snd_kcontrol *kcontrol,
++                                    struct snd_ctl_elem_info *uinfo)
++{
++      uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++      uinfo->count = 1;
++      uinfo->value.integer.min = 0;
++      uinfo->value.integer.max = 200000;
++      uinfo->value.integer.step = 0;
++      return 0;
++}
++
++static const struct snd_kcontrol_new snd_rme_digiface_controls[] = {
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 1 Sync",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_sync_state_info,
++              .get = snd_rme_digiface_sync_state_get,
++              .private_value = 0,
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 1 Format",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_digiface_format_info,
++              .get = snd_rme_digiface_enum_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG0H, BIT(0)) |
++                      RME_DIGIFACE_INVERT,
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 1 Rate",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_digiface_rate_info,
++              .get = snd_rme_digiface_rate_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG1L, GENMASK(3, 0)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 2 Sync",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_sync_state_info,
++              .get = snd_rme_digiface_sync_state_get,
++              .private_value = 1,
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 2 Format",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_digiface_format_info,
++              .get = snd_rme_digiface_enum_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG0L, BIT(13)) |
++                      RME_DIGIFACE_INVERT,
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 2 Rate",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_digiface_rate_info,
++              .get = snd_rme_digiface_rate_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG1L, GENMASK(7, 4)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 3 Sync",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_sync_state_info,
++              .get = snd_rme_digiface_sync_state_get,
++              .private_value = 2,
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 3 Format",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_digiface_format_info,
++              .get = snd_rme_digiface_enum_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG0L, BIT(14)) |
++                      RME_DIGIFACE_INVERT,
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 3 Rate",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_digiface_rate_info,
++              .get = snd_rme_digiface_rate_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG1L, GENMASK(11, 8)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 4 Sync",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_sync_state_info,
++              .get = snd_rme_digiface_sync_state_get,
++              .private_value = 3,
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 4 Format",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_digiface_format_info,
++              .get = snd_rme_digiface_enum_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG0L, GENMASK(15, 12)) |
++                      RME_DIGIFACE_INVERT,
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Input 4 Rate",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_digiface_rate_info,
++              .get = snd_rme_digiface_rate_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG1L, GENMASK(3, 0)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Output 1 Format",
++              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++              .info = snd_rme_digiface_format_info,
++              .get = snd_rme_digiface_enum_get,
++              .put = snd_rme_digiface_enum_put,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_CTL_REG2, BIT(0)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Output 2 Format",
++              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++              .info = snd_rme_digiface_format_info,
++              .get = snd_rme_digiface_enum_get,
++              .put = snd_rme_digiface_enum_put,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_CTL_REG2, BIT(1)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Output 3 Format",
++              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++              .info = snd_rme_digiface_format_info,
++              .get = snd_rme_digiface_enum_get,
++              .put = snd_rme_digiface_enum_put,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_CTL_REG2, BIT(3)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Output 4 Format",
++              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++              .info = snd_rme_digiface_format_info,
++              .get = snd_rme_digiface_enum_get,
++              .put = snd_rme_digiface_enum_put,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_CTL_REG2, BIT(4)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Sync Source",
++              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++              .info = snd_rme_digiface_sync_source_info,
++              .get = snd_rme_digiface_enum_get,
++              .put = snd_rme_digiface_enum_put,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_CTL_REG1, GENMASK(2, 0)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Current Sync Source",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_digiface_sync_source_info,
++              .get = snd_rme_digiface_current_sync_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG0L, GENMASK(12, 10)),
++      },
++      {
++              /*
++               * This is writeable, but it is only set by the PCM rate.
++               * Mixer apps currently need to drive the mixer using raw USB requests,
++               * so they can also change this that way to configure the rate for
++               * stand-alone operation when the PCM is closed.
++               */
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "System Rate",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_rate_info,
++              .get = snd_rme_digiface_rate_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_CTL_REG1, GENMASK(6, 3)),
++      },
++      {
++              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name = "Current Rate",
++              .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++              .info = snd_rme_rate_info,
++              .get = snd_rme_digiface_rate_get,
++              .private_value = RME_DIGIFACE_REGISTER(RME_DIGIFACE_STATUS_REG1H, GENMASK(7, 4)),
++      }
++};
++
++static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer)
++{
++      int err, i;
++
++      for (i = 0; i < ARRAY_SIZE(snd_rme_digiface_controls); ++i) {
++              err = add_single_ctl_with_resume(mixer, 0,
++                                               NULL,
++                                               &snd_rme_digiface_controls[i],
++                                               NULL);
++              if (err < 0)
++                      return err;
++      }
++
++      return 0;
++}
++
+ /*
+  * Pioneer DJ DJM Mixers
+  *
+@@ -3484,6 +3894,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
+       case USB_ID(0x2a39, 0x3fb0): /* RME Babyface Pro FS */
+               err = snd_bbfpro_controls_create(mixer);
+               break;
++      case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
++              err = snd_rme_digiface_controls_create(mixer);
++              break;
+       case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
+               err = snd_djm_controls_create(mixer, SND_DJM_250MK2_IDX);
+               break;
+diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
+index 631b9ab80f6cd..24c981c9b2405 100644
+--- a/sound/usb/quirks-table.h
++++ b/sound/usb/quirks-table.h
+@@ -3620,6 +3620,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                        * Three modes depending on sample rate band,
+                        * with different channel counts for in/out
+                        */
++                      { QUIRK_DATA_STANDARD_MIXER(0) },
+                       {
+                               QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-usb-audio-add-quirk-for-rme-digiface-usb.patch b/queue-6.11/alsa-usb-audio-add-quirk-for-rme-digiface-usb.patch
new file mode 100644 (file)
index 0000000..577f85c
--- /dev/null
@@ -0,0 +1,299 @@
+From dc2b0fb42e2a8bb893b2b21a1f0b54205e5f2db5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Sep 2024 19:52:29 +0900
+Subject: ALSA: usb-audio: Add quirk for RME Digiface USB
+
+From: Cyan Nyan <cyan.vtb@gmail.com>
+
+[ Upstream commit c032044e9672408c534d64a6df2b1ba14449e948 ]
+
+Add trivial support for audio streaming on the RME Digiface USB. Binds
+only to the first interface to allow userspace to directly drive the
+complex I/O and matrix mixer controls.
+
+Signed-off-by: Cyan Nyan <cyan.vtb@gmail.com>
+[Lina: Added 2x/4x sample rate support & boot/format quirks]
+Co-developed-by: Asahi Lina <lina@asahilina.net>
+Signed-off-by: Asahi Lina <lina@asahilina.net>
+Link: https://patch.msgid.link/20240903-rme-digiface-v2-1-71b06c912e97@asahilina.net
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks-table.h | 171 ++++++++++++++++++++++++++++++++++++++-
+ sound/usb/quirks.c       |  58 +++++++++++++
+ 2 files changed, 228 insertions(+), 1 deletion(-)
+
+diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
+index 8d22de8bc2a96..631b9ab80f6cd 100644
+--- a/sound/usb/quirks-table.h
++++ b/sound/usb/quirks-table.h
+@@ -3604,6 +3604,175 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+               }
+       }
+ },
+-
++{
++      /* Only claim interface 0 */
++      .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
++                     USB_DEVICE_ID_MATCH_PRODUCT |
++                     USB_DEVICE_ID_MATCH_INT_CLASS |
++                     USB_DEVICE_ID_MATCH_INT_NUMBER,
++      .idVendor = 0x2a39,
++      .idProduct = 0x3f8c,
++      .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
++      .bInterfaceNumber = 0,
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      /*
++                       * Three modes depending on sample rate band,
++                       * with different channel counts for in/out
++                       */
++                      {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
++                                      .formats = SNDRV_PCM_FMTBIT_S32_LE,
++                                      .channels = 34, // outputs
++                                      .fmt_bits = 24,
++                                      .iface = 0,
++                                      .altsetting = 1,
++                                      .altset_idx = 1,
++                                      .endpoint = 0x02,
++                                      .ep_idx = 1,
++                                      .ep_attr = USB_ENDPOINT_XFER_ISOC |
++                                              USB_ENDPOINT_SYNC_ASYNC,
++                                      .rates = SNDRV_PCM_RATE_32000 |
++                                              SNDRV_PCM_RATE_44100 |
++                                              SNDRV_PCM_RATE_48000,
++                                      .rate_min = 32000,
++                                      .rate_max = 48000,
++                                      .nr_rates = 3,
++                                      .rate_table = (unsigned int[]) {
++                                              32000, 44100, 48000,
++                                      },
++                                      .sync_ep = 0x81,
++                                      .sync_iface = 0,
++                                      .sync_altsetting = 1,
++                                      .sync_ep_idx = 0,
++                                      .implicit_fb = 1,
++                              },
++                      },
++                      {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
++                                      .formats = SNDRV_PCM_FMTBIT_S32_LE,
++                                      .channels = 18, // outputs
++                                      .fmt_bits = 24,
++                                      .iface = 0,
++                                      .altsetting = 1,
++                                      .altset_idx = 1,
++                                      .endpoint = 0x02,
++                                      .ep_idx = 1,
++                                      .ep_attr = USB_ENDPOINT_XFER_ISOC |
++                                              USB_ENDPOINT_SYNC_ASYNC,
++                                      .rates = SNDRV_PCM_RATE_64000 |
++                                              SNDRV_PCM_RATE_88200 |
++                                              SNDRV_PCM_RATE_96000,
++                                      .rate_min = 64000,
++                                      .rate_max = 96000,
++                                      .nr_rates = 3,
++                                      .rate_table = (unsigned int[]) {
++                                              64000, 88200, 96000,
++                                      },
++                                      .sync_ep = 0x81,
++                                      .sync_iface = 0,
++                                      .sync_altsetting = 1,
++                                      .sync_ep_idx = 0,
++                                      .implicit_fb = 1,
++                              },
++                      },
++                      {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
++                                      .formats = SNDRV_PCM_FMTBIT_S32_LE,
++                                      .channels = 10, // outputs
++                                      .fmt_bits = 24,
++                                      .iface = 0,
++                                      .altsetting = 1,
++                                      .altset_idx = 1,
++                                      .endpoint = 0x02,
++                                      .ep_idx = 1,
++                                      .ep_attr = USB_ENDPOINT_XFER_ISOC |
++                                              USB_ENDPOINT_SYNC_ASYNC,
++                                      .rates = SNDRV_PCM_RATE_KNOT |
++                                              SNDRV_PCM_RATE_176400 |
++                                              SNDRV_PCM_RATE_192000,
++                                      .rate_min = 128000,
++                                      .rate_max = 192000,
++                                      .nr_rates = 3,
++                                      .rate_table = (unsigned int[]) {
++                                              128000, 176400, 192000,
++                                      },
++                                      .sync_ep = 0x81,
++                                      .sync_iface = 0,
++                                      .sync_altsetting = 1,
++                                      .sync_ep_idx = 0,
++                                      .implicit_fb = 1,
++                              },
++                      },
++                      {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
++                                      .formats = SNDRV_PCM_FMTBIT_S32_LE,
++                                      .channels = 32, // inputs
++                                      .fmt_bits = 24,
++                                      .iface = 0,
++                                      .altsetting = 1,
++                                      .altset_idx = 1,
++                                      .endpoint = 0x81,
++                                      .ep_attr = USB_ENDPOINT_XFER_ISOC |
++                                              USB_ENDPOINT_SYNC_ASYNC,
++                                      .rates = SNDRV_PCM_RATE_32000 |
++                                              SNDRV_PCM_RATE_44100 |
++                                              SNDRV_PCM_RATE_48000,
++                                      .rate_min = 32000,
++                                      .rate_max = 48000,
++                                      .nr_rates = 3,
++                                      .rate_table = (unsigned int[]) {
++                                              32000, 44100, 48000,
++                                      }
++                              }
++                      },
++                      {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
++                                      .formats = SNDRV_PCM_FMTBIT_S32_LE,
++                                      .channels = 16, // inputs
++                                      .fmt_bits = 24,
++                                      .iface = 0,
++                                      .altsetting = 1,
++                                      .altset_idx = 1,
++                                      .endpoint = 0x81,
++                                      .ep_attr = USB_ENDPOINT_XFER_ISOC |
++                                              USB_ENDPOINT_SYNC_ASYNC,
++                                      .rates = SNDRV_PCM_RATE_64000 |
++                                              SNDRV_PCM_RATE_88200 |
++                                              SNDRV_PCM_RATE_96000,
++                                      .rate_min = 64000,
++                                      .rate_max = 96000,
++                                      .nr_rates = 3,
++                                      .rate_table = (unsigned int[]) {
++                                              64000, 88200, 96000,
++                                      }
++                              }
++                      },
++                      {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
++                                      .formats = SNDRV_PCM_FMTBIT_S32_LE,
++                                      .channels = 8, // inputs
++                                      .fmt_bits = 24,
++                                      .iface = 0,
++                                      .altsetting = 1,
++                                      .altset_idx = 1,
++                                      .endpoint = 0x81,
++                                      .ep_attr = USB_ENDPOINT_XFER_ISOC |
++                                              USB_ENDPOINT_SYNC_ASYNC,
++                                      .rates = SNDRV_PCM_RATE_KNOT |
++                                              SNDRV_PCM_RATE_176400 |
++                                              SNDRV_PCM_RATE_192000,
++                                      .rate_min = 128000,
++                                      .rate_max = 192000,
++                                      .nr_rates = 3,
++                                      .rate_table = (unsigned int[]) {
++                                              128000, 176400, 192000,
++                                      }
++                              }
++                      },
++                      QUIRK_COMPOSITE_END
++              }
++      }
++},
+ #undef USB_DEVICE_VENDOR_SPEC
+ #undef USB_AUDIO_DEVICE
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index e7b68c67852e9..73da862a012c6 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1389,6 +1389,27 @@ static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev)
+       return 0;
+ }
++static int snd_usb_rme_digiface_boot_quirk(struct usb_device *dev)
++{
++      /* Disable mixer, internal clock, all outputs ADAT, 48kHz, TMS off */
++      snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
++                      16, 0x40, 0x2410, 0x7fff, NULL, 0);
++      snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
++                      18, 0x40, 0x0104, 0xffff, NULL, 0);
++
++      /* Disable loopback for all inputs */
++      for (int ch = 0; ch < 32; ch++)
++              snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
++                              22, 0x40, 0x400, ch, NULL, 0);
++
++      /* Unity gain for all outputs */
++      for (int ch = 0; ch < 34; ch++)
++              snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
++                              21, 0x40, 0x9000, 0x100 + ch, NULL, 0);
++
++      return 0;
++}
++
+ /*
+  * Setup quirks
+  */
+@@ -1616,6 +1637,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
+                   get_iface_desc(intf->altsetting)->bInterfaceNumber < 3)
+                       return snd_usb_motu_microbookii_boot_quirk(dev);
+               break;
++      case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
++              return snd_usb_rme_digiface_boot_quirk(dev);
+       }
+       return 0;
+@@ -1771,6 +1794,38 @@ static void mbox3_set_format_quirk(struct snd_usb_substream *subs,
+               dev_warn(&subs->dev->dev, "MBOX3: Couldn't set the sample rate");
+ }
++static const int rme_digiface_rate_table[] = {
++      32000, 44100, 48000, 0,
++      64000, 88200, 96000, 0,
++      128000, 176400, 192000, 0,
++};
++
++static int rme_digiface_set_format_quirk(struct snd_usb_substream *subs)
++{
++      unsigned int cur_rate = subs->data_endpoint->cur_rate;
++      u16 val;
++      int speed_mode;
++      int id;
++
++      for (id = 0; id < ARRAY_SIZE(rme_digiface_rate_table); id++) {
++              if (rme_digiface_rate_table[id] == cur_rate)
++                      break;
++      }
++
++      if (id >= ARRAY_SIZE(rme_digiface_rate_table))
++              return -EINVAL;
++
++      /* 2, 3, 4 for 1x, 2x, 4x */
++      speed_mode = (id >> 2) + 2;
++      val = (id << 3) | (speed_mode << 12);
++
++      /* Set the sample rate */
++      snd_usb_ctl_msg(subs->stream->chip->dev,
++              usb_sndctrlpipe(subs->stream->chip->dev, 0),
++              16, 0x40, val, 0x7078, NULL, 0);
++      return 0;
++}
++
+ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
+                             const struct audioformat *fmt)
+ {
+@@ -1795,6 +1850,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
+       case USB_ID(0x0dba, 0x5000):
+               mbox3_set_format_quirk(subs, fmt); /* Digidesign Mbox 3 */
+               break;
++      case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
++              rme_digiface_set_format_quirk(subs);
++              break;
+       }
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-usb-audio-define-macros-for-quirk-table-entries.patch b/queue-6.11/alsa-usb-audio-define-macros-for-quirk-table-entries.patch
new file mode 100644 (file)
index 0000000..ef14177
--- /dev/null
@@ -0,0 +1,111 @@
+From 3113ff59c2acc7aeb7de921a5e0c712c688eb18e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Aug 2024 15:48:41 +0200
+Subject: ALSA: usb-audio: Define macros for quirk table entries
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 0c3ad39b791c2ecf718afcaca30e5ceafa939d5c ]
+
+Many entries in the USB-audio quirk tables have relatively complex
+expressions.  For improving the readability, introduce a few macros.
+Those are applied in the following patch.
+
+Link: https://patch.msgid.link/20240814134844.2726-2-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks-table.h | 77 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 77 insertions(+)
+
+diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
+index aaa6a515d0f8a..e3a25f4f68792 100644
+--- a/sound/usb/quirks-table.h
++++ b/sound/usb/quirks-table.h
+@@ -35,6 +35,83 @@
+       .bInterfaceClass = USB_CLASS_AUDIO, \
+       .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
++/* Quirk .driver_info, followed by the definition of the quirk entry;
++ * put like QUIRK_DRIVER_INFO { ... } in each entry of the quirk table
++ */
++#define QUIRK_DRIVER_INFO \
++      .driver_info = (unsigned long)&(const struct snd_usb_audio_quirk)
++
++/*
++ * Macros for quirk data entries
++ */
++
++/* Quirk data entry for ignoring the interface */
++#define QUIRK_DATA_IGNORE(_ifno) \
++      .ifnum = (_ifno), .type = QUIRK_IGNORE_INTERFACE
++/* Quirk data entry for a standard audio interface */
++#define QUIRK_DATA_STANDARD_AUDIO(_ifno) \
++      .ifnum = (_ifno), .type = QUIRK_AUDIO_STANDARD_INTERFACE
++/* Quirk data entry for a standard MIDI interface */
++#define QUIRK_DATA_STANDARD_MIDI(_ifno) \
++      .ifnum = (_ifno), .type = QUIRK_MIDI_STANDARD_INTERFACE
++/* Quirk data entry for a standard mixer interface */
++#define QUIRK_DATA_STANDARD_MIXER(_ifno) \
++      .ifnum = (_ifno), .type = QUIRK_AUDIO_STANDARD_MIXER
++
++/* Quirk data entry for Yamaha MIDI */
++#define QUIRK_DATA_MIDI_YAMAHA(_ifno) \
++      .ifnum = (_ifno), .type = QUIRK_MIDI_YAMAHA
++/* Quirk data entry for Edirol UAxx */
++#define QUIRK_DATA_EDIROL_UAXX(_ifno) \
++      .ifnum = (_ifno), .type = QUIRK_AUDIO_EDIROL_UAXX
++/* Quirk data entry for raw bytes interface */
++#define QUIRK_DATA_RAW_BYTES(_ifno) \
++      .ifnum = (_ifno), .type = QUIRK_MIDI_RAW_BYTES
++
++/* Quirk composite array terminator */
++#define QUIRK_COMPOSITE_END   { .ifnum = -1 }
++
++/* Quirk data entry for composite quirks;
++ * followed by the quirk array that is terminated with QUIRK_COMPOSITE_END
++ * e.g. QUIRK_DATA_COMPOSITE { { quirk1 }, { quirk2 },..., QUIRK_COMPOSITE_END }
++ */
++#define QUIRK_DATA_COMPOSITE \
++      .ifnum = QUIRK_ANY_INTERFACE, \
++      .type = QUIRK_COMPOSITE, \
++      .data = &(const struct snd_usb_audio_quirk[])
++
++/* Quirk data entry for a fixed audio endpoint;
++ * followed by audioformat definition
++ * e.g. QUIRK_DATA_AUDIOFORMAT(n) { .formats = xxx, ... }
++ */
++#define QUIRK_DATA_AUDIOFORMAT(_ifno)     \
++      .ifnum = (_ifno),                   \
++      .type = QUIRK_AUDIO_FIXED_ENDPOINT, \
++      .data = &(const struct audioformat)
++
++/* Quirk data entry for a fixed MIDI endpoint;
++ * followed by snd_usb_midi_endpoint_info definition
++ * e.g. QUIRK_DATA_MIDI_FIXED_ENDPOINT(n) { .out_cables = x, .in_cables = y }
++ */
++#define QUIRK_DATA_MIDI_FIXED_ENDPOINT(_ifno) \
++      .ifnum = (_ifno),                     \
++      .type = QUIRK_MIDI_FIXED_ENDPOINT,    \
++      .data = &(const struct snd_usb_midi_endpoint_info)
++/* Quirk data entry for a MIDIMAN MIDI endpoint */
++#define QUIRK_DATA_MIDI_MIDIMAN(_ifno) \
++      .ifnum = (_ifno),              \
++      .type = QUIRK_MIDI_MIDIMAN,    \
++      .data = &(const struct snd_usb_midi_endpoint_info)
++/* Quirk data entry for a EMAGIC MIDI endpoint */
++#define QUIRK_DATA_MIDI_EMAGIC(_ifno) \
++      .ifnum = (_ifno),             \
++      .type = QUIRK_MIDI_EMAGIC,    \
++      .data = &(const struct snd_usb_midi_endpoint_info)
++
++/*
++ * Here we go... the quirk table definition begins:
++ */
++
+ /* FTDI devices */
+ {
+       USB_DEVICE(0x0403, 0xb8d8),
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-usb-audio-replace-complex-quirk-lines-with-macr.patch b/queue-6.11/alsa-usb-audio-replace-complex-quirk-lines-with-macr.patch
new file mode 100644 (file)
index 0000000..c5acc52
--- /dev/null
@@ -0,0 +1,4000 @@
+From 539ac24052f35bb4343a2b0bbe0b5bfc66cf9c3e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Aug 2024 15:48:42 +0200
+Subject: ALSA: usb-audio: Replace complex quirk lines with macros
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit d79e13f8e8abb5cd3a2a0f9fc9bc3fc750c5b06f ]
+
+Apply the newly introduced macros for reduce the complex expressions
+and cast in the quirk table definitions.  It results in a significant
+code reduction, too.
+
+There should be no functional changes.
+
+Link: https://patch.msgid.link/20240814134844.2726-3-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks-table.h | 2210 ++++++++++----------------------------
+ 1 file changed, 593 insertions(+), 1617 deletions(-)
+
+diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
+index e3a25f4f68792..8d22de8bc2a96 100644
+--- a/sound/usb/quirks-table.h
++++ b/sound/usb/quirks-table.h
+@@ -115,7 +115,7 @@
+ /* FTDI devices */
+ {
+       USB_DEVICE(0x0403, 0xb8d8),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "STARR LABS", */
+               /* .product_name = "Starr Labs MIDI USB device", */
+               .ifnum = 0,
+@@ -126,10 +126,8 @@
+ {
+       /* Creative BT-D1 */
+       USB_DEVICE(0x041e, 0x0005),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = 1,
+-              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-              .data = &(const struct audioformat) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_AUDIOFORMAT(1) {
+                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                       .channels = 2,
+                       .iface = 1,
+@@ -164,18 +162,11 @@
+  */
+ {
+       USB_AUDIO_DEVICE(0x041e, 0x4095),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(2) },
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(3) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 16,
+@@ -191,9 +182,7 @@
+                                       .rate_table = (unsigned int[]) { 48000 },
+                               },
+                       },
+-                      {
+-                              .ifnum = -1
+-                      },
++                      QUIRK_COMPOSITE_END
+               },
+       },
+ },
+@@ -205,31 +194,18 @@
+  */
+ {
+       USB_DEVICE(0x0424, 0xb832),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Standard Microsystems Corp.",
+               .product_name = "HP Wireless Audio",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
+                       /* Mixer */
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE,
+-                      },
++                      { QUIRK_DATA_IGNORE(0) },
+                       /* Playback */
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE,
+-                      },
++                      { QUIRK_DATA_IGNORE(1) },
+                       /* Capture */
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_IGNORE_INTERFACE,
+-                      },
++                      { QUIRK_DATA_IGNORE(2) },
+                       /* HID Device, .ifnum = 3 */
+-                      {
+-                              .ifnum = -1,
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -252,20 +228,18 @@
+ #define YAMAHA_DEVICE(id, name) { \
+       USB_DEVICE(0x0499, id), \
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \
++      QUIRK_DRIVER_INFO { \
+               .vendor_name = "Yamaha", \
+               .product_name = name, \
+-              .ifnum = QUIRK_ANY_INTERFACE, \
+-              .type = QUIRK_MIDI_YAMAHA \
++              QUIRK_DATA_MIDI_YAMAHA(QUIRK_ANY_INTERFACE) \
+       } \
+ }
+ #define YAMAHA_INTERFACE(id, intf, name) { \
+       USB_DEVICE_VENDOR_SPEC(0x0499, id), \
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \
++      QUIRK_DRIVER_INFO { \
+               .vendor_name = "Yamaha", \
+               .product_name = name, \
+-              .ifnum = intf, \
+-              .type = QUIRK_MIDI_YAMAHA \
++              QUIRK_DATA_MIDI_YAMAHA(intf) \
+       } \
+ }
+ YAMAHA_DEVICE(0x1000, "UX256"),
+@@ -353,135 +327,67 @@ YAMAHA_DEVICE(0x105d, NULL),
+ YAMAHA_DEVICE(0x1718, "P-125"),
+ {
+       USB_DEVICE(0x0499, 0x1503),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Yamaha", */
+               /* .product_name = "MOX6/MOX8", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_YAMAHA
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      { QUIRK_DATA_MIDI_YAMAHA(3) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0499, 0x1507),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Yamaha", */
+               /* .product_name = "THR10", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_YAMAHA
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      { QUIRK_DATA_MIDI_YAMAHA(3) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0499, 0x1509),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Yamaha", */
+               /* .product_name = "Steinberg UR22", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_YAMAHA
+-                      },
+-                      {
+-                              .ifnum = 4,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      { QUIRK_DATA_MIDI_YAMAHA(3) },
++                      { QUIRK_DATA_IGNORE(4) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0499, 0x150a),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Yamaha", */
+               /* .product_name = "THR5A", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_YAMAHA
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      { QUIRK_DATA_MIDI_YAMAHA(3) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0499, 0x150c),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Yamaha", */
+               /* .product_name = "THR10C", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_YAMAHA
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      { QUIRK_DATA_MIDI_YAMAHA(3) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -515,7 +421,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                      USB_DEVICE_ID_MATCH_INT_CLASS,
+       .idVendor = 0x0499,
+       .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_AUTODETECT
+       }
+@@ -526,16 +432,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+  */
+ {
+       USB_DEVICE(0x0582, 0x0000),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "UA-100",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 4,
+                                       .iface = 0,
+@@ -550,9 +452,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 2,
+                                       .iface = 1,
+@@ -567,106 +467,66 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0007,
+                                       .in_cables  = 0x0007
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0582, 0x0002),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UM-4",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x000f,
+                                       .in_cables  = 0x000f
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0582, 0x0003),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "SC-8850",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x003f,
+                                       .in_cables  = 0x003f
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0582, 0x0004),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "U-8",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0005,
+                                       .in_cables  = 0x0005
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -674,152 +534,92 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+       /* Has ID 0x0099 when not in "Advanced Driver" mode.
+        * The UM-2EX has only one input, but we cannot detect this. */
+       USB_DEVICE(0x0582, 0x0005),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UM-2",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0003,
+                                       .in_cables  = 0x0003
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0582, 0x0007),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "SC-8820",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0013,
+                                       .in_cables  = 0x0013
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0582, 0x0008),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "PC-300",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x009d when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0009),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UM-1",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0582, 0x000b),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "SK-500",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0013,
+                                       .in_cables  = 0x0013
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -827,31 +627,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+       /* thanks to Emiliano Grilli <emillo@libero.it>
+        * for helping researching this data */
+       USB_DEVICE(0x0582, 0x000c),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "SC-D70",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0007,
+                                       .in_cables  = 0x0007
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -865,35 +653,23 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * the 96kHz sample rate.
+        */
+       USB_DEVICE(0x0582, 0x0010),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UA-5",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x0013 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0012),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "XV-5050",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -902,12 +678,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x0015 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0014),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UM-880",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x01ff,
+                       .in_cables  = 0x01ff
+               }
+@@ -916,74 +690,48 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x0017 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0016),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "SD-90",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x000f,
+                                       .in_cables  = 0x000f
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x001c when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x001b),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "MMP-2",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x001e when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x001d),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "V-SYNTH",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -992,12 +740,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x0024 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0023),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UM-550",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x003f,
+                       .in_cables  = 0x003f
+               }
+@@ -1010,20 +756,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * and no MIDI.
+        */
+       USB_DEVICE(0x0582, 0x0025),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UA-20",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 2,
+                                       .iface = 1,
+@@ -1038,9 +777,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 2,
+                                       .iface = 2,
+@@ -1055,28 +792,22 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x0028 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0027),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "SD-20",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0003,
+                       .in_cables  = 0x0007
+               }
+@@ -1085,12 +816,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x002a when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0029),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "SD-80",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x000f,
+                       .in_cables  = 0x000f
+               }
+@@ -1103,39 +832,24 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * but offers only 16-bit PCM and no MIDI.
+        */
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x002b),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UA-700",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_EDIROL_UAXX(1) },
++                      { QUIRK_DATA_EDIROL_UAXX(2) },
++                      { QUIRK_DATA_EDIROL_UAXX(3) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x002e when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x002d),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "XV-2020",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1144,12 +858,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x0030 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x002f),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "VariOS",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0007,
+                       .in_cables  = 0x0007
+               }
+@@ -1158,12 +870,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x0034 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0033),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "PCR",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0003,
+                       .in_cables  = 0x0007
+               }
+@@ -1175,12 +885,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * later revisions use IDs 0x0054 and 0x00a2.
+        */
+       USB_DEVICE(0x0582, 0x0037),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "Digital Piano",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1193,39 +901,24 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * and no MIDI.
+        */
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "BOSS",
+               .product_name = "GS-10",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      { QUIRK_DATA_STANDARD_MIDI(3) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x0041 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0040),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "GI-20",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1234,12 +927,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x0043 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0042),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "RS-70",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1248,36 +939,24 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x0049 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0047),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "EDIROL", */
+               /* .product_name = "UR-80", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
+                       /* in the 96 kHz modes, only interface 1 is there */
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x004a when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0048),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "EDIROL", */
+               /* .product_name = "UR-80", */
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0003,
+                       .in_cables  = 0x0007
+               }
+@@ -1286,35 +965,23 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x004e when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x004c),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "PCR-A",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x004f when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x004d),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "PCR-A",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0003,
+                       .in_cables  = 0x0007
+               }
+@@ -1326,76 +993,52 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * is standard compliant, but has only 16-bit PCM.
+        */
+       USB_DEVICE(0x0582, 0x0050),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UA-3FX",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0582, 0x0052),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UM-1SX",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_STANDARD_INTERFACE
++              QUIRK_DATA_STANDARD_MIDI(0)
+       }
+ },
+ {
+       USB_DEVICE(0x0582, 0x0060),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "EXR Series",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_STANDARD_INTERFACE
++              QUIRK_DATA_STANDARD_MIDI(0)
+       }
+ },
+ {
+       /* has ID 0x0066 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0064),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "EDIROL", */
+               /* .product_name = "PCR-1", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x0067 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0065),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "EDIROL", */
+               /* .product_name = "PCR-1", */
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0003
+               }
+@@ -1404,12 +1047,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x006e when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x006d),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "FANTOM-X",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1422,39 +1063,24 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * offers only 16-bit PCM at 44.1 kHz and no MIDI.
+        */
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x0074),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UA-25",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_EDIROL_UAXX(0) },
++                      { QUIRK_DATA_EDIROL_UAXX(1) },
++                      { QUIRK_DATA_EDIROL_UAXX(2) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* has ID 0x0076 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0075),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "BOSS",
+               .product_name = "DR-880",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1463,12 +1089,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x007b when not in "Advanced Driver" mode */
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x007a),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               /* "RD" or "RD-700SX"? */
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0003,
+                       .in_cables  = 0x0003
+               }
+@@ -1477,12 +1101,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x0081 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0080),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Roland",
+               .product_name = "G-70",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1491,12 +1113,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* has ID 0x008c when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x008b),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "PC-50",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1508,56 +1128,31 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * is standard compliant, but has only 16-bit PCM and no MIDI.
+        */
+       USB_DEVICE(0x0582, 0x00a3),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UA-4FX",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_EDIROL_UAXX(0) },
++                      { QUIRK_DATA_EDIROL_UAXX(1) },
++                      { QUIRK_DATA_EDIROL_UAXX(2) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* Edirol M-16DX */
+       USB_DEVICE(0x0582, 0x00c4),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -1567,37 +1162,22 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * offers only 16-bit PCM at 44.1 kHz and no MIDI.
+        */
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x00e6),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "EDIROL",
+               .product_name = "UA-25EX",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_EDIROL_UAXX
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_EDIROL_UAXX(0) },
++                      { QUIRK_DATA_EDIROL_UAXX(1) },
++                      { QUIRK_DATA_EDIROL_UAXX(2) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* Edirol UM-3G */
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) {
+                       .out_cables = 0x0007,
+                       .in_cables  = 0x0007
+               }
+@@ -1606,45 +1186,29 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* BOSS ME-25 */
+       USB_DEVICE(0x0582, 0x0113),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* only 44.1 kHz works at the moment */
+       USB_DEVICE(0x0582, 0x0120),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Roland", */
+               /* .product_name = "OCTO-CAPTURE", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 10,
+                                       .iface = 0,
+@@ -1660,9 +1224,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 12,
+                                       .iface = 1,
+@@ -1678,40 +1240,26 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 4,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      { QUIRK_DATA_IGNORE(3) },
++                      { QUIRK_DATA_IGNORE(4) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* only 44.1 kHz works at the moment */
+       USB_DEVICE(0x0582, 0x012f),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Roland", */
+               /* .product_name = "QUAD-CAPTURE", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 4,
+                                       .iface = 0,
+@@ -1727,9 +1275,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 6,
+                                       .iface = 1,
+@@ -1745,54 +1291,32 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 4,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      { QUIRK_DATA_IGNORE(3) },
++                      { QUIRK_DATA_IGNORE(4) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0582, 0x0159),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Roland", */
+               /* .product_name = "UA-22", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) {
+                                       .out_cables = 0x0001,
+                                       .in_cables = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -1800,19 +1324,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* UA101 and co are supported by another driver */
+ {
+       USB_DEVICE(0x0582, 0x0044), /* UA-1000 high speed */
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .ifnum = QUIRK_NODEV_INTERFACE
+       },
+ },
+ {
+       USB_DEVICE(0x0582, 0x007d), /* UA-101 high speed */
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .ifnum = QUIRK_NODEV_INTERFACE
+       },
+ },
+ {
+       USB_DEVICE(0x0582, 0x008d), /* UA-101 full speed */
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .ifnum = QUIRK_NODEV_INTERFACE
+       },
+ },
+@@ -1823,7 +1347,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                      USB_DEVICE_ID_MATCH_INT_CLASS,
+       .idVendor = 0x0582,
+       .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_AUTODETECT
+       }
+@@ -1838,12 +1362,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * compliant USB MIDI ports for external MIDI and controls.
+        */
+       USB_DEVICE_VENDOR_SPEC(0x06f8, 0xb000),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Hercules",
+               .product_name = "DJ Console (WE)",
+-              .ifnum = 4,
+-              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_FIXED_ENDPOINT(4) {
+                       .out_cables = 0x0001,
+                       .in_cables = 0x0001
+               }
+@@ -1853,12 +1375,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* Midiman/M-Audio devices */
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x1002),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "MidiSport 2x2",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_MIDI_MIDIMAN,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) {
+                       .out_cables = 0x0003,
+                       .in_cables  = 0x0003
+               }
+@@ -1866,12 +1386,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x1011),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "MidiSport 1x1",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_MIDI_MIDIMAN,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1879,12 +1397,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x1015),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "Keystation",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_MIDI_MIDIMAN,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -1892,12 +1408,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x1021),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "MidiSport 4x4",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_MIDI_MIDIMAN,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) {
+                       .out_cables = 0x000f,
+                       .in_cables  = 0x000f
+               }
+@@ -1910,12 +1424,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * Thanks to Olaf Giesbrecht <Olaf_Giesbrecht@yahoo.de>
+        */
+       USB_DEVICE_VER(0x0763, 0x1031, 0x0100, 0x0109),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "MidiSport 8x8",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_MIDI_MIDIMAN,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) {
+                       .out_cables = 0x01ff,
+                       .in_cables  = 0x01ff
+               }
+@@ -1923,12 +1435,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x1033),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "MidiSport 8x8",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_MIDI_MIDIMAN,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) {
+                       .out_cables = 0x01ff,
+                       .in_cables  = 0x01ff
+               }
+@@ -1936,12 +1446,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x1041),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "MidiSport 2x4",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_MIDI_MIDIMAN,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) {
+                       .out_cables = 0x000f,
+                       .in_cables  = 0x0003
+               }
+@@ -1949,76 +1457,41 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x2001),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "Quattro",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
+                       /*
+                        * Interfaces 0-2 are "Windows-compatible", 16-bit only,
+                        * and share endpoints with the other interfaces.
+                        * Ignore them.  The other interfaces can do 24 bits,
+                        * but captured samples are big-endian (see usbaudio.c).
+                        */
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 4,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 5,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 6,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 7,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 8,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 9,
+-                              .type = QUIRK_MIDI_MIDIMAN,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
++                      { QUIRK_DATA_IGNORE(2) },
++                      { QUIRK_DATA_IGNORE(3) },
++                      { QUIRK_DATA_STANDARD_AUDIO(4) },
++                      { QUIRK_DATA_STANDARD_AUDIO(5) },
++                      { QUIRK_DATA_IGNORE(6) },
++                      { QUIRK_DATA_STANDARD_AUDIO(7) },
++                      { QUIRK_DATA_STANDARD_AUDIO(8) },
++                      {
++                              QUIRK_DATA_MIDI_MIDIMAN(9) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x2003),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "AudioPhile",
+-              .ifnum = 6,
+-              .type = QUIRK_MIDI_MIDIMAN,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_MIDIMAN(6) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -2026,12 +1499,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x2008),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "Ozone",
+-              .ifnum = 3,
+-              .type = QUIRK_MIDI_MIDIMAN,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_MIDIMAN(3) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               }
+@@ -2039,93 +1510,45 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x200d),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "M-Audio",
+               .product_name = "OmniStudio",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 4,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 5,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 6,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 7,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 8,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 9,
+-                              .type = QUIRK_MIDI_MIDIMAN,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
++                      { QUIRK_DATA_IGNORE(2) },
++                      { QUIRK_DATA_IGNORE(3) },
++                      { QUIRK_DATA_STANDARD_AUDIO(4) },
++                      { QUIRK_DATA_STANDARD_AUDIO(5) },
++                      { QUIRK_DATA_IGNORE(6) },
++                      { QUIRK_DATA_STANDARD_AUDIO(7) },
++                      { QUIRK_DATA_STANDARD_AUDIO(8) },
++                      {
++                              QUIRK_DATA_MIDI_MIDIMAN(9) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x0763, 0x2019),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "M-Audio", */
+               /* .product_name = "Ozone Academic", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_MIDIMAN,
+-                              .data = & (const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_MIDIMAN(3) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -2135,21 +1558,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x2030),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "M-Audio", */
+               /* .product_name = "Fast Track C400", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(1) },
+                       /* Playback */
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 6,
+                                       .iface = 2,
+@@ -2173,9 +1589,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                       },
+                       /* Capture */
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(3) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 3,
+@@ -2197,30 +1611,21 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .clock = 0x80,
+                               }
+                       },
+-                      /* MIDI */
+-                      {
+-                              .ifnum = -1 /* Interface = 4 */
+-                      }
++                      /* MIDI: Interface = 4*/
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x2031),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "M-Audio", */
+               /* .product_name = "Fast Track C600", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(1) },
+                       /* Playback */
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 2,
+@@ -2244,9 +1649,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                       },
+                       /* Capture */
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(3) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 6,
+                                       .iface = 3,
+@@ -2268,29 +1671,20 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .clock = 0x80,
+                               }
+                       },
+-                      /* MIDI */
+-                      {
+-                              .ifnum = -1 /* Interface = 4 */
+-                      }
++                      /* MIDI: Interface = 4 */
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "M-Audio", */
+               /* .product_name = "Fast Track Ultra", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(0) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 1,
+@@ -2312,9 +1706,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 2,
+@@ -2336,28 +1728,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       /* interface 3 (MIDI) is standard compliant */
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0763, 0x2081),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "M-Audio", */
+               /* .product_name = "Fast Track Ultra 8R", */
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(0) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 1,
+@@ -2379,9 +1762,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 2,
+@@ -2403,9 +1784,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       /* interface 3 (MIDI) is standard compliant */
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -2413,21 +1792,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* Casio devices */
+ {
+       USB_DEVICE(0x07cf, 0x6801),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Casio",
+               .product_name = "PL-40R",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_YAMAHA
++              QUIRK_DATA_MIDI_YAMAHA(0)
+       }
+ },
+ {
+       /* this ID is used by several devices without a product ID */
+       USB_DEVICE(0x07cf, 0x6802),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Casio",
+               .product_name = "Keyboard",
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_YAMAHA
++              QUIRK_DATA_MIDI_YAMAHA(0)
+       }
+ },
+@@ -2440,23 +1817,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+       .idVendor = 0x07fd,
+       .idProduct = 0x0001,
+       .bDeviceSubClass = 2,
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "MOTU",
+               .product_name = "Fastlane",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_MIDI_RAW_BYTES
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_RAW_BYTES(0) },
++                      { QUIRK_DATA_IGNORE(1) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -2464,12 +1831,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* Emagic devices */
+ {
+       USB_DEVICE(0x086a, 0x0001),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Emagic",
+               .product_name = "Unitor8",
+-              .ifnum = 2,
+-              .type = QUIRK_MIDI_EMAGIC,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_EMAGIC(2) {
+                       .out_cables = 0x80ff,
+                       .in_cables  = 0x80ff
+               }
+@@ -2477,12 +1842,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE(0x086a, 0x0002),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Emagic",
+               /* .product_name = "AMT8", */
+-              .ifnum = 2,
+-              .type = QUIRK_MIDI_EMAGIC,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_EMAGIC(2) {
+                       .out_cables = 0x80ff,
+                       .in_cables  = 0x80ff
+               }
+@@ -2490,12 +1853,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE(0x086a, 0x0003),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Emagic",
+               /* .product_name = "MT4", */
+-              .ifnum = 2,
+-              .type = QUIRK_MIDI_EMAGIC,
+-              .data = & (const struct snd_usb_midi_endpoint_info) {
++              QUIRK_DATA_MIDI_EMAGIC(2) {
+                       .out_cables = 0x800f,
+                       .in_cables  = 0x8003
+               }
+@@ -2505,38 +1866,35 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* KORG devices */
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0944, 0x0200),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "KORG, Inc.",
+               /* .product_name = "PANDORA PX5D", */
+-              .ifnum = 3,
+-              .type = QUIRK_MIDI_STANDARD_INTERFACE,
++              QUIRK_DATA_STANDARD_MIDI(3)
+       }
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0944, 0x0201),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "KORG, Inc.",
+               /* .product_name = "ToneLab ST", */
+-              .ifnum = 3,
+-              .type = QUIRK_MIDI_STANDARD_INTERFACE,
++              QUIRK_DATA_STANDARD_MIDI(3)
+       }
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0944, 0x0204),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "KORG, Inc.",
+               /* .product_name = "ToneLab EX", */
+-              .ifnum = 3,
+-              .type = QUIRK_MIDI_STANDARD_INTERFACE,
++              QUIRK_DATA_STANDARD_MIDI(3)
+       }
+ },
+ /* AKAI devices */
+ {
+       USB_DEVICE(0x09e8, 0x0062),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "AKAI",
+               .product_name = "MPD16",
+               .ifnum = 0,
+@@ -2547,21 +1905,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* Akai MPC Element */
+       USB_DEVICE(0x09e8, 0x0021),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_MIDI_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_STANDARD_MIDI(1) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -2570,66 +1918,36 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* Steinberg MI2 */
+       USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x2040),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = &(const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* Steinberg MI4 */
+       USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x4040),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = & (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = &(const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -2637,34 +1955,31 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* TerraTec devices */
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "TerraTec",
+               .product_name = "PHASE 26",
+-              .ifnum = 3,
+-              .type = QUIRK_MIDI_STANDARD_INTERFACE
++              QUIRK_DATA_STANDARD_MIDI(3)
+       }
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "TerraTec",
+               .product_name = "PHASE 26",
+-              .ifnum = 3,
+-              .type = QUIRK_MIDI_STANDARD_INTERFACE
++              QUIRK_DATA_STANDARD_MIDI(3)
+       }
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0014),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "TerraTec",
+               .product_name = "PHASE 26",
+-              .ifnum = 3,
+-              .type = QUIRK_MIDI_STANDARD_INTERFACE
++              QUIRK_DATA_STANDARD_MIDI(3)
+       }
+ },
+ {
+       USB_DEVICE(0x0ccd, 0x0035),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Miditech",
+               .product_name = "Play'n Roll",
+               .ifnum = 0,
+@@ -2679,7 +1994,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* Novation EMS devices */
+ {
+       USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Novation",
+               .product_name = "ReMOTE Audio/XStation",
+               .ifnum = 4,
+@@ -2688,7 +2003,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x1235, 0x0002),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Novation",
+               .product_name = "Speedio",
+               .ifnum = 3,
+@@ -2697,38 +2012,29 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ {
+       USB_DEVICE(0x1235, 0x000a),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Novation", */
+               /* .product_name = "Nocturn", */
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_RAW_BYTES
++              QUIRK_DATA_RAW_BYTES(0)
+       }
+ },
+ {
+       USB_DEVICE(0x1235, 0x000e),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               /* .vendor_name = "Novation", */
+               /* .product_name = "Launchpad", */
+-              .ifnum = 0,
+-              .type = QUIRK_MIDI_RAW_BYTES
++              QUIRK_DATA_RAW_BYTES(0)
+       }
+ },
+ {
+       USB_DEVICE(0x1235, 0x0010),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Focusrite",
+               .product_name = "Saffire 6 USB",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(0) },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 0,
+@@ -2755,9 +2061,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 2,
+                                       .iface = 0,
+@@ -2779,28 +2083,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_MIDI_RAW_BYTES
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      { QUIRK_DATA_RAW_BYTES(1) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE(0x1235, 0x0018),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Novation",
+               .product_name = "Twitch",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = & (const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 0,
+@@ -2819,19 +2114,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_MIDI_RAW_BYTES
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      { QUIRK_DATA_RAW_BYTES(1) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Novation",
+               .product_name = "ReMOTE25",
+               .ifnum = 0,
+@@ -2843,25 +2133,16 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* VirusTI Desktop */
+       USB_DEVICE_VENDOR_SPEC(0x133e, 0x0815),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = &(const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) {
+                                       .out_cables = 0x0003,
+                                       .in_cables  = 0x0003
+                               }
+                       },
+-                      {
+-                              .ifnum = 4,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      { QUIRK_DATA_IGNORE(4) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -2889,7 +2170,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* QinHeng devices */
+ {
+       USB_DEVICE(0x1a86, 0x752d),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "QinHeng",
+               .product_name = "CH345",
+               .ifnum = 1,
+@@ -2903,7 +2184,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* Miditech devices */
+ {
+       USB_DEVICE(0x4752, 0x0011),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Miditech",
+               .product_name = "Midistart-2",
+               .ifnum = 0,
+@@ -2915,7 +2196,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* this ID used by both Miditech MidiStudio-2 and CME UF-x */
+       USB_DEVICE(0x7104, 0x2202),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .ifnum = 0,
+               .type = QUIRK_MIDI_CME
+       }
+@@ -2925,20 +2206,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       /* Thanks to Clemens Ladisch <clemens@ladisch.de> */
+       USB_DEVICE(0x0dba, 0x1000),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Digidesign",
+               .product_name = "MBox",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]){
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
++              QUIRK_DATA_COMPOSITE{
++                      { QUIRK_DATA_STANDARD_MIXER(0) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+                                       .channels = 2,
+                                       .iface = 1,
+@@ -2959,9 +2233,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+                                       .channels = 2,
+                                       .iface = 1,
+@@ -2982,9 +2254,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -2992,24 +2262,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* DIGIDESIGN MBOX 2 */
+ {
+       USB_DEVICE(0x0dba, 0x3000),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Digidesign",
+               .product_name = "Mbox 2",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+                                       .channels = 2,
+                                       .iface = 2,
+@@ -3027,15 +2287,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
++                      { QUIRK_DATA_IGNORE(3) },
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 4,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
+-                              .formats = SNDRV_PCM_FMTBIT_S24_3BE,
++                              QUIRK_DATA_AUDIOFORMAT(4) {
++                                      .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+                                       .channels = 2,
+                                       .iface = 4,
+                                       .altsetting = 2,
+@@ -3052,14 +2307,9 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
++                      { QUIRK_DATA_IGNORE(5) },
+                       {
+-                              .ifnum = 5,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 6,
+-                              .type = QUIRK_MIDI_MIDIMAN,
+-                              .data = &(const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_MIDIMAN(6) {
+                                       .out_ep =  0x02,
+                                       .out_cables = 0x0001,
+                                       .in_ep = 0x81,
+@@ -3067,33 +2317,21 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .in_cables = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ /* DIGIDESIGN MBOX 3 */
+ {
+       USB_DEVICE(0x0dba, 0x5000),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Digidesign",
+               .product_name = "Mbox 3",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_IGNORE(1) },
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .fmt_bits = 24,
+                                       .channels = 4,
+@@ -3120,9 +2358,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(3) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .fmt_bits = 24,
+                                       .channels = 4,
+@@ -3146,36 +2382,25 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 4,
+-                              .type = QUIRK_MIDI_FIXED_ENDPOINT,
+-                              .data = &(const struct snd_usb_midi_endpoint_info) {
++                              QUIRK_DATA_MIDI_FIXED_ENDPOINT(4) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ {
+       /* Tascam US122 MKII - playback-only support */
+       USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "TASCAM",
+               .product_name = "US122 MKII",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 2,
+                                       .iface = 1,
+@@ -3196,9 +2421,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3206,20 +2429,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ /* Denon DN-X1600 */
+ {
+       USB_AUDIO_DEVICE(0x154e, 0x500e),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Denon",
+               .product_name = "DN-X1600",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]){
++              QUIRK_DATA_COMPOSITE{
++                      { QUIRK_DATA_IGNORE(0) },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE,
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 1,
+@@ -3240,9 +2456,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 2,
+@@ -3262,13 +2476,8 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = 4,
+-                              .type = QUIRK_MIDI_STANDARD_INTERFACE,
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      { QUIRK_DATA_STANDARD_MIDI(4) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3277,17 +2486,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       USB_DEVICE(0x045e, 0x0283),
+       .bInterfaceClass = USB_CLASS_PER_INTERFACE,
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Microsoft",
+               .product_name = "XboxLive Headset/Xbox Communicator",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
+                       {
+                               /* playback */
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 1,
+                                       .iface = 0,
+@@ -3303,9 +2508,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                       },
+                       {
+                               /* capture */
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 1,
+                                       .iface = 1,
+@@ -3319,9 +2522,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_max = 16000
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3330,18 +2531,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ {
+       USB_DEVICE(0x200c, 0x100b),
+       .bInterfaceClass = USB_CLASS_PER_INTERFACE,
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(0) },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 1,
+@@ -3360,9 +2554,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3375,28 +2567,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * enabled in create_standard_audio_quirk().
+        */
+       USB_DEVICE(0x1686, 0x00dd),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              /* Playback  */
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE,
+-                      },
+-                      {
+-                              /* Capture */
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE,
+-                      },
+-                      {
+-                              /* Midi */
+-                              .ifnum = 3,
+-                              .type = QUIRK_MIDI_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      },
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(1) }, /* Playback  */
++                      { QUIRK_DATA_STANDARD_AUDIO(2) }, /* Capture */
++                      { QUIRK_DATA_STANDARD_MIDI(3) }, /* Midi */
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3410,18 +2586,16 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                      USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+       .bInterfaceClass = USB_CLASS_AUDIO,
+       .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING,
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_MIDI_STANDARD_INTERFACE
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_STANDARD_MIDI(QUIRK_ANY_INTERFACE)
+       }
+ },
+ /* Rane SL-1 */
+ {
+       USB_DEVICE(0x13e5, 0x0001),
+-      .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_AUDIO_STANDARD_INTERFACE
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_STANDARD_AUDIO(QUIRK_ANY_INTERFACE)
+         }
+ },
+@@ -3437,24 +2611,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * and only the 48 kHz sample rate works for the playback interface.
+        */
+       USB_DEVICE(0x0a12, 0x1243),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
+-                      /* Capture */
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_IGNORE_INTERFACE,
+-                      },
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(0) },
++                      { QUIRK_DATA_IGNORE(1) }, /* Capture */
+                       /* Playback */
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 2,
+                                       .iface = 2,
+@@ -3473,9 +2636,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3488,19 +2649,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * even on windows.
+        */
+       USB_DEVICE(0x19b5, 0x0021),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(0) },
+                       /* Playback */
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 2,
+                                       .iface = 1,
+@@ -3519,29 +2673,20 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+ /* MOTU Microbook II */
+ {
+       USB_DEVICE_VENDOR_SPEC(0x07fd, 0x0004),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "MOTU",
+               .product_name = "MicroBookII",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(0) },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+                                       .channels = 6,
+                                       .iface = 0,
+@@ -3562,9 +2707,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3BE,
+                                       .channels = 8,
+                                       .iface = 0,
+@@ -3585,9 +2728,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3599,14 +2740,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * The feedback for the output is the input.
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0023),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 12,
+                                       .iface = 0,
+@@ -3623,9 +2760,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 10,
+                                       .iface = 0,
+@@ -3643,9 +2778,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 44100 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3688,14 +2821,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * but not for DVS (Digital Vinyl Systems) like in Mixxx.
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0017),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8, // outputs
+                                       .iface = 0,
+@@ -3712,9 +2841,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8, // inputs
+                                       .iface = 0,
+@@ -3732,9 +2859,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 48000 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3745,14 +2870,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * The feedback for the output is the dummy input.
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000e),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 0,
+@@ -3769,9 +2890,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 2,
+                                       .iface = 0,
+@@ -3789,9 +2908,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 44100 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3802,14 +2919,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * PCM is 6 channels out & 4 channels in @ 44.1 fixed
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000d),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 6, //Master, Headphones & Booth
+                                       .iface = 0,
+@@ -3826,9 +2939,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4, //2x RCA inputs (CH1 & CH2)
+                                       .iface = 0,
+@@ -3846,9 +2957,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 44100 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3860,14 +2969,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * The Feedback for the output is the input
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x001e),
+-              .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 0,
+@@ -3884,9 +2989,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 6,
+                                       .iface = 0,
+@@ -3904,9 +3007,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 44100 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3917,14 +3018,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * 10 channels playback & 12 channels capture @ 44.1/48/96kHz S24LE
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000a),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 10,
+                                       .iface = 0,
+@@ -3945,9 +3042,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 12,
+                                       .iface = 0,
+@@ -3969,9 +3064,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -3983,14 +3076,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * The Feedback for the output is the input
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0029),
+-              .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 6,
+                                       .iface = 0,
+@@ -4007,9 +3096,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 6,
+                                       .iface = 0,
+@@ -4027,9 +3114,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 44100 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4047,20 +3132,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+  */
+ {
+       USB_AUDIO_DEVICE(0x534d, 0x0021),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "MacroSilicon",
+               .product_name = "MS210x",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(2) },
+                       {
+-                              .ifnum = 3,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(3) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 2,
+                                       .iface = 3,
+@@ -4075,9 +3153,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_max = 48000,
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4095,20 +3171,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+  */
+ {
+       USB_AUDIO_DEVICE(0x534d, 0x2109),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "MacroSilicon",
+               .product_name = "MS2109",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_MIXER(2) },
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_MIXER,
+-                      },
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(3) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 2,
+                                       .iface = 3,
+@@ -4123,9 +3192,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_max = 48000,
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4135,14 +3202,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * 8 channels playback & 8 channels capture @ 44.1/48/96kHz S24LE
+        */
+       USB_DEVICE_VENDOR_SPEC(0x08e4, 0x017f),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 0,
+@@ -4161,9 +3224,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 0,
+@@ -4183,9 +3244,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 44100, 48000, 96000 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4195,14 +3254,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * 10 channels playback & 12 channels capture @ 48kHz S24LE
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x001b),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 10,
+                                       .iface = 0,
+@@ -4221,9 +3276,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 12,
+                                       .iface = 0,
+@@ -4241,9 +3294,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 48000 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4255,14 +3306,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * Capture on EP 0x86
+        */
+       USB_DEVICE_VENDOR_SPEC(0x08e4, 0x0163),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 0,
+@@ -4282,9 +3329,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                               }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 0,
+@@ -4304,9 +3349,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 44100, 48000, 96000 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4317,14 +3360,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * and 8 channels in @ 48 fixed (endpoint 0x82).
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0013),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8, // outputs
+                                       .iface = 0,
+@@ -4341,9 +3380,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       }
+                       },
+                       {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8, // inputs
+                                       .iface = 0,
+@@ -4361,9 +3398,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .rate_table = (unsigned int[]) { 48000 }
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4374,28 +3409,15 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        */
+       USB_DEVICE(0x1395, 0x0300),
+       .bInterfaceClass = USB_CLASS_PER_INTERFACE,
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
++      QUIRK_DRIVER_INFO {
++              QUIRK_DATA_COMPOSITE {
+                       // Communication
+-                      {
+-                              .ifnum = 3,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++                      { QUIRK_DATA_STANDARD_AUDIO(3) },
+                       // Recording
+-                      {
+-                              .ifnum = 4,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++                      { QUIRK_DATA_STANDARD_AUDIO(4) },
+                       // Main
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4404,21 +3426,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * Fiero SC-01 (firmware v1.0.0 @ 48 kHz)
+        */
+       USB_DEVICE(0x2b53, 0x0023),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Fiero",
+               .product_name = "SC-01",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
+                       /* Playback */
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+@@ -4438,9 +3453,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                       },
+                       /* Capture */
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+@@ -4459,9 +3472,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .clock = 0x29
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4470,21 +3481,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * Fiero SC-01 (firmware v1.0.0 @ 96 kHz)
+        */
+       USB_DEVICE(0x2b53, 0x0024),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Fiero",
+               .product_name = "SC-01",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
+                       /* Playback */
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+@@ -4504,9 +3508,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                       },
+                       /* Capture */
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+@@ -4525,9 +3527,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .clock = 0x29
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4536,21 +3536,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * Fiero SC-01 (firmware v1.1.0)
+        */
+       USB_DEVICE(0x2b53, 0x0031),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Fiero",
+               .product_name = "SC-01",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = &(const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE
+-                      },
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_STANDARD_AUDIO(0) },
+                       /* Playback */
+                       {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(1) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+@@ -4571,9 +3564,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                       },
+                       /* Capture */
+                       {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+-                              .data = &(const struct audioformat) {
++                              QUIRK_DATA_AUDIOFORMAT(2) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+@@ -4593,9 +3584,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+                                       .clock = 0x29
+                               }
+                       },
+-                      {
+-                              .ifnum = -1
+-                      }
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+@@ -4604,27 +3593,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+        * For the standard mode, Mythware XA001AU has ID ffad:a001
+        */
+       USB_DEVICE_VENDOR_SPEC(0xffad, 0xa001),
+-      .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++      QUIRK_DRIVER_INFO {
+               .vendor_name = "Mythware",
+               .product_name = "XA001AU",
+-              .ifnum = QUIRK_ANY_INTERFACE,
+-              .type = QUIRK_COMPOSITE,
+-              .data = (const struct snd_usb_audio_quirk[]) {
+-                      {
+-                              .ifnum = 0,
+-                              .type = QUIRK_IGNORE_INTERFACE,
+-                      },
+-                      {
+-                              .ifnum = 1,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE,
+-                      },
+-                      {
+-                              .ifnum = 2,
+-                              .type = QUIRK_AUDIO_STANDARD_INTERFACE,
+-                      },
+-                      {
+-                              .ifnum = -1
+-                      }
++              QUIRK_DATA_COMPOSITE {
++                      { QUIRK_DATA_IGNORE(0) },
++                      { QUIRK_DATA_STANDARD_AUDIO(1) },
++                      { QUIRK_DATA_STANDARD_AUDIO(2) },
++                      QUIRK_COMPOSITE_END
+               }
+       }
+ },
+-- 
+2.43.0
+
diff --git a/queue-6.11/alsa-usb-audio-support-multiple-control-interfaces.patch b/queue-6.11/alsa-usb-audio-support-multiple-control-interfaces.patch
new file mode 100644 (file)
index 0000000..0f911a1
--- /dev/null
@@ -0,0 +1,659 @@
+From 0d5ff56702cf94d5a85af9d602ad1a4548d51eae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 11 Aug 2024 17:29:56 -0700
+Subject: ALSA: usb-audio: Support multiple control interfaces
+
+From: Karol Kosik <k.kosik@outlook.com>
+
+[ Upstream commit 6aa8700150f7dc62f60b4cf5b1624e2e3d9ed78e ]
+
+Registering Numark Party Mix II fails with error 'bogus bTerminalLink 1'.
+The problem stems from the driver not being able to find input/output
+terminals required to configure audio streaming. The information about
+those terminals is stored in AudioControl Interface. Numark device
+contains 2 AudioControl Interfaces and the driver checks only one of them.
+
+According to the USB standard, a device can have multiple audio functions,
+each represented by Audio Interface Collection. Every audio function is
+considered to be closed box and will contain unique AudioControl Interface
+and zero or more AudioStreaming and MIDIStreaming Interfaces.
+
+The Numark device adheres to the standard and defines two audio functions:
+- MIDIStreaming function
+- AudioStreaming function
+It starts with MIDI function, followed by the audio function. The driver
+saves the first AudioControl Interface in `snd_usb_audio` structure
+associated with the entire device. It then attempts to use this interface
+to query for terminals and clocks. However, this fails because the correct
+information is stored in the second AudioControl Interface, defined in the
+second Audio Interface Collection.
+
+This patch introduces a structure holding association between each
+MIDI/Audio Interface and its corresponding AudioControl Interface,
+instead of relying on AudioControl Interface defined for the entire
+device. This structure is populated during usb probing phase and leveraged
+later when querying for terminals and when sending USB requests.
+
+Alternative solutions considered include:
+- defining a quirk for Numark where the order of interface is manually
+changed, or terminals are hardcoded in the driver. This solution would
+have fixed only this model, though it seems that device is USB compliant,
+and it also seems that other devices from this company may be affected.
+What's more, it looks like products from other manufacturers have similar
+problems, i.e. Rane One DJ console
+- keeping a list of all AudioControl Interfaces and querying all of them
+to find required information. That would have solved my problem and have
+low probability of breaking other devices, as we would always start with
+the same logic of querying first AudioControl Interface. This solution
+would not have followed the standard though.
+
+This patch preserves the `snd_usb_audio.ctrl_intf` variable, which holds
+the first AudioControl Interface, and uses it as a fallback when some
+interfaces are not parsed correctly and lack an associated AudioControl
+Interface, i.e., when configured via quirks.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=217865
+Signed-off-by: Karol Kosik <k.kosik@outlook.com>
+Link: https://patch.msgid.link/AS8P190MB1285893F4735C8B32AD3886BEC852@AS8P190MB1285.EURP190.PROD.OUTLOOK.COM
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/card.c           |  2 ++
+ sound/usb/clock.c          | 62 ++++++++++++++++++++++++--------------
+ sound/usb/format.c         |  6 ++--
+ sound/usb/helper.c         | 34 +++++++++++++++++++++
+ sound/usb/helper.h         | 10 ++++--
+ sound/usb/mixer.c          |  2 +-
+ sound/usb/mixer_quirks.c   | 17 ++++++-----
+ sound/usb/mixer_scarlett.c |  4 +--
+ sound/usb/power.c          |  3 +-
+ sound/usb/power.h          |  1 +
+ sound/usb/stream.c         | 21 ++++++++-----
+ sound/usb/usbaudio.h       | 12 ++++++++
+ 12 files changed, 127 insertions(+), 47 deletions(-)
+
+diff --git a/sound/usb/card.c b/sound/usb/card.c
+index bdb04fa37a71d..778de9244f1e7 100644
+--- a/sound/usb/card.c
++++ b/sound/usb/card.c
+@@ -206,6 +206,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
+               return -EINVAL;
+       }
++      snd_usb_add_ctrl_interface_link(chip, interface, ctrlif);
++
+       if (! snd_usb_parse_audio_interface(chip, interface)) {
+               usb_set_interface(dev, interface, 0); /* reset the current interface */
+               return usb_driver_claim_interface(&usb_audio_driver, iface,
+diff --git a/sound/usb/clock.c b/sound/usb/clock.c
+index 60fcb872a80b6..8f85200292f3f 100644
+--- a/sound/usb/clock.c
++++ b/sound/usb/clock.c
+@@ -76,11 +76,14 @@ static bool validate_clock_multiplier(void *p, int id, int proto)
+ }
+ #define DEFINE_FIND_HELPER(name, obj, validator, type2, type3)                \
+-static obj *name(struct snd_usb_audio *chip, int id, int proto)       \
++static obj *name(struct snd_usb_audio *chip, int id,  \
++                              const struct audioformat *fmt)  \
+ {                                                                     \
+-      return find_uac_clock_desc(chip->ctrl_intf, id, validator,      \
+-                                 proto == UAC_VERSION_3 ? (type3) : (type2), \
+-                                 proto);                              \
++      struct usb_host_interface *ctrl_intf =  \
++              snd_usb_find_ctrl_interface(chip, fmt->iface); \
++      return find_uac_clock_desc(ctrl_intf, id, validator,    \
++                                 fmt->protocol == UAC_VERSION_3 ? (type3) : (type2), \
++                                 fmt->protocol);                              \
+ }
+ DEFINE_FIND_HELPER(snd_usb_find_clock_source,
+@@ -93,16 +96,19 @@ DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier,
+                  union uac23_clock_multiplier_desc, validate_clock_multiplier,
+                  UAC2_CLOCK_MULTIPLIER, UAC3_CLOCK_MULTIPLIER);
+-static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
++static int uac_clock_selector_get_val(struct snd_usb_audio *chip,
++                              int selector_id, int iface_no)
+ {
++      struct usb_host_interface *ctrl_intf;
+       unsigned char buf;
+       int ret;
++      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
+       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+                             UAC2_CS_CUR,
+                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+                             UAC2_CX_CLOCK_SELECTOR << 8,
+-                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
++                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
+                             &buf, sizeof(buf));
+       if (ret < 0)
+@@ -111,16 +117,18 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
+       return buf;
+ }
+-static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id,
+-                                      unsigned char pin)
++static int uac_clock_selector_set_val(struct snd_usb_audio *chip,
++                                      int selector_id, unsigned char pin, int iface_no)
+ {
++      struct usb_host_interface *ctrl_intf;
+       int ret;
++      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
+       ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
+                             UAC2_CS_CUR,
+                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+                             UAC2_CX_CLOCK_SELECTOR << 8,
+-                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
++                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
+                             &pin, sizeof(pin));
+       if (ret < 0)
+               return ret;
+@@ -132,7 +140,7 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
+               return -EINVAL;
+       }
+-      ret = uac_clock_selector_get_val(chip, selector_id);
++      ret = uac_clock_selector_get_val(chip, selector_id, iface_no);
+       if (ret < 0)
+               return ret;
+@@ -155,8 +163,10 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
+       unsigned char data;
+       struct usb_device *dev = chip->dev;
+       union uac23_clock_source_desc *cs_desc;
++      struct usb_host_interface *ctrl_intf;
+-      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
++      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
++      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
+       if (!cs_desc)
+               return false;
+@@ -191,7 +201,7 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
+                       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+                                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
+-                                            snd_usb_ctrl_intf(chip) | (source_id << 8),
++                                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
+                                             &data, sizeof(data));
+                       if (err < 0) {
+                               dev_warn(&dev->dev,
+@@ -217,8 +227,10 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
+       struct usb_device *dev = chip->dev;
+       u32 bmControls;
+       union uac23_clock_source_desc *cs_desc;
++      struct usb_host_interface *ctrl_intf;
+-      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
++      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
++      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
+       if (!cs_desc)
+               return false;
+@@ -235,7 +247,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
+       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
+-                            snd_usb_ctrl_intf(chip) | (source_id << 8),
++                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
+                             &data, sizeof(data));
+       if (err < 0) {
+@@ -274,7 +286,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
+       }
+       /* first, see if the ID we're looking at is a clock source already */
+-      source = snd_usb_find_clock_source(chip, entity_id, proto);
++      source = snd_usb_find_clock_source(chip, entity_id, fmt);
+       if (source) {
+               entity_id = GET_VAL(source, proto, bClockID);
+               if (validate && !uac_clock_source_is_valid(chip, fmt,
+@@ -287,7 +299,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
+               return entity_id;
+       }
+-      selector = snd_usb_find_clock_selector(chip, entity_id, proto);
++      selector = snd_usb_find_clock_selector(chip, entity_id, fmt);
+       if (selector) {
+               pins = GET_VAL(selector, proto, bNrInPins);
+               clock_id = GET_VAL(selector, proto, bClockID);
+@@ -317,7 +329,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
+               /* the entity ID we are looking at is a selector.
+                * find out what it currently selects */
+-              ret = uac_clock_selector_get_val(chip, clock_id);
++              ret = uac_clock_selector_get_val(chip, clock_id, fmt->iface);
+               if (ret < 0) {
+                       if (!chip->autoclock)
+                               return ret;
+@@ -346,7 +358,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
+                       if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR ||
+                           !writeable)
+                               return ret;
+-                      err = uac_clock_selector_set_val(chip, entity_id, cur);
++                      err = uac_clock_selector_set_val(chip, entity_id, cur, fmt->iface);
+                       if (err < 0) {
+                               if (pins == 1) {
+                                       usb_audio_dbg(chip,
+@@ -377,7 +389,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
+                       if (ret < 0)
+                               continue;
+-                      err = uac_clock_selector_set_val(chip, entity_id, i);
++                      err = uac_clock_selector_set_val(chip, entity_id, i, fmt->iface);
+                       if (err < 0)
+                               continue;
+@@ -391,7 +403,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
+       }
+       /* FIXME: multipliers only act as pass-thru element for now */
+-      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, proto);
++      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, fmt);
+       if (multiplier)
+               return __uac_clock_find_source(chip, fmt,
+                                              GET_VAL(multiplier, proto, bCSourceID),
+@@ -491,11 +503,13 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
+       struct usb_device *dev = chip->dev;
+       __le32 data;
+       int err;
++      struct usb_host_interface *ctrl_intf;
++      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface);
+       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+-                            snd_usb_ctrl_intf(chip) | (clock << 8),
++                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
+                             &data, sizeof(data));
+       if (err < 0) {
+               dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n",
+@@ -524,8 +538,10 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
+       __le32 data;
+       int err;
+       union uac23_clock_source_desc *cs_desc;
++      struct usb_host_interface *ctrl_intf;
+-      cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol);
++      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
++      cs_desc = snd_usb_find_clock_source(chip, clock, fmt);
+       if (!cs_desc)
+               return 0;
+@@ -544,7 +560,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
+       err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+-                            snd_usb_ctrl_intf(chip) | (clock << 8),
++                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
+                             &data, sizeof(data));
+       if (err < 0)
+               return err;
+diff --git a/sound/usb/format.c b/sound/usb/format.c
+index 1bb6a455a1b46..0cbf1d4fbe6ed 100644
+--- a/sound/usb/format.c
++++ b/sound/usb/format.c
+@@ -545,7 +545,9 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
+       unsigned char tmp[2], *data;
+       int nr_triplets, data_size, ret = 0, ret_l6;
+       int clock = snd_usb_clock_find_source(chip, fp, false);
++      struct usb_host_interface *ctrl_intf;
++      ctrl_intf = snd_usb_find_ctrl_interface(chip, fp->iface);
+       if (clock < 0) {
+               dev_err(&dev->dev,
+                       "%s(): unable to find clock source (clock %d)\n",
+@@ -557,7 +559,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
+       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+-                            snd_usb_ctrl_intf(chip) | (clock << 8),
++                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
+                             tmp, sizeof(tmp));
+       if (ret < 0) {
+@@ -592,7 +594,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
+       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+-                            snd_usb_ctrl_intf(chip) | (clock << 8),
++                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
+                             data, data_size);
+       if (ret < 0) {
+diff --git a/sound/usb/helper.c b/sound/usb/helper.c
+index bf80e55d013a8..72b671fb2c84c 100644
+--- a/sound/usb/helper.c
++++ b/sound/usb/helper.c
+@@ -130,3 +130,37 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
+               return NULL;
+       return usb_altnum_to_altsetting(iface, altsetting);
+ }
++
++int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
++              int ctrlif)
++{
++      struct usb_device *dev = chip->dev;
++      struct usb_host_interface *host_iface;
++
++      if (chip->num_intf_to_ctrl >= MAX_CARD_INTERFACES) {
++              dev_info(&dev->dev, "Too many interfaces assigned to the single USB-audio card\n");
++              return -EINVAL;
++      }
++
++      /* find audiocontrol interface */
++      host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
++
++      chip->intf_to_ctrl[chip->num_intf_to_ctrl].interface = ifnum;
++      chip->intf_to_ctrl[chip->num_intf_to_ctrl].ctrl_intf = host_iface;
++      chip->num_intf_to_ctrl++;
++
++      return 0;
++}
++
++struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
++                                                      int ifnum)
++{
++      int i;
++
++      for (i = 0; i < chip->num_intf_to_ctrl; ++i)
++              if (chip->intf_to_ctrl[i].interface == ifnum)
++                      return chip->intf_to_ctrl[i].ctrl_intf;
++
++      /* Fallback to first audiocontrol interface */
++      return chip->ctrl_intf;
++}
+diff --git a/sound/usb/helper.h b/sound/usb/helper.h
+index e2b51ec96ec62..0372e050b3dc4 100644
+--- a/sound/usb/helper.h
++++ b/sound/usb/helper.h
+@@ -17,6 +17,12 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
+ struct usb_host_interface *
+ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting);
++int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
++              int ctrlif);
++
++struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
++                                                              int ifnum);
++
+ /*
+  * retrieve usb_interface descriptor from the host interface
+  * (conditional for compatibility with the older API)
+@@ -28,9 +34,9 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
+ #define snd_usb_get_speed(dev) ((dev)->speed)
+-static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
++static inline int snd_usb_ctrl_intf(struct usb_host_interface *ctrl_intf)
+ {
+-      return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
++      return get_iface_desc(ctrl_intf)->bInterfaceNumber;
+ }
+ /* in validate.c */
+diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
+index 2d27d729c3bea..9945ae55b0d08 100644
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -728,7 +728,7 @@ static int get_cluster_channels_v3(struct mixer_build *state, unsigned int clust
+                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
+                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+                       cluster_id,
+-                      snd_usb_ctrl_intf(state->chip),
++                      snd_usb_ctrl_intf(state->mixer->hostif),
+                       &c_header, sizeof(c_header));
+       if (err < 0)
+               goto error;
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index 2bc344cf54a83..8cbfb65846047 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -1043,7 +1043,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer,
+       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
+                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+                             pval & 0xff00,
+-                            snd_usb_ctrl_intf(mixer->chip) | ((pval & 0xff) << 8),
++                            snd_usb_ctrl_intf(mixer->hostif) | ((pval & 0xff) << 8),
+                             value, 2);
+       if (err < 0)
+               return err;
+@@ -1077,7 +1077,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list)
+                             UAC_SET_CUR,
+                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+                             pval & 0xff00,
+-                            snd_usb_ctrl_intf(chip) | ((pval & 0xff) << 8),
++                            snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8),
+                             value, 2);
+       snd_usb_unlock_shutdown(chip);
+       return err;
+@@ -2115,24 +2115,25 @@ static int dell_dock_mixer_create(struct usb_mixer_interface *mixer)
+       return 0;
+ }
+-static void dell_dock_init_vol(struct snd_usb_audio *chip, int ch, int id)
++static void dell_dock_init_vol(struct usb_mixer_interface *mixer, int ch, int id)
+ {
++      struct snd_usb_audio *chip = mixer->chip;
+       u16 buf = 0;
+       snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
+                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+                       (UAC_FU_VOLUME << 8) | ch,
+-                      snd_usb_ctrl_intf(chip) | (id << 8),
++                      snd_usb_ctrl_intf(mixer->hostif) | (id << 8),
+                       &buf, 2);
+ }
+ static int dell_dock_mixer_init(struct usb_mixer_interface *mixer)
+ {
+       /* fix to 0dB playback volumes */
+-      dell_dock_init_vol(mixer->chip, 1, 16);
+-      dell_dock_init_vol(mixer->chip, 2, 16);
+-      dell_dock_init_vol(mixer->chip, 1, 19);
+-      dell_dock_init_vol(mixer->chip, 2, 19);
++      dell_dock_init_vol(mixer, 1, 16);
++      dell_dock_init_vol(mixer, 2, 16);
++      dell_dock_init_vol(mixer, 1, 19);
++      dell_dock_init_vol(mixer, 2, 19);
+       return 0;
+ }
+diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
+index 0d6e4f15bf77c..ff548041679bb 100644
+--- a/sound/usb/mixer_scarlett.c
++++ b/sound/usb/mixer_scarlett.c
+@@ -460,7 +460,7 @@ static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl,
+       struct snd_usb_audio *chip = elem->head.mixer->chip;
+       unsigned char buf[2 * MAX_CHANNELS] = {0, };
+       int wValue = (elem->control << 8) | elem->idx_off;
+-      int idx = snd_usb_ctrl_intf(chip) | (elem->head.id << 8);
++      int idx = snd_usb_ctrl_intf(elem->head.mixer->hostif) | (elem->head.id << 8);
+       int err;
+       err = snd_usb_ctl_msg(chip->dev,
+@@ -1002,7 +1002,7 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer)
+       err = snd_usb_ctl_msg(mixer->chip->dev,
+               usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR,
+               USB_RECIP_INTERFACE | USB_TYPE_CLASS |
+-              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->chip) |
++              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->hostif) |
+               (0x29 << 8), sample_rate_buffer, 4);
+       if (err < 0)
+               return err;
+diff --git a/sound/usb/power.c b/sound/usb/power.c
+index 606a2cb23eab6..66bd4daa68fd5 100644
+--- a/sound/usb/power.c
++++ b/sound/usb/power.c
+@@ -40,6 +40,7 @@ snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface,
+                                       le16_to_cpu(pd_desc->waRecoveryTime1);
+                               pd->pd_d2d0_rec =
+                                       le16_to_cpu(pd_desc->waRecoveryTime2);
++                              pd->ctrl_iface = ctrl_iface;
+                               return pd;
+                       }
+               }
+@@ -57,7 +58,7 @@ int snd_usb_power_domain_set(struct snd_usb_audio *chip,
+       unsigned char current_state;
+       int err, idx;
+-      idx = snd_usb_ctrl_intf(chip) | (pd->pd_id << 8);
++      idx = snd_usb_ctrl_intf(pd->ctrl_iface) | (pd->pd_id << 8);
+       err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+                             UAC2_CS_CUR,
+diff --git a/sound/usb/power.h b/sound/usb/power.h
+index 396e3e51440a7..1fa92ad0ca925 100644
+--- a/sound/usb/power.h
++++ b/sound/usb/power.h
+@@ -6,6 +6,7 @@ struct snd_usb_power_domain {
+       int pd_id;              /* UAC3 Power Domain ID */
+       int pd_d1d0_rec;        /* D1 to D0 recovery time */
+       int pd_d2d0_rec;        /* D2 to D0 recovery time */
++      struct usb_host_interface *ctrl_iface; /* Control interface */
+ };
+ enum {
+diff --git a/sound/usb/stream.c b/sound/usb/stream.c
+index e14c725acebf2..d70c140813d68 100644
+--- a/sound/usb/stream.c
++++ b/sound/usb/stream.c
+@@ -713,10 +713,13 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
+       struct usb_device *dev = chip->dev;
+       struct uac_format_type_i_continuous_descriptor *fmt;
+       unsigned int num_channels = 0, chconfig = 0;
++      struct usb_host_interface *ctrl_intf;
+       struct audioformat *fp;
+       int clock = 0;
+       u64 format;
++      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
++
+       /* get audio formats */
+       if (protocol == UAC_VERSION_1) {
+               struct uac1_as_header_descriptor *as =
+@@ -740,7 +743,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
+               format = le16_to_cpu(as->wFormatTag); /* remember the format value */
+-              iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
++              iterm = snd_usb_find_input_terminal_descriptor(ctrl_intf,
+                                                              as->bTerminalLink,
+                                                              protocol);
+               if (iterm) {
+@@ -776,7 +779,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
+                * lookup the terminal associated to this interface
+                * to extract the clock
+                */
+-              input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
++              input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
+                                                                   as->bTerminalLink,
+                                                                   protocol);
+               if (input_term) {
+@@ -786,7 +789,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
+                       goto found_clock;
+               }
+-              output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
++              output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
+                                                                     as->bTerminalLink,
+                                                                     protocol);
+               if (output_term) {
+@@ -870,6 +873,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
+       struct uac3_cluster_header_descriptor *cluster;
+       struct uac3_as_header_descriptor *as = NULL;
+       struct uac3_hc_descriptor_header hc_header;
++      struct usb_host_interface *ctrl_intf;
+       struct snd_pcm_chmap_elem *chmap;
+       struct snd_usb_power_domain *pd;
+       unsigned char badd_profile;
+@@ -881,6 +885,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
+       int err;
+       badd_profile = chip->badd_profile;
++      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
+       if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
+               unsigned int maxpacksize =
+@@ -966,7 +971,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
+                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
+                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+                       cluster_id,
+-                      snd_usb_ctrl_intf(chip),
++                      snd_usb_ctrl_intf(ctrl_intf),
+                       &hc_header, sizeof(hc_header));
+       if (err < 0)
+               return ERR_PTR(err);
+@@ -990,7 +995,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
+                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
+                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+                       cluster_id,
+-                      snd_usb_ctrl_intf(chip),
++                      snd_usb_ctrl_intf(ctrl_intf),
+                       cluster, wLength);
+       if (err < 0) {
+               kfree(cluster);
+@@ -1011,7 +1016,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
+        * lookup the terminal associated to this interface
+        * to extract the clock
+        */
+-      input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
++      input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
+                                                           as->bTerminalLink,
+                                                           UAC_VERSION_3);
+       if (input_term) {
+@@ -1019,7 +1024,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
+               goto found_clock;
+       }
+-      output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
++      output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
+                                                             as->bTerminalLink,
+                                                             UAC_VERSION_3);
+       if (output_term) {
+@@ -1068,7 +1073,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
+                                                              UAC_VERSION_3,
+                                                              iface_no);
+-              pd = snd_usb_find_power_domain(chip->ctrl_intf,
++              pd = snd_usb_find_power_domain(ctrl_intf,
+                                              as->bTerminalLink);
+               /* ok, let's parse further... */
+diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
+index 43d4029edab46..b0f042c996087 100644
+--- a/sound/usb/usbaudio.h
++++ b/sound/usb/usbaudio.h
+@@ -21,6 +21,15 @@ struct media_intf_devnode;
+ #define MAX_CARD_INTERFACES   16
++/*
++ * Structure holding assosiation between Audio Control Interface
++ * and given Streaming or Midi Interface.
++ */
++struct snd_intf_to_ctrl {
++      u8 interface;
++      struct usb_host_interface *ctrl_intf;
++};
++
+ struct snd_usb_audio {
+       int index;
+       struct usb_device *dev;
+@@ -63,6 +72,9 @@ struct snd_usb_audio {
+       struct usb_host_interface *ctrl_intf;   /* the audio control interface */
+       struct media_device *media_dev;
+       struct media_intf_devnode *ctl_intf_media_devnode;
++
++      unsigned int num_intf_to_ctrl;
++      struct snd_intf_to_ctrl intf_to_ctrl[MAX_CARD_INTERFACES];
+ };
+ #define USB_AUDIO_IFACE_UNUSED        ((void *)-1L)
+-- 
+2.43.0
+
diff --git a/queue-6.11/arm64-trans_pgd-mark-ptes-entries-as-valid-to-avoid-.patch b/queue-6.11/arm64-trans_pgd-mark-ptes-entries-as-valid-to-avoid-.patch
new file mode 100644 (file)
index 0000000..2390ba6
--- /dev/null
@@ -0,0 +1,62 @@
+From 22ee03538f323c892ed8b1eb1209381d15905d21 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Sep 2024 16:33:08 +0000
+Subject: arm64: trans_pgd: mark PTEs entries as valid to avoid dead kexec()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Fares Mehanna <faresx@amazon.de>
+
+[ Upstream commit 7eced90b202d63cdc1b9b11b1353adb1389830f9 ]
+
+The reasons for PTEs in the kernel direct map to be marked invalid are not
+limited to kfence / debug pagealloc machinery. In particular,
+memfd_secret() also steals pages with set_direct_map_invalid_noflush().
+
+When building the transitional page tables for kexec from the current
+kernel's page tables, those pages need to become regular writable pages,
+otherwise, if the relocation places kexec segments over such pages, a fault
+will occur during kexec, leading to host going dark during kexec.
+
+This patch addresses the kexec issue by marking any PTE as valid if it is
+not none. While this fixes the kexec crash, it does not address the
+security concern that if processes owning secret memory are not terminated
+before kexec, the secret content will be mapped in the new kernel without
+being scrubbed.
+
+Suggested-by: Jan H. Schönherr <jschoenh@amazon.de>
+Signed-off-by: Fares Mehanna <faresx@amazon.de>
+Link: https://lore.kernel.org/r/20240902163309.97113-1-faresx@amazon.de
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/mm/trans_pgd.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm64/mm/trans_pgd.c b/arch/arm64/mm/trans_pgd.c
+index 5139a28130c08..0f7b484cb2ff2 100644
+--- a/arch/arm64/mm/trans_pgd.c
++++ b/arch/arm64/mm/trans_pgd.c
+@@ -42,14 +42,16 @@ static void _copy_pte(pte_t *dst_ptep, pte_t *src_ptep, unsigned long addr)
+                * the temporary mappings we use during restore.
+                */
+               __set_pte(dst_ptep, pte_mkwrite_novma(pte));
+-      } else if ((debug_pagealloc_enabled() ||
+-                 is_kfence_address((void *)addr)) && !pte_none(pte)) {
++      } else if (!pte_none(pte)) {
+               /*
+                * debug_pagealloc will removed the PTE_VALID bit if
+                * the page isn't in use by the resume kernel. It may have
+                * been in use by the original kernel, in which case we need
+                * to put it back in our copy to do the restore.
+                *
++               * Other cases include kfence / vmalloc / memfd_secret which
++               * may call `set_direct_map_invalid_noflush()`.
++               *
+                * Before marking this entry valid, check the pfn should
+                * be mapped.
+                */
+-- 
+2.43.0
+
diff --git a/queue-6.11/asoc-codecs-wsa883x-handle-reading-version-failure.patch b/queue-6.11/asoc-codecs-wsa883x-handle-reading-version-failure.patch
new file mode 100644 (file)
index 0000000..97da63e
--- /dev/null
@@ -0,0 +1,72 @@
+From 4251c27d2f82c97a2cbf85f2efb4706ca3233855 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Jul 2024 15:52:31 +0200
+Subject: ASoC: codecs: wsa883x: Handle reading version failure
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 2fbf16992e5aa14acf0441320033a01a32309ded ]
+
+If reading version and variant from registers fails (which is unlikely
+but possible, because it is a read over bus), the driver will proceed
+and perform device configuration based on uninitialized stack variables.
+Handle it a bit better - bail out without doing any init and failing the
+update status Soundwire callback.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://patch.msgid.link/20240710-asoc-wsa88xx-version-v1-2-f1c54966ccde@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wsa883x.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c
+index 3e4fdaa3f44fb..53f6de4340548 100644
+--- a/sound/soc/codecs/wsa883x.c
++++ b/sound/soc/codecs/wsa883x.c
+@@ -997,15 +997,19 @@ static const struct reg_sequence reg_init[] = {
+       {WSA883X_GMAMP_SUP1, 0xE2},
+ };
+-static void wsa883x_init(struct wsa883x_priv *wsa883x)
++static int wsa883x_init(struct wsa883x_priv *wsa883x)
+ {
+       struct regmap *regmap = wsa883x->regmap;
+-      int variant, version;
++      int variant, version, ret;
+-      regmap_read(regmap, WSA883X_OTP_REG_0, &variant);
++      ret = regmap_read(regmap, WSA883X_OTP_REG_0, &variant);
++      if (ret)
++              return ret;
+       wsa883x->variant = variant & WSA883X_ID_MASK;
+-      regmap_read(regmap, WSA883X_CHIP_ID0, &version);
++      ret = regmap_read(regmap, WSA883X_CHIP_ID0, &version);
++      if (ret)
++              return ret;
+       wsa883x->version = version;
+       switch (wsa883x->variant) {
+@@ -1040,6 +1044,8 @@ static void wsa883x_init(struct wsa883x_priv *wsa883x)
+                                  WSA883X_DRE_OFFSET_MASK,
+                                  wsa883x->comp_offset);
+       }
++
++      return 0;
+ }
+ static int wsa883x_update_status(struct sdw_slave *slave,
+@@ -1048,7 +1054,7 @@ static int wsa883x_update_status(struct sdw_slave *slave,
+       struct wsa883x_priv *wsa883x = dev_get_drvdata(&slave->dev);
+       if (status == SDW_SLAVE_ATTACHED && slave->dev_num > 0)
+-              wsa883x_init(wsa883x);
++              return wsa883x_init(wsa883x);
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/asoc-intel-boards-always-check-the-result-of-acpi_de.patch b/queue-6.11/asoc-intel-boards-always-check-the-result-of-acpi_de.patch
new file mode 100644 (file)
index 0000000..4d50261
--- /dev/null
@@ -0,0 +1,174 @@
+From db0332dbcb40222b8b236880d3446e48b353c014 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 20:32:01 +0800
+Subject: ASoC: Intel: boards: always check the result of
+ acpi_dev_get_first_match_dev()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit 14e91ddd5c02d8c3e5a682ebfa0546352b459911 ]
+
+The code seems mostly copy-pasted, with some machine drivers
+forgetting to test if the 'adev' result is NULL.
+
+Add this check when missing, and use -ENOENT consistently as an error
+code.
+
+Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
+Closes: https://lore.kernel.org/alsa-devel/918944d2-3d00-465e-a9d1-5d57fc966113@stanley.mountain/T/#u
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
+Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://patch.msgid.link/20240827123215.258859-4-yung-chuan.liao@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcht_cx2072x.c | 4 ++++
+ sound/soc/intel/boards/bytcht_da7213.c  | 4 ++++
+ sound/soc/intel/boards/bytcht_es8316.c  | 2 +-
+ sound/soc/intel/boards/bytcr_rt5640.c   | 2 +-
+ sound/soc/intel/boards/bytcr_rt5651.c   | 2 +-
+ sound/soc/intel/boards/cht_bsw_rt5645.c | 4 ++++
+ sound/soc/intel/boards/cht_bsw_rt5672.c | 4 ++++
+ sound/soc/intel/boards/sof_es8336.c     | 2 +-
+ sound/soc/intel/boards/sof_wm8804.c     | 4 ++++
+ 9 files changed, 24 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c
+index df3c2a7b64d23..8c2b4ab764bba 100644
+--- a/sound/soc/intel/boards/bytcht_cx2072x.c
++++ b/sound/soc/intel/boards/bytcht_cx2072x.c
+@@ -255,7 +255,11 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev)
+               snprintf(codec_name, sizeof(codec_name), "i2c-%s",
+                        acpi_dev_name(adev));
+               byt_cht_cx2072x_dais[dai_index].codecs->name = codec_name;
++      } else {
++              dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
++              return -ENOENT;
+       }
++
+       acpi_dev_put(adev);
+       /* override platform name, if required */
+diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c
+index 08c598b7e1eee..9178bbe8d9950 100644
+--- a/sound/soc/intel/boards/bytcht_da7213.c
++++ b/sound/soc/intel/boards/bytcht_da7213.c
+@@ -258,7 +258,11 @@ static int bytcht_da7213_probe(struct platform_device *pdev)
+               snprintf(codec_name, sizeof(codec_name),
+                        "i2c-%s", acpi_dev_name(adev));
+               dailink[dai_index].codecs->name = codec_name;
++      } else {
++              dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
++              return -ENOENT;
+       }
++
+       acpi_dev_put(adev);
+       /* override platform name, if required */
+diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
+index 77b91ea4dc32c..3539c9ff0fd2c 100644
+--- a/sound/soc/intel/boards/bytcht_es8316.c
++++ b/sound/soc/intel/boards/bytcht_es8316.c
+@@ -562,7 +562,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
+               byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
+       } else {
+               dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
+-              return -ENXIO;
++              return -ENOENT;
+       }
+       codec_dev = acpi_get_first_physical_node(adev);
+diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
+index db4a33680d948..4479825c08b5e 100644
+--- a/sound/soc/intel/boards/bytcr_rt5640.c
++++ b/sound/soc/intel/boards/bytcr_rt5640.c
+@@ -1693,7 +1693,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
+               byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;
+       } else {
+               dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
+-              return -ENXIO;
++              return -ENOENT;
+       }
+       codec_dev = acpi_get_first_physical_node(adev);
+diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
+index 8514b79f389bb..1f54da98aacf4 100644
+--- a/sound/soc/intel/boards/bytcr_rt5651.c
++++ b/sound/soc/intel/boards/bytcr_rt5651.c
+@@ -926,7 +926,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
+               byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
+       } else {
+               dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
+-              return -ENXIO;
++              return -ENOENT;
+       }
+       codec_dev = acpi_get_first_physical_node(adev);
+diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
+index 1da9ceee4d593..ac23a8b7cafca 100644
+--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
++++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
+@@ -582,7 +582,11 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
+               snprintf(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name),
+                        "i2c-%s", acpi_dev_name(adev));
+               cht_dailink[dai_index].codecs->name = cht_rt5645_codec_name;
++      } else {
++              dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
++              return -ENOENT;
+       }
++
+       /* acpi_get_first_physical_node() returns a borrowed ref, no need to deref */
+       codec_dev = acpi_get_first_physical_node(adev);
+       acpi_dev_put(adev);
+diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c
+index d68e5bc755dee..c6c469d51243e 100644
+--- a/sound/soc/intel/boards/cht_bsw_rt5672.c
++++ b/sound/soc/intel/boards/cht_bsw_rt5672.c
+@@ -479,7 +479,11 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
+               snprintf(drv->codec_name, sizeof(drv->codec_name),
+                        "i2c-%s", acpi_dev_name(adev));
+               cht_dailink[dai_index].codecs->name = drv->codec_name;
++      }  else {
++              dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
++              return -ENOENT;
+       }
++
+       acpi_dev_put(adev);
+       /* Use SSP0 on Bay Trail CR devices */
+diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
+index 2a88efaa6d26b..b45d0501f1090 100644
+--- a/sound/soc/intel/boards/sof_es8336.c
++++ b/sound/soc/intel/boards/sof_es8336.c
+@@ -681,7 +681,7 @@ static int sof_es8336_probe(struct platform_device *pdev)
+                       dai_links[0].codecs->dai_name = "ES8326 HiFi";
+       } else {
+               dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
+-              return -ENXIO;
++              return -ENOENT;
+       }
+       codec_dev = acpi_get_first_physical_node(adev);
+diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c
+index b2d02cc92a6a8..0a5ce34d7f7bb 100644
+--- a/sound/soc/intel/boards/sof_wm8804.c
++++ b/sound/soc/intel/boards/sof_wm8804.c
+@@ -270,7 +270,11 @@ static int sof_wm8804_probe(struct platform_device *pdev)
+               snprintf(codec_name, sizeof(codec_name),
+                        "%s%s", "i2c-", acpi_dev_name(adev));
+               dailink[dai_index].codecs->name = codec_name;
++      } else {
++              dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
++              return -ENOENT;
+       }
++
+       acpi_dev_put(adev);
+       snd_soc_card_set_drvdata(card, ctx);
+-- 
+2.43.0
+
diff --git a/queue-6.11/ata-pata_serverworks-do-not-use-the-term-blacklist.patch b/queue-6.11/ata-pata_serverworks-do-not-use-the-term-blacklist.patch
new file mode 100644 (file)
index 0000000..fe1e400
--- /dev/null
@@ -0,0 +1,65 @@
+From 106fce3509096c391ee57d0482d1e857e3dfb6fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jul 2024 10:58:36 +0900
+Subject: ata: pata_serverworks: Do not use the term blacklist
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit 858048568c9e3887d8b19e101ee72f129d65cb15 ]
+
+Let's not use the term blacklist in the function
+serverworks_osb4_filter() documentation comment and rather simply refer
+to what that function looks at: the list of devices with groken UDMA5.
+
+While at it, also constify the values of the csb_bad_ata100 array.
+
+Of note is that all of this should probably be handled using libata
+quirk mechanism but it is unclear if these UDMA5 quirks are specific
+to this controller only.
+
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Reviewed-by: Igor Pylypiv <ipylypiv@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/pata_serverworks.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
+index 549ff24a98231..4edddf6bcc150 100644
+--- a/drivers/ata/pata_serverworks.c
++++ b/drivers/ata/pata_serverworks.c
+@@ -46,10 +46,11 @@
+ #define SVWKS_CSB5_REVISION_NEW       0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
+ #define SVWKS_CSB6_REVISION   0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
+-/* Seagate Barracuda ATA IV Family drives in UDMA mode 5
+- * can overrun their FIFOs when used with the CSB5 */
+-
+-static const char *csb_bad_ata100[] = {
++/*
++ * Seagate Barracuda ATA IV Family drives in UDMA mode 5
++ * can overrun their FIFOs when used with the CSB5.
++ */
++static const char * const csb_bad_ata100[] = {
+       "ST320011A",
+       "ST340016A",
+       "ST360021A",
+@@ -163,10 +164,11 @@ static unsigned int serverworks_osb4_filter(struct ata_device *adev, unsigned in
+  *    @adev: ATA device
+  *    @mask: Mask of proposed modes
+  *
+- *    Check the blacklist and disable UDMA5 if matched
++ *    Check the list of devices with broken UDMA5 and
++ *    disable UDMA5 if matched.
+  */
+-
+-static unsigned int serverworks_csb_filter(struct ata_device *adev, unsigned int mask)
++static unsigned int serverworks_csb_filter(struct ata_device *adev,
++                                         unsigned int mask)
+ {
+       const char *p;
+       char model_num[ATA_ID_PROD_LEN + 1];
+-- 
+2.43.0
+
diff --git a/queue-6.11/ata-sata_sil-rename-sil_blacklist-to-sil_quirks.patch b/queue-6.11/ata-sata_sil-rename-sil_blacklist-to-sil_quirks.patch
new file mode 100644 (file)
index 0000000..5dc2a77
--- /dev/null
@@ -0,0 +1,61 @@
+From 90168a23f78b467e39f09fe04ec388ee1c26b49d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jul 2024 11:14:11 +0900
+Subject: ata: sata_sil: Rename sil_blacklist to sil_quirks
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit 93b0f9e11ce511353c65b7f924cf5f95bd9c3aba ]
+
+Rename the array sil_blacklist to sil_quirks as this name is more
+neutral and is also consistent with how this driver define quirks with
+the SIL_QUIRK_XXX flags.
+
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Niklas Cassel <cassel@kernel.org>
+Reviewed-by: Igor Pylypiv <ipylypiv@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/sata_sil.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
+index cc77c02482843..df095659bae0f 100644
+--- a/drivers/ata/sata_sil.c
++++ b/drivers/ata/sata_sil.c
+@@ -128,7 +128,7 @@ static const struct pci_device_id sil_pci_tbl[] = {
+ static const struct sil_drivelist {
+       const char *product;
+       unsigned int quirk;
+-} sil_blacklist [] = {
++} sil_quirks[] = {
+       { "ST320012AS",         SIL_QUIRK_MOD15WRITE },
+       { "ST330013AS",         SIL_QUIRK_MOD15WRITE },
+       { "ST340017AS",         SIL_QUIRK_MOD15WRITE },
+@@ -600,8 +600,8 @@ static void sil_thaw(struct ata_port *ap)
+  *    list, and apply the fixups to only the specific
+  *    devices/hosts/firmwares that need it.
+  *
+- *    20040111 - Seagate drives affected by the Mod15Write bug are blacklisted
+- *    The Maxtor quirk is in the blacklist, but I'm keeping the original
++ *    20040111 - Seagate drives affected by the Mod15Write bug are quirked
++ *    The Maxtor quirk is in sil_quirks, but I'm keeping the original
+  *    pessimistic fix for the following reasons...
+  *    - There seems to be less info on it, only one device gleaned off the
+  *    Windows driver, maybe only one is affected.  More info would be greatly
+@@ -620,9 +620,9 @@ static void sil_dev_config(struct ata_device *dev)
+       ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
+-      for (n = 0; sil_blacklist[n].product; n++)
+-              if (!strcmp(sil_blacklist[n].product, model_num)) {
+-                      quirks = sil_blacklist[n].quirk;
++      for (n = 0; sil_quirks[n].product; n++)
++              if (!strcmp(sil_quirks[n].product, model_num)) {
++                      quirks = sil_quirks[n].quirk;
+                       break;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.11/blk_iocost-fix-more-out-of-bound-shifts.patch b/queue-6.11/blk_iocost-fix-more-out-of-bound-shifts.patch
new file mode 100644 (file)
index 0000000..feff29c
--- /dev/null
@@ -0,0 +1,80 @@
+From 5ae8df2927ac541f656f7296e686d0b0c56358e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Aug 2024 08:41:36 -0700
+Subject: blk_iocost: fix more out of bound shifts
+
+From: Konstantin Ovsepian <ovs@ovs.to>
+
+[ Upstream commit 9bce8005ec0dcb23a58300e8522fe4a31da606fa ]
+
+Recently running UBSAN caught few out of bound shifts in the
+ioc_forgive_debts() function:
+
+UBSAN: shift-out-of-bounds in block/blk-iocost.c:2142:38
+shift exponent 80 is too large for 64-bit type 'u64' (aka 'unsigned long
+long')
+...
+UBSAN: shift-out-of-bounds in block/blk-iocost.c:2144:30
+shift exponent 80 is too large for 64-bit type 'u64' (aka 'unsigned long
+long')
+...
+Call Trace:
+<IRQ>
+dump_stack_lvl+0xca/0x130
+__ubsan_handle_shift_out_of_bounds+0x22c/0x280
+? __lock_acquire+0x6441/0x7c10
+ioc_timer_fn+0x6cec/0x7750
+? blk_iocost_init+0x720/0x720
+? call_timer_fn+0x5d/0x470
+call_timer_fn+0xfa/0x470
+? blk_iocost_init+0x720/0x720
+__run_timer_base+0x519/0x700
+...
+
+Actual impact of this issue was not identified but I propose to fix the
+undefined behaviour.
+The proposed fix to prevent those out of bound shifts consist of
+precalculating exponent before using it the shift operations by taking
+min value from the actual exponent and maximum possible number of bits.
+
+Reported-by: Breno Leitao <leitao@debian.org>
+Signed-off-by: Konstantin Ovsepian <ovs@ovs.to>
+Acked-by: Tejun Heo <tj@kernel.org>
+Link: https://lore.kernel.org/r/20240822154137.2627818-1-ovs@ovs.to
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-iocost.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/block/blk-iocost.c b/block/blk-iocost.c
+index 690ca99dfaca6..5a6098a3db57e 100644
+--- a/block/blk-iocost.c
++++ b/block/blk-iocost.c
+@@ -2076,7 +2076,7 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors,
+                             struct ioc_now *now)
+ {
+       struct ioc_gq *iocg;
+-      u64 dur, usage_pct, nr_cycles;
++      u64 dur, usage_pct, nr_cycles, nr_cycles_shift;
+       /* if no debtor, reset the cycle */
+       if (!nr_debtors) {
+@@ -2138,10 +2138,12 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors,
+               old_debt = iocg->abs_vdebt;
+               old_delay = iocg->delay;
++              nr_cycles_shift = min_t(u64, nr_cycles, BITS_PER_LONG - 1);
+               if (iocg->abs_vdebt)
+-                      iocg->abs_vdebt = iocg->abs_vdebt >> nr_cycles ?: 1;
++                      iocg->abs_vdebt = iocg->abs_vdebt >> nr_cycles_shift ?: 1;
++
+               if (iocg->delay)
+-                      iocg->delay = iocg->delay >> nr_cycles ?: 1;
++                      iocg->delay = iocg->delay >> nr_cycles_shift ?: 1;
+               iocg_kick_waitq(iocg, true, now);
+-- 
+2.43.0
+
diff --git a/queue-6.11/block-fix-integer-overflow-in-blksecdiscard.patch b/queue-6.11/block-fix-integer-overflow-in-blksecdiscard.patch
new file mode 100644 (file)
index 0000000..bfc2b61
--- /dev/null
@@ -0,0 +1,75 @@
+From 85e86a64f07803f473c1bd0aa49eb2cd970deea9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Sep 2024 22:48:19 +0300
+Subject: block: fix integer overflow in BLKSECDISCARD
+
+From: Alexey Dobriyan <adobriyan@gmail.com>
+
+[ Upstream commit 697ba0b6ec4ae04afb67d3911799b5e2043b4455 ]
+
+I independently rediscovered
+
+       commit 22d24a544b0d49bbcbd61c8c0eaf77d3c9297155
+       block: fix overflow in blk_ioctl_discard()
+
+but for secure erase.
+
+Same problem:
+
+       uint64_t r[2] = {512, 18446744073709551104ULL};
+       ioctl(fd, BLKSECDISCARD, r);
+
+will enter near infinite loop inside blkdev_issue_secure_erase():
+
+       a.out: attempt to access beyond end of device
+       loop0: rw=5, sector=3399043073, nr_sectors = 1024 limit=2048
+       bio_check_eod: 3286214 callbacks suppressed
+
+Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
+Link: https://lore.kernel.org/r/9e64057f-650a-46d1-b9f7-34af391536ef@p183
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/ioctl.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/block/ioctl.c b/block/ioctl.c
+index e8e4a4190f183..44257bdfeacbf 100644
+--- a/block/ioctl.c
++++ b/block/ioctl.c
+@@ -126,7 +126,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
+               return -EINVAL;
+       filemap_invalidate_lock(bdev->bd_mapping);
+-      err = truncate_bdev_range(bdev, mode, start, start + len - 1);
++      err = truncate_bdev_range(bdev, mode, start, end - 1);
+       if (err)
+               goto fail;
+@@ -163,7 +163,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
+ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode,
+               void __user *argp)
+ {
+-      uint64_t start, len;
++      uint64_t start, len, end;
+       uint64_t range[2];
+       int err;
+@@ -178,11 +178,12 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode,
+       len = range[1];
+       if ((start & 511) || (len & 511))
+               return -EINVAL;
+-      if (start + len > bdev_nr_bytes(bdev))
++      if (check_add_overflow(start, len, &end) ||
++          end > bdev_nr_bytes(bdev))
+               return -EINVAL;
+       filemap_invalidate_lock(bdev->bd_mapping);
+-      err = truncate_bdev_range(bdev, mode, start, start + len - 1);
++      err = truncate_bdev_range(bdev, mode, start, end - 1);
+       if (!err)
+               err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9,
+                                               GFP_KERNEL);
+-- 
+2.43.0
+
diff --git a/queue-6.11/bluetooth-btrtl-set-msft-ext-address-filter-quirk-fo.patch b/queue-6.11/bluetooth-btrtl-set-msft-ext-address-filter-quirk-fo.patch
new file mode 100644 (file)
index 0000000..0a94756
--- /dev/null
@@ -0,0 +1,42 @@
+From 7a7caf5e307ac95f1eeaba595edcdb0c21c9a072 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Aug 2024 16:40:05 +0800
+Subject: Bluetooth: btrtl: Set msft ext address filter quirk for RTL8852B
+
+From: Hilda Wu <hildawu@realtek.com>
+
+[ Upstream commit 9a0570948c5def5c59e588dc0e009ed850a1f5a1 ]
+
+For tracking multiple devices concurrently with a condition.
+The patch enables the HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER quirk
+on RTL8852B controller.
+
+The quirk setting is based on commit 9e14606d8f38 ("Bluetooth: msft:
+Extended monitor tracking by address filter")
+
+With this setting, when a pattern monitor detects a device, this
+feature issues an address monitor for tracking that device. Let the
+original pattern monitor keep monitor new devices.
+
+Signed-off-by: Hilda Wu <hildawu@realtek.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btrtl.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
+index fd7991ea76726..7cce4abc8a023 100644
+--- a/drivers/bluetooth/btrtl.c
++++ b/drivers/bluetooth/btrtl.c
+@@ -1296,6 +1296,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev)
+                       btrealtek_set_flag(hdev, REALTEK_ALT6_CONTINUOUS_TX_CHIP);
+               if (btrtl_dev->project_id == CHIP_ID_8852A ||
++                  btrtl_dev->project_id == CHIP_ID_8852B ||
+                   btrtl_dev->project_id == CHIP_ID_8852C)
+                       set_bit(HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER, &hdev->quirks);
+-- 
+2.43.0
+
diff --git a/queue-6.11/bluetooth-btusb-add-realtek-rtl8852c-support-id-0x04.patch b/queue-6.11/bluetooth-btusb-add-realtek-rtl8852c-support-id-0x04.patch
new file mode 100644 (file)
index 0000000..2e16822
--- /dev/null
@@ -0,0 +1,67 @@
+From cf592732e3845158198a6101c58eac9ba470ece1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Aug 2024 16:58:22 +0800
+Subject: Bluetooth: btusb: Add Realtek RTL8852C support ID 0x0489:0xe122
+
+From: Hilda Wu <hildawu@realtek.com>
+
+[ Upstream commit bdf9557f70e7512bb2f754abf90d9e9958745316 ]
+
+Add the support ID (0x0489, 0xe122) to usb_device_id table for
+Realtek RTL8852C.
+
+The device info from /sys/kernel/debug/usb/devices as below.
+
+T:  Bus=03 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
+D:  Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
+P:  Vendor=0489 ProdID=e122 Rev= 0.00
+S:  Manufacturer=Realtek
+S:  Product=Bluetooth Radio
+S:  SerialNumber=00e04c000001
+C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA
+I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=81(I) Atr=03(Int.) MxPS=  16 Ivl=1ms
+E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
+E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
+I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
+I:  If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
+I:  If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
+I:  If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
+I:  If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
+I:  If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms
+
+Signed-off-by: Hilda Wu <hildawu@realtek.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btusb.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 1ec71a2fb63ea..93dbeb8b348d5 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -540,6 +540,8 @@ static const struct usb_device_id quirks_table[] = {
+                                                    BTUSB_WIDEBAND_SPEECH },
+       { USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK |
+                                                    BTUSB_WIDEBAND_SPEECH },
++      { USB_DEVICE(0x0489, 0xe122), .driver_info = BTUSB_REALTEK |
++                                                   BTUSB_WIDEBAND_SPEECH },
+       /* Realtek 8852BE Bluetooth devices */
+       { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
+-- 
+2.43.0
+
diff --git a/queue-6.11/bnxt_en-extend-maximum-length-of-version-string-by-1.patch b/queue-6.11/bnxt_en-extend-maximum-length-of-version-string-by-1.patch
new file mode 100644 (file)
index 0000000..d2dad89
--- /dev/null
@@ -0,0 +1,42 @@
+From 5de07ecdb89af53f74a8705f3617ad4819801700 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Aug 2024 15:32:55 +0100
+Subject: bnxt_en: Extend maximum length of version string by 1 byte
+
+From: Simon Horman <horms@kernel.org>
+
+[ Upstream commit ffff7ee843c351ce71d6e0d52f0f20bea35e18c9 ]
+
+This corrects an out-by-one error in the maximum length of the package
+version string. The size argument of snprintf includes space for the
+trailing '\0' byte, so there is no need to allow extra space for it by
+reducing the value of the size argument by 1.
+
+Found by inspection.
+Compile tested only.
+
+Signed-off-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Michael Chan <michael.chan@broadcom.com>
+Link: https://patch.msgid.link/20240813-bnxt-str-v2-1-872050a157e7@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+index 4cf9bf8b01b09..ac06f4a4cf97c 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+@@ -4157,7 +4157,7 @@ static void bnxt_get_pkgver(struct net_device *dev)
+       if (!bnxt_get_pkginfo(dev, buf, sizeof(buf))) {
+               len = strlen(bp->fw_ver_str);
+-              snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
++              snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len,
+                        "/pkg %s", buf);
+       }
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/bpf-fix-a-sdiv-overflow-issue.patch b/queue-6.11/bpf-fix-a-sdiv-overflow-issue.patch
new file mode 100644 (file)
index 0000000..c2f621b
--- /dev/null
@@ -0,0 +1,202 @@
+From 24fe44f29f5a1df9bb8d8da02881c661079800d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Sep 2024 08:03:26 -0700
+Subject: bpf: Fix a sdiv overflow issue
+
+From: Yonghong Song <yonghong.song@linux.dev>
+
+[ Upstream commit 7dd34d7b7dcf9309fc6224caf4dd5b35bedddcb7 ]
+
+Zac Ecob reported a problem where a bpf program may cause kernel crash due
+to the following error:
+  Oops: divide error: 0000 [#1] PREEMPT SMP KASAN PTI
+
+The failure is due to the below signed divide:
+  LLONG_MIN/-1 where LLONG_MIN equals to -9,223,372,036,854,775,808.
+LLONG_MIN/-1 is supposed to give a positive number 9,223,372,036,854,775,808,
+but it is impossible since for 64-bit system, the maximum positive
+number is 9,223,372,036,854,775,807. On x86_64, LLONG_MIN/-1 will
+cause a kernel exception. On arm64, the result for LLONG_MIN/-1 is
+LLONG_MIN.
+
+Further investigation found all the following sdiv/smod cases may trigger
+an exception when bpf program is running on x86_64 platform:
+  - LLONG_MIN/-1 for 64bit operation
+  - INT_MIN/-1 for 32bit operation
+  - LLONG_MIN%-1 for 64bit operation
+  - INT_MIN%-1 for 32bit operation
+where -1 can be an immediate or in a register.
+
+On arm64, there are no exceptions:
+  - LLONG_MIN/-1 = LLONG_MIN
+  - INT_MIN/-1 = INT_MIN
+  - LLONG_MIN%-1 = 0
+  - INT_MIN%-1 = 0
+where -1 can be an immediate or in a register.
+
+Insn patching is needed to handle the above cases and the patched codes
+produced results aligned with above arm64 result. The below are pseudo
+codes to handle sdiv/smod exceptions including both divisor -1 and divisor 0
+and the divisor is stored in a register.
+
+sdiv:
+      tmp = rX
+      tmp += 1 /* [-1, 0] -> [0, 1]
+      if tmp >(unsigned) 1 goto L2
+      if tmp == 0 goto L1
+      rY = 0
+  L1:
+      rY = -rY;
+      goto L3
+  L2:
+      rY /= rX
+  L3:
+
+smod:
+      tmp = rX
+      tmp += 1 /* [-1, 0] -> [0, 1]
+      if tmp >(unsigned) 1 goto L1
+      if tmp == 1 (is64 ? goto L2 : goto L3)
+      rY = 0;
+      goto L2
+  L1:
+      rY %= rX
+  L2:
+      goto L4  // only when !is64
+  L3:
+      wY = wY  // only when !is64
+  L4:
+
+  [1] https://lore.kernel.org/bpf/tPJLTEh7S_DxFEqAI2Ji5MBSoZVg7_G-Py2iaZpAaWtM961fFTWtsnlzwvTbzBzaUzwQAoNATXKUlt0LZOFgnDcIyKCswAnAGdUF3LBrhGQ=@protonmail.com/
+
+Reported-by: Zac Ecob <zacecob@protonmail.com>
+Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
+Acked-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/r/20240913150326.1187788-1-yonghong.song@linux.dev
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 93 +++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 89 insertions(+), 4 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 400449959802b..d5215cb1747f1 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -19953,13 +19953,46 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
+                       /* Convert BPF_CLASS(insn->code) == BPF_ALU64 to 32-bit ALU */
+                       insn->code = BPF_ALU | BPF_OP(insn->code) | BPF_SRC(insn->code);
+-              /* Make divide-by-zero exceptions impossible. */
++              /* Make sdiv/smod divide-by-minus-one exceptions impossible. */
++              if ((insn->code == (BPF_ALU64 | BPF_MOD | BPF_K) ||
++                   insn->code == (BPF_ALU64 | BPF_DIV | BPF_K) ||
++                   insn->code == (BPF_ALU | BPF_MOD | BPF_K) ||
++                   insn->code == (BPF_ALU | BPF_DIV | BPF_K)) &&
++                  insn->off == 1 && insn->imm == -1) {
++                      bool is64 = BPF_CLASS(insn->code) == BPF_ALU64;
++                      bool isdiv = BPF_OP(insn->code) == BPF_DIV;
++                      struct bpf_insn *patchlet;
++                      struct bpf_insn chk_and_sdiv[] = {
++                              BPF_RAW_INSN((is64 ? BPF_ALU64 : BPF_ALU) |
++                                           BPF_NEG | BPF_K, insn->dst_reg,
++                                           0, 0, 0),
++                      };
++                      struct bpf_insn chk_and_smod[] = {
++                              BPF_MOV32_IMM(insn->dst_reg, 0),
++                      };
++
++                      patchlet = isdiv ? chk_and_sdiv : chk_and_smod;
++                      cnt = isdiv ? ARRAY_SIZE(chk_and_sdiv) : ARRAY_SIZE(chk_and_smod);
++
++                      new_prog = bpf_patch_insn_data(env, i + delta, patchlet, cnt);
++                      if (!new_prog)
++                              return -ENOMEM;
++
++                      delta    += cnt - 1;
++                      env->prog = prog = new_prog;
++                      insn      = new_prog->insnsi + i + delta;
++                      goto next_insn;
++              }
++
++              /* Make divide-by-zero and divide-by-minus-one exceptions impossible. */
+               if (insn->code == (BPF_ALU64 | BPF_MOD | BPF_X) ||
+                   insn->code == (BPF_ALU64 | BPF_DIV | BPF_X) ||
+                   insn->code == (BPF_ALU | BPF_MOD | BPF_X) ||
+                   insn->code == (BPF_ALU | BPF_DIV | BPF_X)) {
+                       bool is64 = BPF_CLASS(insn->code) == BPF_ALU64;
+                       bool isdiv = BPF_OP(insn->code) == BPF_DIV;
++                      bool is_sdiv = isdiv && insn->off == 1;
++                      bool is_smod = !isdiv && insn->off == 1;
+                       struct bpf_insn *patchlet;
+                       struct bpf_insn chk_and_div[] = {
+                               /* [R,W]x div 0 -> 0 */
+@@ -19979,10 +20012,62 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
+                               BPF_JMP_IMM(BPF_JA, 0, 0, 1),
+                               BPF_MOV32_REG(insn->dst_reg, insn->dst_reg),
+                       };
++                      struct bpf_insn chk_and_sdiv[] = {
++                              /* [R,W]x sdiv 0 -> 0
++                               * LLONG_MIN sdiv -1 -> LLONG_MIN
++                               * INT_MIN sdiv -1 -> INT_MIN
++                               */
++                              BPF_MOV64_REG(BPF_REG_AX, insn->src_reg),
++                              BPF_RAW_INSN((is64 ? BPF_ALU64 : BPF_ALU) |
++                                           BPF_ADD | BPF_K, BPF_REG_AX,
++                                           0, 0, 1),
++                              BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
++                                           BPF_JGT | BPF_K, BPF_REG_AX,
++                                           0, 4, 1),
++                              BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
++                                           BPF_JEQ | BPF_K, BPF_REG_AX,
++                                           0, 1, 0),
++                              BPF_RAW_INSN((is64 ? BPF_ALU64 : BPF_ALU) |
++                                           BPF_MOV | BPF_K, insn->dst_reg,
++                                           0, 0, 0),
++                              /* BPF_NEG(LLONG_MIN) == -LLONG_MIN == LLONG_MIN */
++                              BPF_RAW_INSN((is64 ? BPF_ALU64 : BPF_ALU) |
++                                           BPF_NEG | BPF_K, insn->dst_reg,
++                                           0, 0, 0),
++                              BPF_JMP_IMM(BPF_JA, 0, 0, 1),
++                              *insn,
++                      };
++                      struct bpf_insn chk_and_smod[] = {
++                              /* [R,W]x mod 0 -> [R,W]x */
++                              /* [R,W]x mod -1 -> 0 */
++                              BPF_MOV64_REG(BPF_REG_AX, insn->src_reg),
++                              BPF_RAW_INSN((is64 ? BPF_ALU64 : BPF_ALU) |
++                                           BPF_ADD | BPF_K, BPF_REG_AX,
++                                           0, 0, 1),
++                              BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
++                                           BPF_JGT | BPF_K, BPF_REG_AX,
++                                           0, 3, 1),
++                              BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
++                                           BPF_JEQ | BPF_K, BPF_REG_AX,
++                                           0, 3 + (is64 ? 0 : 1), 1),
++                              BPF_MOV32_IMM(insn->dst_reg, 0),
++                              BPF_JMP_IMM(BPF_JA, 0, 0, 1),
++                              *insn,
++                              BPF_JMP_IMM(BPF_JA, 0, 0, 1),
++                              BPF_MOV32_REG(insn->dst_reg, insn->dst_reg),
++                      };
+-                      patchlet = isdiv ? chk_and_div : chk_and_mod;
+-                      cnt = isdiv ? ARRAY_SIZE(chk_and_div) :
+-                                    ARRAY_SIZE(chk_and_mod) - (is64 ? 2 : 0);
++                      if (is_sdiv) {
++                              patchlet = chk_and_sdiv;
++                              cnt = ARRAY_SIZE(chk_and_sdiv);
++                      } else if (is_smod) {
++                              patchlet = chk_and_smod;
++                              cnt = ARRAY_SIZE(chk_and_smod) - (is64 ? 2 : 0);
++                      } else {
++                              patchlet = isdiv ? chk_and_div : chk_and_mod;
++                              cnt = isdiv ? ARRAY_SIZE(chk_and_div) :
++                                            ARRAY_SIZE(chk_and_mod) - (is64 ? 2 : 0);
++                      }
+                       new_prog = bpf_patch_insn_data(env, i + delta, patchlet, cnt);
+                       if (!new_prog)
+-- 
+2.43.0
+
diff --git a/queue-6.11/bpf-make-the-pointer-returned-by-iter-next-method-va.patch b/queue-6.11/bpf-make-the-pointer-returned-by-iter-next-method-va.patch
new file mode 100644 (file)
index 0000000..094adf6
--- /dev/null
@@ -0,0 +1,108 @@
+From 6dc2cc2d36c44e2df88f563f87c8d494caa4dd10 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Aug 2024 21:11:17 +0100
+Subject: bpf: Make the pointer returned by iter next method valid
+
+From: Juntong Deng <juntong.deng@outlook.com>
+
+[ Upstream commit 4cc8c50c9abcb2646a7a4fcef3cea5dcb30c06cf ]
+
+Currently we cannot pass the pointer returned by iter next method as
+argument to KF_TRUSTED_ARGS or KF_RCU kfuncs, because the pointer
+returned by iter next method is not "valid".
+
+This patch sets the pointer returned by iter next method to be valid.
+
+This is based on the fact that if the iterator is implemented correctly,
+then the pointer returned from the iter next method should be valid.
+
+This does not make NULL pointer valid. If the iter next method has
+KF_RET_NULL flag, then the verifier will ask the ebpf program to
+check NULL pointer.
+
+KF_RCU_PROTECTED iterator is a special case, the pointer returned by
+iter next method should only be valid within RCU critical section,
+so it should be with MEM_RCU, not PTR_TRUSTED.
+
+Another special case is bpf_iter_num_next, which returns a pointer with
+base type PTR_TO_MEM. PTR_TO_MEM should not be combined with type flag
+PTR_TRUSTED (PTR_TO_MEM already means the pointer is valid).
+
+The pointer returned by iter next method of other types of iterators
+is with PTR_TRUSTED.
+
+In addition, this patch adds get_iter_from_state to help us get the
+current iterator from the current state.
+
+Signed-off-by: Juntong Deng <juntong.deng@outlook.com>
+Link: https://lore.kernel.org/r/AM6PR03MB584869F8B448EA1C87B7CDA399962@AM6PR03MB5848.eurprd03.prod.outlook.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 8c07efa3905b9..400449959802b 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -8029,6 +8029,15 @@ static int widen_imprecise_scalars(struct bpf_verifier_env *env,
+       return 0;
+ }
++static struct bpf_reg_state *get_iter_from_state(struct bpf_verifier_state *cur_st,
++                                               struct bpf_kfunc_call_arg_meta *meta)
++{
++      int iter_frameno = meta->iter.frameno;
++      int iter_spi = meta->iter.spi;
++
++      return &cur_st->frame[iter_frameno]->stack[iter_spi].spilled_ptr;
++}
++
+ /* process_iter_next_call() is called when verifier gets to iterator's next
+  * "method" (e.g., bpf_iter_num_next() for numbers iterator) call. We'll refer
+  * to it as just "iter_next()" in comments below.
+@@ -8113,12 +8122,10 @@ static int process_iter_next_call(struct bpf_verifier_env *env, int insn_idx,
+       struct bpf_verifier_state *cur_st = env->cur_state, *queued_st, *prev_st;
+       struct bpf_func_state *cur_fr = cur_st->frame[cur_st->curframe], *queued_fr;
+       struct bpf_reg_state *cur_iter, *queued_iter;
+-      int iter_frameno = meta->iter.frameno;
+-      int iter_spi = meta->iter.spi;
+       BTF_TYPE_EMIT(struct bpf_iter);
+-      cur_iter = &env->cur_state->frame[iter_frameno]->stack[iter_spi].spilled_ptr;
++      cur_iter = get_iter_from_state(cur_st, meta);
+       if (cur_iter->iter.state != BPF_ITER_STATE_ACTIVE &&
+           cur_iter->iter.state != BPF_ITER_STATE_DRAINED) {
+@@ -8146,7 +8153,7 @@ static int process_iter_next_call(struct bpf_verifier_env *env, int insn_idx,
+               if (!queued_st)
+                       return -ENOMEM;
+-              queued_iter = &queued_st->frame[iter_frameno]->stack[iter_spi].spilled_ptr;
++              queued_iter = get_iter_from_state(queued_st, meta);
+               queued_iter->iter.state = BPF_ITER_STATE_ACTIVE;
+               queued_iter->iter.depth++;
+               if (prev_st)
+@@ -12692,6 +12699,17 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
+                       regs[BPF_REG_0].btf = desc_btf;
+                       regs[BPF_REG_0].type = PTR_TO_BTF_ID;
+                       regs[BPF_REG_0].btf_id = ptr_type_id;
++
++                      if (is_iter_next_kfunc(&meta)) {
++                              struct bpf_reg_state *cur_iter;
++
++                              cur_iter = get_iter_from_state(env->cur_state, &meta);
++
++                              if (cur_iter->type & MEM_RCU) /* KF_RCU_PROTECTED */
++                                      regs[BPF_REG_0].type |= MEM_RCU;
++                              else
++                                      regs[BPF_REG_0].type |= PTR_TRUSTED;
++                      }
+               }
+               if (is_kfunc_ret_null(&meta)) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/bpftool-fix-undefined-behavior-caused-by-shifting-in.patch b/queue-6.11/bpftool-fix-undefined-behavior-caused-by-shifting-in.patch
new file mode 100644 (file)
index 0000000..b3ed0c3
--- /dev/null
@@ -0,0 +1,55 @@
+From 39ab126b771091c734e8546a1d964e9ce72c26e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Sep 2024 22:00:09 +0800
+Subject: bpftool: Fix undefined behavior caused by shifting into the sign bit
+
+From: Kuan-Wei Chiu <visitorckw@gmail.com>
+
+[ Upstream commit 4cdc0e4ce5e893bc92255f5f734d983012f2bc2e ]
+
+Replace shifts of '1' with '1U' in bitwise operations within
+__show_dev_tc_bpf() to prevent undefined behavior caused by shifting
+into the sign bit of a signed integer. By using '1U', the operations
+are explicitly performed on unsigned integers, avoiding potential
+integer overflow or sign-related issues.
+
+Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Acked-by: Quentin Monnet <qmo@kernel.org>
+Link: https://lore.kernel.org/bpf/20240908140009.3149781-1-visitorckw@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/bpf/bpftool/net.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c
+index 968714b4c3d45..ad2ea6cf2db11 100644
+--- a/tools/bpf/bpftool/net.c
++++ b/tools/bpf/bpftool/net.c
+@@ -482,9 +482,9 @@ static void __show_dev_tc_bpf(const struct ip_devname_ifindex *dev,
+               if (prog_flags[i] || json_output) {
+                       NET_START_ARRAY("prog_flags", "%s ");
+                       for (j = 0; prog_flags[i] && j < 32; j++) {
+-                              if (!(prog_flags[i] & (1 << j)))
++                              if (!(prog_flags[i] & (1U << j)))
+                                       continue;
+-                              NET_DUMP_UINT_ONLY(1 << j);
++                              NET_DUMP_UINT_ONLY(1U << j);
+                       }
+                       NET_END_ARRAY("");
+               }
+@@ -493,9 +493,9 @@ static void __show_dev_tc_bpf(const struct ip_devname_ifindex *dev,
+                       if (link_flags[i] || json_output) {
+                               NET_START_ARRAY("link_flags", "%s ");
+                               for (j = 0; link_flags[i] && j < 32; j++) {
+-                                      if (!(link_flags[i] & (1 << j)))
++                                      if (!(link_flags[i] & (1U << j)))
+                                               continue;
+-                                      NET_DUMP_UINT_ONLY(1 << j);
++                                      NET_DUMP_UINT_ONLY(1U << j);
+                               }
+                               NET_END_ARRAY("");
+                       }
+-- 
+2.43.0
+
diff --git a/queue-6.11/bpftool-fix-undefined-behavior-in-qsort-null-0.patch b/queue-6.11/bpftool-fix-undefined-behavior-in-qsort-null-0.patch
new file mode 100644 (file)
index 0000000..7c5ca1c
--- /dev/null
@@ -0,0 +1,57 @@
+From 25be26f6efc7841955167b8ee51bc4779ff29f44 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Sep 2024 23:02:07 +0800
+Subject: bpftool: Fix undefined behavior in qsort(NULL, 0, ...)
+
+From: Kuan-Wei Chiu <visitorckw@gmail.com>
+
+[ Upstream commit f04e2ad394e2755d0bb2d858ecb5598718bf00d5 ]
+
+When netfilter has no entry to display, qsort is called with
+qsort(NULL, 0, ...). This results in undefined behavior, as UBSan
+reports:
+
+net.c:827:2: runtime error: null pointer passed as argument 1, which is declared to never be null
+
+Although the C standard does not explicitly state whether calling qsort
+with a NULL pointer when the size is 0 constitutes undefined behavior,
+Section 7.1.4 of the C standard (Use of library functions) mentions:
+
+"Each of the following statements applies unless explicitly stated
+otherwise in the detailed descriptions that follow: If an argument to a
+function has an invalid value (such as a value outside the domain of
+the function, or a pointer outside the address space of the program, or
+a null pointer, or a pointer to non-modifiable storage when the
+corresponding parameter is not const-qualified) or a type (after
+promotion) not expected by a function with variable number of
+arguments, the behavior is undefined."
+
+To avoid this, add an early return when nf_link_info is NULL to prevent
+calling qsort with a NULL pointer.
+
+Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Reviewed-by: Quentin Monnet <qmo@kernel.org>
+Link: https://lore.kernel.org/bpf/20240910150207.3179306-1-visitorckw@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/bpf/bpftool/net.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c
+index ad2ea6cf2db11..0f2106218e1f0 100644
+--- a/tools/bpf/bpftool/net.c
++++ b/tools/bpf/bpftool/net.c
+@@ -824,6 +824,9 @@ static void show_link_netfilter(void)
+               nf_link_count++;
+       }
++      if (!nf_link_info)
++              return;
++
+       qsort(nf_link_info, nf_link_count, sizeof(*nf_link_info), netfilter_link_compar);
+       for (id = 0; id < nf_link_count; id++) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/btrfs-don-t-readahead-the-relocation-inode-on-rst.patch b/queue-6.11/btrfs-don-t-readahead-the-relocation-inode-on-rst.patch
new file mode 100644 (file)
index 0000000..557779a
--- /dev/null
@@ -0,0 +1,162 @@
+From ae40ffac9faf5d58a2c171a33acdda5980a5913c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 22:43:06 +0200
+Subject: btrfs: don't readahead the relocation inode on RST
+
+From: Johannes Thumshirn <jthumshirn@wdc.com>
+
+[ Upstream commit 04915240e2c3a018e4c7f23418478d27226c8957 ]
+
+On relocation we're doing readahead on the relocation inode, but if the
+filesystem is backed by a RAID stripe tree we can get ENOENT (e.g. due to
+preallocated extents not being mapped in the RST) from the lookup.
+
+But readahead doesn't handle the error and submits invalid reads to the
+device, causing an assertion in the scatter-gather list code:
+
+  BTRFS info (device nvme1n1): balance: start -d -m -s
+  BTRFS info (device nvme1n1): relocating block group 6480920576 flags data|raid0
+  BTRFS error (device nvme1n1): cannot find raid-stripe for logical [6481928192, 6481969152] devid 2, profile raid0
+  ------------[ cut here ]------------
+  kernel BUG at include/linux/scatterlist.h:115!
+  Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI
+  CPU: 0 PID: 1012 Comm: btrfs Not tainted 6.10.0-rc7+ #567
+  RIP: 0010:__blk_rq_map_sg+0x339/0x4a0
+  RSP: 0018:ffffc90001a43820 EFLAGS: 00010202
+  RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffffea00045d4802
+  RDX: 0000000117520000 RSI: 0000000000000000 RDI: ffff8881027d1000
+  RBP: 0000000000003000 R08: ffffea00045d4902 R09: 0000000000000000
+  R10: 0000000000000000 R11: 0000000000001000 R12: ffff8881003d10b8
+  R13: ffffc90001a438f0 R14: 0000000000000000 R15: 0000000000003000
+  FS:  00007fcc048a6900(0000) GS:ffff88813bc00000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 000000002cd11000 CR3: 00000001109ea001 CR4: 0000000000370eb0
+  Call Trace:
+   <TASK>
+   ? __die_body.cold+0x14/0x25
+   ? die+0x2e/0x50
+   ? do_trap+0xca/0x110
+   ? do_error_trap+0x65/0x80
+   ? __blk_rq_map_sg+0x339/0x4a0
+   ? exc_invalid_op+0x50/0x70
+   ? __blk_rq_map_sg+0x339/0x4a0
+   ? asm_exc_invalid_op+0x1a/0x20
+   ? __blk_rq_map_sg+0x339/0x4a0
+   nvme_prep_rq.part.0+0x9d/0x770
+   nvme_queue_rq+0x7d/0x1e0
+   __blk_mq_issue_directly+0x2a/0x90
+   ? blk_mq_get_budget_and_tag+0x61/0x90
+   blk_mq_try_issue_list_directly+0x56/0xf0
+   blk_mq_flush_plug_list.part.0+0x52b/0x5d0
+   __blk_flush_plug+0xc6/0x110
+   blk_finish_plug+0x28/0x40
+   read_pages+0x160/0x1c0
+   page_cache_ra_unbounded+0x109/0x180
+   relocate_file_extent_cluster+0x611/0x6a0
+   ? btrfs_search_slot+0xba4/0xd20
+   ? balance_dirty_pages_ratelimited_flags+0x26/0xb00
+   relocate_data_extent.constprop.0+0x134/0x160
+   relocate_block_group+0x3f2/0x500
+   btrfs_relocate_block_group+0x250/0x430
+   btrfs_relocate_chunk+0x3f/0x130
+   btrfs_balance+0x71b/0xef0
+   ? kmalloc_trace_noprof+0x13b/0x280
+   btrfs_ioctl+0x2c2e/0x3030
+   ? kvfree_call_rcu+0x1e6/0x340
+   ? list_lru_add_obj+0x66/0x80
+   ? mntput_no_expire+0x3a/0x220
+   __x64_sys_ioctl+0x96/0xc0
+   do_syscall_64+0x54/0x110
+   entry_SYSCALL_64_after_hwframe+0x76/0x7e
+  RIP: 0033:0x7fcc04514f9b
+  Code: Unable to access opcode bytes at 0x7fcc04514f71.
+  RSP: 002b:00007ffeba923370 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
+  RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fcc04514f9b
+  RDX: 00007ffeba923460 RSI: 00000000c4009420 RDI: 0000000000000003
+  RBP: 0000000000000000 R08: 0000000000000013 R09: 0000000000000001
+  R10: 00007fcc043fbba8 R11: 0000000000000246 R12: 00007ffeba924fc5
+  R13: 00007ffeba923460 R14: 0000000000000002 R15: 00000000004d4bb0
+   </TASK>
+  Modules linked in:
+  ---[ end trace 0000000000000000 ]---
+  RIP: 0010:__blk_rq_map_sg+0x339/0x4a0
+  RSP: 0018:ffffc90001a43820 EFLAGS: 00010202
+  RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffffea00045d4802
+  RDX: 0000000117520000 RSI: 0000000000000000 RDI: ffff8881027d1000
+  RBP: 0000000000003000 R08: ffffea00045d4902 R09: 0000000000000000
+  R10: 0000000000000000 R11: 0000000000001000 R12: ffff8881003d10b8
+  R13: ffffc90001a438f0 R14: 0000000000000000 R15: 0000000000003000
+  FS:  00007fcc048a6900(0000) GS:ffff88813bc00000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 00007fcc04514f71 CR3: 00000001109ea001 CR4: 0000000000370eb0
+  Kernel panic - not syncing: Fatal exception
+  Kernel Offset: disabled
+  ---[ end Kernel panic - not syncing: Fatal exception ]---
+
+So in case of a relocation on a RAID stripe-tree based file system, skip
+the readahead.
+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/relocation.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
+index 0533d0f82dc99..ea4ed85919ec8 100644
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -36,6 +36,7 @@
+ #include "relocation.h"
+ #include "super.h"
+ #include "tree-checker.h"
++#include "raid-stripe-tree.h"
+ /*
+  * Relocation overview
+@@ -2965,21 +2966,34 @@ static int relocate_one_folio(struct reloc_control *rc,
+       u64 folio_end;
+       u64 cur;
+       int ret;
++      const bool use_rst = btrfs_need_stripe_tree_update(fs_info, rc->block_group->flags);
+       ASSERT(index <= last_index);
+       folio = filemap_lock_folio(inode->i_mapping, index);
+       if (IS_ERR(folio)) {
+-              page_cache_sync_readahead(inode->i_mapping, ra, NULL,
+-                                        index, last_index + 1 - index);
++
++              /*
++               * On relocation we're doing readahead on the relocation inode,
++               * but if the filesystem is backed by a RAID stripe tree we can
++               * get ENOENT (e.g. due to preallocated extents not being
++               * mapped in the RST) from the lookup.
++               *
++               * But readahead doesn't handle the error and submits invalid
++               * reads to the device, causing a assertion failures.
++               */
++              if (!use_rst)
++                      page_cache_sync_readahead(inode->i_mapping, ra, NULL,
++                                                index, last_index + 1 - index);
+               folio = __filemap_get_folio(inode->i_mapping, index,
+-                                          FGP_LOCK | FGP_ACCESSED | FGP_CREAT, mask);
++                                          FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
++                                          mask);
+               if (IS_ERR(folio))
+                       return PTR_ERR(folio);
+       }
+       WARN_ON(folio_order(folio));
+-      if (folio_test_readahead(folio))
++      if (folio_test_readahead(folio) && !use_rst)
+               page_cache_async_readahead(inode->i_mapping, ra, NULL,
+                                          folio, last_index + 1 - index);
+-- 
+2.43.0
+
diff --git a/queue-6.11/can-netlink-avoid-call-to-do_set_data_bittiming-call.patch b/queue-6.11/can-netlink-avoid-call-to-do_set_data_bittiming-call.patch
new file mode 100644 (file)
index 0000000..109e97c
--- /dev/null
@@ -0,0 +1,173 @@
+From b6f7e95f480d289ee7570106517e3f59506a87ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Aug 2024 18:42:24 +0200
+Subject: can: netlink: avoid call to do_set_data_bittiming callback with stale
+ can_priv::ctrlmode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Stefan Mätje <stefan.maetje@esd.eu>
+
+[ Upstream commit 2423cc20087ae9a7b7af575aa62304ef67cad7b6 ]
+
+This patch moves the evaluation of data[IFLA_CAN_CTRLMODE] in function
+can_changelink in front of the evaluation of data[IFLA_CAN_BITTIMING].
+
+This avoids a call to do_set_data_bittiming providing a stale
+can_priv::ctrlmode with a CAN_CTRLMODE_FD flag not matching the
+requested state when switching between a CAN Classic and CAN-FD bitrate.
+
+In the same manner the evaluation of data[IFLA_CAN_CTRLMODE] in function
+can_validate is also moved in front of the evaluation of
+data[IFLA_CAN_BITTIMING].
+
+This is a preparation for patches where the nominal and data bittiming
+may have interdependencies on the driver side depending on the
+CAN_CTRLMODE_FD flag state.
+
+Signed-off-by: Stefan Mätje <stefan.maetje@esd.eu>
+Link: https://patch.msgid.link/20240808164224.213522-1-stefan.maetje@esd.eu
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/dev/netlink.c | 102 +++++++++++++++++-----------------
+ 1 file changed, 51 insertions(+), 51 deletions(-)
+
+diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
+index dfdc039d92a6c..01aacdcda2606 100644
+--- a/drivers/net/can/dev/netlink.c
++++ b/drivers/net/can/dev/netlink.c
+@@ -65,15 +65,6 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
+       if (!data)
+               return 0;
+-      if (data[IFLA_CAN_BITTIMING]) {
+-              struct can_bittiming bt;
+-
+-              memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
+-              err = can_validate_bittiming(&bt, extack);
+-              if (err)
+-                      return err;
+-      }
+-
+       if (data[IFLA_CAN_CTRLMODE]) {
+               struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+               u32 tdc_flags = cm->flags & CAN_CTRLMODE_TDC_MASK;
+@@ -114,6 +105,15 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
+               }
+       }
++      if (data[IFLA_CAN_BITTIMING]) {
++              struct can_bittiming bt;
++
++              memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
++              err = can_validate_bittiming(&bt, extack);
++              if (err)
++                      return err;
++      }
++
+       if (is_can_fd) {
+               if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
+                       return -EOPNOTSUPP;
+@@ -195,48 +195,6 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
+       /* We need synchronization with dev->stop() */
+       ASSERT_RTNL();
+-      if (data[IFLA_CAN_BITTIMING]) {
+-              struct can_bittiming bt;
+-
+-              /* Do not allow changing bittiming while running */
+-              if (dev->flags & IFF_UP)
+-                      return -EBUSY;
+-
+-              /* Calculate bittiming parameters based on
+-               * bittiming_const if set, otherwise pass bitrate
+-               * directly via do_set_bitrate(). Bail out if neither
+-               * is given.
+-               */
+-              if (!priv->bittiming_const && !priv->do_set_bittiming &&
+-                  !priv->bitrate_const)
+-                      return -EOPNOTSUPP;
+-
+-              memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
+-              err = can_get_bittiming(dev, &bt,
+-                                      priv->bittiming_const,
+-                                      priv->bitrate_const,
+-                                      priv->bitrate_const_cnt,
+-                                      extack);
+-              if (err)
+-                      return err;
+-
+-              if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) {
+-                      NL_SET_ERR_MSG_FMT(extack,
+-                                         "arbitration bitrate %u bps surpasses transceiver capabilities of %u bps",
+-                                         bt.bitrate, priv->bitrate_max);
+-                      return -EINVAL;
+-              }
+-
+-              memcpy(&priv->bittiming, &bt, sizeof(bt));
+-
+-              if (priv->do_set_bittiming) {
+-                      /* Finally, set the bit-timing registers */
+-                      err = priv->do_set_bittiming(dev);
+-                      if (err)
+-                              return err;
+-              }
+-      }
+-
+       if (data[IFLA_CAN_CTRLMODE]) {
+               struct can_ctrlmode *cm;
+               u32 ctrlstatic;
+@@ -284,6 +242,48 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
+                       priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_TDC_MASK;
+       }
++      if (data[IFLA_CAN_BITTIMING]) {
++              struct can_bittiming bt;
++
++              /* Do not allow changing bittiming while running */
++              if (dev->flags & IFF_UP)
++                      return -EBUSY;
++
++              /* Calculate bittiming parameters based on
++               * bittiming_const if set, otherwise pass bitrate
++               * directly via do_set_bitrate(). Bail out if neither
++               * is given.
++               */
++              if (!priv->bittiming_const && !priv->do_set_bittiming &&
++                  !priv->bitrate_const)
++                      return -EOPNOTSUPP;
++
++              memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
++              err = can_get_bittiming(dev, &bt,
++                                      priv->bittiming_const,
++                                      priv->bitrate_const,
++                                      priv->bitrate_const_cnt,
++                                      extack);
++              if (err)
++                      return err;
++
++              if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) {
++                      NL_SET_ERR_MSG_FMT(extack,
++                                         "arbitration bitrate %u bps surpasses transceiver capabilities of %u bps",
++                                         bt.bitrate, priv->bitrate_max);
++                      return -EINVAL;
++              }
++
++              memcpy(&priv->bittiming, &bt, sizeof(bt));
++
++              if (priv->do_set_bittiming) {
++                      /* Finally, set the bit-timing registers */
++                      err = priv->do_set_bittiming(dev);
++                      if (err)
++                              return err;
++              }
++      }
++
+       if (data[IFLA_CAN_RESTART_MS]) {
+               /* Do not allow changing restart delay while running */
+               if (dev->flags & IFF_UP)
+-- 
+2.43.0
+
diff --git a/queue-6.11/cgroup-disallow-mounting-v1-hierarchies-without-cont.patch b/queue-6.11/cgroup-disallow-mounting-v1-hierarchies-without-cont.patch
new file mode 100644 (file)
index 0000000..3b08566
--- /dev/null
@@ -0,0 +1,71 @@
+From 0ae1b0ba766f12523373938534ae6ee0c4ccc065 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Sep 2024 18:32:22 +0200
+Subject: cgroup: Disallow mounting v1 hierarchies without controller
+ implementation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michal Koutný <mkoutny@suse.com>
+
+[ Upstream commit 3c41382e920f1dd5c9f432948fe799c07af1cced ]
+
+The configs that disable some v1 controllers would still allow mounting
+them but with no controller-specific files. (Making such hierarchies
+equivalent to named v1 hierarchies.) To achieve behavior consistent with
+actual out-compilation of a whole controller, the mounts should treat
+respective controllers as non-existent.
+
+Wrap implementation into a helper function, leverage legacy_files to
+detect compiled out controllers. The effect is that mounts on v1 would
+fail and produce a message like:
+  [ 1543.999081] cgroup: Unknown subsys name 'memory'
+
+Signed-off-by: Michal Koutný <mkoutny@suse.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/cgroup/cgroup-v1.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
+index b9dbf6bf2779d..784337694a4be 100644
+--- a/kernel/cgroup/cgroup-v1.c
++++ b/kernel/cgroup/cgroup-v1.c
+@@ -46,6 +46,12 @@ bool cgroup1_ssid_disabled(int ssid)
+       return cgroup_no_v1_mask & (1 << ssid);
+ }
++static bool cgroup1_subsys_absent(struct cgroup_subsys *ss)
++{
++      /* Check also dfl_cftypes for file-less controllers, i.e. perf_event */
++      return ss->legacy_cftypes == NULL && ss->dfl_cftypes;
++}
++
+ /**
+  * cgroup_attach_task_all - attach task 'tsk' to all cgroups of task 'from'
+  * @from: attach to all cgroups of a given task
+@@ -932,7 +938,8 @@ int cgroup1_parse_param(struct fs_context *fc, struct fs_parameter *param)
+               if (ret != -ENOPARAM)
+                       return ret;
+               for_each_subsys(ss, i) {
+-                      if (strcmp(param->key, ss->legacy_name))
++                      if (strcmp(param->key, ss->legacy_name) ||
++                          cgroup1_subsys_absent(ss))
+                               continue;
+                       if (!cgroup_ssid_enabled(i) || cgroup1_ssid_disabled(i))
+                               return invalfc(fc, "Disabled controller '%s'",
+@@ -1024,7 +1031,8 @@ static int check_cgroupfs_options(struct fs_context *fc)
+       mask = ~((u16)1 << cpuset_cgrp_id);
+ #endif
+       for_each_subsys(ss, i)
+-              if (cgroup_ssid_enabled(i) && !cgroup1_ssid_disabled(i))
++              if (cgroup_ssid_enabled(i) && !cgroup1_ssid_disabled(i) &&
++                  !cgroup1_subsys_absent(ss))
+                       enabled |= 1 << i;
+       ctx->subsys_mask &= enabled;
+-- 
+2.43.0
+
diff --git a/queue-6.11/coredump-standartize-and-fix-logging.patch b/queue-6.11/coredump-standartize-and-fix-logging.patch
new file mode 100644 (file)
index 0000000..04e5ada
--- /dev/null
@@ -0,0 +1,178 @@
+From 2edeead034757dcfefb3c3b99a8310120ba86a47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jul 2024 11:27:24 -0700
+Subject: coredump: Standartize and fix logging
+
+From: Roman Kisel <romank@linux.microsoft.com>
+
+[ Upstream commit c114e9948c2b6a0b400266e59cc656b59e795bca ]
+
+The coredump code does not log the process ID and the comm
+consistently, logs unescaped comm when it does log it, and
+does not always use the ratelimited logging. That makes it
+harder to analyze logs and puts the system at the risk of
+spamming the system log incase something crashes many times
+over and over again.
+
+Fix that by logging TGID and comm (escaped) consistently and
+using the ratelimited logging always.
+
+Signed-off-by: Roman Kisel <romank@linux.microsoft.com>
+Tested-by: Allen Pais <apais@linux.microsoft.com>
+Link: https://lore.kernel.org/r/20240718182743.1959160-2-romank@linux.microsoft.com
+Signed-off-by: Kees Cook <kees@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/coredump.c            | 43 +++++++++++++++-------------------------
+ include/linux/coredump.h | 22 ++++++++++++++++++++
+ 2 files changed, 38 insertions(+), 27 deletions(-)
+
+diff --git a/fs/coredump.c b/fs/coredump.c
+index 7f12ff6ad1d3e..87ff71a59fbe7 100644
+--- a/fs/coredump.c
++++ b/fs/coredump.c
+@@ -586,8 +586,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
+               struct subprocess_info *sub_info;
+               if (ispipe < 0) {
+-                      printk(KERN_WARNING "format_corename failed\n");
+-                      printk(KERN_WARNING "Aborting core\n");
++                      coredump_report_failure("format_corename failed, aborting core");
+                       goto fail_unlock;
+               }
+@@ -607,27 +606,21 @@ void do_coredump(const kernel_siginfo_t *siginfo)
+                        * right pid if a thread in a multi-threaded
+                        * core_pattern process dies.
+                        */
+-                      printk(KERN_WARNING
+-                              "Process %d(%s) has RLIMIT_CORE set to 1\n",
+-                              task_tgid_vnr(current), current->comm);
+-                      printk(KERN_WARNING "Aborting core\n");
++                      coredump_report_failure("RLIMIT_CORE is set to 1, aborting core");
+                       goto fail_unlock;
+               }
+               cprm.limit = RLIM_INFINITY;
+               dump_count = atomic_inc_return(&core_dump_count);
+               if (core_pipe_limit && (core_pipe_limit < dump_count)) {
+-                      printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n",
+-                             task_tgid_vnr(current), current->comm);
+-                      printk(KERN_WARNING "Skipping core dump\n");
++                      coredump_report_failure("over core_pipe_limit, skipping core dump");
+                       goto fail_dropcount;
+               }
+               helper_argv = kmalloc_array(argc + 1, sizeof(*helper_argv),
+                                           GFP_KERNEL);
+               if (!helper_argv) {
+-                      printk(KERN_WARNING "%s failed to allocate memory\n",
+-                             __func__);
++                      coredump_report_failure("%s failed to allocate memory", __func__);
+                       goto fail_dropcount;
+               }
+               for (argi = 0; argi < argc; argi++)
+@@ -644,8 +637,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
+               kfree(helper_argv);
+               if (retval) {
+-                      printk(KERN_INFO "Core dump to |%s pipe failed\n",
+-                             cn.corename);
++                      coredump_report_failure("|%s pipe failed", cn.corename);
+                       goto close_fail;
+               }
+       } else {
+@@ -658,10 +650,8 @@ void do_coredump(const kernel_siginfo_t *siginfo)
+                       goto fail_unlock;
+               if (need_suid_safe && cn.corename[0] != '/') {
+-                      printk(KERN_WARNING "Pid %d(%s) can only dump core "\
+-                              "to fully qualified path!\n",
+-                              task_tgid_vnr(current), current->comm);
+-                      printk(KERN_WARNING "Skipping core dump\n");
++                      coredump_report_failure(
++                              "this process can only dump core to a fully qualified path, skipping core dump");
+                       goto fail_unlock;
+               }
+@@ -730,13 +720,13 @@ void do_coredump(const kernel_siginfo_t *siginfo)
+               idmap = file_mnt_idmap(cprm.file);
+               if (!vfsuid_eq_kuid(i_uid_into_vfsuid(idmap, inode),
+                                   current_fsuid())) {
+-                      pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n",
+-                                          cn.corename);
++                      coredump_report_failure("Core dump to %s aborted: "
++                              "cannot preserve file owner", cn.corename);
+                       goto close_fail;
+               }
+               if ((inode->i_mode & 0677) != 0600) {
+-                      pr_info_ratelimited("Core dump to %s aborted: cannot preserve file permissions\n",
+-                                          cn.corename);
++                      coredump_report_failure("Core dump to %s aborted: "
++                              "cannot preserve file permissions", cn.corename);
+                       goto close_fail;
+               }
+               if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
+@@ -757,7 +747,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
+                * have this set to NULL.
+                */
+               if (!cprm.file) {
+-                      pr_info("Core dump to |%s disabled\n", cn.corename);
++                      coredump_report_failure("Core dump to |%s disabled", cn.corename);
+                       goto close_fail;
+               }
+               if (!dump_vma_snapshot(&cprm))
+@@ -983,11 +973,10 @@ void validate_coredump_safety(void)
+ {
+       if (suid_dumpable == SUID_DUMP_ROOT &&
+           core_pattern[0] != '/' && core_pattern[0] != '|') {
+-              pr_warn(
+-"Unsafe core_pattern used with fs.suid_dumpable=2.\n"
+-"Pipe handler or fully qualified core dump path required.\n"
+-"Set kernel.core_pattern before fs.suid_dumpable.\n"
+-              );
++
++              coredump_report_failure("Unsafe core_pattern used with fs.suid_dumpable=2: "
++                      "pipe handler or fully qualified core dump path required. "
++                      "Set kernel.core_pattern before fs.suid_dumpable.");
+       }
+ }
+diff --git a/include/linux/coredump.h b/include/linux/coredump.h
+index 0904ba010341a..45e598fe34766 100644
+--- a/include/linux/coredump.h
++++ b/include/linux/coredump.h
+@@ -43,8 +43,30 @@ extern int dump_align(struct coredump_params *cprm, int align);
+ int dump_user_range(struct coredump_params *cprm, unsigned long start,
+                   unsigned long len);
+ extern void do_coredump(const kernel_siginfo_t *siginfo);
++
++/*
++ * Logging for the coredump code, ratelimited.
++ * The TGID and comm fields are added to the message.
++ */
++
++#define __COREDUMP_PRINTK(Level, Format, ...) \
++      do {    \
++              char comm[TASK_COMM_LEN];       \
++      \
++              get_task_comm(comm, current);   \
++              printk_ratelimited(Level "coredump: %d(%*pE): " Format "\n",    \
++                      task_tgid_vnr(current), (int)strlen(comm), comm, ##__VA_ARGS__);        \
++      } while (0)     \
++
++#define coredump_report(fmt, ...) __COREDUMP_PRINTK(KERN_INFO, fmt, ##__VA_ARGS__)
++#define coredump_report_failure(fmt, ...) __COREDUMP_PRINTK(KERN_WARNING, fmt, ##__VA_ARGS__)
++
+ #else
+ static inline void do_coredump(const kernel_siginfo_t *siginfo) {}
++
++#define coredump_report(...)
++#define coredump_report_failure(...)
++
+ #endif
+ #if defined(CONFIG_COREDUMP) && defined(CONFIG_SYSCTL)
+-- 
+2.43.0
+
diff --git a/queue-6.11/cpufreq-amd-pstate-add-check-for-cpufreq_cpu_get-s-r.patch b/queue-6.11/cpufreq-amd-pstate-add-check-for-cpufreq_cpu_get-s-r.patch
new file mode 100644 (file)
index 0000000..68a169e
--- /dev/null
@@ -0,0 +1,61 @@
+From a5aef7e74d9144cf76e0648bb95729cdd743eaca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Aug 2024 16:38:41 +0300
+Subject: cpufreq: amd-pstate: add check for cpufreq_cpu_get's return value
+
+From: Anastasia Belova <abelova@astralinux.ru>
+
+[ Upstream commit 5493f9714e4cdaf0ee7cec15899a231400cb1a9f ]
+
+cpufreq_cpu_get may return NULL. To avoid NULL-dereference check it
+and return in case of error.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Signed-off-by: Anastasia Belova <abelova@astralinux.ru>
+Reviewed-by: Perry Yuan <perry.yuan@amd.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/amd-pstate.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
+index 073ca9caf52ac..589fde37ccd7a 100644
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -659,7 +659,12 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
+       unsigned long max_perf, min_perf, des_perf,
+                     cap_perf, lowest_nonlinear_perf;
+       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+-      struct amd_cpudata *cpudata = policy->driver_data;
++      struct amd_cpudata *cpudata;
++
++      if (!policy)
++              return;
++
++      cpudata = policy->driver_data;
+       if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)
+               amd_pstate_update_min_max_limit(policy);
+@@ -873,11 +878,16 @@ static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata)
+ static void amd_pstate_update_limits(unsigned int cpu)
+ {
+       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+-      struct amd_cpudata *cpudata = policy->driver_data;
++      struct amd_cpudata *cpudata;
+       u32 prev_high = 0, cur_high = 0;
+       int ret;
+       bool highest_perf_changed = false;
++      if (!policy)
++              return;
++
++      cpudata = policy->driver_data;
++
+       mutex_lock(&amd_pstate_driver_lock);
+       if ((!amd_pstate_prefcore) || (!cpudata->hw_prefcore))
+               goto free_cpufreq_put;
+-- 
+2.43.0
+
diff --git a/queue-6.11/cpufreq-loongson3-use-raw_smp_processor_id-in-do_ser.patch b/queue-6.11/cpufreq-loongson3-use-raw_smp_processor_id-in-do_ser.patch
new file mode 100644 (file)
index 0000000..2519c75
--- /dev/null
@@ -0,0 +1,42 @@
+From 3644681f29c0dc9331eca176bb94055acb253e0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Aug 2024 14:24:59 +0800
+Subject: cpufreq: loongson3: Use raw_smp_processor_id() in
+ do_service_request()
+
+From: Huacai Chen <chenhuacai@loongson.cn>
+
+[ Upstream commit 2b7ec33e534f7a10033a5cf07794acf48b182bbe ]
+
+Use raw_smp_processor_id() instead of plain smp_processor_id() in
+do_service_request(), otherwise we may get some errors with the driver
+enabled:
+
+ BUG: using smp_processor_id() in preemptible [00000000] code: (udev-worker)/208
+ caller is loongson3_cpufreq_probe+0x5c/0x250 [loongson3_cpufreq]
+
+Reported-by: Xi Ruoyao <xry111@xry111.site>
+Tested-by: Binbin Zhou <zhoubinbin@loongson.cn>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/loongson3_cpufreq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/cpufreq/loongson3_cpufreq.c b/drivers/cpufreq/loongson3_cpufreq.c
+index 5f79b6de127c9..6b5e6798d9a28 100644
+--- a/drivers/cpufreq/loongson3_cpufreq.c
++++ b/drivers/cpufreq/loongson3_cpufreq.c
+@@ -176,7 +176,7 @@ static DEFINE_PER_CPU(struct loongson3_freq_data *, freq_data);
+ static inline int do_service_request(u32 id, u32 info, u32 cmd, u32 val, u32 extra)
+ {
+       int retries;
+-      unsigned int cpu = smp_processor_id();
++      unsigned int cpu = raw_smp_processor_id();
+       unsigned int package = cpu_data[cpu].package;
+       union smc_message msg, last;
+-- 
+2.43.0
+
diff --git a/queue-6.11/crypto-hisilicon-fix-missed-error-branch.patch b/queue-6.11/crypto-hisilicon-fix-missed-error-branch.patch
new file mode 100644 (file)
index 0000000..43b378e
--- /dev/null
@@ -0,0 +1,69 @@
+From 029453071e55dfd9085d4ec8f32ee22af729bce5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 31 Aug 2024 17:50:07 +0800
+Subject: crypto: hisilicon - fix missed error branch
+
+From: Yang Shen <shenyang39@huawei.com>
+
+[ Upstream commit f386dc64e1a5d3dcb84579119ec350ab026fea88 ]
+
+If an error occurs in the process after the SGL is mapped
+successfully, it need to unmap the SGL.
+
+Otherwise, memory problems may occur.
+
+Signed-off-by: Yang Shen <shenyang39@huawei.com>
+Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/hisilicon/sgl.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/crypto/hisilicon/sgl.c b/drivers/crypto/hisilicon/sgl.c
+index 568acd0aee3fa..c974f95cd126f 100644
+--- a/drivers/crypto/hisilicon/sgl.c
++++ b/drivers/crypto/hisilicon/sgl.c
+@@ -225,7 +225,7 @@ hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev,
+       dma_addr_t curr_sgl_dma = 0;
+       struct acc_hw_sge *curr_hw_sge;
+       struct scatterlist *sg;
+-      int sg_n;
++      int sg_n, ret;
+       if (!dev || !sgl || !pool || !hw_sgl_dma || index >= pool->count)
+               return ERR_PTR(-EINVAL);
+@@ -240,14 +240,15 @@ hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev,
+       if (sg_n_mapped > pool->sge_nr) {
+               dev_err(dev, "the number of entries in input scatterlist is bigger than SGL pool setting.\n");
+-              return ERR_PTR(-EINVAL);
++              ret = -EINVAL;
++              goto err_unmap;
+       }
+       curr_hw_sgl = acc_get_sgl(pool, index, &curr_sgl_dma);
+       if (IS_ERR(curr_hw_sgl)) {
+               dev_err(dev, "Get SGL error!\n");
+-              dma_unmap_sg(dev, sgl, sg_n, DMA_BIDIRECTIONAL);
+-              return ERR_PTR(-ENOMEM);
++              ret = -ENOMEM;
++              goto err_unmap;
+       }
+       curr_hw_sgl->entry_length_in_sgl = cpu_to_le16(pool->sge_nr);
+       curr_hw_sge = curr_hw_sgl->sge_entries;
+@@ -262,6 +263,11 @@ hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev,
+       *hw_sgl_dma = curr_sgl_dma;
+       return curr_hw_sgl;
++
++err_unmap:
++      dma_unmap_sg(dev, sgl, sg_n, DMA_BIDIRECTIONAL);
++
++      return ERR_PTR(ret);
+ }
+ EXPORT_SYMBOL_GPL(hisi_acc_sg_buf_map_to_hw_sgl);
+-- 
+2.43.0
+
diff --git a/queue-6.11/crypto-octeontx-fix-authenc-setkey.patch b/queue-6.11/crypto-octeontx-fix-authenc-setkey.patch
new file mode 100644 (file)
index 0000000..97b48c8
--- /dev/null
@@ -0,0 +1,408 @@
+From 7ec9ec7627214da78d42f77d9a67dab8f58e0510 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 17 Aug 2024 12:13:23 +0800
+Subject: crypto: octeontx - Fix authenc setkey
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+[ Upstream commit 311eea7e37c4c0b44b557d0c100860a03b4eab65 ]
+
+Use the generic crypto_authenc_extractkeys helper instead of custom
+parsing code that is slightly broken.  Also fix a number of memory
+leaks by moving memory allocation from setkey to init_tfm (setkey
+can be called multiple times over the life of a tfm).
+
+Finally accept all hash key lengths by running the digest over
+extra-long keys.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../crypto/marvell/octeontx/otx_cptvf_algs.c  | 261 +++++++-----------
+ 1 file changed, 93 insertions(+), 168 deletions(-)
+
+diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c b/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c
+index 3c5d577d8f0d5..0a1b85ad0057f 100644
+--- a/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c
++++ b/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c
+@@ -17,7 +17,6 @@
+ #include <crypto/sha2.h>
+ #include <crypto/xts.h>
+ #include <crypto/scatterwalk.h>
+-#include <linux/rtnetlink.h>
+ #include <linux/sort.h>
+ #include <linux/module.h>
+ #include "otx_cptvf.h"
+@@ -66,6 +65,8 @@ static struct cpt_device_table ae_devices = {
+       .count = ATOMIC_INIT(0)
+ };
++static struct otx_cpt_sdesc *alloc_sdesc(struct crypto_shash *alg);
++
+ static inline int get_se_device(struct pci_dev **pdev, int *cpu_num)
+ {
+       int count, ret = 0;
+@@ -509,44 +510,61 @@ static int cpt_aead_init(struct crypto_aead *tfm, u8 cipher_type, u8 mac_type)
+       ctx->cipher_type = cipher_type;
+       ctx->mac_type = mac_type;
++      switch (ctx->mac_type) {
++      case OTX_CPT_SHA1:
++              ctx->hashalg = crypto_alloc_shash("sha1", 0, 0);
++              break;
++
++      case OTX_CPT_SHA256:
++              ctx->hashalg = crypto_alloc_shash("sha256", 0, 0);
++              break;
++
++      case OTX_CPT_SHA384:
++              ctx->hashalg = crypto_alloc_shash("sha384", 0, 0);
++              break;
++
++      case OTX_CPT_SHA512:
++              ctx->hashalg = crypto_alloc_shash("sha512", 0, 0);
++              break;
++      }
++
++      if (IS_ERR(ctx->hashalg))
++              return PTR_ERR(ctx->hashalg);
++
++      crypto_aead_set_reqsize_dma(tfm, sizeof(struct otx_cpt_req_ctx));
++
++      if (!ctx->hashalg)
++              return 0;
++
+       /*
+        * When selected cipher is NULL we use HMAC opcode instead of
+        * FLEXICRYPTO opcode therefore we don't need to use HASH algorithms
+        * for calculating ipad and opad
+        */
+       if (ctx->cipher_type != OTX_CPT_CIPHER_NULL) {
+-              switch (ctx->mac_type) {
+-              case OTX_CPT_SHA1:
+-                      ctx->hashalg = crypto_alloc_shash("sha1", 0,
+-                                                        CRYPTO_ALG_ASYNC);
+-                      if (IS_ERR(ctx->hashalg))
+-                              return PTR_ERR(ctx->hashalg);
+-                      break;
+-
+-              case OTX_CPT_SHA256:
+-                      ctx->hashalg = crypto_alloc_shash("sha256", 0,
+-                                                        CRYPTO_ALG_ASYNC);
+-                      if (IS_ERR(ctx->hashalg))
+-                              return PTR_ERR(ctx->hashalg);
+-                      break;
++              int ss = crypto_shash_statesize(ctx->hashalg);
+-              case OTX_CPT_SHA384:
+-                      ctx->hashalg = crypto_alloc_shash("sha384", 0,
+-                                                        CRYPTO_ALG_ASYNC);
+-                      if (IS_ERR(ctx->hashalg))
+-                              return PTR_ERR(ctx->hashalg);
+-                      break;
++              ctx->ipad = kzalloc(ss, GFP_KERNEL);
++              if (!ctx->ipad) {
++                      crypto_free_shash(ctx->hashalg);
++                      return -ENOMEM;
++              }
+-              case OTX_CPT_SHA512:
+-                      ctx->hashalg = crypto_alloc_shash("sha512", 0,
+-                                                        CRYPTO_ALG_ASYNC);
+-                      if (IS_ERR(ctx->hashalg))
+-                              return PTR_ERR(ctx->hashalg);
+-                      break;
++              ctx->opad = kzalloc(ss, GFP_KERNEL);
++              if (!ctx->opad) {
++                      kfree(ctx->ipad);
++                      crypto_free_shash(ctx->hashalg);
++                      return -ENOMEM;
+               }
+       }
+-      crypto_aead_set_reqsize_dma(tfm, sizeof(struct otx_cpt_req_ctx));
++      ctx->sdesc = alloc_sdesc(ctx->hashalg);
++      if (!ctx->sdesc) {
++              kfree(ctx->opad);
++              kfree(ctx->ipad);
++              crypto_free_shash(ctx->hashalg);
++              return -ENOMEM;
++      }
+       return 0;
+ }
+@@ -602,8 +620,7 @@ static void otx_cpt_aead_exit(struct crypto_aead *tfm)
+       kfree(ctx->ipad);
+       kfree(ctx->opad);
+-      if (ctx->hashalg)
+-              crypto_free_shash(ctx->hashalg);
++      crypto_free_shash(ctx->hashalg);
+       kfree(ctx->sdesc);
+ }
+@@ -699,7 +716,7 @@ static inline void swap_data64(void *buf, u32 len)
+               *dst = cpu_to_be64p(src);
+ }
+-static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
++static int swap_pad(u8 mac_type, u8 *pad)
+ {
+       struct sha512_state *sha512;
+       struct sha256_state *sha256;
+@@ -707,22 +724,19 @@ static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
+       switch (mac_type) {
+       case OTX_CPT_SHA1:
+-              sha1 = (struct sha1_state *) in_pad;
++              sha1 = (struct sha1_state *)pad;
+               swap_data32(sha1->state, SHA1_DIGEST_SIZE);
+-              memcpy(out_pad, &sha1->state, SHA1_DIGEST_SIZE);
+               break;
+       case OTX_CPT_SHA256:
+-              sha256 = (struct sha256_state *) in_pad;
++              sha256 = (struct sha256_state *)pad;
+               swap_data32(sha256->state, SHA256_DIGEST_SIZE);
+-              memcpy(out_pad, &sha256->state, SHA256_DIGEST_SIZE);
+               break;
+       case OTX_CPT_SHA384:
+       case OTX_CPT_SHA512:
+-              sha512 = (struct sha512_state *) in_pad;
++              sha512 = (struct sha512_state *)pad;
+               swap_data64(sha512->state, SHA512_DIGEST_SIZE);
+-              memcpy(out_pad, &sha512->state, SHA512_DIGEST_SIZE);
+               break;
+       default:
+@@ -732,55 +746,53 @@ static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
+       return 0;
+ }
+-static int aead_hmac_init(struct crypto_aead *cipher)
++static int aead_hmac_init(struct crypto_aead *cipher,
++                        struct crypto_authenc_keys *keys)
+ {
+       struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
+-      int state_size = crypto_shash_statesize(ctx->hashalg);
+       int ds = crypto_shash_digestsize(ctx->hashalg);
+       int bs = crypto_shash_blocksize(ctx->hashalg);
+-      int authkeylen = ctx->auth_key_len;
++      int authkeylen = keys->authkeylen;
+       u8 *ipad = NULL, *opad = NULL;
+-      int ret = 0, icount = 0;
++      int icount = 0;
++      int ret;
+-      ctx->sdesc = alloc_sdesc(ctx->hashalg);
+-      if (!ctx->sdesc)
+-              return -ENOMEM;
++      if (authkeylen > bs) {
++              ret = crypto_shash_digest(&ctx->sdesc->shash, keys->authkey,
++                                        authkeylen, ctx->key);
++              if (ret)
++                      return ret;
++              authkeylen = ds;
++      } else
++              memcpy(ctx->key, keys->authkey, authkeylen);
+-      ctx->ipad = kzalloc(bs, GFP_KERNEL);
+-      if (!ctx->ipad) {
+-              ret = -ENOMEM;
+-              goto calc_fail;
+-      }
++      ctx->enc_key_len = keys->enckeylen;
++      ctx->auth_key_len = authkeylen;
+-      ctx->opad = kzalloc(bs, GFP_KERNEL);
+-      if (!ctx->opad) {
+-              ret = -ENOMEM;
+-              goto calc_fail;
+-      }
++      if (ctx->cipher_type == OTX_CPT_CIPHER_NULL)
++              return keys->enckeylen ? -EINVAL : 0;
+-      ipad = kzalloc(state_size, GFP_KERNEL);
+-      if (!ipad) {
+-              ret = -ENOMEM;
+-              goto calc_fail;
++      switch (keys->enckeylen) {
++      case AES_KEYSIZE_128:
++              ctx->key_type = OTX_CPT_AES_128_BIT;
++              break;
++      case AES_KEYSIZE_192:
++              ctx->key_type = OTX_CPT_AES_192_BIT;
++              break;
++      case AES_KEYSIZE_256:
++              ctx->key_type = OTX_CPT_AES_256_BIT;
++              break;
++      default:
++              /* Invalid key length */
++              return -EINVAL;
+       }
+-      opad = kzalloc(state_size, GFP_KERNEL);
+-      if (!opad) {
+-              ret = -ENOMEM;
+-              goto calc_fail;
+-      }
++      memcpy(ctx->key + authkeylen, keys->enckey, keys->enckeylen);
+-      if (authkeylen > bs) {
+-              ret = crypto_shash_digest(&ctx->sdesc->shash, ctx->key,
+-                                        authkeylen, ipad);
+-              if (ret)
+-                      goto calc_fail;
+-
+-              authkeylen = ds;
+-      } else {
+-              memcpy(ipad, ctx->key, authkeylen);
+-      }
++      ipad = ctx->ipad;
++      opad = ctx->opad;
++      memcpy(ipad, ctx->key, authkeylen);
+       memset(ipad + authkeylen, 0, bs - authkeylen);
+       memcpy(opad, ipad, bs);
+@@ -798,7 +810,7 @@ static int aead_hmac_init(struct crypto_aead *cipher)
+       crypto_shash_init(&ctx->sdesc->shash);
+       crypto_shash_update(&ctx->sdesc->shash, ipad, bs);
+       crypto_shash_export(&ctx->sdesc->shash, ipad);
+-      ret = copy_pad(ctx->mac_type, ctx->ipad, ipad);
++      ret = swap_pad(ctx->mac_type, ipad);
+       if (ret)
+               goto calc_fail;
+@@ -806,25 +818,9 @@ static int aead_hmac_init(struct crypto_aead *cipher)
+       crypto_shash_init(&ctx->sdesc->shash);
+       crypto_shash_update(&ctx->sdesc->shash, opad, bs);
+       crypto_shash_export(&ctx->sdesc->shash, opad);
+-      ret = copy_pad(ctx->mac_type, ctx->opad, opad);
+-      if (ret)
+-              goto calc_fail;
+-
+-      kfree(ipad);
+-      kfree(opad);
+-
+-      return 0;
++      ret = swap_pad(ctx->mac_type, opad);
+ calc_fail:
+-      kfree(ctx->ipad);
+-      ctx->ipad = NULL;
+-      kfree(ctx->opad);
+-      ctx->opad = NULL;
+-      kfree(ipad);
+-      kfree(opad);
+-      kfree(ctx->sdesc);
+-      ctx->sdesc = NULL;
+-
+       return ret;
+ }
+@@ -832,57 +828,15 @@ static int otx_cpt_aead_cbc_aes_sha_setkey(struct crypto_aead *cipher,
+                                          const unsigned char *key,
+                                          unsigned int keylen)
+ {
+-      struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
+-      struct crypto_authenc_key_param *param;
+-      int enckeylen = 0, authkeylen = 0;
+-      struct rtattr *rta = (void *)key;
+-      int status = -EINVAL;
+-
+-      if (!RTA_OK(rta, keylen))
+-              goto badkey;
+-
+-      if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+-              goto badkey;
+-
+-      if (RTA_PAYLOAD(rta) < sizeof(*param))
+-              goto badkey;
+-
+-      param = RTA_DATA(rta);
+-      enckeylen = be32_to_cpu(param->enckeylen);
+-      key += RTA_ALIGN(rta->rta_len);
+-      keylen -= RTA_ALIGN(rta->rta_len);
+-      if (keylen < enckeylen)
+-              goto badkey;
++      struct crypto_authenc_keys authenc_keys;
++      int status;
+-      if (keylen > OTX_CPT_MAX_KEY_SIZE)
+-              goto badkey;
+-
+-      authkeylen = keylen - enckeylen;
+-      memcpy(ctx->key, key, keylen);
+-
+-      switch (enckeylen) {
+-      case AES_KEYSIZE_128:
+-              ctx->key_type = OTX_CPT_AES_128_BIT;
+-              break;
+-      case AES_KEYSIZE_192:
+-              ctx->key_type = OTX_CPT_AES_192_BIT;
+-              break;
+-      case AES_KEYSIZE_256:
+-              ctx->key_type = OTX_CPT_AES_256_BIT;
+-              break;
+-      default:
+-              /* Invalid key length */
+-              goto badkey;
+-      }
+-
+-      ctx->enc_key_len = enckeylen;
+-      ctx->auth_key_len = authkeylen;
+-
+-      status = aead_hmac_init(cipher);
++      status = crypto_authenc_extractkeys(&authenc_keys, key, keylen);
+       if (status)
+               goto badkey;
+-      return 0;
++      status = aead_hmac_init(cipher, &authenc_keys);
++
+ badkey:
+       return status;
+ }
+@@ -891,36 +845,7 @@ static int otx_cpt_aead_ecb_null_sha_setkey(struct crypto_aead *cipher,
+                                           const unsigned char *key,
+                                           unsigned int keylen)
+ {
+-      struct otx_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
+-      struct crypto_authenc_key_param *param;
+-      struct rtattr *rta = (void *)key;
+-      int enckeylen = 0;
+-
+-      if (!RTA_OK(rta, keylen))
+-              goto badkey;
+-
+-      if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+-              goto badkey;
+-
+-      if (RTA_PAYLOAD(rta) < sizeof(*param))
+-              goto badkey;
+-
+-      param = RTA_DATA(rta);
+-      enckeylen = be32_to_cpu(param->enckeylen);
+-      key += RTA_ALIGN(rta->rta_len);
+-      keylen -= RTA_ALIGN(rta->rta_len);
+-      if (enckeylen != 0)
+-              goto badkey;
+-
+-      if (keylen > OTX_CPT_MAX_KEY_SIZE)
+-              goto badkey;
+-
+-      memcpy(ctx->key, key, keylen);
+-      ctx->enc_key_len = enckeylen;
+-      ctx->auth_key_len = keylen;
+-      return 0;
+-badkey:
+-      return -EINVAL;
++      return otx_cpt_aead_cbc_aes_sha_setkey(cipher, key, keylen);
+ }
+ static int otx_cpt_aead_gcm_aes_setkey(struct crypto_aead *cipher,
+-- 
+2.43.0
+
diff --git a/queue-6.11/crypto-octeontx2-fix-authenc-setkey.patch b/queue-6.11/crypto-octeontx2-fix-authenc-setkey.patch
new file mode 100644 (file)
index 0000000..58c6136
--- /dev/null
@@ -0,0 +1,394 @@
+From 5de02438c58a8d3cf3f3ee9f3af2c4b8a8b3b788 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 17 Aug 2024 12:36:19 +0800
+Subject: crypto: octeontx2 - Fix authenc setkey
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+[ Upstream commit 7ccb750dcac8abbfc7743aab0db6a72c1c3703c7 ]
+
+Use the generic crypto_authenc_extractkeys helper instead of custom
+parsing code that is slightly broken.  Also fix a number of memory
+leaks by moving memory allocation from setkey to init_tfm (setkey
+can be called multiple times over the life of a tfm).
+
+Finally accept all hash key lengths by running the digest over
+extra-long keys.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../marvell/octeontx2/otx2_cptvf_algs.c       | 254 +++++++-----------
+ 1 file changed, 90 insertions(+), 164 deletions(-)
+
+diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c
+index 1604fc58dc13e..5aa56f20f888c 100644
+--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c
++++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c
+@@ -11,7 +11,6 @@
+ #include <crypto/xts.h>
+ #include <crypto/gcm.h>
+ #include <crypto/scatterwalk.h>
+-#include <linux/rtnetlink.h>
+ #include <linux/sort.h>
+ #include <linux/module.h>
+ #include "otx2_cptvf.h"
+@@ -55,6 +54,8 @@ static struct cpt_device_table se_devices = {
+       .count = ATOMIC_INIT(0)
+ };
++static struct otx2_cpt_sdesc *alloc_sdesc(struct crypto_shash *alg);
++
+ static inline int get_se_device(struct pci_dev **pdev, int *cpu_num)
+ {
+       int count;
+@@ -598,40 +599,56 @@ static int cpt_aead_init(struct crypto_aead *atfm, u8 cipher_type, u8 mac_type)
+       ctx->cipher_type = cipher_type;
+       ctx->mac_type = mac_type;
++      switch (ctx->mac_type) {
++      case OTX2_CPT_SHA1:
++              ctx->hashalg = crypto_alloc_shash("sha1", 0, 0);
++              break;
++
++      case OTX2_CPT_SHA256:
++              ctx->hashalg = crypto_alloc_shash("sha256", 0, 0);
++              break;
++
++      case OTX2_CPT_SHA384:
++              ctx->hashalg = crypto_alloc_shash("sha384", 0, 0);
++              break;
++
++      case OTX2_CPT_SHA512:
++              ctx->hashalg = crypto_alloc_shash("sha512", 0, 0);
++              break;
++      }
++
++      if (IS_ERR(ctx->hashalg))
++              return PTR_ERR(ctx->hashalg);
++
++      if (ctx->hashalg) {
++              ctx->sdesc = alloc_sdesc(ctx->hashalg);
++              if (!ctx->sdesc) {
++                      crypto_free_shash(ctx->hashalg);
++                      return -ENOMEM;
++              }
++      }
++
+       /*
+        * When selected cipher is NULL we use HMAC opcode instead of
+        * FLEXICRYPTO opcode therefore we don't need to use HASH algorithms
+        * for calculating ipad and opad
+        */
+-      if (ctx->cipher_type != OTX2_CPT_CIPHER_NULL) {
+-              switch (ctx->mac_type) {
+-              case OTX2_CPT_SHA1:
+-                      ctx->hashalg = crypto_alloc_shash("sha1", 0,
+-                                                        CRYPTO_ALG_ASYNC);
+-                      if (IS_ERR(ctx->hashalg))
+-                              return PTR_ERR(ctx->hashalg);
+-                      break;
+-
+-              case OTX2_CPT_SHA256:
+-                      ctx->hashalg = crypto_alloc_shash("sha256", 0,
+-                                                        CRYPTO_ALG_ASYNC);
+-                      if (IS_ERR(ctx->hashalg))
+-                              return PTR_ERR(ctx->hashalg);
+-                      break;
++      if (ctx->cipher_type != OTX2_CPT_CIPHER_NULL && ctx->hashalg) {
++              int ss = crypto_shash_statesize(ctx->hashalg);
+-              case OTX2_CPT_SHA384:
+-                      ctx->hashalg = crypto_alloc_shash("sha384", 0,
+-                                                        CRYPTO_ALG_ASYNC);
+-                      if (IS_ERR(ctx->hashalg))
+-                              return PTR_ERR(ctx->hashalg);
+-                      break;
++              ctx->ipad = kzalloc(ss, GFP_KERNEL);
++              if (!ctx->ipad) {
++                      kfree(ctx->sdesc);
++                      crypto_free_shash(ctx->hashalg);
++                      return -ENOMEM;
++              }
+-              case OTX2_CPT_SHA512:
+-                      ctx->hashalg = crypto_alloc_shash("sha512", 0,
+-                                                        CRYPTO_ALG_ASYNC);
+-                      if (IS_ERR(ctx->hashalg))
+-                              return PTR_ERR(ctx->hashalg);
+-                      break;
++              ctx->opad = kzalloc(ss, GFP_KERNEL);
++              if (!ctx->opad) {
++                      kfree(ctx->ipad);
++                      kfree(ctx->sdesc);
++                      crypto_free_shash(ctx->hashalg);
++                      return -ENOMEM;
+               }
+       }
+       switch (ctx->cipher_type) {
+@@ -713,8 +730,7 @@ static void otx2_cpt_aead_exit(struct crypto_aead *tfm)
+       kfree(ctx->ipad);
+       kfree(ctx->opad);
+-      if (ctx->hashalg)
+-              crypto_free_shash(ctx->hashalg);
++      crypto_free_shash(ctx->hashalg);
+       kfree(ctx->sdesc);
+       if (ctx->fbk_cipher) {
+@@ -788,7 +804,7 @@ static inline void swap_data64(void *buf, u32 len)
+               cpu_to_be64s(src);
+ }
+-static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
++static int swap_pad(u8 mac_type, u8 *pad)
+ {
+       struct sha512_state *sha512;
+       struct sha256_state *sha256;
+@@ -796,22 +812,19 @@ static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
+       switch (mac_type) {
+       case OTX2_CPT_SHA1:
+-              sha1 = (struct sha1_state *) in_pad;
++              sha1 = (struct sha1_state *)pad;
+               swap_data32(sha1->state, SHA1_DIGEST_SIZE);
+-              memcpy(out_pad, &sha1->state, SHA1_DIGEST_SIZE);
+               break;
+       case OTX2_CPT_SHA256:
+-              sha256 = (struct sha256_state *) in_pad;
++              sha256 = (struct sha256_state *)pad;
+               swap_data32(sha256->state, SHA256_DIGEST_SIZE);
+-              memcpy(out_pad, &sha256->state, SHA256_DIGEST_SIZE);
+               break;
+       case OTX2_CPT_SHA384:
+       case OTX2_CPT_SHA512:
+-              sha512 = (struct sha512_state *) in_pad;
++              sha512 = (struct sha512_state *)pad;
+               swap_data64(sha512->state, SHA512_DIGEST_SIZE);
+-              memcpy(out_pad, &sha512->state, SHA512_DIGEST_SIZE);
+               break;
+       default:
+@@ -821,55 +834,54 @@ static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
+       return 0;
+ }
+-static int aead_hmac_init(struct crypto_aead *cipher)
++static int aead_hmac_init(struct crypto_aead *cipher,
++                        struct crypto_authenc_keys *keys)
+ {
+       struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
+-      int state_size = crypto_shash_statesize(ctx->hashalg);
+       int ds = crypto_shash_digestsize(ctx->hashalg);
+       int bs = crypto_shash_blocksize(ctx->hashalg);
+-      int authkeylen = ctx->auth_key_len;
++      int authkeylen = keys->authkeylen;
+       u8 *ipad = NULL, *opad = NULL;
+-      int ret = 0, icount = 0;
++      int icount = 0;
++      int ret;
+-      ctx->sdesc = alloc_sdesc(ctx->hashalg);
+-      if (!ctx->sdesc)
+-              return -ENOMEM;
++      if (authkeylen > bs) {
++              ret = crypto_shash_digest(&ctx->sdesc->shash, keys->authkey,
++                                        authkeylen, ctx->key);
++              if (ret)
++                      goto calc_fail;
+-      ctx->ipad = kzalloc(bs, GFP_KERNEL);
+-      if (!ctx->ipad) {
+-              ret = -ENOMEM;
+-              goto calc_fail;
+-      }
++              authkeylen = ds;
++      } else
++              memcpy(ctx->key, keys->authkey, authkeylen);
+-      ctx->opad = kzalloc(bs, GFP_KERNEL);
+-      if (!ctx->opad) {
+-              ret = -ENOMEM;
+-              goto calc_fail;
+-      }
++      ctx->enc_key_len = keys->enckeylen;
++      ctx->auth_key_len = authkeylen;
+-      ipad = kzalloc(state_size, GFP_KERNEL);
+-      if (!ipad) {
+-              ret = -ENOMEM;
+-              goto calc_fail;
+-      }
++      if (ctx->cipher_type == OTX2_CPT_CIPHER_NULL)
++              return keys->enckeylen ? -EINVAL : 0;
+-      opad = kzalloc(state_size, GFP_KERNEL);
+-      if (!opad) {
+-              ret = -ENOMEM;
+-              goto calc_fail;
++      switch (keys->enckeylen) {
++      case AES_KEYSIZE_128:
++              ctx->key_type = OTX2_CPT_AES_128_BIT;
++              break;
++      case AES_KEYSIZE_192:
++              ctx->key_type = OTX2_CPT_AES_192_BIT;
++              break;
++      case AES_KEYSIZE_256:
++              ctx->key_type = OTX2_CPT_AES_256_BIT;
++              break;
++      default:
++              /* Invalid key length */
++              return -EINVAL;
+       }
+-      if (authkeylen > bs) {
+-              ret = crypto_shash_digest(&ctx->sdesc->shash, ctx->key,
+-                                        authkeylen, ipad);
+-              if (ret)
+-                      goto calc_fail;
++      memcpy(ctx->key + authkeylen, keys->enckey, keys->enckeylen);
+-              authkeylen = ds;
+-      } else {
+-              memcpy(ipad, ctx->key, authkeylen);
+-      }
++      ipad = ctx->ipad;
++      opad = ctx->opad;
++      memcpy(ipad, ctx->key, authkeylen);
+       memset(ipad + authkeylen, 0, bs - authkeylen);
+       memcpy(opad, ipad, bs);
+@@ -887,7 +899,7 @@ static int aead_hmac_init(struct crypto_aead *cipher)
+       crypto_shash_init(&ctx->sdesc->shash);
+       crypto_shash_update(&ctx->sdesc->shash, ipad, bs);
+       crypto_shash_export(&ctx->sdesc->shash, ipad);
+-      ret = copy_pad(ctx->mac_type, ctx->ipad, ipad);
++      ret = swap_pad(ctx->mac_type, ipad);
+       if (ret)
+               goto calc_fail;
+@@ -895,25 +907,9 @@ static int aead_hmac_init(struct crypto_aead *cipher)
+       crypto_shash_init(&ctx->sdesc->shash);
+       crypto_shash_update(&ctx->sdesc->shash, opad, bs);
+       crypto_shash_export(&ctx->sdesc->shash, opad);
+-      ret = copy_pad(ctx->mac_type, ctx->opad, opad);
+-      if (ret)
+-              goto calc_fail;
+-
+-      kfree(ipad);
+-      kfree(opad);
+-
+-      return 0;
++      ret = swap_pad(ctx->mac_type, opad);
+ calc_fail:
+-      kfree(ctx->ipad);
+-      ctx->ipad = NULL;
+-      kfree(ctx->opad);
+-      ctx->opad = NULL;
+-      kfree(ipad);
+-      kfree(opad);
+-      kfree(ctx->sdesc);
+-      ctx->sdesc = NULL;
+-
+       return ret;
+ }
+@@ -921,87 +917,17 @@ static int otx2_cpt_aead_cbc_aes_sha_setkey(struct crypto_aead *cipher,
+                                           const unsigned char *key,
+                                           unsigned int keylen)
+ {
+-      struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
+-      struct crypto_authenc_key_param *param;
+-      int enckeylen = 0, authkeylen = 0;
+-      struct rtattr *rta = (void *)key;
+-
+-      if (!RTA_OK(rta, keylen))
+-              return -EINVAL;
++      struct crypto_authenc_keys authenc_keys;
+-      if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+-              return -EINVAL;
+-
+-      if (RTA_PAYLOAD(rta) < sizeof(*param))
+-              return -EINVAL;
+-
+-      param = RTA_DATA(rta);
+-      enckeylen = be32_to_cpu(param->enckeylen);
+-      key += RTA_ALIGN(rta->rta_len);
+-      keylen -= RTA_ALIGN(rta->rta_len);
+-      if (keylen < enckeylen)
+-              return -EINVAL;
+-
+-      if (keylen > OTX2_CPT_MAX_KEY_SIZE)
+-              return -EINVAL;
+-
+-      authkeylen = keylen - enckeylen;
+-      memcpy(ctx->key, key, keylen);
+-
+-      switch (enckeylen) {
+-      case AES_KEYSIZE_128:
+-              ctx->key_type = OTX2_CPT_AES_128_BIT;
+-              break;
+-      case AES_KEYSIZE_192:
+-              ctx->key_type = OTX2_CPT_AES_192_BIT;
+-              break;
+-      case AES_KEYSIZE_256:
+-              ctx->key_type = OTX2_CPT_AES_256_BIT;
+-              break;
+-      default:
+-              /* Invalid key length */
+-              return -EINVAL;
+-      }
+-
+-      ctx->enc_key_len = enckeylen;
+-      ctx->auth_key_len = authkeylen;
+-
+-      return aead_hmac_init(cipher);
++      return crypto_authenc_extractkeys(&authenc_keys, key, keylen) ?:
++             aead_hmac_init(cipher, &authenc_keys);
+ }
+ static int otx2_cpt_aead_ecb_null_sha_setkey(struct crypto_aead *cipher,
+                                            const unsigned char *key,
+                                            unsigned int keylen)
+ {
+-      struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
+-      struct crypto_authenc_key_param *param;
+-      struct rtattr *rta = (void *)key;
+-      int enckeylen = 0;
+-
+-      if (!RTA_OK(rta, keylen))
+-              return -EINVAL;
+-
+-      if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+-              return -EINVAL;
+-
+-      if (RTA_PAYLOAD(rta) < sizeof(*param))
+-              return -EINVAL;
+-
+-      param = RTA_DATA(rta);
+-      enckeylen = be32_to_cpu(param->enckeylen);
+-      key += RTA_ALIGN(rta->rta_len);
+-      keylen -= RTA_ALIGN(rta->rta_len);
+-      if (enckeylen != 0)
+-              return -EINVAL;
+-
+-      if (keylen > OTX2_CPT_MAX_KEY_SIZE)
+-              return -EINVAL;
+-
+-      memcpy(ctx->key, key, keylen);
+-      ctx->enc_key_len = enckeylen;
+-      ctx->auth_key_len = keylen;
+-
+-      return 0;
++      return otx2_cpt_aead_cbc_aes_sha_setkey(cipher, key, keylen);
+ }
+ static int otx2_cpt_aead_gcm_aes_setkey(struct crypto_aead *cipher,
+-- 
+2.43.0
+
diff --git a/queue-6.11/crypto-simd-do-not-call-crypto_alloc_tfm-during-regi.patch b/queue-6.11/crypto-simd-do-not-call-crypto_alloc_tfm-during-regi.patch
new file mode 100644 (file)
index 0000000..ac5aba3
--- /dev/null
@@ -0,0 +1,249 @@
+From c69a25613a94634ea8a98c14a07b75e17161957d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 17 Aug 2024 14:58:35 +0800
+Subject: crypto: simd - Do not call crypto_alloc_tfm during registration
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+[ Upstream commit 3c44d31cb34ce4eb8311a2e73634d57702948230 ]
+
+Algorithm registration is usually carried out during module init,
+where as little work as possible should be carried out.  The SIMD
+code violated this rule by allocating a tfm, this then triggers a
+full test of the algorithm which may dead-lock in certain cases.
+
+SIMD is only allocating the tfm to get at the alg object, which is
+in fact already available as it is what we are registering.  Use
+that directly and remove the crypto_alloc_tfm call.
+
+Also remove some obsolete and unused SIMD API.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/crypto/aes-ce-glue.c     |  2 +-
+ arch/arm/crypto/aes-neonbs-glue.c |  2 +-
+ crypto/simd.c                     | 76 ++++++-------------------------
+ include/crypto/internal/simd.h    | 12 +----
+ 4 files changed, 19 insertions(+), 73 deletions(-)
+
+diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c
+index b668c97663ec0..f5b66f4cf45d9 100644
+--- a/arch/arm/crypto/aes-ce-glue.c
++++ b/arch/arm/crypto/aes-ce-glue.c
+@@ -711,7 +711,7 @@ static int __init aes_init(void)
+               algname = aes_algs[i].base.cra_name + 2;
+               drvname = aes_algs[i].base.cra_driver_name + 2;
+               basename = aes_algs[i].base.cra_driver_name;
+-              simd = simd_skcipher_create_compat(algname, drvname, basename);
++              simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
+               err = PTR_ERR(simd);
+               if (IS_ERR(simd))
+                       goto unregister_simds;
+diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c
+index 201eb35dde37e..735a2441ad484 100644
+--- a/arch/arm/crypto/aes-neonbs-glue.c
++++ b/arch/arm/crypto/aes-neonbs-glue.c
+@@ -540,7 +540,7 @@ static int __init aes_init(void)
+               algname = aes_algs[i].base.cra_name + 2;
+               drvname = aes_algs[i].base.cra_driver_name + 2;
+               basename = aes_algs[i].base.cra_driver_name;
+-              simd = simd_skcipher_create_compat(algname, drvname, basename);
++              simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
+               err = PTR_ERR(simd);
+               if (IS_ERR(simd))
+                       goto unregister_simds;
+diff --git a/crypto/simd.c b/crypto/simd.c
+index 2aa4f72e224fd..b07721d1f3f6e 100644
+--- a/crypto/simd.c
++++ b/crypto/simd.c
+@@ -136,27 +136,19 @@ static int simd_skcipher_init(struct crypto_skcipher *tfm)
+       return 0;
+ }
+-struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
++struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg,
++                                                    const char *algname,
+                                                     const char *drvname,
+                                                     const char *basename)
+ {
+       struct simd_skcipher_alg *salg;
+-      struct crypto_skcipher *tfm;
+-      struct skcipher_alg *ialg;
+       struct skcipher_alg *alg;
+       int err;
+-      tfm = crypto_alloc_skcipher(basename, CRYPTO_ALG_INTERNAL,
+-                                  CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
+-      if (IS_ERR(tfm))
+-              return ERR_CAST(tfm);
+-
+-      ialg = crypto_skcipher_alg(tfm);
+-
+       salg = kzalloc(sizeof(*salg), GFP_KERNEL);
+       if (!salg) {
+               salg = ERR_PTR(-ENOMEM);
+-              goto out_put_tfm;
++              goto out;
+       }
+       salg->ialg_name = basename;
+@@ -195,30 +187,16 @@ struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
+       if (err)
+               goto out_free_salg;
+-out_put_tfm:
+-      crypto_free_skcipher(tfm);
++out:
+       return salg;
+ out_free_salg:
+       kfree(salg);
+       salg = ERR_PTR(err);
+-      goto out_put_tfm;
++      goto out;
+ }
+ EXPORT_SYMBOL_GPL(simd_skcipher_create_compat);
+-struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
+-                                             const char *basename)
+-{
+-      char drvname[CRYPTO_MAX_ALG_NAME];
+-
+-      if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
+-          CRYPTO_MAX_ALG_NAME)
+-              return ERR_PTR(-ENAMETOOLONG);
+-
+-      return simd_skcipher_create_compat(algname, drvname, basename);
+-}
+-EXPORT_SYMBOL_GPL(simd_skcipher_create);
+-
+ void simd_skcipher_free(struct simd_skcipher_alg *salg)
+ {
+       crypto_unregister_skcipher(&salg->alg);
+@@ -246,7 +224,7 @@ int simd_register_skciphers_compat(struct skcipher_alg *algs, int count,
+               algname = algs[i].base.cra_name + 2;
+               drvname = algs[i].base.cra_driver_name + 2;
+               basename = algs[i].base.cra_driver_name;
+-              simd = simd_skcipher_create_compat(algname, drvname, basename);
++              simd = simd_skcipher_create_compat(algs + i, algname, drvname, basename);
+               err = PTR_ERR(simd);
+               if (IS_ERR(simd))
+                       goto err_unregister;
+@@ -383,27 +361,19 @@ static int simd_aead_init(struct crypto_aead *tfm)
+       return 0;
+ }
+-struct simd_aead_alg *simd_aead_create_compat(const char *algname,
+-                                            const char *drvname,
+-                                            const char *basename)
++static struct simd_aead_alg *simd_aead_create_compat(struct aead_alg *ialg,
++                                                   const char *algname,
++                                                   const char *drvname,
++                                                   const char *basename)
+ {
+       struct simd_aead_alg *salg;
+-      struct crypto_aead *tfm;
+-      struct aead_alg *ialg;
+       struct aead_alg *alg;
+       int err;
+-      tfm = crypto_alloc_aead(basename, CRYPTO_ALG_INTERNAL,
+-                              CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
+-      if (IS_ERR(tfm))
+-              return ERR_CAST(tfm);
+-
+-      ialg = crypto_aead_alg(tfm);
+-
+       salg = kzalloc(sizeof(*salg), GFP_KERNEL);
+       if (!salg) {
+               salg = ERR_PTR(-ENOMEM);
+-              goto out_put_tfm;
++              goto out;
+       }
+       salg->ialg_name = basename;
+@@ -442,36 +412,20 @@ struct simd_aead_alg *simd_aead_create_compat(const char *algname,
+       if (err)
+               goto out_free_salg;
+-out_put_tfm:
+-      crypto_free_aead(tfm);
++out:
+       return salg;
+ out_free_salg:
+       kfree(salg);
+       salg = ERR_PTR(err);
+-      goto out_put_tfm;
+-}
+-EXPORT_SYMBOL_GPL(simd_aead_create_compat);
+-
+-struct simd_aead_alg *simd_aead_create(const char *algname,
+-                                     const char *basename)
+-{
+-      char drvname[CRYPTO_MAX_ALG_NAME];
+-
+-      if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
+-          CRYPTO_MAX_ALG_NAME)
+-              return ERR_PTR(-ENAMETOOLONG);
+-
+-      return simd_aead_create_compat(algname, drvname, basename);
++      goto out;
+ }
+-EXPORT_SYMBOL_GPL(simd_aead_create);
+-void simd_aead_free(struct simd_aead_alg *salg)
++static void simd_aead_free(struct simd_aead_alg *salg)
+ {
+       crypto_unregister_aead(&salg->alg);
+       kfree(salg);
+ }
+-EXPORT_SYMBOL_GPL(simd_aead_free);
+ int simd_register_aeads_compat(struct aead_alg *algs, int count,
+                              struct simd_aead_alg **simd_algs)
+@@ -493,7 +447,7 @@ int simd_register_aeads_compat(struct aead_alg *algs, int count,
+               algname = algs[i].base.cra_name + 2;
+               drvname = algs[i].base.cra_driver_name + 2;
+               basename = algs[i].base.cra_driver_name;
+-              simd = simd_aead_create_compat(algname, drvname, basename);
++              simd = simd_aead_create_compat(algs + i, algname, drvname, basename);
+               err = PTR_ERR(simd);
+               if (IS_ERR(simd))
+                       goto err_unregister;
+diff --git a/include/crypto/internal/simd.h b/include/crypto/internal/simd.h
+index d2316242a9884..be97b97a75dd2 100644
+--- a/include/crypto/internal/simd.h
++++ b/include/crypto/internal/simd.h
+@@ -14,11 +14,10 @@
+ struct simd_skcipher_alg;
+ struct skcipher_alg;
+-struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
++struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg,
++                                                    const char *algname,
+                                                     const char *drvname,
+                                                     const char *basename);
+-struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
+-                                             const char *basename);
+ void simd_skcipher_free(struct simd_skcipher_alg *alg);
+ int simd_register_skciphers_compat(struct skcipher_alg *algs, int count,
+@@ -32,13 +31,6 @@ void simd_unregister_skciphers(struct skcipher_alg *algs, int count,
+ struct simd_aead_alg;
+ struct aead_alg;
+-struct simd_aead_alg *simd_aead_create_compat(const char *algname,
+-                                            const char *drvname,
+-                                            const char *basename);
+-struct simd_aead_alg *simd_aead_create(const char *algname,
+-                                     const char *basename);
+-void simd_aead_free(struct simd_aead_alg *alg);
+-
+ int simd_register_aeads_compat(struct aead_alg *algs, int count,
+                              struct simd_aead_alg **simd_algs);
+-- 
+2.43.0
+
diff --git a/queue-6.11/crypto-x86-sha256-add-parentheses-around-macros-sing.patch b/queue-6.11/crypto-x86-sha256-add-parentheses-around-macros-sing.patch
new file mode 100644 (file)
index 0000000..244cc9a
--- /dev/null
@@ -0,0 +1,92 @@
+From 5a5eca88c86811d2c7441f2dc0ba251ae0219a7c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Aug 2024 21:48:02 -0700
+Subject: crypto: x86/sha256 - Add parentheses around macros' single arguments
+
+From: Fangrui Song <maskray@google.com>
+
+[ Upstream commit 3363c460ef726ba693704dbcd73b7e7214ccc788 ]
+
+The macros FOUR_ROUNDS_AND_SCHED and DO_4ROUNDS rely on an
+unexpected/undocumented behavior of the GNU assembler, which might
+change in the future
+(https://sourceware.org/bugzilla/show_bug.cgi?id=32073).
+
+    M (1) (2) // 1 arg !? Future: 2 args
+    M 1 + 2   // 1 arg !? Future: 3 args
+
+    M 1 2     // 2 args
+
+Add parentheses around the single arguments to support future GNU
+assembler and LLVM integrated assembler (when the IsOperator hack from
+the following link is dropped).
+
+Link: https://github.com/llvm/llvm-project/commit/055006475e22014b28a070db1bff41ca15f322f0
+Signed-off-by: Fangrui Song <maskray@google.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/crypto/sha256-avx2-asm.S | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/arch/x86/crypto/sha256-avx2-asm.S b/arch/x86/crypto/sha256-avx2-asm.S
+index 0ffb072be9561..0bbec1c75cd0b 100644
+--- a/arch/x86/crypto/sha256-avx2-asm.S
++++ b/arch/x86/crypto/sha256-avx2-asm.S
+@@ -592,22 +592,22 @@ SYM_TYPED_FUNC_START(sha256_transform_rorx)
+       leaq    K256+0*32(%rip), INP            ## reuse INP as scratch reg
+       vpaddd  (INP, SRND), X0, XFER
+       vmovdqa XFER, 0*32+_XFER(%rsp, SRND)
+-      FOUR_ROUNDS_AND_SCHED   _XFER + 0*32
++      FOUR_ROUNDS_AND_SCHED   (_XFER + 0*32)
+       leaq    K256+1*32(%rip), INP
+       vpaddd  (INP, SRND), X0, XFER
+       vmovdqa XFER, 1*32+_XFER(%rsp, SRND)
+-      FOUR_ROUNDS_AND_SCHED   _XFER + 1*32
++      FOUR_ROUNDS_AND_SCHED   (_XFER + 1*32)
+       leaq    K256+2*32(%rip), INP
+       vpaddd  (INP, SRND), X0, XFER
+       vmovdqa XFER, 2*32+_XFER(%rsp, SRND)
+-      FOUR_ROUNDS_AND_SCHED   _XFER + 2*32
++      FOUR_ROUNDS_AND_SCHED   (_XFER + 2*32)
+       leaq    K256+3*32(%rip), INP
+       vpaddd  (INP, SRND), X0, XFER
+       vmovdqa XFER, 3*32+_XFER(%rsp, SRND)
+-      FOUR_ROUNDS_AND_SCHED   _XFER + 3*32
++      FOUR_ROUNDS_AND_SCHED   (_XFER + 3*32)
+       add     $4*32, SRND
+       cmp     $3*4*32, SRND
+@@ -618,12 +618,12 @@ SYM_TYPED_FUNC_START(sha256_transform_rorx)
+       leaq    K256+0*32(%rip), INP
+       vpaddd  (INP, SRND), X0, XFER
+       vmovdqa XFER, 0*32+_XFER(%rsp, SRND)
+-      DO_4ROUNDS      _XFER + 0*32
++      DO_4ROUNDS      (_XFER + 0*32)
+       leaq    K256+1*32(%rip), INP
+       vpaddd  (INP, SRND), X1, XFER
+       vmovdqa XFER, 1*32+_XFER(%rsp, SRND)
+-      DO_4ROUNDS      _XFER + 1*32
++      DO_4ROUNDS      (_XFER + 1*32)
+       add     $2*32, SRND
+       vmovdqa X2, X0
+@@ -651,8 +651,8 @@ SYM_TYPED_FUNC_START(sha256_transform_rorx)
+       xor     SRND, SRND
+ .align 16
+ .Lloop3:
+-      DO_4ROUNDS       _XFER + 0*32 + 16
+-      DO_4ROUNDS       _XFER + 1*32 + 16
++      DO_4ROUNDS      (_XFER + 0*32 + 16)
++      DO_4ROUNDS      (_XFER + 1*32 + 16)
+       add     $2*32, SRND
+       cmp     $4*4*32, SRND
+       jb      .Lloop3
+-- 
+2.43.0
+
diff --git a/queue-6.11/drivers-perf-arm_spe-use-perf_allow_kernel-for-permi.patch b/queue-6.11/drivers-perf-arm_spe-use-perf_allow_kernel-for-permi.patch
new file mode 100644 (file)
index 0000000..a56448e
--- /dev/null
@@ -0,0 +1,115 @@
+From 45d3524e60e15513dfe0fbe36a5e8694d29afaf7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 15:51:12 +0100
+Subject: drivers/perf: arm_spe: Use perf_allow_kernel() for permissions
+
+From: James Clark <james.clark@linaro.org>
+
+[ Upstream commit 5e9629d0ae977d6f6916d7e519724804e95f0b07 ]
+
+Use perf_allow_kernel() for 'pa_enable' (physical addresses),
+'pct_enable' (physical timestamps) and context IDs. This means that
+perf_event_paranoid is now taken into account and LSM hooks can be used,
+which is more consistent with other perf_event_open calls. For example
+PERF_SAMPLE_PHYS_ADDR uses perf_allow_kernel() rather than just
+perfmon_capable().
+
+This also indirectly fixes the following error message which is
+misleading because perf_event_paranoid is not taken into account by
+perfmon_capable():
+
+  $ perf record -e arm_spe/pa_enable/
+
+  Error:
+  Access to performance monitoring and observability operations is
+  limited. Consider adjusting /proc/sys/kernel/perf_event_paranoid
+  setting ...
+
+Suggested-by: Al Grant <al.grant@arm.com>
+Signed-off-by: James Clark <james.clark@linaro.org>
+Link: https://lore.kernel.org/r/20240827145113.1224604-1-james.clark@linaro.org
+Link: https://lore.kernel.org/all/20240807120039.GD37996@noisy.programming.kicks-ass.net/
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/arm_spe_pmu.c | 9 ++++-----
+ include/linux/perf_event.h | 8 +-------
+ kernel/events/core.c       | 9 +++++++++
+ 3 files changed, 14 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c
+index 9100d82bfabc0..3569050f9cf37 100644
+--- a/drivers/perf/arm_spe_pmu.c
++++ b/drivers/perf/arm_spe_pmu.c
+@@ -41,7 +41,7 @@
+ /*
+  * Cache if the event is allowed to trace Context information.
+- * This allows us to perform the check, i.e, perfmon_capable(),
++ * This allows us to perform the check, i.e, perf_allow_kernel(),
+  * in the context of the event owner, once, during the event_init().
+  */
+ #define SPE_PMU_HW_FLAGS_CX                   0x00001
+@@ -50,7 +50,7 @@ static_assert((PERF_EVENT_FLAG_ARCH & SPE_PMU_HW_FLAGS_CX) == SPE_PMU_HW_FLAGS_C
+ static void set_spe_event_has_cx(struct perf_event *event)
+ {
+-      if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && perfmon_capable())
++      if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && !perf_allow_kernel(&event->attr))
+               event->hw.flags |= SPE_PMU_HW_FLAGS_CX;
+ }
+@@ -745,9 +745,8 @@ static int arm_spe_pmu_event_init(struct perf_event *event)
+       set_spe_event_has_cx(event);
+       reg = arm_spe_event_to_pmscr(event);
+-      if (!perfmon_capable() &&
+-          (reg & (PMSCR_EL1_PA | PMSCR_EL1_PCT)))
+-              return -EACCES;
++      if (reg & (PMSCR_EL1_PA | PMSCR_EL1_PCT))
++              return perf_allow_kernel(&event->attr);
+       return 0;
+ }
+diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
+index 1a8942277ddad..e336306b8c08e 100644
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -1602,13 +1602,7 @@ static inline int perf_is_paranoid(void)
+       return sysctl_perf_event_paranoid > -1;
+ }
+-static inline int perf_allow_kernel(struct perf_event_attr *attr)
+-{
+-      if (sysctl_perf_event_paranoid > 1 && !perfmon_capable())
+-              return -EACCES;
+-
+-      return security_perf_event_open(attr, PERF_SECURITY_KERNEL);
+-}
++int perf_allow_kernel(struct perf_event_attr *attr);
+ static inline int perf_allow_cpu(struct perf_event_attr *attr)
+ {
+diff --git a/kernel/events/core.c b/kernel/events/core.c
+index 8a6c6bbcd658a..b21c8f24a9876 100644
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -13358,6 +13358,15 @@ const struct perf_event_attr *perf_event_attrs(struct perf_event *event)
+       return &event->attr;
+ }
++int perf_allow_kernel(struct perf_event_attr *attr)
++{
++      if (sysctl_perf_event_paranoid > 1 && !perfmon_capable())
++              return -EACCES;
++
++      return security_perf_event_open(attr, PERF_SECURITY_KERNEL);
++}
++EXPORT_SYMBOL_GPL(perf_allow_kernel);
++
+ /*
+  * Inherit an event from parent task to child task.
+  *
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-afb-in-amdgpu_dm_.patch b/queue-6.11/drm-amd-display-add-null-check-for-afb-in-amdgpu_dm_.patch
new file mode 100644 (file)
index 0000000..578c22d
--- /dev/null
@@ -0,0 +1,55 @@
+From 2c2e30b1beebfb031dbaf75b575033e86c186037 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 12:20:36 +0530
+Subject: drm/amd/display: Add null check for 'afb' in amdgpu_dm_update_cursor
+ (v2)
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 0fe20258b4989b9112b5e9470df33a0939403fd4 ]
+
+This commit adds a null check for the 'afb' variable in the
+amdgpu_dm_update_cursor function. Previously, 'afb' was assumed to be
+null at line 8388, but was used later in the code without a null check.
+This could potentially lead to a null pointer dereference.
+
+Changes since v1:
+- Moved the null check for 'afb' to the line where 'afb' is used. (Alex)
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:8433 amdgpu_dm_update_cursor()
+       error: we previously assumed 'afb' could be null (see line 8388)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Co-developed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 188d10820654a..579022bb198d1 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -8795,7 +8795,8 @@ static void amdgpu_dm_update_cursor(struct drm_plane *plane,
+           adev->dm.dc->caps.color.dpp.gamma_corr)
+               attributes.attribute_flags.bits.ENABLE_CURSOR_DEGAMMA = 1;
+-      attributes.pitch = afb->base.pitches[0] / afb->base.format->cpp[0];
++      if (afb)
++              attributes.pitch = afb->base.pitches[0] / afb->base.format->cpp[0];
+       if (crtc_state->stream) {
+               if (!dc_stream_set_cursor_attributes(crtc_state->stream,
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-afb-in-amdgpu_dm_.patch-8577 b/queue-6.11/drm-amd-display-add-null-check-for-afb-in-amdgpu_dm_.patch-8577
new file mode 100644 (file)
index 0000000..fddc948
--- /dev/null
@@ -0,0 +1,54 @@
+From b012a349228e03203c9b292c1aaf1b62798e03ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 12:35:13 +0530
+Subject: drm/amd/display: Add null check for 'afb' in
+ amdgpu_dm_plane_handle_cursor_update (v2)
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit cd9e9e0852d501f169aa3bb34e4b413d2eb48c37 ]
+
+This commit adds a null check for the 'afb' variable in the
+amdgpu_dm_plane_handle_cursor_update function. Previously, 'afb' was
+assumed to be null, but was used later in the code without a null check.
+This could potentially lead to a null pointer dereference.
+
+Changes since v1:
+- Moved the null check for 'afb' to the line where 'afb' is used. (Alex)
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm_plane.c:1298 amdgpu_dm_plane_handle_cursor_update() error: we previously assumed 'afb' could be null (see line 1252)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Co-developed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+index 5cb11cc2d0636..a573a66398984 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+@@ -1377,7 +1377,8 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
+           adev->dm.dc->caps.color.dpp.gamma_corr)
+               attributes.attribute_flags.bits.ENABLE_CURSOR_DEGAMMA = 1;
+-      attributes.pitch = afb->base.pitches[0] / afb->base.format->cpp[0];
++      if (afb)
++              attributes.pitch = afb->base.pitches[0] / afb->base.format->cpp[0];
+       if (crtc_state->stream) {
+               mutex_lock(&adev->dm.dc_lock);
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-clk_mgr-and-clk_m.patch b/queue-6.11/drm-amd-display-add-null-check-for-clk_mgr-and-clk_m.patch
new file mode 100644 (file)
index 0000000..1f719dd
--- /dev/null
@@ -0,0 +1,67 @@
+From 70ec1bdac1a38dbe3e1531683c7bea11f31534f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jul 2024 16:21:19 +0530
+Subject: drm/amd/display: Add NULL check for clk_mgr and clk_mgr->funcs in
+ dcn30_init_hw
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit cba7fec864172dadd953daefdd26e01742b71a6a ]
+
+This commit addresses a potential null pointer dereference issue in the
+`dcn30_init_hw` function. The issue could occur when `dc->clk_mgr` or
+`dc->clk_mgr->funcs` is null.
+
+The fix adds a check to ensure `dc->clk_mgr` and `dc->clk_mgr->funcs` is
+not null before accessing its functions. This prevents a potential null
+pointer dereference.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c:789 dcn30_init_hw() error: we previously assumed 'dc->clk_mgr' could be null (see line 628)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+index 2b4dae2d4b0c1..6f5c6f7b19db6 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+@@ -629,7 +629,7 @@ void dcn30_init_hw(struct dc *dc)
+       uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
+-      if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
++      if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks)
+               dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
+       // Initialize the dccg
+@@ -790,11 +790,12 @@ void dcn30_init_hw(struct dc *dc)
+       if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
+               dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
+-      if (dc->clk_mgr->funcs->notify_wm_ranges)
++      if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+       //if softmax is enabled then hardmax will be set by a different call
+-      if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
++      if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->set_hard_max_memclk &&
++          !dc->clk_mgr->dc_mode_softmax_enabled)
+               dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
+       if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-clk_mgr-and-clk_m.patch-5210 b/queue-6.11/drm-amd-display-add-null-check-for-clk_mgr-and-clk_m.patch-5210
new file mode 100644 (file)
index 0000000..670ffc5
--- /dev/null
@@ -0,0 +1,72 @@
+From b204c3ee8c5a17bac98bb5d544e88d22e3cf263f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jul 2024 16:58:32 +0530
+Subject: drm/amd/display: Add NULL check for clk_mgr and clk_mgr->funcs in
+ dcn401_init_hw
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 4b6377f0e96085cbec96eb7f0b282430ccdd3d75 ]
+
+This commit addresses a potential null pointer dereference issue in the
+`dcn401_init_hw` function. The issue could occur when `dc->clk_mgr` or
+`dc->clk_mgr->funcs` is null.
+
+The fix adds a check to ensure `dc->clk_mgr` and `dc->clk_mgr->funcs` is
+not null before accessing its functions. This prevents a potential null
+pointer dereference.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn401/dcn401_hwseq.c:416 dcn401_init_hw() error: we previously assumed 'dc->clk_mgr' could be null (see line 225)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+index 2c50c0f745a0b..324e77ceaf1cf 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+@@ -222,7 +222,7 @@ void dcn401_init_hw(struct dc *dc)
+       uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
+-      if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) {
++      if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
+               dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
+               // mark dcmode limits present if any clock has distinct AC and DC values from SMU
+@@ -413,7 +413,7 @@ void dcn401_init_hw(struct dc *dc)
+       if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
+               dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
+-      if (dc->clk_mgr->funcs->notify_wm_ranges)
++      if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+       if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
+@@ -438,7 +438,9 @@ void dcn401_init_hw(struct dc *dc)
+               dc->debug.fams2_config.bits.enable &= dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver == 2;
+               if (!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box) {
+                       /* update bounding box if FAMS2 disabled */
+-                      dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
++                      if (dc->clk_mgr)
++                              dc->res_pool->funcs->update_bw_bounding_box(dc,
++                                                                          dc->clk_mgr->bw_params);
+               }
+       }
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-clk_mgr-in-dcn32_.patch b/queue-6.11/drm-amd-display-add-null-check-for-clk_mgr-in-dcn32_.patch
new file mode 100644 (file)
index 0000000..9e4ac47
--- /dev/null
@@ -0,0 +1,65 @@
+From 6faf23773b028fad997f08f2c57dcd8186b34e6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jul 2024 16:44:40 +0530
+Subject: drm/amd/display: Add NULL check for clk_mgr in dcn32_init_hw
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit c395fd47d1565bd67671f45cca281b3acc2c31ef ]
+
+This commit addresses a potential null pointer dereference issue in the
+`dcn32_init_hw` function. The issue could occur when `dc->clk_mgr` is
+null.
+
+The fix adds a check to ensure `dc->clk_mgr` is not null before
+accessing its functions. This prevents a potential null pointer
+dereference.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn32/dcn32_hwseq.c:961 dcn32_init_hw() error: we previously assumed 'dc->clk_mgr' could be null (see line 782)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+index df80072174b79..9a912b9c1f2e9 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+@@ -779,7 +779,7 @@ void dcn32_init_hw(struct dc *dc)
+       uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
+-      if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
++      if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks)
+               dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
+       // Initialize the dccg
+@@ -958,10 +958,11 @@ void dcn32_init_hw(struct dc *dc)
+       if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
+               dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
+-      if (dc->clk_mgr->funcs->notify_wm_ranges)
++      if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+-      if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
++      if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->set_hard_max_memclk &&
++          !dc->clk_mgr->dc_mode_softmax_enabled)
+               dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
+       if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-function-pointer-.patch b/queue-6.11/drm-amd-display-add-null-check-for-function-pointer-.patch
new file mode 100644 (file)
index 0000000..27204cb
--- /dev/null
@@ -0,0 +1,53 @@
+From 9467d16f10439393df52a1a6d7db156879dd4e37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 13:09:28 +0530
+Subject: drm/amd/display: Add NULL check for function pointer in
+ dcn20_set_output_transfer_func
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 62ed6f0f198da04e884062264df308277628004f ]
+
+This commit adds a null check for the set_output_gamma function pointer
+in the dcn20_set_output_transfer_func function. Previously,
+set_output_gamma was being checked for null at line 1030, but then it
+was being dereferenced without any null check at line 1048. This could
+potentially lead to a null pointer dereference error if set_output_gamma
+is null.
+
+To fix this, we now ensure that set_output_gamma is not null before
+dereferencing it. We do this by adding a null check for set_output_gamma
+before the call to set_output_gamma at line 1048.
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+index 17d1c195663a0..7ca0da88290af 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+@@ -1044,7 +1044,8 @@ bool dcn20_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
+       /*
+        * if above if is not executed then 'params' equal to 0 and set in bypass
+        */
+-      mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
++      if (mpc->funcs->set_output_gamma)
++              mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
+       return true;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-function-pointer-.patch-16350 b/queue-6.11/drm-amd-display-add-null-check-for-function-pointer-.patch-16350
new file mode 100644 (file)
index 0000000..cb48736
--- /dev/null
@@ -0,0 +1,53 @@
+From f2efe05c52f1b1596f56275a8764b884d1893d0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 13:15:00 +0530
+Subject: drm/amd/display: Add NULL check for function pointer in
+ dcn32_set_output_transfer_func
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 28574b08c70e56d34d6f6379326a860b96749051 ]
+
+This commit adds a null check for the set_output_gamma function pointer
+in the dcn32_set_output_transfer_func function. Previously,
+set_output_gamma was being checked for null, but then it was being
+dereferenced without any null check. This could lead to a null pointer
+dereference if set_output_gamma is null.
+
+To fix this, we now ensure that set_output_gamma is not null before
+dereferencing it. We do this by adding a null check for set_output_gamma
+before the call to set_output_gamma.
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+index 9a912b9c1f2e9..33e3d94e429d4 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+@@ -582,7 +582,9 @@ bool dcn32_set_output_transfer_func(struct dc *dc,
+               }
+       }
+-      mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
++      if (mpc->funcs->set_output_gamma)
++              mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
++
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-function-pointer-.patch-4383 b/queue-6.11/drm-amd-display-add-null-check-for-function-pointer-.patch-4383
new file mode 100644 (file)
index 0000000..739d447
--- /dev/null
@@ -0,0 +1,53 @@
+From 0af6765e878891640b0b988895a937118f352277 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 13:22:06 +0530
+Subject: drm/amd/display: Add NULL check for function pointer in
+ dcn401_set_output_transfer_func
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit dd340acd42c24a3f28dd22fae6bf38662334264c ]
+
+This commit adds a null check for the set_output_gamma function pointer
+in the dcn401_set_output_transfer_func function. Previously,
+set_output_gamma was being checked for null, but then it was being
+dereferenced without any null check. This could lead to a null pointer
+dereference if set_output_gamma is null.
+
+To fix this, we now ensure that set_output_gamma is not null before
+dereferencing it. We do this by adding a null check for set_output_gamma
+before the call to set_output_gamma.
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+index 537a24ec74c85..7c724cf682840 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+@@ -748,7 +748,9 @@ bool dcn401_set_output_transfer_func(struct dc *dc,
+               }
+       }
+-      mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
++      if (mpc->funcs->set_output_gamma)
++              mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
++
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-head_pipe-in-dcn2.patch b/queue-6.11/drm-amd-display-add-null-check-for-head_pipe-in-dcn2.patch
new file mode 100644 (file)
index 0000000..eea1505
--- /dev/null
@@ -0,0 +1,55 @@
+From 700b90705775d023fe1f1157803524c708fb1743 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 21 Jul 2024 19:18:58 +0530
+Subject: drm/amd/display: Add null check for head_pipe in
+ dcn201_acquire_free_pipe_for_layer
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit f22f4754aaa47d8c59f166ba3042182859e5dff7 ]
+
+This commit addresses a potential null pointer dereference issue in the
+`dcn201_acquire_free_pipe_for_layer` function. The issue could occur
+when `head_pipe` is null.
+
+The fix adds a check to ensure `head_pipe` is not null before asserting
+it. If `head_pipe` is null, the function returns NULL to prevent a
+potential null pointer dereference.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn201/dcn201_resource.c:1016 dcn201_acquire_free_pipe_for_layer() error: we previously assumed 'head_pipe' could be null (see line 1010)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c  | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
+index 131d98025bd47..fc54483b91047 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
+@@ -1007,8 +1007,10 @@ static struct pipe_ctx *dcn201_acquire_free_pipe_for_layer(
+       struct pipe_ctx *head_pipe = resource_get_otg_master_for_stream(res_ctx, opp_head_pipe->stream);
+       struct pipe_ctx *idle_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, head_pipe);
+-      if (!head_pipe)
++      if (!head_pipe) {
+               ASSERT(0);
++              return NULL;
++      }
+       if (!idle_pipe)
+               return NULL;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-head_pipe-in-dcn3.patch b/queue-6.11/drm-amd-display-add-null-check-for-head_pipe-in-dcn3.patch
new file mode 100644 (file)
index 0000000..a762250
--- /dev/null
@@ -0,0 +1,55 @@
+From d4f027d7d32594ab55dbb20d7edfd3c413ad73a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 21 Jul 2024 19:30:16 +0530
+Subject: drm/amd/display: Add null check for head_pipe in
+ dcn32_acquire_idle_pipe_for_head_pipe_in_layer
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit ac2140449184a26eac99585b7f69814bd3ba8f2d ]
+
+This commit addresses a potential null pointer dereference issue in the
+`dcn32_acquire_idle_pipe_for_head_pipe_in_layer` function. The issue
+could occur when `head_pipe` is null.
+
+The fix adds a check to ensure `head_pipe` is not null before asserting
+it. If `head_pipe` is null, the function returns NULL to prevent a
+potential null pointer dereference.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn32/dcn32_resource.c:2690 dcn32_acquire_idle_pipe_for_head_pipe_in_layer() error: we previously assumed 'head_pipe' could be null (see line 2681)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c    | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+index a43ffa53890af..6e2a08a9572b8 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+@@ -2674,8 +2674,10 @@ static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
+       struct resource_context *old_ctx = &stream->ctx->dc->current_state->res_ctx;
+       int head_index;
+-      if (!head_pipe)
++      if (!head_pipe) {
+               ASSERT(0);
++              return NULL;
++      }
+       /*
+        * Modified from dcn20_acquire_idle_pipe_for_layer
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-pipe_ctx-plane_st.patch b/queue-6.11/drm-amd-display-add-null-check-for-pipe_ctx-plane_st.patch
new file mode 100644 (file)
index 0000000..571a7be
--- /dev/null
@@ -0,0 +1,100 @@
+From 27a70b1abaf28313e93c1ddc3afeb7aaa223b591 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jul 2024 08:14:56 +0530
+Subject: drm/amd/display: Add null check for pipe_ctx->plane_state in
+ dcn20_program_pipe
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 8e4ed3cf1642df0c4456443d865cff61a9598aa8 ]
+
+This commit addresses a null pointer dereference issue in the
+`dcn20_program_pipe` function. The issue could occur when
+`pipe_ctx->plane_state` is null.
+
+The fix adds a check to ensure `pipe_ctx->plane_state` is not null
+before accessing. This prevents a null pointer dereference.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn20/dcn20_hwseq.c:1925 dcn20_program_pipe() error: we previously assumed 'pipe_ctx->plane_state' could be null (see line 1877)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   | 30 ++++++++++++-------
+ 1 file changed, 19 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+index 456e19e0d415c..17d1c195663a0 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+@@ -1921,22 +1921,29 @@ static void dcn20_program_pipe(
+                               dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size);
+       }
+-      if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw)
++      if (pipe_ctx->update_flags.raw ||
++          (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) ||
++          pipe_ctx->stream->update_flags.raw)
+               dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
+-      if (pipe_ctx->update_flags.bits.enable
+-                      || pipe_ctx->plane_state->update_flags.bits.hdr_mult)
++      if (pipe_ctx->update_flags.bits.enable ||
++          (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.bits.hdr_mult))
+               hws->funcs.set_hdr_multiplier(pipe_ctx);
+       if (hws->funcs.populate_mcm_luts) {
+-              hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts,
+-                              pipe_ctx->plane_state->lut_bank_a);
+-              pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a;
++              if (pipe_ctx->plane_state) {
++                      hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts,
++                                                   pipe_ctx->plane_state->lut_bank_a);
++                      pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a;
++              }
+       }
+       if (pipe_ctx->update_flags.bits.enable ||
+-          pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
+-          pipe_ctx->plane_state->update_flags.bits.gamma_change ||
+-          pipe_ctx->plane_state->update_flags.bits.lut_3d)
++          (pipe_ctx->plane_state &&
++           pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change) ||
++          (pipe_ctx->plane_state &&
++           pipe_ctx->plane_state->update_flags.bits.gamma_change) ||
++          (pipe_ctx->plane_state &&
++           pipe_ctx->plane_state->update_flags.bits.lut_3d))
+               hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
+       /* dcn10_translate_regamma_to_hw_format takes 750us to finish
+@@ -1946,7 +1953,8 @@ static void dcn20_program_pipe(
+       if (pipe_ctx->update_flags.bits.enable ||
+                       pipe_ctx->update_flags.bits.plane_changed ||
+                       pipe_ctx->stream->update_flags.bits.out_tf ||
+-                      pipe_ctx->plane_state->update_flags.bits.output_tf_change)
++                      (pipe_ctx->plane_state &&
++                       pipe_ctx->plane_state->update_flags.bits.output_tf_change))
+               hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
+       /* If the pipe has been enabled or has a different opp, we
+@@ -1970,7 +1978,7 @@ static void dcn20_program_pipe(
+       }
+       /* Set ABM pipe after other pipe configurations done */
+-      if (pipe_ctx->plane_state->visible) {
++      if ((pipe_ctx->plane_state && pipe_ctx->plane_state->visible)) {
+               if (pipe_ctx->stream_res.abm) {
+                       dc->hwss.set_pipe(pipe_ctx);
+                       pipe_ctx->stream_res.abm->funcs->set_abm_level(pipe_ctx->stream_res.abm,
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-add-null-check-for-top_pipe_to_progr.patch b/queue-6.11/drm-amd-display-add-null-check-for-top_pipe_to_progr.patch
new file mode 100644 (file)
index 0000000..299cc1c
--- /dev/null
@@ -0,0 +1,52 @@
+From 29ea7fc25a29da4c94055934f1f01b6050f7887c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jul 2024 07:23:48 +0530
+Subject: drm/amd/display: Add null check for top_pipe_to_program in
+ commit_planes_for_stream
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 66d71a72539e173a9b00ca0b1852cbaa5f5bf1ad ]
+
+This commit addresses a null pointer dereference issue in the
+`commit_planes_for_stream` function at line 4140. The issue could occur
+when `top_pipe_to_program` is null.
+
+The fix adds a check to ensure `top_pipe_to_program` is not null before
+accessing its stream_res. This prevents a null pointer dereference.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc.c:4140 commit_planes_for_stream() error: we previously assumed 'top_pipe_to_program' could be null (see line 3906)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index 85a2ef82afa53..9e7ba846e032b 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -4127,7 +4127,8 @@ static void commit_planes_for_stream(struct dc *dc,
+       }
+       if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
+-              if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
++              if (top_pipe_to_program &&
++                  top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
+                       top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
+                               top_pipe_to_program->stream_res.tg,
+                               CRTC_STATE_VACTIVE);
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-avoid-overflow-assignment-in-link_dp.patch b/queue-6.11/drm-amd-display-avoid-overflow-assignment-in-link_dp.patch
new file mode 100644 (file)
index 0000000..457674d
--- /dev/null
@@ -0,0 +1,71 @@
+From f5e0019a94b26a1e5ae67a652d48f32d31322733 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jul 2024 09:17:56 -0600
+Subject: drm/amd/display: Avoid overflow assignment in link_dp_cts
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit a15268787b79fd183dd526cc16bec9af4f4e49a1 ]
+
+sampling_rate is an uint8_t but is assigned an unsigned int, and thus it
+can overflow. As a result, sampling_rate is changed to uint32_t.
+
+Similarly, LINK_QUAL_PATTERN_SET has a size of 2 bits, and it should
+only be assigned to a value less or equal than 4.
+
+This fixes 2 INTEGER_OVERFLOW issues reported by Coverity.
+
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dc_dp_types.h                  | 2 +-
+ drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c | 3 ++-
+ drivers/gpu/drm/amd/display/include/dpcd_defs.h               | 1 +
+ 3 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+index 519c3df78ee5b..95c275bf649bd 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+@@ -727,7 +727,7 @@ struct dp_audio_test_data_flags {
+ struct dp_audio_test_data {
+       struct dp_audio_test_data_flags flags;
+-      uint8_t sampling_rate;
++      uint32_t sampling_rate;
+       uint8_t channel_count;
+       uint8_t pattern_type;
+       uint8_t pattern_period[8];
+diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+index df3781081da7a..32d5a4b143333 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
++++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+@@ -775,7 +775,8 @@ bool dp_set_test_pattern(
+                       core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
+                                           &training_pattern.raw,
+                                           sizeof(training_pattern));
+-                      training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
++                      if (pattern <= PHY_TEST_PATTERN_END_DP11)
++                              training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
+                       core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
+                                            &training_pattern.raw,
+                                            sizeof(training_pattern));
+diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
+index aee5170f5fb23..c246235e4afec 100644
+--- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h
++++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
+@@ -76,6 +76,7 @@ enum dpcd_phy_test_patterns {
+       PHY_TEST_PATTERN_D10_2,
+       PHY_TEST_PATTERN_SYMBOL_ERROR,
+       PHY_TEST_PATTERN_PRBS7,
++      PHY_TEST_PATTERN_END_DP11 = PHY_TEST_PATTERN_PRBS7,
+       PHY_TEST_PATTERN_80BIT_CUSTOM,/* For DP1.2 only */
+       PHY_TEST_PATTERN_CP2520_1,
+       PHY_TEST_PATTERN_CP2520_2,
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-check-null-initialized-variables.patch b/queue-6.11/drm-amd-display-check-null-initialized-variables.patch
new file mode 100644 (file)
index 0000000..7547e53
--- /dev/null
@@ -0,0 +1,55 @@
+From 6e84a2726b8faa39ea7d5a6d1e5185111ab43586 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jun 2024 17:34:18 -0600
+Subject: drm/amd/display: Check null-initialized variables
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 367cd9ceba1933b63bc1d87d967baf6d9fd241d2 ]
+
+[WHAT & HOW]
+drr_timing and subvp_pipe are initialized to null and they are not
+always assigned new values. It is necessary to check for null before
+dereferencing.
+
+This fixes 2 FORWARD_NULL issues reported by Coverity.
+
+Reviewed-by: Nevenko Stupar <nevenko.stupar@amd.com>
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+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 9d399c4ce957d..4cb0227bdd270 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
+@@ -871,8 +871,9 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context)
+        * for VBLANK: (VACTIVE region of the SubVP pipe can fit the MALL prefetch, VBLANK frame time,
+        * and the max of (VBLANK blanking time, MALL region)).
+        */
+-      if (stretched_drr_us < (1 / (double)drr_timing->min_refresh_in_uhz) * 1000000 * 1000000 &&
+-                      subvp_active_us - prefetch_us - stretched_drr_us - max_vblank_mallregion > 0)
++      if (drr_timing &&
++          stretched_drr_us < (1 / (double)drr_timing->min_refresh_in_uhz) * 1000000 * 1000000 &&
++          subvp_active_us - prefetch_us - stretched_drr_us - max_vblank_mallregion > 0)
+               schedulable = true;
+       return schedulable;
+@@ -937,7 +938,7 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
+               if (!subvp_pipe && pipe_mall_type == SUBVP_MAIN)
+                       subvp_pipe = pipe;
+       }
+-      if (found) {
++      if (found && subvp_pipe) {
+               phantom_stream = dc_state_get_paired_subvp_stream(context, subvp_pipe->stream);
+               main_timing = &subvp_pipe->stream->timing;
+               phantom_timing = &phantom_stream->timing;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-check-null-pointer-before-try-to-acc.patch b/queue-6.11/drm-amd-display-check-null-pointer-before-try-to-acc.patch
new file mode 100644 (file)
index 0000000..f29b6c3
--- /dev/null
@@ -0,0 +1,59 @@
+From aadb33686c0531f49d9f3d1ccb9dcd5fdf9420f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 20:02:45 -0600
+Subject: drm/amd/display: Check null pointer before try to access it
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ Upstream commit 1b686053c06ffb9f4524b288110cf2a831ff7a25 ]
+
+[why & how]
+Change the order of the pipe_ctx->plane_state check to ensure that
+plane_state is not null before accessing it.
+
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c   | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+index 7ca0da88290af..936c0ec076bc4 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+@@ -1931,6 +1931,11 @@ static void dcn20_program_pipe(
+           (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.bits.hdr_mult))
+               hws->funcs.set_hdr_multiplier(pipe_ctx);
++      if ((pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.bits.hdr_mult) ||
++          pipe_ctx->update_flags.bits.enable)
++              hws->funcs.set_hdr_multiplier(pipe_ctx);
++
++
+       if (hws->funcs.populate_mcm_luts) {
+               if (pipe_ctx->plane_state) {
+                       hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts,
+@@ -1938,13 +1943,13 @@ static void dcn20_program_pipe(
+                       pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a;
+               }
+       }
+-      if (pipe_ctx->update_flags.bits.enable ||
+-          (pipe_ctx->plane_state &&
++      if ((pipe_ctx->plane_state &&
+            pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change) ||
+           (pipe_ctx->plane_state &&
+            pipe_ctx->plane_state->update_flags.bits.gamma_change) ||
+           (pipe_ctx->plane_state &&
+-           pipe_ctx->plane_state->update_flags.bits.lut_3d))
++           pipe_ctx->plane_state->update_flags.bits.lut_3d) ||
++           pipe_ctx->update_flags.bits.enable)
+               hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
+       /* dcn10_translate_regamma_to_hw_format takes 750us to finish
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-check-null-pointers-before-multiple-.patch b/queue-6.11/drm-amd-display-check-null-pointers-before-multiple-.patch
new file mode 100644 (file)
index 0000000..aee811a
--- /dev/null
@@ -0,0 +1,265 @@
+From 89ae643c567cfed5dcb5519f22faf2fe78f08eab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jun 2024 10:37:35 -0600
+Subject: drm/amd/display: Check null pointers before multiple uses
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit fdd5ecbbff751c3b9061d8ebb08e5c96119915b4 ]
+
+[WHAT & HOW]
+Poniters, such as stream_enc and dc->bw_vbios, are null checked previously
+in the same function, so Coverity warns "implies that stream_enc and
+dc->bw_vbios might be null". They are used multiple times in the
+subsequent code and need to be checked.
+
+This fixes 10 FORWARD_NULL issues reported by Coverity.
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/dc/core/dc_hw_sequencer.c | 96 ++++++++++---------
+ .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   |  8 +-
+ .../display/dc/link/accessories/link_dp_cts.c |  5 +-
+ .../amd/display/dc/link/hwss/link_hwss_dio.c  |  5 +-
+ .../dc/resource/dce112/dce112_resource.c      |  5 +-
+ .../dc/resource/dcn32/dcn32_resource.c        |  3 +
+ .../resource/dcn32/dcn32_resource_helpers.c   | 10 +-
+ 7 files changed, 76 insertions(+), 56 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+index 87e36d51c56d8..4a88412fdfab1 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+@@ -636,57 +636,59 @@ void hwss_build_fast_sequence(struct dc *dc,
+       while (current_pipe) {
+               current_mpc_pipe = current_pipe;
+               while (current_mpc_pipe) {
+-                      if (dc->hwss.set_flip_control_gsl && current_mpc_pipe->plane_state && current_mpc_pipe->plane_state->update_flags.raw) {
+-                              block_sequence[*num_steps].params.set_flip_control_gsl_params.pipe_ctx = current_mpc_pipe;
+-                              block_sequence[*num_steps].params.set_flip_control_gsl_params.flip_immediate = current_mpc_pipe->plane_state->flip_immediate;
+-                              block_sequence[*num_steps].func = HUBP_SET_FLIP_CONTROL_GSL;
+-                              (*num_steps)++;
+-                      }
+-                      if (dc->hwss.program_triplebuffer && dc->debug.enable_tri_buf && current_mpc_pipe->plane_state->update_flags.raw) {
+-                              block_sequence[*num_steps].params.program_triplebuffer_params.dc = dc;
+-                              block_sequence[*num_steps].params.program_triplebuffer_params.pipe_ctx = current_mpc_pipe;
+-                              block_sequence[*num_steps].params.program_triplebuffer_params.enableTripleBuffer = current_mpc_pipe->plane_state->triplebuffer_flips;
+-                              block_sequence[*num_steps].func = HUBP_PROGRAM_TRIPLEBUFFER;
+-                              (*num_steps)++;
+-                      }
+-                      if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) {
+-                              if (resource_is_pipe_type(current_mpc_pipe, OTG_MASTER) &&
+-                                              stream_status->mall_stream_config.type == SUBVP_MAIN) {
+-                                      block_sequence[*num_steps].params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv;
+-                                      block_sequence[*num_steps].params.subvp_save_surf_addr.addr = &current_mpc_pipe->plane_state->address;
+-                                      block_sequence[*num_steps].params.subvp_save_surf_addr.subvp_index = current_mpc_pipe->subvp_index;
+-                                      block_sequence[*num_steps].func = DMUB_SUBVP_SAVE_SURF_ADDR;
++                      if (current_mpc_pipe->plane_state) {
++                              if (dc->hwss.set_flip_control_gsl && current_mpc_pipe->plane_state->update_flags.raw) {
++                                      block_sequence[*num_steps].params.set_flip_control_gsl_params.pipe_ctx = current_mpc_pipe;
++                                      block_sequence[*num_steps].params.set_flip_control_gsl_params.flip_immediate = current_mpc_pipe->plane_state->flip_immediate;
++                                      block_sequence[*num_steps].func = HUBP_SET_FLIP_CONTROL_GSL;
++                                      (*num_steps)++;
++                              }
++                              if (dc->hwss.program_triplebuffer && dc->debug.enable_tri_buf && current_mpc_pipe->plane_state->update_flags.raw) {
++                                      block_sequence[*num_steps].params.program_triplebuffer_params.dc = dc;
++                                      block_sequence[*num_steps].params.program_triplebuffer_params.pipe_ctx = current_mpc_pipe;
++                                      block_sequence[*num_steps].params.program_triplebuffer_params.enableTripleBuffer = current_mpc_pipe->plane_state->triplebuffer_flips;
++                                      block_sequence[*num_steps].func = HUBP_PROGRAM_TRIPLEBUFFER;
++                                      (*num_steps)++;
++                              }
++                              if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) {
++                                      if (resource_is_pipe_type(current_mpc_pipe, OTG_MASTER) &&
++                                                      stream_status->mall_stream_config.type == SUBVP_MAIN) {
++                                              block_sequence[*num_steps].params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv;
++                                              block_sequence[*num_steps].params.subvp_save_surf_addr.addr = &current_mpc_pipe->plane_state->address;
++                                              block_sequence[*num_steps].params.subvp_save_surf_addr.subvp_index = current_mpc_pipe->subvp_index;
++                                              block_sequence[*num_steps].func = DMUB_SUBVP_SAVE_SURF_ADDR;
++                                              (*num_steps)++;
++                                      }
++
++                                      block_sequence[*num_steps].params.update_plane_addr_params.dc = dc;
++                                      block_sequence[*num_steps].params.update_plane_addr_params.pipe_ctx = current_mpc_pipe;
++                                      block_sequence[*num_steps].func = HUBP_UPDATE_PLANE_ADDR;
+                                       (*num_steps)++;
+                               }
+-                              block_sequence[*num_steps].params.update_plane_addr_params.dc = dc;
+-                              block_sequence[*num_steps].params.update_plane_addr_params.pipe_ctx = current_mpc_pipe;
+-                              block_sequence[*num_steps].func = HUBP_UPDATE_PLANE_ADDR;
+-                              (*num_steps)++;
+-                      }
+-
+-                      if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_flags.bits.gamma_change) {
+-                              block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc;
+-                              block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe;
+-                              block_sequence[*num_steps].params.set_input_transfer_func_params.plane_state = current_mpc_pipe->plane_state;
+-                              block_sequence[*num_steps].func = DPP_SET_INPUT_TRANSFER_FUNC;
+-                              (*num_steps)++;
+-                      }
++                              if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_flags.bits.gamma_change) {
++                                      block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc;
++                                      block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe;
++                                      block_sequence[*num_steps].params.set_input_transfer_func_params.plane_state = current_mpc_pipe->plane_state;
++                                      block_sequence[*num_steps].func = DPP_SET_INPUT_TRANSFER_FUNC;
++                                      (*num_steps)++;
++                              }
+-                      if (dc->hwss.program_gamut_remap && current_mpc_pipe->plane_state->update_flags.bits.gamut_remap_change) {
+-                              block_sequence[*num_steps].params.program_gamut_remap_params.pipe_ctx = current_mpc_pipe;
+-                              block_sequence[*num_steps].func = DPP_PROGRAM_GAMUT_REMAP;
+-                              (*num_steps)++;
+-                      }
+-                      if (current_mpc_pipe->plane_state->update_flags.bits.input_csc_change) {
+-                              block_sequence[*num_steps].params.setup_dpp_params.pipe_ctx = current_mpc_pipe;
+-                              block_sequence[*num_steps].func = DPP_SETUP_DPP;
+-                              (*num_steps)++;
+-                      }
+-                      if (current_mpc_pipe->plane_state->update_flags.bits.coeff_reduction_change) {
+-                              block_sequence[*num_steps].params.program_bias_and_scale_params.pipe_ctx = current_mpc_pipe;
+-                              block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE;
+-                              (*num_steps)++;
++                              if (dc->hwss.program_gamut_remap && current_mpc_pipe->plane_state->update_flags.bits.gamut_remap_change) {
++                                      block_sequence[*num_steps].params.program_gamut_remap_params.pipe_ctx = current_mpc_pipe;
++                                      block_sequence[*num_steps].func = DPP_PROGRAM_GAMUT_REMAP;
++                                      (*num_steps)++;
++                              }
++                              if (current_mpc_pipe->plane_state->update_flags.bits.input_csc_change) {
++                                      block_sequence[*num_steps].params.setup_dpp_params.pipe_ctx = current_mpc_pipe;
++                                      block_sequence[*num_steps].func = DPP_SETUP_DPP;
++                                      (*num_steps)++;
++                              }
++                              if (current_mpc_pipe->plane_state->update_flags.bits.coeff_reduction_change) {
++                                      block_sequence[*num_steps].params.program_bias_and_scale_params.pipe_ctx = current_mpc_pipe;
++                                      block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE;
++                                      (*num_steps)++;
++                              }
+                       }
+                       if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) {
+                               block_sequence[*num_steps].params.set_output_transfer_func_params.dc = dc;
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+index 2532ad410cb56..456e19e0d415c 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+@@ -2283,6 +2283,9 @@ void dcn20_post_unlock_program_front_end(
+               }
+       }
++      if (!hwseq)
++              return;
++
+       /* P-State support transitions:
+        * Natural -> FPO:              P-State disabled in prepare, force disallow anytime is safe
+        * FPO -> Natural:              Unforce anytime after FW disable is safe (P-State will assert naturally)
+@@ -2290,7 +2293,7 @@ void dcn20_post_unlock_program_front_end(
+        * FPO -> Unsupported:  P-State disabled in prepare, unforce disallow anytime is safe
+        * FPO <-> SubVP:               Force disallow is maintained on the FPO / SubVP pipes
+        */
+-      if (hwseq && hwseq->funcs.update_force_pstate)
++      if (hwseq->funcs.update_force_pstate)
+               dc->hwseq->funcs.update_force_pstate(dc, context);
+       /* Only program the MALL registers after all the main and phantom pipes
+@@ -2529,6 +2532,9 @@ bool dcn20_wait_for_blank_complete(
+ {
+       int counter;
++      if (!opp)
++              return false;
++
+       for (counter = 0; counter < 1000; counter++) {
+               if (!opp->funcs->dpg_is_pending(opp))
+                       break;
+diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+index 555c1c484cfdd..df3781081da7a 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
++++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+@@ -804,8 +804,11 @@ bool dp_set_test_pattern(
+                       break;
+               }
++              if (!pipe_ctx->stream)
++                      return false;
++
+               if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
+-                      if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
++                      if (should_use_dmub_lock(pipe_ctx->stream->link)) {
+                               union dmub_hw_lock_flags hw_locks = { 0 };
+                               struct dmub_hw_lock_inst_flags inst_flags = { 0 };
+diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
+index b76737b7b9e41..3e47a6735912a 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
++++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
+@@ -74,7 +74,10 @@ void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx)
+       struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link);
+       struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
+-      if (stream_enc && stream_enc->funcs->disable_fifo)
++      if (!stream_enc)
++              return;
++
++      if (stream_enc->funcs->disable_fifo)
+               stream_enc->funcs->disable_fifo(stream_enc);
+       if (stream_enc->funcs->set_input_mode)
+               stream_enc->funcs->set_input_mode(stream_enc, 0);
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
+index 88afb2a30eef5..162856c523e40 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
+@@ -1067,7 +1067,10 @@ static void bw_calcs_data_update_from_pplib(struct dc *dc)
+       struct dm_pp_clock_levels clks = {0};
+       int memory_type_multiplier = MEMORY_TYPE_MULTIPLIER_CZ;
+-      if (dc->bw_vbios && dc->bw_vbios->memory_type == bw_def_hbm)
++      if (!dc->bw_vbios)
++              return;
++
++      if (dc->bw_vbios->memory_type == bw_def_hbm)
+               memory_type_multiplier = MEMORY_TYPE_HBM;
+       /*do system clock  TODO PPLIB: after PPLIB implement,
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+index 969658313fd65..a43ffa53890af 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+@@ -1651,6 +1651,9 @@ static void dcn32_enable_phantom_plane(struct dc *dc,
+               else
+                       phantom_plane = dc_state_create_phantom_plane(dc, context, curr_pipe->plane_state);
++              if (!phantom_plane)
++                      continue;
++
+               memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address));
+               memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality,
+                               sizeof(phantom_plane->scaling_quality));
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
+index d184105ce2b3e..47c8a9fbe7546 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
+@@ -218,12 +218,12 @@ bool dcn32_is_center_timing(struct pipe_ctx *pipe)
+                               pipe->stream->timing.v_addressable != pipe->stream->src.height) {
+                       is_center_timing = true;
+               }
+-      }
+-      if (pipe->plane_state) {
+-              if (pipe->stream->timing.v_addressable != pipe->plane_state->dst_rect.height &&
+-                              pipe->stream->timing.v_addressable != pipe->plane_state->src_rect.height) {
+-                      is_center_timing = true;
++              if (pipe->plane_state) {
++                      if (pipe->stream->timing.v_addressable != pipe->plane_state->dst_rect.height &&
++                                      pipe->stream->timing.v_addressable != pipe->plane_state->src_rect.height) {
++                              is_center_timing = true;
++                      }
+               }
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-check-null-pointers-before-used.patch b/queue-6.11/drm-amd-display-check-null-pointers-before-used.patch
new file mode 100644 (file)
index 0000000..d1427a4
--- /dev/null
@@ -0,0 +1,187 @@
+From ee1a341c3a8d01911dfd278f07cacf151b2fc7c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jun 2024 10:35:52 -0600
+Subject: drm/amd/display: Check null pointers before used
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit be1fb44389ca3038ad2430dac4234669bc177ee3 ]
+
+[WHAT & HOW]
+Poniters, such as dc->clk_mgr, are null checked previously in the same
+function, so Coverity warns "implies that "dc->clk_mgr" might be null".
+As a result, these pointers need to be checked when used again.
+
+This fixes 10 FORWARD_NULL issues reported by Coverity.
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c    | 2 +-
+ drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c    | 3 ++-
+ drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c    | 3 ++-
+ drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 5 +++--
+ drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c   | 4 ++--
+ drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c   | 4 ++--
+ drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c   | 8 ++++----
+ .../amd/display/dc/link/protocols/link_dp_capability.c    | 2 +-
+ 8 files changed, 17 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
+index 78df96882d6ec..f8409453434c1 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
+@@ -195,7 +195,7 @@ void dce11_pplib_apply_display_requirements(
+        * , then change minimum memory clock based on real-time bandwidth
+        * limitation.
+        */
+-      if ((dc->ctx->asic_id.chip_family == FAMILY_AI) &&
++      if (dc->bw_vbios && (dc->ctx->asic_id.chip_family == FAMILY_AI) &&
+            ASICREV_IS_VEGA20_P(dc->ctx->asic_id.hw_internal_rev) && (context->stream_count >= 2)) {
+               pp_display_cfg->min_memory_clock_khz = max(pp_display_cfg->min_memory_clock_khz,
+                                                          (uint32_t) div64_s64(
+diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c
+index bf399819ca800..22ac2b7e49aea 100644
+--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c
++++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c
+@@ -749,7 +749,8 @@ bool hubp1_is_flip_pending(struct hubp *hubp)
+       if (flip_pending)
+               return true;
+-      if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part)
++      if (hubp &&
++          earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part)
+               return true;
+       return false;
+diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c
+index 6bba020ad6fbf..0637e4c552d8a 100644
+--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c
++++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c
+@@ -927,7 +927,8 @@ bool hubp2_is_flip_pending(struct hubp *hubp)
+       if (flip_pending)
+               return true;
+-      if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part)
++      if (hubp &&
++          earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part)
+               return true;
+       return false;
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+index fc0d2077aaec4..96371dac72fc1 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+@@ -950,7 +950,7 @@ void dce110_edp_backlight_control(
+ {
+       struct dc_context *ctx = link->ctx;
+       struct bp_transmitter_control cntl = { 0 };
+-      uint8_t pwrseq_instance;
++      uint8_t pwrseq_instance = 0;
+       unsigned int pre_T11_delay = OLED_PRE_T11_DELAY;
+       unsigned int post_T7_delay = OLED_POST_T7_DELAY;
+@@ -1003,7 +1003,8 @@ void dce110_edp_backlight_control(
+        */
+       /* dc_service_sleep_in_milliseconds(50); */
+               /*edp 1.2*/
+-      pwrseq_instance = link->panel_cntl->pwrseq_inst;
++      if (link->panel_cntl)
++              pwrseq_instance = link->panel_cntl->pwrseq_inst;
+       if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) {
+               if (!link->dc->config.edp_no_power_sequencing)
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+index 1d2be574f6680..83942abd08e84 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+@@ -1554,7 +1554,7 @@ void dcn10_init_hw(struct dc *dc)
+               dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
+       /* Align bw context with hw config when system resume. */
+-      if (dc->clk_mgr->clks.dispclk_khz != 0 && dc->clk_mgr->clks.dppclk_khz != 0) {
++      if (dc->clk_mgr && dc->clk_mgr->clks.dispclk_khz != 0 && dc->clk_mgr->clks.dppclk_khz != 0) {
+               dc->current_state->bw_ctx.bw.dcn.clk.dispclk_khz = dc->clk_mgr->clks.dispclk_khz;
+               dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz = dc->clk_mgr->clks.dppclk_khz;
+       }
+@@ -1674,7 +1674,7 @@ void dcn10_init_hw(struct dc *dc)
+               REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+       }
+-      if (dc->clk_mgr->funcs->notify_wm_ranges)
++      if (dc->clk_mgr && dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+index 746c522adf84c..3d4b31bd99469 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+@@ -256,10 +256,10 @@ void dcn31_init_hw(struct dc *dc)
+       if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
+               dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
+-      if (dc->clk_mgr->funcs->notify_wm_ranges)
++      if (dc->clk_mgr && dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+-      if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
++      if (dc->clk_mgr && dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
+               dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
+       if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+index 80db40787e019..12a39dbc35419 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+@@ -235,7 +235,7 @@ void dcn35_init_hw(struct dc *dc)
+       if (hws->funcs.enable_power_gating_plane)
+               hws->funcs.enable_power_gating_plane(dc->hwseq, true);
+ */
+-      if (res_pool->hubbub->funcs->dchubbub_init)
++      if (res_pool->hubbub && res_pool->hubbub->funcs->dchubbub_init)
+               res_pool->hubbub->funcs->dchubbub_init(dc->res_pool->hubbub);
+       /* If taking control over from VBIOS, we may want to optimize our first
+        * mode set, so we need to skip powering down pipes until we know which
+@@ -328,10 +328,10 @@ void dcn35_init_hw(struct dc *dc)
+       if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
+               dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
+-      if (dc->clk_mgr->funcs->notify_wm_ranges)
++      if (dc->clk_mgr && dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+-      if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
++      if (dc->clk_mgr && dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
+               dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
+@@ -1054,7 +1054,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
+               if (pipe_ctx->plane_res.hubp)
+                       update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->plane_res.hubp->inst] = false;
+-              if (pipe_ctx->plane_res.dpp)
++              if (pipe_ctx->plane_res.dpp && pipe_ctx->plane_res.hubp)
+                       update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->plane_res.hubp->inst] = false;
+               if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp)
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+index 46bb7a855bc21..60015e94c4aa8 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+@@ -2254,7 +2254,7 @@ bool dp_verify_link_cap_with_retries(
+               memset(&link->verified_link_cap, 0,
+                               sizeof(struct dc_link_settings));
+-              if (!link_detect_connection_type(link, &type) || type == dc_connection_none) {
++              if (link->link_enc && (!link_detect_connection_type(link, &type) || type == dc_connection_none)) {
+                       link->verified_link_cap = fail_safe_link_settings;
+                       break;
+               } else if (dp_verify_link_cap(link, known_limit_link_setting, &fail_count)) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-check-null-pointers-before-using-dc-.patch b/queue-6.11/drm-amd-display-check-null-pointers-before-using-dc-.patch
new file mode 100644 (file)
index 0000000..01774f7
--- /dev/null
@@ -0,0 +1,46 @@
+From f73a9587ac5565b20c9c8d029d6eca88419c8545 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 15:29:09 -0600
+Subject: drm/amd/display: Check null pointers before using dc->clk_mgr
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 95d9e0803e51d5a24276b7643b244c7477daf463 ]
+
+[WHY & HOW]
+dc->clk_mgr is null checked previously in the same function, indicating
+it might be null.
+
+Passing "dc" to "dc->hwss.apply_idle_power_optimizations", which
+dereferences null "dc->clk_mgr". (The function pointer resolves to
+"dcn35_apply_idle_power_optimizations".)
+
+This fixes 1 FORWARD_NULL issue reported by Coverity.
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index 9e7ba846e032b..81fab62ef38eb 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -5383,7 +5383,8 @@ void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const
+       if (allow == dc->idle_optimizations_allowed)
+               return;
+-      if (dc->hwss.apply_idle_power_optimizations && dc->hwss.apply_idle_power_optimizations(dc, allow))
++      if (dc->hwss.apply_idle_power_optimizations && dc->clk_mgr != NULL &&
++          dc->hwss.apply_idle_power_optimizations(dc, allow))
+               dc->idle_optimizations_allowed = allow;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-check-null-pointers-before-using-the.patch b/queue-6.11/drm-amd-display-check-null-pointers-before-using-the.patch
new file mode 100644 (file)
index 0000000..cd96e59
--- /dev/null
@@ -0,0 +1,66 @@
+From 141b6a8eff0dd460953aa0c0f9c2f626ee051e22 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jun 2024 17:38:16 -0600
+Subject: drm/amd/display: Check null pointers before using them
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 1ff12bcd7deaeed25efb5120433c6a45dd5504a8 ]
+
+[WHAT & HOW]
+These pointers are null checked previously in the same function,
+indicating they might be null as reported by Coverity. As a result,
+they need to be checked when used again.
+
+This fixes 3 FORWARD_NULL issue reported by Coverity.
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index f6cbff0ed6f94..188d10820654a 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -7275,6 +7275,9 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
+       int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8;
+       enum dc_status dc_result = DC_OK;
++      if (!dm_state)
++              return NULL;
++
+       do {
+               stream = create_stream_for_sink(connector, drm_mode,
+                                               dm_state, old_stream,
+@@ -9382,7 +9385,7 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
+               if (acrtc)
+                       old_crtc_state = drm_atomic_get_old_crtc_state(state, &acrtc->base);
+-              if (!acrtc->wb_enabled)
++              if (!acrtc || !acrtc->wb_enabled)
+                       continue;
+               dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
+@@ -9786,9 +9789,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
+                       DRM_INFO("[HDCP_DM] hdcp_update_display enable_encryption = %x\n", enable_encryption);
+-                      hdcp_update_display(
+-                              adev->dm.hdcp_workqueue, aconnector->dc_link->link_index, aconnector,
+-                              new_con_state->hdcp_content_type, enable_encryption);
++                      if (aconnector->dc_link)
++                              hdcp_update_display(
++                                      adev->dm.hdcp_workqueue, aconnector->dc_link->link_index, aconnector,
++                                      new_con_state->hdcp_content_type, enable_encryption);
+               }
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-check-phantom_stream-before-it-is-us.patch b/queue-6.11/drm-amd-display-check-phantom_stream-before-it-is-us.patch
new file mode 100644 (file)
index 0000000..d88e707
--- /dev/null
@@ -0,0 +1,41 @@
+From 53053df42bd1d5e92e8d116882a4cc231a3b022d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jun 2024 20:23:41 -0600
+Subject: drm/amd/display: Check phantom_stream before it is used
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 3718a619a8c0a53152e76bb6769b6c414e1e83f4 ]
+
+dcn32_enable_phantom_stream can return null, so returned value
+must be checked before used.
+
+This fixes 1 NULL_RETURNS issue reported by Coverity.
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+index 6e2a08a9572b8..8bacff23c3563 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+@@ -1720,6 +1720,9 @@ void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context,
+       // be a valid candidate for SubVP (i.e. has a plane, stream, doesn't
+       // already have phantom pipe assigned, etc.) by previous checks.
+       phantom_stream = dcn32_enable_phantom_stream(dc, context, pipes, pipe_cnt, index);
++      if (!phantom_stream)
++              return;
++
+       dcn32_enable_phantom_plane(dc, context, phantom_stream, index);
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-check-stream-before-comparing-them.patch b/queue-6.11/drm-amd-display-check-stream-before-comparing-them.patch
new file mode 100644 (file)
index 0000000..a15e2f8
--- /dev/null
@@ -0,0 +1,41 @@
+From 8c3677ef8aafdcde0295432b04ec4e8045f11fe5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jun 2024 20:05:14 -0600
+Subject: drm/amd/display: Check stream before comparing them
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 35ff747c86767937ee1e0ca987545b7eed7a0810 ]
+
+[WHAT & HOW]
+amdgpu_dm can pass a null stream to dc_is_stream_unchanged. It is
+necessary to check for null before dereferencing them.
+
+This fixes 1 FORWARD_NULL issue reported by Coverity.
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index 67794497457d3..913adca531fc4 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -3241,6 +3241,8 @@ static bool are_stream_backends_same(
+ bool dc_is_stream_unchanged(
+       struct dc_stream_state *old_stream, struct dc_stream_state *stream)
+ {
++      if (!old_stream || !stream)
++              return false;
+       if (!are_stream_backends_same(old_stream, stream))
+               return false;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-check-stream_status-before-it-is-use.patch b/queue-6.11/drm-amd-display-check-stream_status-before-it-is-use.patch
new file mode 100644 (file)
index 0000000..af5a1eb
--- /dev/null
@@ -0,0 +1,41 @@
+From aac8dbc5ba019857ded286b21cce15d0b9c0675d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jul 2024 10:37:28 -0600
+Subject: drm/amd/display: Check stream_status before it is used
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 58a8ee96f84d2c21abb85ad8c22d2bbdf59bd7a9 ]
+
+[WHAT & HOW]
+dc_state_get_stream_status can return null, and therefore null must be
+checked before stream_status is used.
+
+This fixes 1 NULL_RETURNS issue reported by Coverity.
+
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index 81fab62ef38eb..9e05d77453ac3 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -3739,7 +3739,7 @@ static void commit_planes_for_stream_fast(struct dc *dc,
+                               surface_count,
+                               stream,
+                               context);
+-      } else {
++      } else if (stream_status) {
+               build_dmub_cmd_list(dc,
+                               srf_updates,
+                               surface_count,
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-deallocate-dml-memory-if-allocation-.patch b/queue-6.11/drm-amd-display-deallocate-dml-memory-if-allocation-.patch
new file mode 100644 (file)
index 0000000..37278f9
--- /dev/null
@@ -0,0 +1,53 @@
+From 562a5f58d9d980094abe80ac9b8a8d278960379d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jun 2024 15:09:06 -0400
+Subject: drm/amd/display: Deallocate DML memory if allocation fails
+
+From: Chris Park <chris.park@amd.com>
+
+[ Upstream commit 892abca6877a96c9123bb1c010cafccdf8ca1b75 ]
+
+[Why]
+When DC state create DML memory allocation fails, memory is not
+deallocated subsequently, resulting in uninitialized structure
+that is not NULL.
+
+[How]
+Deallocate memory if DML memory allocation fails.
+
+Reviewed-by: Joshua Aberback <joshua.aberback@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Chris Park <chris.park@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_state.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+index e990346e51f67..665157f8d4cbe 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+@@ -211,10 +211,16 @@ struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *p
+ #ifdef CONFIG_DRM_AMD_DC_FP
+       if (dc->debug.using_dml2) {
+               dml2_opt->use_clock_dc_limits = false;
+-              dml2_create(dc, dml2_opt, &state->bw_ctx.dml2);
++              if (!dml2_create(dc, dml2_opt, &state->bw_ctx.dml2)) {
++                      dc_state_release(state);
++                      return NULL;
++              }
+               dml2_opt->use_clock_dc_limits = true;
+-              dml2_create(dc, dml2_opt, &state->bw_ctx.dml2_dc_power_source);
++              if (!dml2_create(dc, dml2_opt, &state->bw_ctx.dml2_dc_power_source)) {
++                      dc_state_release(state);
++                      return NULL;
++              }
+       }
+ #endif
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-fix-a-ubsan-warning-in-dml2.1.patch b/queue-6.11/drm-amd-display-fix-a-ubsan-warning-in-dml2.1.patch
new file mode 100644 (file)
index 0000000..9eb3a42
--- /dev/null
@@ -0,0 +1,186 @@
+From 1f0aef4ac05d68a63bf70c8ed3fda66b01218a8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jul 2024 14:10:58 -0400
+Subject: drm/amd/display: fix a UBSAN warning in DML2.1
+
+From: Aurabindo Pillai <aurabindo.pillai@amd.com>
+
+[ Upstream commit eaf3adb8faab611ba57594fa915893fc93a7788c ]
+
+When programming phantom pipe, since cursor_width is explicity set to 0,
+this causes calculation logic to trigger overflow for an unsigned int
+triggering the kernel's UBSAN check as below:
+
+[   40.962845] UBSAN: shift-out-of-bounds in /tmp/amd.EfpumTkO/amd/amdgpu/../display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c:3312:34
+[   40.962849] shift exponent 4294967170 is too large for 32-bit type 'unsigned int'
+[   40.962852] CPU: 1 PID: 1670 Comm: gnome-shell Tainted: G        W  OE      6.5.0-41-generic #41~22.04.2-Ubuntu
+[   40.962854] Hardware name: Gigabyte Technology Co., Ltd. X670E AORUS PRO X/X670E AORUS PRO X, BIOS F21 01/10/2024
+[   40.962856] Call Trace:
+[   40.962857]  <TASK>
+[   40.962860]  dump_stack_lvl+0x48/0x70
+[   40.962870]  dump_stack+0x10/0x20
+[   40.962872]  __ubsan_handle_shift_out_of_bounds+0x1ac/0x360
+[   40.962878]  calculate_cursor_req_attributes.cold+0x1b/0x28 [amdgpu]
+[   40.963099]  dml_core_mode_support+0x6b91/0x16bc0 [amdgpu]
+[   40.963327]  ? srso_alias_return_thunk+0x5/0x7f
+[   40.963331]  ? CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport+0x18b8/0x2790 [amdgpu]
+[   40.963534]  ? srso_alias_return_thunk+0x5/0x7f
+[   40.963536]  ? dml_core_mode_support+0xb3db/0x16bc0 [amdgpu]
+[   40.963730]  dml2_core_calcs_mode_support_ex+0x2c/0x90 [amdgpu]
+[   40.963906]  ? srso_alias_return_thunk+0x5/0x7f
+[   40.963909]  ? dml2_core_calcs_mode_support_ex+0x2c/0x90 [amdgpu]
+[   40.964078]  core_dcn4_mode_support+0x72/0xbf0 [amdgpu]
+[   40.964247]  dml2_top_optimization_perform_optimization_phase+0x1d3/0x2a0 [amdgpu]
+[   40.964420]  dml2_build_mode_programming+0x23d/0x750 [amdgpu]
+[   40.964587]  dml21_validate+0x274/0x770 [amdgpu]
+[   40.964761]  ? srso_alias_return_thunk+0x5/0x7f
+[   40.964763]  ? resource_append_dpp_pipes_for_plane_composition+0x27c/0x3b0 [amdgpu]
+[   40.964942]  dml2_validate+0x504/0x750 [amdgpu]
+[   40.965117]  ? dml21_copy+0x95/0xb0 [amdgpu]
+[   40.965291]  ? srso_alias_return_thunk+0x5/0x7f
+[   40.965295]  dcn401_validate_bandwidth+0x4e/0x70 [amdgpu]
+[   40.965491]  update_planes_and_stream_state+0x38d/0x5c0 [amdgpu]
+[   40.965672]  update_planes_and_stream_v3+0x52/0x1e0 [amdgpu]
+[   40.965845]  ? srso_alias_return_thunk+0x5/0x7f
+[   40.965849]  dc_update_planes_and_stream+0x71/0xb0 [amdgpu]
+
+Fix this by adding a guard for checking cursor width before triggering
+the size calculation.
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../src/dml2_core/dml2_core_dcn4_calcs.c      | 93 ++++++++++---------
+ 1 file changed, 49 insertions(+), 44 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+index 6f4026e396e09..c40cd5d634568 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+@@ -7231,10 +7231,9 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
+       /* Cursor Support Check */
+       mode_lib->ms.support.CursorSupport = true;
+       for (k = 0; k < mode_lib->ms.num_active_planes; k++) {
+-              if (display_cfg->plane_descriptors[k].cursor.cursor_width > 0.0) {
+-                      if (display_cfg->plane_descriptors[k].cursor.cursor_bpp == 64 && mode_lib->ip.cursor_64bpp_support == false) {
++              if (display_cfg->plane_descriptors[k].cursor.num_cursors > 0) {
++                      if (display_cfg->plane_descriptors[k].cursor.cursor_bpp == 64 && mode_lib->ip.cursor_64bpp_support == false)
+                               mode_lib->ms.support.CursorSupport = false;
+-                      }
+               }
+       }
+@@ -8091,27 +8090,31 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
+       for (k = 0; k < mode_lib->ms.num_active_planes; ++k) {
+               double line_time_us = (double)display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.h_total / ((double)display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.pixel_clock_khz / 1000);
+               bool cursor_not_enough_urgent_latency_hiding = 0;
+-              calculate_cursor_req_attributes(
+-                      display_cfg->plane_descriptors[k].cursor.cursor_width,
+-                      display_cfg->plane_descriptors[k].cursor.cursor_bpp,
+-                      // output
+-                      &s->cursor_lines_per_chunk[k],
+-                      &s->cursor_bytes_per_line[k],
+-                      &s->cursor_bytes_per_chunk[k],
+-                      &s->cursor_bytes[k]);
+-
+-              calculate_cursor_urgent_burst_factor(
+-                      mode_lib->ip.cursor_buffer_size,
+-                      display_cfg->plane_descriptors[k].cursor.cursor_width,
+-                      s->cursor_bytes_per_chunk[k],
+-                      s->cursor_lines_per_chunk[k],
+-                      line_time_us,
+-                      mode_lib->ms.UrgLatency,
++              if (display_cfg->plane_descriptors[k].cursor.num_cursors > 0) {
++                      calculate_cursor_req_attributes(
++                              display_cfg->plane_descriptors[k].cursor.cursor_width,
++                              display_cfg->plane_descriptors[k].cursor.cursor_bpp,
++
++                              // output
++                              &s->cursor_lines_per_chunk[k],
++                              &s->cursor_bytes_per_line[k],
++                              &s->cursor_bytes_per_chunk[k],
++                              &s->cursor_bytes[k]);
++
++                      calculate_cursor_urgent_burst_factor(
++                              mode_lib->ip.cursor_buffer_size,
++                              display_cfg->plane_descriptors[k].cursor.cursor_width,
++                              s->cursor_bytes_per_chunk[k],
++                              s->cursor_lines_per_chunk[k],
++                              line_time_us,
++                              mode_lib->ms.UrgLatency,
++
++                              // output
++                              &mode_lib->ms.UrgentBurstFactorCursor[k],
++                              &cursor_not_enough_urgent_latency_hiding);
++              }
+-                      // output
+-                      &mode_lib->ms.UrgentBurstFactorCursor[k],
+-                      &cursor_not_enough_urgent_latency_hiding);
+               mode_lib->ms.UrgentBurstFactorCursorPre[k] = mode_lib->ms.UrgentBurstFactorCursor[k];
+ #ifdef __DML_VBA_DEBUG__
+@@ -10592,31 +10595,33 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex
+       for (k = 0; k < s->num_active_planes; ++k) {
+               bool cursor_not_enough_urgent_latency_hiding = 0;
+-              double line_time_us;
++              double line_time_us = 0.0;
+-              calculate_cursor_req_attributes(
+-                      display_cfg->plane_descriptors[k].cursor.cursor_width,
+-                      display_cfg->plane_descriptors[k].cursor.cursor_bpp,
++              line_time_us = display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.h_total /
++                      ((double)display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.pixel_clock_khz / 1000);
++              if (display_cfg->plane_descriptors[k].cursor.num_cursors > 0) {
++                      calculate_cursor_req_attributes(
++                              display_cfg->plane_descriptors[k].cursor.cursor_width,
++                              display_cfg->plane_descriptors[k].cursor.cursor_bpp,
+-                      // output
+-                      &s->cursor_lines_per_chunk[k],
+-                      &s->cursor_bytes_per_line[k],
+-                      &s->cursor_bytes_per_chunk[k],
+-                      &s->cursor_bytes[k]);
+-
+-              line_time_us = display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.h_total / ((double)display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.pixel_clock_khz / 1000);
+-
+-              calculate_cursor_urgent_burst_factor(
+-                      mode_lib->ip.cursor_buffer_size,
+-                      display_cfg->plane_descriptors[k].cursor.cursor_width,
+-                      s->cursor_bytes_per_chunk[k],
+-                      s->cursor_lines_per_chunk[k],
+-                      line_time_us,
+-                      mode_lib->mp.UrgentLatency,
++                              // output
++                              &s->cursor_lines_per_chunk[k],
++                              &s->cursor_bytes_per_line[k],
++                              &s->cursor_bytes_per_chunk[k],
++                              &s->cursor_bytes[k]);
++
++                      calculate_cursor_urgent_burst_factor(
++                              mode_lib->ip.cursor_buffer_size,
++                              display_cfg->plane_descriptors[k].cursor.cursor_width,
++                              s->cursor_bytes_per_chunk[k],
++                              s->cursor_lines_per_chunk[k],
++                              line_time_us,
++                              mode_lib->mp.UrgentLatency,
+-                      // output
+-                      &mode_lib->mp.UrgentBurstFactorCursor[k],
+-                      &cursor_not_enough_urgent_latency_hiding);
++                              // output
++                              &mode_lib->mp.UrgentBurstFactorCursor[k],
++                              &cursor_not_enough_urgent_latency_hiding);
++              }
+               mode_lib->mp.UrgentBurstFactorCursorPre[k] = mode_lib->mp.UrgentBurstFactorCursor[k];
+               CalculateUrgentBurstFactor(
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-fix-double-free-issue-during-amdgpu-.patch b/queue-6.11/drm-amd-display-fix-double-free-issue-during-amdgpu-.patch
new file mode 100644 (file)
index 0000000..be8b467
--- /dev/null
@@ -0,0 +1,79 @@
+From be7a65a82f254df53ba17965b26e68ef87f1dbd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Aug 2024 18:45:22 -0400
+Subject: drm/amd/display: fix double free issue during amdgpu module unload
+
+From: Tim Huang <tim.huang@amd.com>
+
+[ Upstream commit 20b5a8f9f4670a8503aa9fa95ca632e77c6bf55d ]
+
+Flexible endpoints use DIGs from available inflexible endpoints,
+so only the encoders of inflexible links need to be freed.
+Otherwise, a double free issue may occur when unloading the
+amdgpu module.
+
+[  279.190523] RIP: 0010:__slab_free+0x152/0x2f0
+[  279.190577] Call Trace:
+[  279.190580]  <TASK>
+[  279.190582]  ? show_regs+0x69/0x80
+[  279.190590]  ? die+0x3b/0x90
+[  279.190595]  ? do_trap+0xc8/0xe0
+[  279.190601]  ? do_error_trap+0x73/0xa0
+[  279.190605]  ? __slab_free+0x152/0x2f0
+[  279.190609]  ? exc_invalid_op+0x56/0x70
+[  279.190616]  ? __slab_free+0x152/0x2f0
+[  279.190642]  ? asm_exc_invalid_op+0x1f/0x30
+[  279.190648]  ? dcn10_link_encoder_destroy+0x19/0x30 [amdgpu]
+[  279.191096]  ? __slab_free+0x152/0x2f0
+[  279.191102]  ? dcn10_link_encoder_destroy+0x19/0x30 [amdgpu]
+[  279.191469]  kfree+0x260/0x2b0
+[  279.191474]  dcn10_link_encoder_destroy+0x19/0x30 [amdgpu]
+[  279.191821]  link_destroy+0xd7/0x130 [amdgpu]
+[  279.192248]  dc_destruct+0x90/0x270 [amdgpu]
+[  279.192666]  dc_destroy+0x19/0x40 [amdgpu]
+[  279.193020]  amdgpu_dm_fini+0x16e/0x200 [amdgpu]
+[  279.193432]  dm_hw_fini+0x26/0x40 [amdgpu]
+[  279.193795]  amdgpu_device_fini_hw+0x24c/0x400 [amdgpu]
+[  279.194108]  amdgpu_driver_unload_kms+0x4f/0x70 [amdgpu]
+[  279.194436]  amdgpu_pci_remove+0x40/0x80 [amdgpu]
+[  279.194632]  pci_device_remove+0x3a/0xa0
+[  279.194638]  device_remove+0x40/0x70
+[  279.194642]  device_release_driver_internal+0x1ad/0x210
+[  279.194647]  driver_detach+0x4e/0xa0
+[  279.194650]  bus_remove_driver+0x6f/0xf0
+[  279.194653]  driver_unregister+0x33/0x60
+[  279.194657]  pci_unregister_driver+0x44/0x90
+[  279.194662]  amdgpu_exit+0x19/0x1f0 [amdgpu]
+[  279.194939]  __do_sys_delete_module.isra.0+0x198/0x2f0
+[  279.194946]  __x64_sys_delete_module+0x16/0x20
+[  279.194950]  do_syscall_64+0x58/0x120
+[  279.194954]  entry_SYSCALL_64_after_hwframe+0x6e/0x76
+[  279.194980]  </TASK>
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Tim Huang <tim.huang@amd.com>
+Reviewed-by: Roman Li <roman.li@amd.com>
+Signed-off-by: Roman Li <roman.li@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/link/link_factory.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+index 8246006857b30..49d069dae29bf 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
++++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+@@ -385,7 +385,7 @@ static void link_destruct(struct dc_link *link)
+       if (link->panel_cntl)
+               link->panel_cntl->funcs->destroy(&link->panel_cntl);
+-      if (link->link_enc) {
++      if (link->link_enc && !link->is_dig_mapping_flexible) {
+               /* Update link encoder resource tracking variables. These are used for
+                * the dynamic assignment of link encoders to streams. Virtual links
+                * are not assigned encoder resources on creation.
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-fix-index-out-of-bounds-in-dcn30-col.patch b/queue-6.11/drm-amd-display-fix-index-out-of-bounds-in-dcn30-col.patch
new file mode 100644 (file)
index 0000000..e2fc6e8
--- /dev/null
@@ -0,0 +1,54 @@
+From f4db4833f8d48a535b6488a2ed0f995cd2f956fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 20 Jul 2024 18:05:20 +0530
+Subject: drm/amd/display: Fix index out of bounds in DCN30 color
+ transformation
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit d81873f9e715b72d4f8d391c8eb243946f784dfc ]
+
+This commit addresses a potential index out of bounds issue in the
+`cm3_helper_translate_curve_to_hw_format` function in the DCN30 color
+management module. The issue could occur when the index 'i' exceeds the
+number of transfer function points (TRANSFER_FUNC_POINTS).
+
+The fix adds a check to ensure 'i' is within bounds before accessing the
+transfer function points. If 'i' is out of bounds, the function returns
+false to indicate an error.
+
+drivers/gpu/drm/amd/amdgpu/../display/dc/dcn30/dcn30_cm_common.c:180 cm3_helper_translate_curve_to_hw_format() error: buffer overflow 'output_tf->tf_pts.red' 1025 <= s32max
+drivers/gpu/drm/amd/amdgpu/../display/dc/dcn30/dcn30_cm_common.c:181 cm3_helper_translate_curve_to_hw_format() error: buffer overflow 'output_tf->tf_pts.green' 1025 <= s32max
+drivers/gpu/drm/amd/amdgpu/../display/dc/dcn30/dcn30_cm_common.c:182 cm3_helper_translate_curve_to_hw_format() error: buffer overflow 'output_tf->tf_pts.blue' 1025 <= s32max
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+index edc77615d0973..0433f6b5dac78 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+@@ -177,6 +177,8 @@ bool cm3_helper_translate_curve_to_hw_format(
+                               i += increment) {
+                       if (j == hw_points)
+                               break;
++                      if (i >= TRANSFER_FUNC_POINTS)
++                              return false;
+                       rgb_resulted[j].red = output_tf->tf_pts.red[i];
+                       rgb_resulted[j].green = output_tf->tf_pts.green[i];
+                       rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-fix-index-out-of-bounds-in-dcn30-deg.patch b/queue-6.11/drm-amd-display-fix-index-out-of-bounds-in-dcn30-deg.patch
new file mode 100644 (file)
index 0000000..13ae846
--- /dev/null
@@ -0,0 +1,55 @@
+From 35eb12cd8c5bed360f8c3f4f3549aded3ebe7ddf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 20 Jul 2024 18:44:02 +0530
+Subject: drm/amd/display: Fix index out of bounds in DCN30 degamma hardware
+ format translation
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit bc50b614d59990747dd5aeced9ec22f9258991ff ]
+
+This commit addresses a potential index out of bounds issue in the
+`cm3_helper_translate_curve_to_degamma_hw_format` function in the DCN30
+color  management module. The issue could occur when the index 'i'
+exceeds the  number of transfer function points (TRANSFER_FUNC_POINTS).
+
+The fix adds a check to ensure 'i' is within bounds before accessing the
+transfer function points. If 'i' is out of bounds, the function returns
+false to indicate an error.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/dcn30/dcn30_cm_common.c:338 cm3_helper_translate_curve_to_degamma_hw_format() error: buffer overflow 'output_tf->tf_pts.red' 1025 <= s32max
+drivers/gpu/drm/amd/amdgpu/../display/dc/dcn30/dcn30_cm_common.c:339 cm3_helper_translate_curve_to_degamma_hw_format() error: buffer overflow 'output_tf->tf_pts.green' 1025 <= s32max
+drivers/gpu/drm/amd/amdgpu/../display/dc/dcn30/dcn30_cm_common.c:340 cm3_helper_translate_curve_to_degamma_hw_format() error: buffer overflow 'output_tf->tf_pts.blue' 1025 <= s32max
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+index b8327237ed441..edc77615d0973 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+@@ -335,6 +335,8 @@ bool cm3_helper_translate_curve_to_degamma_hw_format(
+                               i += increment) {
+                       if (j == hw_points - 1)
+                               break;
++                      if (i >= TRANSFER_FUNC_POINTS)
++                              return false;
+                       rgb_resulted[j].red = output_tf->tf_pts.red[i];
+                       rgb_resulted[j].green = output_tf->tf_pts.green[i];
+                       rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-fix-index-out-of-bounds-in-degamma-h.patch b/queue-6.11/drm-amd-display-fix-index-out-of-bounds-in-degamma-h.patch
new file mode 100644 (file)
index 0000000..622d5fe
--- /dev/null
@@ -0,0 +1,55 @@
+From 712caa4357dff7a3546d3c1e7a8355c4b11d5b7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 20 Jul 2024 17:48:27 +0530
+Subject: drm/amd/display: Fix index out of bounds in degamma hardware format
+ translation
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit b7e99058eb2e86aabd7a10761e76cae33d22b49f ]
+
+Fixes index out of bounds issue in
+`cm_helper_translate_curve_to_degamma_hw_format` function. The issue
+could occur when the index 'i' exceeds the number of transfer function
+points (TRANSFER_FUNC_POINTS).
+
+The fix adds a check to ensure 'i' is within bounds before accessing the
+transfer function points. If 'i' is out of bounds the function returns
+false to indicate an error.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_cm_common.c:594 cm_helper_translate_curve_to_degamma_hw_format() error: buffer overflow 'output_tf->tf_pts.red' 1025 <= s32max
+drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_cm_common.c:595 cm_helper_translate_curve_to_degamma_hw_format() error: buffer overflow 'output_tf->tf_pts.green' 1025 <= s32max
+drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_cm_common.c:596 cm_helper_translate_curve_to_degamma_hw_format() error: buffer overflow 'output_tf->tf_pts.blue' 1025 <= s32max
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
+index 0b49362f71b06..eaed5d1c398aa 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
+@@ -591,6 +591,8 @@ bool cm_helper_translate_curve_to_degamma_hw_format(
+                               i += increment) {
+                       if (j == hw_points - 1)
+                               break;
++                      if (i >= TRANSFER_FUNC_POINTS)
++                              return false;
+                       rgb_resulted[j].red = output_tf->tf_pts.red[i];
+                       rgb_resulted[j].green = output_tf->tf_pts.green[i];
+                       rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-fix-possible-overflow-in-integer-mul.patch b/queue-6.11/drm-amd-display-fix-possible-overflow-in-integer-mul.patch
new file mode 100644 (file)
index 0000000..6a0006b
--- /dev/null
@@ -0,0 +1,51 @@
+From 69f8ff349ac6a1507e265009c887581742fe3738 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jun 2024 22:09:53 -0600
+Subject: drm/amd/display: Fix possible overflow in integer multiplication
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 3f96f545f877ac59d0c967f52d760b4b2b3b9a47 ]
+
+[WHAT & HOW]
+Integer multiplies integer may overflow in context that expects an
+expression of unsigned long long (64 bits). This can be fixed by casting
+integer to unsigned long long to force 64 bits results.
+
+This fixes 2 OVERFLOW_BEFORE_WIDEN issues reported by Coverity.
+
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/display/dc/resource/dcn32/dcn32_resource_helpers.c    | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
+index 47c8a9fbe7546..f5a4e97c40ced 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
+@@ -663,7 +663,7 @@ bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context)
+                               subvp_disallow |= disallow_subvp_in_active_plus_blank(pipe);
+                               refresh_rate = (pipe->stream->timing.pix_clk_100hz * (uint64_t)100 +
+-                                      pipe->stream->timing.v_total * pipe->stream->timing.h_total - (uint64_t)1);
++                                      pipe->stream->timing.v_total * (unsigned long long)pipe->stream->timing.h_total - (uint64_t)1);
+                               refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total);
+                               refresh_rate = div_u64(refresh_rate, pipe->stream->timing.h_total);
+                       }
+@@ -724,7 +724,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
+                               subvp_disallow |= disallow_subvp_in_active_plus_blank(pipe);
+                               refresh_rate = (pipe->stream->timing.pix_clk_100hz * (uint64_t)100 +
+-                                      pipe->stream->timing.v_total * pipe->stream->timing.h_total - (uint64_t)1);
++                                      pipe->stream->timing.v_total * (unsigned long long)pipe->stream->timing.h_total - (uint64_t)1);
+                               refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total);
+                               refresh_rate = div_u64(refresh_rate, pipe->stream->timing.h_total);
+                       }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-force-enable-3dlut-dma-check-for-dcn.patch b/queue-6.11/drm-amd-display-force-enable-3dlut-dma-check-for-dcn.patch
new file mode 100644 (file)
index 0000000..27509f6
--- /dev/null
@@ -0,0 +1,89 @@
+From 937d1938414b5c9d304aba501633f5370c28d442 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jul 2024 15:54:23 -0400
+Subject: drm/amd/display: Force enable 3DLUT DMA check for dcn401 in DML
+
+From: Dillon Varone <dillon.varone@amd.com>
+
+[ Upstream commit b8dc6ca028d9a39196a3a066b9ef2d4a5eca475d ]
+
+[WHY]
+Currently TR0 (trip 0) is not properly budgeting for urgent latency in
+DML2.1. This results in overly aggressive prefetch schedules that are
+vulnerable to request return jitter, resulting in severe underflow at
+the start of the frame.
+
+[HOW]
+Forcing 3DLUT DMA check to enable causes urgent latency to be budgeted
+properly into the prefetch schedule, avoiding the vulnerability.
+
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Signed-off-by: Dillon Varone <dillon.varone@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/display/dc/dml2/dml21/dml21_translation_helper.c    | 6 ++++--
+ drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h          | 1 +
+ .../drm/amd/display/dc/resource/dcn401/dcn401_resource.c    | 1 +
+ 3 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
+index 2baaf602815ec..ef0150a258b12 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
+@@ -827,6 +827,7 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
+       if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
+               plane->tdlut.setup_for_tdlut = true;
++
+               switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.layout) {
+               case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
+               case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
+@@ -836,6 +837,7 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
+                       plane->tdlut.tdlut_addressing_mode = dml2_tdlut_simple_linear;
+                       break;
+               }
++
+               switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.size) {
+               case DC_CM2_GPU_MEM_SIZE_171717:
+                       plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
+@@ -844,8 +846,8 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
+                       //plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
+                       break;
+               }
+-      } else
+-              plane->tdlut.setup_for_tdlut = false;
++      }
++      plane->tdlut.setup_for_tdlut |= dml_ctx->config.force_tdlut_enable;
+       plane->dynamic_meta_data.enable = false;
+       plane->dynamic_meta_data.lines_before_active_required = 0;
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+index 023325e8f6e22..0f944fcfd5a5b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+@@ -236,6 +236,7 @@ struct dml2_configuration_options {
+       bool use_clock_dc_limits;
+       bool gpuvm_enable;
++      bool force_tdlut_enable;
+       struct dml2_soc_bb *bb_from_dmub;
+ };
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+index 3e76732ac0dca..ec676d269d33f 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+@@ -2099,6 +2099,7 @@ static bool dcn401_resource_construct(
+       dc->dml2_options.use_native_soc_bb_construction = true;
+       dc->dml2_options.minimize_dispclk_using_odm = true;
+       dc->dml2_options.map_dc_pipes_with_callbacks = true;
++      dc->dml2_options.force_tdlut_enable = true;
+       resource_init_common_dml2_callbacks(dc, &dc->dml2_options);
+       dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-guard-write-a-0-post_divider-value-t.patch b/queue-6.11/drm-amd-display-guard-write-a-0-post_divider-value-t.patch
new file mode 100644 (file)
index 0000000..a9b41f5
--- /dev/null
@@ -0,0 +1,39 @@
+From dfdb24a68816fcf4589b20e8b374884f52fecdc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Aug 2024 17:11:55 -0400
+Subject: drm/amd/display: guard write a 0 post_divider value to HW
+
+From: Ahmed, Muhammad <Ahmed.Ahmed@amd.com>
+
+[ Upstream commit 5d666496c24129edeb2bcb500498b87cc64e7f07 ]
+
+[why]
+post_divider_value should not be 0.
+
+Reviewed-by: Charlene Liu <charlene.liu@amd.com>
+Signed-off-by: Ahmed, Muhammad <Ahmed.Ahmed@amd.com>
+Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
+index 68cd3258f4a97..a64d8f3ec93a3 100644
+--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
+@@ -47,7 +47,8 @@ static void dccg35_trigger_dio_fifo_resync(struct dccg *dccg)
+       uint32_t dispclk_rdivider_value = 0;
+       REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value);
+-      REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
++      if (dispclk_rdivider_value != 0)
++              REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
+ }
+ static void dcn35_set_dppclk_enable(struct dccg *dccg,
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-handle-null-stream_status-in-planes_.patch b/queue-6.11/drm-amd-display-handle-null-stream_status-in-planes_.patch
new file mode 100644 (file)
index 0000000..0473b06
--- /dev/null
@@ -0,0 +1,52 @@
+From cc836f029c337a40e93a6b7a970ecd068906cbce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jul 2024 19:31:55 +0530
+Subject: drm/amd/display: Handle null 'stream_status' in
+ 'planes_changed_for_existing_stream'
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 8141f21b941710ecebe49220b69822cab3abd23d ]
+
+This commit adds a null check for 'stream_status' in the function
+'planes_changed_for_existing_stream'. Previously, the code assumed
+'stream_status' could be null, but did not handle the case where it was
+actually null. This could lead to a null pointer dereference.
+
+Reported by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_resource.c:3784 planes_changed_for_existing_stream() error: we previously assumed 'stream_status' could be null (see line 3774)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index bcb5267b5a6bc..67794497457d3 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -3771,8 +3771,10 @@ static bool planes_changed_for_existing_stream(struct dc_state *context,
+               }
+       }
+-      if (!stream_status)
++      if (!stream_status) {
+               ASSERT(0);
++              return false;
++      }
+       for (i = 0; i < set_count; i++)
+               if (set[i].stream == stream)
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-implement-bounds-check-for-stream-en.patch b/queue-6.11/drm-amd-display-implement-bounds-check-for-stream-en.patch
new file mode 100644 (file)
index 0000000..4b21339
--- /dev/null
@@ -0,0 +1,59 @@
+From f8dc84c7ce1646baacdfc562658224694a383d89 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jul 2024 21:39:57 +0530
+Subject: drm/amd/display: Implement bounds check for stream encoder creation
+ in DCN401
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit bdf606810210e8e07a0cdf1af3c467291363b295 ]
+
+'stream_enc_regs' array is an array of dcn10_stream_enc_registers
+structures. The array is initialized with four elements, corresponding
+to the four calls to stream_enc_regs() in the array initializer. This
+means that valid indices for this array are 0, 1, 2, and 3.
+
+The error message 'stream_enc_regs' 4 <= 5 below, is indicating that
+there is an attempt to access this array with an index of 5, which is
+out of bounds. This could lead to undefined behavior
+
+Here, eng_id is used as an index to access the stream_enc_regs array. If
+eng_id is 5, this would result in an out-of-bounds access on the
+stream_enc_regs array.
+
+Thus fixing Buffer overflow error in dcn401_stream_encoder_create
+
+Found by smatch:
+drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn401/dcn401_resource.c:1209 dcn401_stream_encoder_create() error: buffer overflow 'stream_enc_regs' 4 <= 5
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c    | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+index 34b02147881dd..3e76732ac0dca 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+@@ -1188,7 +1188,7 @@ static struct stream_encoder *dcn401_stream_encoder_create(
+       vpg = dcn401_vpg_create(ctx, vpg_inst);
+       afmt = dcn401_afmt_create(ctx, afmt_inst);
+-      if (!enc1 || !vpg || !afmt) {
++      if (!enc1 || !vpg || !afmt || eng_id >= ARRAY_SIZE(stream_enc_regs)) {
+               kfree(enc1);
+               kfree(vpg);
+               kfree(afmt);
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-increase-array-size-of-dummy_boolean.patch b/queue-6.11/drm-amd-display-increase-array-size-of-dummy_boolean.patch
new file mode 100644 (file)
index 0000000..029564f
--- /dev/null
@@ -0,0 +1,46 @@
+From 6fd976c7126f685a956359e3c2a125a673199dff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jul 2024 10:50:35 -0600
+Subject: drm/amd/display: Increase array size of dummy_boolean
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 6d64d39486197083497a01b39e23f2f8474b35d3 ]
+
+[WHY]
+dml2_core_shared_mode_support and dml_core_mode_support access the third
+element of dummy_boolean, i.e. hw_debug5 = &s->dummy_boolean[2], when
+dummy_boolean has size of 2. Any assignment to hw_debug5 causes an
+OVERRUN.
+
+[HOW]
+Increase dummy_boolean's array size to 3.
+
+This fixes 2 OVERRUN issues reported by Coverity.
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h        | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h
+index 1343b744eeb31..67e32a4ab0114 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h
+@@ -865,7 +865,7 @@ struct dml2_core_calcs_mode_support_locals {
+       unsigned int dpte_row_bytes_per_row_l[DML2_MAX_PLANES];
+       unsigned int dpte_row_bytes_per_row_c[DML2_MAX_PLANES];
+-      bool dummy_boolean[2];
++      bool dummy_boolean[3];
+       unsigned int dummy_integer[3];
+       unsigned int dummy_integer_array[36][DML2_MAX_PLANES];
+       enum dml2_odm_mode dummy_odm_mode[DML2_MAX_PLANES];
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-initialize-denominators-default-to-1.patch b/queue-6.11/drm-amd-display-initialize-denominators-default-to-1.patch
new file mode 100644 (file)
index 0000000..2f464e8
--- /dev/null
@@ -0,0 +1,71 @@
+From 64bd455f93cd63c6ac057a666db587c4aa6d5ebc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jun 2024 14:05:08 -0600
+Subject: drm/amd/display: Initialize denominators' default to 1
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit b995c0a6de6c74656a0c39cd57a0626351b13e3c ]
+
+[WHAT & HOW]
+Variables used as denominators and maybe not assigned to other values,
+should not be 0. Change their default to 1 so they are never 0.
+
+This fixes 10 DIVIDE_BY_ZERO issues reported by Coverity.
+
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c | 2 +-
+ drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c | 2 +-
+ .../display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c    | 4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
+index 7c56ad0f88122..e7019c95ba79e 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
+@@ -78,7 +78,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
+ static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
+ {
+-      unsigned int ret_val = 0;
++      unsigned int ret_val = 1;
+       if (source_format == dm_444_16) {
+               if (!is_chroma)
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
+index dae13f202220e..d8bfc85e5dcd0 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
+@@ -39,7 +39,7 @@
+ static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
+ {
+-      unsigned int ret_val = 0;
++      unsigned int ret_val = 1;
+       if (source_format == dm_444_16) {
+               if (!is_chroma)
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c
+index 81f0a6f19f87b..679b200319034 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared.c
+@@ -9386,8 +9386,8 @@ static void CalculateVMGroupAndRequestTimes(
+       double TimePerVMRequestVBlank[],
+       double TimePerVMRequestFlip[])
+ {
+-      unsigned int num_group_per_lower_vm_stage = 0;
+-      unsigned int num_req_per_lower_vm_stage = 0;
++      unsigned int num_group_per_lower_vm_stage = 1;
++      unsigned int num_req_per_lower_vm_stage = 1;
+ #ifdef __DML_VBA_DEBUG__
+       dml2_printf("DML::%s: NumberOfActiveSurfaces = %u\n", __func__, NumberOfActiveSurfaces);
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-initialize-get_bytes_per_element-s-d.patch b/queue-6.11/drm-amd-display-initialize-get_bytes_per_element-s-d.patch
new file mode 100644 (file)
index 0000000..6f25dac
--- /dev/null
@@ -0,0 +1,55 @@
+From bab794750563ebc5fb19840f2cca72c33e2544b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jul 2024 09:57:01 -0600
+Subject: drm/amd/display: Initialize get_bytes_per_element's default to 1
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 4067f4fa0423a89fb19a30b57231b384d77d2610 ]
+
+Variables, used as denominators and maybe not assigned to other values,
+should not be 0. bytes_per_element_y & bytes_per_element_c are
+initialized by get_bytes_per_element() which should never return 0.
+
+This fixes 10 DIVIDE_BY_ZERO issues reported by Coverity.
+
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c | 2 +-
+ .../gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c   | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
+index 3d95bfa5aca23..ae52510417280 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
+@@ -78,7 +78,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
+ static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
+ {
+-      unsigned int ret_val = 0;
++      unsigned int ret_val = 1;
+       if (source_format == dm_444_16) {
+               if (!is_chroma)
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
+index 98502a4f05672..9e1c18b90805d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
+@@ -53,7 +53,7 @@ static void calculate_ttu_cursor(
+ static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
+ {
+-      unsigned int ret_val = 0;
++      unsigned int ret_val = 1;
+       if (source_format == dm_444_16) {
+               if (!is_chroma)
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-pass-non-null-to-dcn20_validate_appl.patch b/queue-6.11/drm-amd-display-pass-non-null-to-dcn20_validate_appl.patch
new file mode 100644 (file)
index 0000000..a3349b0
--- /dev/null
@@ -0,0 +1,73 @@
+From a75198bf8875b60c1f75d67bb8d203256c97ffd2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jun 2024 11:51:27 -0600
+Subject: drm/amd/display: Pass non-null to
+ dcn20_validate_apply_pipe_split_flags
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 5559598742fb4538e4c51c48ef70563c49c2af23 ]
+
+[WHAT & HOW]
+"dcn20_validate_apply_pipe_split_flags" dereferences merge, and thus it
+cannot be a null pointer. Let's pass a valid pointer to avoid null
+dereference.
+
+This fixes 2 FORWARD_NULL issues reported by Coverity.
+
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c | 3 ++-
+ drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c | 3 ++-
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+index 5e7cfa8e8ec93..eea2b3b307cd5 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+@@ -2040,6 +2040,7 @@ bool dcn20_fast_validate_bw(
+ {
+       bool out = false;
+       int split[MAX_PIPES] = { 0 };
++      bool merge[MAX_PIPES] = { false };
+       int pipe_cnt, i, pipe_idx, vlevel;
+       ASSERT(pipes);
+@@ -2064,7 +2065,7 @@ bool dcn20_fast_validate_bw(
+       if (vlevel > context->bw_ctx.dml.soc.num_states)
+               goto validate_fail;
+-      vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, NULL);
++      vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge);
+       /*initialize pipe_just_split_from to invalid idx*/
+       for (i = 0; i < MAX_PIPES; i++)
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
+index 8663cbc3d1cf5..347e6aaea582f 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
+@@ -774,6 +774,7 @@ bool dcn21_fast_validate_bw(struct dc *dc,
+ {
+       bool out = false;
+       int split[MAX_PIPES] = { 0 };
++      bool merge[MAX_PIPES] = { false };
+       int pipe_cnt, i, pipe_idx, vlevel;
+       ASSERT(pipes);
+@@ -816,7 +817,7 @@ bool dcn21_fast_validate_bw(struct dc *dc,
+                       goto validate_fail;
+       }
+-      vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, NULL);
++      vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge);
+       for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-underflow-seen-on-dcn401-egpu.patch b/queue-6.11/drm-amd-display-underflow-seen-on-dcn401-egpu.patch
new file mode 100644 (file)
index 0000000..d9b65e0
--- /dev/null
@@ -0,0 +1,65 @@
+From 346998b7832e4266196a40cd120d1bf131d53af0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jul 2024 13:39:09 -0400
+Subject: drm/amd/display: Underflow Seen on DCN401 eGPU
+
+From: Daniel Sa <Daniel.Sa@amd.com>
+
+[ Upstream commit ca0fb243c3bb53dbbd71d16c76f319bf923ee3d4 ]
+
+[WHY]
+In dcn401 we read clock values before FW is loaded. These incorrect
+values cause the driver to believe that we are running higher clocks
+than what we actually have. This then causes corruption/underflow for
+the eGPU.
+
+[HOW]
+When new values are read from HW, update internal structures to
+propagate the new/correct value. Fixes issue
+
+Signed-off-by: Daniel Sa <Daniel.Sa@amd.com>
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+index 324e77ceaf1cf..537a24ec74c85 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+@@ -221,6 +221,7 @@ void dcn401_init_hw(struct dc *dc)
+       int edp_num;
+       uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
++      int current_dchub_ref_freq = 0;
+       if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
+               dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
+@@ -264,6 +265,8 @@ void dcn401_init_hw(struct dc *dc)
+                                       dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+                                       &res_pool->ref_clocks.dccg_ref_clock_inKhz);
++                      current_dchub_ref_freq = res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
++
+                       (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+                                       res_pool->ref_clocks.dccg_ref_clock_inKhz,
+                                       &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+@@ -436,8 +439,9 @@ void dcn401_init_hw(struct dc *dc)
+               dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0;
+               dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
+               dc->debug.fams2_config.bits.enable &= dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver == 2;
+-              if (!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box) {
+-                      /* update bounding box if FAMS2 disabled */
++              if ((!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box)
++                      || res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq) {
++                      /* update bounding box if FAMS2 disabled, or if dchub clk has changed */
+                       if (dc->clk_mgr)
+                               dc->res_pool->funcs->update_bw_bounding_box(dc,
+                                                                           dc->clk_mgr->bw_params);
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-unlock-pipes-based-on-det-allocation.patch b/queue-6.11/drm-amd-display-unlock-pipes-based-on-det-allocation.patch
new file mode 100644 (file)
index 0000000..f6c11f7
--- /dev/null
@@ -0,0 +1,264 @@
+From 90e4c59eafdcee4e4dcf61b23feafa551390665d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 11:55:23 -0400
+Subject: drm/amd/display: Unlock Pipes Based On DET Allocation
+
+From: Austin Zheng <Austin.Zheng@amd.com>
+
+[ Upstream commit 4af0d8ebf74ccbb60d33fdd410891283dd6cb109 ]
+
+[Why]
+DML21 does not allocate DET evenly between pipes.
+May result in underflow when unlocking the pipes as DET could
+be overallocated.
+
+[How]
+1. Unlock pipes that have a decreased amount of DET allocation
+2. Wait for the double buffer to be updated.
+3. Unlock the remaining pipes.
+
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Signed-off-by: Austin Zheng <Austin.Zheng@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/core/dc_resource.c | 28 ++++++
+ .../display/dc/hubbub/dcn401/dcn401_hubbub.c  | 23 +++++
+ .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 91 +++++++++++++++++++
+ .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h |  2 +
+ .../amd/display/dc/hwss/dcn401/dcn401_init.c  |  2 +-
+ .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h  |  1 +
+ drivers/gpu/drm/amd/display/dc/inc/resource.h |  5 +
+ 7 files changed, 151 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index 913adca531fc4..5ab5866dc73af 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -5275,3 +5275,31 @@ void resource_init_common_dml2_callbacks(struct dc *dc, struct dml2_configuratio
+       dml2_options->svp_pstate.callbacks.remove_phantom_streams_and_planes = &dc_state_remove_phantom_streams_and_planes;
+       dml2_options->svp_pstate.callbacks.release_phantom_streams_and_planes = &dc_state_release_phantom_streams_and_planes;
+ }
++
++/* Returns number of DET segments allocated for a given OTG_MASTER pipe */
++int resource_calculate_det_for_stream(struct dc_state *state, struct pipe_ctx *otg_master)
++{
++      struct pipe_ctx *opp_heads[MAX_PIPES];
++      struct pipe_ctx *dpp_pipes[MAX_PIPES];
++
++      int dpp_count = 0;
++      int det_segments = 0;
++
++      if (!otg_master->stream)
++              return 0;
++
++      int slice_count = resource_get_opp_heads_for_otg_master(otg_master,
++                      &state->res_ctx, opp_heads);
++
++      for (int slice_idx = 0; slice_idx < slice_count; slice_idx++) {
++              if (opp_heads[slice_idx]->plane_state) {
++                      dpp_count = resource_get_dpp_pipes_for_opp_head(
++                                      opp_heads[slice_idx],
++                                      &state->res_ctx,
++                                      dpp_pipes);
++                      for (int dpp_idx = 0; dpp_idx < dpp_count; dpp_idx++)
++                              det_segments += dpp_pipes[dpp_idx]->hubp_regs.det_size;
++              }
++      }
++      return det_segments;
++}
+diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
+index 181041d6d177c..70ddc0392a5b6 100644
+--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
++++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
+@@ -1170,6 +1170,28 @@ static void dcn401_program_compbuf_segments(struct hubbub *hubbub, unsigned comp
+       }
+ }
++static void dcn401_wait_for_det_update(struct hubbub *hubbub, int hubp_inst)
++{
++      struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
++
++      switch (hubp_inst) {
++      case 0:
++              REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100000); /* 1 vupdate at 10hz */
++              break;
++      case 1:
++              REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100000);
++              break;
++      case 2:
++              REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100000);
++              break;
++      case 3:
++              REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100000);
++              break;
++      default:
++              break;
++      }
++}
++
+ static const struct hubbub_funcs hubbub4_01_funcs = {
+       .update_dchub = hubbub2_update_dchub,
+       .init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx,
+@@ -1192,6 +1214,7 @@ static const struct hubbub_funcs hubbub4_01_funcs = {
+       .set_request_limit = hubbub32_set_request_limit,
+       .program_det_segments = dcn401_program_det_segments,
+       .program_compbuf_segments = dcn401_program_compbuf_segments,
++      .wait_for_det_update = dcn401_wait_for_det_update,
+ };
+ void hubbub401_construct(struct dcn20_hubbub *hubbub2,
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+index 7c724cf682840..edd302ebbdfcf 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+@@ -1677,3 +1677,94 @@ void dcn401_hardware_release(struct dc *dc)
+       }
+ }
++void dcn401_wait_for_det_buffer_update(struct dc *dc, struct dc_state *context, struct pipe_ctx *otg_master)
++{
++      struct pipe_ctx *opp_heads[MAX_PIPES];
++      struct pipe_ctx *dpp_pipes[MAX_PIPES];
++      struct hubbub *hubbub = dc->res_pool->hubbub;
++      int dpp_count = 0;
++
++      if (!otg_master->stream)
++              return;
++
++      int slice_count = resource_get_opp_heads_for_otg_master(otg_master,
++                      &context->res_ctx, opp_heads);
++
++      for (int slice_idx = 0; slice_idx < slice_count; slice_idx++) {
++              if (opp_heads[slice_idx]->plane_state) {
++                      dpp_count = resource_get_dpp_pipes_for_opp_head(
++                                      opp_heads[slice_idx],
++                                      &context->res_ctx,
++                                      dpp_pipes);
++                      for (int dpp_idx = 0; dpp_idx < dpp_count; dpp_idx++) {
++                              struct pipe_ctx *dpp_pipe = dpp_pipes[dpp_idx];
++                                      if (dpp_pipe && hubbub &&
++                                              dpp_pipe->plane_res.hubp &&
++                                              hubbub->funcs->wait_for_det_update)
++                                              hubbub->funcs->wait_for_det_update(hubbub, dpp_pipe->plane_res.hubp->inst);
++                      }
++              }
++      }
++}
++
++void dcn401_interdependent_update_lock(struct dc *dc,
++              struct dc_state *context, bool lock)
++{
++      unsigned int i = 0;
++      struct pipe_ctx *pipe = NULL;
++      struct timing_generator *tg = NULL;
++      bool pipe_unlocked[MAX_PIPES] = {0};
++
++      if (lock) {
++              for (i = 0; i < dc->res_pool->pipe_count; i++) {
++                      pipe = &context->res_ctx.pipe_ctx[i];
++                      tg = pipe->stream_res.tg;
++
++                      if (!resource_is_pipe_type(pipe, OTG_MASTER) ||
++                                      !tg->funcs->is_tg_enabled(tg) ||
++                                      dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM)
++                              continue;
++                      dc->hwss.pipe_control_lock(dc, pipe, true);
++              }
++      } else {
++              /* Unlock pipes based on the change in DET allocation instead of pipe index
++               * Prevents over allocation of DET during unlock process
++               * e.g. 2 pipe config with different streams with a max of 20 DET segments
++               *      Before:                                                         After:
++               *              - Pipe0: 10 DET segments                        - Pipe0: 12 DET segments
++               *              - Pipe1: 10 DET segments                        - Pipe1: 8 DET segments
++               * If Pipe0 gets updated first, 22 DET segments will be allocated
++               */
++              for (i = 0; i < dc->res_pool->pipe_count; i++) {
++                      pipe = &context->res_ctx.pipe_ctx[i];
++                      tg = pipe->stream_res.tg;
++                      int current_pipe_idx = i;
++
++                      if (!resource_is_pipe_type(pipe, OTG_MASTER) ||
++                                      !tg->funcs->is_tg_enabled(tg) ||
++                                      dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
++                              pipe_unlocked[i] = true;
++                              continue;
++                      }
++
++                      // If the same stream exists in old context, ensure the OTG_MASTER pipes for the same stream get compared
++                      struct pipe_ctx *old_otg_master = resource_get_otg_master_for_stream(&dc->current_state->res_ctx, pipe->stream);
++
++                      if (old_otg_master)
++                              current_pipe_idx = old_otg_master->pipe_idx;
++                      if (resource_calculate_det_for_stream(context, pipe) <
++                                      resource_calculate_det_for_stream(dc->current_state, &dc->current_state->res_ctx.pipe_ctx[current_pipe_idx])) {
++                              dc->hwss.pipe_control_lock(dc, pipe, false);
++                              pipe_unlocked[i] = true;
++                              dcn401_wait_for_det_buffer_update(dc, context, pipe);
++                      }
++              }
++
++              for (i = 0; i < dc->res_pool->pipe_count; i++) {
++                      if (pipe_unlocked[i])
++                              continue;
++                      pipe = &context->res_ctx.pipe_ctx[i];
++                      dc->hwss.pipe_control_lock(dc, pipe, false);
++              }
++      }
++}
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
+index 8e9c1c17aa662..3ecb1ebffcee8 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
+@@ -81,4 +81,6 @@ void dcn401_hardware_release(struct dc *dc);
+ void dcn401_update_odm(struct dc *dc, struct dc_state *context,
+               struct pipe_ctx *otg_master);
+ void adjust_hotspot_between_slices_for_2x_magnify(uint32_t cursor_width, struct dc_cursor_position *pos_cpy);
++void dcn401_wait_for_det_buffer_update(struct dc *dc, struct dc_state *context, struct pipe_ctx *otg_master);
++void dcn401_interdependent_update_lock(struct dc *dc, struct dc_state *context, bool lock);
+ #endif /* __DC_HWSS_DCN401_H__ */
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+index 6a768702c7bde..28f3eb8f4b2d8 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+@@ -38,7 +38,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
+       .disable_audio_stream = dce110_disable_audio_stream,
+       .disable_plane = dcn20_disable_plane,
+       .pipe_control_lock = dcn20_pipe_control_lock,
+-      .interdependent_update_lock = dcn32_interdependent_update_lock,
++      .interdependent_update_lock = dcn401_interdependent_update_lock,
+       .cursor_lock = dcn10_cursor_lock,
+       .prepare_bandwidth = dcn401_prepare_bandwidth,
+       .optimize_bandwidth = dcn401_optimize_bandwidth,
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+index dd2b2864876c7..67c32401893e8 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+@@ -227,6 +227,7 @@ struct hubbub_funcs {
+       void (*get_mall_en)(struct hubbub *hubbub, unsigned int *mall_in_use);
+       void (*program_det_segments)(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg);
+       void (*program_compbuf_segments)(struct hubbub *hubbub, unsigned compbuf_size_seg, bool safe_to_increase);
++      void (*wait_for_det_update)(struct hubbub *hubbub, int hubp_inst);
+ };
+ struct hubbub {
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
+index 96d40d33a1f99..9cd80d3864c7b 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
+@@ -639,4 +639,9 @@ struct dscl_prog_data *resource_get_dscl_prog_data(struct pipe_ctx *pipe_ctx);
+  * @dml2_options: struct to hold callbacks
+  */
+ void resource_init_common_dml2_callbacks(struct dc *dc, struct dml2_configuration_options *dml2_options);
++
++/*
++ *Calculate total DET allocated for all pipes for a given OTG_MASTER pipe
++ */
++int resource_calculate_det_for_stream(struct dc_state *state, struct pipe_ctx *otg_master);
+ #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-display-use-gpuvm_min_page_size_kbytes-for-d.patch b/queue-6.11/drm-amd-display-use-gpuvm_min_page_size_kbytes-for-d.patch
new file mode 100644 (file)
index 0000000..5813863
--- /dev/null
@@ -0,0 +1,96 @@
+From df6b86a227e82f1ef8cdc0386b3d2eaf111a2754 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jul 2024 11:53:31 -0400
+Subject: drm/amd/display: Use gpuvm_min_page_size_kbytes for DML2 surfaces
+
+From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+
+[ Upstream commit 31663521ede2edb622ee1b397ae3ac666d6351c5 ]
+
+[Why]
+It's currently hard coded to 256 when it should be using the SOC
+provided values. This can result in corruption with linear surfaces
+where we prefetch more PTE than the buffer can hold.
+
+[How]
+Update the min page size correctly for the plane.
+
+Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Reviewed-by: Jun Lei <jun.lei@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../display/dc/dml2/dml2_translation_helper.c | 20 +++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
+index 8b9dcee772660..73c285b751d6f 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
+@@ -953,7 +953,9 @@ static void get_scaler_data_for_plane(const struct dc_plane_state *in, struct dc
+       memcpy(out, &temp_pipe->plane_res.scl_data, sizeof(*out));
+ }
+-static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_stream_state *in)
++static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned int location,
++                                       const struct dc_stream_state *in,
++                                       const struct soc_bounding_box_st *soc)
+ {
+       dml_uint_t width, height;
+@@ -970,7 +972,7 @@ static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned
+       out->CursorBPP[location] = dml_cur_32bit;
+       out->CursorWidth[location] = 256;
+-      out->GPUVMMinPageSizeKBytes[location] = 256;
++      out->GPUVMMinPageSizeKBytes[location] = soc->gpuvm_min_page_size_kbytes;
+       out->ViewportWidth[location] = width;
+       out->ViewportHeight[location] = height;
+@@ -1007,7 +1009,9 @@ static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned
+       out->ScalerEnabled[location] = false;
+ }
+-static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_plane_state *in, struct dc_state *context)
++static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out, unsigned int location,
++                                                  const struct dc_plane_state *in, struct dc_state *context,
++                                                  const struct soc_bounding_box_st *soc)
+ {
+       struct scaler_data *scaler_data = kzalloc(sizeof(*scaler_data), GFP_KERNEL);
+       if (!scaler_data)
+@@ -1018,7 +1022,7 @@ static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out
+       out->CursorBPP[location] = dml_cur_32bit;
+       out->CursorWidth[location] = 256;
+-      out->GPUVMMinPageSizeKBytes[location] = 256;
++      out->GPUVMMinPageSizeKBytes[location] = soc->gpuvm_min_page_size_kbytes;
+       out->ViewportWidth[location] = scaler_data->viewport.width;
+       out->ViewportHeight[location] = scaler_data->viewport.height;
+@@ -1299,7 +1303,8 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat
+                       disp_cfg_plane_location = dml_dispcfg->num_surfaces++;
+                       populate_dummy_dml_surface_cfg(&dml_dispcfg->surface, disp_cfg_plane_location, context->streams[i]);
+-                      populate_dummy_dml_plane_cfg(&dml_dispcfg->plane, disp_cfg_plane_location, context->streams[i]);
++                      populate_dummy_dml_plane_cfg(&dml_dispcfg->plane, disp_cfg_plane_location,
++                                                   context->streams[i], &dml2->v20.dml_core_ctx.soc);
+                       dml_dispcfg->plane.BlendingAndTiming[disp_cfg_plane_location] = disp_cfg_stream_location;
+@@ -1315,7 +1320,10 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat
+                               ASSERT(disp_cfg_plane_location >= 0 && disp_cfg_plane_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__);
+                               populate_dml_surface_cfg_from_plane_state(dml2->v20.dml_core_ctx.project, &dml_dispcfg->surface, disp_cfg_plane_location, context->stream_status[i].plane_states[j]);
+-                              populate_dml_plane_cfg_from_plane_state(&dml_dispcfg->plane, disp_cfg_plane_location, context->stream_status[i].plane_states[j], context);
++                              populate_dml_plane_cfg_from_plane_state(
++                                      &dml_dispcfg->plane, disp_cfg_plane_location,
++                                      context->stream_status[i].plane_states[j], context,
++                                      &dml2->v20.dml_core_ctx.soc);
+                               if (stream_mall_type == SUBVP_MAIN) {
+                                       dml_dispcfg->plane.UseMALLForPStateChange[disp_cfg_plane_location] = dml_use_mall_pstate_change_sub_viewport;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amd-pm-ensure-the-fw_info-is-not-null-before-usi.patch b/queue-6.11/drm-amd-pm-ensure-the-fw_info-is-not-null-before-usi.patch
new file mode 100644 (file)
index 0000000..04abc09
--- /dev/null
@@ -0,0 +1,36 @@
+From 15d08f76560e5eec67b713a420f286837e767f08 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 17:15:12 +0800
+Subject: drm/amd/pm: ensure the fw_info is not null before using it
+
+From: Tim Huang <tim.huang@amd.com>
+
+[ Upstream commit 186fb12e7a7b038c2710ceb2fb74068f1b5d55a4 ]
+
+This resolves the dereference null return value warning
+reported by Coverity.
+
+Signed-off-by: Tim Huang <tim.huang@amd.com>
+Reviewed-by: Jesse Zhang <jesse.zhang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
+index ca1c7ae8d146d..f06b29e33ba45 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
+@@ -1183,6 +1183,8 @@ static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
+       fw_info = smu_atom_get_data_table(hwmgr->adev,
+                        GetIndexIntoMasterTable(DATA, FirmwareInfo),
+                        &size, &frev, &crev);
++      PP_ASSERT_WITH_CODE(fw_info != NULL,
++                          "Missing firmware info!", return -EINVAL);
+       if ((fw_info->ucTableFormatRevision == 1)
+           && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-add-list-empty-check-to-avoid-null-pointe.patch b/queue-6.11/drm-amdgpu-add-list-empty-check-to-avoid-null-pointe.patch
new file mode 100644 (file)
index 0000000..0af6d2b
--- /dev/null
@@ -0,0 +1,61 @@
+From 250a3251a5bce5c9cb77fff22caa9e8358f3ded9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 14:42:41 +0800
+Subject: drm/amdgpu: add list empty check to avoid null pointer issue
+
+From: Yang Wang <kevinyang.wang@amd.com>
+
+[ Upstream commit 4416377ae1fdc41a90b665943152ccd7ff61d3c5 ]
+
+Add list empty check to avoid null pointer issues in some corner cases.
+- list_for_each_entry_safe()
+
+Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
+Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
+index 19158cc30f31f..43f3e72fb247a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
+@@ -80,6 +80,9 @@ static void aca_banks_release(struct aca_banks *banks)
+ {
+       struct aca_bank_node *node, *tmp;
++      if (list_empty(&banks->list))
++              return;
++
+       list_for_each_entry_safe(node, tmp, &banks->list, node) {
+               list_del(&node->node);
+               kvfree(node);
+@@ -562,9 +565,13 @@ static void aca_error_fini(struct aca_error *aerr)
+       struct aca_bank_error *bank_error, *tmp;
+       mutex_lock(&aerr->lock);
++      if (list_empty(&aerr->list))
++              goto out_unlock;
++
+       list_for_each_entry_safe(bank_error, tmp, &aerr->list, node)
+               aca_bank_error_remove(aerr, bank_error);
++out_unlock:
+       mutex_destroy(&aerr->lock);
+ }
+@@ -680,6 +687,9 @@ static void aca_manager_fini(struct aca_handle_manager *mgr)
+ {
+       struct aca_handle *handle, *tmp;
++      if (list_empty(&mgr->list))
++              return;
++
+       list_for_each_entry_safe(handle, tmp, &mgr->list, node)
+               amdgpu_aca_remove_handle(handle);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-add-raven1-gfxoff-quirk.patch b/queue-6.11/drm-amdgpu-add-raven1-gfxoff-quirk.patch
new file mode 100644 (file)
index 0000000..be0e6c2
--- /dev/null
@@ -0,0 +1,35 @@
+From e009661952edba4bbaeb38381cf4275509dd1ae2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 Aug 2024 15:25:54 +0800
+Subject: drm/amdgpu: add raven1 gfxoff quirk
+
+From: Peng Liu <liupeng01@kylinos.cn>
+
+[ Upstream commit 0126c0ae11e8b52ecfde9d1b174ee2f32d6c3a5d ]
+
+Fix screen corruption with openkylin.
+
+Link: https://bbs.openkylin.top/t/topic/171497
+Signed-off-by: Peng Liu <liupeng01@kylinos.cn>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+index 2929c8972ea73..9360a4425c4ae 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+@@ -1301,6 +1301,8 @@ static const struct amdgpu_gfxoff_quirk amdgpu_gfxoff_quirk_list[] = {
+       { 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc6 },
+       /* Apple MacBook Pro (15-inch, 2019) Radeon Pro Vega 20 4 GB */
+       { 0x1002, 0x69af, 0x106b, 0x019a, 0xc0 },
++      /* https://bbs.openkylin.top/t/topic/171497 */
++      { 0x1002, 0x15d8, 0x19e5, 0x3e14, 0xc2 },
+       { 0, 0, 0, 0, 0 },
+ };
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-block-mmr_read-ioctl-in-reset.patch b/queue-6.11/drm-amdgpu-block-mmr_read-ioctl-in-reset.patch
new file mode 100644 (file)
index 0000000..7c1acf3
--- /dev/null
@@ -0,0 +1,111 @@
+From d771ad7ec28a026d048f6b511fc3afa655b84592 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Aug 2024 13:40:23 -0400
+Subject: drm/amdgpu: Block MMR_READ IOCTL in reset
+
+From: Victor Skvortsov <victor.skvortsov@amd.com>
+
+[ Upstream commit 9e823f307074c0f82b5f6044943b0086e3079bed ]
+
+Register access from userspace should be blocked until
+reset is complete.
+
+Signed-off-by: Victor Skvortsov <victor.skvortsov@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 43 ++++++++++++++++++-------
+ 1 file changed, 31 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+index 66782be5917b9..96af9ff1acb67 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+@@ -43,6 +43,7 @@
+ #include "amdgpu_gem.h"
+ #include "amdgpu_display.h"
+ #include "amdgpu_ras.h"
++#include "amdgpu_reset.h"
+ #include "amd_pcie.h"
+ void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
+@@ -778,6 +779,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+                                   ? -EFAULT : 0;
+       }
+       case AMDGPU_INFO_READ_MMR_REG: {
++              int ret = 0;
+               unsigned int n, alloc_size;
+               uint32_t *regs;
+               unsigned int se_num = (info->read_mmr_reg.instance >>
+@@ -787,24 +789,37 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+                                  AMDGPU_INFO_MMR_SH_INDEX_SHIFT) &
+                                 AMDGPU_INFO_MMR_SH_INDEX_MASK;
++              if (!down_read_trylock(&adev->reset_domain->sem))
++                      return -ENOENT;
++
+               /* set full masks if the userspace set all bits
+                * in the bitfields
+                */
+-              if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK)
++              if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK) {
+                       se_num = 0xffffffff;
+-              else if (se_num >= AMDGPU_GFX_MAX_SE)
+-                      return -EINVAL;
+-              if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK)
++              } else if (se_num >= AMDGPU_GFX_MAX_SE) {
++                      ret = -EINVAL;
++                      goto out;
++              }
++
++              if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK) {
+                       sh_num = 0xffffffff;
+-              else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE)
+-                      return -EINVAL;
++              } else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE) {
++                      ret = -EINVAL;
++                      goto out;
++              }
+-              if (info->read_mmr_reg.count > 128)
+-                      return -EINVAL;
++              if (info->read_mmr_reg.count > 128) {
++                      ret = -EINVAL;
++                      goto out;
++              }
+               regs = kmalloc_array(info->read_mmr_reg.count, sizeof(*regs), GFP_KERNEL);
+-              if (!regs)
+-                      return -ENOMEM;
++              if (!regs) {
++                      ret = -ENOMEM;
++                      goto out;
++              }
++
+               alloc_size = info->read_mmr_reg.count * sizeof(*regs);
+               amdgpu_gfx_off_ctrl(adev, false);
+@@ -816,13 +831,17 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+                                             info->read_mmr_reg.dword_offset + i);
+                               kfree(regs);
+                               amdgpu_gfx_off_ctrl(adev, true);
+-                              return -EFAULT;
++                              ret = -EFAULT;
++                              goto out;
+                       }
+               }
+               amdgpu_gfx_off_ctrl(adev, true);
+               n = copy_to_user(out, regs, min(size, alloc_size));
+               kfree(regs);
+-              return n ? -EFAULT : 0;
++              ret = (n ? -EFAULT : 0);
++out:
++              up_read(&adev->reset_domain->sem);
++              return ret;
+       }
+       case AMDGPU_INFO_DEV_INFO: {
+               struct drm_amdgpu_info_device *dev_info;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-disallow-multiple-bo_handles-chunks-in-on.patch b/queue-6.11/drm-amdgpu-disallow-multiple-bo_handles-chunks-in-on.patch
new file mode 100644 (file)
index 0000000..0eec9bd
--- /dev/null
@@ -0,0 +1,49 @@
+From 21bfa487a699f2091fe655ed0d8b814033c668f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jul 2024 11:54:30 +0200
+Subject: drm/amdgpu: disallow multiple BO_HANDLES chunks in one submit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
+
+[ Upstream commit fec5f8e8c6bcf83ed7a392801d7b44c5ecfc1e82 ]
+
+Before this commit, only submits with both a BO_HANDLES chunk and a
+'bo_list_handle' would be rejected (by amdgpu_cs_parser_bos).
+
+But if UMD sent multiple BO_HANDLES, what would happen is:
+* only the last one would be really used
+* all the others would leak memory as amdgpu_cs_p1_bo_handles would
+  overwrite the previous p->bo_list value
+
+This commit rejects submissions with multiple BO_HANDLES chunks to
+match the implementation of the parser.
+
+Signed-off-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+index 6dfdff58bffd1..78b3c067fea7e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -263,6 +263,10 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
+                       if (size < sizeof(struct drm_amdgpu_bo_list_in))
+                               goto free_partial_kdata;
++                      /* Only a single BO list is allowed to simplify handling. */
++                      if (p->bo_list)
++                              ret = -EINVAL;
++
+                       ret = amdgpu_cs_p1_bo_handles(p, p->chunks[i].kdata);
+                       if (ret)
+                               goto free_partial_kdata;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-enable-gfxoff-quirk-on-hp-705g4.patch b/queue-6.11/drm-amdgpu-enable-gfxoff-quirk-on-hp-705g4.patch
new file mode 100644 (file)
index 0000000..e590d52
--- /dev/null
@@ -0,0 +1,38 @@
+From 77165cd9a72e2a2d6daf37050bf2224392c1a267 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 Aug 2024 15:27:08 +0800
+Subject: drm/amdgpu: enable gfxoff quirk on HP 705G4
+
+From: Peng Liu <liupeng01@kylinos.cn>
+
+[ Upstream commit 2c7795e245d993bcba2f716a8c93a5891ef910c9 ]
+
+Enabling gfxoff quirk results in perfectly usable
+graphical user interface on HP 705G4 DM with R5 2400G.
+
+Without the quirk, X server is completely unusable as
+every few seconds there is gpu reset due to ring gfx timeout.
+
+Signed-off-by: Peng Liu <liupeng01@kylinos.cn>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+index 9360a4425c4ae..fc4153a87f947 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+@@ -1303,6 +1303,8 @@ static const struct amdgpu_gfxoff_quirk amdgpu_gfxoff_quirk_list[] = {
+       { 0x1002, 0x69af, 0x106b, 0x019a, 0xc0 },
+       /* https://bbs.openkylin.top/t/topic/171497 */
+       { 0x1002, 0x15d8, 0x19e5, 0x3e14, 0xc2 },
++      /* HP 705G4 DM with R5 2400G */
++      { 0x1002, 0x15dd, 0x103c, 0x8464, 0xd6 },
+       { 0, 0, 0, 0, 0 },
+ };
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-fix-ptr-check-warning-in-gfx10-ip_dump.patch b/queue-6.11/drm-amdgpu-fix-ptr-check-warning-in-gfx10-ip_dump.patch
new file mode 100644 (file)
index 0000000..b879475
--- /dev/null
@@ -0,0 +1,54 @@
+From 7f936e0a20b1ea7868d864d9a4d45fe32e0a3b03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 17:25:24 +0530
+Subject: drm/amdgpu: fix ptr check warning in gfx10 ip_dump
+
+From: Sunil Khatri <sunil.khatri@amd.com>
+
+[ Upstream commit 98df5a7732e3b78bf8824d2938a8865a45cfc113 ]
+
+Change condition, if (ptr == NULL) to if (!ptr)
+for a better format and fix the warning.
+
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sunil Khatri <sunil.khatri@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+index e444e621ddaa0..5b41c6a44068c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+@@ -4649,7 +4649,7 @@ static void gfx_v10_0_alloc_ip_dump(struct amdgpu_device *adev)
+       uint32_t inst;
+       ptr = kcalloc(reg_count, sizeof(uint32_t), GFP_KERNEL);
+-      if (ptr == NULL) {
++      if (!ptr) {
+               DRM_ERROR("Failed to allocate memory for GFX IP Dump\n");
+               adev->gfx.ip_dump_core = NULL;
+       } else {
+@@ -4662,7 +4662,7 @@ static void gfx_v10_0_alloc_ip_dump(struct amdgpu_device *adev)
+               adev->gfx.mec.num_queue_per_pipe;
+       ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
+-      if (ptr == NULL) {
++      if (!ptr) {
+               DRM_ERROR("Failed to allocate memory for Compute Queues IP Dump\n");
+               adev->gfx.ip_dump_compute_queues = NULL;
+       } else {
+@@ -4675,7 +4675,7 @@ static void gfx_v10_0_alloc_ip_dump(struct amdgpu_device *adev)
+               adev->gfx.me.num_queue_per_pipe;
+       ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
+-      if (ptr == NULL) {
++      if (!ptr) {
+               DRM_ERROR("Failed to allocate memory for GFX Queues IP Dump\n");
+               adev->gfx.ip_dump_gfx_queues = NULL;
+       } else {
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-fix-ptr-check-warning-in-gfx11-ip_dump.patch b/queue-6.11/drm-amdgpu-fix-ptr-check-warning-in-gfx11-ip_dump.patch
new file mode 100644 (file)
index 0000000..dc5255d
--- /dev/null
@@ -0,0 +1,54 @@
+From 38b746b2f10bbc1d18b8fbe55bf6ff6737d427e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 17:27:10 +0530
+Subject: drm/amdgpu: fix ptr check warning in gfx11 ip_dump
+
+From: Sunil Khatri <sunil.khatri@amd.com>
+
+[ Upstream commit bd15f805cdc503ac229a14f5fe21db12e6e7f84a ]
+
+Change condition, if (ptr == NULL) to if (!ptr)
+for a better format and fix the warning.
+
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sunil Khatri <sunil.khatri@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+index dcef399074492..61e62d846900c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+@@ -1484,7 +1484,7 @@ static void gfx_v11_0_alloc_ip_dump(struct amdgpu_device *adev)
+       uint32_t inst;
+       ptr = kcalloc(reg_count, sizeof(uint32_t), GFP_KERNEL);
+-      if (ptr == NULL) {
++      if (!ptr) {
+               DRM_ERROR("Failed to allocate memory for GFX IP Dump\n");
+               adev->gfx.ip_dump_core = NULL;
+       } else {
+@@ -1497,7 +1497,7 @@ static void gfx_v11_0_alloc_ip_dump(struct amdgpu_device *adev)
+               adev->gfx.mec.num_queue_per_pipe;
+       ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
+-      if (ptr == NULL) {
++      if (!ptr) {
+               DRM_ERROR("Failed to allocate memory for Compute Queues IP Dump\n");
+               adev->gfx.ip_dump_compute_queues = NULL;
+       } else {
+@@ -1510,7 +1510,7 @@ static void gfx_v11_0_alloc_ip_dump(struct amdgpu_device *adev)
+               adev->gfx.me.num_queue_per_pipe;
+       ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
+-      if (ptr == NULL) {
++      if (!ptr) {
+               DRM_ERROR("Failed to allocate memory for GFX Queues IP Dump\n");
+               adev->gfx.ip_dump_gfx_queues = NULL;
+       } else {
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-fix-ptr-check-warning-in-gfx9-ip_dump.patch b/queue-6.11/drm-amdgpu-fix-ptr-check-warning-in-gfx9-ip_dump.patch
new file mode 100644 (file)
index 0000000..f9c6752
--- /dev/null
@@ -0,0 +1,45 @@
+From 0ec0cff30390ad35628e340057cdc60e8151d732 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 17:21:53 +0530
+Subject: drm/amdgpu: fix ptr check warning in gfx9 ip_dump
+
+From: Sunil Khatri <sunil.khatri@amd.com>
+
+[ Upstream commit 07f4f9c00ec545dfa6251a44a09d2c48a76e7ee5 ]
+
+Change if (ptr == NULL) to if (!ptr) for a better
+format and fix the warning.
+
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sunil Khatri <sunil.khatri@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+index 7d517c94c3efb..6f178bfb8f104 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+@@ -2133,7 +2133,7 @@ static void gfx_v9_0_alloc_ip_dump(struct amdgpu_device *adev)
+       uint32_t inst;
+       ptr = kcalloc(reg_count, sizeof(uint32_t), GFP_KERNEL);
+-      if (ptr == NULL) {
++      if (!ptr) {
+               DRM_ERROR("Failed to allocate memory for GFX IP Dump\n");
+               adev->gfx.ip_dump_core = NULL;
+       } else {
+@@ -2146,7 +2146,7 @@ static void gfx_v9_0_alloc_ip_dump(struct amdgpu_device *adev)
+               adev->gfx.mec.num_queue_per_pipe;
+       ptr = kcalloc(reg_count * inst, sizeof(uint32_t), GFP_KERNEL);
+-      if (ptr == NULL) {
++      if (!ptr) {
+               DRM_ERROR("Failed to allocate memory for Compute Queues IP Dump\n");
+               adev->gfx.ip_dump_compute_queues = NULL;
+       } else {
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-fix-unchecked-return-value-warning-for-am.patch b/queue-6.11/drm-amdgpu-fix-unchecked-return-value-warning-for-am.patch
new file mode 100644 (file)
index 0000000..23cdbe6
--- /dev/null
@@ -0,0 +1,72 @@
+From 767ddf4e0f0c225534e921a28e40c4272f5f0453 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 10:38:37 +0800
+Subject: drm/amdgpu: fix unchecked return value warning for amdgpu_gfx
+
+From: Tim Huang <tim.huang@amd.com>
+
+[ Upstream commit c0277b9d7c2ee9ee5dbc948548984f0fbb861301 ]
+
+This resolves the unchecded return value warning reported by Coverity.
+
+Signed-off-by: Tim Huang <tim.huang@amd.com>
+Reviewed-by: Jesse Zhang <jesse.zhang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+index 1849510a308ad..3ff39d3ec317c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+@@ -882,8 +882,11 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
+       int r;
+       if (amdgpu_ras_is_supported(adev, ras_block->block)) {
+-              if (!amdgpu_persistent_edc_harvesting_supported(adev))
+-                      amdgpu_ras_reset_error_status(adev, AMDGPU_RAS_BLOCK__GFX);
++              if (!amdgpu_persistent_edc_harvesting_supported(adev)) {
++                      r = amdgpu_ras_reset_error_status(adev, AMDGPU_RAS_BLOCK__GFX);
++                      if (r)
++                              return r;
++              }
+               r = amdgpu_ras_block_late_init(adev, ras_block);
+               if (r)
+@@ -1027,7 +1030,10 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_
+               pr_err("critical bug! too many kiq readers\n");
+               goto failed_unlock;
+       }
+-      amdgpu_ring_alloc(ring, 32);
++      r = amdgpu_ring_alloc(ring, 32);
++      if (r)
++              goto failed_unlock;
++
+       amdgpu_ring_emit_rreg(ring, reg, reg_val_offs);
+       r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
+       if (r)
+@@ -1093,7 +1099,10 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint3
+       }
+       spin_lock_irqsave(&kiq->ring_lock, flags);
+-      amdgpu_ring_alloc(ring, 32);
++      r = amdgpu_ring_alloc(ring, 32);
++      if (r)
++              goto failed_unlock;
++
+       amdgpu_ring_emit_wreg(ring, reg, v);
+       r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
+       if (r)
+@@ -1129,6 +1138,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint3
+ failed_undo:
+       amdgpu_ring_undo(ring);
++failed_unlock:
+       spin_unlock_irqrestore(&kiq->ring_lock, flags);
+ failed_kiq_write:
+       dev_err(adev->dev, "failed to write reg:%x\n", reg);
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-fix-unchecked-return-value-warning-for-am.patch-17138 b/queue-6.11/drm-amdgpu-fix-unchecked-return-value-warning-for-am.patch-17138
new file mode 100644 (file)
index 0000000..136904c
--- /dev/null
@@ -0,0 +1,110 @@
+From 0c724a1bb8e67508434da6dcbce1f8c01e030024 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 13:47:55 +0800
+Subject: drm/amdgpu: fix unchecked return value warning for amdgpu_atombios
+
+From: Tim Huang <tim.huang@amd.com>
+
+[ Upstream commit 92549780e32718d64a6d08bbbb3c6fffecb541c7 ]
+
+This resolves the unchecded return value warning reported by Coverity.
+
+Signed-off-by: Tim Huang <tim.huang@amd.com>
+Reviewed-by: Jesse Zhang <jesse.zhang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 35 ++++++++++++--------
+ 1 file changed, 21 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+index 7dc102f0bc1d3..0c8975ac5af9e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+@@ -1018,8 +1018,9 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
+               if (clock_type == COMPUTE_ENGINE_PLL_PARAM) {
+                       args.v3.ulClockParams = cpu_to_le32((clock_type << 24) | clock);
+-                      amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
+-                              sizeof(args));
++                      if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
++                          index, (uint32_t *)&args, sizeof(args)))
++                              return -EINVAL;
+                       dividers->post_div = args.v3.ucPostDiv;
+                       dividers->enable_post_div = (args.v3.ucCntlFlag &
+@@ -1039,8 +1040,9 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
+                       if (strobe_mode)
+                               args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN;
+-                      amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
+-                              sizeof(args));
++                      if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
++                          index, (uint32_t *)&args, sizeof(args)))
++                              return -EINVAL;
+                       dividers->post_div = args.v5.ucPostDiv;
+                       dividers->enable_post_div = (args.v5.ucCntlFlag &
+@@ -1058,8 +1060,9 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
+               /* fusion */
+               args.v4.ulClock = cpu_to_le32(clock);   /* 10 khz */
+-              amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
+-                      sizeof(args));
++              if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
++                  index, (uint32_t *)&args, sizeof(args)))
++                      return -EINVAL;
+               dividers->post_divider = dividers->post_div = args.v4.ucPostDiv;
+               dividers->real_clock = le32_to_cpu(args.v4.ulClock);
+@@ -1070,8 +1073,9 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev,
+               args.v6_in.ulClock.ulComputeClockFlag = clock_type;
+               args.v6_in.ulClock.ulClockFreq = cpu_to_le32(clock);    /* 10 khz */
+-              amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
+-                      sizeof(args));
++              if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
++                  index, (uint32_t *)&args, sizeof(args)))
++                      return -EINVAL;
+               dividers->whole_fb_div = le16_to_cpu(args.v6_out.ulFbDiv.usFbDiv);
+               dividers->frac_fb_div = le16_to_cpu(args.v6_out.ulFbDiv.usFbDivFrac);
+@@ -1113,8 +1117,9 @@ int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev,
+                       if (strobe_mode)
+                               args.ucInputFlag |= MPLL_INPUT_FLAG_STROBE_MODE_EN;
+-                      amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
+-                              sizeof(args));
++                      if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
++                          index, (uint32_t *)&args, sizeof(args)))
++                              return -EINVAL;
+                       mpll_param->clkfrac = le16_to_cpu(args.ulFbDiv.usFbDivFrac);
+                       mpll_param->clkf = le16_to_cpu(args.ulFbDiv.usFbDiv);
+@@ -1211,8 +1216,9 @@ int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
+               args.v2.ucVoltageMode = 0;
+               args.v2.usVoltageLevel = 0;
+-              amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
+-                      sizeof(args));
++              if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
++                  index, (uint32_t *)&args, sizeof(args)))
++                      return -EINVAL;
+               *voltage = le16_to_cpu(args.v2.usVoltageLevel);
+               break;
+@@ -1221,8 +1227,9 @@ int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
+               args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL;
+               args.v3.usVoltageLevel = cpu_to_le16(voltage_id);
+-              amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args,
+-                      sizeof(args));
++              if (amdgpu_atom_execute_table(adev->mode_info.atom_context,
++                  index, (uint32_t *)&args, sizeof(args)))
++                      return -EINVAL;
+               *voltage = le16_to_cpu(args.v3.usVoltageLevel);
+               break;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-gfx10-use-rlc-safe-mode-for-soft-recovery.patch b/queue-6.11/drm-amdgpu-gfx10-use-rlc-safe-mode-for-soft-recovery.patch
new file mode 100644 (file)
index 0000000..36ccdf0
--- /dev/null
@@ -0,0 +1,35 @@
+From 0e3313e612d5a6a565bab7077a933e942002973f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jul 2024 18:20:34 -0400
+Subject: drm/amdgpu/gfx10: use rlc safe mode for soft recovery
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit ead60e9c4e29c8574cae1be4fe3af1d9a978fb0f ]
+
+Protect the MMIO access with safe mode.
+
+Acked-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+index 5b41c6a44068c..1bb602c4f9b3f 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+@@ -8889,7 +8889,9 @@ static void gfx_v10_0_ring_soft_recovery(struct amdgpu_ring *ring,
+       value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
+       value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
+       value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
++      amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
+       WREG32_SOC15(GC, 0, mmSQ_CMD, value);
++      amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
+ }
+ static void
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-gfx11-enter-safe-mode-before-touching-cp_.patch b/queue-6.11/drm-amdgpu-gfx11-enter-safe-mode-before-touching-cp_.patch
new file mode 100644 (file)
index 0000000..b4d1e8c
--- /dev/null
@@ -0,0 +1,43 @@
+From 3330d78e083ba52ca911d386ebefccad40e4d330 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Jul 2024 15:36:19 -0400
+Subject: drm/amdgpu/gfx11: enter safe mode before touching CP_INT_CNTL
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit b5be054c585110b2c5c1b180136800e8c41c7bb4 ]
+
+Need to enter safe mode before touching GC MMIO.
+
+Acked-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+index 61e62d846900c..228124b389541 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+@@ -4707,6 +4707,8 @@ static int gfx_v11_0_soft_reset(void *handle)
+       int r, i, j, k;
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
++      gfx_v11_0_set_safe_mode(adev, 0);
++
+       tmp = RREG32_SOC15(GC, 0, regCP_INT_CNTL);
+       tmp = REG_SET_FIELD(tmp, CP_INT_CNTL, CMP_BUSY_INT_ENABLE, 0);
+       tmp = REG_SET_FIELD(tmp, CP_INT_CNTL, CNTX_BUSY_INT_ENABLE, 0);
+@@ -4714,8 +4716,6 @@ static int gfx_v11_0_soft_reset(void *handle)
+       tmp = REG_SET_FIELD(tmp, CP_INT_CNTL, GFX_IDLE_INT_ENABLE, 0);
+       WREG32_SOC15(GC, 0, regCP_INT_CNTL, tmp);
+-      gfx_v11_0_set_safe_mode(adev, 0);
+-
+       mutex_lock(&adev->srbm_mutex);
+       for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
+               for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-gfx11-use-rlc-safe-mode-for-soft-recovery.patch b/queue-6.11/drm-amdgpu-gfx11-use-rlc-safe-mode-for-soft-recovery.patch
new file mode 100644 (file)
index 0000000..d43dd39
--- /dev/null
@@ -0,0 +1,35 @@
+From 181297346883767f67ffcbe52974bbdf6f4a57c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jul 2024 18:20:23 -0400
+Subject: drm/amdgpu/gfx11: use rlc safe mode for soft recovery
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit 3f2d35c325534c1b7ac5072173f0dc7ca969dec2 ]
+
+Protect the MMIO access with safe mode.
+
+Acked-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+index 228124b389541..b80b1b6f2eea7 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+@@ -6008,7 +6008,9 @@ static void gfx_v11_0_ring_soft_recovery(struct amdgpu_ring *ring,
+       value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
+       value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
+       value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
++      amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
+       WREG32_SOC15(GC, 0, regSQ_CMD, value);
++      amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
+ }
+ static void
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-gfx12-properly-handle-error-ints-on-all-p.patch b/queue-6.11/drm-amdgpu-gfx12-properly-handle-error-ints-on-all-p.patch
new file mode 100644 (file)
index 0000000..a0f9742
--- /dev/null
@@ -0,0 +1,204 @@
+From 0850e205f339b5e4bde77405ed6264cbeb39a5c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jul 2024 17:40:55 -0400
+Subject: drm/amdgpu/gfx12: properly handle error ints on all pipes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit 39879321769cc2d9a690725959ef76af92a38ac1 ]
+
+Need to handle the interrupt enables for all pipes.
+
+v2: fix indexing (Jessie)
+
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 130 ++++++++++++++++++++-----
+ 1 file changed, 106 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+index 34b95ca700b23..ac671656069a3 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+@@ -1690,26 +1690,68 @@ static void gfx_v12_0_constants_init(struct amdgpu_device *adev)
+       gfx_v12_0_init_compute_vmid(adev);
+ }
++static u32 gfx_v12_0_get_cpg_int_cntl(struct amdgpu_device *adev,
++                                    int me, int pipe)
++{
++      if (me != 0)
++              return 0;
++
++      switch (pipe) {
++      case 0:
++              return SOC15_REG_OFFSET(GC, 0, regCP_INT_CNTL_RING0);
++      default:
++              return 0;
++      }
++}
++
++static u32 gfx_v12_0_get_cpc_int_cntl(struct amdgpu_device *adev,
++                                    int me, int pipe)
++{
++      /*
++       * amdgpu controls only the first MEC. That's why this function only
++       * handles the setting of interrupts for this specific MEC. All other
++       * pipes' interrupts are set by amdkfd.
++       */
++      if (me != 1)
++              return 0;
++
++      switch (pipe) {
++      case 0:
++              return SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE0_INT_CNTL);
++      case 1:
++              return SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE1_INT_CNTL);
++      default:
++              return 0;
++      }
++}
++
+ static void gfx_v12_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
+-                                              bool enable)
++                                             bool enable)
+ {
+-      u32 tmp;
++      u32 tmp, cp_int_cntl_reg;
++      int i, j;
+       if (amdgpu_sriov_vf(adev))
+               return;
+-      tmp = RREG32_SOC15(GC, 0, regCP_INT_CNTL_RING0);
+-
+-      tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE,
+-                          enable ? 1 : 0);
+-      tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE,
+-                          enable ? 1 : 0);
+-      tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE,
+-                          enable ? 1 : 0);
+-      tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE,
+-                          enable ? 1 : 0);
+-
+-      WREG32_SOC15(GC, 0, regCP_INT_CNTL_RING0, tmp);
++      for (i = 0; i < adev->gfx.me.num_me; i++) {
++              for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
++                      cp_int_cntl_reg = gfx_v12_0_get_cpg_int_cntl(adev, i, j);
++
++                      if (cp_int_cntl_reg) {
++                              tmp = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
++                              tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE,
++                                                  enable ? 1 : 0);
++                              tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE,
++                                                  enable ? 1 : 0);
++                              tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE,
++                                                  enable ? 1 : 0);
++                              tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE,
++                                                  enable ? 1 : 0);
++                              WREG32_SOC15_IP(GC, cp_int_cntl_reg, tmp);
++                      }
++              }
++      }
+ }
+ static int gfx_v12_0_init_csb(struct amdgpu_device *adev)
+@@ -4755,15 +4797,42 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
+ static int gfx_v12_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
+                                             struct amdgpu_irq_src *source,
+-                                            unsigned type,
++                                            unsigned int type,
+                                             enum amdgpu_interrupt_state state)
+ {
++      u32 cp_int_cntl_reg, cp_int_cntl;
++      int i, j;
++
+       switch (state) {
+       case AMDGPU_IRQ_STATE_DISABLE:
+       case AMDGPU_IRQ_STATE_ENABLE:
+-              WREG32_FIELD15_PREREG(GC, 0, CP_INT_CNTL_RING0,
+-                                    PRIV_REG_INT_ENABLE,
+-                                    state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++              for (i = 0; i < adev->gfx.me.num_me; i++) {
++                      for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
++                              cp_int_cntl_reg = gfx_v12_0_get_cpg_int_cntl(adev, i, j);
++
++                              if (cp_int_cntl_reg) {
++                                      cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
++                                      cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
++                                                                  PRIV_REG_INT_ENABLE,
++                                                                  state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++                                      WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
++                              }
++                      }
++              }
++              for (i = 0; i < adev->gfx.mec.num_mec; i++) {
++                      for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
++                              /* MECs start at 1 */
++                              cp_int_cntl_reg = gfx_v12_0_get_cpc_int_cntl(adev, i + 1, j);
++
++                              if (cp_int_cntl_reg) {
++                                      cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
++                                      cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
++                                                                  PRIV_REG_INT_ENABLE,
++                                                                  state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++                                      WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
++                              }
++                      }
++              }
+               break;
+       default:
+               break;
+@@ -4774,15 +4843,28 @@ static int gfx_v12_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
+ static int gfx_v12_0_set_priv_inst_fault_state(struct amdgpu_device *adev,
+                                              struct amdgpu_irq_src *source,
+-                                             unsigned type,
++                                             unsigned int type,
+                                              enum amdgpu_interrupt_state state)
+ {
++      u32 cp_int_cntl_reg, cp_int_cntl;
++      int i, j;
++
+       switch (state) {
+       case AMDGPU_IRQ_STATE_DISABLE:
+       case AMDGPU_IRQ_STATE_ENABLE:
+-              WREG32_FIELD15_PREREG(GC, 0, CP_INT_CNTL_RING0,
+-                             PRIV_INSTR_INT_ENABLE,
+-                             state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++              for (i = 0; i < adev->gfx.me.num_me; i++) {
++                      for (j = 0; j < adev->gfx.me.num_pipe_per_me; j++) {
++                              cp_int_cntl_reg = gfx_v12_0_get_cpg_int_cntl(adev, i, j);
++
++                              if (cp_int_cntl_reg) {
++                                      cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
++                                      cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
++                                                                  PRIV_INSTR_INT_ENABLE,
++                                                                  state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++                                      WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
++                              }
++                      }
++              }
+               break;
+       default:
+               break;
+@@ -4806,8 +4888,8 @@ static void gfx_v12_0_handle_priv_fault(struct amdgpu_device *adev,
+       case 0:
+               for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
+                       ring = &adev->gfx.gfx_ring[i];
+-                      /* we only enabled 1 gfx queue per pipe for now */
+-                      if (ring->me == me_id && ring->pipe == pipe_id)
++                      if (ring->me == me_id && ring->pipe == pipe_id &&
++                          ring->queue == queue_id)
+                               drm_sched_fault(&ring->sched);
+               }
+               break;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-gfx12-use-rlc-safe-mode-for-soft-recovery.patch b/queue-6.11/drm-amdgpu-gfx12-use-rlc-safe-mode-for-soft-recovery.patch
new file mode 100644 (file)
index 0000000..eccc5b8
--- /dev/null
@@ -0,0 +1,35 @@
+From 1653b9648f936eb66a1e826cab7c1cf6b0fb3744 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jul 2024 18:20:13 -0400
+Subject: drm/amdgpu/gfx12: use rlc safe mode for soft recovery
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit 21818f39beda2e843199e5d8d9e3f9e43c8080a3 ]
+
+Protect the MMIO access with safe mode.
+
+Acked-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+index ac671656069a3..515fc7d6f8389 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+@@ -4613,7 +4613,9 @@ static void gfx_v12_0_ring_soft_recovery(struct amdgpu_ring *ring,
+       value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
+       value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
+       value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
++      amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
+       WREG32_SOC15(GC, 0, regSQ_CMD, value);
++      amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
+ }
+ static void
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-gfx9-properly-handle-error-ints-on-all-pi.patch b/queue-6.11/drm-amdgpu-gfx9-properly-handle-error-ints-on-all-pi.patch
new file mode 100644 (file)
index 0000000..c9055b1
--- /dev/null
@@ -0,0 +1,170 @@
+From ff24f4e10d117a646d11fa72c6f39bfce411f27d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jul 2024 10:24:59 -0400
+Subject: drm/amdgpu/gfx9: properly handle error ints on all pipes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit 48695573d2feaf42812c1ad54e01caff0d1c2d71 ]
+
+Need to handle the interrupt enables for all pipes.
+
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c   | 44 +++++++++++++++++++++-
+ drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 50 +++++++++++++++++++++++--
+ 2 files changed, 89 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+index fc4153a87f947..7d517c94c3efb 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+@@ -2638,7 +2638,7 @@ static void gfx_v9_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
+       tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE, enable ? 1 : 0);
+       tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE, enable ? 1 : 0);
+       tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, enable ? 1 : 0);
+-      if(adev->gfx.num_gfx_rings)
++      if (adev->gfx.num_gfx_rings)
+               tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, enable ? 1 : 0);
+       WREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0, tmp);
+@@ -5933,17 +5933,59 @@ static void gfx_v9_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
+       }
+ }
++static u32 gfx_v9_0_get_cpc_int_cntl(struct amdgpu_device *adev,
++                                   int me, int pipe)
++{
++      /*
++       * amdgpu controls only the first MEC. That's why this function only
++       * handles the setting of interrupts for this specific MEC. All other
++       * pipes' interrupts are set by amdkfd.
++       */
++      if (me != 1)
++              return 0;
++
++      switch (pipe) {
++      case 0:
++              return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE0_INT_CNTL);
++      case 1:
++              return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE1_INT_CNTL);
++      case 2:
++              return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE2_INT_CNTL);
++      case 3:
++              return SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE3_INT_CNTL);
++      default:
++              return 0;
++      }
++}
++
+ static int gfx_v9_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
+                                            struct amdgpu_irq_src *source,
+                                            unsigned type,
+                                            enum amdgpu_interrupt_state state)
+ {
++      u32 cp_int_cntl_reg, cp_int_cntl;
++      int i, j;
++
+       switch (state) {
+       case AMDGPU_IRQ_STATE_DISABLE:
+       case AMDGPU_IRQ_STATE_ENABLE:
+               WREG32_FIELD15(GC, 0, CP_INT_CNTL_RING0,
+                              PRIV_REG_INT_ENABLE,
+                              state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++              for (i = 0; i < adev->gfx.mec.num_mec; i++) {
++                      for (j = 0; j < adev->gfx.mec.num_pipe_per_mec; j++) {
++                              /* MECs start at 1 */
++                              cp_int_cntl_reg = gfx_v9_0_get_cpc_int_cntl(adev, i + 1, j);
++
++                              if (cp_int_cntl_reg) {
++                                      cp_int_cntl = RREG32_SOC15_IP(GC, cp_int_cntl_reg);
++                                      cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_ME1_PIPE0_INT_CNTL,
++                                                                  PRIV_REG_INT_ENABLE,
++                                                                  state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++                                      WREG32_SOC15_IP(GC, cp_int_cntl_reg, cp_int_cntl);
++                              }
++                      }
++              }
+               break;
+       default:
+               break;
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+index 20ea6cb01edfd..d95f9a84f97b4 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+@@ -2886,21 +2886,63 @@ static void gfx_v9_4_3_xcc_set_compute_eop_interrupt_state(
+       }
+ }
++static u32 gfx_v9_4_3_get_cpc_int_cntl(struct amdgpu_device *adev,
++                                   int xcc_id, int me, int pipe)
++{
++      /*
++       * amdgpu controls only the first MEC. That's why this function only
++       * handles the setting of interrupts for this specific MEC. All other
++       * pipes' interrupts are set by amdkfd.
++       */
++      if (me != 1)
++              return 0;
++
++      switch (pipe) {
++      case 0:
++              return SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE0_INT_CNTL);
++      case 1:
++              return SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE1_INT_CNTL);
++      case 2:
++              return SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE2_INT_CNTL);
++      case 3:
++              return SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), regCP_ME1_PIPE3_INT_CNTL);
++      default:
++              return 0;
++      }
++}
++
+ static int gfx_v9_4_3_set_priv_reg_fault_state(struct amdgpu_device *adev,
+                                            struct amdgpu_irq_src *source,
+                                            unsigned type,
+                                            enum amdgpu_interrupt_state state)
+ {
+-      int i, num_xcc;
++      u32 mec_int_cntl_reg, mec_int_cntl;
++      int i, j, k, num_xcc;
+       num_xcc = NUM_XCC(adev->gfx.xcc_mask);
+       switch (state) {
+       case AMDGPU_IRQ_STATE_DISABLE:
+       case AMDGPU_IRQ_STATE_ENABLE:
+-              for (i = 0; i < num_xcc; i++)
++              for (i = 0; i < num_xcc; i++) {
+                       WREG32_FIELD15_PREREG(GC, GET_INST(GC, i), CP_INT_CNTL_RING0,
+-                              PRIV_REG_INT_ENABLE,
+-                              state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++                                            PRIV_REG_INT_ENABLE,
++                                            state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++                      for (j = 0; j < adev->gfx.mec.num_mec; j++) {
++                              for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) {
++                                      /* MECs start at 1 */
++                                      mec_int_cntl_reg = gfx_v9_4_3_get_cpc_int_cntl(adev, i, j + 1, k);
++
++                                      if (mec_int_cntl_reg) {
++                                              mec_int_cntl = RREG32_XCC(mec_int_cntl_reg, i);
++                                              mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL,
++                                                                           PRIV_REG_INT_ENABLE,
++                                                                           state == AMDGPU_IRQ_STATE_ENABLE ?
++                                                                           1 : 0);
++                                              WREG32_XCC(mec_int_cntl_reg, mec_int_cntl, i);
++                                      }
++                              }
++                      }
++              }
+               break;
+       default:
+               break;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdgpu-gfx9-use-rlc-safe-mode-for-soft-recovery.patch b/queue-6.11/drm-amdgpu-gfx9-use-rlc-safe-mode-for-soft-recovery.patch
new file mode 100644 (file)
index 0000000..2ada603
--- /dev/null
@@ -0,0 +1,35 @@
+From fffa2733abd32366156b9ff4340aef7cbf65f556 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jul 2024 18:20:57 -0400
+Subject: drm/amdgpu/gfx9: use rlc safe mode for soft recovery
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit 3ec2ad7c34c412bd9264cd1ff235d0812be90e82 ]
+
+Protect the MMIO access with safe mode.
+
+Acked-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+index 6f178bfb8f104..02eb5bd9d7d82 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+@@ -5862,7 +5862,9 @@ static void gfx_v9_0_ring_soft_recovery(struct amdgpu_ring *ring, unsigned vmid)
+       value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
+       value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
+       value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
++      amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
+       WREG32_SOC15(GC, 0, mmSQ_CMD, value);
++      amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
+ }
+ static void gfx_v9_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdkfd-amdkfd_free_gtt_mem-clear-the-correct-poi.patch b/queue-6.11/drm-amdkfd-amdkfd_free_gtt_mem-clear-the-correct-poi.patch
new file mode 100644 (file)
index 0000000..a9b1b48
--- /dev/null
@@ -0,0 +1,165 @@
+From 61b3843ea68d82fa4ae15a218b92a369734bd9ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Jul 2024 11:11:05 -0400
+Subject: drm/amdkfd: amdkfd_free_gtt_mem clear the correct pointer
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit c86ad39140bbcb9dc75a10046c2221f657e8083b ]
+
+Pass pointer reference to amdgpu_bo_unref to clear the correct pointer,
+otherwise amdgpu_bo_unref clear the local variable, the original pointer
+not set to NULL, this could cause use-after-free bug.
+
+Signed-off-by: Philip Yang <Philip.Yang@amd.com>
+Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c         | 14 +++++++-------
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h         |  2 +-
+ drivers/gpu/drm/amd/amdkfd/kfd_chardev.c           |  2 +-
+ drivers/gpu/drm/amd/amdkfd/kfd_device.c            |  4 ++--
+ .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c  |  2 +-
+ drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c       |  2 +-
+ drivers/gpu/drm/amd/amdkfd/kfd_process.c           |  2 +-
+ .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c |  4 ++--
+ 8 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+index 03205e3c37463..c272461d70a9a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -364,15 +364,15 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,
+       return r;
+ }
+-void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void *mem_obj)
++void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void **mem_obj)
+ {
+-      struct amdgpu_bo *bo = (struct amdgpu_bo *) mem_obj;
++      struct amdgpu_bo **bo = (struct amdgpu_bo **) mem_obj;
+-      amdgpu_bo_reserve(bo, true);
+-      amdgpu_bo_kunmap(bo);
+-      amdgpu_bo_unpin(bo);
+-      amdgpu_bo_unreserve(bo);
+-      amdgpu_bo_unref(&(bo));
++      amdgpu_bo_reserve(*bo, true);
++      amdgpu_bo_kunmap(*bo);
++      amdgpu_bo_unpin(*bo);
++      amdgpu_bo_unreserve(*bo);
++      amdgpu_bo_unref(bo);
+ }
+ int amdgpu_amdkfd_alloc_gws(struct amdgpu_device *adev, size_t size,
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+index e7bb1ca358014..8b4108a23636a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+@@ -235,7 +235,7 @@ int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo,
+ int amdgpu_amdkfd_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,
+                               void **mem_obj, uint64_t *gpu_addr,
+                               void **cpu_ptr, bool mqd_gfx9);
+-void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void *mem_obj);
++void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void **mem_obj);
+ int amdgpu_amdkfd_alloc_gws(struct amdgpu_device *adev, size_t size,
+                               void **mem_obj);
+ void amdgpu_amdkfd_free_gws(struct amdgpu_device *adev, void *mem_obj);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+index 32e5db509560e..546b02f2241a6 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+@@ -423,7 +423,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
+ err_create_queue:
+       if (wptr_bo)
+-              amdgpu_amdkfd_free_gtt_mem(dev->adev, wptr_bo);
++              amdgpu_amdkfd_free_gtt_mem(dev->adev, (void **)&wptr_bo);
+ err_wptr_map_gart:
+ err_bind_process:
+ err_pdd:
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+index f4d20adaa0689..6619028dd58ba 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+@@ -907,7 +907,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
+ kfd_doorbell_error:
+       kfd_gtt_sa_fini(kfd);
+ kfd_gtt_sa_init_error:
+-      amdgpu_amdkfd_free_gtt_mem(kfd->adev, kfd->gtt_mem);
++      amdgpu_amdkfd_free_gtt_mem(kfd->adev, &kfd->gtt_mem);
+ alloc_gtt_mem_failure:
+       dev_err(kfd_device,
+               "device %x:%x NOT added due to errors\n",
+@@ -925,7 +925,7 @@ void kgd2kfd_device_exit(struct kfd_dev *kfd)
+               kfd_doorbell_fini(kfd);
+               ida_destroy(&kfd->doorbell_ida);
+               kfd_gtt_sa_fini(kfd);
+-              amdgpu_amdkfd_free_gtt_mem(kfd->adev, kfd->gtt_mem);
++              amdgpu_amdkfd_free_gtt_mem(kfd->adev, &kfd->gtt_mem);
+       }
+       kfree(kfd);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+index 4f48507418d2f..420444eb8e982 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+@@ -2621,7 +2621,7 @@ static void deallocate_hiq_sdma_mqd(struct kfd_node *dev,
+ {
+       WARN(!mqd, "No hiq sdma mqd trunk to free");
+-      amdgpu_amdkfd_free_gtt_mem(dev->adev, mqd->gtt_mem);
++      amdgpu_amdkfd_free_gtt_mem(dev->adev, &mqd->gtt_mem);
+ }
+ void device_queue_manager_uninit(struct device_queue_manager *dqm)
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
+index 50a81da43ce19..d9ae854b69084 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
+@@ -225,7 +225,7 @@ void kfd_free_mqd_cp(struct mqd_manager *mm, void *mqd,
+             struct kfd_mem_obj *mqd_mem_obj)
+ {
+       if (mqd_mem_obj->gtt_mem) {
+-              amdgpu_amdkfd_free_gtt_mem(mm->dev->adev, mqd_mem_obj->gtt_mem);
++              amdgpu_amdkfd_free_gtt_mem(mm->dev->adev, &mqd_mem_obj->gtt_mem);
+               kfree(mqd_mem_obj);
+       } else {
+               kfd_gtt_sa_free(mm->dev, mqd_mem_obj);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index 17e42161b0151..9e29b92eb523d 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -1048,7 +1048,7 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
+               if (pdd->dev->kfd->shared_resources.enable_mes)
+                       amdgpu_amdkfd_free_gtt_mem(pdd->dev->adev,
+-                                                 pdd->proc_ctx_bo);
++                                                 &pdd->proc_ctx_bo);
+               /*
+                * before destroying pdd, make sure to report availability
+                * for auto suspend
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+index 21f5a1fb3bf88..36f0460cbffe6 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+@@ -204,9 +204,9 @@ static void pqm_clean_queue_resource(struct process_queue_manager *pqm,
+       }
+       if (dev->kfd->shared_resources.enable_mes) {
+-              amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->gang_ctx_bo);
++              amdgpu_amdkfd_free_gtt_mem(dev->adev, &pqn->q->gang_ctx_bo);
+               if (pqn->q->wptr_bo)
+-                      amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->wptr_bo);
++                      amdgpu_amdkfd_free_gtt_mem(dev->adev, (void **)&pqn->q->wptr_bo);
+       }
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdkfd-check-int-source-id-for-utcl2-poison-even.patch b/queue-6.11/drm-amdkfd-check-int-source-id-for-utcl2-poison-even.patch
new file mode 100644 (file)
index 0000000..853fd10
--- /dev/null
@@ -0,0 +1,76 @@
+From fad058802ea2acbcf3efe1eb45a8b76621e32d9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Aug 2024 13:56:32 +0800
+Subject: drm/amdkfd: Check int source id for utcl2 poison event
+
+From: Hawking Zhang <Hawking.Zhang@amd.com>
+
+[ Upstream commit db6341a9168d2a24ded526277eeab29724d76e9d ]
+
+Traditional utcl2 fault_status polling does not
+work in SRIOV environment. The polling of fault
+status register from guest side will be dropped
+by hardware.
+
+Driver should switch to check utcl2 interrupt
+source id to identify utcl2 poison event. It is
+set to 1 when poisoned data interrupts are
+signaled.
+
+v2: drop the unused local variable (Tao)
+
+Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
+Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/amdkfd/kfd_int_process_v9.c    | 18 +-----------------
+ drivers/gpu/drm/amd/amdkfd/soc15_int.h         |  1 +
+ 2 files changed, 2 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+index a9c3580be8c9b..fecdbbab98949 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+@@ -431,25 +431,9 @@ static void event_interrupt_wq_v9(struct kfd_node *dev,
+                  client_id == SOC15_IH_CLIENTID_UTCL2) {
+               struct kfd_vm_fault_info info = {0};
+               uint16_t ring_id = SOC15_RING_ID_FROM_IH_ENTRY(ih_ring_entry);
+-              uint32_t node_id = SOC15_NODEID_FROM_IH_ENTRY(ih_ring_entry);
+-              uint32_t vmid_type = SOC15_VMID_TYPE_FROM_IH_ENTRY(ih_ring_entry);
+-              int hub_inst = 0;
+               struct kfd_hsa_memory_exception_data exception_data;
+-              /* gfxhub */
+-              if (!vmid_type && dev->adev->gfx.funcs->ih_node_to_logical_xcc) {
+-                      hub_inst = dev->adev->gfx.funcs->ih_node_to_logical_xcc(dev->adev,
+-                              node_id);
+-                      if (hub_inst < 0)
+-                              hub_inst = 0;
+-              }
+-
+-              /* mmhub */
+-              if (vmid_type && client_id == SOC15_IH_CLIENTID_VMC)
+-                      hub_inst = node_id / 4;
+-
+-              if (amdgpu_amdkfd_ras_query_utcl2_poison_status(dev->adev,
+-                                      hub_inst, vmid_type)) {
++              if (source_id == SOC15_INTSRC_VMC_UTCL2_POISON) {
+                       event_interrupt_poison_consumption_v9(dev, pasid, client_id);
+                       return;
+               }
+diff --git a/drivers/gpu/drm/amd/amdkfd/soc15_int.h b/drivers/gpu/drm/amd/amdkfd/soc15_int.h
+index 10138676f27fd..e5c0205f26181 100644
+--- a/drivers/gpu/drm/amd/amdkfd/soc15_int.h
++++ b/drivers/gpu/drm/amd/amdkfd/soc15_int.h
+@@ -29,6 +29,7 @@
+ #define SOC15_INTSRC_CP_BAD_OPCODE    183
+ #define SOC15_INTSRC_SQ_INTERRUPT_MSG 239
+ #define SOC15_INTSRC_VMC_FAULT                0
++#define SOC15_INTSRC_VMC_UTCL2_POISON 1
+ #define SOC15_INTSRC_SDMA_TRAP                224
+ #define SOC15_INTSRC_SDMA_ECC         220
+ #define SOC21_INTSRC_SDMA_TRAP                49
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-amdkfd-fix-resource-leak-in-criu-restore-queue.patch b/queue-6.11/drm-amdkfd-fix-resource-leak-in-criu-restore-queue.patch
new file mode 100644 (file)
index 0000000..4bf27c5
--- /dev/null
@@ -0,0 +1,35 @@
+From 848b0bd84971416af72a2817e33487fa5f2c2b92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Sep 2024 11:29:55 +0800
+Subject: drm/amdkfd: Fix resource leak in criu restore queue
+
+From: Jesse Zhang <jesse.zhang@amd.com>
+
+[ Upstream commit aa47fe8d3595365a935921a90d00bc33ee374728 ]
+
+To avoid memory leaks, release q_extra_data when exiting the restore queue.
+v2: Correct the proto (Alex)
+
+Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
+Reviewed-by: Tim Huang <tim.huang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+index 36f0460cbffe6..e0f19f3ae2207 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+@@ -988,6 +988,7 @@ int kfd_criu_restore_queue(struct kfd_process *p,
+               pr_debug("Queue id %d was restored successfully\n", queue_id);
+       kfree(q_data);
++      kfree(q_extra_data);
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-msm-adreno-assign-msm_gpu-pdev-earlier-to-avoid-.patch b/queue-6.11/drm-msm-adreno-assign-msm_gpu-pdev-earlier-to-avoid-.patch
new file mode 100644 (file)
index 0000000..82188ae
--- /dev/null
@@ -0,0 +1,61 @@
+From a16a99e004ebeceb50141ce0af8c7b262337dee4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Jul 2024 13:15:40 +0200
+Subject: drm/msm/adreno: Assign msm_gpu->pdev earlier to avoid nullptrs
+
+From: Konrad Dybcio <konrad.dybcio@linaro.org>
+
+[ Upstream commit 16007768551d5bfe53426645401435ca8d2ef54f ]
+
+There are some cases, such as the one uncovered by Commit 46d4efcccc68
+("drm/msm/a6xx: Avoid a nullptr dereference when speedbin setting fails")
+where
+
+msm_gpu_cleanup() : platform_set_drvdata(gpu->pdev, NULL);
+
+is called on gpu->pdev == NULL, as the GPU device has not been fully
+initialized yet.
+
+Turns out that there's more than just the aforementioned path that
+causes this to happen (e.g. the case when there's speedbin data in the
+catalog, but opp-supported-hw is missing in DT).
+
+Assigning msm_gpu->pdev earlier seems like the least painful solution
+to this, therefore do so.
+
+Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Patchwork: https://patchwork.freedesktop.org/patch/602742/
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/adreno/adreno_gpu.c | 1 +
+ drivers/gpu/drm/msm/msm_gpu.c           | 1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+index 3896123ec51c9..83caca2c4026a 100644
+--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
++++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+@@ -1083,6 +1083,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
+       adreno_gpu->chip_id = config->chip_id;
+       gpu->allow_relocs = config->info->family < ADRENO_6XX_GEN1;
++      gpu->pdev = pdev;
+       /* Only handle the core clock when GMU is not in use (or is absent). */
+       if (adreno_has_gmu_wrapper(adreno_gpu) ||
+diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
+index 3666b42b4ecd7..a274b84664237 100644
+--- a/drivers/gpu/drm/msm/msm_gpu.c
++++ b/drivers/gpu/drm/msm/msm_gpu.c
+@@ -931,7 +931,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
+       if (IS_ERR(gpu->gpu_cx))
+               gpu->gpu_cx = NULL;
+-      gpu->pdev = pdev;
+       platform_set_drvdata(pdev, &gpu->adreno_smmu);
+       msm_devfreq_init(gpu);
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-printer-allow-null-data-in-devcoredump-printer.patch b/queue-6.11/drm-printer-allow-null-data-in-devcoredump-printer.patch
new file mode 100644 (file)
index 0000000..e3a0e7e
--- /dev/null
@@ -0,0 +1,144 @@
+From 41cb8c66b8d8fdd5a5cb87198e791ea9c87c61ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 08:41:17 -0700
+Subject: drm/printer: Allow NULL data in devcoredump printer
+
+From: Matthew Brost <matthew.brost@intel.com>
+
+[ Upstream commit 53369581dc0c68a5700ed51e1660f44c4b2bb524 ]
+
+We want to determine the size of the devcoredump before writing it out.
+To that end, we will run the devcoredump printer with NULL data to get
+the size, alloc data based on the generated offset, then run the
+devcorecump again with a valid data pointer to print.  This necessitates
+not writing data to the data pointer on the initial pass, when it is
+NULL.
+
+v5:
+ - Better commit message (Jonathan)
+ - Add kerenl doc with examples (Jani)
+
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Acked-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Jonathan Cavitt <jonathan.cavitt@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240801154118.2547543-3-matthew.brost@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_print.c | 13 +++++----
+ include/drm/drm_print.h     | 54 ++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 61 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
+index cf24dfdeb6b27..0081190201a7f 100644
+--- a/drivers/gpu/drm/drm_print.c
++++ b/drivers/gpu/drm/drm_print.c
+@@ -100,8 +100,9 @@ void __drm_puts_coredump(struct drm_printer *p, const char *str)
+                       copy = iterator->remain;
+               /* Copy out the bit of the string that we need */
+-              memcpy(iterator->data,
+-                      str + (iterator->start - iterator->offset), copy);
++              if (iterator->data)
++                      memcpy(iterator->data,
++                             str + (iterator->start - iterator->offset), copy);
+               iterator->offset = iterator->start + copy;
+               iterator->remain -= copy;
+@@ -110,7 +111,8 @@ void __drm_puts_coredump(struct drm_printer *p, const char *str)
+               len = min_t(ssize_t, strlen(str), iterator->remain);
+-              memcpy(iterator->data + pos, str, len);
++              if (iterator->data)
++                      memcpy(iterator->data + pos, str, len);
+               iterator->offset += len;
+               iterator->remain -= len;
+@@ -140,8 +142,9 @@ void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
+       if ((iterator->offset >= iterator->start) && (len < iterator->remain)) {
+               ssize_t pos = iterator->offset - iterator->start;
+-              snprintf(((char *) iterator->data) + pos,
+-                      iterator->remain, "%pV", vaf);
++              if (iterator->data)
++                      snprintf(((char *) iterator->data) + pos,
++                               iterator->remain, "%pV", vaf);
+               iterator->offset += len;
+               iterator->remain -= len;
+diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
+index 5d9dff5149c99..d2676831d765d 100644
+--- a/include/drm/drm_print.h
++++ b/include/drm/drm_print.h
+@@ -221,7 +221,8 @@ drm_vprintf(struct drm_printer *p, const char *fmt, va_list *va)
+ /**
+  * struct drm_print_iterator - local struct used with drm_printer_coredump
+- * @data: Pointer to the devcoredump output buffer
++ * @data: Pointer to the devcoredump output buffer, can be NULL if using
++ * drm_printer_coredump to determine size of devcoredump
+  * @start: The offset within the buffer to start writing
+  * @remain: The number of bytes to write for this iteration
+  */
+@@ -266,6 +267,57 @@ struct drm_print_iterator {
+  *                    coredump_read, ...)
+  *    }
+  *
++ * The above example has a time complexity of O(N^2), where N is the size of the
++ * devcoredump. This is acceptable for small devcoredumps but scales poorly for
++ * larger ones.
++ *
++ * Another use case for drm_coredump_printer is to capture the devcoredump into
++ * a saved buffer before the dev_coredump() callback. This involves two passes:
++ * one to determine the size of the devcoredump and another to print it to a
++ * buffer. Then, in dev_coredump(), copy from the saved buffer into the
++ * devcoredump read buffer.
++ *
++ * For example::
++ *
++ *    char *devcoredump_saved_buffer;
++ *
++ *    ssize_t __coredump_print(char *buffer, ssize_t count, ...)
++ *    {
++ *            struct drm_print_iterator iter;
++ *            struct drm_printer p;
++ *
++ *            iter.data = buffer;
++ *            iter.start = 0;
++ *            iter.remain = count;
++ *
++ *            p = drm_coredump_printer(&iter);
++ *
++ *            drm_printf(p, "foo=%d\n", foo);
++ *            ...
++ *            return count - iter.remain;
++ *    }
++ *
++ *    void coredump_print(...)
++ *    {
++ *            ssize_t count;
++ *
++ *            count = __coredump_print(NULL, INT_MAX, ...);
++ *            devcoredump_saved_buffer = kvmalloc(count, GFP_KERNEL);
++ *            __coredump_print(devcoredump_saved_buffer, count, ...);
++ *    }
++ *
++ *    void coredump_read(char *buffer, loff_t offset, size_t count,
++ *                       void *data, size_t datalen)
++ *    {
++ *            ...
++ *            memcpy(buffer, devcoredump_saved_buffer + offset, count);
++ *            ...
++ *    }
++ *
++ * The above example has a time complexity of O(N*2), where N is the size of the
++ * devcoredump. This scales better than the previous example for larger
++ * devcoredumps.
++ *
+  * RETURNS:
+  * The &drm_printer object
+  */
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-radeon-r100-handle-unknown-family-in-r100_cp_ini.patch b/queue-6.11/drm-radeon-r100-handle-unknown-family-in-r100_cp_ini.patch
new file mode 100644 (file)
index 0000000..9d3bb95
--- /dev/null
@@ -0,0 +1,140 @@
+From 1ff52199779d20faa35666827902199e3c4bd909 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 17:58:12 +0200
+Subject: drm/radeon/r100: Handle unknown family in r100_cp_init_microcode()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+[ Upstream commit c6dbab46324b1742b50dc2fb5c1fee2c28129439 ]
+
+With -Werror:
+
+    In function ‘r100_cp_init_microcode’,
+       inlined from ‘r100_cp_init’ at drivers/gpu/drm/radeon/r100.c:1136:7:
+    include/linux/printk.h:465:44: error: ‘%s’ directive argument is null [-Werror=format-overflow=]
+      465 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
+         |                                            ^
+    include/linux/printk.h:437:17: note: in definition of macro ‘printk_index_wrap’
+      437 |                 _p_func(_fmt, ##__VA_ARGS__);                           \
+         |                 ^~~~~~~
+    include/linux/printk.h:508:9: note: in expansion of macro ‘printk’
+      508 |         printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+         |         ^~~~~~
+    drivers/gpu/drm/radeon/r100.c:1062:17: note: in expansion of macro ‘pr_err’
+     1062 |                 pr_err("radeon_cp: Failed to load firmware \"%s\"\n", fw_name);
+         |                 ^~~~~~
+
+Fix this by converting the if/else if/... construct into a proper
+switch() statement with a default to handle the error case.
+
+As a bonus, the generated code is ca. 100 bytes smaller (with gcc 11.4.0
+targeting arm32).
+
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/radeon/r100.c | 70 ++++++++++++++++++++++-------------
+ 1 file changed, 45 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
+index 0b1e19345f43a..bfd42e3e161e9 100644
+--- a/drivers/gpu/drm/radeon/r100.c
++++ b/drivers/gpu/drm/radeon/r100.c
+@@ -1016,45 +1016,65 @@ static int r100_cp_init_microcode(struct radeon_device *rdev)
+       DRM_DEBUG_KMS("\n");
+-      if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) ||
+-          (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) ||
+-          (rdev->family == CHIP_RS200)) {
++      switch (rdev->family) {
++      case CHIP_R100:
++      case CHIP_RV100:
++      case CHIP_RV200:
++      case CHIP_RS100:
++      case CHIP_RS200:
+               DRM_INFO("Loading R100 Microcode\n");
+               fw_name = FIRMWARE_R100;
+-      } else if ((rdev->family == CHIP_R200) ||
+-                 (rdev->family == CHIP_RV250) ||
+-                 (rdev->family == CHIP_RV280) ||
+-                 (rdev->family == CHIP_RS300)) {
++              break;
++
++      case CHIP_R200:
++      case CHIP_RV250:
++      case CHIP_RV280:
++      case CHIP_RS300:
+               DRM_INFO("Loading R200 Microcode\n");
+               fw_name = FIRMWARE_R200;
+-      } else if ((rdev->family == CHIP_R300) ||
+-                 (rdev->family == CHIP_R350) ||
+-                 (rdev->family == CHIP_RV350) ||
+-                 (rdev->family == CHIP_RV380) ||
+-                 (rdev->family == CHIP_RS400) ||
+-                 (rdev->family == CHIP_RS480)) {
++              break;
++
++      case CHIP_R300:
++      case CHIP_R350:
++      case CHIP_RV350:
++      case CHIP_RV380:
++      case CHIP_RS400:
++      case CHIP_RS480:
+               DRM_INFO("Loading R300 Microcode\n");
+               fw_name = FIRMWARE_R300;
+-      } else if ((rdev->family == CHIP_R420) ||
+-                 (rdev->family == CHIP_R423) ||
+-                 (rdev->family == CHIP_RV410)) {
++              break;
++
++      case CHIP_R420:
++      case CHIP_R423:
++      case CHIP_RV410:
+               DRM_INFO("Loading R400 Microcode\n");
+               fw_name = FIRMWARE_R420;
+-      } else if ((rdev->family == CHIP_RS690) ||
+-                 (rdev->family == CHIP_RS740)) {
++              break;
++
++      case CHIP_RS690:
++      case CHIP_RS740:
+               DRM_INFO("Loading RS690/RS740 Microcode\n");
+               fw_name = FIRMWARE_RS690;
+-      } else if (rdev->family == CHIP_RS600) {
++              break;
++
++      case CHIP_RS600:
+               DRM_INFO("Loading RS600 Microcode\n");
+               fw_name = FIRMWARE_RS600;
+-      } else if ((rdev->family == CHIP_RV515) ||
+-                 (rdev->family == CHIP_R520) ||
+-                 (rdev->family == CHIP_RV530) ||
+-                 (rdev->family == CHIP_R580) ||
+-                 (rdev->family == CHIP_RV560) ||
+-                 (rdev->family == CHIP_RV570)) {
++              break;
++
++      case CHIP_RV515:
++      case CHIP_R520:
++      case CHIP_RV530:
++      case CHIP_R580:
++      case CHIP_RV560:
++      case CHIP_RV570:
+               DRM_INFO("Loading R500 Microcode\n");
+               fw_name = FIRMWARE_R520;
++              break;
++
++      default:
++              DRM_ERROR("Unsupported Radeon family %u\n", rdev->family);
++              return -EINVAL;
+       }
+       err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-stm-avoid-use-after-free-issues-with-crtc-and-pl.patch b/queue-6.11/drm-stm-avoid-use-after-free-issues-with-crtc-and-pl.patch
new file mode 100644 (file)
index 0000000..6f393c3
--- /dev/null
@@ -0,0 +1,254 @@
+From 80c23b5a788f5bfc1195c51cae81cfadcb905127 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Feb 2024 15:50:40 +0300
+Subject: drm/stm: Avoid use-after-free issues with crtc and plane
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Katya Orlova <e.orlova@ispras.ru>
+
+[ Upstream commit 19dd9780b7ac673be95bf6fd6892a184c9db611f ]
+
+ltdc_load() calls functions drm_crtc_init_with_planes(),
+drm_universal_plane_init() and drm_encoder_init(). These functions
+should not be called with parameters allocated with devm_kzalloc()
+to avoid use-after-free issues [1].
+
+Use allocations managed by the DRM framework.
+
+Found by Linux Verification Center (linuxtesting.org).
+
+[1]
+https://lore.kernel.org/lkml/u366i76e3qhh3ra5oxrtngjtm2u5lterkekcz6y2jkndhuxzli@diujon4h7qwb/
+
+Signed-off-by: Katya Orlova <e.orlova@ispras.ru>
+Acked-by: Raphaël Gallais-Pou <raphael.gallais-pou@foss.st.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240216125040.8968-1-e.orlova@ispras.ru
+Signed-off-by: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/stm/drv.c  |  3 +-
+ drivers/gpu/drm/stm/ltdc.c | 73 ++++++++++----------------------------
+ 2 files changed, 20 insertions(+), 56 deletions(-)
+
+diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
+index 4d2db079ad4ff..e1232f74dfa53 100644
+--- a/drivers/gpu/drm/stm/drv.c
++++ b/drivers/gpu/drm/stm/drv.c
+@@ -25,6 +25,7 @@
+ #include <drm/drm_module.h>
+ #include <drm/drm_probe_helper.h>
+ #include <drm/drm_vblank.h>
++#include <drm/drm_managed.h>
+ #include "ltdc.h"
+@@ -75,7 +76,7 @@ static int drv_load(struct drm_device *ddev)
+       DRM_DEBUG("%s\n", __func__);
+-      ldev = devm_kzalloc(ddev->dev, sizeof(*ldev), GFP_KERNEL);
++      ldev = drmm_kzalloc(ddev, sizeof(*ldev), GFP_KERNEL);
+       if (!ldev)
+               return -ENOMEM;
+diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
+index 5aec1e58c968c..056642d12265c 100644
+--- a/drivers/gpu/drm/stm/ltdc.c
++++ b/drivers/gpu/drm/stm/ltdc.c
+@@ -36,6 +36,7 @@
+ #include <drm/drm_probe_helper.h>
+ #include <drm/drm_simple_kms_helper.h>
+ #include <drm/drm_vblank.h>
++#include <drm/drm_managed.h>
+ #include <video/videomode.h>
+@@ -1199,7 +1200,6 @@ static void ltdc_crtc_atomic_print_state(struct drm_printer *p,
+ }
+ static const struct drm_crtc_funcs ltdc_crtc_funcs = {
+-      .destroy = drm_crtc_cleanup,
+       .set_config = drm_atomic_helper_set_config,
+       .page_flip = drm_atomic_helper_page_flip,
+       .reset = drm_atomic_helper_crtc_reset,
+@@ -1212,7 +1212,6 @@ static const struct drm_crtc_funcs ltdc_crtc_funcs = {
+ };
+ static const struct drm_crtc_funcs ltdc_crtc_with_crc_support_funcs = {
+-      .destroy = drm_crtc_cleanup,
+       .set_config = drm_atomic_helper_set_config,
+       .page_flip = drm_atomic_helper_page_flip,
+       .reset = drm_atomic_helper_crtc_reset,
+@@ -1545,7 +1544,6 @@ static void ltdc_plane_atomic_print_state(struct drm_printer *p,
+ static const struct drm_plane_funcs ltdc_plane_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+-      .destroy = drm_plane_cleanup,
+       .reset = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+@@ -1572,7 +1570,6 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
+       const u64 *modifiers = ltdc_format_modifiers;
+       u32 lofs = index * LAY_OFS;
+       u32 val;
+-      int ret;
+       /* Allocate the biggest size according to supported color formats */
+       formats = devm_kzalloc(dev, (ldev->caps.pix_fmt_nb +
+@@ -1615,14 +1612,10 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
+               }
+       }
+-      plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL);
+-      if (!plane)
+-              return NULL;
+-
+-      ret = drm_universal_plane_init(ddev, plane, possible_crtcs,
+-                                     &ltdc_plane_funcs, formats, nb_fmt,
+-                                     modifiers, type, NULL);
+-      if (ret < 0)
++      plane = drmm_universal_plane_alloc(ddev, struct drm_plane, dev,
++                                         possible_crtcs, &ltdc_plane_funcs, formats,
++                                         nb_fmt, modifiers, type, NULL);
++      if (IS_ERR(plane))
+               return NULL;
+       if (ldev->caps.ycbcr_input) {
+@@ -1645,15 +1638,6 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
+       return plane;
+ }
+-static void ltdc_plane_destroy_all(struct drm_device *ddev)
+-{
+-      struct drm_plane *plane, *plane_temp;
+-
+-      list_for_each_entry_safe(plane, plane_temp,
+-                               &ddev->mode_config.plane_list, head)
+-              drm_plane_cleanup(plane);
+-}
+-
+ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
+ {
+       struct ltdc_device *ldev = ddev->dev_private;
+@@ -1679,14 +1663,14 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
+       /* Init CRTC according to its hardware features */
+       if (ldev->caps.crc)
+-              ret = drm_crtc_init_with_planes(ddev, crtc, primary, NULL,
+-                                              &ltdc_crtc_with_crc_support_funcs, NULL);
++              ret = drmm_crtc_init_with_planes(ddev, crtc, primary, NULL,
++                                               &ltdc_crtc_with_crc_support_funcs, NULL);
+       else
+-              ret = drm_crtc_init_with_planes(ddev, crtc, primary, NULL,
+-                                              &ltdc_crtc_funcs, NULL);
++              ret = drmm_crtc_init_with_planes(ddev, crtc, primary, NULL,
++                                               &ltdc_crtc_funcs, NULL);
+       if (ret) {
+               DRM_ERROR("Can not initialize CRTC\n");
+-              goto cleanup;
++              return ret;
+       }
+       drm_crtc_helper_add(crtc, &ltdc_crtc_helper_funcs);
+@@ -1700,9 +1684,8 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
+       for (i = 1; i < ldev->caps.nb_layers; i++) {
+               overlay = ltdc_plane_create(ddev, DRM_PLANE_TYPE_OVERLAY, i);
+               if (!overlay) {
+-                      ret = -ENOMEM;
+                       DRM_ERROR("Can not create overlay plane %d\n", i);
+-                      goto cleanup;
++                      return -ENOMEM;
+               }
+               if (ldev->caps.dynamic_zorder)
+                       drm_plane_create_zpos_property(overlay, i, 0, ldev->caps.nb_layers - 1);
+@@ -1715,10 +1698,6 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
+       }
+       return 0;
+-
+-cleanup:
+-      ltdc_plane_destroy_all(ddev);
+-      return ret;
+ }
+ static void ltdc_encoder_disable(struct drm_encoder *encoder)
+@@ -1778,23 +1757,19 @@ static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
+       struct drm_encoder *encoder;
+       int ret;
+-      encoder = devm_kzalloc(ddev->dev, sizeof(*encoder), GFP_KERNEL);
+-      if (!encoder)
+-              return -ENOMEM;
++      encoder = drmm_simple_encoder_alloc(ddev, struct drm_encoder, dev,
++                                          DRM_MODE_ENCODER_DPI);
++      if (IS_ERR(encoder))
++              return PTR_ERR(encoder);
+       encoder->possible_crtcs = CRTC_MASK;
+       encoder->possible_clones = 0;   /* No cloning support */
+-      drm_simple_encoder_init(ddev, encoder, DRM_MODE_ENCODER_DPI);
+-
+       drm_encoder_helper_add(encoder, &ltdc_encoder_helper_funcs);
+       ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+-      if (ret) {
+-              if (ret != -EPROBE_DEFER)
+-                      drm_encoder_cleanup(encoder);
++      if (ret)
+               return ret;
+-      }
+       DRM_DEBUG_DRIVER("Bridge encoder:%d created\n", encoder->base.id);
+@@ -1964,8 +1939,7 @@ int ltdc_load(struct drm_device *ddev)
+                       goto err;
+               if (panel) {
+-                      bridge = drm_panel_bridge_add_typed(panel,
+-                                                          DRM_MODE_CONNECTOR_DPI);
++                      bridge = drmm_panel_bridge_add(ddev, panel);
+                       if (IS_ERR(bridge)) {
+                               DRM_ERROR("panel-bridge endpoint %d\n", i);
+                               ret = PTR_ERR(bridge);
+@@ -2047,7 +2021,7 @@ int ltdc_load(struct drm_device *ddev)
+               }
+       }
+-      crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL);
++      crtc = drmm_kzalloc(ddev, sizeof(*crtc), GFP_KERNEL);
+       if (!crtc) {
+               DRM_ERROR("Failed to allocate crtc\n");
+               ret = -ENOMEM;
+@@ -2074,9 +2048,6 @@ int ltdc_load(struct drm_device *ddev)
+       return 0;
+ err:
+-      for (i = 0; i < nb_endpoints; i++)
+-              drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i);
+-
+       clk_disable_unprepare(ldev->pixel_clk);
+       return ret;
+@@ -2084,16 +2055,8 @@ int ltdc_load(struct drm_device *ddev)
+ void ltdc_unload(struct drm_device *ddev)
+ {
+-      struct device *dev = ddev->dev;
+-      int nb_endpoints, i;
+-
+       DRM_DEBUG_DRIVER("\n");
+-      nb_endpoints = of_graph_get_endpoint_count(dev->of_node);
+-
+-      for (i = 0; i < nb_endpoints; i++)
+-              drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i);
+-
+       pm_runtime_disable(ddev->dev);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-stm-ltdc-reset-plane-transparency-after-plane-di.patch b/queue-6.11/drm-stm-ltdc-reset-plane-transparency-after-plane-di.patch
new file mode 100644 (file)
index 0000000..03f07a1
--- /dev/null
@@ -0,0 +1,38 @@
+From c9f04db565dcf8bcf50bce4b8cb11fa761daca7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Jul 2024 15:13:44 +0200
+Subject: drm/stm: ltdc: reset plane transparency after plane disable
+
+From: Yannick Fertre <yannick.fertre@foss.st.com>
+
+[ Upstream commit 02fa62d41c8abff945bae5bfc3ddcf4721496aca ]
+
+The plane's opacity should be reseted while the plane
+is disabled. It prevents from seeing a possible global
+or layer background color set earlier.
+
+Signed-off-by: Yannick Fertre <yannick.fertre@foss.st.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240712131344.98113-1-yannick.fertre@foss.st.com
+Signed-off-by: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/stm/ltdc.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
+index 056642d12265c..0832b749b66e7 100644
+--- a/drivers/gpu/drm/stm/ltdc.c
++++ b/drivers/gpu/drm/stm/ltdc.c
+@@ -1513,6 +1513,9 @@ static void ltdc_plane_atomic_disable(struct drm_plane *plane,
+       /* Disable layer */
+       regmap_write_bits(ldev->regmap, LTDC_L1CR + lofs, LXCR_LEN | LXCR_CLUTEN |  LXCR_HMEN, 0);
++      /* Reset the layer transparency to hide any related background color */
++      regmap_write_bits(ldev->regmap, LTDC_L1CACR + lofs, LXCACR_CONSTA, 0x00);
++
+       /* Commit shadow registers = update plane at next vblank */
+       if (ldev->caps.plane_reg_shadow)
+               regmap_write_bits(ldev->regmap, LTDC_L1RCR + lofs,
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-xe-add-timeout-to-preempt-fences.patch b/queue-6.11/drm-xe-add-timeout-to-preempt-fences.patch
new file mode 100644 (file)
index 0000000..c52d73e
--- /dev/null
@@ -0,0 +1,207 @@
+From 9d30d7e0dd6db51a2fcdbd43f7e6ed3ca7fb59f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jun 2024 17:41:37 -0700
+Subject: drm/xe: Add timeout to preempt fences
+
+From: Matthew Brost <matthew.brost@intel.com>
+
+[ Upstream commit 627c961d672d3304564455ba471f5e4405170eec ]
+
+To adhere to dma fencing rules that fences must signal within a
+reasonable amount of time, add a 5 second timeout to preempt fences. If
+this timeout occurs, kill the associated VM as this fatal to the VM.
+
+v2:
+ - Add comment for smp_wmb (Checkpatch)
+ - Fix kernel doc typo (Inspection)
+ - Add comment for killed check (Niranjana)
+v3:
+ - Drop smp_wmb (Matthew Auld)
+ - Don't take vm->lock in preempt fence worker (Matthew Auld)
+ - Drop RB given changes to patch
+v4:
+ - Add WRITE/READ_ONCE (Niranjana)
+ - Don't export xe_vm_kill (Niranjana)
+
+Cc: Matthew Auld <matthew.auld@intel.com>
+Cc: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Tested-by: Stuart Summers <stuart.summers@intel.com>
+Reviewed-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240626004137.4060806-1-matthew.brost@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_exec_queue_types.h |  6 ++--
+ drivers/gpu/drm/xe/xe_execlist.c         |  3 +-
+ drivers/gpu/drm/xe/xe_guc_submit.c       | 39 ++++++++++++++++++++----
+ drivers/gpu/drm/xe/xe_preempt_fence.c    | 12 ++++++--
+ drivers/gpu/drm/xe/xe_vm.c               | 12 +++++++-
+ 5 files changed, 59 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
+index f6ee0ae80fd63..fc2a1a20b7e4b 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
++++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
+@@ -169,9 +169,11 @@ struct xe_exec_queue_ops {
+       int (*suspend)(struct xe_exec_queue *q);
+       /**
+        * @suspend_wait: Wait for an exec queue to suspend executing, should be
+-       * call after suspend.
++       * call after suspend. In dma-fencing path thus must return within a
++       * reasonable amount of time. -ETIME return shall indicate an error
++       * waiting for suspend resulting in associated VM getting killed.
+        */
+-      void (*suspend_wait)(struct xe_exec_queue *q);
++      int (*suspend_wait)(struct xe_exec_queue *q);
+       /**
+        * @resume: Resume exec queue execution, exec queue must be in a suspended
+        * state and dma fence returned from most recent suspend call must be
+diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c
+index db906117db6d6..7502e3486eafa 100644
+--- a/drivers/gpu/drm/xe/xe_execlist.c
++++ b/drivers/gpu/drm/xe/xe_execlist.c
+@@ -422,10 +422,11 @@ static int execlist_exec_queue_suspend(struct xe_exec_queue *q)
+       return 0;
+ }
+-static void execlist_exec_queue_suspend_wait(struct xe_exec_queue *q)
++static int execlist_exec_queue_suspend_wait(struct xe_exec_queue *q)
+ {
+       /* NIY */
++      return 0;
+ }
+ static void execlist_exec_queue_resume(struct xe_exec_queue *q)
+diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
+index 64b3a7848f4ab..fd4ac3899edd2 100644
+--- a/drivers/gpu/drm/xe/xe_guc_submit.c
++++ b/drivers/gpu/drm/xe/xe_guc_submit.c
+@@ -1318,6 +1318,15 @@ static void __guc_exec_queue_process_msg_set_sched_props(struct xe_sched_msg *ms
+       kfree(msg);
+ }
++static void __suspend_fence_signal(struct xe_exec_queue *q)
++{
++      if (!q->guc->suspend_pending)
++              return;
++
++      WRITE_ONCE(q->guc->suspend_pending, false);
++      wake_up(&q->guc->suspend_wait);
++}
++
+ static void suspend_fence_signal(struct xe_exec_queue *q)
+ {
+       struct xe_guc *guc = exec_queue_to_guc(q);
+@@ -1327,9 +1336,7 @@ static void suspend_fence_signal(struct xe_exec_queue *q)
+                 guc_read_stopped(guc));
+       xe_assert(xe, q->guc->suspend_pending);
+-      q->guc->suspend_pending = false;
+-      smp_wmb();
+-      wake_up(&q->guc->suspend_wait);
++      __suspend_fence_signal(q);
+ }
+ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg)
+@@ -1486,6 +1493,7 @@ static void guc_exec_queue_kill(struct xe_exec_queue *q)
+ {
+       trace_xe_exec_queue_kill(q);
+       set_exec_queue_killed(q);
++      __suspend_fence_signal(q);
+       xe_guc_exec_queue_trigger_cleanup(q);
+ }
+@@ -1584,12 +1592,31 @@ static int guc_exec_queue_suspend(struct xe_exec_queue *q)
+       return 0;
+ }
+-static void guc_exec_queue_suspend_wait(struct xe_exec_queue *q)
++static int guc_exec_queue_suspend_wait(struct xe_exec_queue *q)
+ {
+       struct xe_guc *guc = exec_queue_to_guc(q);
++      int ret;
++
++      /*
++       * Likely don't need to check exec_queue_killed() as we clear
++       * suspend_pending upon kill but to be paranoid but races in which
++       * suspend_pending is set after kill also check kill here.
++       */
++      ret = wait_event_timeout(q->guc->suspend_wait,
++                               !READ_ONCE(q->guc->suspend_pending) ||
++                               exec_queue_killed(q) ||
++                               guc_read_stopped(guc),
++                               HZ * 5);
+-      wait_event(q->guc->suspend_wait, !q->guc->suspend_pending ||
+-                 guc_read_stopped(guc));
++      if (!ret) {
++              xe_gt_warn(guc_to_gt(guc),
++                         "Suspend fence, guc_id=%d, failed to respond",
++                         q->guc->id);
++              /* XXX: Trigger GT reset? */
++              return -ETIME;
++      }
++
++      return 0;
+ }
+ static void guc_exec_queue_resume(struct xe_exec_queue *q)
+diff --git a/drivers/gpu/drm/xe/xe_preempt_fence.c b/drivers/gpu/drm/xe/xe_preempt_fence.c
+index c453f45328b1c..83fbeea5aa201 100644
+--- a/drivers/gpu/drm/xe/xe_preempt_fence.c
++++ b/drivers/gpu/drm/xe/xe_preempt_fence.c
+@@ -17,10 +17,16 @@ static void preempt_fence_work_func(struct work_struct *w)
+               container_of(w, typeof(*pfence), preempt_work);
+       struct xe_exec_queue *q = pfence->q;
+-      if (pfence->error)
++      if (pfence->error) {
+               dma_fence_set_error(&pfence->base, pfence->error);
+-      else
+-              q->ops->suspend_wait(q);
++      } else if (!q->ops->reset_status(q)) {
++              int err = q->ops->suspend_wait(q);
++
++              if (err)
++                      dma_fence_set_error(&pfence->base, err);
++      } else {
++              dma_fence_set_error(&pfence->base, -ENOENT);
++      }
+       dma_fence_signal(&pfence->base);
+       /*
+diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
+index b49bee0dfac5d..743c8d79d79d2 100644
+--- a/drivers/gpu/drm/xe/xe_vm.c
++++ b/drivers/gpu/drm/xe/xe_vm.c
+@@ -133,8 +133,10 @@ static int wait_for_existing_preempt_fences(struct xe_vm *vm)
+               if (q->lr.pfence) {
+                       long timeout = dma_fence_wait(q->lr.pfence, false);
+-                      if (timeout < 0)
++                      /* Only -ETIME on fence indicates VM needs to be killed */
++                      if (timeout < 0 || q->lr.pfence->error == -ETIME)
+                               return -ETIME;
++
+                       dma_fence_put(q->lr.pfence);
+                       q->lr.pfence = NULL;
+               }
+@@ -311,6 +313,14 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm)
+ #define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
++/*
++ * xe_vm_kill() - VM Kill
++ * @vm: The VM.
++ * @unlocked: Flag indicates the VM's dma-resv is not held
++ *
++ * Kill the VM by setting banned flag indicated VM is no longer available for
++ * use. If in preempt fence mode, also kill all exec queue attached to the VM.
++ */
+ static void xe_vm_kill(struct xe_vm *vm, bool unlocked)
+ {
+       struct xe_exec_queue *q;
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-xe-drop-warn-on-xe_guc_pc_gucrc_disable-in-guc-p.patch b/queue-6.11/drm-xe-drop-warn-on-xe_guc_pc_gucrc_disable-in-guc-p.patch
new file mode 100644 (file)
index 0000000..e9355ea
--- /dev/null
@@ -0,0 +1,35 @@
+From 8bd2c5f26f47e2c7aa58a63f7be92d6592c7375b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Aug 2024 10:29:55 -0700
+Subject: drm/xe: Drop warn on xe_guc_pc_gucrc_disable in guc pc fini
+
+From: Matthew Brost <matthew.brost@intel.com>
+
+[ Upstream commit a323782567812ee925e9b7926445532c7afe331b ]
+
+Not a big deal if CT is down as driver is unloading, no need to warn.
+
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Jagmeet Randhawa <jagmeet.randhawa@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240820172958.1095143-4-matthew.brost@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_guc_pc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c
+index ccd574e948aa3..034b29984d5ed 100644
+--- a/drivers/gpu/drm/xe/xe_guc_pc.c
++++ b/drivers/gpu/drm/xe/xe_guc_pc.c
+@@ -1042,7 +1042,7 @@ static void xe_guc_pc_fini_hw(void *arg)
+               return;
+       XE_WARN_ON(xe_force_wake_get(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL));
+-      XE_WARN_ON(xe_guc_pc_gucrc_disable(pc));
++      xe_guc_pc_gucrc_disable(pc);
+       XE_WARN_ON(xe_guc_pc_stop(pc));
+       /* Bind requested freq to mert_freq_cap before unload */
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-xe-fbdev-limit-the-usage-of-stolen-for-lnl.patch b/queue-6.11/drm-xe-fbdev-limit-the-usage-of-stolen-for-lnl.patch
new file mode 100644 (file)
index 0000000..2d83044
--- /dev/null
@@ -0,0 +1,106 @@
+From dbe127c5bdd4395dfaf96cbb56ff9f6d1f226d20 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jul 2024 13:52:52 +0530
+Subject: drm/xe/fbdev: Limit the usage of stolen for LNL+
+
+From: Uma Shankar <uma.shankar@intel.com>
+
+[ Upstream commit 775d0adc01a55fe0458139330415d86bb3533efe ]
+
+As per recommendation in the workarounds:
+WA_22019338487
+
+There is an issue with accessing Stolen memory pages due a
+hardware limitation. Limit the usage of stolen memory for
+fbdev for LNL+. Don't use BIOS FB from stolen on LNL+ and
+assign the same from system memory.
+
+v2: Corrected the WA Number, limited WA to LNL and
+    Adopted XE_WA framework as suggested by Lucas and Matt.
+
+v3: Introduced the waxxx_display to implement display side
+    of WA changes on Lunarlake. Used xe_root_mmio_gt and
+    avoid the for loop (Suggested by Lucas)
+
+v4: Fixed some nits (Luca)
+
+Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Signed-off-by: Uma Shankar <uma.shankar@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240717082252.3875909-1-uma.shankar@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/display/intel_fbdev_fb.c   | 6 +++++-
+ drivers/gpu/drm/xe/display/xe_plane_initial.c | 6 ++++++
+ drivers/gpu/drm/xe/xe_wa_oob.rules            | 1 +
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
+index 816ad13821a83..cd8948c08661b 100644
+--- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
++++ b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
+@@ -10,6 +10,9 @@
+ #include "xe_bo.h"
+ #include "xe_gt.h"
+ #include "xe_ttm_stolen_mgr.h"
++#include "xe_wa.h"
++
++#include <generated/xe_wa_oob.h>
+ struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
+                                              struct drm_fb_helper_surface_size *sizes)
+@@ -37,7 +40,7 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
+       size = PAGE_ALIGN(size);
+       obj = ERR_PTR(-ENODEV);
+-      if (!IS_DGFX(xe)) {
++      if (!IS_DGFX(xe) && !XE_WA(xe_root_mmio_gt(xe), 22019338487_display)) {
+               obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe),
+                                          NULL, size,
+                                          ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT |
+@@ -48,6 +51,7 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
+               else
+                       drm_info(&xe->drm, "Allocated fbdev into stolen failed: %li\n", PTR_ERR(obj));
+       }
++
+       if (IS_ERR(obj)) {
+               obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), NULL, size,
+                                          ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT |
+diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c
+index 5eccd6abb3ef5..a50ab9eae40ae 100644
+--- a/drivers/gpu/drm/xe/display/xe_plane_initial.c
++++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c
+@@ -18,6 +18,9 @@
+ #include "intel_frontbuffer.h"
+ #include "intel_plane_initial.h"
+ #include "xe_bo.h"
++#include "xe_wa.h"
++
++#include <generated/xe_wa_oob.h>
+ static bool
+ intel_reuse_initial_plane_obj(struct intel_crtc *this,
+@@ -104,6 +107,9 @@ initial_plane_bo(struct xe_device *xe,
+               phys_base = base;
+               flags |= XE_BO_FLAG_STOLEN;
++              if (XE_WA(xe_root_mmio_gt(xe), 22019338487_display))
++                      return NULL;
++
+               /*
+                * If the FB is too big, just don't use it since fbdev is not very
+                * important and we should probably use that space with FBC or other
+diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules
+index d4c33dbc14c7a..24a5b7d7cdcc1 100644
+--- a/drivers/gpu/drm/xe/xe_wa_oob.rules
++++ b/drivers/gpu/drm/xe/xe_wa_oob.rules
+@@ -29,6 +29,7 @@
+ 13011645652   GRAPHICS_VERSION(2004)
+ 22019338487   MEDIA_VERSION(2000)
+               GRAPHICS_VERSION(2001)
++22019338487_display   PLATFORM(LUNARLAKE)
+ 16023588340   GRAPHICS_VERSION(2001)
+ 14019789679   GRAPHICS_VERSION(1255)
+               GRAPHICS_VERSION_RANGE(1270, 2004)
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-xe-hdcp-check-gsc-structure-validity.patch b/queue-6.11/drm-xe-hdcp-check-gsc-structure-validity.patch
new file mode 100644 (file)
index 0000000..23498d6
--- /dev/null
@@ -0,0 +1,52 @@
+From bc4b9d91779456c05effa24f4a50078cce0e2447 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jul 2024 12:14:51 +0530
+Subject: drm/xe/hdcp: Check GSC structure validity
+
+From: Suraj Kandpal <suraj.kandpal@intel.com>
+
+[ Upstream commit b4224f6bae3801d589f815672ec62800a1501b0d ]
+
+Sometimes xe_gsc is not initialized when checked at HDCP capability
+check. Add gsc structure check to avoid null pointer error.
+
+Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
+Reviewed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240722064451.3610512-4-suraj.kandpal@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
+index 990285aa9b261..0af667ebebf98 100644
+--- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
++++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
+@@ -40,10 +40,14 @@ bool intel_hdcp_gsc_check_status(struct xe_device *xe)
+ {
+       struct xe_tile *tile = xe_device_get_root_tile(xe);
+       struct xe_gt *gt = tile->media_gt;
++      struct xe_gsc *gsc = &gt->uc.gsc;
+       bool ret = true;
+-      if (!xe_uc_fw_is_enabled(&gt->uc.gsc.fw))
++      if (!gsc && !xe_uc_fw_is_enabled(&gsc->fw)) {
++              drm_dbg_kms(&xe->drm,
++                          "GSC Components not ready for HDCP2.x\n");
+               return false;
++      }
+       xe_pm_runtime_get(xe);
+       if (xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC)) {
+@@ -53,7 +57,7 @@ bool intel_hdcp_gsc_check_status(struct xe_device *xe)
+               goto out;
+       }
+-      if (!xe_gsc_proxy_init_done(&gt->uc.gsc))
++      if (!xe_gsc_proxy_init_done(gsc))
+               ret = false;
+       xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC);
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-xe-name-and-document-wa_14019789679.patch b/queue-6.11/drm-xe-name-and-document-wa_14019789679.patch
new file mode 100644 (file)
index 0000000..e820022
--- /dev/null
@@ -0,0 +1,111 @@
+From 367fa824d725248ae4a3faebd8ca0b411c335654 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Aug 2024 11:10:43 -0700
+Subject: drm/xe: Name and document Wa_14019789679
+
+From: Matt Roper <matthew.d.roper@intel.com>
+
+[ Upstream commit 1d734a3e5d6bb266f52eaf2b1400c5d3f1875a54 ]
+
+Early in the development of Xe we identified an issue with SVG state
+handling on DG2 and MTL (and later on Xe2 as well).  In
+commit 72ac304769dd ("drm/xe: Emit SVG state on RCS during driver load
+on DG2 and MTL") and commit fb24b858a20d ("drm/xe/xe2: Update SVG state
+handling") we implemented our own workaround to prevent SVG state from
+leaking from context A to context B in cases where context B never
+issues a specific state setting.
+
+The hardware teams have now created official workaround Wa_14019789679
+to cover this issue.  The workaround description only requires emitting
+3DSTATE_MESH_CONTROL, since they believe that's the only SVG instruction
+that would potentially remain unset by a context B, but still cause
+notable issues if unwanted values were inherited from context A.
+However since we already have a more extensive implementation that emits
+the entire SVG state and prevents _any_ SVG state from unintentionally
+leaking, we'll stick with our existing implementation just to be safe.
+
+Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
+Reviewed-by: Jonathan Cavitt <jonathan.cavitt@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240812181042.2013508-2-matthew.d.roper@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_lrc.c        | 35 +++++++++++++++++++++---------
+ drivers/gpu/drm/xe/xe_wa_oob.rules |  2 ++
+ 2 files changed, 27 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c
+index 58121821f0814..974a9cd8c3795 100644
+--- a/drivers/gpu/drm/xe/xe_lrc.c
++++ b/drivers/gpu/drm/xe/xe_lrc.c
+@@ -5,6 +5,8 @@
+ #include "xe_lrc.h"
++#include <generated/xe_wa_oob.h>
++
+ #include <linux/ascii85.h>
+ #include "instructions/xe_mi_commands.h"
+@@ -24,6 +26,7 @@
+ #include "xe_memirq.h"
+ #include "xe_sriov.h"
+ #include "xe_vm.h"
++#include "xe_wa.h"
+ #define LRC_VALID                             BIT_ULL(0)
+ #define LRC_PRIVILEGE                         BIT_ULL(8)
+@@ -1581,19 +1584,31 @@ void xe_lrc_emit_hwe_state_instructions(struct xe_exec_queue *q, struct xe_bb *b
+       int state_table_size = 0;
+       /*
+-       * At the moment we only need to emit non-register state for the RCS
+-       * engine.
++       * Wa_14019789679
++       *
++       * If the driver doesn't explicitly emit the SVG instructions while
++       * setting up the default LRC, the context switch will write 0's
++       * (noops) into the LRC memory rather than the expected instruction
++       * headers.  Application contexts start out as a copy of the default
++       * LRC, and if they also do not emit specific settings for some SVG
++       * state, then on context restore they'll unintentionally inherit
++       * whatever state setting the previous context had programmed into the
++       * hardware (i.e., the lack of a 3DSTATE_* instruction in the LRC will
++       * prevent the hardware from resetting that state back to any specific
++       * value).
++       *
++       * The official workaround only requires emitting 3DSTATE_MESH_CONTROL
++       * since that's a specific state setting that can easily cause GPU
++       * hangs if unintentionally inherited.  However to be safe we'll
++       * continue to emit all of the SVG state since it's best not to leak
++       * any of the state between contexts, even if that leakage is harmless.
+        */
+-      if (q->hwe->class != XE_ENGINE_CLASS_RENDER)
+-              return;
+-
+-      switch (GRAPHICS_VERx100(xe)) {
+-      case 1255:
+-      case 1270 ... 2004:
++      if (XE_WA(gt, 14019789679) && q->hwe->class == XE_ENGINE_CLASS_RENDER) {
+               state_table = xe_hpg_svg_state;
+               state_table_size = ARRAY_SIZE(xe_hpg_svg_state);
+-              break;
+-      default:
++      }
++
++      if (!state_table) {
+               xe_gt_dbg(gt, "No non-register state to emit on graphics ver %d.%02d\n",
+                         GRAPHICS_VER(xe), GRAPHICS_VERx100(xe) % 100);
+               return;
+diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules
+index 08f7336881e32..d4c33dbc14c7a 100644
+--- a/drivers/gpu/drm/xe/xe_wa_oob.rules
++++ b/drivers/gpu/drm/xe/xe_wa_oob.rules
+@@ -30,3 +30,5 @@
+ 22019338487   MEDIA_VERSION(2000)
+               GRAPHICS_VERSION(2001)
+ 16023588340   GRAPHICS_VERSION(2001)
++14019789679   GRAPHICS_VERSION(1255)
++              GRAPHICS_VERSION_RANGE(1270, 2004)
+-- 
+2.43.0
+
diff --git a/queue-6.11/drm-xe-use-topology-to-determine-page-fault-queue-si.patch b/queue-6.11/drm-xe-use-topology-to-determine-page-fault-queue-si.patch
new file mode 100644 (file)
index 0000000..e9032ae
--- /dev/null
@@ -0,0 +1,165 @@
+From b664414a7b337d5e1b9e59cd11d666aff59eb0ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 17 Aug 2024 02:47:31 +0000
+Subject: drm/xe: Use topology to determine page fault queue size
+
+From: Stuart Summers <stuart.summers@intel.com>
+
+[ Upstream commit 3338e4f90c143cf32f77d64f464cb7f2c2d24700 ]
+
+Currently the page fault queue size is hard coded. However
+the hardware supports faulting for each EU and each CS.
+For some applications running on hardware with a large
+number of EUs and CSs, this can result in an overflow of
+the page fault queue.
+
+Add a small calculation to determine the page fault queue
+size based on the number of EUs and CSs in the platform as
+detmined by fuses.
+
+Signed-off-by: Stuart Summers <stuart.summers@intel.com>
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/24d582a3b48c97793b8b6a402f34b4b469471636.1723862633.git.stuart.summers@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gt_pagefault.c | 54 +++++++++++++++++++++-------
+ drivers/gpu/drm/xe/xe_gt_types.h     |  9 +++--
+ 2 files changed, 49 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
+index b2a7fa55bd181..401c0527d9140 100644
+--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
++++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
+@@ -287,7 +287,7 @@ static bool get_pagefault(struct pf_queue *pf_queue, struct pagefault *pf)
+                       PFD_VIRTUAL_ADDR_LO_SHIFT;
+               pf_queue->tail = (pf_queue->tail + PF_MSG_LEN_DW) %
+-                      PF_QUEUE_NUM_DW;
++                      pf_queue->num_dw;
+               ret = true;
+       }
+       spin_unlock_irq(&pf_queue->lock);
+@@ -299,7 +299,8 @@ static bool pf_queue_full(struct pf_queue *pf_queue)
+ {
+       lockdep_assert_held(&pf_queue->lock);
+-      return CIRC_SPACE(pf_queue->head, pf_queue->tail, PF_QUEUE_NUM_DW) <=
++      return CIRC_SPACE(pf_queue->head, pf_queue->tail,
++                        pf_queue->num_dw) <=
+               PF_MSG_LEN_DW;
+ }
+@@ -312,22 +313,23 @@ int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len)
+       u32 asid;
+       bool full;
+-      /*
+-       * The below logic doesn't work unless PF_QUEUE_NUM_DW % PF_MSG_LEN_DW == 0
+-       */
+-      BUILD_BUG_ON(PF_QUEUE_NUM_DW % PF_MSG_LEN_DW);
+-
+       if (unlikely(len != PF_MSG_LEN_DW))
+               return -EPROTO;
+       asid = FIELD_GET(PFD_ASID, msg[1]);
+       pf_queue = gt->usm.pf_queue + (asid % NUM_PF_QUEUE);
++      /*
++       * The below logic doesn't work unless PF_QUEUE_NUM_DW % PF_MSG_LEN_DW == 0
++       */
++      xe_gt_assert(gt, !(pf_queue->num_dw % PF_MSG_LEN_DW));
++
+       spin_lock_irqsave(&pf_queue->lock, flags);
+       full = pf_queue_full(pf_queue);
+       if (!full) {
+               memcpy(pf_queue->data + pf_queue->head, msg, len * sizeof(u32));
+-              pf_queue->head = (pf_queue->head + len) % PF_QUEUE_NUM_DW;
++              pf_queue->head = (pf_queue->head + len) %
++                      pf_queue->num_dw;
+               queue_work(gt->usm.pf_wq, &pf_queue->worker);
+       } else {
+               drm_warn(&xe->drm, "PF Queue full, shouldn't be possible");
+@@ -386,26 +388,54 @@ static void pagefault_fini(void *arg)
+ {
+       struct xe_gt *gt = arg;
+       struct xe_device *xe = gt_to_xe(gt);
++      int i;
+       if (!xe->info.has_usm)
+               return;
+       destroy_workqueue(gt->usm.acc_wq);
+       destroy_workqueue(gt->usm.pf_wq);
++
++      for (i = 0; i < NUM_PF_QUEUE; ++i)
++              kfree(gt->usm.pf_queue[i].data);
++}
++
++static int xe_alloc_pf_queue(struct xe_gt *gt, struct pf_queue *pf_queue)
++{
++      xe_dss_mask_t all_dss;
++      int num_dss, num_eus;
++
++      bitmap_or(all_dss, gt->fuse_topo.g_dss_mask, gt->fuse_topo.c_dss_mask,
++                XE_MAX_DSS_FUSE_BITS);
++
++      num_dss = bitmap_weight(all_dss, XE_MAX_DSS_FUSE_BITS);
++      num_eus = bitmap_weight(gt->fuse_topo.eu_mask_per_dss,
++                              XE_MAX_EU_FUSE_BITS) * num_dss;
++
++      /* user can issue separate page faults per EU and per CS */
++      pf_queue->num_dw =
++              (num_eus + XE_NUM_HW_ENGINES) * PF_MSG_LEN_DW;
++
++      pf_queue->gt = gt;
++      pf_queue->data = kzalloc(pf_queue->num_dw, GFP_KERNEL);
++      spin_lock_init(&pf_queue->lock);
++      INIT_WORK(&pf_queue->worker, pf_queue_work_func);
++
++      return 0;
+ }
+ int xe_gt_pagefault_init(struct xe_gt *gt)
+ {
+       struct xe_device *xe = gt_to_xe(gt);
+-      int i;
++      int i, ret = 0;
+       if (!xe->info.has_usm)
+               return 0;
+       for (i = 0; i < NUM_PF_QUEUE; ++i) {
+-              gt->usm.pf_queue[i].gt = gt;
+-              spin_lock_init(&gt->usm.pf_queue[i].lock);
+-              INIT_WORK(&gt->usm.pf_queue[i].worker, pf_queue_work_func);
++              ret = xe_alloc_pf_queue(gt, &gt->usm.pf_queue[i]);
++              if (ret)
++                      return ret;
+       }
+       for (i = 0; i < NUM_ACC_QUEUE; ++i) {
+               gt->usm.acc_queue[i].gt = gt;
+diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
+index c582541970dff..ba6662c9863b5 100644
+--- a/drivers/gpu/drm/xe/xe_gt_types.h
++++ b/drivers/gpu/drm/xe/xe_gt_types.h
+@@ -233,9 +233,14 @@ struct xe_gt {
+               struct pf_queue {
+                       /** @usm.pf_queue.gt: back pointer to GT */
+                       struct xe_gt *gt;
+-#define PF_QUEUE_NUM_DW       128
+                       /** @usm.pf_queue.data: data in the page fault queue */
+-                      u32 data[PF_QUEUE_NUM_DW];
++                      u32 *data;
++                      /**
++                       * @usm.pf_queue.num_dw: number of DWORDS in the page
++                       * fault queue. Dynamically calculated based on the number
++                       * of compute resources available.
++                       */
++                      u32 num_dw;
+                       /**
+                        * @usm.pf_queue.tail: tail pointer in DWs for page fault queue,
+                        * moved by worker which processes faults (consumer).
+-- 
+2.43.0
+
diff --git a/queue-6.11/exec-don-t-warn-for-racy-path_noexec-check.patch b/queue-6.11/exec-don-t-warn-for-racy-path_noexec-check.patch
new file mode 100644 (file)
index 0000000..96179d9
--- /dev/null
@@ -0,0 +1,109 @@
+From 778d32bfd1c23b75353cae45f3be8347d591d731 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 15:17:21 +0200
+Subject: exec: don't WARN for racy path_noexec check
+
+From: Mateusz Guzik <mjguzik@gmail.com>
+
+[ Upstream commit 0d196e7589cefe207d5d41f37a0a28a1fdeeb7c6 ]
+
+Both i_mode and noexec checks wrapped in WARN_ON stem from an artifact
+of the previous implementation. They used to legitimately check for the
+condition, but that got moved up in two commits:
+633fb6ac3980 ("exec: move S_ISREG() check earlier")
+0fd338b2d2cd ("exec: move path_noexec() check earlier")
+
+Instead of being removed said checks are WARN_ON'ed instead, which
+has some debug value.
+
+However, the spurious path_noexec check is racy, resulting in
+unwarranted warnings should someone race with setting the noexec flag.
+
+One can note there is more to perm-checking whether execve is allowed
+and none of the conditions are guaranteed to still hold after they were
+tested for.
+
+Additionally this does not validate whether the code path did any perm
+checking to begin with -- it will pass if the inode happens to be
+regular.
+
+Keep the redundant path_noexec() check even though it's mindless
+nonsense checking for guarantee that isn't given so drop the WARN.
+
+Reword the commentary and do small tidy ups while here.
+
+Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
+Link: https://lore.kernel.org/r/20240805131721.765484-1-mjguzik@gmail.com
+[brauner: keep redundant path_noexec() check]
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/exec.c | 31 ++++++++++++-------------------
+ 1 file changed, 12 insertions(+), 19 deletions(-)
+
+diff --git a/fs/exec.c b/fs/exec.c
+index 50e76cc633c4b..caae051c5a956 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -145,13 +145,11 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
+               goto out;
+       /*
+-       * may_open() has already checked for this, so it should be
+-       * impossible to trip now. But we need to be extra cautious
+-       * and check again at the very end too.
++       * Check do_open_execat() for an explanation.
+        */
+       error = -EACCES;
+-      if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) ||
+-                       path_noexec(&file->f_path)))
++      if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) ||
++          path_noexec(&file->f_path))
+               goto exit;
+       error = -ENOEXEC;
+@@ -954,7 +952,6 @@ EXPORT_SYMBOL(transfer_args_to_stack);
+ static struct file *do_open_execat(int fd, struct filename *name, int flags)
+ {
+       struct file *file;
+-      int err;
+       struct open_flags open_exec_flags = {
+               .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
+               .acc_mode = MAY_EXEC,
+@@ -971,24 +968,20 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
+       file = do_filp_open(fd, name, &open_exec_flags);
+       if (IS_ERR(file))
+-              goto out;
++              return file;
+       /*
+-       * may_open() has already checked for this, so it should be
+-       * impossible to trip now. But we need to be extra cautious
+-       * and check again at the very end too.
++       * In the past the regular type check was here. It moved to may_open() in
++       * 633fb6ac3980 ("exec: move S_ISREG() check earlier"). Since then it is
++       * an invariant that all non-regular files error out before we get here.
+        */
+-      err = -EACCES;
+-      if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) ||
+-                       path_noexec(&file->f_path)))
+-              goto exit;
++      if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) ||
++          path_noexec(&file->f_path)) {
++              fput(file);
++              return ERR_PTR(-EACCES);
++      }
+-out:
+       return file;
+-
+-exit:
+-      fput(file);
+-      return ERR_PTR(err);
+ }
+ /**
+-- 
+2.43.0
+
diff --git a/queue-6.11/ext4-avoid-use-after-free-in-ext4_ext_show_leaf.patch b/queue-6.11/ext4-avoid-use-after-free-in-ext4_ext_show_leaf.patch
new file mode 100644 (file)
index 0000000..c047df1
--- /dev/null
@@ -0,0 +1,94 @@
+From bf3fbc9f52671cc4541a61c900e96c589a3aa333 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Aug 2024 10:35:24 +0800
+Subject: ext4: avoid use-after-free in ext4_ext_show_leaf()
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit 4e2524ba2ca5f54bdbb9e5153bea00421ef653f5 ]
+
+In ext4_find_extent(), path may be freed by error or be reallocated, so
+using a previously saved *ppath may have been freed and thus may trigger
+use-after-free, as follows:
+
+ext4_split_extent
+  path = *ppath;
+  ext4_split_extent_at(ppath)
+  path = ext4_find_extent(ppath)
+  ext4_split_extent_at(ppath)
+    // ext4_find_extent fails to free path
+    // but zeroout succeeds
+  ext4_ext_show_leaf(inode, path)
+    eh = path[depth].p_hdr
+    // path use-after-free !!!
+
+Similar to ext4_split_extent_at(), we use *ppath directly as an input to
+ext4_ext_show_leaf(). Fix a spelling error by the way.
+
+Same problem in ext4_ext_handle_unwritten_extents(). Since 'path' is only
+used in ext4_ext_show_leaf(), remove 'path' and use *ppath directly.
+
+This issue is triggered only when EXT_DEBUG is defined and therefore does
+not affect functionality.
+
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Link: https://patch.msgid.link/20240822023545.1994557-5-libaokun@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/extents.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index e067f2dd0335c..7954430f886d8 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3287,7 +3287,7 @@ static int ext4_split_extent_at(handle_t *handle,
+ }
+ /*
+- * ext4_split_extents() splits an extent and mark extent which is covered
++ * ext4_split_extent() splits an extent and mark extent which is covered
+  * by @map as split_flags indicates
+  *
+  * It may result in splitting the extent into multiple extents (up to three)
+@@ -3363,7 +3363,7 @@ static int ext4_split_extent(handle_t *handle,
+                       goto out;
+       }
+-      ext4_ext_show_leaf(inode, path);
++      ext4_ext_show_leaf(inode, *ppath);
+ out:
+       return err ? err : allocated;
+ }
+@@ -3828,14 +3828,13 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
+                       struct ext4_ext_path **ppath, int flags,
+                       unsigned int allocated, ext4_fsblk_t newblock)
+ {
+-      struct ext4_ext_path __maybe_unused *path = *ppath;
+       int ret = 0;
+       int err = 0;
+       ext_debug(inode, "logical block %llu, max_blocks %u, flags 0x%x, allocated %u\n",
+                 (unsigned long long)map->m_lblk, map->m_len, flags,
+                 allocated);
+-      ext4_ext_show_leaf(inode, path);
++      ext4_ext_show_leaf(inode, *ppath);
+       /*
+        * When writing into unwritten space, we should not fail to
+@@ -3932,7 +3931,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
+       if (allocated > map->m_len)
+               allocated = map->m_len;
+       map->m_len = allocated;
+-      ext4_ext_show_leaf(inode, path);
++      ext4_ext_show_leaf(inode, *ppath);
+ out2:
+       return err ? err : allocated;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/ext4-don-t-set-sb_rdonly-after-filesystem-errors.patch b/queue-6.11/ext4-don-t-set-sb_rdonly-after-filesystem-errors.patch
new file mode 100644 (file)
index 0000000..7b9da5f
--- /dev/null
@@ -0,0 +1,56 @@
+From 822e36f1bec439e66e5a268cf5f05536cd783021 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 22:12:41 +0200
+Subject: ext4: don't set SB_RDONLY after filesystem errors
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit d3476f3dad4ad68ae5f6b008ea6591d1520da5d8 ]
+
+When the filesystem is mounted with errors=remount-ro, we were setting
+SB_RDONLY flag to stop all filesystem modifications. We knew this misses
+proper locking (sb->s_umount) and does not go through proper filesystem
+remount procedure but it has been the way this worked since early ext2
+days and it was good enough for catastrophic situation damage
+mitigation. Recently, syzbot has found a way (see link) to trigger
+warnings in filesystem freezing because the code got confused by
+SB_RDONLY changing under its hands. Since these days we set
+EXT4_FLAGS_SHUTDOWN on the superblock which is enough to stop all
+filesystem modifications, modifying SB_RDONLY shouldn't be needed. So
+stop doing that.
+
+Link: https://lore.kernel.org/all/000000000000b90a8e061e21d12f@google.com
+Reported-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Link: https://patch.msgid.link/20240805201241.27286-1-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/super.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index cecea19908109..b3f47d6879ebf 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -735,11 +735,12 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
+       ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
+       /*
+-       * Make sure updated value of ->s_mount_flags will be visible before
+-       * ->s_flags update
++       * EXT4_FLAGS_SHUTDOWN was set which stops all filesystem
++       * modifications. We don't set SB_RDONLY because that requires
++       * sb->s_umount semaphore and setting it without proper remount
++       * procedure is confusing code such as freeze_super() leading to
++       * deadlocks and other problems.
+        */
+-      smp_wmb();
+-      sb->s_flags |= SB_RDONLY;
+ }
+ static void update_super_work(struct work_struct *work)
+-- 
+2.43.0
+
diff --git a/queue-6.11/ext4-ext4_search_dir-should-return-a-proper-error.patch b/queue-6.11/ext4-ext4_search_dir-should-return-a-proper-error.patch
new file mode 100644 (file)
index 0000000..cb52688
--- /dev/null
@@ -0,0 +1,86 @@
+From b8311c6b74bca025bb10bb01d72158e6c8160b6d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 12:23:21 -0300
+Subject: ext4: ext4_search_dir should return a proper error
+
+From: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+
+[ Upstream commit cd69f8f9de280e331c9e6ff689ced0a688a9ce8f ]
+
+ext4_search_dir currently returns -1 in case of a failure, while it returns
+0 when the name is not found. In such failure cases, it should return an
+error code instead.
+
+This becomes even more important when ext4_find_inline_entry returns an
+error code as well in the next commit.
+
+-EFSCORRUPTED seems appropriate as such error code as these failures would
+be caused by unexpected record lengths and is in line with other instances
+of ext4_check_dir_entry failures.
+
+In the case of ext4_dx_find_entry, the current use of ERR_BAD_DX_DIR was
+left as is to reduce the risk of regressions.
+
+Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+Link: https://patch.msgid.link/20240821152324.3621860-2-cascardo@igalia.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/namei.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 6a95713f9193b..8af437ac30511 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1482,7 +1482,7 @@ static bool ext4_match(struct inode *parent,
+ }
+ /*
+- * Returns 0 if not found, -1 on failure, and 1 on success
++ * Returns 0 if not found, -EFSCORRUPTED on failure, and 1 on success
+  */
+ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
+                   struct inode *dir, struct ext4_filename *fname,
+@@ -1503,7 +1503,7 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
+                        * a full check */
+                       if (ext4_check_dir_entry(dir, NULL, de, bh, search_buf,
+                                                buf_size, offset))
+-                              return -1;
++                              return -EFSCORRUPTED;
+                       *res_dir = de;
+                       return 1;
+               }
+@@ -1511,7 +1511,7 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
+               de_len = ext4_rec_len_from_disk(de->rec_len,
+                                               dir->i_sb->s_blocksize);
+               if (de_len <= 0)
+-                      return -1;
++                      return -EFSCORRUPTED;
+               offset += de_len;
+               de = (struct ext4_dir_entry_2 *) ((char *) de + de_len);
+       }
+@@ -1663,8 +1663,10 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
+                       goto cleanup_and_exit;
+               } else {
+                       brelse(bh);
+-                      if (i < 0)
++                      if (i < 0) {
++                              ret = ERR_PTR(i);
+                               goto cleanup_and_exit;
++                      }
+               }
+       next:
+               if (++block >= nblocks)
+@@ -1758,7 +1760,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
+               if (retval == 1)
+                       goto success;
+               brelse(bh);
+-              if (retval == -1) {
++              if (retval < 0) {
+                       bh = ERR_PTR(ERR_BAD_DX_DIR);
+                       goto errout;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.11/ext4-filesystems-without-casefold-feature-cannot-be-.patch b/queue-6.11/ext4-filesystems-without-casefold-feature-cannot-be-.patch
new file mode 100644 (file)
index 0000000..323f429
--- /dev/null
@@ -0,0 +1,43 @@
+From 0c20ddfb36a0f028d11cdc03949cf1bc95ebb360 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 09:23:35 +0800
+Subject: ext4: filesystems without casefold feature cannot be mounted with
+ siphash
+
+From: Lizhi Xu <lizhi.xu@windriver.com>
+
+[ Upstream commit 985b67cd86392310d9e9326de941c22fc9340eec ]
+
+When mounting the ext4 filesystem, if the default hash version is set to
+DX_HASH_SIPHASH but the casefold feature is not set, exit the mounting.
+
+Reported-by: syzbot+340581ba9dceb7e06fb3@syzkaller.appspotmail.com
+Signed-off-by: Lizhi Xu <lizhi.xu@windriver.com>
+Link: https://patch.msgid.link/20240605012335.44086-1-lizhi.xu@windriver.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/super.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7e73e13741d1e..cecea19908109 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3582,6 +3582,13 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly)
+                        "mounted without CONFIG_UNICODE");
+               return 0;
+       }
++      if (EXT4_SB(sb)->s_es->s_def_hash_version == DX_HASH_SIPHASH &&
++          !ext4_has_feature_casefold(sb)) {
++              ext4_msg(sb, KERN_ERR,
++                       "Filesystem without casefold feature cannot be "
++                       "mounted with siphash");
++              return 0;
++      }
+       if (readonly)
+               return 1;
+-- 
+2.43.0
+
diff --git a/queue-6.11/ext4-fix-i_data_sem-unlock-order-in-ext4_ind_migrate.patch b/queue-6.11/ext4-fix-i_data_sem-unlock-order-in-ext4_ind_migrate.patch
new file mode 100644 (file)
index 0000000..e5ad41a
--- /dev/null
@@ -0,0 +1,55 @@
+From d82993393d85aa2ca6347b8c30532e52a1cb0bc4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Aug 2024 15:22:09 +0000
+Subject: ext4: fix i_data_sem unlock order in ext4_ind_migrate()
+
+From: Artem Sadovnikov <ancowi69@gmail.com>
+
+[ Upstream commit cc749e61c011c255d81b192a822db650c68b313f ]
+
+Fuzzing reports a possible deadlock in jbd2_log_wait_commit.
+
+This issue is triggered when an EXT4_IOC_MIGRATE ioctl is set to require
+synchronous updates because the file descriptor is opened with O_SYNC.
+This can lead to the jbd2_journal_stop() function calling
+jbd2_might_wait_for_commit(), potentially causing a deadlock if the
+EXT4_IOC_MIGRATE call races with a write(2) system call.
+
+This problem only arises when CONFIG_PROVE_LOCKING is enabled. In this
+case, the jbd2_might_wait_for_commit macro locks jbd2_handle in the
+jbd2_journal_stop function while i_data_sem is locked. This triggers
+lockdep because the jbd2_journal_start function might also lock the same
+jbd2_handle simultaneously.
+
+Found by Linux Verification Center (linuxtesting.org) with syzkaller.
+
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Co-developed-by: Mikhail Ukhin <mish.uxin2012@yandex.ru>
+Signed-off-by: Mikhail Ukhin <mish.uxin2012@yandex.ru>
+Signed-off-by: Artem Sadovnikov <ancowi69@gmail.com>
+Rule: add
+Link: https://lore.kernel.org/stable/20240404095000.5872-1-mish.uxin2012%40yandex.ru
+Link: https://patch.msgid.link/20240829152210.2754-1-ancowi69@gmail.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/migrate.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index d98ac2af8199f..a5e1492bbaaa5 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -663,8 +663,8 @@ int ext4_ind_migrate(struct inode *inode)
+       if (unlikely(ret2 && !ret))
+               ret = ret2;
+ errout:
+-      ext4_journal_stop(handle);
+       up_write(&EXT4_I(inode)->i_data_sem);
++      ext4_journal_stop(handle);
+ out_unlock:
+       ext4_writepages_up_write(inode->i_sb, alloc_ctx);
+       return ret;
+-- 
+2.43.0
+
diff --git a/queue-6.11/fbdev-efifb-register-sysfs-groups-through-driver-cor.patch b/queue-6.11/fbdev-efifb-register-sysfs-groups-through-driver-cor.patch
new file mode 100644 (file)
index 0000000..f95c95d
--- /dev/null
@@ -0,0 +1,73 @@
+From 3b14bdbc9e0323ee29b1f9c7ce3b2a002a5eea16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 17:25:13 +0200
+Subject: fbdev: efifb: Register sysfs groups through driver core
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 95cdd538e0e5677efbdf8aade04ec098ab98f457 ]
+
+The driver core can register and cleanup sysfs groups already.
+Make use of that functionality to simplify the error handling and
+cleanup.
+
+Also avoid a UAF race during unregistering where the sysctl attributes
+were usable after the info struct was freed.
+
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/efifb.c | 11 ++---------
+ 1 file changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
+index 8dd82afb3452b..595b8e27bea66 100644
+--- a/drivers/video/fbdev/efifb.c
++++ b/drivers/video/fbdev/efifb.c
+@@ -561,15 +561,10 @@ static int efifb_probe(struct platform_device *dev)
+               break;
+       }
+-      err = sysfs_create_groups(&dev->dev.kobj, efifb_groups);
+-      if (err) {
+-              pr_err("efifb: cannot add sysfs attrs\n");
+-              goto err_unmap;
+-      }
+       err = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (err < 0) {
+               pr_err("efifb: cannot allocate colormap\n");
+-              goto err_groups;
++              goto err_unmap;
+       }
+       err = devm_aperture_acquire_for_platform_device(dev, par->base, par->size);
+@@ -587,8 +582,6 @@ static int efifb_probe(struct platform_device *dev)
+ err_fb_dealloc_cmap:
+       fb_dealloc_cmap(&info->cmap);
+-err_groups:
+-      sysfs_remove_groups(&dev->dev.kobj, efifb_groups);
+ err_unmap:
+       if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC))
+               iounmap(info->screen_base);
+@@ -608,12 +601,12 @@ static void efifb_remove(struct platform_device *pdev)
+       /* efifb_destroy takes care of info cleanup */
+       unregister_framebuffer(info);
+-      sysfs_remove_groups(&pdev->dev.kobj, efifb_groups);
+ }
+ static struct platform_driver efifb_driver = {
+       .driver = {
+               .name = "efi-framebuffer",
++              .dev_groups = efifb_groups,
+       },
+       .probe = efifb_probe,
+       .remove_new = efifb_remove,
+-- 
+2.43.0
+
diff --git a/queue-6.11/fbdev-pxafb-fix-possible-use-after-free-in-pxafb_tas.patch b/queue-6.11/fbdev-pxafb-fix-possible-use-after-free-in-pxafb_tas.patch
new file mode 100644 (file)
index 0000000..bdd878f
--- /dev/null
@@ -0,0 +1,59 @@
+From 4cbec8fecdff37a9ab8586b513e8c17ecd6835f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 22:29:52 +0800
+Subject: fbdev: pxafb: Fix possible use after free in pxafb_task()
+
+From: Kaixin Wang <kxwang23@m.fudan.edu.cn>
+
+[ Upstream commit 4a6921095eb04a900e0000da83d9475eb958e61e ]
+
+In the pxafb_probe function, it calls the pxafb_init_fbinfo function,
+after which &fbi->task is associated with pxafb_task. Moreover,
+within this pxafb_init_fbinfo function, the pxafb_blank function
+within the &pxafb_ops struct is capable of scheduling work.
+
+If we remove the module which will call pxafb_remove to make cleanup,
+it will call unregister_framebuffer function which can call
+do_unregister_framebuffer to free fbi->fb through
+put_fb_info(fb_info), while the work mentioned above will be used.
+The sequence of operations that may lead to a UAF bug is as follows:
+
+CPU0                                                CPU1
+
+                                   | pxafb_task
+pxafb_remove                       |
+unregister_framebuffer(info)       |
+do_unregister_framebuffer(fb_info) |
+put_fb_info(fb_info)               |
+// free fbi->fb                    | set_ctrlr_state(fbi, state)
+                                   | __pxafb_lcd_power(fbi, 0)
+                                   | fbi->lcd_power(on, &fbi->fb.var)
+                                   | //use fbi->fb
+
+Fix it by ensuring that the work is canceled before proceeding
+with the cleanup in pxafb_remove.
+
+Note that only root user can remove the driver at runtime.
+
+Signed-off-by: Kaixin Wang <kxwang23@m.fudan.edu.cn>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/pxafb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c
+index 2ef56fa28aff3..5ce02495cda63 100644
+--- a/drivers/video/fbdev/pxafb.c
++++ b/drivers/video/fbdev/pxafb.c
+@@ -2403,6 +2403,7 @@ static void pxafb_remove(struct platform_device *dev)
+       info = &fbi->fb;
+       pxafb_overlay_exit(fbi);
++      cancel_work_sync(&fbi->task);
+       unregister_framebuffer(info);
+       pxafb_disable_controller(fbi);
+-- 
+2.43.0
+
diff --git a/queue-6.11/fs-inode-prevent-dump_mapping-accessing-invalid-dent.patch b/queue-6.11/fs-inode-prevent-dump_mapping-accessing-invalid-dent.patch
new file mode 100644 (file)
index 0000000..5d13c62
--- /dev/null
@@ -0,0 +1,136 @@
+From e95cfea241eb7969bfd7eb072cf8b14369046b8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Aug 2024 13:55:03 +0800
+Subject: fs/inode: Prevent dump_mapping() accessing invalid dentry.d_name.name
+
+From: Li Zhijian <lizhijian@fujitsu.com>
+
+[ Upstream commit 7f7b850689ac06a62befe26e1fd1806799e7f152 ]
+
+It's observed that a crash occurs during hot-remove a memory device,
+in which user is accessing the hugetlb. See calltrace as following:
+
+------------[ cut here ]------------
+WARNING: CPU: 1 PID: 14045 at arch/x86/mm/fault.c:1278 do_user_addr_fault+0x2a0/0x790
+Modules linked in: kmem device_dax cxl_mem cxl_pmem cxl_port cxl_pci dax_hmem dax_pmem nd_pmem cxl_acpi nd_btt cxl_core crc32c_intel nvme virtiofs fuse nvme_core nfit libnvdimm dm_multipath scsi_dh_rdac scsi_dh_emc s
+mirror dm_region_hash dm_log dm_mod
+CPU: 1 PID: 14045 Comm: daxctl Not tainted 6.10.0-rc2-lizhijian+ #492
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
+RIP: 0010:do_user_addr_fault+0x2a0/0x790
+Code: 48 8b 00 a8 04 0f 84 b5 fe ff ff e9 1c ff ff ff 4c 89 e9 4c 89 e2 be 01 00 00 00 bf 02 00 00 00 e8 b5 ef 24 00 e9 42 fe ff ff <0f> 0b 48 83 c4 08 4c 89 ea 48 89 ee 4c 89 e7 5b 5d 41 5c 41 5d 41
+RSP: 0000:ffffc90000a575f0 EFLAGS: 00010046
+RAX: ffff88800c303600 RBX: 0000000000000000 RCX: 0000000000000000
+RDX: 0000000000001000 RSI: ffffffff82504162 RDI: ffffffff824b2c36
+RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000000 R12: ffffc90000a57658
+R13: 0000000000001000 R14: ffff88800bc2e040 R15: 0000000000000000
+FS:  00007f51cb57d880(0000) GS:ffff88807fd00000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000000000001000 CR3: 00000000072e2004 CR4: 00000000001706f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ ? __warn+0x8d/0x190
+ ? do_user_addr_fault+0x2a0/0x790
+ ? report_bug+0x1c3/0x1d0
+ ? handle_bug+0x3c/0x70
+ ? exc_invalid_op+0x14/0x70
+ ? asm_exc_invalid_op+0x16/0x20
+ ? do_user_addr_fault+0x2a0/0x790
+ ? exc_page_fault+0x31/0x200
+ exc_page_fault+0x68/0x200
+<...snip...>
+BUG: unable to handle page fault for address: 0000000000001000
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ PGD 800000000ad92067 P4D 800000000ad92067 PUD 7677067 PMD 0
+ Oops: Oops: 0000 [#1] PREEMPT SMP PTI
+ ---[ end trace 0000000000000000 ]---
+ BUG: unable to handle page fault for address: 0000000000001000
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ PGD 800000000ad92067 P4D 800000000ad92067 PUD 7677067 PMD 0
+ Oops: Oops: 0000 [#1] PREEMPT SMP PTI
+ CPU: 1 PID: 14045 Comm: daxctl Kdump: loaded Tainted: G        W          6.10.0-rc2-lizhijian+ #492
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
+ RIP: 0010:dentry_name+0x1f4/0x440
+<...snip...>
+? dentry_name+0x2fa/0x440
+vsnprintf+0x1f3/0x4f0
+vprintk_store+0x23a/0x540
+vprintk_emit+0x6d/0x330
+_printk+0x58/0x80
+dump_mapping+0x10b/0x1a0
+? __pfx_free_object_rcu+0x10/0x10
+__dump_page+0x26b/0x3e0
+? vprintk_emit+0xe0/0x330
+? _printk+0x58/0x80
+? dump_page+0x17/0x50
+dump_page+0x17/0x50
+do_migrate_range+0x2f7/0x7f0
+? do_migrate_range+0x42/0x7f0
+? offline_pages+0x2f4/0x8c0
+offline_pages+0x60a/0x8c0
+memory_subsys_offline+0x9f/0x1c0
+? lockdep_hardirqs_on+0x77/0x100
+? _raw_spin_unlock_irqrestore+0x38/0x60
+device_offline+0xe3/0x110
+state_store+0x6e/0xc0
+kernfs_fop_write_iter+0x143/0x200
+vfs_write+0x39f/0x560
+ksys_write+0x65/0xf0
+do_syscall_64+0x62/0x130
+
+Previously, some sanity check have been done in dump_mapping() before
+the print facility parsing '%pd' though, it's still possible to run into
+an invalid dentry.d_name.name.
+
+Since dump_mapping() only needs to dump the filename only, retrieve it
+by itself in a safer way to prevent an unnecessary crash.
+
+Note that either retrieving the filename with '%pd' or
+strncpy_from_kernel_nofault(), the filename could be unreliable.
+
+Signed-off-by: Li Zhijian <lizhijian@fujitsu.com>
+Link: https://lore.kernel.org/r/20240826055503.1522320-1-lizhijian@fujitsu.com
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/inode.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/fs/inode.c b/fs/inode.c
+index 7125b73b53675..551ba352072fa 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -595,6 +595,7 @@ void dump_mapping(const struct address_space *mapping)
+       struct hlist_node *dentry_first;
+       struct dentry *dentry_ptr;
+       struct dentry dentry;
++      char fname[64] = {};
+       unsigned long ino;
+       /*
+@@ -631,11 +632,14 @@ void dump_mapping(const struct address_space *mapping)
+               return;
+       }
++      if (strncpy_from_kernel_nofault(fname, dentry.d_name.name, 63) < 0)
++              strscpy(fname, "<invalid>");
+       /*
+-       * if dentry is corrupted, the %pd handler may still crash,
+-       * but it's unlikely that we reach here with a corrupt mapping
++       * Even if strncpy_from_kernel_nofault() succeeded,
++       * the fname could be unreliable
+        */
+-      pr_warn("aops:%ps ino:%lx dentry name:\"%pd\"\n", a_ops, ino, &dentry);
++      pr_warn("aops:%ps ino:%lx dentry name(?):\"%s\"\n",
++              a_ops, ino, fname);
+ }
+ void clear_inode(struct inode *inode)
+-- 
+2.43.0
+
diff --git a/queue-6.11/hid-i2c-hid-ensure-various-commands-do-not-interfere.patch b/queue-6.11/hid-i2c-hid-ensure-various-commands-do-not-interfere.patch
new file mode 100644 (file)
index 0000000..889f604
--- /dev/null
@@ -0,0 +1,130 @@
+From e3f7606499caf8c8be4c1932627971821da7f1a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Sep 2024 13:37:40 -0700
+Subject: HID: i2c-hid: ensure various commands do not interfere with each
+ other
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+[ Upstream commit b4ed18a3d56eabd18cfd9841ff05111e3cfbe8f9 ]
+
+i2c-hid uses 2 shared buffers: command and "raw" input buffer for
+sending requests to peripherals and read data from peripherals when
+executing variety of commands. Such commands include reading of HID
+registers, requesting particular power mode, getting and setting
+reports and so on. Because all such requests use the same 2 buffers
+they should not execute simultaneously.
+
+Fix this by introducing "cmd_lock" mutex and acquire it whenever
+we needs to access ihid->cmdbuf or idid->rawbuf.
+
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/i2c-hid/i2c-hid-core.c | 42 +++++++++++++++++++-----------
+ 1 file changed, 27 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
+index 632eaf9e11a6b..2f8a9d3f1e861 100644
+--- a/drivers/hid/i2c-hid/i2c-hid-core.c
++++ b/drivers/hid/i2c-hid/i2c-hid-core.c
+@@ -105,6 +105,7 @@ struct i2c_hid {
+       wait_queue_head_t       wait;           /* For waiting the interrupt */
++      struct mutex            cmd_lock;       /* protects cmdbuf and rawbuf */
+       struct mutex            reset_lock;
+       struct i2chid_ops       *ops;
+@@ -220,6 +221,8 @@ static int i2c_hid_xfer(struct i2c_hid *ihid,
+ static int i2c_hid_read_register(struct i2c_hid *ihid, __le16 reg,
+                                void *buf, size_t len)
+ {
++      guard(mutex)(&ihid->cmd_lock);
++
+       *(__le16 *)ihid->cmdbuf = reg;
+       return i2c_hid_xfer(ihid, ihid->cmdbuf, sizeof(__le16), buf, len);
+@@ -252,6 +255,8 @@ static int i2c_hid_get_report(struct i2c_hid *ihid,
+       i2c_hid_dbg(ihid, "%s\n", __func__);
++      guard(mutex)(&ihid->cmd_lock);
++
+       /* Command register goes first */
+       *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
+       length += sizeof(__le16);
+@@ -342,6 +347,8 @@ static int i2c_hid_set_or_send_report(struct i2c_hid *ihid,
+       if (!do_set && le16_to_cpu(ihid->hdesc.wMaxOutputLength) == 0)
+               return -ENOSYS;
++      guard(mutex)(&ihid->cmd_lock);
++
+       if (do_set) {
+               /* Command register goes first */
+               *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
+@@ -384,6 +391,8 @@ static int i2c_hid_set_power_command(struct i2c_hid *ihid, int power_state)
+ {
+       size_t length;
++      guard(mutex)(&ihid->cmd_lock);
++
+       /* SET_POWER uses command register */
+       *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
+       length = sizeof(__le16);
+@@ -440,25 +449,27 @@ static int i2c_hid_start_hwreset(struct i2c_hid *ihid)
+       if (ret)
+               return ret;
+-      /* Prepare reset command. Command register goes first. */
+-      *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
+-      length += sizeof(__le16);
+-      /* Next is RESET command itself */
+-      length += i2c_hid_encode_command(ihid->cmdbuf + length,
+-                                       I2C_HID_OPCODE_RESET, 0, 0);
++      scoped_guard(mutex, &ihid->cmd_lock) {
++              /* Prepare reset command. Command register goes first. */
++              *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
++              length += sizeof(__le16);
++              /* Next is RESET command itself */
++              length += i2c_hid_encode_command(ihid->cmdbuf + length,
++                                               I2C_HID_OPCODE_RESET, 0, 0);
+-      set_bit(I2C_HID_RESET_PENDING, &ihid->flags);
++              set_bit(I2C_HID_RESET_PENDING, &ihid->flags);
+-      ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0);
+-      if (ret) {
+-              dev_err(&ihid->client->dev,
+-                      "failed to reset device: %d\n", ret);
+-              goto err_clear_reset;
+-      }
++              ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0);
++              if (ret) {
++                      dev_err(&ihid->client->dev,
++                              "failed to reset device: %d\n", ret);
++                      break;
++              }
+-      return 0;
++              return 0;
++      }
+-err_clear_reset:
++      /* Clean up if sending reset command failed */
+       clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
+       i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
+       return ret;
+@@ -1200,6 +1211,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
+       ihid->is_panel_follower = drm_is_panel_follower(&client->dev);
+       init_waitqueue_head(&ihid->wait);
++      mutex_init(&ihid->cmd_lock);
+       mutex_init(&ihid->reset_lock);
+       INIT_WORK(&ihid->panel_follower_prepare_work, ihid_core_panel_prepare_work);
+-- 
+2.43.0
+
diff --git a/queue-6.11/hid-ignore-battery-for-all-elan-i2c-hid-devices.patch b/queue-6.11/hid-ignore-battery-for-all-elan-i2c-hid-devices.patch
new file mode 100644 (file)
index 0000000..194238a
--- /dev/null
@@ -0,0 +1,126 @@
+From fe351c59e4d765519fe6bbfbe4ad72d5c5779d3d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 16:51:47 +0200
+Subject: HID: Ignore battery for all ELAN I2C-HID devices
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit bcc31692a1d1e21f0d06c5f727c03ee299d2264e ]
+
+Before this change there were 16 vid:pid based quirks to ignore the battery
+reported by Elan I2C-HID touchscreens on various Asus and HP laptops.
+
+And a report has been received that the 04F3:2A00 I2C touchscreen on
+the HP ProBook x360 11 G5 EE/86CF also reports a non present battery.
+
+Since I2C-HID devices are always builtin to laptops they are not battery
+owered so it should be safe to just ignore the battery on all Elan I2C-HID
+devices, rather then adding a 17th quirk for the 04F3:2A00 touchscreen.
+
+As reported in the changelog of commit a3a5a37efba1 ("HID: Ignore battery
+for ELAN touchscreens 2F2C and 4116"), which added 2 new Elan touchscreen
+quirks about a month ago, the HID reported battery seems to be related
+to a stylus being used. But even when a stylus is in use it does not
+properly report the charge of the stylus battery, instead the reported
+battery charge jumps from 0% to 1%. So it is best to just ignore the
+HID battery.
+
+Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2302776
+Cc: Louis Dalibard <ontake@ontake.dev>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-ids.h   | 16 ----------------
+ drivers/hid/hid-input.c | 37 +++++--------------------------------
+ 2 files changed, 5 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 781c5aa298598..53655f81d9950 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -417,24 +417,8 @@
+ #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W       0x0401
+ #define USB_DEVICE_ID_HP_X2           0x074d
+ #define USB_DEVICE_ID_HP_X2_10_COVER  0x0755
+-#define I2C_DEVICE_ID_HP_ENVY_X360_15 0x2d05
+-#define I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100  0x29CF
+-#define I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV   0x2CF9
+-#define I2C_DEVICE_ID_HP_SPECTRE_X360_15      0x2817
+-#define I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG  0x29DF
+-#define I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN 0x2BC8
+-#define I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN 0x2C82
+-#define I2C_DEVICE_ID_ASUS_UX3402_TOUCHSCREEN 0x2F2C
+-#define I2C_DEVICE_ID_ASUS_UX6404_TOUCHSCREEN 0x4116
+ #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN        0x2544
+ #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN  0x2706
+-#define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN  0x261A
+-#define I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN 0x2A1C
+-#define I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN    0x279F
+-#define I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100       0x29F5
+-#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1    0x2BED
+-#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2    0x2BEE
+-#define I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG                0x2D02
+ #define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM       0x2F81
+ #define USB_VENDOR_ID_ELECOM          0x056e
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index c9094a4f281e9..fda9dce3da998 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -373,14 +373,6 @@ static const struct hid_device_id hid_battery_quirks[] = {
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
+               USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD),
+         HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_UX3402_TOUCHSCREEN),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_UX6404_TOUCHSCREEN),
+-        HID_BATTERY_QUIRK_IGNORE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN),
+         HID_BATTERY_QUIRK_IGNORE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN),
+@@ -391,32 +383,13 @@ static const struct hid_device_id hid_battery_quirks[] = {
+         HID_BATTERY_QUIRK_AVOID_QUERY },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW),
+         HID_BATTERY_QUIRK_AVOID_QUERY },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2),
+-        HID_BATTERY_QUIRK_IGNORE },
+-      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG),
+-        HID_BATTERY_QUIRK_IGNORE },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM),
+         HID_BATTERY_QUIRK_AVOID_QUERY },
++      /*
++       * Elan I2C-HID touchscreens seem to all report a non present battery,
++       * set HID_BATTERY_QUIRK_IGNORE for all Elan I2C-HID devices.
++       */
++      { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_IGNORE },
+       {}
+ };
+-- 
+2.43.0
+
diff --git a/queue-6.11/hid-multitouch-add-support-for-thinkpad-x12-gen-2-kb.patch b/queue-6.11/hid-multitouch-add-support-for-thinkpad-x12-gen-2-kb.patch
new file mode 100644 (file)
index 0000000..3914829
--- /dev/null
@@ -0,0 +1,54 @@
+From 165ccdc2481b0e0e899a1f3613e92c9f87036db8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Aug 2024 16:27:29 +0900
+Subject: HID: multitouch: Add support for Thinkpad X12 Gen 2 Kbd Portfolio
+
+From: Vishnu Sankar <vishnuocv@gmail.com>
+
+[ Upstream commit 65b72ea91a257a5f0cb5a26b01194d3dd4b85298 ]
+
+This applies similar quirks used by previous generation device, so that
+Trackpoint and buttons on the touchpad works.  New USB KBD PID 0x61AE for
+Thinkpad X12 Tab is added.
+
+Signed-off-by: Vishnu Sankar <vishnuocv@gmail.com>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-ids.h        | 1 +
+ drivers/hid/hid-multitouch.c | 6 ++++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 53655f81d9950..06104a4e0fdc1 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -794,6 +794,7 @@
+ #define USB_DEVICE_ID_LENOVO_X1_TAB   0x60a3
+ #define USB_DEVICE_ID_LENOVO_X1_TAB3  0x60b5
+ #define USB_DEVICE_ID_LENOVO_X12_TAB  0x60fe
++#define USB_DEVICE_ID_LENOVO_X12_TAB2 0x61ae
+ #define USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E   0x600e
+ #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D    0x608d
+ #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019    0x6019
+diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
+index 99812c0f830b5..c4a6908bbe540 100644
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -2113,6 +2113,12 @@ static const struct hid_device_id mt_devices[] = {
+                          USB_VENDOR_ID_LENOVO,
+                          USB_DEVICE_ID_LENOVO_X12_TAB) },
++      /* Lenovo X12 TAB Gen 2 */
++      { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU,
++              HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
++                         USB_VENDOR_ID_LENOVO,
++                         USB_DEVICE_ID_LENOVO_X12_TAB2) },
++
+       /* Logitech devices */
+       { .driver_data = MT_CLS_NSMU,
+               HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH_WIN_8,
+-- 
+2.43.0
+
diff --git a/queue-6.11/hwmon-nct6775-add-g15cf-to-asus-wmi-monitoring-list.patch b/queue-6.11/hwmon-nct6775-add-g15cf-to-asus-wmi-monitoring-list.patch
new file mode 100644 (file)
index 0000000..55cd038
--- /dev/null
@@ -0,0 +1,39 @@
+From e319ce9aa75d421378c9beeeaf1df59a00cca36d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Aug 2024 18:26:38 +0300
+Subject: hwmon: (nct6775) add G15CF to ASUS WMI monitoring list
+
+From: Denis Pauk <pauk.denis@gmail.com>
+
+[ Upstream commit 1f432e4cf1dd3ecfec5ed80051b4611632a0fd51 ]
+
+Boards G15CF has got a nct6775 chip, but by default there's no use of it
+because of resource conflict with WMI method.
+
+Add the board to the WMI monitoring list.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=204807
+Signed-off-by: Denis Pauk <pauk.denis@gmail.com>
+Tested-by: Attila <attila@fulop.one>
+Message-ID: <20240812152652.1303-1-pauk.denis@gmail.com>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/nct6775-platform.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c
+index 9aa4dcf4a6f33..096f1daa8f2bc 100644
+--- a/drivers/hwmon/nct6775-platform.c
++++ b/drivers/hwmon/nct6775-platform.c
+@@ -1269,6 +1269,7 @@ static const char * const asus_msi_boards[] = {
+       "EX-B760M-V5 D4",
+       "EX-H510M-V3",
+       "EX-H610M-V3 D4",
++      "G15CF",
+       "PRIME A620M-A",
+       "PRIME B560-PLUS",
+       "PRIME B560-PLUS AC-HES",
+-- 
+2.43.0
+
diff --git a/queue-6.11/ice-adjust-over-allocation-of-memory-in-ice_sched_ad.patch b/queue-6.11/ice-adjust-over-allocation-of-memory-in-ice_sched_ad.patch
new file mode 100644 (file)
index 0000000..7a2b383
--- /dev/null
@@ -0,0 +1,61 @@
+From 687f2f6d8f01301d06cf5cbfb21998ea6fd4c4ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Jul 2024 15:39:49 +0300
+Subject: ice: Adjust over allocation of memory in ice_sched_add_root_node()
+ and ice_sched_add_node()
+
+From: Aleksandr Mishin <amishin@t-argos.ru>
+
+[ Upstream commit 62fdaf9e8056e9a9e6fe63aa9c816ec2122d60c6 ]
+
+In ice_sched_add_root_node() and ice_sched_add_node() there are calls to
+devm_kcalloc() in order to allocate memory for array of pointers to
+'ice_sched_node' structure. But incorrect types are used as sizeof()
+arguments in these calls (structures instead of pointers) which leads to
+over allocation of memory.
+
+Adjust over allocation of memory by correcting types in devm_kcalloc()
+sizeof() arguments.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_sched.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c
+index ecf8f5d602921..6ca13c5dcb14e 100644
+--- a/drivers/net/ethernet/intel/ice/ice_sched.c
++++ b/drivers/net/ethernet/intel/ice/ice_sched.c
+@@ -28,9 +28,8 @@ ice_sched_add_root_node(struct ice_port_info *pi,
+       if (!root)
+               return -ENOMEM;
+-      /* coverity[suspicious_sizeof] */
+       root->children = devm_kcalloc(ice_hw_to_dev(hw), hw->max_children[0],
+-                                    sizeof(*root), GFP_KERNEL);
++                                    sizeof(*root->children), GFP_KERNEL);
+       if (!root->children) {
+               devm_kfree(ice_hw_to_dev(hw), root);
+               return -ENOMEM;
+@@ -186,10 +185,9 @@ ice_sched_add_node(struct ice_port_info *pi, u8 layer,
+       if (!node)
+               return -ENOMEM;
+       if (hw->max_children[layer]) {
+-              /* coverity[suspicious_sizeof] */
+               node->children = devm_kcalloc(ice_hw_to_dev(hw),
+                                             hw->max_children[layer],
+-                                            sizeof(*node), GFP_KERNEL);
++                                            sizeof(*node->children), GFP_KERNEL);
+               if (!node->children) {
+                       devm_kfree(ice_hw_to_dev(hw), node);
+                       return -ENOMEM;
+-- 
+2.43.0
+
diff --git a/queue-6.11/intel_idle-disable-promotion-to-c1e-on-jasper-lake-a.patch b/queue-6.11/intel_idle-disable-promotion-to-c1e-on-jasper-lake-a.patch
new file mode 100644 (file)
index 0000000..994311d
--- /dev/null
@@ -0,0 +1,76 @@
+From eb865596b4b82e7cf33ddda39b04313593509c1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Aug 2024 12:11:28 +0800
+Subject: intel_idle: Disable promotion to C1E on Jasper Lake and Elkhart Lake
+
+From: Kai-Heng Feng <kai.heng.feng@canonical.com>
+
+[ Upstream commit 5bb33212b5c664396e5de4cd5a2999abb84a3978 ]
+
+PCIe ethernet throughut is sub-optimal on Jasper Lake and Elkhart Lake.
+
+The CPU can take long time to exit to C0 to handle IRQ and perform DMA
+when C1E has been entered.
+
+For this reason, adjust intel_idle to disable promotion to C1E and still
+use C-states from ACPI _CST on those two platforms.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=219023
+Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Link: https://patch.msgid.link/20240820041128.102452-1-kai.heng.feng@canonical.com
+[ rjw: Subject and changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/idle/intel_idle.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
+index 88470602b789e..67aebfe0fed66 100644
+--- a/drivers/idle/intel_idle.c
++++ b/drivers/idle/intel_idle.c
+@@ -1530,6 +1530,10 @@ static const struct idle_cpu idle_cpu_dnv __initconst = {
+       .use_acpi = true,
+ };
++static const struct idle_cpu idle_cpu_tmt __initconst = {
++      .disable_promotion_to_c1e = true,
++};
++
+ static const struct idle_cpu idle_cpu_snr __initconst = {
+       .state_table = snr_cstates,
+       .disable_promotion_to_c1e = true,
+@@ -1594,6 +1598,8 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
+       X86_MATCH_VFM(INTEL_ATOM_GOLDMONT,      &idle_cpu_bxt),
+       X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_PLUS, &idle_cpu_bxt),
+       X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_D,    &idle_cpu_dnv),
++      X86_MATCH_VFM(INTEL_ATOM_TREMONT,       &idle_cpu_tmt),
++      X86_MATCH_VFM(INTEL_ATOM_TREMONT_L,     &idle_cpu_tmt),
+       X86_MATCH_VFM(INTEL_ATOM_TREMONT_D,     &idle_cpu_snr),
+       X86_MATCH_VFM(INTEL_ATOM_CRESTMONT,     &idle_cpu_grr),
+       X86_MATCH_VFM(INTEL_ATOM_CRESTMONT_X,   &idle_cpu_srf),
+@@ -2142,7 +2148,7 @@ static void __init intel_idle_cpuidle_driver_init(struct cpuidle_driver *drv)
+       drv->state_count = 1;
+-      if (icpu)
++      if (icpu && icpu->state_table)
+               intel_idle_init_cstates_icpu(drv);
+       else
+               intel_idle_init_cstates_acpi(drv);
+@@ -2276,7 +2282,11 @@ static int __init intel_idle_init(void)
+       icpu = (const struct idle_cpu *)id->driver_data;
+       if (icpu) {
+-              cpuidle_state_table = icpu->state_table;
++              if (icpu->state_table)
++                      cpuidle_state_table = icpu->state_table;
++              else if (!intel_idle_acpi_cst_extract())
++                      return -ENODEV;
++
+               auto_demotion_disable_flags = icpu->auto_demotion_disable_flags;
+               if (icpu->disable_promotion_to_c1e)
+                       c1e_promotion = C1E_PROMOTION_DISABLE;
+-- 
+2.43.0
+
diff --git a/queue-6.11/iomap-handle-a-post-direct-i-o-invalidate-race-in-io.patch b/queue-6.11/iomap-handle-a-post-direct-i-o-invalidate-race-in-io.patch
new file mode 100644 (file)
index 0000000..d4619e7
--- /dev/null
@@ -0,0 +1,49 @@
+From f696f4bbeec141d7fecf0c8b3f87c65532ea537d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Sep 2024 07:39:03 +0300
+Subject: iomap: handle a post-direct I/O invalidate race in
+ iomap_write_delalloc_release
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 7a9d43eace888a0ee6095035997bb138425844d3 ]
+
+When direct I/O completions invalidates the page cache it holds neither the
+i_rwsem nor the invalidate_lock so it can be racing with
+iomap_write_delalloc_release.  If the search for the end of the region that
+contains data returns the start offset we hit such a race and just need to
+look for the end of the newly created hole instead.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20240910043949.3481298-2-hch@lst.de
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/iomap/buffered-io.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
+index 389de94715b53..8e6edb6628183 100644
+--- a/fs/iomap/buffered-io.c
++++ b/fs/iomap/buffered-io.c
+@@ -1241,7 +1241,15 @@ static int iomap_write_delalloc_release(struct inode *inode,
+                       error = data_end;
+                       goto out_unlock;
+               }
+-              WARN_ON_ONCE(data_end <= start_byte);
++
++              /*
++               * If we race with post-direct I/O invalidation of the page cache,
++               * there might be no data left at start_byte.
++               */
++              if (data_end == start_byte)
++                      continue;
++
++              WARN_ON_ONCE(data_end < start_byte);
+               WARN_ON_ONCE(data_end > scan_end_byte);
+               error = iomap_write_delalloc_scan(inode, &punch_start_byte,
+-- 
+2.43.0
+
diff --git a/queue-6.11/iommu-arm-smmu-v3-do-not-use-devm-for-the-cd-table-a.patch b/queue-6.11/iommu-arm-smmu-v3-do-not-use-devm-for-the-cd-table-a.patch
new file mode 100644 (file)
index 0000000..c622db2
--- /dev/null
@@ -0,0 +1,103 @@
+From b2c8358f4e39e80103c809635b3f070c9563fb11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Sep 2024 12:47:52 -0300
+Subject: iommu/arm-smmu-v3: Do not use devm for the cd table allocations
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit 47b2de35cab2b683f69d03515c2658c2d8515323 ]
+
+The master->cd_table is entirely contained within the struct
+arm_smmu_master which is guaranteed to be freed by the core code under
+arm_smmu_release_device().
+
+There is no reason to use devm here, arm_smmu_free_cd_tables() is reliably
+called to free the CD related memory. Remove it and save some memory.
+
+Tested-by: Nicolin Chen <nicolinc@nvidia.com>
+Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Link: https://lore.kernel.org/r/5-v4-6416877274e1+1af-smmuv3_tidy_jgg@nvidia.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 29 +++++++++------------
+ 1 file changed, 13 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+index d271525fa3917..473eb772ea210 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+@@ -1185,8 +1185,8 @@ static int arm_smmu_alloc_cd_leaf_table(struct arm_smmu_device *smmu,
+ {
+       size_t size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
+-      l1_desc->l2ptr = dmam_alloc_coherent(smmu->dev, size,
+-                                           &l1_desc->l2ptr_dma, GFP_KERNEL);
++      l1_desc->l2ptr = dma_alloc_coherent(smmu->dev, size,
++                                          &l1_desc->l2ptr_dma, GFP_KERNEL);
+       if (!l1_desc->l2ptr) {
+               dev_warn(smmu->dev,
+                        "failed to allocate context descriptor table\n");
+@@ -1400,17 +1400,17 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
+               cd_table->num_l1_ents = DIV_ROUND_UP(max_contexts,
+                                                 CTXDESC_L2_ENTRIES);
+-              cd_table->l1_desc = devm_kcalloc(smmu->dev, cd_table->num_l1_ents,
+-                                            sizeof(*cd_table->l1_desc),
+-                                            GFP_KERNEL);
++              cd_table->l1_desc = kcalloc(cd_table->num_l1_ents,
++                                          sizeof(*cd_table->l1_desc),
++                                          GFP_KERNEL);
+               if (!cd_table->l1_desc)
+                       return -ENOMEM;
+               l1size = cd_table->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
+       }
+-      cd_table->cdtab = dmam_alloc_coherent(smmu->dev, l1size, &cd_table->cdtab_dma,
+-                                         GFP_KERNEL);
++      cd_table->cdtab = dma_alloc_coherent(smmu->dev, l1size,
++                                           &cd_table->cdtab_dma, GFP_KERNEL);
+       if (!cd_table->cdtab) {
+               dev_warn(smmu->dev, "failed to allocate context descriptor\n");
+               ret = -ENOMEM;
+@@ -1421,7 +1421,7 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
+ err_free_l1:
+       if (cd_table->l1_desc) {
+-              devm_kfree(smmu->dev, cd_table->l1_desc);
++              kfree(cd_table->l1_desc);
+               cd_table->l1_desc = NULL;
+       }
+       return ret;
+@@ -1441,21 +1441,18 @@ static void arm_smmu_free_cd_tables(struct arm_smmu_master *master)
+                       if (!cd_table->l1_desc[i].l2ptr)
+                               continue;
+-                      dmam_free_coherent(smmu->dev, size,
+-                                         cd_table->l1_desc[i].l2ptr,
+-                                         cd_table->l1_desc[i].l2ptr_dma);
++                      dma_free_coherent(smmu->dev, size,
++                                        cd_table->l1_desc[i].l2ptr,
++                                        cd_table->l1_desc[i].l2ptr_dma);
+               }
+-              devm_kfree(smmu->dev, cd_table->l1_desc);
+-              cd_table->l1_desc = NULL;
++              kfree(cd_table->l1_desc);
+               l1size = cd_table->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
+       } else {
+               l1size = cd_table->num_l1_ents * (CTXDESC_CD_DWORDS << 3);
+       }
+-      dmam_free_coherent(smmu->dev, l1size, cd_table->cdtab, cd_table->cdtab_dma);
+-      cd_table->cdtab_dma = 0;
+-      cd_table->cdtab = NULL;
++      dma_free_coherent(smmu->dev, l1size, cd_table->cdtab, cd_table->cdtab_dma);
+ }
+ /* Stream table manipulation functions */
+-- 
+2.43.0
+
diff --git a/queue-6.11/iommu-arm-smmu-v3-match-stall-behaviour-for-s2.patch b/queue-6.11/iommu-arm-smmu-v3-match-stall-behaviour-for-s2.patch
new file mode 100644 (file)
index 0000000..86fa3a0
--- /dev/null
@@ -0,0 +1,93 @@
+From 072c4951a7ecaf8ff537dd9ed50b5937deec405c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 Aug 2024 11:03:47 +0000
+Subject: iommu/arm-smmu-v3: Match Stall behaviour for S2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mostafa Saleh <smostafa@google.com>
+
+[ Upstream commit ce7cb08e22e09f43649b025c849a3ae3b80833c4 ]
+
+According to the spec (ARM IHI 0070 F.b), in
+"5.5 Fault configuration (A, R, S bits)":
+    A STE with stage 2 translation enabled and STE.S2S == 0 is
+    considered ILLEGAL if SMMU_IDR0.STALL_MODEL == 0b10.
+
+Also described in the pseudocode “SteIllegal()”
+    if STE.Config == '11x' then
+        [..]
+        if eff_idr0_stall_model == '10' && STE.S2S == '0' then
+            // stall_model forcing stall, but S2S == 0
+            return TRUE;
+
+Which means, S2S must be set when stall model is
+"ARM_SMMU_FEAT_STALL_FORCE", but currently the driver ignores that.
+
+Although, the driver can do the minimum and only set S2S for
+“ARM_SMMU_FEAT_STALL_FORCE”, it is more consistent to match S1
+behaviour, which also sets it for “ARM_SMMU_FEAT_STALL” if the
+master has requested stalls.
+
+Also, since S2 stalls are enabled now, report them to the IOMMU layer
+and for VFIO devices it will fail anyway as VFIO doesn’t register an
+iopf handler.
+
+Signed-off-by: Mostafa Saleh <smostafa@google.com>
+Link: https://lore.kernel.org/r/20240830110349.797399-2-smostafa@google.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 8 +++-----
+ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 +
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+index f490385c13605..d271525fa3917 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+@@ -1012,7 +1012,8 @@ void arm_smmu_get_ste_used(const __le64 *ent, __le64 *used_bits)
+               used_bits[2] |=
+                       cpu_to_le64(STRTAB_STE_2_S2VMID | STRTAB_STE_2_VTCR |
+                                   STRTAB_STE_2_S2AA64 | STRTAB_STE_2_S2ENDI |
+-                                  STRTAB_STE_2_S2PTW | STRTAB_STE_2_S2R);
++                                  STRTAB_STE_2_S2PTW | STRTAB_STE_2_S2S |
++                                  STRTAB_STE_2_S2R);
+               used_bits[3] |= cpu_to_le64(STRTAB_STE_3_S2TTB_MASK);
+       }
+@@ -1646,6 +1647,7 @@ void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
+               STRTAB_STE_2_S2ENDI |
+ #endif
+               STRTAB_STE_2_S2PTW |
++              (master->stall_enabled ? STRTAB_STE_2_S2S : 0) |
+               STRTAB_STE_2_S2R);
+       target->data[3] = cpu_to_le64(pgtbl_cfg->arm_lpae_s2_cfg.vttbr &
+@@ -1739,10 +1741,6 @@ static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt)
+               return -EOPNOTSUPP;
+       }
+-      /* Stage-2 is always pinned at the moment */
+-      if (evt[1] & EVTQ_1_S2)
+-              return -EFAULT;
+-
+       if (!(evt[1] & EVTQ_1_STALL))
+               return -EOPNOTSUPP;
+diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+index 14bca41a981b4..0dc7ad43c64c0 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+@@ -267,6 +267,7 @@ struct arm_smmu_ste {
+ #define STRTAB_STE_2_S2AA64           (1UL << 51)
+ #define STRTAB_STE_2_S2ENDI           (1UL << 52)
+ #define STRTAB_STE_2_S2PTW            (1UL << 54)
++#define STRTAB_STE_2_S2S              (1UL << 57)
+ #define STRTAB_STE_2_S2R              (1UL << 58)
+ #define STRTAB_STE_3_S2TTB_MASK               GENMASK_ULL(51, 4)
+-- 
+2.43.0
+
diff --git a/queue-6.11/iommu-vt-d-always-reserve-a-domain-id-for-identity-s.patch b/queue-6.11/iommu-vt-d-always-reserve-a-domain-id-for-identity-s.patch
new file mode 100644 (file)
index 0000000..8010b29
--- /dev/null
@@ -0,0 +1,44 @@
+From 042652825b1ec3b81b50407fbec1ff314036bb86 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Sep 2024 10:27:13 +0800
+Subject: iommu/vt-d: Always reserve a domain ID for identity setup
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit 2c13012e09190174614fd6901857a1b8c199e17d ]
+
+We will use a global static identity domain. Reserve a static domain ID
+for it.
+
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Link: https://lore.kernel.org/r/20240809055431.36513-4-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/iommu.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 4aa070cf56e70..e3e513cabc86a 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -1447,10 +1447,10 @@ static int iommu_init_domains(struct intel_iommu *iommu)
+        * entry for first-level or pass-through translation modes should
+        * be programmed with a domain id different from those used for
+        * second-level or nested translation. We reserve a domain id for
+-       * this purpose.
++       * this purpose. This domain id is also used for identity domain
++       * in legacy mode.
+        */
+-      if (sm_supported(iommu))
+-              set_bit(FLPT_DEFAULT_DID, iommu->domain_ids);
++      set_bit(FLPT_DEFAULT_DID, iommu->domain_ids);
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/iommu-vt-d-fix-potential-lockup-if-qi_submit_sync-ca.patch b/queue-6.11/iommu-vt-d-fix-potential-lockup-if-qi_submit_sync-ca.patch
new file mode 100644 (file)
index 0000000..8505acf
--- /dev/null
@@ -0,0 +1,128 @@
+From 46c704ef73764d7b8dbf2649d3868a825bdbe458 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Sep 2024 10:27:18 +0800
+Subject: iommu/vt-d: Fix potential lockup if qi_submit_sync called with 0
+ count
+
+From: Sanjay K Kumar <sanjay.k.kumar@intel.com>
+
+[ Upstream commit 3cf74230c139f208b7fb313ae0054386eee31a81 ]
+
+If qi_submit_sync() is invoked with 0 invalidation descriptors (for
+instance, for DMA draining purposes), we can run into a bug where a
+submitting thread fails to detect the completion of invalidation_wait.
+Subsequently, this led to a soft lockup. Currently, there is no impact
+by this bug on the existing users because no callers are submitting
+invalidations with 0 descriptors. This fix will enable future users
+(such as DMA drain) calling qi_submit_sync() with 0 count.
+
+Suppose thread T1 invokes qi_submit_sync() with non-zero descriptors, while
+concurrently, thread T2 calls qi_submit_sync() with zero descriptors. Both
+threads then enter a while loop, waiting for their respective descriptors
+to complete. T1 detects its completion (i.e., T1's invalidation_wait status
+changes to QI_DONE by HW) and proceeds to call reclaim_free_desc() to
+reclaim all descriptors, potentially including adjacent ones of other
+threads that are also marked as QI_DONE.
+
+During this time, while T2 is waiting to acquire the qi->q_lock, the IOMMU
+hardware may complete the invalidation for T2, setting its status to
+QI_DONE. However, if T1's execution of reclaim_free_desc() frees T2's
+invalidation_wait descriptor and changes its status to QI_FREE, T2 will
+not observe the QI_DONE status for its invalidation_wait and will
+indefinitely remain stuck.
+
+This soft lockup does not occur when only non-zero descriptors are
+submitted.In such cases, invalidation descriptors are interspersed among
+wait descriptors with the status QI_IN_USE, acting as barriers. These
+barriers prevent the reclaim code from mistakenly freeing descriptors
+belonging to other submitters.
+
+Considered the following example timeline:
+       T1                      T2
+========================================
+       ID1
+       WD1
+       while(WD1!=QI_DONE)
+       unlock
+                               lock
+       WD1=QI_DONE*            WD2
+                               while(WD2!=QI_DONE)
+                               unlock
+       lock
+       WD1==QI_DONE?
+       ID1=QI_DONE             WD2=DONE*
+       reclaim()
+       ID1=FREE
+       WD1=FREE
+       WD2=FREE
+       unlock
+                               soft lockup! T2 never sees QI_DONE in WD2
+
+Where:
+ID = invalidation descriptor
+WD = wait descriptor
+* Written by hardware
+
+The root of the problem is that the descriptor status QI_DONE flag is used
+for two conflicting purposes:
+1. signal a descriptor is ready for reclaim (to be freed)
+2. signal by the hardware that a wait descriptor is complete
+
+The solution (in this patch) is state separation by using QI_FREE flag
+for #1.
+
+Once a thread's invalidation descriptors are complete, their status would
+be set to QI_FREE. The reclaim_free_desc() function would then only
+free descriptors marked as QI_FREE instead of those marked as
+QI_DONE. This change ensures that T2 (from the previous example) will
+correctly observe the completion of its invalidation_wait (marked as
+QI_DONE).
+
+Signed-off-by: Sanjay K Kumar <sanjay.k.kumar@intel.com>
+Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20240728210059.1964602-1-jacob.jun.pan@linux.intel.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/dmar.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
+index 1c8d3141cb55c..01e157d89a163 100644
+--- a/drivers/iommu/intel/dmar.c
++++ b/drivers/iommu/intel/dmar.c
+@@ -1204,9 +1204,7 @@ static void free_iommu(struct intel_iommu *iommu)
+  */
+ static inline void reclaim_free_desc(struct q_inval *qi)
+ {
+-      while (qi->desc_status[qi->free_tail] == QI_DONE ||
+-             qi->desc_status[qi->free_tail] == QI_ABORT) {
+-              qi->desc_status[qi->free_tail] = QI_FREE;
++      while (qi->desc_status[qi->free_tail] == QI_FREE && qi->free_tail != qi->free_head) {
+               qi->free_tail = (qi->free_tail + 1) % QI_LENGTH;
+               qi->free_cnt++;
+       }
+@@ -1463,8 +1461,16 @@ int qi_submit_sync(struct intel_iommu *iommu, struct qi_desc *desc,
+               raw_spin_lock(&qi->q_lock);
+       }
+-      for (i = 0; i < count; i++)
+-              qi->desc_status[(index + i) % QI_LENGTH] = QI_DONE;
++      /*
++       * The reclaim code can free descriptors from multiple submissions
++       * starting from the tail of the queue. When count == 0, the
++       * status of the standalone wait descriptor at the tail of the queue
++       * must be set to QI_FREE to allow the reclaim code to proceed.
++       * It is also possible that descriptors from one of the previous
++       * submissions has to be reclaimed by a subsequent submission.
++       */
++      for (i = 0; i <= count; i++)
++              qi->desc_status[(index + i) % QI_LENGTH] = QI_FREE;
+       reclaim_free_desc(qi);
+       raw_spin_unlock_irqrestore(&qi->q_lock, flags);
+-- 
+2.43.0
+
diff --git a/queue-6.11/iommu-vt-d-unconditionally-flush-device-tlb-for-pasi.patch b/queue-6.11/iommu-vt-d-unconditionally-flush-device-tlb-for-pasi.patch
new file mode 100644 (file)
index 0000000..e7978aa
--- /dev/null
@@ -0,0 +1,70 @@
+From b5f7c9a1e1e61ee5540b847d9083cd9d616d2ca2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Sep 2024 10:27:20 +0800
+Subject: iommu/vt-d: Unconditionally flush device TLB for pasid table updates
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+[ Upstream commit 1f5e307ca16c0c19186cbd56ac460a687e6daba0 ]
+
+The caching mode of an IOMMU is irrelevant to the behavior of the device
+TLB. Previously, commit <304b3bde24b5> ("iommu/vt-d: Remove caching mode
+check before device TLB flush") removed this redundant check in the
+domain unmap path.
+
+Checking the caching mode before flushing the device TLB after a pasid
+table entry is updated is unnecessary and can lead to inconsistent
+behavior.
+
+Extends this consistency by removing the caching mode check in the pasid
+table update path.
+
+Suggested-by: Yi Liu <yi.l.liu@intel.com>
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Link: https://lore.kernel.org/r/20240820030208.20020-1-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/pasid.c | 12 +++---------
+ 1 file changed, 3 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
+index b51fc268dc845..2e5fa0a232999 100644
+--- a/drivers/iommu/intel/pasid.c
++++ b/drivers/iommu/intel/pasid.c
+@@ -264,9 +264,7 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
+       else
+               iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
+-      /* Device IOTLB doesn't need to be flushed in caching mode. */
+-      if (!cap_caching_mode(iommu->cap))
+-              devtlb_invalidation_with_pasid(iommu, dev, pasid);
++      devtlb_invalidation_with_pasid(iommu, dev, pasid);
+ }
+ /*
+@@ -493,9 +491,7 @@ int intel_pasid_setup_dirty_tracking(struct intel_iommu *iommu,
+       iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
+-      /* Device IOTLB doesn't need to be flushed in caching mode. */
+-      if (!cap_caching_mode(iommu->cap))
+-              devtlb_invalidation_with_pasid(iommu, dev, pasid);
++      devtlb_invalidation_with_pasid(iommu, dev, pasid);
+       return 0;
+ }
+@@ -572,9 +568,7 @@ void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,
+       pasid_cache_invalidation_with_pasid(iommu, did, pasid);
+       qi_flush_piotlb(iommu, did, pasid, 0, -1, 0);
+-      /* Device IOTLB doesn't need to be flushed in caching mode. */
+-      if (!cap_caching_mode(iommu->cap))
+-              devtlb_invalidation_with_pasid(iommu, dev, pasid);
++      devtlb_invalidation_with_pasid(iommu, dev, pasid);
+ }
+ /**
+-- 
+2.43.0
+
diff --git a/queue-6.11/ipv4-check-in_dev-earlier-for-ioctl-siocsifaddr.patch b/queue-6.11/ipv4-check-in_dev-earlier-for-ioctl-siocsifaddr.patch
new file mode 100644 (file)
index 0000000..8633fbd
--- /dev/null
@@ -0,0 +1,52 @@
+From af2f39cc2e7e84bd5bf50c3890d3fe42d9ed6a49 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Aug 2024 16:54:02 -0700
+Subject: ipv4: Check !in_dev earlier for ioctl(SIOCSIFADDR).
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit e3af3d3c5b26c33a7950e34e137584f6056c4319 ]
+
+dev->ip_ptr could be NULL if we set an invalid MTU.
+
+Even then, if we issue ioctl(SIOCSIFADDR) for a new IPv4 address,
+devinet_ioctl() allocates struct in_ifaddr and fails later in
+inet_set_ifa() because in_dev is NULL.
+
+Let's move the check earlier.
+
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20240809235406.50187-2-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/devinet.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
+index d96f3e452fef6..ddab151164542 100644
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -574,10 +574,6 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
+       ASSERT_RTNL();
+-      if (!in_dev) {
+-              inet_free_ifa(ifa);
+-              return -ENOBUFS;
+-      }
+       ipv4_devconf_setall(in_dev);
+       neigh_parms_data_state_setall(in_dev->arp_parms);
+       if (ifa->ifa_dev != in_dev) {
+@@ -1184,6 +1180,8 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
+               if (!ifa) {
+                       ret = -ENOBUFS;
++                      if (!in_dev)
++                              break;
+                       ifa = inet_alloc_ifa();
+                       if (!ifa)
+                               break;
+-- 
+2.43.0
+
diff --git a/queue-6.11/ipv4-mask-upper-dscp-bits-and-ecn-bits-in-netlink_fi.patch b/queue-6.11/ipv4-mask-upper-dscp-bits-and-ecn-bits-in-netlink_fi.patch
new file mode 100644 (file)
index 0000000..a794552
--- /dev/null
@@ -0,0 +1,50 @@
+From 98865e33421db4f85e06636e1f6e896bc7763980 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Aug 2024 15:52:22 +0300
+Subject: ipv4: Mask upper DSCP bits and ECN bits in NETLINK_FIB_LOOKUP family
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 8fed54758cd248cd311a2b5c1e180abef1866237 ]
+
+The NETLINK_FIB_LOOKUP netlink family can be used to perform a FIB
+lookup according to user provided parameters and communicate the result
+back to user space.
+
+However, unlike other users of the FIB lookup API, the upper DSCP bits
+and the ECN bits of the DS field are not masked, which can result in the
+wrong result being returned.
+
+Solve this by masking the upper DSCP bits and the ECN bits using
+IPTOS_RT_MASK.
+
+The structure that communicates the request and the response is not
+exported to user space, so it is unlikely that this netlink family is
+actually in use [1].
+
+[1] https://lore.kernel.org/netdev/ZpqpB8vJU%2FQ6LSqa@debian/
+
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Guillaume Nault <gnault@redhat.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/fib_frontend.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
+index 7ad2cafb92763..da540ddb7af65 100644
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -1343,7 +1343,7 @@ static void nl_fib_lookup(struct net *net, struct fib_result_nl *frn)
+       struct flowi4           fl4 = {
+               .flowi4_mark = frn->fl_mark,
+               .daddr = frn->fl_addr,
+-              .flowi4_tos = frn->fl_tos,
++              .flowi4_tos = frn->fl_tos & IPTOS_RT_MASK,
+               .flowi4_scope = frn->fl_scope,
+       };
+       struct fib_table *tb;
+-- 
+2.43.0
+
diff --git a/queue-6.11/jfs-check-if-leafidx-greater-than-num-leaves-per-dma.patch b/queue-6.11/jfs-check-if-leafidx-greater-than-num-leaves-per-dma.patch
new file mode 100644 (file)
index 0000000..a92cf32
--- /dev/null
@@ -0,0 +1,52 @@
+From 2230541508d37db500d963c104a3d7212d138a54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 24 Aug 2024 09:25:23 +0800
+Subject: jfs: check if leafidx greater than num leaves per dmap tree
+
+From: Edward Adam Davis <eadavis@qq.com>
+
+[ Upstream commit d64ff0d2306713ff084d4b09f84ed1a8c75ecc32 ]
+
+syzbot report a out of bounds in dbSplit, it because dmt_leafidx greater
+than num leaves per dmap tree, add a checking for dmt_leafidx in dbFindLeaf.
+
+Shaggy:
+Modified sanity check to apply to control pages as well as leaf pages.
+
+Reported-and-tested-by: syzbot+dca05492eff41f604890@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=dca05492eff41f604890
+Signed-off-by: Edward Adam Davis <eadavis@qq.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_dmap.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index 8847e8c5d5b45..974ecf5e0d952 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -2944,9 +2944,10 @@ static void dbAdjTree(dmtree_t *tp, int leafno, int newval, bool is_ctl)
+ static int dbFindLeaf(dmtree_t *tp, int l2nb, int *leafidx, bool is_ctl)
+ {
+       int ti, n = 0, k, x = 0;
+-      int max_size;
++      int max_size, max_idx;
+       max_size = is_ctl ? CTLTREESIZE : TREESIZE;
++      max_idx = is_ctl ? LPERCTL : LPERDMAP;
+       /* first check the root of the tree to see if there is
+        * sufficient free space.
+@@ -2978,6 +2979,8 @@ static int dbFindLeaf(dmtree_t *tp, int l2nb, int *leafidx, bool is_ctl)
+                */
+               assert(n < 4);
+       }
++      if (le32_to_cpu(tp->dmt_leafidx) >= max_idx)
++              return -ENOSPC;
+       /* set the return to the leftmost leaf describing sufficient
+        * free space.
+-- 
+2.43.0
+
diff --git a/queue-6.11/jfs-fix-uaf-in-dbfreebits.patch b/queue-6.11/jfs-fix-uaf-in-dbfreebits.patch
new file mode 100644 (file)
index 0000000..66fa667
--- /dev/null
@@ -0,0 +1,117 @@
+From 7e460e2fd2715a44612206eb3db66ed918214f84 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 24 Aug 2024 10:50:48 +0800
+Subject: jfs: Fix uaf in dbFreeBits
+
+From: Edward Adam Davis <eadavis@qq.com>
+
+[ Upstream commit d6c1b3599b2feb5c7291f5ac3a36e5fa7cedb234 ]
+
+[syzbot reported]
+==================================================================
+BUG: KASAN: slab-use-after-free in __mutex_lock_common kernel/locking/mutex.c:587 [inline]
+BUG: KASAN: slab-use-after-free in __mutex_lock+0xfe/0xd70 kernel/locking/mutex.c:752
+Read of size 8 at addr ffff8880229254b0 by task syz-executor357/5216
+
+CPU: 0 UID: 0 PID: 5216 Comm: syz-executor357 Not tainted 6.11.0-rc3-syzkaller-00156-gd7a5aa4b3c00 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/27/2024
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:93 [inline]
+ dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119
+ print_address_description mm/kasan/report.c:377 [inline]
+ print_report+0x169/0x550 mm/kasan/report.c:488
+ kasan_report+0x143/0x180 mm/kasan/report.c:601
+ __mutex_lock_common kernel/locking/mutex.c:587 [inline]
+ __mutex_lock+0xfe/0xd70 kernel/locking/mutex.c:752
+ dbFreeBits+0x7ea/0xd90 fs/jfs/jfs_dmap.c:2390
+ dbFreeDmap fs/jfs/jfs_dmap.c:2089 [inline]
+ dbFree+0x35b/0x680 fs/jfs/jfs_dmap.c:409
+ dbDiscardAG+0x8a9/0xa20 fs/jfs/jfs_dmap.c:1650
+ jfs_ioc_trim+0x433/0x670 fs/jfs/jfs_discard.c:100
+ jfs_ioctl+0x2d0/0x3e0 fs/jfs/ioctl.c:131
+ vfs_ioctl fs/ioctl.c:51 [inline]
+ __do_sys_ioctl fs/ioctl.c:907 [inline]
+ __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:893
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+
+Freed by task 5218:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
+ kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:579
+ poison_slab_object+0xe0/0x150 mm/kasan/common.c:240
+ __kasan_slab_free+0x37/0x60 mm/kasan/common.c:256
+ kasan_slab_free include/linux/kasan.h:184 [inline]
+ slab_free_hook mm/slub.c:2252 [inline]
+ slab_free mm/slub.c:4473 [inline]
+ kfree+0x149/0x360 mm/slub.c:4594
+ dbUnmount+0x11d/0x190 fs/jfs/jfs_dmap.c:278
+ jfs_mount_rw+0x4ac/0x6a0 fs/jfs/jfs_mount.c:247
+ jfs_remount+0x3d1/0x6b0 fs/jfs/super.c:454
+ reconfigure_super+0x445/0x880 fs/super.c:1083
+ vfs_cmd_reconfigure fs/fsopen.c:263 [inline]
+ vfs_fsconfig_locked fs/fsopen.c:292 [inline]
+ __do_sys_fsconfig fs/fsopen.c:473 [inline]
+ __se_sys_fsconfig+0xb6e/0xf80 fs/fsopen.c:345
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+[Analysis]
+There are two paths (dbUnmount and jfs_ioc_trim) that generate race
+condition when accessing bmap, which leads to the occurrence of uaf.
+
+Use the lock s_umount to synchronize them, in order to avoid uaf caused
+by race condition.
+
+Reported-and-tested-by: syzbot+3c010e21296f33a5dc16@syzkaller.appspotmail.com
+Signed-off-by: Edward Adam Davis <eadavis@qq.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_discard.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/fs/jfs/jfs_discard.c b/fs/jfs/jfs_discard.c
+index 575cb2ba74fc8..5f4b305030ad5 100644
+--- a/fs/jfs/jfs_discard.c
++++ b/fs/jfs/jfs_discard.c
+@@ -65,7 +65,7 @@ void jfs_issue_discard(struct inode *ip, u64 blkno, u64 nblocks)
+ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
+ {
+       struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
+-      struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
++      struct bmap *bmp;
+       struct super_block *sb = ipbmap->i_sb;
+       int agno, agno_end;
+       u64 start, end, minlen;
+@@ -83,10 +83,15 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
+       if (minlen == 0)
+               minlen = 1;
++      down_read(&sb->s_umount);
++      bmp = JFS_SBI(ip->i_sb)->bmap;
++
+       if (minlen > bmp->db_agsize ||
+           start >= bmp->db_mapsize ||
+-          range->len < sb->s_blocksize)
++          range->len < sb->s_blocksize) {
++              up_read(&sb->s_umount);
+               return -EINVAL;
++      }
+       if (end >= bmp->db_mapsize)
+               end = bmp->db_mapsize - 1;
+@@ -100,6 +105,8 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
+               trimmed += dbDiscardAG(ip, agno, minlen);
+               agno++;
+       }
++
++      up_read(&sb->s_umount);
+       range->len = trimmed << sb->s_blocksize_bits;
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-6.11/jfs-fix-uninit-value-access-of-new_ea-in-ea_buffer.patch b/queue-6.11/jfs-fix-uninit-value-access-of-new_ea-in-ea_buffer.patch
new file mode 100644 (file)
index 0000000..c0a6661
--- /dev/null
@@ -0,0 +1,57 @@
+From 66d6b0c2e4289856ab1e07d205b7af02b6e0ad1f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Sep 2024 09:07:58 +0800
+Subject: jfs: Fix uninit-value access of new_ea in ea_buffer
+
+From: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
+
+[ Upstream commit 2b59ffad47db1c46af25ccad157bb3b25147c35c ]
+
+syzbot reports that lzo1x_1_do_compress is using uninit-value:
+
+=====================================================
+BUG: KMSAN: uninit-value in lzo1x_1_do_compress+0x19f9/0x2510 lib/lzo/lzo1x_compress.c:178
+
+...
+
+Uninit was stored to memory at:
+ ea_put fs/jfs/xattr.c:639 [inline]
+
+...
+
+Local variable ea_buf created at:
+ __jfs_setxattr+0x5d/0x1ae0 fs/jfs/xattr.c:662
+ __jfs_xattr_set+0xe6/0x1f0 fs/jfs/xattr.c:934
+
+=====================================================
+
+The reason is ea_buf->new_ea is not initialized properly.
+
+Fix this by using memset to empty its content at the beginning
+in ea_get().
+
+Reported-by: syzbot+02341e0daa42a15ce130@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=02341e0daa42a15ce130
+Signed-off-by: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/xattr.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
+index 2999ed5d83f5e..0fb05e314edf6 100644
+--- a/fs/jfs/xattr.c
++++ b/fs/jfs/xattr.c
+@@ -434,6 +434,8 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
+       int rc;
+       int quota_allocation = 0;
++      memset(&ea_buf->new_ea, 0, sizeof(ea_buf->new_ea));
++
+       /* When fsck.jfs clears a bad ea, it doesn't clear the size */
+       if (ji->ea.flag == 0)
+               ea_size = 0;
+-- 
+2.43.0
+
diff --git a/queue-6.11/jfs-ubsan-shift-out-of-bounds-in-dbfindbits.patch b/queue-6.11/jfs-ubsan-shift-out-of-bounds-in-dbfindbits.patch
new file mode 100644 (file)
index 0000000..3aca28d
--- /dev/null
@@ -0,0 +1,35 @@
+From f349f8ca3bddaa9b30aaf218ccc9591cef9b021e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Jul 2024 00:12:44 +0000
+Subject: jfs: UBSAN: shift-out-of-bounds in dbFindBits
+
+From: Remington Brasga <rbrasga@uci.edu>
+
+[ Upstream commit b0b2fc815e514221f01384f39fbfbff65d897e1c ]
+
+Fix issue with UBSAN throwing shift-out-of-bounds warning.
+
+Reported-by: syzbot+e38d703eeb410b17b473@syzkaller.appspotmail.com
+Signed-off-by: Remington Brasga <rbrasga@uci.edu>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_dmap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index 0625d1c0d0649..8847e8c5d5b45 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -3022,7 +3022,7 @@ static int dbFindBits(u32 word, int l2nb)
+       /* scan the word for nb free bits at nb alignments.
+        */
+-      for (bitno = 0; mask != 0; bitno += nb, mask >>= nb) {
++      for (bitno = 0; mask != 0; bitno += nb, mask = (mask >> nb)) {
+               if ((mask & word) == mask)
+                       break;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.11/ksmbd-add-refcnt-to-ksmbd_conn-struct.patch b/queue-6.11/ksmbd-add-refcnt-to-ksmbd_conn-struct.patch
new file mode 100644 (file)
index 0000000..e51bbcf
--- /dev/null
@@ -0,0 +1,245 @@
+From 3a353f437dec2af57f603bf7675069aab9070d2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Sep 2024 20:28:08 +0900
+Subject: ksmbd: add refcnt to ksmbd_conn struct
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit ee426bfb9d09b29987369b897fe9b6485ac2be27 ]
+
+When sending an oplock break request, opinfo->conn is used,
+But freed ->conn can be used on multichannel.
+This patch add a reference count to the ksmbd_conn struct
+so that it can be freed when it is no longer used.
+
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/connection.c |  4 ++-
+ fs/smb/server/connection.h |  1 +
+ fs/smb/server/oplock.c     | 55 +++++++++++---------------------------
+ fs/smb/server/vfs_cache.c  |  3 +++
+ 4 files changed, 23 insertions(+), 40 deletions(-)
+
+diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
+index 7889df8112b4e..cac80e7bfefc7 100644
+--- a/fs/smb/server/connection.c
++++ b/fs/smb/server/connection.c
+@@ -39,7 +39,8 @@ void ksmbd_conn_free(struct ksmbd_conn *conn)
+       xa_destroy(&conn->sessions);
+       kvfree(conn->request_buf);
+       kfree(conn->preauth_info);
+-      kfree(conn);
++      if (atomic_dec_and_test(&conn->refcnt))
++              kfree(conn);
+ }
+ /**
+@@ -68,6 +69,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
+               conn->um = NULL;
+       atomic_set(&conn->req_running, 0);
+       atomic_set(&conn->r_count, 0);
++      atomic_set(&conn->refcnt, 1);
+       conn->total_credits = 1;
+       conn->outstanding_credits = 0;
+diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h
+index 5b947175c048e..b379ae4fdcdff 100644
+--- a/fs/smb/server/connection.h
++++ b/fs/smb/server/connection.h
+@@ -106,6 +106,7 @@ struct ksmbd_conn {
+       bool                            signing_negotiated;
+       __le16                          signing_algorithm;
+       bool                            binding;
++      atomic_t                        refcnt;
+ };
+ struct ksmbd_conn_ops {
+diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
+index e546ffa57b55a..8ee86478287f9 100644
+--- a/fs/smb/server/oplock.c
++++ b/fs/smb/server/oplock.c
+@@ -51,6 +51,7 @@ static struct oplock_info *alloc_opinfo(struct ksmbd_work *work,
+       init_waitqueue_head(&opinfo->oplock_brk);
+       atomic_set(&opinfo->refcount, 1);
+       atomic_set(&opinfo->breaking_cnt, 0);
++      atomic_inc(&opinfo->conn->refcnt);
+       return opinfo;
+ }
+@@ -124,6 +125,8 @@ static void free_opinfo(struct oplock_info *opinfo)
+ {
+       if (opinfo->is_lease)
+               free_lease(opinfo);
++      if (opinfo->conn && atomic_dec_and_test(&opinfo->conn->refcnt))
++              kfree(opinfo->conn);
+       kfree(opinfo);
+ }
+@@ -163,9 +166,7 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
+                   !atomic_inc_not_zero(&opinfo->refcount))
+                       opinfo = NULL;
+               else {
+-                      atomic_inc(&opinfo->conn->r_count);
+                       if (ksmbd_conn_releasing(opinfo->conn)) {
+-                              atomic_dec(&opinfo->conn->r_count);
+                               atomic_dec(&opinfo->refcount);
+                               opinfo = NULL;
+                       }
+@@ -177,26 +178,11 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
+       return opinfo;
+ }
+-static void opinfo_conn_put(struct oplock_info *opinfo)
++void opinfo_put(struct oplock_info *opinfo)
+ {
+-      struct ksmbd_conn *conn;
+-
+       if (!opinfo)
+               return;
+-      conn = opinfo->conn;
+-      /*
+-       * Checking waitqueue to dropping pending requests on
+-       * disconnection. waitqueue_active is safe because it
+-       * uses atomic operation for condition.
+-       */
+-      if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
+-              wake_up(&conn->r_count_q);
+-      opinfo_put(opinfo);
+-}
+-
+-void opinfo_put(struct oplock_info *opinfo)
+-{
+       if (!atomic_dec_and_test(&opinfo->refcount))
+               return;
+@@ -1127,14 +1113,11 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
+                       if (!atomic_inc_not_zero(&opinfo->refcount))
+                               continue;
+-                      atomic_inc(&opinfo->conn->r_count);
+-                      if (ksmbd_conn_releasing(opinfo->conn)) {
+-                              atomic_dec(&opinfo->conn->r_count);
++                      if (ksmbd_conn_releasing(opinfo->conn))
+                               continue;
+-                      }
+                       oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
+-                      opinfo_conn_put(opinfo);
++                      opinfo_put(opinfo);
+               }
+       }
+       up_read(&p_ci->m_lock);
+@@ -1167,13 +1150,10 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
+                       if (!atomic_inc_not_zero(&opinfo->refcount))
+                               continue;
+-                      atomic_inc(&opinfo->conn->r_count);
+-                      if (ksmbd_conn_releasing(opinfo->conn)) {
+-                              atomic_dec(&opinfo->conn->r_count);
++                      if (ksmbd_conn_releasing(opinfo->conn))
+                               continue;
+-                      }
+                       oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
+-                      opinfo_conn_put(opinfo);
++                      opinfo_put(opinfo);
+               }
+       }
+       up_read(&p_ci->m_lock);
+@@ -1252,7 +1232,7 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
+       prev_opinfo = opinfo_get_list(ci);
+       if (!prev_opinfo ||
+           (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx)) {
+-              opinfo_conn_put(prev_opinfo);
++              opinfo_put(prev_opinfo);
+               goto set_lev;
+       }
+       prev_op_has_lease = prev_opinfo->is_lease;
+@@ -1262,19 +1242,19 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
+       if (share_ret < 0 &&
+           prev_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
+               err = share_ret;
+-              opinfo_conn_put(prev_opinfo);
++              opinfo_put(prev_opinfo);
+               goto err_out;
+       }
+       if (prev_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
+           prev_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
+-              opinfo_conn_put(prev_opinfo);
++              opinfo_put(prev_opinfo);
+               goto op_break_not_needed;
+       }
+       list_add(&work->interim_entry, &prev_opinfo->interim_list);
+       err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II);
+-      opinfo_conn_put(prev_opinfo);
++      opinfo_put(prev_opinfo);
+       if (err == -ENOENT)
+               goto set_lev;
+       /* Check all oplock was freed by close */
+@@ -1337,14 +1317,14 @@ static void smb_break_all_write_oplock(struct ksmbd_work *work,
+               return;
+       if (brk_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
+           brk_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
+-              opinfo_conn_put(brk_opinfo);
++              opinfo_put(brk_opinfo);
+               return;
+       }
+       brk_opinfo->open_trunc = is_trunc;
+       list_add(&work->interim_entry, &brk_opinfo->interim_list);
+       oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II);
+-      opinfo_conn_put(brk_opinfo);
++      opinfo_put(brk_opinfo);
+ }
+ /**
+@@ -1376,11 +1356,8 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
+               if (!atomic_inc_not_zero(&brk_op->refcount))
+                       continue;
+-              atomic_inc(&brk_op->conn->r_count);
+-              if (ksmbd_conn_releasing(brk_op->conn)) {
+-                      atomic_dec(&brk_op->conn->r_count);
++              if (ksmbd_conn_releasing(brk_op->conn))
+                       continue;
+-              }
+               rcu_read_unlock();
+               if (brk_op->is_lease && (brk_op->o_lease->state &
+@@ -1411,7 +1388,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
+               brk_op->open_trunc = is_trunc;
+               oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE);
+ next:
+-              opinfo_conn_put(brk_op);
++              opinfo_put(brk_op);
+               rcu_read_lock();
+       }
+       rcu_read_unlock();
+diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
+index 4d4ee696e37cd..a19f4e563c7e5 100644
+--- a/fs/smb/server/vfs_cache.c
++++ b/fs/smb/server/vfs_cache.c
+@@ -863,6 +863,8 @@ static bool session_fd_check(struct ksmbd_tree_connect *tcon,
+       list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
+               if (op->conn != conn)
+                       continue;
++              if (op->conn && atomic_dec_and_test(&op->conn->refcnt))
++                      kfree(op->conn);
+               op->conn = NULL;
+       }
+       up_write(&ci->m_lock);
+@@ -965,6 +967,7 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
+               if (op->conn)
+                       continue;
+               op->conn = fp->conn;
++              atomic_inc(&op->conn->refcnt);
+       }
+       up_write(&ci->m_lock);
+-- 
+2.43.0
+
diff --git a/queue-6.11/l2tp-free-sessions-using-rcu.patch b/queue-6.11/l2tp-free-sessions-using-rcu.patch
new file mode 100644 (file)
index 0000000..96c856e
--- /dev/null
@@ -0,0 +1,59 @@
+From 4b55d4e197d215162aa1d29367b8c6766e5e271b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 16:38:08 +0100
+Subject: l2tp: free sessions using rcu
+
+From: James Chapman <jchapman@katalix.com>
+
+[ Upstream commit d17e89999574aca143dd4ede43e4382d32d98724 ]
+
+l2tp sessions may be accessed under an rcu read lock. Have them freed
+via rcu and remove the now unneeded synchronize_rcu when a session is
+removed.
+
+Signed-off-by: James Chapman <jchapman@katalix.com>
+Signed-off-by: Tom Parkin <tparkin@katalix.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/l2tp/l2tp_core.c | 4 +---
+ net/l2tp/l2tp_core.h | 1 +
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
+index a9cbcbc9d016d..edff7afc06199 100644
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -152,7 +152,7 @@ static void l2tp_session_free(struct l2tp_session *session)
+       trace_free_session(session);
+       if (session->tunnel)
+               l2tp_tunnel_dec_refcount(session->tunnel);
+-      kfree(session);
++      kfree_rcu(session, rcu);
+ }
+ struct l2tp_tunnel *l2tp_sk_to_tunnel(struct sock *sk)
+@@ -1298,8 +1298,6 @@ static void l2tp_session_unhash(struct l2tp_session *session)
+               spin_unlock_bh(&pn->l2tp_session_idr_lock);
+               spin_unlock_bh(&tunnel->list_lock);
+-
+-              synchronize_rcu();
+       }
+ }
+diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
+index 6c25c196cc222..d0e3460089d90 100644
+--- a/net/l2tp/l2tp_core.h
++++ b/net/l2tp/l2tp_core.h
+@@ -67,6 +67,7 @@ struct l2tp_session_coll_list {
+ struct l2tp_session {
+       int                     magic;          /* should be L2TP_SESSION_MAGIC */
+       long                    dead;
++      struct rcu_head         rcu;
+       struct l2tp_tunnel      *tunnel;        /* back pointer to tunnel context */
+       u32                     session_id;
+-- 
+2.43.0
+
diff --git a/queue-6.11/l2tp-prevent-possible-tunnel-refcount-underflow.patch b/queue-6.11/l2tp-prevent-possible-tunnel-refcount-underflow.patch
new file mode 100644 (file)
index 0000000..23045b2
--- /dev/null
@@ -0,0 +1,169 @@
+From 58885d40361a64baab788a5de6b306cd0dedaee4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 16:38:10 +0100
+Subject: l2tp: prevent possible tunnel refcount underflow
+
+From: James Chapman <jchapman@katalix.com>
+
+[ Upstream commit 24256415d18695b46da06c93135f5b51c548b950 ]
+
+When a session is created, it sets a backpointer to its tunnel. When
+the session refcount drops to 0, l2tp_session_free drops the tunnel
+refcount if session->tunnel is non-NULL. However, session->tunnel is
+set in l2tp_session_create, before the tunnel refcount is incremented
+by l2tp_session_register, which leaves a small window where
+session->tunnel is non-NULL when the tunnel refcount hasn't been
+bumped.
+
+Moving the assignment to l2tp_session_register is trivial but
+l2tp_session_create calls l2tp_session_set_header_len which uses
+session->tunnel to get the tunnel's encap. Add an encap arg to
+l2tp_session_set_header_len to avoid using session->tunnel.
+
+If l2tpv3 sessions have colliding IDs, it is possible for
+l2tp_v3_session_get to race with l2tp_session_register and fetch a
+session which doesn't yet have session->tunnel set. Add a check for
+this case.
+
+Signed-off-by: James Chapman <jchapman@katalix.com>
+Signed-off-by: Tom Parkin <tparkin@katalix.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/l2tp/l2tp_core.c    | 24 +++++++++++++++++-------
+ net/l2tp/l2tp_core.h    |  3 ++-
+ net/l2tp/l2tp_netlink.c |  4 +++-
+ net/l2tp/l2tp_ppp.c     |  3 ++-
+ 4 files changed, 24 insertions(+), 10 deletions(-)
+
+diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
+index 2e86f520f7994..a9cbcbc9d016d 100644
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -254,7 +254,14 @@ struct l2tp_session *l2tp_v3_session_get(const struct net *net, struct sock *sk,
+               hash_for_each_possible_rcu(pn->l2tp_v3_session_htable, session,
+                                          hlist, key) {
+-                      if (session->tunnel->sock == sk &&
++                      /* session->tunnel may be NULL if another thread is in
++                       * l2tp_session_register and has added an item to
++                       * l2tp_v3_session_htable but hasn't yet added the
++                       * session to its tunnel's session_list.
++                       */
++                      struct l2tp_tunnel *tunnel = READ_ONCE(session->tunnel);
++
++                      if (tunnel && tunnel->sock == sk &&
+                           refcount_inc_not_zero(&session->ref_count)) {
+                               rcu_read_unlock_bh();
+                               return session;
+@@ -482,6 +489,7 @@ int l2tp_session_register(struct l2tp_session *session,
+       }
+       l2tp_tunnel_inc_refcount(tunnel);
++      WRITE_ONCE(session->tunnel, tunnel);
+       list_add(&session->list, &tunnel->session_list);
+       if (tunnel->version == L2TP_HDR_VER_3) {
+@@ -797,7 +805,8 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
+               if (!session->lns_mode && !session->send_seq) {
+                       trace_session_seqnum_lns_enable(session);
+                       session->send_seq = 1;
+-                      l2tp_session_set_header_len(session, tunnel->version);
++                      l2tp_session_set_header_len(session, tunnel->version,
++                                                  tunnel->encap);
+               }
+       } else {
+               /* No sequence numbers.
+@@ -818,7 +827,8 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
+               if (!session->lns_mode && session->send_seq) {
+                       trace_session_seqnum_lns_disable(session);
+                       session->send_seq = 0;
+-                      l2tp_session_set_header_len(session, tunnel->version);
++                      l2tp_session_set_header_len(session, tunnel->version,
++                                                  tunnel->encap);
+               } else if (session->send_seq) {
+                       pr_debug_ratelimited("%s: recv data has no seq numbers when required. Discarding.\n",
+                                            session->name);
+@@ -1663,7 +1673,8 @@ EXPORT_SYMBOL_GPL(l2tp_session_delete);
+ /* We come here whenever a session's send_seq, cookie_len or
+  * l2specific_type parameters are set.
+  */
+-void l2tp_session_set_header_len(struct l2tp_session *session, int version)
++void l2tp_session_set_header_len(struct l2tp_session *session, int version,
++                               enum l2tp_encap_type encap)
+ {
+       if (version == L2TP_HDR_VER_2) {
+               session->hdr_len = 6;
+@@ -1672,7 +1683,7 @@ void l2tp_session_set_header_len(struct l2tp_session *session, int version)
+       } else {
+               session->hdr_len = 4 + session->cookie_len;
+               session->hdr_len += l2tp_get_l2specific_len(session);
+-              if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP)
++              if (encap == L2TP_ENCAPTYPE_UDP)
+                       session->hdr_len += 4;
+       }
+ }
+@@ -1686,7 +1697,6 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn
+       session = kzalloc(sizeof(*session) + priv_size, GFP_KERNEL);
+       if (session) {
+               session->magic = L2TP_SESSION_MAGIC;
+-              session->tunnel = tunnel;
+               session->session_id = session_id;
+               session->peer_session_id = peer_session_id;
+@@ -1724,7 +1734,7 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn
+                       memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len);
+               }
+-              l2tp_session_set_header_len(session, tunnel->version);
++              l2tp_session_set_header_len(session, tunnel->version, tunnel->encap);
+               refcount_set(&session->ref_count, 1);
+diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
+index 8ac81bc1bc6fa..6c25c196cc222 100644
+--- a/net/l2tp/l2tp_core.h
++++ b/net/l2tp/l2tp_core.h
+@@ -260,7 +260,8 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
+ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb);
+ /* Transmit path helpers for sending packets over the tunnel socket. */
+-void l2tp_session_set_header_len(struct l2tp_session *session, int version);
++void l2tp_session_set_header_len(struct l2tp_session *session, int version,
++                               enum l2tp_encap_type encap);
+ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb);
+ /* Pseudowire management.
+diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
+index d105030520f95..fc43ecbd128cc 100644
+--- a/net/l2tp/l2tp_netlink.c
++++ b/net/l2tp/l2tp_netlink.c
+@@ -692,8 +692,10 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf
+               session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]);
+       if (info->attrs[L2TP_ATTR_SEND_SEQ]) {
++              struct l2tp_tunnel *tunnel = session->tunnel;
++
+               session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]);
+-              l2tp_session_set_header_len(session, session->tunnel->version);
++              l2tp_session_set_header_len(session, tunnel->version, tunnel->encap);
+       }
+       if (info->attrs[L2TP_ATTR_LNS_MODE])
+diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
+index 3596290047b28..4f25c1212cacb 100644
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -1205,7 +1205,8 @@ static int pppol2tp_session_setsockopt(struct sock *sk,
+                       po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ :
+                               PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+               }
+-              l2tp_session_set_header_len(session, session->tunnel->version);
++              l2tp_session_set_header_len(session, session->tunnel->version,
++                                          session->tunnel->encap);
+               break;
+       case PPPOL2TP_SO_LNSMODE:
+-- 
+2.43.0
+
diff --git a/queue-6.11/l2tp-use-rcu-list-add-del-when-updating-lists.patch b/queue-6.11/l2tp-use-rcu-list-add-del-when-updating-lists.patch
new file mode 100644 (file)
index 0000000..ba81902
--- /dev/null
@@ -0,0 +1,63 @@
+From abb8ba5dad5de8aa0cb1292b0fda8885ed3c33a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 16:38:11 +0100
+Subject: l2tp: use rcu list add/del when updating lists
+
+From: James Chapman <jchapman@katalix.com>
+
+[ Upstream commit 89b768ec2dfefaeba5212de14fc71368e12d06ba ]
+
+l2tp_v3_session_htable and tunnel->session_list are read by lockless
+getters using RCU. Use rcu list variants when adding or removing list
+items.
+
+Signed-off-by: James Chapman <jchapman@katalix.com>
+Signed-off-by: Tom Parkin <tparkin@katalix.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/l2tp/l2tp_core.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
+index edff7afc06199..ee8133f77b64c 100644
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -394,12 +394,12 @@ static int l2tp_session_collision_add(struct l2tp_net *pn,
+       /* If existing session isn't already in the session hlist, add it. */
+       if (!hash_hashed(&session2->hlist))
+-              hash_add(pn->l2tp_v3_session_htable, &session2->hlist,
+-                       session2->hlist_key);
++              hash_add_rcu(pn->l2tp_v3_session_htable, &session2->hlist,
++                           session2->hlist_key);
+       /* Add new session to the hlist and collision list */
+-      hash_add(pn->l2tp_v3_session_htable, &session1->hlist,
+-               session1->hlist_key);
++      hash_add_rcu(pn->l2tp_v3_session_htable, &session1->hlist,
++                   session1->hlist_key);
+       refcount_inc(&clist->ref_count);
+       l2tp_session_coll_list_add(clist, session1);
+@@ -415,7 +415,7 @@ static void l2tp_session_collision_del(struct l2tp_net *pn,
+       lockdep_assert_held(&pn->l2tp_session_idr_lock);
+-      hash_del(&session->hlist);
++      hash_del_rcu(&session->hlist);
+       if (clist) {
+               /* Remove session from its collision list. If there
+@@ -490,7 +490,7 @@ int l2tp_session_register(struct l2tp_session *session,
+       l2tp_tunnel_inc_refcount(tunnel);
+       WRITE_ONCE(session->tunnel, tunnel);
+-      list_add(&session->list, &tunnel->session_list);
++      list_add_rcu(&session->list, &tunnel->session_list);
+       if (tunnel->version == L2TP_HDR_VER_3) {
+               if (!other_session)
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-atlantic-avoid-warning-about-potential-string-tr.patch b/queue-6.11/net-atlantic-avoid-warning-about-potential-string-tr.patch
new file mode 100644 (file)
index 0000000..23cb214
--- /dev/null
@@ -0,0 +1,79 @@
+From 180d0e607493987812879a9d80112072473fb8fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 16:58:57 +0100
+Subject: net: atlantic: Avoid warning about potential string truncation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Simon Horman <horms@kernel.org>
+
+[ Upstream commit 5874e0c9f25661c2faefe4809907166defae3d7f ]
+
+W=1 builds with GCC 14.2.0 warn that:
+
+.../aq_ethtool.c:278:59: warning: ‘%d’ directive output may be truncated writing between 1 and 11 bytes into a region of size 6 [-Wformat-truncation=]
+  278 |                                 snprintf(tc_string, 8, "TC%d ", tc);
+      |                                                           ^~
+.../aq_ethtool.c:278:56: note: directive argument in the range [-2147483641, 254]
+  278 |                                 snprintf(tc_string, 8, "TC%d ", tc);
+      |                                                        ^~~~~~~
+.../aq_ethtool.c:278:33: note: ‘snprintf’ output between 5 and 15 bytes into a destination of size 8
+  278 |                                 snprintf(tc_string, 8, "TC%d ", tc);
+      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+tc is always in the range 0 - cfg->tcs. And as cfg->tcs is a u8,
+the range is 0 - 255. Further, on inspecting the code, it seems
+that cfg->tcs will never be more than AQ_CFG_TCS_MAX (8), so
+the range is actually 0 - 8.
+
+So, it seems that the condition that GCC flags will not occur.
+But, nonetheless, it would be nice if it didn't emit the warning.
+
+It seems that this can be achieved by changing the format specifier
+from %d to %u, in which case I believe GCC recognises an upper bound
+on the range of tc of 0 - 255. After some experimentation I think
+this is due to the combination of the use of %u and the type of
+cfg->tcs (u8).
+
+Empirically, updating the type of the tc variable to unsigned int
+has the same effect.
+
+As both of these changes seem to make sense in relation to what the code
+is actually doing - iterating over unsigned values - do both.
+
+Compile tested only.
+
+Signed-off-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20240821-atlantic-str-v1-1-fa2cfe38ca00@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+index d0aecd1d73573..876b95306404e 100644
+--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+@@ -266,7 +266,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
+               const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
+               const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
+               char tc_string[8];
+-              int tc;
++              unsigned int tc;
+               memset(tc_string, 0, sizeof(tc_string));
+               memcpy(p, aq_ethtool_stat_names,
+@@ -275,7 +275,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
+               for (tc = 0; tc < cfg->tcs; tc++) {
+                       if (cfg->is_qos)
+-                              snprintf(tc_string, 8, "TC%d ", tc);
++                              snprintf(tc_string, 8, "TC%u ", tc);
+                       for (i = 0; i < cfg->vecs; i++) {
+                               for (si = 0; si < rx_stat_cnt; si++) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-hisilicon-hip04-fix-of-node-leak-in-probe.patch b/queue-6.11/net-hisilicon-hip04-fix-of-node-leak-in-probe.patch
new file mode 100644 (file)
index 0000000..a0761a9
--- /dev/null
@@ -0,0 +1,36 @@
+From ef3ecbc97bf647833dd8a7ee680e033cfa3ad1fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 16:44:19 +0200
+Subject: net: hisilicon: hip04: fix OF node leak in probe()
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 17555297dbd5bccc93a01516117547e26a61caf1 ]
+
+Driver is leaking OF node reference from
+of_parse_phandle_with_fixed_args() in probe().
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20240827144421.52852-2-krzysztof.kozlowski@linaro.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hip04_eth.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
+index b91e7a06b97f7..beb815e5289b1 100644
+--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
++++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
+@@ -947,6 +947,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
+       priv->tx_coalesce_timer.function = tx_done;
+       priv->map = syscon_node_to_regmap(arg.np);
++      of_node_put(arg.np);
+       if (IS_ERR(priv->map)) {
+               dev_warn(d, "no syscon hisilicon,hip04-ppe\n");
+               ret = PTR_ERR(priv->map);
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-hisilicon-hns_dsaf_mac-fix-of-node-leak-in-hns_m.patch b/queue-6.11/net-hisilicon-hns_dsaf_mac-fix-of-node-leak-in-hns_m.patch
new file mode 100644 (file)
index 0000000..3251f3d
--- /dev/null
@@ -0,0 +1,36 @@
+From bbc74b59ad26eb28d5399d0b5bf57eac92e3b656 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 16:44:20 +0200
+Subject: net: hisilicon: hns_dsaf_mac: fix OF node leak in hns_mac_get_info()
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 5680cf8d34e1552df987e2f4bb1bff0b2a8c8b11 ]
+
+Driver is leaking OF node reference from
+of_parse_phandle_with_fixed_args() in hns_mac_get_info().
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20240827144421.52852-3-krzysztof.kozlowski@linaro.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+index f75668c479351..616a2768e5048 100644
+--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
++++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+@@ -933,6 +933,7 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb)
+                       mac_cb->cpld_ctrl = NULL;
+               } else {
+                       syscon = syscon_node_to_regmap(cpld_args.np);
++                      of_node_put(cpld_args.np);
+                       if (IS_ERR_OR_NULL(syscon)) {
+                               dev_dbg(mac_cb->dev, "no cpld-syscon found!\n");
+                               mac_cb->cpld_ctrl = NULL;
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-hisilicon-hns_mdio-fix-of-node-leak-in-probe.patch b/queue-6.11/net-hisilicon-hns_mdio-fix-of-node-leak-in-probe.patch
new file mode 100644 (file)
index 0000000..1a669d1
--- /dev/null
@@ -0,0 +1,36 @@
+From b1d62a8c5942585cc9bdf591fcee602fda52a5b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 16:44:21 +0200
+Subject: net: hisilicon: hns_mdio: fix OF node leak in probe()
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit e62beddc45f487b9969821fad3a0913d9bc18a2f ]
+
+Driver is leaking OF node reference from
+of_parse_phandle_with_fixed_args() in probe().
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20240827144421.52852-4-krzysztof.kozlowski@linaro.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns_mdio.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c
+index ed73707176c1a..8a047145f0c50 100644
+--- a/drivers/net/ethernet/hisilicon/hns_mdio.c
++++ b/drivers/net/ethernet/hisilicon/hns_mdio.c
+@@ -575,6 +575,7 @@ static int hns_mdio_probe(struct platform_device *pdev)
+                                               MDIO_SC_RESET_ST;
+                               }
+                       }
++                      of_node_put(reg_args.np);
+               } else {
+                       dev_warn(&pdev->dev, "find syscon ret = %#x\n", ret);
+                       mdio_dev->subctrl_vbase = NULL;
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-mvpp2-increase-size-of-queue_name-buffer.patch b/queue-6.11/net-mvpp2-increase-size-of-queue_name-buffer.patch
new file mode 100644 (file)
index 0000000..4f816a5
--- /dev/null
@@ -0,0 +1,58 @@
+From f2c890557f9330192a017899ad8c751890d5123d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 12:28:24 +0100
+Subject: net: mvpp2: Increase size of queue_name buffer
+
+From: Simon Horman <horms@kernel.org>
+
+[ Upstream commit 91d516d4de48532d967a77967834e00c8c53dfe6 ]
+
+Increase size of queue_name buffer from 30 to 31 to accommodate
+the largest string written to it. This avoids truncation in
+the possibly unlikely case where the string is name is the
+maximum size.
+
+Flagged by gcc-14:
+
+  .../mvpp2_main.c: In function 'mvpp2_probe':
+  .../mvpp2_main.c:7636:32: warning: 'snprintf' output may be truncated before the last format character [-Wformat-truncation=]
+   7636 |                  "stats-wq-%s%s", netdev_name(priv->port_list[0]->dev),
+        |                                ^
+  .../mvpp2_main.c:7635:9: note: 'snprintf' output between 10 and 31 bytes into a destination of size 30
+   7635 |         snprintf(priv->queue_name, sizeof(priv->queue_name),
+        |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   7636 |                  "stats-wq-%s%s", netdev_name(priv->port_list[0]->dev),
+        |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   7637 |                  priv->port_count > 1 ? "+" : "");
+        |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Introduced by commit 118d6298f6f0 ("net: mvpp2: add ethtool GOP statistics").
+I am not flagging this as a bug as I am not aware that it is one.
+
+Compile tested only.
+
+Signed-off-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Marcin Wojtas <marcin.s.wojtas@gmail.com>
+Link: https://patch.msgid.link/20240806-mvpp2-namelen-v1-1-6dc773653f2f@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
+index e809f91c08fb9..9e02e4367bec8 100644
+--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
+@@ -1088,7 +1088,7 @@ struct mvpp2 {
+       unsigned int max_port_rxqs;
+       /* Workqueue to gather hardware statistics */
+-      char queue_name[30];
++      char queue_name[31];
+       struct workqueue_struct *stats_queue;
+       /* Debugfs root entry */
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-napi-prevent-overflow-of-napi_defer_hard_irqs.patch b/queue-6.11/net-napi-prevent-overflow-of-napi_defer_hard_irqs.patch
new file mode 100644 (file)
index 0000000..5052630
--- /dev/null
@@ -0,0 +1,125 @@
+From 810afaa3b594de0cc541a3627f76fa8eab6a6347 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Sep 2024 15:34:30 +0000
+Subject: net: napi: Prevent overflow of napi_defer_hard_irqs
+
+From: Joe Damato <jdamato@fastly.com>
+
+[ Upstream commit 08062af0a52107a243f7608fd972edb54ca5b7f8 ]
+
+In commit 6f8b12d661d0 ("net: napi: add hard irqs deferral feature")
+napi_defer_irqs was added to net_device and napi_defer_irqs_count was
+added to napi_struct, both as type int.
+
+This value never goes below zero, so there is not reason for it to be a
+signed int. Change the type for both from int to u32, and add an
+overflow check to sysfs to limit the value to S32_MAX.
+
+The limit of S32_MAX was chosen because the practical limit before this
+patch was S32_MAX (anything larger was an overflow) and thus there are
+no behavioral changes introduced. If the extra bit is needed in the
+future, the limit can be raised.
+
+Before this patch:
+
+$ sudo bash -c 'echo 2147483649 > /sys/class/net/eth4/napi_defer_hard_irqs'
+$ cat /sys/class/net/eth4/napi_defer_hard_irqs
+-2147483647
+
+After this patch:
+
+$ sudo bash -c 'echo 2147483649 > /sys/class/net/eth4/napi_defer_hard_irqs'
+bash: line 0: echo: write error: Numerical result out of range
+
+Similarly, /sys/class/net/XXXXX/tx_queue_len is defined as unsigned:
+
+include/linux/netdevice.h:      unsigned int            tx_queue_len;
+
+And has an overflow check:
+
+dev_change_tx_queue_len(..., unsigned long new_len):
+
+  if (new_len != (unsigned int)new_len)
+          return -ERANGE;
+
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Joe Damato <jdamato@fastly.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20240904153431.307932-1-jdamato@fastly.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/networking/net_cachelines/net_device.rst | 2 +-
+ include/linux/netdevice.h                              | 4 ++--
+ net/core/net-sysfs.c                                   | 6 +++++-
+ 3 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/networking/net_cachelines/net_device.rst b/Documentation/networking/net_cachelines/net_device.rst
+index 70c4fb9d4e5ce..d68f37f5b1f82 100644
+--- a/Documentation/networking/net_cachelines/net_device.rst
++++ b/Documentation/networking/net_cachelines/net_device.rst
+@@ -98,7 +98,7 @@ unsigned_int                        num_rx_queues
+ unsigned_int                        real_num_rx_queues      -                   read_mostly         get_rps_cpu
+ struct_bpf_prog*                    xdp_prog                -                   read_mostly         netif_elide_gro()
+ unsigned_long                       gro_flush_timeout       -                   read_mostly         napi_complete_done
+-int                                 napi_defer_hard_irqs    -                   read_mostly         napi_complete_done
++u32                                 napi_defer_hard_irqs    -                   read_mostly         napi_complete_done
+ unsigned_int                        gro_max_size            -                   read_mostly         skb_gro_receive
+ unsigned_int                        gro_ipv4_max_size       -                   read_mostly         skb_gro_receive
+ rx_handler_func_t*                  rx_handler              read_mostly         -                   __netif_receive_skb_core
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 59fb3cb8538fd..b26954dc9ed77 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -356,7 +356,7 @@ struct napi_struct {
+       unsigned long           state;
+       int                     weight;
+-      int                     defer_hard_irqs_count;
++      u32                     defer_hard_irqs_count;
+       unsigned long           gro_bitmask;
+       int                     (*poll)(struct napi_struct *, int);
+ #ifdef CONFIG_NETPOLL
+@@ -2091,7 +2091,7 @@ struct net_device {
+       unsigned int            real_num_rx_queues;
+       struct netdev_rx_queue  *_rx;
+       unsigned long           gro_flush_timeout;
+-      int                     napi_defer_hard_irqs;
++      u32                     napi_defer_hard_irqs;
+       unsigned int            gro_max_size;
+       unsigned int            gro_ipv4_max_size;
+       rx_handler_func_t __rcu *rx_handler;
+diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
+index 291fdf4a328b3..93dd5d5436849 100644
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -32,6 +32,7 @@
+ #ifdef CONFIG_SYSFS
+ static const char fmt_hex[] = "%#x\n";
+ static const char fmt_dec[] = "%d\n";
++static const char fmt_uint[] = "%u\n";
+ static const char fmt_ulong[] = "%lu\n";
+ static const char fmt_u64[] = "%llu\n";
+@@ -425,6 +426,9 @@ NETDEVICE_SHOW_RW(gro_flush_timeout, fmt_ulong);
+ static int change_napi_defer_hard_irqs(struct net_device *dev, unsigned long val)
+ {
++      if (val > S32_MAX)
++              return -ERANGE;
++
+       WRITE_ONCE(dev->napi_defer_hard_irqs, val);
+       return 0;
+ }
+@@ -438,7 +442,7 @@ static ssize_t napi_defer_hard_irqs_store(struct device *dev,
+       return netdev_store(dev, attr, buf, len, change_napi_defer_hard_irqs);
+ }
+-NETDEVICE_SHOW_RW(napi_defer_hard_irqs, fmt_dec);
++NETDEVICE_SHOW_RW(napi_defer_hard_irqs, fmt_uint);
+ static ssize_t ifalias_store(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t len)
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-phy-check-for-read-errors-in-siocgmiireg.patch b/queue-6.11/net-phy-check-for-read-errors-in-siocgmiireg.patch
new file mode 100644 (file)
index 0000000..3aae182
--- /dev/null
@@ -0,0 +1,82 @@
+From a3bde6a16b8c2aa5aa321f9fd68284be3c69f717 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Sep 2024 19:15:36 +0200
+Subject: net: phy: Check for read errors in SIOCGMIIREG
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+[ Upstream commit 569bf6d481b0b823c3c9c3b8be77908fd7caf66b ]
+
+When reading registers from the PHY using the SIOCGMIIREG IOCTL any
+errors returned from either mdiobus_read() or mdiobus_c45_read() are
+ignored, and parts of the returned error is passed as the register value
+back to user-space.
+
+For example, if mdiobus_c45_read() is used with a bus that do not
+implement the read_c45() callback -EOPNOTSUPP is returned. This is
+however directly stored in mii_data->val_out and returned as the
+registers content. As val_out is a u16 the error code is truncated and
+returned as a plausible register value.
+
+Fix this by first checking the return value for errors before returning
+it as the register content.
+
+Before this patch,
+
+    # phytool read eth0/0:1/0
+    0xffa1
+
+After this change,
+
+    $ phytool read eth0/0:1/0
+    error: phy_read (-95)
+
+Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://patch.msgid.link/20240903171536.628930-1-niklas.soderlund+renesas@ragnatech.se
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/phy.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index 785182fa5fe01..b88d857ea23b8 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -342,14 +342,19 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
+               if (mdio_phy_id_is_c45(mii_data->phy_id)) {
+                       prtad = mdio_phy_id_prtad(mii_data->phy_id);
+                       devad = mdio_phy_id_devad(mii_data->phy_id);
+-                      mii_data->val_out = mdiobus_c45_read(
+-                              phydev->mdio.bus, prtad, devad,
+-                              mii_data->reg_num);
++                      ret = mdiobus_c45_read(phydev->mdio.bus, prtad, devad,
++                                             mii_data->reg_num);
++
+               } else {
+-                      mii_data->val_out = mdiobus_read(
+-                              phydev->mdio.bus, mii_data->phy_id,
+-                              mii_data->reg_num);
++                      ret = mdiobus_read(phydev->mdio.bus, mii_data->phy_id,
++                                         mii_data->reg_num);
+               }
++
++              if (ret < 0)
++                      return ret;
++
++              mii_data->val_out = ret;
++
+               return 0;
+       case SIOCSMIIREG:
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-sched-consistently-use-rcu_replace_pointer-in-ta.patch b/queue-6.11/net-sched-consistently-use-rcu_replace_pointer-in-ta.patch
new file mode 100644 (file)
index 0000000..8b9188b
--- /dev/null
@@ -0,0 +1,42 @@
+From bad064772c96d27592aabf9e0430ef13ce221fbf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Sep 2024 14:54:01 +0300
+Subject: net: sched: consistently use rcu_replace_pointer() in taprio_change()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit d5c4546062fd6f5dbce575c7ea52ad66d1968678 ]
+
+According to Vinicius (and carefully looking through the whole
+https://syzkaller.appspot.com/bug?extid=b65e0af58423fc8a73aa
+once again), txtime branch of 'taprio_change()' is not going to
+race against 'advance_sched()'. But using 'rcu_replace_pointer()'
+in the former may be a good idea as well.
+
+Suggested-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_taprio.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
+index cc2df9f8c14a6..8498d0606b248 100644
+--- a/net/sched/sch_taprio.c
++++ b/net/sched/sch_taprio.c
+@@ -1952,7 +1952,9 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
+                       goto unlock;
+               }
+-              rcu_assign_pointer(q->admin_sched, new_admin);
++              /* Not going to race against advance_sched(), but still */
++              admin = rcu_replace_pointer(q->admin_sched, new_admin,
++                                          lockdep_rtnl_is_held());
+               if (admin)
+                       call_rcu(&admin->rcu, taprio_free_sched_cb);
+       } else {
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-skbuff-sprinkle-more-__gfp_nowarn-on-ingress-all.patch b/queue-6.11/net-skbuff-sprinkle-more-__gfp_nowarn-on-ingress-all.patch
new file mode 100644 (file)
index 0000000..d69c2d4
--- /dev/null
@@ -0,0 +1,79 @@
+From 5430c043caa5aefe1d5b096cdbde9114b86e8457 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 17:19:56 -0700
+Subject: net: skbuff: sprinkle more __GFP_NOWARN on ingress allocs
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit c89cca307b20917da739567a255a68a0798ee129 ]
+
+build_skb() and frag allocations done with GFP_ATOMIC will
+fail in real life, when system is under memory pressure,
+and there's nothing we can do about that. So no point
+printing warnings.
+
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skbuff.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 83f8cd8aa2d16..de2a044cc6656 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -314,8 +314,8 @@ void *__napi_alloc_frag_align(unsigned int fragsz, unsigned int align_mask)
+       fragsz = SKB_DATA_ALIGN(fragsz);
+       local_lock_nested_bh(&napi_alloc_cache.bh_lock);
+-      data = __page_frag_alloc_align(&nc->page, fragsz, GFP_ATOMIC,
+-                                     align_mask);
++      data = __page_frag_alloc_align(&nc->page, fragsz,
++                                     GFP_ATOMIC | __GFP_NOWARN, align_mask);
+       local_unlock_nested_bh(&napi_alloc_cache.bh_lock);
+       return data;
+@@ -330,7 +330,8 @@ void *__netdev_alloc_frag_align(unsigned int fragsz, unsigned int align_mask)
+               struct page_frag_cache *nc = this_cpu_ptr(&netdev_alloc_cache);
+               fragsz = SKB_DATA_ALIGN(fragsz);
+-              data = __page_frag_alloc_align(nc, fragsz, GFP_ATOMIC,
++              data = __page_frag_alloc_align(nc, fragsz,
++                                             GFP_ATOMIC | __GFP_NOWARN,
+                                              align_mask);
+       } else {
+               local_bh_disable();
+@@ -349,7 +350,7 @@ static struct sk_buff *napi_skb_cache_get(void)
+       local_lock_nested_bh(&napi_alloc_cache.bh_lock);
+       if (unlikely(!nc->skb_count)) {
+               nc->skb_count = kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
+-                                                    GFP_ATOMIC,
++                                                    GFP_ATOMIC | __GFP_NOWARN,
+                                                     NAPI_SKB_CACHE_BULK,
+                                                     nc->skb_cache);
+               if (unlikely(!nc->skb_count)) {
+@@ -418,7 +419,8 @@ struct sk_buff *slab_build_skb(void *data)
+       struct sk_buff *skb;
+       unsigned int size;
+-      skb = kmem_cache_alloc(net_hotdata.skbuff_cache, GFP_ATOMIC);
++      skb = kmem_cache_alloc(net_hotdata.skbuff_cache,
++                             GFP_ATOMIC | __GFP_NOWARN);
+       if (unlikely(!skb))
+               return NULL;
+@@ -469,7 +471,8 @@ struct sk_buff *__build_skb(void *data, unsigned int frag_size)
+ {
+       struct sk_buff *skb;
+-      skb = kmem_cache_alloc(net_hotdata.skbuff_cache, GFP_ATOMIC);
++      skb = kmem_cache_alloc(net_hotdata.skbuff_cache,
++                             GFP_ATOMIC | __GFP_NOWARN);
+       if (unlikely(!skb))
+               return NULL;
+-- 
+2.43.0
+
diff --git a/queue-6.11/net-xen-netback-prevent-uaf-in-xenvif_flush_hash.patch b/queue-6.11/net-xen-netback-prevent-uaf-in-xenvif_flush_hash.patch
new file mode 100644 (file)
index 0000000..694f5c8
--- /dev/null
@@ -0,0 +1,50 @@
+From 6014345f715abe5a3bb571ccd51fc759a0290e3c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Aug 2024 03:11:09 +0900
+Subject: net/xen-netback: prevent UAF in xenvif_flush_hash()
+
+From: Jeongjun Park <aha310510@gmail.com>
+
+[ Upstream commit 0fa5e94a1811d68fbffa0725efe6d4ca62c03d12 ]
+
+During the list_for_each_entry_rcu iteration call of xenvif_flush_hash,
+kfree_rcu does not exist inside the rcu read critical section, so if
+kfree_rcu is called when the rcu grace period ends during the iteration,
+UAF occurs when accessing head->next after the entry becomes free.
+
+Therefore, to solve this, you need to change it to list_for_each_entry_safe.
+
+Signed-off-by: Jeongjun Park <aha310510@gmail.com>
+Link: https://patch.msgid.link/20240822181109.2577354-1-aha310510@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/xen-netback/hash.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c
+index ff96f22648efd..45ddce35f6d2c 100644
+--- a/drivers/net/xen-netback/hash.c
++++ b/drivers/net/xen-netback/hash.c
+@@ -95,7 +95,7 @@ static u32 xenvif_new_hash(struct xenvif *vif, const u8 *data,
+ static void xenvif_flush_hash(struct xenvif *vif)
+ {
+-      struct xenvif_hash_cache_entry *entry;
++      struct xenvif_hash_cache_entry *entry, *n;
+       unsigned long flags;
+       if (xenvif_hash_cache_size == 0)
+@@ -103,8 +103,7 @@ static void xenvif_flush_hash(struct xenvif *vif)
+       spin_lock_irqsave(&vif->hash.cache.lock, flags);
+-      list_for_each_entry_rcu(entry, &vif->hash.cache.list, link,
+-                              lockdep_is_held(&vif->hash.cache.lock)) {
++      list_for_each_entry_safe(entry, n, &vif->hash.cache.list, link) {
+               list_del_rcu(&entry->link);
+               vif->hash.cache.count--;
+               kfree_rcu(entry, rcu);
+-- 
+2.43.0
+
diff --git a/queue-6.11/netdev-genl-set-extack-and-fix-error-on-napi-get.patch b/queue-6.11/netdev-genl-set-extack-and-fix-error-on-napi-get.patch
new file mode 100644 (file)
index 0000000..ef06941
--- /dev/null
@@ -0,0 +1,64 @@
+From 6b209605973b9e096c016fc88660569e8fe211c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 31 Aug 2024 12:17:04 +0000
+Subject: netdev-genl: Set extack and fix error on napi-get
+
+From: Joe Damato <jdamato@fastly.com>
+
+[ Upstream commit 4e3a024b437ec0aee82550cc66a0f4e1a7a88a67 ]
+
+In commit 27f91aaf49b3 ("netdev-genl: Add netlink framework functions
+for napi"), when an invalid NAPI ID is specified the return value
+-EINVAL is used and no extack is set.
+
+Change the return value to -ENOENT and set the extack.
+
+Before this commit:
+
+$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \
+                          --do napi-get --json='{"id": 451}'
+Netlink error: Invalid argument
+nl_len = 36 (20) nl_flags = 0x100 nl_type = 2
+       error: -22
+
+After this commit:
+
+$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \
+                         --do napi-get --json='{"id": 451}'
+Netlink error: No such file or directory
+nl_len = 44 (28) nl_flags = 0x300 nl_type = 2
+       error: -2
+       extack: {'bad-attr': '.id'}
+
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Joe Damato <jdamato@fastly.com>
+Link: https://patch.msgid.link/20240831121707.17562-1-jdamato@fastly.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/netdev-genl.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
+index 05f9515d2c05c..a17d7eaeb0019 100644
+--- a/net/core/netdev-genl.c
++++ b/net/core/netdev-genl.c
+@@ -216,10 +216,12 @@ int netdev_nl_napi_get_doit(struct sk_buff *skb, struct genl_info *info)
+       rtnl_lock();
+       napi = napi_by_id(napi_id);
+-      if (napi)
++      if (napi) {
+               err = netdev_nl_napi_fill_one(rsp, napi, info);
+-      else
+-              err = -EINVAL;
++      } else {
++              NL_SET_BAD_ATTR(info->extack, info->attrs[NETDEV_A_NAPI_ID]);
++              err = -ENOENT;
++      }
+       rtnl_unlock();
+-- 
+2.43.0
+
diff --git a/queue-6.11/netfilter-nf_tables-do-not-remove-elements-if-set-ba.patch b/queue-6.11/netfilter-nf_tables-do-not-remove-elements-if-set-ba.patch
new file mode 100644 (file)
index 0000000..a1a607c
--- /dev/null
@@ -0,0 +1,60 @@
+From f3a9e949d2a1927ad6008a1273418f01f431b73a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jul 2024 13:32:31 +0200
+Subject: netfilter: nf_tables: do not remove elements if set backend
+ implements .abort
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit c9526aeb4998393171d85225ff540e28c7d4ab86 ]
+
+pipapo set backend maintains two copies of the datastructure, removing
+the elements from the copy that is going to be discarded slows down
+the abort path significantly, from several minutes to few seconds after
+this patch.
+
+This patch was previously reverted by
+
+  f86fb94011ae ("netfilter: nf_tables: revert do not remove elements if set backend implements .abort")
+
+but it is now possible since recent work by Florian Westphal to perform
+on-demand clone from insert/remove path:
+
+  532aec7e878b ("netfilter: nft_set_pipapo: remove dirty flag")
+  3f1d886cc7c3 ("netfilter: nft_set_pipapo: move cloning of match info to insert/removal path")
+  a238106703ab ("netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone")
+  c5444786d0ea ("netfilter: nft_set_pipapo: merge deactivate helper into caller")
+  6c108d9bee44 ("netfilter: nft_set_pipapo: prepare walk function for on-demand clone")
+  8b8a2417558c ("netfilter: nft_set_pipapo: prepare destroy function for on-demand clone")
+  80efd2997fb9 ("netfilter: nft_set_pipapo: make pipapo_clone helper return NULL")
+  a590f4760922 ("netfilter: nft_set_pipapo: move prove_locking helper around")
+
+after this series, the clone is fully released once aborted, no need to
+take it back to previous state. Thus, no stale reference to elements can
+occur.
+
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 472f211472db4..e792f153f9587 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -10795,7 +10795,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
+                               break;
+                       }
+                       te = nft_trans_container_elem(trans);
+-                      nft_setelem_remove(net, te->set, te->elem_priv);
++                      if (!te->set->ops->abort ||
++                          nft_setelem_is_catchall(te->set, te->elem_priv))
++                              nft_setelem_remove(net, te->set, te->elem_priv);
++
+                       if (!nft_setelem_is_catchall(te->set, te->elem_priv))
+                               atomic_dec(&te->set->nelems);
+-- 
+2.43.0
+
diff --git a/queue-6.11/netfs-cancel-dirty-folios-that-have-no-storage-desti.patch b/queue-6.11/netfs-cancel-dirty-folios-that-have-no-storage-desti.patch
new file mode 100644 (file)
index 0000000..7207ffd
--- /dev/null
@@ -0,0 +1,80 @@
+From a93470e020e28cd01c2b74775cccf2886a1b1d67 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 12:23:11 +0100
+Subject: netfs: Cancel dirty folios that have no storage destination
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit 8f246b7c0a1be0882374f2ff831a61f0dbe77678 ]
+
+Kafs wants to be able to cache the contents of directories (and symlinks),
+but whilst these are downloaded from the server with the FS.FetchData RPC
+op and similar, the same as for regular files, they can't be updated by
+FS.StoreData, but rather have special operations (FS.MakeDir, etc.).
+
+Now, rather than redownloading a directory's content after each change made
+to that directory, kafs modifies the local blob.  This blob can be saved
+out to the cache, and since it's using netfslib, kafs just marks the folios
+dirty and lets ->writepages() on the directory take care of it, as for an
+regular file.
+
+This is fine as long as there's a cache as although the upload stream is
+disabled, there's a cache stream to drive the procedure.  But if the cache
+goes away in the meantime, suddenly there's no way do any writes and the
+code gets confused, complains "R=%x: No submit" to dmesg and leaves the
+dirty folio hanging.
+
+Fix this by just cancelling the store of the folio if neither stream is
+active.  (If there's no cache at the time of dirtying, we should just not
+mark the folio dirty).
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+cc: Jeff Layton <jlayton@kernel.org>
+cc: netfs@lists.linux.dev
+cc: linux-fsdevel@vger.kernel.org
+Link: https://lore.kernel.org/r/20240814203850.2240469-23-dhowells@redhat.com/ # v2
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/netfs/write_issue.c       | 6 +++++-
+ include/trace/events/netfs.h | 1 +
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c
+index 9486e54b1e563..b08673d97470c 100644
+--- a/fs/netfs/write_issue.c
++++ b/fs/netfs/write_issue.c
+@@ -410,13 +410,17 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
+       folio_unlock(folio);
+       if (fgroup == NETFS_FOLIO_COPY_TO_CACHE) {
+-              if (!fscache_resources_valid(&wreq->cache_resources)) {
++              if (!cache->avail) {
+                       trace_netfs_folio(folio, netfs_folio_trace_cancel_copy);
+                       netfs_issue_write(wreq, upload);
+                       netfs_folio_written_back(folio);
+                       return 0;
+               }
+               trace_netfs_folio(folio, netfs_folio_trace_store_copy);
++      } else if (!upload->avail && !cache->avail) {
++              trace_netfs_folio(folio, netfs_folio_trace_cancel_store);
++              netfs_folio_written_back(folio);
++              return 0;
+       } else if (!upload->construct) {
+               trace_netfs_folio(folio, netfs_folio_trace_store);
+       } else {
+diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h
+index 606b4a0f92dae..edcc3b3a3ecf8 100644
+--- a/include/trace/events/netfs.h
++++ b/include/trace/events/netfs.h
+@@ -141,6 +141,7 @@
+       EM(netfs_streaming_cont_filled_page,    "mod-streamw-f+") \
+       /* The rest are for writeback */                        \
+       EM(netfs_folio_trace_cancel_copy,       "cancel-copy")  \
++      EM(netfs_folio_trace_cancel_store,      "cancel-store") \
+       EM(netfs_folio_trace_clear,             "clear")        \
+       EM(netfs_folio_trace_clear_cc,          "clear-cc")     \
+       EM(netfs_folio_trace_clear_g,           "clear-g")      \
+-- 
+2.43.0
+
diff --git a/queue-6.11/netpoll-ensure-clean-state-on-setup-failures.patch b/queue-6.11/netpoll-ensure-clean-state-on-setup-failures.patch
new file mode 100644 (file)
index 0000000..2da8754
--- /dev/null
@@ -0,0 +1,106 @@
+From b3b9e1793c6011eb7270da5ce9ffe51cadba44f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Aug 2024 04:10:47 -0700
+Subject: netpoll: Ensure clean state on setup failures
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit ae5a0456e0b4cfd7e61619e55251ffdf1bc7adfb ]
+
+Modify netpoll_setup() and __netpoll_setup() to ensure that the netpoll
+structure (np) is left in a clean state if setup fails for any reason.
+This prevents carrying over misconfigured fields in case of partial
+setup success.
+
+Key changes:
+- np->dev is now set only after successful setup, ensuring it's always
+  NULL if netpoll is not configured or if netpoll_setup() fails.
+- np->local_ip is zeroed if netpoll setup doesn't complete successfully.
+- Added DEBUG_NET_WARN_ON_ONCE() checks to catch unexpected states.
+- Reordered some operations in __netpoll_setup() for better logical flow.
+
+These changes improve the reliability of netpoll configuration, since it
+assures that the structure is fully initialized or totally unset.
+
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20240822111051.179850-2-leitao@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/netpoll.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/net/core/netpoll.c b/net/core/netpoll.c
+index d657b042d5a04..930acc87c8c08 100644
+--- a/net/core/netpoll.c
++++ b/net/core/netpoll.c
+@@ -624,12 +624,9 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
+       const struct net_device_ops *ops;
+       int err;
+-      np->dev = ndev;
+-      strscpy(np->dev_name, ndev->name, IFNAMSIZ);
+-
+       if (ndev->priv_flags & IFF_DISABLE_NETPOLL) {
+               np_err(np, "%s doesn't support polling, aborting\n",
+-                     np->dev_name);
++                     ndev->name);
+               err = -ENOTSUPP;
+               goto out;
+       }
+@@ -647,7 +644,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
+               refcount_set(&npinfo->refcnt, 1);
+-              ops = np->dev->netdev_ops;
++              ops = ndev->netdev_ops;
+               if (ops->ndo_netpoll_setup) {
+                       err = ops->ndo_netpoll_setup(ndev, npinfo);
+                       if (err)
+@@ -658,6 +655,8 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
+               refcount_inc(&npinfo->refcnt);
+       }
++      np->dev = ndev;
++      strscpy(np->dev_name, ndev->name, IFNAMSIZ);
+       npinfo->netpoll = np;
+       /* last thing to do is link it to the net device structure */
+@@ -675,6 +674,7 @@ EXPORT_SYMBOL_GPL(__netpoll_setup);
+ int netpoll_setup(struct netpoll *np)
+ {
+       struct net_device *ndev = NULL;
++      bool ip_overwritten = false;
+       struct in_device *in_dev;
+       int err;
+@@ -739,6 +739,7 @@ int netpoll_setup(struct netpoll *np)
+                       }
+                       np->local_ip.ip = ifa->ifa_local;
++                      ip_overwritten = true;
+                       np_info(np, "local IP %pI4\n", &np->local_ip.ip);
+               } else {
+ #if IS_ENABLED(CONFIG_IPV6)
+@@ -755,6 +756,7 @@ int netpoll_setup(struct netpoll *np)
+                                           !!(ipv6_addr_type(&np->remote_ip.in6) & IPV6_ADDR_LINKLOCAL))
+                                               continue;
+                                       np->local_ip.in6 = ifp->addr;
++                                      ip_overwritten = true;
+                                       err = 0;
+                                       break;
+                               }
+@@ -785,6 +787,9 @@ int netpoll_setup(struct netpoll *np)
+       return 0;
+ put:
++      DEBUG_NET_WARN_ON_ONCE(np->dev);
++      if (ip_overwritten)
++              memset(&np->local_ip, 0, sizeof(np->local_ip));
+       netdev_put(ndev, &np->dev_tracker);
+ unlock:
+       rtnl_unlock();
+-- 
+2.43.0
+
diff --git a/queue-6.11/nfp-use-irqf_no_autoen-flag-in-request_irq.patch b/queue-6.11/nfp-use-irqf_no_autoen-flag-in-request_irq.patch
new file mode 100644 (file)
index 0000000..553076c
--- /dev/null
@@ -0,0 +1,46 @@
+From cc6700f0fd1263b4b19aa54306c317386f08e263 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 17:44:45 +0800
+Subject: nfp: Use IRQF_NO_AUTOEN flag in request_irq()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit daaba19d357f0900b303a530ced96c78086267ea ]
+
+disable_irq() after request_irq() still has a time gap in which
+interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will
+disable IRQ auto-enable when request IRQ.
+
+Reviewed-by: Louis Peens <louis.peens@corigine.com>
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Link: https://patch.msgid.link/20240911094445.1922476-4-ruanjinjie@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+index 182ba0a8b095b..6e0929af0f725 100644
+--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+@@ -821,14 +821,13 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
+       snprintf(r_vec->name, sizeof(r_vec->name),
+                "%s-rxtx-%d", nfp_net_name(nn), idx);
+-      err = request_irq(r_vec->irq_vector, r_vec->handler, 0, r_vec->name,
+-                        r_vec);
++      err = request_irq(r_vec->irq_vector, r_vec->handler, IRQF_NO_AUTOEN,
++                        r_vec->name, r_vec);
+       if (err) {
+               nfp_net_napi_del(&nn->dp, r_vec);
+               nn_err(nn, "Error requesting IRQ %d\n", r_vec->irq_vector);
+               return err;
+       }
+-      disable_irq(r_vec->irq_vector);
+       irq_set_affinity_hint(r_vec->irq_vector, &r_vec->affinity_mask);
+-- 
+2.43.0
+
diff --git a/queue-6.11/nvme-fix-metadata-handling-in-nvme-passthrough.patch b/queue-6.11/nvme-fix-metadata-handling-in-nvme-passthrough.patch
new file mode 100644 (file)
index 0000000..171f951
--- /dev/null
@@ -0,0 +1,87 @@
+From 9ccc6bd5d21fa69f87e2051fa6820f954800fcb2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Aug 2024 13:32:17 +0000
+Subject: nvme: fix metadata handling in nvme-passthrough
+
+From: Puranjay Mohan <pjy@amazon.com>
+
+[ Upstream commit 7c2fd76048e95dd267055b5f5e0a48e6e7c81fd9 ]
+
+On an NVMe namespace that does not support metadata, it is possible to
+send an IO command with metadata through io-passthru. This allows issues
+like [1] to trigger in the completion code path.
+nvme_map_user_request() doesn't check if the namespace supports metadata
+before sending it forward. It also allows admin commands with metadata to
+be processed as it ignores metadata when bdev == NULL and may report
+success.
+
+Reject an IO command with metadata when the NVMe namespace doesn't
+support it and reject an admin command if it has metadata.
+
+[1] https://lore.kernel.org/all/mb61pcylvnym8.fsf@amazon.com/
+
+Suggested-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Puranjay Mohan <pjy@amazon.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Anuj Gupta <anuj20.g@samsung.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/ioctl.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
+index f1d58e70933f5..15c93ce07e263 100644
+--- a/drivers/nvme/host/ioctl.c
++++ b/drivers/nvme/host/ioctl.c
+@@ -4,6 +4,7 @@
+  * Copyright (c) 2017-2021 Christoph Hellwig.
+  */
+ #include <linux/bio-integrity.h>
++#include <linux/blk-integrity.h>
+ #include <linux/ptrace.h>     /* for force_successful_syscall_return */
+ #include <linux/nvme_ioctl.h>
+ #include <linux/io_uring/cmd.h>
+@@ -119,9 +120,14 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
+       struct request_queue *q = req->q;
+       struct nvme_ns *ns = q->queuedata;
+       struct block_device *bdev = ns ? ns->disk->part0 : NULL;
++      bool supports_metadata = bdev && blk_get_integrity(bdev->bd_disk);
++      bool has_metadata = meta_buffer && meta_len;
+       struct bio *bio = NULL;
+       int ret;
++      if (has_metadata && !supports_metadata)
++              return -EINVAL;
++
+       if (ioucmd && (ioucmd->flags & IORING_URING_CMD_FIXED)) {
+               struct iov_iter iter;
+@@ -143,15 +149,15 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
+               goto out;
+       bio = req->bio;
+-      if (bdev) {
++      if (bdev)
+               bio_set_dev(bio, bdev);
+-              if (meta_buffer && meta_len) {
+-                      ret = bio_integrity_map_user(bio, meta_buffer, meta_len,
+-                                                   meta_seed);
+-                      if (ret)
+-                              goto out_unmap;
+-                      req->cmd_flags |= REQ_INTEGRITY;
+-              }
++
++      if (has_metadata) {
++              ret = bio_integrity_map_user(bio, meta_buffer, meta_len,
++                                           meta_seed);
++              if (ret)
++                      goto out_unmap;
++              req->cmd_flags |= REQ_INTEGRITY;
+       }
+       return ret;
+-- 
+2.43.0
+
diff --git a/queue-6.11/nvme-keyring-restrict-match-length-for-version-1-ide.patch b/queue-6.11/nvme-keyring-restrict-match-length-for-version-1-ide.patch
new file mode 100644 (file)
index 0000000..e859c58
--- /dev/null
@@ -0,0 +1,133 @@
+From 1dcc2accd20b5dfc544ea489fe71585bc7b13451 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jul 2024 14:02:18 +0200
+Subject: nvme-keyring: restrict match length for version '1' identifiers
+
+From: Hannes Reinecke <hare@kernel.org>
+
+[ Upstream commit 79559c75332458985ab8a21f11b08bf7c9b833b0 ]
+
+TP8018 introduced a new TLS PSK identifier version (version 1), which appended
+a PSK hash value to the existing identifier (cf NVMe TCP specification v1.1,
+section 3.6.1.3 'TLS PSK and PSK Identity Derivation').
+An original (version 0) identifier has the form:
+
+NVMe0<type><hmac> <hostnqn> <subsysnqn>
+
+and a version 1 identifier has the form:
+
+NVMe1<type><hmac> <hostnqn> <subsysnqn> <hash>
+
+This patch modifies the lookup algorthm to compare only the first part
+of the identifier (excluding the hash value) to handle both version 0 and
+version 1 identifiers.
+And the spec declares 'version 0' identifiers obsolete, so the lookup
+algorithm is modified to prever v1 identifiers.
+
+Signed-off-by: Hannes Reinecke <hare@kernel.org>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/common/keyring.c | 36 +++++++++++++++++++++++++----------
+ 1 file changed, 26 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/nvme/common/keyring.c b/drivers/nvme/common/keyring.c
+index 6f7e7a8fa5ae4..05e89307c8aa3 100644
+--- a/drivers/nvme/common/keyring.c
++++ b/drivers/nvme/common/keyring.c
+@@ -36,14 +36,12 @@ static bool nvme_tls_psk_match(const struct key *key,
+               pr_debug("%s: no key description\n", __func__);
+               return false;
+       }
+-      match_len = strlen(key->description);
+-      pr_debug("%s: id %s len %zd\n", __func__, key->description, match_len);
+-
+       if (!match_data->raw_data) {
+               pr_debug("%s: no match data\n", __func__);
+               return false;
+       }
+       match_id = match_data->raw_data;
++      match_len = strlen(match_id);
+       pr_debug("%s: match '%s' '%s' len %zd\n",
+                __func__, match_id, key->description, match_len);
+       return !memcmp(key->description, match_id, match_len);
+@@ -71,7 +69,7 @@ static struct key_type nvme_tls_psk_key_type = {
+ static struct key *nvme_tls_psk_lookup(struct key *keyring,
+               const char *hostnqn, const char *subnqn,
+-              int hmac, bool generated)
++              u8 hmac, u8 psk_ver, bool generated)
+ {
+       char *identity;
+       size_t identity_len = (NVMF_NQN_SIZE) * 2 + 11;
+@@ -82,8 +80,8 @@ static struct key *nvme_tls_psk_lookup(struct key *keyring,
+       if (!identity)
+               return ERR_PTR(-ENOMEM);
+-      snprintf(identity, identity_len, "NVMe0%c%02d %s %s",
+-               generated ? 'G' : 'R', hmac, hostnqn, subnqn);
++      snprintf(identity, identity_len, "NVMe%u%c%02u %s %s",
++               psk_ver, generated ? 'G' : 'R', hmac, hostnqn, subnqn);
+       if (!keyring)
+               keyring = nvme_keyring;
+@@ -107,21 +105,38 @@ static struct key *nvme_tls_psk_lookup(struct key *keyring,
+ /*
+  * NVMe PSK priority list
+  *
+- * 'Retained' PSKs (ie 'generated == false')
+- * should be preferred to 'generated' PSKs,
+- * and SHA-384 should be preferred to SHA-256.
++ * 'Retained' PSKs (ie 'generated == false') should be preferred to 'generated'
++ * PSKs, PSKs with hash (psk_ver 1) should be preferred to PSKs without hash
++ * (psk_ver 0), and SHA-384 should be preferred to SHA-256.
+  */
+ static struct nvme_tls_psk_priority_list {
+       bool generated;
++      u8 psk_ver;
+       enum nvme_tcp_tls_cipher cipher;
+ } nvme_tls_psk_prio[] = {
+       { .generated = false,
++        .psk_ver = 1,
++        .cipher = NVME_TCP_TLS_CIPHER_SHA384, },
++      { .generated = false,
++        .psk_ver = 1,
++        .cipher = NVME_TCP_TLS_CIPHER_SHA256, },
++      { .generated = false,
++        .psk_ver = 0,
+         .cipher = NVME_TCP_TLS_CIPHER_SHA384, },
+       { .generated = false,
++        .psk_ver = 0,
++        .cipher = NVME_TCP_TLS_CIPHER_SHA256, },
++      { .generated = true,
++        .psk_ver = 1,
++        .cipher = NVME_TCP_TLS_CIPHER_SHA384, },
++      { .generated = true,
++        .psk_ver = 1,
+         .cipher = NVME_TCP_TLS_CIPHER_SHA256, },
+       { .generated = true,
++        .psk_ver = 0,
+         .cipher = NVME_TCP_TLS_CIPHER_SHA384, },
+       { .generated = true,
++        .psk_ver = 0,
+         .cipher = NVME_TCP_TLS_CIPHER_SHA256, },
+ };
+@@ -137,10 +152,11 @@ key_serial_t nvme_tls_psk_default(struct key *keyring,
+       for (prio = 0; prio < ARRAY_SIZE(nvme_tls_psk_prio); prio++) {
+               bool generated = nvme_tls_psk_prio[prio].generated;
++              u8 ver = nvme_tls_psk_prio[prio].psk_ver;
+               enum nvme_tcp_tls_cipher cipher = nvme_tls_psk_prio[prio].cipher;
+               tls_key = nvme_tls_psk_lookup(keyring, hostnqn, subnqn,
+-                                            cipher, generated);
++                                            cipher, ver, generated);
+               if (!IS_ERR(tls_key)) {
+                       tls_key_id = tls_key->serial;
+                       key_put(tls_key);
+-- 
+2.43.0
+
diff --git a/queue-6.11/nvme-tcp-check-for-invalidated-or-revoked-key.patch b/queue-6.11/nvme-tcp-check-for-invalidated-or-revoked-key.patch
new file mode 100644 (file)
index 0000000..ec91f65
--- /dev/null
@@ -0,0 +1,122 @@
+From 08f3a2dbfbad1046623a86c74edfc169d19f4a55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jul 2024 14:02:20 +0200
+Subject: nvme-tcp: check for invalidated or revoked key
+
+From: Hannes Reinecke <hare@kernel.org>
+
+[ Upstream commit 5bc46b49c828a6dfaab80b71ecb63fe76a1096d2 ]
+
+key_lookup() will always return a key, even if that key is revoked
+or invalidated. So check for invalid keys before continuing.
+
+Signed-off-by: Hannes Reinecke <hare@kernel.org>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/common/keyring.c | 22 ++++++++++++++++++++++
+ drivers/nvme/host/Kconfig     |  1 +
+ drivers/nvme/host/fabrics.c   |  2 +-
+ drivers/nvme/host/tcp.c       |  2 +-
+ include/linux/nvme-keyring.h  |  6 +++++-
+ 5 files changed, 30 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/nvme/common/keyring.c b/drivers/nvme/common/keyring.c
+index 05e89307c8aa3..ed5167f942d89 100644
+--- a/drivers/nvme/common/keyring.c
++++ b/drivers/nvme/common/keyring.c
+@@ -20,6 +20,28 @@ key_serial_t nvme_keyring_id(void)
+ }
+ EXPORT_SYMBOL_GPL(nvme_keyring_id);
++static bool nvme_tls_psk_revoked(struct key *psk)
++{
++      return test_bit(KEY_FLAG_REVOKED, &psk->flags) ||
++              test_bit(KEY_FLAG_INVALIDATED, &psk->flags);
++}
++
++struct key *nvme_tls_key_lookup(key_serial_t key_id)
++{
++      struct key *key = key_lookup(key_id);
++
++      if (IS_ERR(key)) {
++              pr_err("key id %08x not found\n", key_id);
++              return key;
++      }
++      if (nvme_tls_psk_revoked(key)) {
++              pr_err("key id %08x revoked\n", key_id);
++              return ERR_PTR(-EKEYREVOKED);
++      }
++      return key;
++}
++EXPORT_SYMBOL_GPL(nvme_tls_key_lookup);
++
+ static void nvme_tls_psk_describe(const struct key *key, struct seq_file *m)
+ {
+       seq_puts(m, key->description);
+diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig
+index a3caef75aa0a8..883aaab2d83e3 100644
+--- a/drivers/nvme/host/Kconfig
++++ b/drivers/nvme/host/Kconfig
+@@ -109,6 +109,7 @@ config NVME_HOST_AUTH
+       bool "NVMe over Fabrics In-Band Authentication in host side"
+       depends on NVME_CORE
+       select NVME_AUTH
++      select NVME_KEYRING if NVME_TCP_TLS
+       help
+         This provides support for NVMe over Fabrics In-Band Authentication in
+         host side.
+diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
+index f5f545fa01035..432efcbf9e2f5 100644
+--- a/drivers/nvme/host/fabrics.c
++++ b/drivers/nvme/host/fabrics.c
+@@ -665,7 +665,7 @@ static struct key *nvmf_parse_key(int key_id)
+               return ERR_PTR(-EINVAL);
+       }
+-      key = key_lookup(key_id);
++      key = nvme_tls_key_lookup(key_id);
+       if (IS_ERR(key))
+               pr_err("key id %08x not found\n", key_id);
+       else
+diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
+index b305873e588e6..e3d82e91151af 100644
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -1596,7 +1596,7 @@ static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid)
+               goto out_complete;
+       }
+-      tls_key = key_lookup(pskid);
++      tls_key = nvme_tls_key_lookup(pskid);
+       if (IS_ERR(tls_key)) {
+               dev_warn(ctrl->ctrl.device, "queue %d: Invalid key %x\n",
+                        qid, pskid);
+diff --git a/include/linux/nvme-keyring.h b/include/linux/nvme-keyring.h
+index e10333d78dbbe..19d2b256180fd 100644
+--- a/include/linux/nvme-keyring.h
++++ b/include/linux/nvme-keyring.h
+@@ -12,7 +12,7 @@ key_serial_t nvme_tls_psk_default(struct key *keyring,
+               const char *hostnqn, const char *subnqn);
+ key_serial_t nvme_keyring_id(void);
+-
++struct key *nvme_tls_key_lookup(key_serial_t key_id);
+ #else
+ static inline key_serial_t nvme_tls_psk_default(struct key *keyring,
+@@ -24,5 +24,9 @@ static inline key_serial_t nvme_keyring_id(void)
+ {
+       return 0;
+ }
++static inline struct key *nvme_tls_key_lookup(key_serial_t key_id)
++{
++      return ERR_PTR(-ENOTSUPP);
++}
+ #endif /* !CONFIG_NVME_KEYRING */
+ #endif /* _NVME_KEYRING_H */
+-- 
+2.43.0
+
diff --git a/queue-6.11/nvme-tcp-sanitize-tls-key-handling.patch b/queue-6.11/nvme-tcp-sanitize-tls-key-handling.patch
new file mode 100644 (file)
index 0000000..e8a7cea
--- /dev/null
@@ -0,0 +1,220 @@
+From e1fd03b740fabfc6ca599385ce0ad1faaca0fe92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jul 2024 14:02:19 +0200
+Subject: nvme-tcp: sanitize TLS key handling
+
+From: Hannes Reinecke <hare@kernel.org>
+
+[ Upstream commit 363895767fbfa05891b0b4d9e06ebde7a10c6a07 ]
+
+There is a difference between TLS configured (ie the user has
+provisioned/requested a key) and TLS enabled (ie the connection
+is encrypted with TLS). This becomes important for secure concatenation,
+where the initial authentication is run on an unencrypted connection
+(ie with TLS configured, but not enabled), and then the queue is reset to
+run over TLS (ie TLS configured _and_ enabled).
+So to differentiate between those two states store the generated
+key in opts->tls_key (as we're using the same TLS key for all queues),
+the key serial of the resulting TLS handshake in ctrl->tls_pskid
+(to signal that TLS on the admin queue is enabled), and a simple
+flag for the queues to indicated that TLS has been enabled.
+
+Signed-off-by: Hannes Reinecke <hare@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/core.c  |  1 -
+ drivers/nvme/host/nvme.h  |  2 +-
+ drivers/nvme/host/sysfs.c |  4 +--
+ drivers/nvme/host/tcp.c   | 53 +++++++++++++++++++++++++++++----------
+ 4 files changed, 43 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 983909a600adb..a6fb1359a7e14 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -4678,7 +4678,6 @@ static void nvme_free_ctrl(struct device *dev)
+       if (!subsys || ctrl->instance != subsys->instance)
+               ida_free(&nvme_instance_ida, ctrl->instance);
+-      key_put(ctrl->tls_key);
+       nvme_free_cels(ctrl);
+       nvme_mpath_uninit(ctrl);
+       cleanup_srcu_struct(&ctrl->srcu);
+diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
+index e01b1332d245a..313a4f978a2cf 100644
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -377,7 +377,7 @@ struct nvme_ctrl {
+       struct nvme_dhchap_key *ctrl_key;
+       u16 transaction;
+ #endif
+-      struct key *tls_key;
++      key_serial_t tls_pskid;
+       /* Power saving configuration */
+       u64 ps_max_latency_us;
+diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
+index ba05faaac562d..72675b59a7a73 100644
+--- a/drivers/nvme/host/sysfs.c
++++ b/drivers/nvme/host/sysfs.c
+@@ -670,9 +670,9 @@ static ssize_t tls_key_show(struct device *dev,
+ {
+       struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+-      if (!ctrl->tls_key)
++      if (!ctrl->tls_pskid)
+               return 0;
+-      return sysfs_emit(buf, "%08x", key_serial(ctrl->tls_key));
++      return sysfs_emit(buf, "%08x", ctrl->tls_pskid);
+ }
+ static DEVICE_ATTR_RO(tls_key);
+ #endif
+diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
+index a2a47d3ab99f0..b305873e588e6 100644
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -165,6 +165,7 @@ struct nvme_tcp_queue {
+       bool                    hdr_digest;
+       bool                    data_digest;
++      bool                    tls_enabled;
+       struct ahash_request    *rcv_hash;
+       struct ahash_request    *snd_hash;
+       __le32                  exp_ddgst;
+@@ -213,7 +214,21 @@ static inline int nvme_tcp_queue_id(struct nvme_tcp_queue *queue)
+       return queue - queue->ctrl->queues;
+ }
+-static inline bool nvme_tcp_tls(struct nvme_ctrl *ctrl)
++/*
++ * Check if the queue is TLS encrypted
++ */
++static inline bool nvme_tcp_queue_tls(struct nvme_tcp_queue *queue)
++{
++      if (!IS_ENABLED(CONFIG_NVME_TCP_TLS))
++              return 0;
++
++      return queue->tls_enabled;
++}
++
++/*
++ * Check if TLS is configured for the controller.
++ */
++static inline bool nvme_tcp_tls_configured(struct nvme_ctrl *ctrl)
+ {
+       if (!IS_ENABLED(CONFIG_NVME_TCP_TLS))
+               return 0;
+@@ -368,7 +383,7 @@ static inline bool nvme_tcp_queue_has_pending(struct nvme_tcp_queue *queue)
+ static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue)
+ {
+-      return !nvme_tcp_tls(&queue->ctrl->ctrl) &&
++      return !nvme_tcp_queue_tls(queue) &&
+               nvme_tcp_queue_has_pending(queue);
+ }
+@@ -1427,7 +1442,7 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
+       memset(&msg, 0, sizeof(msg));
+       iov.iov_base = icresp;
+       iov.iov_len = sizeof(*icresp);
+-      if (nvme_tcp_tls(&queue->ctrl->ctrl)) {
++      if (nvme_tcp_queue_tls(queue)) {
+               msg.msg_control = cbuf;
+               msg.msg_controllen = sizeof(cbuf);
+       }
+@@ -1439,7 +1454,7 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
+               goto free_icresp;
+       }
+       ret = -ENOTCONN;
+-      if (nvme_tcp_tls(&queue->ctrl->ctrl)) {
++      if (nvme_tcp_queue_tls(queue)) {
+               ctype = tls_get_record_type(queue->sock->sk,
+                                           (struct cmsghdr *)cbuf);
+               if (ctype != TLS_RECORD_TYPE_DATA) {
+@@ -1587,7 +1602,10 @@ static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid)
+                        qid, pskid);
+               queue->tls_err = -ENOKEY;
+       } else {
+-              ctrl->ctrl.tls_key = tls_key;
++              queue->tls_enabled = true;
++              if (qid == 0)
++                      ctrl->ctrl.tls_pskid = key_serial(tls_key);
++              key_put(tls_key);
+               queue->tls_err = 0;
+       }
+@@ -1768,7 +1786,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
+       }
+       /* If PSKs are configured try to start TLS */
+-      if (IS_ENABLED(CONFIG_NVME_TCP_TLS) && pskid) {
++      if (nvme_tcp_tls_configured(nctrl) && pskid) {
+               ret = nvme_tcp_start_tls(nctrl, queue, pskid);
+               if (ret)
+                       goto err_init_connect;
+@@ -1829,6 +1847,8 @@ static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid)
+       mutex_lock(&queue->queue_lock);
+       if (test_and_clear_bit(NVME_TCP_Q_LIVE, &queue->flags))
+               __nvme_tcp_stop_queue(queue);
++      /* Stopping the queue will disable TLS */
++      queue->tls_enabled = false;
+       mutex_unlock(&queue->queue_lock);
+ }
+@@ -1925,16 +1945,17 @@ static int nvme_tcp_alloc_admin_queue(struct nvme_ctrl *ctrl)
+       int ret;
+       key_serial_t pskid = 0;
+-      if (nvme_tcp_tls(ctrl)) {
++      if (nvme_tcp_tls_configured(ctrl)) {
+               if (ctrl->opts->tls_key)
+                       pskid = key_serial(ctrl->opts->tls_key);
+-              else
++              else {
+                       pskid = nvme_tls_psk_default(ctrl->opts->keyring,
+                                                     ctrl->opts->host->nqn,
+                                                     ctrl->opts->subsysnqn);
+-              if (!pskid) {
+-                      dev_err(ctrl->device, "no valid PSK found\n");
+-                      return -ENOKEY;
++                      if (!pskid) {
++                              dev_err(ctrl->device, "no valid PSK found\n");
++                              return -ENOKEY;
++                      }
+               }
+       }
+@@ -1957,13 +1978,14 @@ static int __nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl)
+ {
+       int i, ret;
+-      if (nvme_tcp_tls(ctrl) && !ctrl->tls_key) {
++      if (nvme_tcp_tls_configured(ctrl) && !ctrl->tls_pskid) {
+               dev_err(ctrl->device, "no PSK negotiated\n");
+               return -ENOKEY;
+       }
++
+       for (i = 1; i < ctrl->queue_count; i++) {
+               ret = nvme_tcp_alloc_queue(ctrl, i,
+-                              key_serial(ctrl->tls_key));
++                              ctrl->tls_pskid);
+               if (ret)
+                       goto out_free_queues;
+       }
+@@ -2144,6 +2166,11 @@ static void nvme_tcp_teardown_admin_queue(struct nvme_ctrl *ctrl,
+       if (remove)
+               nvme_unquiesce_admin_queue(ctrl);
+       nvme_tcp_destroy_admin_queue(ctrl, remove);
++      if (ctrl->tls_pskid) {
++              dev_dbg(ctrl->device, "Wipe negotiated TLS_PSK %08x\n",
++                      ctrl->tls_pskid);
++              ctrl->tls_pskid = 0;
++      }
+ }
+ static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl,
+-- 
+2.43.0
+
diff --git a/queue-6.11/of-irq-refer-to-actual-buffer-size-in-of_irq_parse_o.patch b/queue-6.11/of-irq-refer-to-actual-buffer-size-in-of_irq_parse_o.patch
new file mode 100644 (file)
index 0000000..f5914f3
--- /dev/null
@@ -0,0 +1,39 @@
+From bc5edb74d7500794b710a415ae0d1c5b92365081 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Aug 2024 14:16:53 +0200
+Subject: of/irq: Refer to actual buffer size in of_irq_parse_one()
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+[ Upstream commit 39ab331ab5d377a18fbf5a0e0b228205edfcc7f4 ]
+
+Replace two open-coded calculations of the buffer size by invocations of
+sizeof() on the buffer itself, to make sure the code will always use the
+actual buffer size.
+
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/817c0b9626fd30790fc488c472a3398324cfcc0c.1724156125.git.geert+renesas@glider.be
+Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/of/irq.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/of/irq.c b/drivers/of/irq.c
+index 8fd63100ba8f0..d67b69cb84bfe 100644
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -357,8 +357,8 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
+       addr = of_get_property(device, "reg", &addr_len);
+       /* Prevent out-of-bounds read in case of longer interrupt parent address size */
+-      if (addr_len > (3 * sizeof(__be32)))
+-              addr_len = 3 * sizeof(__be32);
++      if (addr_len > sizeof(addr_buf))
++              addr_len = sizeof(addr_buf);
+       if (addr)
+               memcpy(addr_buf, addr, addr_len);
+-- 
+2.43.0
+
diff --git a/queue-6.11/ovl-fsync-after-metadata-copy-up.patch b/queue-6.11/ovl-fsync-after-metadata-copy-up.patch
new file mode 100644 (file)
index 0000000..b8f2be1
--- /dev/null
@@ -0,0 +1,131 @@
+From ea3eef3f30dc1432b4de6b21f266a682fe03a751 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Aug 2024 17:51:08 +0200
+Subject: ovl: fsync after metadata copy-up
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+[ Upstream commit 7d6899fb69d25e1bc6f4700b7c1d92e6b608593d ]
+
+For upper filesystems which do not use strict ordering of persisting
+metadata changes (e.g. ubifs), when overlayfs file is modified for
+the first time, copy up will create a copy of the lower file and
+its parent directories in the upper layer. Permission lost of the
+new upper parent directory was observed during power-cut stress test.
+
+Fix by moving the fsync call to after metadata copy to make sure that the
+metadata copied up directory and files persists to disk before renaming
+from tmp to final destination.
+
+With metacopy enabled, this change will hurt performance of workloads
+such as chown -R, so we keep the legacy behavior of fsync only on copyup
+of data.
+
+Link: https://lore.kernel.org/linux-unionfs/CAOQ4uxj-pOvmw1-uXR3qVdqtLjSkwcR9nVKcNU_vC10Zyf2miQ@mail.gmail.com/
+Reported-and-tested-by: Fei Lv <feilv@asrmicro.com>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/copy_up.c | 43 ++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 39 insertions(+), 4 deletions(-)
+
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index a5ef2005a2cc5..051a802893a18 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -243,8 +243,24 @@ static int ovl_verify_area(loff_t pos, loff_t pos2, loff_t len, loff_t totlen)
+       return 0;
+ }
++static int ovl_sync_file(struct path *path)
++{
++      struct file *new_file;
++      int err;
++
++      new_file = ovl_path_open(path, O_LARGEFILE | O_RDONLY);
++      if (IS_ERR(new_file))
++              return PTR_ERR(new_file);
++
++      err = vfs_fsync(new_file, 0);
++      fput(new_file);
++
++      return err;
++}
++
+ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
+-                          struct file *new_file, loff_t len)
++                          struct file *new_file, loff_t len,
++                          bool datasync)
+ {
+       struct path datapath;
+       struct file *old_file;
+@@ -342,7 +358,8 @@ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
+               len -= bytes;
+       }
+-      if (!error && ovl_should_sync(ofs))
++      /* call fsync once, either now or later along with metadata */
++      if (!error && ovl_should_sync(ofs) && datasync)
+               error = vfs_fsync(new_file, 0);
+ out_fput:
+       fput(old_file);
+@@ -574,6 +591,7 @@ struct ovl_copy_up_ctx {
+       bool indexed;
+       bool metacopy;
+       bool metacopy_digest;
++      bool metadata_fsync;
+ };
+ static int ovl_link_up(struct ovl_copy_up_ctx *c)
+@@ -634,7 +652,8 @@ static int ovl_copy_up_data(struct ovl_copy_up_ctx *c, const struct path *temp)
+       if (IS_ERR(new_file))
+               return PTR_ERR(new_file);
+-      err = ovl_copy_up_file(ofs, c->dentry, new_file, c->stat.size);
++      err = ovl_copy_up_file(ofs, c->dentry, new_file, c->stat.size,
++                             !c->metadata_fsync);
+       fput(new_file);
+       return err;
+@@ -701,6 +720,10 @@ static int ovl_copy_up_metadata(struct ovl_copy_up_ctx *c, struct dentry *temp)
+               err = ovl_set_attr(ofs, temp, &c->stat);
+       inode_unlock(temp->d_inode);
++      /* fsync metadata before moving it into upper dir */
++      if (!err && ovl_should_sync(ofs) && c->metadata_fsync)
++              err = ovl_sync_file(&upperpath);
++
+       return err;
+ }
+@@ -860,7 +883,8 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
+       temp = tmpfile->f_path.dentry;
+       if (!c->metacopy && c->stat.size) {
+-              err = ovl_copy_up_file(ofs, c->dentry, tmpfile, c->stat.size);
++              err = ovl_copy_up_file(ofs, c->dentry, tmpfile, c->stat.size,
++                                     !c->metadata_fsync);
+               if (err)
+                       goto out_fput;
+       }
+@@ -1135,6 +1159,17 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
+           !kgid_has_mapping(current_user_ns(), ctx.stat.gid))
+               return -EOVERFLOW;
++      /*
++       * With metacopy disabled, we fsync after final metadata copyup, for
++       * both regular files and directories to get atomic copyup semantics
++       * on filesystems that do not use strict metadata ordering (e.g. ubifs).
++       *
++       * With metacopy enabled we want to avoid fsync on all meta copyup
++       * that will hurt performance of workloads such as chown -R, so we
++       * only fsync on data copyup as legacy behavior.
++       */
++      ctx.metadata_fsync = !OVL_FS(dentry->d_sb)->config.metacopy &&
++                           (S_ISREG(ctx.stat.mode) || S_ISDIR(ctx.stat.mode));
+       ctx.metacopy = ovl_need_meta_copy_up(dentry, ctx.stat.mode, flags);
+       if (parent) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/perf-fix-event_function_call-locking.patch b/queue-6.11/perf-fix-event_function_call-locking.patch
new file mode 100644 (file)
index 0000000..5844c66
--- /dev/null
@@ -0,0 +1,63 @@
+From 71722d7c6ec4ec760c25af184f34e41cb66a1a84 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 13:29:27 +0200
+Subject: perf: Fix event_function_call() locking
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 558abc7e3f895049faa46b08656be4c60dc6e9fd ]
+
+All the event_function/@func call context already uses perf_ctx_lock()
+except for the !ctx->is_active case. Make it all consistent.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Reviewed-by: Namhyung Kim <namhyung@kernel.org>
+Link: https://lore.kernel.org/r/20240807115550.138301094@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/events/core.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/kernel/events/core.c b/kernel/events/core.c
+index b21c8f24a9876..4339df585d42d 100644
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -263,6 +263,7 @@ static int event_function(void *info)
+ static void event_function_call(struct perf_event *event, event_f func, void *data)
+ {
+       struct perf_event_context *ctx = event->ctx;
++      struct perf_cpu_context *cpuctx = this_cpu_ptr(&perf_cpu_context);
+       struct task_struct *task = READ_ONCE(ctx->task); /* verified in event_function */
+       struct event_function_struct efs = {
+               .event = event,
+@@ -291,22 +292,22 @@ static void event_function_call(struct perf_event *event, event_f func, void *da
+       if (!task_function_call(task, event_function, &efs))
+               return;
+-      raw_spin_lock_irq(&ctx->lock);
++      perf_ctx_lock(cpuctx, ctx);
+       /*
+        * Reload the task pointer, it might have been changed by
+        * a concurrent perf_event_context_sched_out().
+        */
+       task = ctx->task;
+       if (task == TASK_TOMBSTONE) {
+-              raw_spin_unlock_irq(&ctx->lock);
++              perf_ctx_unlock(cpuctx, ctx);
+               return;
+       }
+       if (ctx->is_active) {
+-              raw_spin_unlock_irq(&ctx->lock);
++              perf_ctx_unlock(cpuctx, ctx);
+               goto again;
+       }
+       func(event, NULL, ctx, data);
+-      raw_spin_unlock_irq(&ctx->lock);
++      perf_ctx_unlock(cpuctx, ctx);
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.11/perf-x86-avoid-missing-caller-address-in-stack-trace.patch b/queue-6.11/perf-x86-avoid-missing-caller-address-in-stack-trace.patch
new file mode 100644 (file)
index 0000000..a454cea
--- /dev/null
@@ -0,0 +1,197 @@
+From 61832eaec653570d520d1a83a05222efee39dcda Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 10:52:23 -0700
+Subject: perf,x86: avoid missing caller address in stack traces captured in
+ uprobe
+
+From: Andrii Nakryiko <andrii@kernel.org>
+
+[ Upstream commit cfa7f3d2c526c224a6271cc78a4a27a0de06f4f0 ]
+
+When tracing user functions with uprobe functionality, it's common to
+install the probe (e.g., a BPF program) at the first instruction of the
+function. This is often going to be `push %rbp` instruction in function
+preamble, which means that within that function frame pointer hasn't
+been established yet. This leads to consistently missing an actual
+caller of the traced function, because perf_callchain_user() only
+records current IP (capturing traced function) and then following frame
+pointer chain (which would be caller's frame, containing the address of
+caller's caller).
+
+So when we have target_1 -> target_2 -> target_3 call chain and we are
+tracing an entry to target_3, captured stack trace will report
+target_1 -> target_3 call chain, which is wrong and confusing.
+
+This patch proposes a x86-64-specific heuristic to detect `push %rbp`
+(`push %ebp` on 32-bit architecture) instruction being traced. Given
+entire kernel implementation of user space stack trace capturing works
+under assumption that user space code was compiled with frame pointer
+register (%rbp/%ebp) preservation, it seems pretty reasonable to use
+this instruction as a strong indicator that this is the entry to the
+function. In that case, return address is still pointed to by %rsp/%esp,
+so we fetch it and add to stack trace before proceeding to unwind the
+rest using frame pointer-based logic.
+
+We also check for `endbr64` (for 64-bit modes) as another common pattern
+for function entry, as suggested by Josh Poimboeuf. Even if we get this
+wrong sometimes for uprobes attached not at the function entry, it's OK
+because stack trace will still be overall meaningful, just with one
+extra bogus entry. If we don't detect this, we end up with guaranteed to
+be missing caller function entry in the stack trace, which is worse
+overall.
+
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20240729175223.23914-1-andrii@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/core.c  | 63 +++++++++++++++++++++++++++++++++++++++++
+ include/linux/uprobes.h |  2 ++
+ kernel/events/uprobes.c |  2 ++
+ 3 files changed, 67 insertions(+)
+
+diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
+index be01823b1bb45..65ab6460aed4d 100644
+--- a/arch/x86/events/core.c
++++ b/arch/x86/events/core.c
+@@ -41,6 +41,8 @@
+ #include <asm/desc.h>
+ #include <asm/ldt.h>
+ #include <asm/unwind.h>
++#include <asm/uprobes.h>
++#include <asm/ibt.h>
+ #include "perf_event.h"
+@@ -2816,6 +2818,46 @@ static unsigned long get_segment_base(unsigned int segment)
+       return get_desc_base(desc);
+ }
++#ifdef CONFIG_UPROBES
++/*
++ * Heuristic-based check if uprobe is installed at the function entry.
++ *
++ * Under assumption of user code being compiled with frame pointers,
++ * `push %rbp/%ebp` is a good indicator that we indeed are.
++ *
++ * Similarly, `endbr64` (assuming 64-bit mode) is also a common pattern.
++ * If we get this wrong, captured stack trace might have one extra bogus
++ * entry, but the rest of stack trace will still be meaningful.
++ */
++static bool is_uprobe_at_func_entry(struct pt_regs *regs)
++{
++      struct arch_uprobe *auprobe;
++
++      if (!current->utask)
++              return false;
++
++      auprobe = current->utask->auprobe;
++      if (!auprobe)
++              return false;
++
++      /* push %rbp/%ebp */
++      if (auprobe->insn[0] == 0x55)
++              return true;
++
++      /* endbr64 (64-bit only) */
++      if (user_64bit_mode(regs) && is_endbr(*(u32 *)auprobe->insn))
++              return true;
++
++      return false;
++}
++
++#else
++static bool is_uprobe_at_func_entry(struct pt_regs *regs)
++{
++      return false;
++}
++#endif /* CONFIG_UPROBES */
++
+ #ifdef CONFIG_IA32_EMULATION
+ #include <linux/compat.h>
+@@ -2827,6 +2869,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent
+       unsigned long ss_base, cs_base;
+       struct stack_frame_ia32 frame;
+       const struct stack_frame_ia32 __user *fp;
++      u32 ret_addr;
+       if (user_64bit_mode(regs))
+               return 0;
+@@ -2836,6 +2879,12 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent
+       fp = compat_ptr(ss_base + regs->bp);
+       pagefault_disable();
++
++      /* see perf_callchain_user() below for why we do this */
++      if (is_uprobe_at_func_entry(regs) &&
++          !get_user(ret_addr, (const u32 __user *)regs->sp))
++              perf_callchain_store(entry, ret_addr);
++
+       while (entry->nr < entry->max_stack) {
+               if (!valid_user_frame(fp, sizeof(frame)))
+                       break;
+@@ -2864,6 +2913,7 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
+ {
+       struct stack_frame frame;
+       const struct stack_frame __user *fp;
++      unsigned long ret_addr;
+       if (perf_guest_state()) {
+               /* TODO: We don't support guest os callchain now */
+@@ -2887,6 +2937,19 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
+               return;
+       pagefault_disable();
++
++      /*
++       * If we are called from uprobe handler, and we are indeed at the very
++       * entry to user function (which is normally a `push %rbp` instruction,
++       * under assumption of application being compiled with frame pointers),
++       * we should read return address from *regs->sp before proceeding
++       * to follow frame pointers, otherwise we'll skip immediate caller
++       * as %rbp is not yet setup.
++       */
++      if (is_uprobe_at_func_entry(regs) &&
++          !get_user(ret_addr, (const unsigned long __user *)regs->sp))
++              perf_callchain_store(entry, ret_addr);
++
+       while (entry->nr < entry->max_stack) {
+               if (!valid_user_frame(fp, sizeof(frame)))
+                       break;
+diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
+index b503fafb7fb3e..a270a5892ab4f 100644
+--- a/include/linux/uprobes.h
++++ b/include/linux/uprobes.h
+@@ -76,6 +76,8 @@ struct uprobe_task {
+       struct uprobe                   *active_uprobe;
+       unsigned long                   xol_vaddr;
++      struct arch_uprobe              *auprobe;
++
+       struct return_instance          *return_instances;
+       unsigned int                    depth;
+ };
+diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
+index 50d7949be2b17..333c44f2ce55d 100644
+--- a/kernel/events/uprobes.c
++++ b/kernel/events/uprobes.c
+@@ -2081,6 +2081,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
+       bool need_prep = false; /* prepare return uprobe, when needed */
+       down_read(&uprobe->register_rwsem);
++      current->utask->auprobe = &uprobe->arch;
+       for (uc = uprobe->consumers; uc; uc = uc->next) {
+               int rc = 0;
+@@ -2095,6 +2096,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
+               remove &= rc;
+       }
++      current->utask->auprobe = NULL;
+       if (need_prep && !remove)
+               prepare_uretprobe(uprobe, regs); /* put bp at return */
+-- 
+2.43.0
+
diff --git a/queue-6.11/platform-mellanox-mlxbf-pmc-fix-lockdep-warning.patch b/queue-6.11/platform-mellanox-mlxbf-pmc-fix-lockdep-warning.patch
new file mode 100644 (file)
index 0000000..3224f26
--- /dev/null
@@ -0,0 +1,135 @@
+From 187fc4997115fef776a88e19415902bb75741fb2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Sep 2024 15:05:32 -0400
+Subject: platform/mellanox: mlxbf-pmc: fix lockdep warning
+
+From: Luiz Capitulino <luizcap@redhat.com>
+
+[ Upstream commit 305790dd91057a3f7497c9d128614a4f8486b62b ]
+
+It seems the mlxbf-pmc driver is missing initializing sysfs attributes
+which causes the warning below when CONFIG_LOCKDEP and
+CONFIG_DEBUG_LOCK_ALLOC are enabled. This commit fixes it.
+
+[  155.380843] BUG: key ffff470f45dfa6d8 has not been registered!
+[  155.386749] ------------[ cut here ]------------
+[  155.391361] DEBUG_LOCKS_WARN_ON(1)
+[  155.391381] WARNING: CPU: 4 PID: 1828 at kernel/locking/lockdep.c:4894 lockdep_init_map_type+0x1d0/0x288
+[  155.404254] Modules linked in: mlxbf_pmc(+) xfs libcrc32c mmc_block mlx5_core crct10dif_ce mlxfw ghash_ce virtio_net tls net_failover sha2
+_ce failover psample sha256_arm64 dw_mmc_bluefield pci_hyperv_intf sha1_ce dw_mmc_pltfm sbsa_gwdt dw_mmc micrel mmc_core nfit i2c_mlxbf pwr_m
+lxbf gpio_generic libnvdimm mlxbf_tmfifo mlxbf_gige dm_mirror dm_region_hash dm_log dm_mod
+[  155.436786] CPU: 4 UID: 0 PID: 1828 Comm: modprobe Kdump: loaded Not tainted 6.11.0-rc7-rep1+ #1
+[  155.445562] Hardware name: https://www.mellanox.com BlueField SoC/BlueField SoC, BIOS 4.8.0.13249 Aug  7 2024
+[  155.455463] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+[  155.462413] pc : lockdep_init_map_type+0x1d0/0x288
+[  155.467196] lr : lockdep_init_map_type+0x1d0/0x288
+[  155.471976] sp : ffff80008a1734e0
+[  155.475279] x29: ffff80008a1734e0 x28: ffff470f45df0240 x27: 00000000ffffee4b
+[  155.482406] x26: 00000000000011b4 x25: 0000000000000000 x24: 0000000000000000
+[  155.489532] x23: ffff470f45dfa6d8 x22: 0000000000000000 x21: ffffd54ef6bea000
+[  155.496659] x20: ffff470f45dfa6d8 x19: ffff470f49cdc638 x18: ffffffffffffffff
+[  155.503784] x17: 2f30303a31444642 x16: ffffd54ef48a65e8 x15: ffff80010a172fe7
+[  155.510911] x14: 0000000000000000 x13: 284e4f5f4e524157 x12: 5f534b434f4c5f47
+[  155.518037] x11: 0000000000000001 x10: 0000000000000001 x9 : ffffd54ef3f48a14
+[  155.525163] x8 : 00000000000bffe8 x7 : c0000000ffff7fff x6 : 00000000002bffa8
+[  155.532289] x5 : ffff4712bdcb6088 x4 : 0000000000000000 x3 : 0000000000000027
+[  155.539416] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff470f43e5be00
+[  155.546542] Call trace:
+[  155.548976]  lockdep_init_map_type+0x1d0/0x288
+[  155.553410]  __kernfs_create_file+0x80/0x138
+[  155.557673]  sysfs_add_file_mode_ns+0x94/0x150
+[  155.562106]  create_files+0xb0/0x248
+[  155.565672]  internal_create_group+0x10c/0x328
+[  155.570105]  internal_create_groups.part.0+0x50/0xc8
+[  155.575060]  sysfs_create_groups+0x20/0x38
+[  155.579146]  device_add_attrs+0x1b8/0x228
+[  155.583146]  device_add+0x2a4/0x690
+[  155.586625]  device_register+0x24/0x38
+[  155.590362]  __hwmon_device_register+0x1e0/0x3c8
+[  155.594969]  devm_hwmon_device_register_with_groups+0x78/0xe0
+[  155.600703]  mlxbf_pmc_probe+0x224/0x3a0 [mlxbf_pmc]
+[  155.605669]  platform_probe+0x6c/0xe0
+[  155.609320]  really_probe+0xc4/0x398
+[  155.612887]  __driver_probe_device+0x80/0x168
+[  155.617233]  driver_probe_device+0x44/0x120
+[  155.621405]  __driver_attach+0xf4/0x200
+[  155.625230]  bus_for_each_dev+0x7c/0xe8
+[  155.629055]  driver_attach+0x28/0x38
+[  155.632619]  bus_add_driver+0x110/0x238
+[  155.636445]  driver_register+0x64/0x128
+[  155.640270]  __platform_driver_register+0x2c/0x40
+[  155.644965]  pmc_driver_init+0x24/0xff8 [mlxbf_pmc]
+[  155.649833]  do_one_initcall+0x70/0x3d0
+[  155.653660]  do_init_module+0x64/0x220
+[  155.657400]  load_module+0x628/0x6a8
+[  155.660964]  init_module_from_file+0x8c/0xd8
+[  155.665222]  idempotent_init_module+0x194/0x290
+[  155.669742]  __arm64_sys_finit_module+0x6c/0xd8
+[  155.674261]  invoke_syscall.constprop.0+0x74/0xd0
+[  155.678957]  do_el0_svc+0xb4/0xd0
+[  155.682262]  el0_svc+0x5c/0x248
+[  155.685394]  el0t_64_sync_handler+0x134/0x150
+[  155.689739]  el0t_64_sync+0x17c/0x180
+[  155.693390] irq event stamp: 6407
+[  155.696693] hardirqs last  enabled at (6407): [<ffffd54ef3f48564>] console_unlock+0x154/0x1b8
+[  155.705207] hardirqs last disabled at (6406): [<ffffd54ef3f485ac>] console_unlock+0x19c/0x1b8
+[  155.713719] softirqs last  enabled at (6404): [<ffffd54ef3e9740c>] handle_softirqs+0x4f4/0x518
+[  155.722320] softirqs last disabled at (6395): [<ffffd54ef3df0160>] __do_softirq+0x18/0x20
+[  155.730484] ---[ end trace 0000000000000000 ]---
+
+Signed-off-by: Luiz Capitulino <luizcap@redhat.com>
+Link: https://lore.kernel.org/r/20240912190532.377097-1-luizcap@redhat.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/mellanox/mlxbf-pmc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c
+index 4ed9c7fd2b62a..9d18dfca6a673 100644
+--- a/drivers/platform/mellanox/mlxbf-pmc.c
++++ b/drivers/platform/mellanox/mlxbf-pmc.c
+@@ -1774,6 +1774,7 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_
+       /* "event_list" sysfs to list events supported by the block */
+       attr = &pmc->block[blk_num].attr_event_list;
++      sysfs_attr_init(&attr->dev_attr.attr);
+       attr->dev_attr.attr.mode = 0444;
+       attr->dev_attr.show = mlxbf_pmc_event_list_show;
+       attr->nr = blk_num;
+@@ -1787,6 +1788,7 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_
+       if (strstr(pmc->block_name[blk_num], "l3cache") ||
+           ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE))) {
+               attr = &pmc->block[blk_num].attr_enable;
++              sysfs_attr_init(&attr->dev_attr.attr);
+               attr->dev_attr.attr.mode = 0644;
+               attr->dev_attr.show = mlxbf_pmc_enable_show;
+               attr->dev_attr.store = mlxbf_pmc_enable_store;
+@@ -1814,6 +1816,7 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_
+       /* "eventX" and "counterX" sysfs to program and read counter values */
+       for (j = 0; j < pmc->block[blk_num].counters; ++j) {
+               attr = &pmc->block[blk_num].attr_counter[j];
++              sysfs_attr_init(&attr->dev_attr.attr);
+               attr->dev_attr.attr.mode = 0644;
+               attr->dev_attr.show = mlxbf_pmc_counter_show;
+               attr->dev_attr.store = mlxbf_pmc_counter_store;
+@@ -1826,6 +1829,7 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_
+               attr = NULL;
+               attr = &pmc->block[blk_num].attr_event[j];
++              sysfs_attr_init(&attr->dev_attr.attr);
+               attr->dev_attr.attr.mode = 0644;
+               attr->dev_attr.show = mlxbf_pmc_event_show;
+               attr->dev_attr.store = mlxbf_pmc_event_store;
+@@ -1861,6 +1865,7 @@ static int mlxbf_pmc_init_perftype_reg(struct device *dev, unsigned int blk_num)
+       while (count > 0) {
+               --count;
+               attr = &pmc->block[blk_num].attr_event[count];
++              sysfs_attr_init(&attr->dev_attr.attr);
+               attr->dev_attr.attr.mode = 0644;
+               attr->dev_attr.show = mlxbf_pmc_counter_show;
+               attr->dev_attr.store = mlxbf_pmc_counter_store;
+-- 
+2.43.0
+
diff --git a/queue-6.11/platform-x86-amd-pmf-add-quirk-for-tuf-gaming-a14.patch b/queue-6.11/platform-x86-amd-pmf-add-quirk-for-tuf-gaming-a14.patch
new file mode 100644 (file)
index 0000000..8050681
--- /dev/null
@@ -0,0 +1,44 @@
+From eeddc6641048a08ccd2cc0d7a0fbca6eff328912 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Sep 2024 15:36:01 +0800
+Subject: platform/x86/amd: pmf: Add quirk for TUF Gaming A14
+
+From: aln8 <aln8un@gmail.com>
+
+[ Upstream commit 06369503d644068abd9e90918c6611274d94c126 ]
+
+The ASUS TUF Gaming A14 has the same issue as the ROG Zephyrus G14
+where it advertises SPS support but doesn't use it.
+
+Signed-off-by: aln8 <aln8un@gmail.com>
+Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+Link: https://lore.kernel.org/r/20240912073601.65656-1-aln8un@gmail.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/amd/pmf/pmf-quirks.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/platform/x86/amd/pmf/pmf-quirks.c b/drivers/platform/x86/amd/pmf/pmf-quirks.c
+index 48870ca52b413..7cde5733b9cac 100644
+--- a/drivers/platform/x86/amd/pmf/pmf-quirks.c
++++ b/drivers/platform/x86/amd/pmf/pmf-quirks.c
+@@ -37,6 +37,14 @@ static const struct dmi_system_id fwbug_list[] = {
+               },
+               .driver_data = &quirk_no_sps_bug,
+       },
++      {
++              .ident = "ASUS TUF Gaming A14",
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "FA401W"),
++              },
++              .driver_data = &quirk_no_sps_bug,
++      },
+       {}
+ };
+-- 
+2.43.0
+
diff --git a/queue-6.11/platform-x86-lenovo-ymc-ignore-the-0x0-state.patch b/queue-6.11/platform-x86-lenovo-ymc-ignore-the-0x0-state.patch
new file mode 100644 (file)
index 0000000..cc02a11
--- /dev/null
@@ -0,0 +1,46 @@
+From 0046bbf06340984f501720f7a12ae6c1c72663d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Aug 2024 17:38:57 +0200
+Subject: platform/x86: lenovo-ymc: Ignore the 0x0 state
+
+From: Gergo Koteles <soyer@irl.hu>
+
+[ Upstream commit d9dca215708d32e7f88ac0591fbb187cbf368adb ]
+
+While booting, Lenovo 14ARB7 reports 'lenovo-ymc: Unknown key 0 pressed'
+warning. This is caused by lenovo_ymc_probe() calling lenovo_ymc_notify()
+at probe time to get the initial tablet-mode-switch state and the key-code
+lenovo_ymc_notify() reads from the firmware is not initialized at probe
+time yet on the Lenovo 14ARB7.
+
+The hardware/firmware does an ACPI notify on the WMI device itself when
+it initializes the tablet-mode-switch state later on.
+
+Add 0x0 YMC state to the sparse keymap to silence the warning.
+
+Signed-off-by: Gergo Koteles <soyer@irl.hu>
+Link: https://lore.kernel.org/r/08ab73bb74c4ad448409f2ce707b1148874a05ce.1724340562.git.soyer@irl.hu
+[hdegoede@redhat.com: Reword commit message]
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/lenovo-ymc.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/platform/x86/lenovo-ymc.c b/drivers/platform/x86/lenovo-ymc.c
+index e0bbd6a14a89c..bd9f95404c7cb 100644
+--- a/drivers/platform/x86/lenovo-ymc.c
++++ b/drivers/platform/x86/lenovo-ymc.c
+@@ -43,6 +43,8 @@ struct lenovo_ymc_private {
+ };
+ static const struct key_entry lenovo_ymc_keymap[] = {
++      /* Ignore the uninitialized state */
++      { KE_IGNORE, 0x00 },
+       /* Laptop */
+       { KE_SW, 0x01, { .sw = { SW_TABLET_MODE, 0 } } },
+       /* Tablet */
+-- 
+2.43.0
+
diff --git a/queue-6.11/platform-x86-touchscreen_dmi-add-nanote-next-quirk.patch b/queue-6.11/platform-x86-touchscreen_dmi-add-nanote-next-quirk.patch
new file mode 100644 (file)
index 0000000..42e776c
--- /dev/null
@@ -0,0 +1,69 @@
+From 1e81f9a368574c0dc4e505f9a64c6a34cb3bf8a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 21:12:40 +0200
+Subject: platform/x86: touchscreen_dmi: add nanote-next quirk
+
+From: Ckath <ckath@yandex.ru>
+
+[ Upstream commit c11619af35bae5884029bd14170c3e4b55ddf6f3 ]
+
+Add touschscreen info for the nanote next (UMPC-03-SR).
+
+After checking with multiple owners the DMI info really is this generic.
+
+Signed-off-by: Ckath <ckath@yandex.ru>
+Link: https://lore.kernel.org/r/e8dda83a-10ae-42cf-a061-5d29be0d193a@yandex.ru
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/touchscreen_dmi.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
+index f74af0a689f20..0a39f68c641d1 100644
+--- a/drivers/platform/x86/touchscreen_dmi.c
++++ b/drivers/platform/x86/touchscreen_dmi.c
+@@ -840,6 +840,21 @@ static const struct ts_dmi_data rwc_nanote_p8_data = {
+       .properties = rwc_nanote_p8_props,
+ };
++static const struct property_entry rwc_nanote_next_props[] = {
++      PROPERTY_ENTRY_U32("touchscreen-min-x", 5),
++      PROPERTY_ENTRY_U32("touchscreen-min-y", 5),
++      PROPERTY_ENTRY_U32("touchscreen-size-x", 1785),
++      PROPERTY_ENTRY_U32("touchscreen-size-y", 1145),
++      PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
++      PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-rwc-nanote-next.fw"),
++      { }
++};
++
++static const struct ts_dmi_data rwc_nanote_next_data = {
++      .acpi_name = "MSSL1680:00",
++      .properties = rwc_nanote_next_props,
++};
++
+ static const struct property_entry schneider_sct101ctm_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1715),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
+@@ -1589,6 +1604,17 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
+                       DMI_MATCH(DMI_PRODUCT_SKU, "0001")
+               },
+       },
++      {
++              /* RWC NANOTE NEXT */
++              .driver_data = (void *)&rwc_nanote_next_data,
++              .matches = {
++                      DMI_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."),
++                      DMI_MATCH(DMI_BOARD_NAME, "To be filled by O.E.M."),
++                      DMI_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
++                      /* Above matches are too generic, add bios-version match */
++                      DMI_MATCH(DMI_BIOS_VERSION, "S8A70R100-V005"),
++              },
++      },
+       {
+               /* Schneider SCT101CTM */
+               .driver_data = (void *)&schneider_sct101ctm_data,
+-- 
+2.43.0
+
diff --git a/queue-6.11/platform-x86-x86-android-tablets-adjust-xiaomi-pad-2.patch b/queue-6.11/platform-x86-x86-android-tablets-adjust-xiaomi-pad-2.patch
new file mode 100644 (file)
index 0000000..26b38e9
--- /dev/null
@@ -0,0 +1,70 @@
+From 37a5d01fa8eaa07ea4e8363489e7dd5ef219f4ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Sep 2024 11:02:55 +0200
+Subject: platform/x86: x86-android-tablets: Adjust Xiaomi Pad 2 bottom bezel
+ touch buttons LED
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit df40a23cc34c200cfde559eda7ca540f3ae7bd9e ]
+
+The "input-events" LED trigger used to turn on the backlight LEDs had to
+be rewritten to use led_trigger_register_simple() + led_trigger_event()
+to fix a serious locking issue.
+
+This means it no longer supports using blink_brightness to set a per LED
+brightness for the trigger and it no longer sets LED_CORE_SUSPENDRESUME.
+
+Adjust the MiPad 2 bottom bezel touch buttons LED class device to match:
+
+1. Make LED_FULL the maximum brightness to fix the LED brightness
+   being very low when on.
+2. Set flags = LED_CORE_SUSPENDRESUME.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20240916090255.35548-1-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/x86-android-tablets/other.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/platform/x86/x86-android-tablets/other.c b/drivers/platform/x86/x86-android-tablets/other.c
+index eb0e55c69dfed..2549c348c8825 100644
+--- a/drivers/platform/x86/x86-android-tablets/other.c
++++ b/drivers/platform/x86/x86-android-tablets/other.c
+@@ -670,7 +670,7 @@ static const struct software_node *ktd2026_node_group[] = {
+  * is controlled by the "pwm_soc_lpss_2" PWM output.
+  */
+ #define XIAOMI_MIPAD2_LED_PERIOD_NS           19200
+-#define XIAOMI_MIPAD2_LED_DEFAULT_DUTY                 6000 /* From Android kernel */
++#define XIAOMI_MIPAD2_LED_MAX_DUTY_NS          6000 /* From Android kernel */
+ static struct pwm_device *xiaomi_mipad2_led_pwm;
+@@ -679,7 +679,7 @@ static int xiaomi_mipad2_brightness_set(struct led_classdev *led_cdev,
+ {
+       struct pwm_state state = {
+               .period = XIAOMI_MIPAD2_LED_PERIOD_NS,
+-              .duty_cycle = val,
++              .duty_cycle = XIAOMI_MIPAD2_LED_MAX_DUTY_NS * val / LED_FULL,
+               /* Always set PWM enabled to avoid the pin floating */
+               .enabled = true,
+       };
+@@ -701,11 +701,11 @@ static int __init xiaomi_mipad2_init(struct device *dev)
+               return -ENOMEM;
+       led_cdev->name = "mipad2:white:touch-buttons-backlight";
+-      led_cdev->max_brightness = XIAOMI_MIPAD2_LED_PERIOD_NS;
+-      /* "input-events" trigger uses blink_brightness */
+-      led_cdev->blink_brightness = XIAOMI_MIPAD2_LED_DEFAULT_DUTY;
++      led_cdev->max_brightness = LED_FULL;
+       led_cdev->default_trigger = "input-events";
+       led_cdev->brightness_set_blocking = xiaomi_mipad2_brightness_set;
++      /* Turn LED off during suspend */
++      led_cdev->flags = LED_CORE_SUSPENDRESUME;
+       ret = devm_led_classdev_register(dev, led_cdev);
+       if (ret)
+-- 
+2.43.0
+
diff --git a/queue-6.11/pmdomain-core-don-t-hold-the-genpd-lock-when-calling.patch b/queue-6.11/pmdomain-core-don-t-hold-the-genpd-lock-when-calling.patch
new file mode 100644 (file)
index 0000000..ee11220
--- /dev/null
@@ -0,0 +1,65 @@
+From 8966a7528c9ca10e6d8c008c8c8c6704103c7f30 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 16:25:52 +0200
+Subject: pmdomain: core: Don't hold the genpd-lock when calling
+ dev_pm_domain_set()
+
+From: Ulf Hansson <ulf.hansson@linaro.org>
+
+[ Upstream commit b87eee38605c396f0e1fa435939960e5c6cd41d6 ]
+
+There is no need to hold the genpd-lock, while assigning the
+dev->pm_domain. In fact, it becomes a problem on a PREEMPT_RT based
+configuration as the genpd-lock may be a raw spinlock, while the lock
+acquired through the call to dev_pm_domain_set() is a regular spinlock.
+
+To fix the problem, let's simply move the calls to dev_pm_domain_set()
+outside the genpd-lock.
+
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Tested-by: Raghavendra Kakarla <quic_rkakarla@quicinc.com>  # qcm6490 with PREEMPT_RT set
+Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20240527142557.321610-3-ulf.hansson@linaro.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pmdomain/core.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
+index acdc3e7b2eae2..ca7f780582cf4 100644
+--- a/drivers/pmdomain/core.c
++++ b/drivers/pmdomain/core.c
+@@ -1758,7 +1758,6 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
+       genpd_lock(genpd);
+       genpd_set_cpumask(genpd, gpd_data->cpu);
+-      dev_pm_domain_set(dev, &genpd->domain);
+       genpd->device_count++;
+       if (gd)
+@@ -1767,6 +1766,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
+       list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
+       genpd_unlock(genpd);
++      dev_pm_domain_set(dev, &genpd->domain);
+  out:
+       if (ret)
+               genpd_free_dev_data(dev, gpd_data);
+@@ -1823,12 +1823,13 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
+               genpd->gd->max_off_time_changed = true;
+       genpd_clear_cpumask(genpd, gpd_data->cpu);
+-      dev_pm_domain_set(dev, NULL);
+       list_del_init(&pdd->list_node);
+       genpd_unlock(genpd);
++      dev_pm_domain_set(dev, NULL);
++
+       if (genpd->detach_dev)
+               genpd->detach_dev(genpd, dev);
+-- 
+2.43.0
+
diff --git a/queue-6.11/pmdomain-core-use-dev_name-instead-of-kobject_get_pa.patch b/queue-6.11/pmdomain-core-use-dev_name-instead-of-kobject_get_pa.patch
new file mode 100644 (file)
index 0000000..65aea33
--- /dev/null
@@ -0,0 +1,87 @@
+From 884c90a7c6f52651c57191d0290fbc741fb735f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 16:25:53 +0200
+Subject: pmdomain: core: Use dev_name() instead of kobject_get_path() in
+ debugfs
+
+From: Ulf Hansson <ulf.hansson@linaro.org>
+
+[ Upstream commit 9094e53ff5c86ebe372ad3960c3216c9817a1a04 ]
+
+Using kobject_get_path() means a dynamic memory allocation gets done, which
+doesn't work on a PREEMPT_RT based configuration while holding genpd's raw
+spinlock.
+
+To fix the problem, let's convert into using the simpler dev_name(). This
+means the information about the path doesn't get presented in debugfs, but
+hopefully this shouldn't be an issue.
+
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Tested-by: Raghavendra Kakarla <quic_rkakarla@quicinc.com>  # qcm6490 with PREEMPT_RT set
+Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20240527142557.321610-4-ulf.hansson@linaro.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pmdomain/core.c | 23 +++--------------------
+ 1 file changed, 3 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
+index ca7f780582cf4..95b30d35e0b42 100644
+--- a/drivers/pmdomain/core.c
++++ b/drivers/pmdomain/core.c
+@@ -3210,7 +3210,6 @@ static int genpd_summary_one(struct seq_file *s,
+               [GENPD_STATE_OFF] = "off"
+       };
+       struct pm_domain_data *pm_data;
+-      const char *kobj_path;
+       struct gpd_link *link;
+       char state[16];
+       int ret;
+@@ -3243,17 +3242,10 @@ static int genpd_summary_one(struct seq_file *s,
+       }
+       list_for_each_entry(pm_data, &genpd->dev_list, list_node) {
+-              kobj_path = kobject_get_path(&pm_data->dev->kobj,
+-                              genpd_is_irq_safe(genpd) ?
+-                              GFP_ATOMIC : GFP_KERNEL);
+-              if (kobj_path == NULL)
+-                      continue;
+-
+-              seq_printf(s, "\n    %-50s  ", kobj_path);
++              seq_printf(s, "\n    %-50s  ", dev_name(pm_data->dev));
+               rtpm_status_str(s, pm_data->dev);
+               perf_status_str(s, pm_data->dev);
+               mode_status_str(s, pm_data->dev);
+-              kfree(kobj_path);
+       }
+       seq_puts(s, "\n");
+@@ -3422,23 +3414,14 @@ static int devices_show(struct seq_file *s, void *data)
+ {
+       struct generic_pm_domain *genpd = s->private;
+       struct pm_domain_data *pm_data;
+-      const char *kobj_path;
+       int ret = 0;
+       ret = genpd_lock_interruptible(genpd);
+       if (ret)
+               return -ERESTARTSYS;
+-      list_for_each_entry(pm_data, &genpd->dev_list, list_node) {
+-              kobj_path = kobject_get_path(&pm_data->dev->kobj,
+-                              genpd_is_irq_safe(genpd) ?
+-                              GFP_ATOMIC : GFP_KERNEL);
+-              if (kobj_path == NULL)
+-                      continue;
+-
+-              seq_printf(s, "%s\n", kobj_path);
+-              kfree(kobj_path);
+-      }
++      list_for_each_entry(pm_data, &genpd->dev_list, list_node)
++              seq_printf(s, "%s\n", dev_name(pm_data->dev));
+       genpd_unlock(genpd);
+       return ret;
+-- 
+2.43.0
+
diff --git a/queue-6.11/power-reset-brcmstb-do-not-go-into-infinite-loop-if-.patch b/queue-6.11/power-reset-brcmstb-do-not-go-into-infinite-loop-if-.patch
new file mode 100644 (file)
index 0000000..5aeb1e4
--- /dev/null
@@ -0,0 +1,39 @@
+From 8ac2ee06e8c919b3fd24f13a79346ab26897f23b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Jun 2024 09:28:36 -0500
+Subject: power: reset: brcmstb: Do not go into infinite loop if reset fails
+
+From: Andrew Davis <afd@ti.com>
+
+[ Upstream commit cf8c39b00e982fa506b16f9d76657838c09150cb ]
+
+There may be other backup reset methods available, do not halt
+here so that other reset methods can be tried.
+
+Signed-off-by: Andrew Davis <afd@ti.com>
+Reviewed-by: Dhruva Gole <d-gole@ti.com>
+Acked-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://lore.kernel.org/r/20240610142836.168603-5-afd@ti.com
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/reset/brcmstb-reboot.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/power/reset/brcmstb-reboot.c b/drivers/power/reset/brcmstb-reboot.c
+index 0f2944dc93551..a04713f191a11 100644
+--- a/drivers/power/reset/brcmstb-reboot.c
++++ b/drivers/power/reset/brcmstb-reboot.c
+@@ -62,9 +62,6 @@ static int brcmstb_restart_handler(struct notifier_block *this,
+               return NOTIFY_DONE;
+       }
+-      while (1)
+-              ;
+-
+       return NOTIFY_DONE;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/powerpc-pseries-use-correct-data-types-from-pseries_.patch b/queue-6.11/powerpc-pseries-use-correct-data-types-from-pseries_.patch
new file mode 100644 (file)
index 0000000..bf2c21a
--- /dev/null
@@ -0,0 +1,157 @@
+From 4965ad9011c924fd94a59d60bd99b6b652d2d055 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 19:50:26 -0700
+Subject: powerpc/pseries: Use correct data types from pseries_hp_errorlog
+ struct
+
+From: Haren Myneni <haren@linux.ibm.com>
+
+[ Upstream commit b76e0d4215b6b622127ebcceaa7f603313ceaec4 ]
+
+_be32 type is defined for some elements in pseries_hp_errorlog
+struct but also used them u32 after be32_to_cpu() conversion.
+
+Example: In handle_dlpar_errorlog()
+hp_elog->_drc_u.drc_index = be32_to_cpu(hp_elog->_drc_u.drc_index);
+
+And later assigned to u32 type
+dlpar_cpu() - u32 drc_index = hp_elog->_drc_u.drc_index;
+
+This incorrect usage is giving the following warnings and the
+patch resolve these warnings with the correct assignment.
+
+arch/powerpc/platforms/pseries/dlpar.c:398:53: sparse: sparse:
+incorrect type in argument 1 (different base types) @@
+expected unsigned int [usertype] drc_index @@
+got restricted __be32 [usertype] drc_index @@
+...
+arch/powerpc/platforms/pseries/dlpar.c:418:43: sparse: sparse:
+incorrect type in assignment (different base types) @@
+expected restricted __be32 [usertype] drc_count @@
+got unsigned int [usertype] @@
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202408182142.wuIKqYae-lkp@intel.com/
+Closes: https://lore.kernel.org/oe-kbuild-all/202408182302.o7QRO45S-lkp@intel.com/
+Signed-off-by: Haren Myneni <haren@linux.ibm.com>
+
+v3:
+- Fix warnings from using incorrect data types in pseries_hp_errorlog
+  struct
+v2:
+- Remove pr_info() and TODO comments
+- Update more information in the commit logs
+
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20240822025028.938332-1-haren@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/platforms/pseries/dlpar.c          | 17 -----------------
+ arch/powerpc/platforms/pseries/hotplug-cpu.c    |  2 +-
+ arch/powerpc/platforms/pseries/hotplug-memory.c | 16 ++++++++--------
+ arch/powerpc/platforms/pseries/pmem.c           |  2 +-
+ 4 files changed, 10 insertions(+), 27 deletions(-)
+
+diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
+index 47f8eabd1bee3..9873b916b2370 100644
+--- a/arch/powerpc/platforms/pseries/dlpar.c
++++ b/arch/powerpc/platforms/pseries/dlpar.c
+@@ -334,23 +334,6 @@ int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog)
+ {
+       int rc;
+-      /* pseries error logs are in BE format, convert to cpu type */
+-      switch (hp_elog->id_type) {
+-      case PSERIES_HP_ELOG_ID_DRC_COUNT:
+-              hp_elog->_drc_u.drc_count =
+-                              be32_to_cpu(hp_elog->_drc_u.drc_count);
+-              break;
+-      case PSERIES_HP_ELOG_ID_DRC_INDEX:
+-              hp_elog->_drc_u.drc_index =
+-                              be32_to_cpu(hp_elog->_drc_u.drc_index);
+-              break;
+-      case PSERIES_HP_ELOG_ID_DRC_IC:
+-              hp_elog->_drc_u.ic.count =
+-                              be32_to_cpu(hp_elog->_drc_u.ic.count);
+-              hp_elog->_drc_u.ic.index =
+-                              be32_to_cpu(hp_elog->_drc_u.ic.index);
+-      }
+-
+       switch (hp_elog->resource) {
+       case PSERIES_HP_ELOG_RESOURCE_MEM:
+               rc = dlpar_memory(hp_elog);
+diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
+index e62835a12d73f..6838a0fcda296 100644
+--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
++++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
+@@ -757,7 +757,7 @@ int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
+       u32 drc_index;
+       int rc;
+-      drc_index = hp_elog->_drc_u.drc_index;
++      drc_index = be32_to_cpu(hp_elog->_drc_u.drc_index);
+       lock_device_hotplug();
+diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
+index 3fe3ddb30c04b..38dc4f7c9296b 100644
+--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
+@@ -817,16 +817,16 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
+       case PSERIES_HP_ELOG_ACTION_ADD:
+               switch (hp_elog->id_type) {
+               case PSERIES_HP_ELOG_ID_DRC_COUNT:
+-                      count = hp_elog->_drc_u.drc_count;
++                      count = be32_to_cpu(hp_elog->_drc_u.drc_count);
+                       rc = dlpar_memory_add_by_count(count);
+                       break;
+               case PSERIES_HP_ELOG_ID_DRC_INDEX:
+-                      drc_index = hp_elog->_drc_u.drc_index;
++                      drc_index = be32_to_cpu(hp_elog->_drc_u.drc_index);
+                       rc = dlpar_memory_add_by_index(drc_index);
+                       break;
+               case PSERIES_HP_ELOG_ID_DRC_IC:
+-                      count = hp_elog->_drc_u.ic.count;
+-                      drc_index = hp_elog->_drc_u.ic.index;
++                      count = be32_to_cpu(hp_elog->_drc_u.ic.count);
++                      drc_index = be32_to_cpu(hp_elog->_drc_u.ic.index);
+                       rc = dlpar_memory_add_by_ic(count, drc_index);
+                       break;
+               default:
+@@ -838,16 +838,16 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
+       case PSERIES_HP_ELOG_ACTION_REMOVE:
+               switch (hp_elog->id_type) {
+               case PSERIES_HP_ELOG_ID_DRC_COUNT:
+-                      count = hp_elog->_drc_u.drc_count;
++                      count = be32_to_cpu(hp_elog->_drc_u.drc_count);
+                       rc = dlpar_memory_remove_by_count(count);
+                       break;
+               case PSERIES_HP_ELOG_ID_DRC_INDEX:
+-                      drc_index = hp_elog->_drc_u.drc_index;
++                      drc_index = be32_to_cpu(hp_elog->_drc_u.drc_index);
+                       rc = dlpar_memory_remove_by_index(drc_index);
+                       break;
+               case PSERIES_HP_ELOG_ID_DRC_IC:
+-                      count = hp_elog->_drc_u.ic.count;
+-                      drc_index = hp_elog->_drc_u.ic.index;
++                      count = be32_to_cpu(hp_elog->_drc_u.ic.count);
++                      drc_index = be32_to_cpu(hp_elog->_drc_u.ic.index);
+                       rc = dlpar_memory_remove_by_ic(count, drc_index);
+                       break;
+               default:
+diff --git a/arch/powerpc/platforms/pseries/pmem.c b/arch/powerpc/platforms/pseries/pmem.c
+index 3c290b9ed01b3..0f1d45f32e4a4 100644
+--- a/arch/powerpc/platforms/pseries/pmem.c
++++ b/arch/powerpc/platforms/pseries/pmem.c
+@@ -121,7 +121,7 @@ int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog)
+               return -EINVAL;
+       }
+-      drc_index = hp_elog->_drc_u.drc_index;
++      drc_index = be32_to_cpu(hp_elog->_drc_u.drc_index);
+       lock_device_hotplug();
+-- 
+2.43.0
+
diff --git a/queue-6.11/proc-add-config-param-to-block-forcing-mem-writes.patch b/queue-6.11/proc-add-config-param-to-block-forcing-mem-writes.patch
new file mode 100644 (file)
index 0000000..652c49f
--- /dev/null
@@ -0,0 +1,200 @@
+From 79f24f9cae11180337815e9768badf03817c4186 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 11:02:25 +0300
+Subject: proc: add config & param to block forcing mem writes
+
+From: Adrian Ratiu <adrian.ratiu@collabora.com>
+
+[ Upstream commit 41e8149c8892ed1962bd15350b3c3e6e90cba7f4 ]
+
+This adds a Kconfig option and boot param to allow removing
+the FOLL_FORCE flag from /proc/pid/mem write calls because
+it can be abused.
+
+The traditional forcing behavior is kept as default because
+it can break GDB and some other use cases.
+
+Previously we tried a more sophisticated approach allowing
+distributions to fine-tune /proc/pid/mem behavior, however
+that got NAK-ed by Linus [1], who prefers this simpler
+approach with semantics also easier to understand for users.
+
+Link: https://lore.kernel.org/lkml/CAHk-=wiGWLChxYmUA5HrT5aopZrB7_2VTa0NLZcxORgkUe5tEQ@mail.gmail.com/ [1]
+Cc: Doug Anderson <dianders@chromium.org>
+Cc: Jeff Xu <jeffxu@google.com>
+Cc: Jann Horn <jannh@google.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: Ard Biesheuvel <ardb@kernel.org>
+Cc: Christian Brauner <brauner@kernel.org>
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
+Link: https://lore.kernel.org/r/20240802080225.89408-1-adrian.ratiu@collabora.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../admin-guide/kernel-parameters.txt         | 10 +++
+ fs/proc/base.c                                | 61 ++++++++++++++++++-
+ security/Kconfig                              | 32 ++++++++++
+ 3 files changed, 102 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index 09126bb8cc9ff..be010fec76541 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -4788,6 +4788,16 @@
+       printk.time=    Show timing data prefixed to each printk message line
+                       Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
++      proc_mem.force_override= [KNL]
++                      Format: {always | ptrace | never}
++                      Traditionally /proc/pid/mem allows memory permissions to be
++                      overridden without restrictions. This option may be set to
++                      restrict that. Can be one of:
++                      - 'always': traditional behavior always allows mem overrides.
++                      - 'ptrace': only allow mem overrides for active ptracers.
++                      - 'never':  never allow mem overrides.
++                      If not specified, default is the CONFIG_PROC_MEM_* choice.
++
+       processor.max_cstate=   [HW,ACPI]
+                       Limit processor to maximum C-state
+                       max_cstate=9 overrides any DMI blacklist limit.
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index 72a1acd03675c..f389c69767fa5 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -85,6 +85,7 @@
+ #include <linux/elf.h>
+ #include <linux/pid_namespace.h>
+ #include <linux/user_namespace.h>
++#include <linux/fs_parser.h>
+ #include <linux/fs_struct.h>
+ #include <linux/slab.h>
+ #include <linux/sched/autogroup.h>
+@@ -117,6 +118,40 @@
+ static u8 nlink_tid __ro_after_init;
+ static u8 nlink_tgid __ro_after_init;
++enum proc_mem_force {
++      PROC_MEM_FORCE_ALWAYS,
++      PROC_MEM_FORCE_PTRACE,
++      PROC_MEM_FORCE_NEVER
++};
++
++static enum proc_mem_force proc_mem_force_override __ro_after_init =
++      IS_ENABLED(CONFIG_PROC_MEM_NO_FORCE) ? PROC_MEM_FORCE_NEVER :
++      IS_ENABLED(CONFIG_PROC_MEM_FORCE_PTRACE) ? PROC_MEM_FORCE_PTRACE :
++      PROC_MEM_FORCE_ALWAYS;
++
++static const struct constant_table proc_mem_force_table[] __initconst = {
++      { "always", PROC_MEM_FORCE_ALWAYS },
++      { "ptrace", PROC_MEM_FORCE_PTRACE },
++      { "never", PROC_MEM_FORCE_NEVER },
++      { }
++};
++
++static int __init early_proc_mem_force_override(char *buf)
++{
++      if (!buf)
++              return -EINVAL;
++
++      /*
++       * lookup_constant() defaults to proc_mem_force_override to preseve
++       * the initial Kconfig choice in case an invalid param gets passed.
++       */
++      proc_mem_force_override = lookup_constant(proc_mem_force_table,
++                                                buf, proc_mem_force_override);
++
++      return 0;
++}
++early_param("proc_mem.force_override", early_proc_mem_force_override);
++
+ struct pid_entry {
+       const char *name;
+       unsigned int len;
+@@ -835,6 +870,28 @@ static int mem_open(struct inode *inode, struct file *file)
+       return ret;
+ }
++static bool proc_mem_foll_force(struct file *file, struct mm_struct *mm)
++{
++      struct task_struct *task;
++      bool ptrace_active = false;
++
++      switch (proc_mem_force_override) {
++      case PROC_MEM_FORCE_NEVER:
++              return false;
++      case PROC_MEM_FORCE_PTRACE:
++              task = get_proc_task(file_inode(file));
++              if (task) {
++                      ptrace_active = READ_ONCE(task->ptrace) &&
++                                      READ_ONCE(task->mm) == mm &&
++                                      READ_ONCE(task->parent) == current;
++                      put_task_struct(task);
++              }
++              return ptrace_active;
++      default:
++              return true;
++      }
++}
++
+ static ssize_t mem_rw(struct file *file, char __user *buf,
+                       size_t count, loff_t *ppos, int write)
+ {
+@@ -855,7 +912,9 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
+       if (!mmget_not_zero(mm))
+               goto free;
+-      flags = FOLL_FORCE | (write ? FOLL_WRITE : 0);
++      flags = write ? FOLL_WRITE : 0;
++      if (proc_mem_foll_force(file, mm))
++              flags |= FOLL_FORCE;
+       while (count > 0) {
+               size_t this_len = min_t(size_t, count, PAGE_SIZE);
+diff --git a/security/Kconfig b/security/Kconfig
+index 412e76f1575d0..a93c1a9b7c283 100644
+--- a/security/Kconfig
++++ b/security/Kconfig
+@@ -19,6 +19,38 @@ config SECURITY_DMESG_RESTRICT
+         If you are unsure how to answer this question, answer N.
++choice
++      prompt "Allow /proc/pid/mem access override"
++      default PROC_MEM_ALWAYS_FORCE
++      help
++        Traditionally /proc/pid/mem allows users to override memory
++        permissions for users like ptrace, assuming they have ptrace
++        capability.
++
++        This allows people to limit that - either never override, or
++        require actual active ptrace attachment.
++
++        Defaults to the traditional behavior (for now)
++
++config PROC_MEM_ALWAYS_FORCE
++      bool "Traditional /proc/pid/mem behavior"
++      help
++        This allows /proc/pid/mem accesses to override memory mapping
++        permissions if you have ptrace access rights.
++
++config PROC_MEM_FORCE_PTRACE
++      bool "Require active ptrace() use for access override"
++      help
++        This allows /proc/pid/mem accesses to override memory mapping
++        permissions for active ptracers like gdb.
++
++config PROC_MEM_NO_FORCE
++      bool "Never"
++      help
++        Never override memory mapping permissions
++
++endchoice
++
+ config SECURITY
+       bool "Enable different security models"
+       depends on SYSFS
+-- 
+2.43.0
+
diff --git a/queue-6.11/rcu-tasks-fix-access-non-existent-percpu-rtpcp-varia.patch b/queue-6.11/rcu-tasks-fix-access-non-existent-percpu-rtpcp-varia.patch
new file mode 100644 (file)
index 0000000..38a4931
--- /dev/null
@@ -0,0 +1,262 @@
+From 10bfe84ec789094ad5ac80a4693aba0b88eaaa16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Jul 2024 12:45:42 +0800
+Subject: rcu-tasks: Fix access non-existent percpu rtpcp variable in
+ rcu_tasks_need_gpcb()
+
+From: Zqiang <qiang.zhang1211@gmail.com>
+
+[ Upstream commit fd70e9f1d85f5323096ad313ba73f5fe3d15ea41 ]
+
+For kernels built with CONFIG_FORCE_NR_CPUS=y, the nr_cpu_ids is
+defined as NR_CPUS instead of the number of possible cpus, this
+will cause the following system panic:
+
+smpboot: Allowing 4 CPUs, 0 hotplug CPUs
+...
+setup_percpu: NR_CPUS:512 nr_cpumask_bits:512 nr_cpu_ids:512 nr_node_ids:1
+...
+BUG: unable to handle page fault for address: ffffffff9911c8c8
+Oops: 0000 [#1] PREEMPT SMP PTI
+CPU: 0 PID: 15 Comm: rcu_tasks_trace Tainted: G W
+6.6.21 #1 5dc7acf91a5e8e9ac9dcfc35bee0245691283ea6
+RIP: 0010:rcu_tasks_need_gpcb+0x25d/0x2c0
+RSP: 0018:ffffa371c00a3e60 EFLAGS: 00010082
+CR2: ffffffff9911c8c8 CR3: 000000040fa20005 CR4: 00000000001706f0
+Call Trace:
+<TASK>
+? __die+0x23/0x80
+? page_fault_oops+0xa4/0x180
+? exc_page_fault+0x152/0x180
+? asm_exc_page_fault+0x26/0x40
+? rcu_tasks_need_gpcb+0x25d/0x2c0
+? __pfx_rcu_tasks_kthread+0x40/0x40
+rcu_tasks_one_gp+0x69/0x180
+rcu_tasks_kthread+0x94/0xc0
+kthread+0xe8/0x140
+? __pfx_kthread+0x40/0x40
+ret_from_fork+0x34/0x80
+? __pfx_kthread+0x40/0x40
+ret_from_fork_asm+0x1b/0x80
+</TASK>
+
+Considering that there may be holes in the CPU numbers, use the
+maximum possible cpu number, instead of nr_cpu_ids, for configuring
+enqueue and dequeue limits.
+
+[ neeraj.upadhyay: Fix htmldocs build error reported by Stephen Rothwell ]
+
+Closes: https://lore.kernel.org/linux-input/CALMA0xaTSMN+p4xUXkzrtR5r6k7hgoswcaXx7baR_z9r5jjskw@mail.gmail.com/T/#u
+Reported-by: Zhixu Liu <zhixu.liu@gmail.com>
+Signed-off-by: Zqiang <qiang.zhang1211@gmail.com>
+Signed-off-by: Neeraj Upadhyay <neeraj.upadhyay@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/tasks.h | 82 ++++++++++++++++++++++++++++++----------------
+ 1 file changed, 53 insertions(+), 29 deletions(-)
+
+diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
+index ba3440a45b6dd..bc8429ada7a51 100644
+--- a/kernel/rcu/tasks.h
++++ b/kernel/rcu/tasks.h
+@@ -34,6 +34,7 @@ typedef void (*postgp_func_t)(struct rcu_tasks *rtp);
+  * @rtp_blkd_tasks: List of tasks blocked as readers.
+  * @rtp_exit_list: List of tasks in the latter portion of do_exit().
+  * @cpu: CPU number corresponding to this entry.
++ * @index: Index of this CPU in rtpcp_array of the rcu_tasks structure.
+  * @rtpp: Pointer to the rcu_tasks structure.
+  */
+ struct rcu_tasks_percpu {
+@@ -49,6 +50,7 @@ struct rcu_tasks_percpu {
+       struct list_head rtp_blkd_tasks;
+       struct list_head rtp_exit_list;
+       int cpu;
++      int index;
+       struct rcu_tasks *rtpp;
+ };
+@@ -76,6 +78,7 @@ struct rcu_tasks_percpu {
+  * @call_func: This flavor's call_rcu()-equivalent function.
+  * @wait_state: Task state for synchronous grace-period waits (default TASK_UNINTERRUPTIBLE).
+  * @rtpcpu: This flavor's rcu_tasks_percpu structure.
++ * @rtpcp_array: Array of pointers to rcu_tasks_percpu structure of CPUs in cpu_possible_mask.
+  * @percpu_enqueue_shift: Shift down CPU ID this much when enqueuing callbacks.
+  * @percpu_enqueue_lim: Number of per-CPU callback queues in use for enqueuing.
+  * @percpu_dequeue_lim: Number of per-CPU callback queues in use for dequeuing.
+@@ -110,6 +113,7 @@ struct rcu_tasks {
+       call_rcu_func_t call_func;
+       unsigned int wait_state;
+       struct rcu_tasks_percpu __percpu *rtpcpu;
++      struct rcu_tasks_percpu **rtpcp_array;
+       int percpu_enqueue_shift;
+       int percpu_enqueue_lim;
+       int percpu_dequeue_lim;
+@@ -182,6 +186,8 @@ module_param(rcu_task_collapse_lim, int, 0444);
+ static int rcu_task_lazy_lim __read_mostly = 32;
+ module_param(rcu_task_lazy_lim, int, 0444);
++static int rcu_task_cpu_ids;
++
+ /* RCU tasks grace-period state for debugging. */
+ #define RTGS_INIT              0
+ #define RTGS_WAIT_WAIT_CBS     1
+@@ -245,6 +251,8 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
+       int cpu;
+       int lim;
+       int shift;
++      int maxcpu;
++      int index = 0;
+       if (rcu_task_enqueue_lim < 0) {
+               rcu_task_enqueue_lim = 1;
+@@ -254,14 +262,9 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
+       }
+       lim = rcu_task_enqueue_lim;
+-      if (lim > nr_cpu_ids)
+-              lim = nr_cpu_ids;
+-      shift = ilog2(nr_cpu_ids / lim);
+-      if (((nr_cpu_ids - 1) >> shift) >= lim)
+-              shift++;
+-      WRITE_ONCE(rtp->percpu_enqueue_shift, shift);
+-      WRITE_ONCE(rtp->percpu_dequeue_lim, lim);
+-      smp_store_release(&rtp->percpu_enqueue_lim, lim);
++      rtp->rtpcp_array = kcalloc(num_possible_cpus(), sizeof(struct rcu_tasks_percpu *), GFP_KERNEL);
++      BUG_ON(!rtp->rtpcp_array);
++
+       for_each_possible_cpu(cpu) {
+               struct rcu_tasks_percpu *rtpcp = per_cpu_ptr(rtp->rtpcpu, cpu);
+@@ -273,14 +276,29 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
+               INIT_WORK(&rtpcp->rtp_work, rcu_tasks_invoke_cbs_wq);
+               rtpcp->cpu = cpu;
+               rtpcp->rtpp = rtp;
++              rtpcp->index = index;
++              rtp->rtpcp_array[index] = rtpcp;
++              index++;
+               if (!rtpcp->rtp_blkd_tasks.next)
+                       INIT_LIST_HEAD(&rtpcp->rtp_blkd_tasks);
+               if (!rtpcp->rtp_exit_list.next)
+                       INIT_LIST_HEAD(&rtpcp->rtp_exit_list);
++              maxcpu = cpu;
+       }
+-      pr_info("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d.\n", rtp->name,
+-                      data_race(rtp->percpu_enqueue_shift), data_race(rtp->percpu_enqueue_lim), rcu_task_cb_adjust);
++      rcu_task_cpu_ids = maxcpu + 1;
++      if (lim > rcu_task_cpu_ids)
++              lim = rcu_task_cpu_ids;
++      shift = ilog2(rcu_task_cpu_ids / lim);
++      if (((rcu_task_cpu_ids - 1) >> shift) >= lim)
++              shift++;
++      WRITE_ONCE(rtp->percpu_enqueue_shift, shift);
++      WRITE_ONCE(rtp->percpu_dequeue_lim, lim);
++      smp_store_release(&rtp->percpu_enqueue_lim, lim);
++
++      pr_info("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d rcu_task_cpu_ids=%d.\n",
++                      rtp->name, data_race(rtp->percpu_enqueue_shift), data_race(rtp->percpu_enqueue_lim),
++                      rcu_task_cb_adjust, rcu_task_cpu_ids);
+ }
+ // Compute wakeup time for lazy callback timer.
+@@ -348,7 +366,7 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
+                       rtpcp->rtp_n_lock_retries = 0;
+               }
+               if (rcu_task_cb_adjust && ++rtpcp->rtp_n_lock_retries > rcu_task_contend_lim &&
+-                  READ_ONCE(rtp->percpu_enqueue_lim) != nr_cpu_ids)
++                  READ_ONCE(rtp->percpu_enqueue_lim) != rcu_task_cpu_ids)
+                       needadjust = true;  // Defer adjustment to avoid deadlock.
+       }
+       // Queuing callbacks before initialization not yet supported.
+@@ -368,10 +386,10 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
+       raw_spin_unlock_irqrestore_rcu_node(rtpcp, flags);
+       if (unlikely(needadjust)) {
+               raw_spin_lock_irqsave(&rtp->cbs_gbl_lock, flags);
+-              if (rtp->percpu_enqueue_lim != nr_cpu_ids) {
++              if (rtp->percpu_enqueue_lim != rcu_task_cpu_ids) {
+                       WRITE_ONCE(rtp->percpu_enqueue_shift, 0);
+-                      WRITE_ONCE(rtp->percpu_dequeue_lim, nr_cpu_ids);
+-                      smp_store_release(&rtp->percpu_enqueue_lim, nr_cpu_ids);
++                      WRITE_ONCE(rtp->percpu_dequeue_lim, rcu_task_cpu_ids);
++                      smp_store_release(&rtp->percpu_enqueue_lim, rcu_task_cpu_ids);
+                       pr_info("Switching %s to per-CPU callback queuing.\n", rtp->name);
+               }
+               raw_spin_unlock_irqrestore(&rtp->cbs_gbl_lock, flags);
+@@ -444,6 +462,8 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
+       dequeue_limit = smp_load_acquire(&rtp->percpu_dequeue_lim);
+       for (cpu = 0; cpu < dequeue_limit; cpu++) {
++              if (!cpu_possible(cpu))
++                      continue;
+               struct rcu_tasks_percpu *rtpcp = per_cpu_ptr(rtp->rtpcpu, cpu);
+               /* Advance and accelerate any new callbacks. */
+@@ -481,7 +501,7 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
+       if (rcu_task_cb_adjust && ncbs <= rcu_task_collapse_lim) {
+               raw_spin_lock_irqsave(&rtp->cbs_gbl_lock, flags);
+               if (rtp->percpu_enqueue_lim > 1) {
+-                      WRITE_ONCE(rtp->percpu_enqueue_shift, order_base_2(nr_cpu_ids));
++                      WRITE_ONCE(rtp->percpu_enqueue_shift, order_base_2(rcu_task_cpu_ids));
+                       smp_store_release(&rtp->percpu_enqueue_lim, 1);
+                       rtp->percpu_dequeue_gpseq = get_state_synchronize_rcu();
+                       gpdone = false;
+@@ -496,7 +516,9 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
+                       pr_info("Completing switch %s to CPU-0 callback queuing.\n", rtp->name);
+               }
+               if (rtp->percpu_dequeue_lim == 1) {
+-                      for (cpu = rtp->percpu_dequeue_lim; cpu < nr_cpu_ids; cpu++) {
++                      for (cpu = rtp->percpu_dequeue_lim; cpu < rcu_task_cpu_ids; cpu++) {
++                              if (!cpu_possible(cpu))
++                                      continue;
+                               struct rcu_tasks_percpu *rtpcp = per_cpu_ptr(rtp->rtpcpu, cpu);
+                               WARN_ON_ONCE(rcu_segcblist_n_cbs(&rtpcp->cblist));
+@@ -511,30 +533,32 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
+ // Advance callbacks and invoke any that are ready.
+ static void rcu_tasks_invoke_cbs(struct rcu_tasks *rtp, struct rcu_tasks_percpu *rtpcp)
+ {
+-      int cpu;
+-      int cpunext;
+       int cpuwq;
+       unsigned long flags;
+       int len;
++      int index;
+       struct rcu_head *rhp;
+       struct rcu_cblist rcl = RCU_CBLIST_INITIALIZER(rcl);
+       struct rcu_tasks_percpu *rtpcp_next;
+-      cpu = rtpcp->cpu;
+-      cpunext = cpu * 2 + 1;
+-      if (cpunext < smp_load_acquire(&rtp->percpu_dequeue_lim)) {
+-              rtpcp_next = per_cpu_ptr(rtp->rtpcpu, cpunext);
+-              cpuwq = rcu_cpu_beenfullyonline(cpunext) ? cpunext : WORK_CPU_UNBOUND;
+-              queue_work_on(cpuwq, system_wq, &rtpcp_next->rtp_work);
+-              cpunext++;
+-              if (cpunext < smp_load_acquire(&rtp->percpu_dequeue_lim)) {
+-                      rtpcp_next = per_cpu_ptr(rtp->rtpcpu, cpunext);
+-                      cpuwq = rcu_cpu_beenfullyonline(cpunext) ? cpunext : WORK_CPU_UNBOUND;
++      index = rtpcp->index * 2 + 1;
++      if (index < num_possible_cpus()) {
++              rtpcp_next = rtp->rtpcp_array[index];
++              if (rtpcp_next->cpu < smp_load_acquire(&rtp->percpu_dequeue_lim)) {
++                      cpuwq = rcu_cpu_beenfullyonline(rtpcp_next->cpu) ? rtpcp_next->cpu : WORK_CPU_UNBOUND;
+                       queue_work_on(cpuwq, system_wq, &rtpcp_next->rtp_work);
++                      index++;
++                      if (index < num_possible_cpus()) {
++                              rtpcp_next = rtp->rtpcp_array[index];
++                              if (rtpcp_next->cpu < smp_load_acquire(&rtp->percpu_dequeue_lim)) {
++                                      cpuwq = rcu_cpu_beenfullyonline(rtpcp_next->cpu) ? rtpcp_next->cpu : WORK_CPU_UNBOUND;
++                                      queue_work_on(cpuwq, system_wq, &rtpcp_next->rtp_work);
++                              }
++                      }
+               }
+       }
+-      if (rcu_segcblist_empty(&rtpcp->cblist) || !cpu_possible(cpu))
++      if (rcu_segcblist_empty(&rtpcp->cblist))
+               return;
+       raw_spin_lock_irqsave_rcu_node(rtpcp, flags);
+       rcu_segcblist_advance(&rtpcp->cblist, rcu_seq_current(&rtp->tasks_gp_seq));
+-- 
+2.43.0
+
diff --git a/queue-6.11/rcuscale-provide-clear-error-when-async-specified-wi.patch b/queue-6.11/rcuscale-provide-clear-error-when-async-specified-wi.patch
new file mode 100644 (file)
index 0000000..2605344
--- /dev/null
@@ -0,0 +1,47 @@
+From ea919d13d6d318eb5c1c3ed9b602ff705606422b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 17:43:03 -0700
+Subject: rcuscale: Provide clear error when async specified without primitives
+
+From: Paul E. McKenney <paulmck@kernel.org>
+
+[ Upstream commit 11377947b5861fa59bf77c827e1dd7c081842cc9 ]
+
+Currently, if the rcuscale module's async module parameter is specified
+for RCU implementations that do not have async primitives such as RCU
+Tasks Rude (which now lacks a call_rcu_tasks_rude() function), there
+will be a series of splats due to calls to a NULL pointer.  This commit
+therefore warns of this situation, but switches to non-async testing.
+
+Signed-off-by: "Paul E. McKenney" <paulmck@kernel.org>
+Signed-off-by: Neeraj Upadhyay <neeraj.upadhyay@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/rcuscale.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c
+index b53a9e8f5904f..f88c75b3cea3b 100644
+--- a/kernel/rcu/rcuscale.c
++++ b/kernel/rcu/rcuscale.c
+@@ -499,7 +499,7 @@ rcu_scale_writer(void *arg)
+                       schedule_timeout_idle(torture_random(&tr) % writer_holdoff_jiffies + 1);
+               wdp = &wdpp[i];
+               *wdp = ktime_get_mono_fast_ns();
+-              if (gp_async) {
++              if (gp_async && !WARN_ON_ONCE(!cur_ops->async)) {
+ retry:
+                       if (!rhp)
+                               rhp = kmalloc(sizeof(*rhp), GFP_KERNEL);
+@@ -555,7 +555,7 @@ rcu_scale_writer(void *arg)
+                       i++;
+               rcu_scale_wait_shutdown();
+       } while (!torture_must_stop());
+-      if (gp_async) {
++      if (gp_async && cur_ops->async) {
+               cur_ops->gp_barrier();
+       }
+       writer_n_durations[me] = i_max + 1;
+-- 
+2.43.0
+
diff --git a/queue-6.11/scsi-aacraid-rearrange-order-of-struct-aac_srb_unit.patch b/queue-6.11/scsi-aacraid-rearrange-order-of-struct-aac_srb_unit.patch
new file mode 100644 (file)
index 0000000..7cbc1b6
--- /dev/null
@@ -0,0 +1,112 @@
+From ed1d435eabbde9fa16ab42dce24909d6e0aa3dc7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Jul 2024 14:57:37 -0700
+Subject: scsi: aacraid: Rearrange order of struct aac_srb_unit
+
+From: Kees Cook <kees@kernel.org>
+
+[ Upstream commit 6e5860b0ad4934baee8c7a202c02033b2631bb44 ]
+
+struct aac_srb_unit contains struct aac_srb, which contains struct sgmap,
+which ends in a (currently) "fake" (1-element) flexible array.  Converting
+this to a flexible array is needed so that runtime bounds checking won't
+think the array is fixed size (i.e. under CONFIG_FORTIFY_SOURCE=y and/or
+CONFIG_UBSAN_BOUNDS=y), as other parts of aacraid use struct sgmap as a
+flexible array.
+
+It is not legal to have a flexible array in the middle of a structure, so
+it either needs to be split up or rearranged so that it is at the end of
+the structure. Luckily, struct aac_srb_unit, which is exclusively
+consumed/updated by aac_send_safw_bmic_cmd(), does not depend on member
+ordering.
+
+The values set in the on-stack struct aac_srb_unit instance "srbu" by the
+only two callers, aac_issue_safw_bmic_identify() and
+aac_get_safw_ciss_luns(), do not contain anything in srbu.srb.sgmap.sg, and
+they both implicitly initialize srbu.srb.sgmap.count to 0 during
+memset(). For example:
+
+        memset(&srbu, 0, sizeof(struct aac_srb_unit));
+
+        srbcmd = &srbu.srb;
+        srbcmd->flags   = cpu_to_le32(SRB_DataIn);
+        srbcmd->cdb[0]  = CISS_REPORT_PHYSICAL_LUNS;
+        srbcmd->cdb[1]  = 2; /* extended reporting */
+        srbcmd->cdb[8]  = (u8)(datasize >> 8);
+        srbcmd->cdb[9]  = (u8)(datasize);
+
+        rcode = aac_send_safw_bmic_cmd(dev, &srbu, phys_luns, datasize);
+
+During aac_send_safw_bmic_cmd(), a separate srb is mapped into DMA, and has
+srbu.srb copied into it:
+
+        srb = fib_data(fibptr);
+        memcpy(srb, &srbu->srb, sizeof(struct aac_srb));
+
+Only then is srb.sgmap.count written and srb->sg populated:
+
+        srb->count              = cpu_to_le32(xfer_len);
+
+        sg64 = (struct sgmap64 *)&srb->sg;
+        sg64->count             = cpu_to_le32(1);
+        sg64->sg[0].addr[1]     = cpu_to_le32(upper_32_bits(addr));
+        sg64->sg[0].addr[0]     = cpu_to_le32(lower_32_bits(addr));
+        sg64->sg[0].count       = cpu_to_le32(xfer_len);
+
+But this is happening in the DMA memory, not in srbu.srb. An attempt to
+copy the changes back to srbu does happen:
+
+        /*
+         * Copy the updated data for other dumping or other usage if
+         * needed
+         */
+        memcpy(&srbu->srb, srb, sizeof(struct aac_srb));
+
+But this was never correct: the sg64 (3 u32s) overlap of srb.sg (2 u32s)
+always meant that srbu.srb would have held truncated information and any
+attempt to walk srbu.srb.sg.sg based on the value of srbu.srb.sg.count
+would result in attempting to parse past the end of srbu.srb.sg.sg[0] into
+srbu.srb_reply.
+
+After getting a reply from hardware, the reply is copied into
+srbu.srb_reply:
+
+        srb_reply = (struct aac_srb_reply *)fib_data(fibptr);
+        memcpy(&srbu->srb_reply, srb_reply, sizeof(struct aac_srb_reply));
+
+This has always been fixed-size, so there's no issue here. It is worth
+noting that the two callers _never check_ srbu contents -- neither
+srbu.srb nor srbu.srb_reply is examined. (They depend on the mapped
+xfer_buf instead.)
+
+Therefore, the ordering of members in struct aac_srb_unit does not matter,
+and the flexible array member can moved to the end.
+
+(Additionally, the two memcpy()s that update srbu could be entirely
+removed as they are never consumed, but I left that as-is.)
+
+Signed-off-by: Kees Cook <kees@kernel.org>
+Link: https://lore.kernel.org/r/20240711215739.208776-1-kees@kernel.org
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/aacraid/aacraid.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
+index 7d5a155073c62..9b66fa29fb05c 100644
+--- a/drivers/scsi/aacraid/aacraid.h
++++ b/drivers/scsi/aacraid/aacraid.h
+@@ -2029,8 +2029,8 @@ struct aac_srb_reply
+ };
+ struct aac_srb_unit {
+-      struct aac_srb          srb;
+       struct aac_srb_reply    srb_reply;
++      struct aac_srb          srb;
+ };
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.11/scsi-lpfc-fix-unsolicited-flogi-kref-imbalance-when-.patch b/queue-6.11/scsi-lpfc-fix-unsolicited-flogi-kref-imbalance-when-.patch
new file mode 100644 (file)
index 0000000..2aad483
--- /dev/null
@@ -0,0 +1,197 @@
+From c4c5ea7e1135b44e19d73036f0ce137e36e5cb42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jul 2024 16:15:09 -0700
+Subject: scsi: lpfc: Fix unsolicited FLOGI kref imbalance when in direct
+ attached topology
+
+From: Justin Tee <justin.tee@broadcom.com>
+
+[ Upstream commit b5c18c9dd138733c16893613345af44deadcf05e ]
+
+In direct attached topology, certain target vendors that are quick to issue
+FLOGI followed by a cable pull for more than dev_loss_tmo may result in a
+kref imbalance for the remote port ndlp object.
+
+Add an nlp_get when the defer_flogi_acc flag is set.  This is expected to
+balance the nlp_put in the defer_flogi_acc clause in the
+lpfc_issue_els_flogi() routine.  Because we need to retain the ndlp ptr,
+reorganize all of the defer_flogi_acc information into one
+lpfc_defer_flogi_acc struct.
+
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Link: https://lore.kernel.org/r/20240726231512.92867-6-justintee8345@gmail.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc.h         | 12 ++++++---
+ drivers/scsi/lpfc/lpfc_els.c     | 46 +++++++++++++++++++-------------
+ drivers/scsi/lpfc/lpfc_hbadisc.c | 11 ++++++--
+ 3 files changed, 46 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 7c147d6ea8a8f..e5a9c5a323f8b 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -306,6 +306,14 @@ struct lpfc_stats {
+ struct lpfc_hba;
++/* Data structure to keep withheld FLOGI_ACC information */
++struct lpfc_defer_flogi_acc {
++      bool flag;
++      u16 rx_id;
++      u16 ox_id;
++      struct lpfc_nodelist *ndlp;
++
++};
+ #define LPFC_VMID_TIMER   300 /* timer interval in seconds */
+@@ -1430,9 +1438,7 @@ struct lpfc_hba {
+       uint16_t vlan_id;
+       struct list_head fcf_conn_rec_list;
+-      bool defer_flogi_acc_flag;
+-      uint16_t defer_flogi_acc_rx_id;
+-      uint16_t defer_flogi_acc_ox_id;
++      struct lpfc_defer_flogi_acc defer_flogi_acc;
+       spinlock_t ct_ev_lock; /* synchronize access to ct_ev_waiters */
+       struct list_head ct_ev_waiters;
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index 929cbfc95163b..8c0926ffee1bf 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -1390,7 +1390,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+       phba->link_flag &= ~LS_EXTERNAL_LOOPBACK;
+       /* Check for a deferred FLOGI ACC condition */
+-      if (phba->defer_flogi_acc_flag) {
++      if (phba->defer_flogi_acc.flag) {
+               /* lookup ndlp for received FLOGI */
+               ndlp = lpfc_findnode_did(vport, 0);
+               if (!ndlp)
+@@ -1404,34 +1404,38 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+               if (phba->sli_rev == LPFC_SLI_REV4) {
+                       bf_set(wqe_ctxt_tag,
+                              &defer_flogi_acc.wqe.xmit_els_rsp.wqe_com,
+-                             phba->defer_flogi_acc_rx_id);
++                             phba->defer_flogi_acc.rx_id);
+                       bf_set(wqe_rcvoxid,
+                              &defer_flogi_acc.wqe.xmit_els_rsp.wqe_com,
+-                             phba->defer_flogi_acc_ox_id);
++                             phba->defer_flogi_acc.ox_id);
+               } else {
+                       icmd = &defer_flogi_acc.iocb;
+-                      icmd->ulpContext = phba->defer_flogi_acc_rx_id;
++                      icmd->ulpContext = phba->defer_flogi_acc.rx_id;
+                       icmd->unsli3.rcvsli3.ox_id =
+-                              phba->defer_flogi_acc_ox_id;
++                              phba->defer_flogi_acc.ox_id;
+               }
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                "3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
+                                " ox_id: x%x, hba_flag x%lx\n",
+-                               phba->defer_flogi_acc_rx_id,
+-                               phba->defer_flogi_acc_ox_id, phba->hba_flag);
++                               phba->defer_flogi_acc.rx_id,
++                               phba->defer_flogi_acc.ox_id, phba->hba_flag);
+               /* Send deferred FLOGI ACC */
+               lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, &defer_flogi_acc,
+                                ndlp, NULL);
+-              phba->defer_flogi_acc_flag = false;
+-              vport->fc_myDID = did;
++              phba->defer_flogi_acc.flag = false;
+-              /* Decrement ndlp reference count to indicate the node can be
+-               * released when other references are removed.
++              /* Decrement the held ndlp that was incremented when the
++               * deferred flogi acc flag was set.
+                */
+-              lpfc_nlp_put(ndlp);
++              if (phba->defer_flogi_acc.ndlp) {
++                      lpfc_nlp_put(phba->defer_flogi_acc.ndlp);
++                      phba->defer_flogi_acc.ndlp = NULL;
++              }
++
++              vport->fc_myDID = did;
+       }
+       return 0;
+@@ -8454,9 +8458,9 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+       /* Defer ACC response until AFTER we issue a FLOGI */
+       if (!test_bit(HBA_FLOGI_ISSUED, &phba->hba_flag)) {
+-              phba->defer_flogi_acc_rx_id = bf_get(wqe_ctxt_tag,
++              phba->defer_flogi_acc.rx_id = bf_get(wqe_ctxt_tag,
+                                                    &wqe->xmit_els_rsp.wqe_com);
+-              phba->defer_flogi_acc_ox_id = bf_get(wqe_rcvoxid,
++              phba->defer_flogi_acc.ox_id = bf_get(wqe_rcvoxid,
+                                                    &wqe->xmit_els_rsp.wqe_com);
+               vport->fc_myDID = did;
+@@ -8464,11 +8468,17 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                "3344 Deferring FLOGI ACC: rx_id: x%x,"
+                                " ox_id: x%x, hba_flag x%lx\n",
+-                               phba->defer_flogi_acc_rx_id,
+-                               phba->defer_flogi_acc_ox_id, phba->hba_flag);
++                               phba->defer_flogi_acc.rx_id,
++                               phba->defer_flogi_acc.ox_id, phba->hba_flag);
+-              phba->defer_flogi_acc_flag = true;
++              phba->defer_flogi_acc.flag = true;
++              /* This nlp_get is paired with nlp_puts that reset the
++               * defer_flogi_acc.flag back to false.  We need to retain
++               * a kref on the ndlp until the deferred FLOGI ACC is
++               * processed or cancelled.
++               */
++              phba->defer_flogi_acc.ndlp = lpfc_nlp_get(ndlp);
+               return 0;
+       }
+@@ -10504,7 +10514,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+               lpfc_els_rcv_flogi(vport, elsiocb, ndlp);
+               /* retain node if our response is deferred */
+-              if (phba->defer_flogi_acc_flag)
++              if (phba->defer_flogi_acc.flag)
+                       break;
+               if (newnode)
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index f21c5993e8d72..35c9181c6608a 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -1255,7 +1255,14 @@ lpfc_linkdown(struct lpfc_hba *phba)
+       lpfc_scsi_dev_block(phba);
+       offline = pci_channel_offline(phba->pcidev);
+-      phba->defer_flogi_acc_flag = false;
++      /* Decrement the held ndlp if there is a deferred flogi acc */
++      if (phba->defer_flogi_acc.flag) {
++              if (phba->defer_flogi_acc.ndlp) {
++                      lpfc_nlp_put(phba->defer_flogi_acc.ndlp);
++                      phba->defer_flogi_acc.ndlp = NULL;
++              }
++      }
++      phba->defer_flogi_acc.flag = false;
+       /* Clear external loopback plug detected flag */
+       phba->link_flag &= ~LS_EXTERNAL_LOOPBACK;
+@@ -1377,7 +1384,7 @@ lpfc_linkup_port(struct lpfc_vport *vport)
+               (vport != phba->pport))
+               return;
+-      if (phba->defer_flogi_acc_flag) {
++      if (phba->defer_flogi_acc.flag) {
+               clear_bit(FC_ABORT_DISCOVERY, &vport->fc_flag);
+               clear_bit(FC_RSCN_MODE, &vport->fc_flag);
+               clear_bit(FC_NLP_MORE, &vport->fc_flag);
+-- 
+2.43.0
+
diff --git a/queue-6.11/scsi-lpfc-update-prlo-handling-in-direct-attached-to.patch b/queue-6.11/scsi-lpfc-update-prlo-handling-in-direct-attached-to.patch
new file mode 100644 (file)
index 0000000..02feb58
--- /dev/null
@@ -0,0 +1,113 @@
+From 28282ddbc1365f47e06853b76c43b0864c15b292 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jul 2024 16:15:10 -0700
+Subject: scsi: lpfc: Update PRLO handling in direct attached topology
+
+From: Justin Tee <justin.tee@broadcom.com>
+
+[ Upstream commit 1f0f7679ad8942f810b0f19ee9cf098c3502d66a ]
+
+A kref imbalance occurs when handling an unsolicited PRLO in direct
+attached topology.
+
+Rework PRLO rcv handling when in MAPPED state.  Save the state that we were
+handling a PRLO by setting nlp_last_elscmd to ELS_CMD_PRLO.  Then in the
+lpfc_cmpl_els_logo_acc() completion routine, manually restart discovery.
+By issuing the PLOGI, which nlp_gets, before nlp_put at the end of the
+lpfc_cmpl_els_logo_acc() routine, we are saving us from a final nlp_put.
+And, we are still allowing the unreg_rpi to happen.
+
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Link: https://lore.kernel.org/r/20240726231512.92867-7-justintee8345@gmail.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_els.c       | 27 ++++++++++++++++-----------
+ drivers/scsi/lpfc/lpfc_nportdisc.c | 22 ++++++++++++++++++++--
+ 2 files changed, 36 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index 8c0926ffee1bf..e27f5d955edb4 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -5244,9 +5244,10 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+       /* ACC to LOGO completes to NPort <nlp_DID> */
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                        "0109 ACC to LOGO completes to NPort x%x refcnt %d "
+-                       "Data: x%x x%x x%x\n",
+-                       ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag,
+-                       ndlp->nlp_state, ndlp->nlp_rpi);
++                       "last els x%x Data: x%x x%x x%x\n",
++                       ndlp->nlp_DID, kref_read(&ndlp->kref),
++                       ndlp->nlp_last_elscmd, ndlp->nlp_flag, ndlp->nlp_state,
++                       ndlp->nlp_rpi);
+       /* This clause allows the LOGO ACC to complete and free resources
+        * for the Fabric Domain Controller.  It does deliberately skip
+@@ -5258,18 +5259,22 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+               goto out;
+       if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
+-              /* If PLOGI is being retried, PLOGI completion will cleanup the
+-               * node. The NLP_NPR_2B_DISC flag needs to be retained to make
+-               * progress on nodes discovered from last RSCN.
+-               */
+-              if ((ndlp->nlp_flag & NLP_DELAY_TMO) &&
+-                  (ndlp->nlp_last_elscmd == ELS_CMD_PLOGI))
+-                      goto out;
+-
+               if (ndlp->nlp_flag & NLP_RPI_REGISTERED)
+                       lpfc_unreg_rpi(vport, ndlp);
++              /* If came from PRLO, then PRLO_ACC is done.
++               * Start rediscovery now.
++               */
++              if (ndlp->nlp_last_elscmd == ELS_CMD_PRLO) {
++                      spin_lock_irq(&ndlp->lock);
++                      ndlp->nlp_flag |= NLP_NPR_2B_DISC;
++                      spin_unlock_irq(&ndlp->lock);
++                      ndlp->nlp_prev_state = ndlp->nlp_state;
++                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
++                      lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
++              }
+       }
++
+  out:
+       /*
+        * The driver received a LOGO from the rport and has ACK'd it.
+diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
+index f6a53446e57f9..4574716c8764f 100644
+--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
+@@ -2652,8 +2652,26 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+       /* flush the target */
+       lpfc_sli_abort_iocb(vport, ndlp->nlp_sid, 0, LPFC_CTX_TGT);
+-      /* Treat like rcv logo */
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
++      /* Send PRLO_ACC */
++      spin_lock_irq(&ndlp->lock);
++      ndlp->nlp_flag |= NLP_LOGO_ACC;
++      spin_unlock_irq(&ndlp->lock);
++      lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
++
++      /* Save ELS_CMD_PRLO as the last elscmd and then set to NPR.
++       * lpfc_cmpl_els_logo_acc is expected to restart discovery.
++       */
++      ndlp->nlp_last_elscmd = ELS_CMD_PRLO;
++      ndlp->nlp_prev_state = ndlp->nlp_state;
++
++      lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_ELS | LOG_DISCOVERY,
++                       "3422 DID x%06x nflag x%x lastels x%x ref cnt %u\n",
++                       ndlp->nlp_DID, ndlp->nlp_flag,
++                       ndlp->nlp_last_elscmd,
++                       kref_read(&ndlp->kref));
++
++      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++
+       return ndlp->nlp_state;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/scsi-lpfc-validate-hdwq-pointers-before-dereferencin.patch b/queue-6.11/scsi-lpfc-validate-hdwq-pointers-before-dereferencin.patch
new file mode 100644 (file)
index 0000000..7a1486f
--- /dev/null
@@ -0,0 +1,94 @@
+From 16ab1eb4cc96c42e610f721d8974d8e701de8316 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jul 2024 16:15:07 -0700
+Subject: scsi: lpfc: Validate hdwq pointers before dereferencing in
+ reset/errata paths
+
+From: Justin Tee <justin.tee@broadcom.com>
+
+[ Upstream commit 2be1d4f11944cd6283cb97268b3e17c4424945ca ]
+
+When the HBA is undergoing a reset or is handling an errata event, NULL ptr
+dereference crashes may occur in routines such as
+lpfc_sli_flush_io_rings(), lpfc_dev_loss_tmo_callbk(), or
+lpfc_abort_handler().
+
+Add NULL ptr checks before dereferencing hdwq pointers that may have been
+freed due to operations colliding with a reset or errata event handler.
+
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Link: https://lore.kernel.org/r/20240726231512.92867-4-justintee8345@gmail.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_hbadisc.c |  3 ++-
+ drivers/scsi/lpfc/lpfc_scsi.c    | 13 +++++++++++--
+ drivers/scsi/lpfc/lpfc_sli.c     | 11 +++++++++++
+ 3 files changed, 24 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index 6943f6c6395c4..f21c5993e8d72 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -175,7 +175,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
+                        ndlp->nlp_state, ndlp->fc4_xpt_flags);
+       /* Don't schedule a worker thread event if the vport is going down. */
+-      if (test_bit(FC_UNLOADING, &vport->load_flag)) {
++      if (test_bit(FC_UNLOADING, &vport->load_flag) ||
++          !test_bit(HBA_SETUP, &phba->hba_flag)) {
+               spin_lock_irqsave(&ndlp->lock, iflags);
+               ndlp->rport = NULL;
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 9f0b59672e191..0eaede8275dac 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -5555,11 +5555,20 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+       iocb = &lpfc_cmd->cur_iocbq;
+       if (phba->sli_rev == LPFC_SLI_REV4) {
+-              pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring;
+-              if (!pring_s4) {
++              /* if the io_wq & pring are gone, the port was reset. */
++              if (!phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq ||
++                  !phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring) {
++                      lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
++                                       "2877 SCSI Layer I/O Abort Request "
++                                       "IO CMPL Status x%x ID %d LUN %llu "
++                                       "HBA_SETUP %d\n", FAILED,
++                                       cmnd->device->id,
++                                       (u64)cmnd->device->lun,
++                                       test_bit(HBA_SETUP, &phba->hba_flag));
+                       ret = FAILED;
+                       goto out_unlock_hba;
+               }
++              pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring;
+               spin_lock(&pring_s4->ring_lock);
+       }
+       /* the command is in process of being cancelled */
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index 88debef2fb6db..7dc34c71eb78c 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -4687,6 +4687,17 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba)
+       /* Look on all the FCP Rings for the iotag */
+       if (phba->sli_rev >= LPFC_SLI_REV4) {
+               for (i = 0; i < phba->cfg_hdw_queue; i++) {
++                      if (!phba->sli4_hba.hdwq ||
++                          !phba->sli4_hba.hdwq[i].io_wq) {
++                              lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
++                                              "7777 hdwq's deleted %lx "
++                                              "%lx %x %x\n",
++                                              phba->pport->load_flag,
++                                              phba->hba_flag,
++                                              phba->link_state,
++                                              phba->sli.sli_flag);
++                              return;
++                      }
+                       pring = phba->sli4_hba.hdwq[i].io_wq->pring;
+                       spin_lock_irq(&pring->ring_lock);
+-- 
+2.43.0
+
diff --git a/queue-6.11/scsi-ncr5380-initialize-buffer-for-msg-in-and-status.patch b/queue-6.11/scsi-ncr5380-initialize-buffer-for-msg-in-and-status.patch
new file mode 100644 (file)
index 0000000..acf6eb9
--- /dev/null
@@ -0,0 +1,50 @@
+From 0826684be5ec9e62d094728d97490a0e5f96dae5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 13:36:28 +1000
+Subject: scsi: NCR5380: Initialize buffer for MSG IN and STATUS transfers
+
+From: Finn Thain <fthain@linux-m68k.org>
+
+[ Upstream commit 1c71065df2df693d208dd32758171c1dece66341 ]
+
+Following an incomplete transfer in MSG IN phase, the driver would not
+notice the problem and would make use of invalid data. Initialize 'tmp'
+appropriately and bail out if no message was received. For STATUS phase,
+preserve the existing status code unless a new value was transferred.
+
+Tested-by: Stan Johnson <userm57@yahoo.com>
+Signed-off-by: Finn Thain <fthain@linux-m68k.org>
+Link: https://lore.kernel.org/r/52e02a8812ae1a2d810d7f9f7fd800c3ccc320c4.1723001788.git.fthain@linux-m68k.org
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/NCR5380.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
+index 00e245173320c..4fcb73b727aa5 100644
+--- a/drivers/scsi/NCR5380.c
++++ b/drivers/scsi/NCR5380.c
+@@ -1807,8 +1807,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
+                               return;
+                       case PHASE_MSGIN:
+                               len = 1;
++                              tmp = 0xff;
+                               data = &tmp;
+                               NCR5380_transfer_pio(instance, &phase, &len, &data, 0);
++                              if (tmp == 0xff)
++                                      break;
+                               ncmd->message = tmp;
+                               switch (tmp) {
+@@ -1996,6 +1999,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
+                               break;
+                       case PHASE_STATIN:
+                               len = 1;
++                              tmp = ncmd->status;
+                               data = &tmp;
+                               NCR5380_transfer_pio(instance, &phase, &len, &data, 0);
+                               ncmd->status = tmp;
+-- 
+2.43.0
+
diff --git a/queue-6.11/scsi-smartpqi-add-new-controller-pci-ids.patch b/queue-6.11/scsi-smartpqi-add-new-controller-pci-ids.patch
new file mode 100644 (file)
index 0000000..bae6b78
--- /dev/null
@@ -0,0 +1,193 @@
+From 4082cb2496ee9853f1f8e1b4758694df3d9b4960 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Jul 2024 14:47:00 -0500
+Subject: scsi: smartpqi: Add new controller PCI IDs
+
+From: David Strahan <David.Strahan@microchip.com>
+
+[ Upstream commit 0e21e73384d324f75ea16f3d622cfc433fa6209b ]
+
+All PCI ID entries in hex.
+
+Add new inagile PCI IDs:
+                                             VID  / DID  / SVID / SDID
+                                             ----   ----   ----   ----
+            SMART-HBA 8242-24i               9005 / 028f / 1ff9 / 0045
+            RAID 8236-16i                    9005 / 028f / 1ff9 / 0046
+            RAID 8240-24i                    9005 / 028f / 1ff9 / 0047
+            SMART-HBA 8238-16i               9005 / 028f / 1ff9 / 0048
+            PM8222-SHBA                      9005 / 028f / 1ff9 / 004a
+            RAID PM8204-2GB                  9005 / 028f / 1ff9 / 004b
+            RAID PM8204-4GB                  9005 / 028f / 1ff9 / 004c
+            PM8222-HBA                       9005 / 028f / 1ff9 / 004f
+            MT0804M6R                        9005 / 028f / 1ff9 / 0051
+            MT0801M6E                        9005 / 028f / 1ff9 / 0052
+            MT0808M6R                        9005 / 028f / 1ff9 / 0053
+            MT0800M6H                        9005 / 028f / 1ff9 / 0054
+            RS0800M5H24i                     9005 / 028f / 1ff9 / 006b
+            RS0800M5E8i                      9005 / 028f / 1ff9 / 006c
+            RS0800M5H8i                      9005 / 028f / 1ff9 / 006d
+            RS0804M5R16i                     9005 / 028f / 1ff9 / 006f
+            RS0800M5E24i                     9005 / 028f / 1ff9 / 0070
+            RS0800M5H16i                     9005 / 028f / 1ff9 / 0071
+            RS0800M5E16i                     9005 / 028f / 1ff9 / 0072
+            RT0800M7E                        9005 / 028f / 1ff9 / 0086
+            RT0800M7H                        9005 / 028f / 1ff9 / 0087
+            RT0804M7R                        9005 / 028f / 1ff9 / 0088
+            RT0808M7R                        9005 / 028f / 1ff9 / 0089
+            RT1608M6R16i                     9005 / 028f / 1ff9 / 00a1
+
+Add new h3c pci_id:
+                                             VID  / DID  / SVID / SDID
+                                             ----   ----   ----   ----
+            UN RAID P4408-Mr-2               9005 / 028f / 193d / 1110
+
+Add new powerleader pci ids:
+                                             VID  / DID  / SVID / SDID
+                                             ----   ----   ----   ----
+            PL SmartROC PM8204               9005 / 028f / 1f3a / 0104
+
+Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
+Reviewed-by: Scott Teel <scott.teel@microchip.com>
+Reviewed-by: Mike McGowen <mike.mcgowen@microchip.com>
+Signed-off-by: David Strahan <David.Strahan@microchip.com>
+Signed-off-by: Don Brace <don.brace@microchip.com>
+Link: https://lore.kernel.org/r/20240711194704.982400-2-don.brace@microchip.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 104 ++++++++++++++++++++++++++
+ 1 file changed, 104 insertions(+)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index c1524fb334eb5..02d16fddd3123 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -9456,6 +9456,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x193d, 0x110b)
+       },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x193d, 0x1110)
++      },
+       {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x193d, 0x8460)
+@@ -9572,6 +9576,14 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x1bd4, 0x0089)
+       },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x00a1)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1f3a, 0x0104)
++      },
+       {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x19e5, 0xd227)
+@@ -10164,6 +10176,98 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x1137, 0x02fa)
+       },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0045)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0046)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0047)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0048)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x004a)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x004b)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x004c)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x004f)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0051)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0052)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0053)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0054)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x006b)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x006c)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x006d)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x006f)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0070)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0071)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0072)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0086)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0087)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0088)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x0089)
++      },
+       {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                               0x1e93, 0x1000)
+-- 
+2.43.0
+
diff --git a/queue-6.11/scsi-smartpqi-add-new-controller-pci-ids.patch-30880 b/queue-6.11/scsi-smartpqi-add-new-controller-pci-ids.patch-30880
new file mode 100644 (file)
index 0000000..a993e56
--- /dev/null
@@ -0,0 +1,99 @@
+From ed6602e8ecfd214358cfb718e3d863d38677533e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 13:54:58 -0500
+Subject: scsi: smartpqi: add new controller PCI IDs
+
+From: David Strahan <David.Strahan@microchip.com>
+
+[ Upstream commit dbc39b84540f746cc814e69b21e53e6d3e12329a ]
+
+All PCI ID entries in Hex.
+
+Add new cisco pci ids:
+                                             VID  / DID  / SVID / SDID
+                                             ----   ----   ----   ----
+                                             9005   028f   1137   02fe
+                                             9005   028f   1137   02ff
+                                             9005   028f   1137   0300
+
+Add new h3c pci ids:
+                                             VID  / DID  / SVID / SDID
+                                             ----   ----   ----   ----
+                                             9005   028f   193d   0462
+                                             9005   028f   193d   8462
+
+Add new ieit pci ids:
+                                             VID  / DID  / SVID / SDID
+                                             ----   ----   ----   ----
+                                             9005   028f   1ff9   00a3
+
+Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
+Reviewed-by: Mike McGowen <mike.mcgowen@microchip.com>
+Signed-off-by: David Strahan <David.Strahan@microchip.com>
+Signed-off-by: Don Brace <don.brace@microchip.com>
+Link: https://lore.kernel.org/r/20240827185501.692804-5-don.brace@microchip.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index a4719af88718e..4230714e5f3a1 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -9428,6 +9428,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x152d, 0x8a37)
+       },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x193d, 0x0462)
++      },
+       {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x193d, 0x1104)
+@@ -9468,6 +9472,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x193d, 0x8461)
+       },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x193d, 0x8462)
++      },
+       {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x193d, 0xc460)
+@@ -10176,6 +10184,18 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x1137, 0x02fa)
+       },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1137, 0x02fe)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1137, 0x02ff)
++      },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1137, 0x0300)
++      },
+       {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x1ff9, 0x0045)
+@@ -10352,6 +10372,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              0x1f51, 0x1045)
+       },
++      {
++              PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
++                             0x1ff9, 0x00a3)
++      },
+       {
+               PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+                              PCI_ANY_ID, PCI_ANY_ID)
+-- 
+2.43.0
+
diff --git a/queue-6.11/scsi-smartpqi-correct-stream-detection.patch b/queue-6.11/scsi-smartpqi-correct-stream-detection.patch
new file mode 100644 (file)
index 0000000..178fc4a
--- /dev/null
@@ -0,0 +1,50 @@
+From 3a07e28b054a759bdf1d7020bf1fab60fbba5d52 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 13:54:56 -0500
+Subject: scsi: smartpqi: correct stream detection
+
+From: Mahesh Rajashekhara <mahesh.rajashekhara@microchip.com>
+
+[ Upstream commit 4c76114932d1d6fad2e72823e7898a3c960cf2a7 ]
+
+Correct stream detection by initializing the structure
+pqi_scsi_dev_raid_map_data to 0s.
+
+When the OS issues SCSI READ commands, the driver erroneously considers
+them as SCSI WRITES. If they are identified as sequential IOs, the driver
+then submits those requests via the RAID path instead of the AIO path.
+
+The 'is_write' flag might be set for SCSI READ commands also.  The driver
+may interpret SCSI READ commands as SCSI WRITE commands, resulting in IOs
+being submitted through the RAID path.
+
+Note: This does not cause data corruption.
+
+Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
+Reviewed-by: Scott Teel <scott.teel@microchip.com>
+Reviewed-by: Mike McGowen <mike.mcgowen@microchip.com>
+Signed-off-by: Mahesh Rajashekhara <mahesh.rajashekhara@microchip.com>
+Signed-off-by: Don Brace <don.brace@microchip.com>
+Link: https://lore.kernel.org/r/20240827185501.692804-3-don.brace@microchip.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index 02d16fddd3123..a4719af88718e 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -5917,7 +5917,7 @@ static bool pqi_is_parity_write_stream(struct pqi_ctrl_info *ctrl_info,
+       int rc;
+       struct pqi_scsi_dev *device;
+       struct pqi_stream_data *pqi_stream_data;
+-      struct pqi_scsi_dev_raid_map_data rmd;
++      struct pqi_scsi_dev_raid_map_data rmd = { 0 };
+       if (!ctrl_info->enable_stream_detection)
+               return false;
+-- 
+2.43.0
+
diff --git a/queue-6.11/selftests-bpf-fix-uprobe.path-leak-in-bpf_testmod.patch b/queue-6.11/selftests-bpf-fix-uprobe.path-leak-in-bpf_testmod.patch
new file mode 100644 (file)
index 0000000..712707e
--- /dev/null
@@ -0,0 +1,35 @@
+From a1361456651afda442315bd463ae01bf168b39c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 15:27:24 +0200
+Subject: selftests/bpf: fix uprobe.path leak in bpf_testmod
+
+From: Jiri Olsa <olsajiri@gmail.com>
+
+[ Upstream commit db61e6a4eee5a7884b2cafeaf407895f253bbaa7 ]
+
+testmod_unregister_uprobe() forgets to path_put(&uprobe.path).
+
+Signed-off-by: Jiri Olsa <olsajiri@gmail.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20240801132724.GA8791@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
+index fd28c1157bd3d..72f565af4f829 100644
+--- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
++++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
+@@ -477,6 +477,7 @@ static void testmod_unregister_uprobe(void)
+       if (uprobe.offset) {
+               uprobe_unregister(d_real_inode(uprobe.path.dentry),
+                                 uprobe.offset, &uprobe.consumer);
++              path_put(&uprobe.path);
+               uprobe.offset = 0;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.11/selftests-nolibc-avoid-passing-null-to-printf-s.patch b/queue-6.11/selftests-nolibc-avoid-passing-null-to-printf-s.patch
new file mode 100644 (file)
index 0000000..47a91b1
--- /dev/null
@@ -0,0 +1,52 @@
+From b1fc6bfdf11212de38eff0c344da59a82ef84a34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 23:51:44 +0200
+Subject: selftests/nolibc: avoid passing NULL to printf("%s")
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit f1a58f61d88642ae1e6e97e9d72d73bc70a93cb8 ]
+
+Clang on higher optimization levels detects that NULL is passed to
+printf("%s") and warns about it.
+While printf() from nolibc gracefully handles that NULL,
+it is undefined behavior as per POSIX, so the warning is reasonable.
+Avoid the warning by transforming NULL into a non-NULL placeholder.
+
+Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
+Acked-by: Willy Tarreau <w@1wt.eu>
+Link: https://lore.kernel.org/r/20240807-nolibc-llvm-v2-8-c20f2f5fc7c2@weissschuh.net
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/nolibc/nolibc-test.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
+index 093d0512f4c57..8cbb51dca0cd6 100644
+--- a/tools/testing/selftests/nolibc/nolibc-test.c
++++ b/tools/testing/selftests/nolibc/nolibc-test.c
+@@ -542,7 +542,7 @@ int expect_strzr(const char *expr, int llen)
+ {
+       int ret = 0;
+-      llen += printf(" = <%s> ", expr);
++      llen += printf(" = <%s> ", expr ? expr : "(null)");
+       if (expr) {
+               ret = 1;
+               result(llen, FAIL);
+@@ -561,7 +561,7 @@ int expect_strnz(const char *expr, int llen)
+ {
+       int ret = 0;
+-      llen += printf(" = <%s> ", expr);
++      llen += printf(" = <%s> ", expr ? expr : "(null)");
+       if (!expr) {
+               ret = 1;
+               result(llen, FAIL);
+-- 
+2.43.0
+
index e4ae7ef3cce2d7c4bdc98615f1c826bef85924fe..5023c24c0c590d30473624fe5a4cd105dc6fa624 100644 (file)
@@ -81,3 +81,234 @@ drm-amd-display-disable-replay-if-vrr-capability-is-.patch
 drm-amd-display-fix-vrr-cannot-enable.patch
 drm-amd-display-re-enable-panel-replay-feature.patch
 e1000e-avoid-failing-the-system-during-pm_suspend.patch
+l2tp-prevent-possible-tunnel-refcount-underflow.patch
+wifi-ath9k-fix-possible-integer-overflow-in-ath9k_ge.patch
+wifi-rtw89-avoid-to-add-interface-to-list-twice-when.patch
+wifi-ath9k_htc-use-__skb_set_length-for-resetting-ur.patch
+intel_idle-disable-promotion-to-c1e-on-jasper-lake-a.patch
+crypto-x86-sha256-add-parentheses-around-macros-sing.patch
+crypto-octeontx-fix-authenc-setkey.patch
+crypto-octeontx2-fix-authenc-setkey.patch
+ice-adjust-over-allocation-of-memory-in-ice_sched_ad.patch
+wifi-iwlwifi-mvm-fix-a-race-in-scan-abort-flow.patch
+wifi-iwlwifi-mvm-drop-wrong-sta-selection-in-tx.patch
+wifi-cfg80211-set-correct-chandef-when-starting-cac.patch
+net-xen-netback-prevent-uaf-in-xenvif_flush_hash.patch
+net-hisilicon-hip04-fix-of-node-leak-in-probe.patch
+net-hisilicon-hns_dsaf_mac-fix-of-node-leak-in-hns_m.patch
+net-hisilicon-hns_mdio-fix-of-node-leak-in-probe.patch
+acpi-pad-fix-crash-in-exit_round_robin.patch
+acpica-fix-memory-leak-if-acpi_ps_get_next_namepath-.patch
+acpica-fix-memory-leak-if-acpi_ps_get_next_field-fai.patch
+exec-don-t-warn-for-racy-path_noexec-check.patch
+fs-inode-prevent-dump_mapping-accessing-invalid-dent.patch
+acpi-resource-skip-irq-override-on-asus-vivobook-go-.patch
+wifi-mt76-mt7915-disable-tx-worker-during-tx-ba-sess.patch
+net-sched-consistently-use-rcu_replace_pointer-in-ta.patch
+bluetooth-btusb-add-realtek-rtl8852c-support-id-0x04.patch
+bluetooth-btrtl-set-msft-ext-address-filter-quirk-fo.patch
+acpi-video-add-force_vendor-quirk-for-panasonic-toug.patch
+acpi-cppc-add-support-for-setting-epp-register-in-ff.patch
+blk_iocost-fix-more-out-of-bound-shifts.patch
+btrfs-don-t-readahead-the-relocation-inode-on-rst.patch
+wifi-ath12k-fix-array-out-of-bound-access-in-soc-sta.patch
+wifi-ath11k-fix-array-out-of-bound-access-in-soc-sta.patch
+wifi-rtw88-select-want_dev_coredump.patch
+l2tp-free-sessions-using-rcu.patch
+l2tp-use-rcu-list-add-del-when-updating-lists.patch
+wifi-rtw89-885xb-reset-idmem-mode-to-prevent-downloa.patch
+acpi-ec-do-not-release-locks-during-operation-region.patch
+acpica-check-null-return-of-acpi_allocate_zeroed-in-.patch
+tipc-guard-against-string-buffer-overrun.patch
+net-skbuff-sprinkle-more-__gfp_nowarn-on-ingress-all.patch
+net-mvpp2-increase-size-of-queue_name-buffer.patch
+bnxt_en-extend-maximum-length-of-version-string-by-1.patch
+ipv4-check-in_dev-earlier-for-ioctl-siocsifaddr.patch
+wifi-rtw89-correct-base-ht-rate-mask-for-firmware.patch
+netfilter-nf_tables-do-not-remove-elements-if-set-ba.patch
+ipv4-mask-upper-dscp-bits-and-ecn-bits-in-netlink_fi.patch
+nvme-keyring-restrict-match-length-for-version-1-ide.patch
+nvme-tcp-sanitize-tls-key-handling.patch
+nvme-tcp-check-for-invalidated-or-revoked-key.patch
+net-atlantic-avoid-warning-about-potential-string-tr.patch
+crypto-simd-do-not-call-crypto_alloc_tfm-during-regi.patch
+netpoll-ensure-clean-state-on-setup-failures.patch
+tcp-avoid-reusing-fin_wait2-when-trying-to-find-port.patch
+wifi-iwlwifi-mvm-use-correct-key-iteration.patch
+wifi-iwlwifi-allow-only-cn-mcc-from-wrdd.patch
+wifi-iwlwifi-mvm-avoid-null-pointer-dereference.patch
+virt-sev-guest-ensure-the-snp-guest-messages-do-not-.patch
+wifi-mac80211-fix-rcu-list-iterations.patch
+acpica-iasl-handle-empty-connection_node.patch
+proc-add-config-param-to-block-forcing-mem-writes.patch
+vfs-use-rcu-in-ilookup.patch
+drivers-perf-arm_spe-use-perf_allow_kernel-for-permi.patch
+nvme-fix-metadata-handling-in-nvme-passthrough.patch
+can-netlink-avoid-call-to-do_set_data_bittiming-call.patch
+netdev-genl-set-extack-and-fix-error-on-napi-get.patch
+wifi-wilc1000-do-not-operate-uninitialized-hardware-.patch
+block-fix-integer-overflow-in-blksecdiscard.patch
+cpufreq-amd-pstate-add-check-for-cpufreq_cpu_get-s-r.patch
+cpufreq-loongson3-use-raw_smp_processor_id-in-do_ser.patch
+arm64-trans_pgd-mark-ptes-entries-as-valid-to-avoid-.patch
+net-phy-check-for-read-errors-in-siocgmiireg.patch
+wifi-rtw89-avoid-reading-out-of-bounds-when-loading-.patch
+x86-bugs-add-missing-no_ssb-flag.patch
+x86-bugs-fix-handling-when-srso-mitigation-is-disabl.patch
+net-napi-prevent-overflow-of-napi_defer_hard_irqs.patch
+crypto-hisilicon-fix-missed-error-branch.patch
+wifi-mt76-mt7915-add-dummy-hw-offload-of-ieee-802.11.patch
+wifi-mt76-mt7915-hold-dev-mt76.mutex-while-disabling.patch
+wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch
+netfs-cancel-dirty-folios-that-have-no-storage-desti.patch
+nfp-use-irqf_no_autoen-flag-in-request_irq.patch
+alsa-usb-audio-add-input-value-sanity-checks-for-sta.patch
+x86-ioapic-handle-allocation-failures-gracefully.patch
+x86-apic-remove-logical-destination-mode-for-64-bit.patch
+alsa-usb-audio-support-multiple-control-interfaces.patch
+alsa-usb-audio-define-macros-for-quirk-table-entries.patch
+alsa-usb-audio-replace-complex-quirk-lines-with-macr.patch
+alsa-usb-audio-add-quirk-for-rme-digiface-usb.patch
+alsa-usb-audio-add-mixer-quirk-for-rme-digiface-usb.patch
+alsa-hda-realtek-refactor-and-simplify-samsung-galax.patch
+alsa-usb-audio-add-logitech-audio-profile-quirk.patch
+asoc-codecs-wsa883x-handle-reading-version-failure.patch
+alsa-control-take-power_ref-lock-primarily.patch
+tools-x86-kcpuid-protect-against-faulty-max-subleaf-.patch
+x86-pkeys-add-pkru-as-a-parameter-in-signal-handling.patch
+x86-pkeys-restore-altstack-access-in-sigreturn.patch
+x86-kexec-add-efi-config-table-identity-mapping-for-.patch
+x86-mm-ident_map-use-gbpages-only-where-full-gb-page.patch
+alsa-asihpi-fix-potential-oob-array-access.patch
+alsa-hdsp-break-infinite-midi-input-flush-loop.patch
+tools-nolibc-powerpc-limit-stack-protector-workaroun.patch
+selftests-nolibc-avoid-passing-null-to-printf-s.patch
+x86-syscall-avoid-memcpy-for-ia32-syscall_get_argume.patch
+asoc-intel-boards-always-check-the-result-of-acpi_de.patch
+rcu-tasks-fix-access-non-existent-percpu-rtpcp-varia.patch
+hwmon-nct6775-add-g15cf-to-asus-wmi-monitoring-list.patch
+fbdev-efifb-register-sysfs-groups-through-driver-cor.patch
+fbdev-pxafb-fix-possible-use-after-free-in-pxafb_tas.patch
+pmdomain-core-don-t-hold-the-genpd-lock-when-calling.patch
+pmdomain-core-use-dev_name-instead-of-kobject_get_pa.patch
+coredump-standartize-and-fix-logging.patch
+rcuscale-provide-clear-error-when-async-specified-wi.patch
+power-reset-brcmstb-do-not-go-into-infinite-loop-if-.patch
+iommu-arm-smmu-v3-match-stall-behaviour-for-s2.patch
+iommu-vt-d-always-reserve-a-domain-id-for-identity-s.patch
+iommu-vt-d-fix-potential-lockup-if-qi_submit_sync-ca.patch
+iommu-vt-d-unconditionally-flush-device-tlb-for-pasi.patch
+iommu-arm-smmu-v3-do-not-use-devm-for-the-cd-table-a.patch
+cgroup-disallow-mounting-v1-hierarchies-without-cont.patch
+drm-stm-avoid-use-after-free-issues-with-crtc-and-pl.patch
+drm-amd-display-pass-non-null-to-dcn20_validate_appl.patch
+drm-amd-display-check-null-pointers-before-using-the.patch
+drm-amd-display-check-null-pointers-before-used.patch
+drm-amd-display-check-null-pointers-before-multiple-.patch
+drm-amdgpu-disallow-multiple-bo_handles-chunks-in-on.patch
+drm-amdkfd-amdkfd_free_gtt_mem-clear-the-correct-poi.patch
+drm-amd-display-add-null-check-for-head_pipe-in-dcn2.patch
+drm-amd-display-add-null-check-for-head_pipe-in-dcn3.patch
+drm-amd-display-add-null-check-for-clk_mgr-and-clk_m.patch
+drm-amd-display-add-null-check-for-clk_mgr-and-clk_m.patch-5210
+drm-amd-display-add-null-check-for-clk_mgr-in-dcn32_.patch
+drm-xe-hdcp-check-gsc-structure-validity.patch
+drm-amd-display-add-null-check-for-pipe_ctx-plane_st.patch
+drm-amd-display-add-null-check-for-top_pipe_to_progr.patch
+drm-amd-display-use-gpuvm_min_page_size_kbytes-for-d.patch
+ata-pata_serverworks-do-not-use-the-term-blacklist.patch
+ata-sata_sil-rename-sil_blacklist-to-sil_quirks.patch
+selftests-bpf-fix-uprobe.path-leak-in-bpf_testmod.patch
+scsi-smartpqi-add-new-controller-pci-ids.patch
+hid-ignore-battery-for-all-elan-i2c-hid-devices.patch
+drm-amd-display-underflow-seen-on-dcn401-egpu.patch
+drm-amd-display-handle-null-stream_status-in-planes_.patch
+drm-amd-display-add-null-check-for-function-pointer-.patch
+drm-amd-display-add-null-check-for-function-pointer-.patch-4383
+drm-amd-display-add-null-check-for-function-pointer-.patch-16350
+drm-amd-display-fix-a-ubsan-warning-in-dml2.1.patch
+drm-amd-display-add-null-check-for-afb-in-amdgpu_dm_.patch
+drm-amd-display-check-null-pointers-before-using-dc-.patch
+drm-amd-display-check-null-pointer-before-try-to-acc.patch
+drm-amd-display-add-null-check-for-afb-in-amdgpu_dm_.patch-8577
+drm-xe-name-and-document-wa_14019789679.patch
+drm-amd-display-fix-double-free-issue-during-amdgpu-.patch
+drm-amdgpu-add-list-empty-check-to-avoid-null-pointe.patch
+jfs-ubsan-shift-out-of-bounds-in-dbfindbits.patch
+jfs-fix-uaf-in-dbfreebits.patch
+jfs-check-if-leafidx-greater-than-num-leaves-per-dma.patch
+scsi-smartpqi-correct-stream-detection.patch
+scsi-smartpqi-add-new-controller-pci-ids.patch-30880
+drm-msm-adreno-assign-msm_gpu-pdev-earlier-to-avoid-.patch
+jfs-fix-uninit-value-access-of-new_ea-in-ea_buffer.patch
+drm-amdgpu-add-raven1-gfxoff-quirk.patch
+drm-amdgpu-enable-gfxoff-quirk-on-hp-705g4.patch
+drm-amdkfd-fix-resource-leak-in-criu-restore-queue.patch
+hid-multitouch-add-support-for-thinkpad-x12-gen-2-kb.patch
+platform-x86-touchscreen_dmi-add-nanote-next-quirk.patch
+platform-x86-amd-pmf-add-quirk-for-tuf-gaming-a14.patch
+drm-xe-add-timeout-to-preempt-fences.patch
+drm-xe-fbdev-limit-the-usage-of-stolen-for-lnl.patch
+drm-stm-ltdc-reset-plane-transparency-after-plane-di.patch
+drm-amd-display-initialize-denominators-default-to-1.patch
+drm-amd-display-check-null-initialized-variables.patch
+drm-amd-display-check-phantom_stream-before-it-is-us.patch
+drm-amd-display-check-stream-before-comparing-them.patch
+drm-amd-display-deallocate-dml-memory-if-allocation-.patch
+drm-amd-display-increase-array-size-of-dummy_boolean.patch
+drm-amd-display-fix-index-out-of-bounds-in-dcn30-deg.patch
+drm-amd-display-fix-index-out-of-bounds-in-degamma-h.patch
+drm-amd-display-implement-bounds-check-for-stream-en.patch
+drm-amd-display-fix-index-out-of-bounds-in-dcn30-col.patch
+drm-amdgpu-gfx12-properly-handle-error-ints-on-all-p.patch
+drm-amdgpu-gfx9-properly-handle-error-ints-on-all-pi.patch
+drm-amd-display-fix-possible-overflow-in-integer-mul.patch
+drm-amd-display-check-stream_status-before-it-is-use.patch
+drm-amd-display-avoid-overflow-assignment-in-link_dp.patch
+drm-amd-display-initialize-get_bytes_per_element-s-d.patch
+drm-printer-allow-null-data-in-devcoredump-printer.patch
+perf-x86-avoid-missing-caller-address-in-stack-trace.patch
+scsi-aacraid-rearrange-order-of-struct-aac_srb_unit.patch
+scsi-lpfc-validate-hdwq-pointers-before-dereferencin.patch
+scsi-lpfc-fix-unsolicited-flogi-kref-imbalance-when-.patch
+scsi-lpfc-update-prlo-handling-in-direct-attached-to.patch
+drm-amd-display-force-enable-3dlut-dma-check-for-dcn.patch
+drm-amdgpu-fix-unchecked-return-value-warning-for-am.patch
+drm-amdgpu-fix-unchecked-return-value-warning-for-am.patch-17138
+perf-fix-event_function_call-locking.patch
+scsi-ncr5380-initialize-buffer-for-msg-in-and-status.patch
+drm-radeon-r100-handle-unknown-family-in-r100_cp_ini.patch
+drm-amd-display-unlock-pipes-based-on-det-allocation.patch
+drm-amdgpu-fix-ptr-check-warning-in-gfx9-ip_dump.patch
+drm-amdgpu-fix-ptr-check-warning-in-gfx10-ip_dump.patch
+drm-amdgpu-fix-ptr-check-warning-in-gfx11-ip_dump.patch
+drm-amdgpu-block-mmr_read-ioctl-in-reset.patch
+drm-amdgpu-gfx9-use-rlc-safe-mode-for-soft-recovery.patch
+drm-amdgpu-gfx11-enter-safe-mode-before-touching-cp_.patch
+drm-xe-use-topology-to-determine-page-fault-queue-si.patch
+drm-amd-pm-ensure-the-fw_info-is-not-null-before-usi.patch
+drm-amdkfd-check-int-source-id-for-utcl2-poison-even.patch
+drm-xe-drop-warn-on-xe_guc_pc_gucrc_disable-in-guc-p.patch
+of-irq-refer-to-actual-buffer-size-in-of_irq_parse_o.patch
+drm-amd-display-guard-write-a-0-post_divider-value-t.patch
+powerpc-pseries-use-correct-data-types-from-pseries_.patch
+ovl-fsync-after-metadata-copy-up.patch
+drm-amdgpu-gfx12-use-rlc-safe-mode-for-soft-recovery.patch
+drm-amdgpu-gfx11-use-rlc-safe-mode-for-soft-recovery.patch
+drm-amdgpu-gfx10-use-rlc-safe-mode-for-soft-recovery.patch
+platform-x86-lenovo-ymc-ignore-the-0x0-state.patch
+tools-hv-add-memory-allocation-check-in-hv_fcopy_sta.patch
+hid-i2c-hid-ensure-various-commands-do-not-interfere.patch
+ksmbd-add-refcnt-to-ksmbd_conn-struct.patch
+platform-mellanox-mlxbf-pmc-fix-lockdep-warning.patch
+platform-x86-x86-android-tablets-adjust-xiaomi-pad-2.patch
+ext4-filesystems-without-casefold-feature-cannot-be-.patch
+ext4-don-t-set-sb_rdonly-after-filesystem-errors.patch
+bpf-make-the-pointer-returned-by-iter-next-method-va.patch
+ext4-ext4_search_dir-should-return-a-proper-error.patch
+ext4-avoid-use-after-free-in-ext4_ext_show_leaf.patch
+ext4-fix-i_data_sem-unlock-order-in-ext4_ind_migrate.patch
+bpftool-fix-undefined-behavior-caused-by-shifting-in.patch
+iomap-handle-a-post-direct-i-o-invalidate-race-in-io.patch
+bpftool-fix-undefined-behavior-in-qsort-null-0.patch
+bpf-fix-a-sdiv-overflow-issue.patch
diff --git a/queue-6.11/tcp-avoid-reusing-fin_wait2-when-trying-to-find-port.patch b/queue-6.11/tcp-avoid-reusing-fin_wait2-when-trying-to-find-port.patch
new file mode 100644 (file)
index 0000000..8fd08e2
--- /dev/null
@@ -0,0 +1,82 @@
+From 5ce229bba6d8ea30c14f7d5a1b8df8293fd1a61e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Aug 2024 08:11:52 +0800
+Subject: tcp: avoid reusing FIN_WAIT2 when trying to find port in connect()
+ process
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit 0d9e5df4a257afc3a471a82961ace9a22b88295a ]
+
+We found that one close-wait socket was reset by the other side
+due to a new connection reusing the same port which is beyond our
+expectation, so we have to investigate the underlying reason.
+
+The following experiment is conducted in the test environment. We
+limit the port range from 40000 to 40010 and delay the time to close()
+after receiving a fin from the active close side, which can help us
+easily reproduce like what happened in production.
+
+Here are three connections captured by tcpdump:
+127.0.0.1.40002 > 127.0.0.1.9999: Flags [S], seq 2965525191
+127.0.0.1.9999 > 127.0.0.1.40002: Flags [S.], seq 2769915070
+127.0.0.1.40002 > 127.0.0.1.9999: Flags [.], ack 1
+127.0.0.1.40002 > 127.0.0.1.9999: Flags [F.], seq 1, ack 1
+// a few seconds later, within 60 seconds
+127.0.0.1.40002 > 127.0.0.1.9999: Flags [S], seq 2965590730
+127.0.0.1.9999 > 127.0.0.1.40002: Flags [.], ack 2
+127.0.0.1.40002 > 127.0.0.1.9999: Flags [R], seq 2965525193
+// later, very quickly
+127.0.0.1.40002 > 127.0.0.1.9999: Flags [S], seq 2965590730
+127.0.0.1.9999 > 127.0.0.1.40002: Flags [S.], seq 3120990805
+127.0.0.1.40002 > 127.0.0.1.9999: Flags [.], ack 1
+
+As we can see, the first flow is reset because:
+1) client starts a new connection, I mean, the second one
+2) client tries to find a suitable port which is a timewait socket
+   (its state is timewait, substate is fin_wait2)
+3) client occupies that timewait port to send a SYN
+4) server finds a corresponding close-wait socket in ehash table,
+   then replies with a challenge ack
+5) client sends an RST to terminate this old close-wait socket.
+
+I don't think the port selection algo can choose a FIN_WAIT2 socket
+when we turn on tcp_tw_reuse because on the server side there
+remain unread data. In some cases, if one side haven't call close() yet,
+we should not consider it as expendable and treat it at will.
+
+Even though, sometimes, the server isn't able to call close() as soon
+as possible like what we expect, it can not be terminated easily,
+especially due to a second unrelated connection happening.
+
+After this patch, we can see the expected failure if we start a
+connection when all the ports are occupied in fin_wait2 state:
+"Ncat: Cannot assign requested address."
+
+Reported-by: Jade Dong <jadedong@tencent.com>
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20240823001152.31004-1-kerneljasonxing@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_ipv4.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index a4e510846905e..5087e12209a19 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -120,6 +120,9 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
+       struct tcp_sock *tp = tcp_sk(sk);
+       int ts_recent_stamp;
++      if (tw->tw_substate == TCP_FIN_WAIT2)
++              reuse = 0;
++
+       if (reuse == 2) {
+               /* Still does not detect *everything* that goes through
+                * lo, since we require a loopback src or dst address
+-- 
+2.43.0
+
diff --git a/queue-6.11/tipc-guard-against-string-buffer-overrun.patch b/queue-6.11/tipc-guard-against-string-buffer-overrun.patch
new file mode 100644 (file)
index 0000000..7f152a9
--- /dev/null
@@ -0,0 +1,53 @@
+From ba92221760b06cbd871fd6be7dcb7c149e1df293 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 19:35:37 +0100
+Subject: tipc: guard against string buffer overrun
+
+From: Simon Horman <horms@kernel.org>
+
+[ Upstream commit 6555a2a9212be6983d2319d65276484f7c5f431a ]
+
+Smatch reports that copying media_name and if_name to name_parts may
+overwrite the destination.
+
+ .../bearer.c:166 bearer_name_validate() error: strcpy() 'media_name' too large for 'name_parts->media_name' (32 vs 16)
+ .../bearer.c:167 bearer_name_validate() error: strcpy() 'if_name' too large for 'name_parts->if_name' (1010102 vs 16)
+
+This does seem to be the case so guard against this possibility by using
+strscpy() and failing if truncation occurs.
+
+Introduced by commit b97bf3fd8f6a ("[TIPC] Initial merge")
+
+Compile tested only.
+
+Reviewed-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20240801-tipic-overrun-v2-1-c5b869d1f074@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tipc/bearer.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
+index 5a526ebafeb4b..3c9e25f6a1d22 100644
+--- a/net/tipc/bearer.c
++++ b/net/tipc/bearer.c
+@@ -163,8 +163,12 @@ static int bearer_name_validate(const char *name,
+       /* return bearer name components, if necessary */
+       if (name_parts) {
+-              strcpy(name_parts->media_name, media_name);
+-              strcpy(name_parts->if_name, if_name);
++              if (strscpy(name_parts->media_name, media_name,
++                          TIPC_MAX_MEDIA_NAME) < 0)
++                      return 0;
++              if (strscpy(name_parts->if_name, if_name,
++                          TIPC_MAX_IF_NAME) < 0)
++                      return 0;
+       }
+       return 1;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/tools-hv-add-memory-allocation-check-in-hv_fcopy_sta.patch b/queue-6.11/tools-hv-add-memory-allocation-check-in-hv_fcopy_sta.patch
new file mode 100644 (file)
index 0000000..2b7023f
--- /dev/null
@@ -0,0 +1,44 @@
+From 3213da5d637f74dc9331e94bb0ab9959dd8ea3d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Sep 2024 02:13:33 -0700
+Subject: tools/hv: Add memory allocation check in hv_fcopy_start
+
+From: Zhu Jun <zhujun2@cmss.chinamobile.com>
+
+[ Upstream commit 94e86b174d103d941b4afc4f016af8af9e5352fa ]
+
+Added error handling for memory allocation failures
+of file_name and path_name.
+
+Signed-off-by: Zhu Jun <zhujun2@cmss.chinamobile.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Tested-by: Saurabh Sengar <ssengar@linux.microsoft.com>
+Link: https://lore.kernel.org/r/20240906091333.11419-1-zhujun2@cmss.chinamobile.com
+Signed-off-by: Wei Liu <wei.liu@kernel.org>
+Message-ID: <20240906091333.11419-1-zhujun2@cmss.chinamobile.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/hv/hv_fcopy_uio_daemon.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/tools/hv/hv_fcopy_uio_daemon.c b/tools/hv/hv_fcopy_uio_daemon.c
+index 3ce316cc9f970..7a00f3066a980 100644
+--- a/tools/hv/hv_fcopy_uio_daemon.c
++++ b/tools/hv/hv_fcopy_uio_daemon.c
+@@ -296,6 +296,13 @@ static int hv_fcopy_start(struct hv_start_fcopy *smsg_in)
+       file_name = (char *)malloc(file_size * sizeof(char));
+       path_name = (char *)malloc(path_size * sizeof(char));
++      if (!file_name || !path_name) {
++              free(file_name);
++              free(path_name);
++              syslog(LOG_ERR, "Can't allocate memory for file name and/or path name");
++              return HV_E_FAIL;
++      }
++
+       wcstoutf8(file_name, (__u16 *)in_file_name, file_size);
+       wcstoutf8(path_name, (__u16 *)in_path_name, path_size);
+-- 
+2.43.0
+
diff --git a/queue-6.11/tools-nolibc-powerpc-limit-stack-protector-workaroun.patch b/queue-6.11/tools-nolibc-powerpc-limit-stack-protector-workaroun.patch
new file mode 100644 (file)
index 0000000..68d5170
--- /dev/null
@@ -0,0 +1,41 @@
+From 5f113f0d9278e9a37929bf54d796edb7c316c73b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 23:51:39 +0200
+Subject: tools/nolibc: powerpc: limit stack-protector workaround to GCC
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 1daea158d0aae0770371f3079305a29fdb66829e ]
+
+As mentioned in the comment, the workaround for
+__attribute__((no_stack_protector)) is only necessary on GCC.
+Avoid applying the workaround on clang, as clang does not recognize
+__attribute__((__optimize__)) and would fail.
+
+Acked-by: Willy Tarreau <w@1wt.eu>
+Link: https://lore.kernel.org/r/20240807-nolibc-llvm-v2-3-c20f2f5fc7c2@weissschuh.net
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/include/nolibc/arch-powerpc.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/include/nolibc/arch-powerpc.h b/tools/include/nolibc/arch-powerpc.h
+index ac212e6185b26..41ebd394b90c7 100644
+--- a/tools/include/nolibc/arch-powerpc.h
++++ b/tools/include/nolibc/arch-powerpc.h
+@@ -172,7 +172,7 @@
+       _ret;                                                                \
+ })
+-#ifndef __powerpc64__
++#if !defined(__powerpc64__) && !defined(__clang__)
+ /* FIXME: For 32-bit PowerPC, with newer gcc compilers (e.g. gcc 13.1.0),
+  * "omit-frame-pointer" fails with __attribute__((no_stack_protector)) but
+  * works with __attribute__((__optimize__("-fno-stack-protector")))
+-- 
+2.43.0
+
diff --git a/queue-6.11/tools-x86-kcpuid-protect-against-faulty-max-subleaf-.patch b/queue-6.11/tools-x86-kcpuid-protect-against-faulty-max-subleaf-.patch
new file mode 100644 (file)
index 0000000..8cbbe1a
--- /dev/null
@@ -0,0 +1,68 @@
+From 9cef2a2b66eb4004145c6471b20fa19324bb0667 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jul 2024 15:47:44 +0200
+Subject: tools/x86/kcpuid: Protect against faulty "max subleaf" values
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ahmed S. Darwish <darwi@linutronix.de>
+
+[ Upstream commit cf96ab1a966b87b09fdd9e8cc8357d2d00776a3a ]
+
+Protect against the kcpuid code parsing faulty max subleaf numbers
+through a min() expression.  Thus, ensuring that max_subleaf will always
+be ≤ MAX_SUBLEAF_NUM.
+
+Use "u32" for the subleaf numbers since kcpuid is compiled with -Wextra,
+which includes signed/unsigned comparisons warnings.
+
+Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/all/20240718134755.378115-5-darwi@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/arch/x86/kcpuid/kcpuid.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/tools/arch/x86/kcpuid/kcpuid.c b/tools/arch/x86/kcpuid/kcpuid.c
+index 24b7d017ec2c1..b7965dfff33a9 100644
+--- a/tools/arch/x86/kcpuid/kcpuid.c
++++ b/tools/arch/x86/kcpuid/kcpuid.c
+@@ -7,7 +7,8 @@
+ #include <string.h>
+ #include <getopt.h>
+-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
++#define min(a, b)     (((a) < (b)) ? (a) : (b))
+ typedef unsigned int u32;
+ typedef unsigned long long u64;
+@@ -207,12 +208,9 @@ static void raw_dump_range(struct cpuid_range *range)
+ #define MAX_SUBLEAF_NUM               32
+ struct cpuid_range *setup_cpuid_range(u32 input_eax)
+ {
+-      u32 max_func, idx_func;
+-      int subleaf;
++      u32 max_func, idx_func, subleaf, max_subleaf;
++      u32 eax, ebx, ecx, edx, f = input_eax;
+       struct cpuid_range *range;
+-      u32 eax, ebx, ecx, edx;
+-      u32 f = input_eax;
+-      int max_subleaf;
+       bool allzero;
+       eax = input_eax;
+@@ -258,7 +256,7 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax)
+                * others have to be tried (0xf)
+                */
+               if (f == 0x7 || f == 0x14 || f == 0x17 || f == 0x18)
+-                      max_subleaf = (eax & 0xff) + 1;
++                      max_subleaf = min((eax & 0xff) + 1, max_subleaf);
+               if (f == 0xb)
+                       max_subleaf = 2;
+-- 
+2.43.0
+
diff --git a/queue-6.11/vfs-use-rcu-in-ilookup.patch b/queue-6.11/vfs-use-rcu-in-ilookup.patch
new file mode 100644 (file)
index 0000000..71dcde6
--- /dev/null
@@ -0,0 +1,43 @@
+From b873dca73a94b7dfa98b81a4e4783ce9e0b2702c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jul 2024 09:13:24 +0200
+Subject: vfs: use RCU in ilookup
+
+From: Mateusz Guzik <mjguzik@gmail.com>
+
+[ Upstream commit 122381a46954ad592ee93d7da2bef5074b396247 ]
+
+A soft lockup in ilookup was reported when stress-testing a 512-way
+system [1] (see [2] for full context) and it was verified that not
+taking the lock shifts issues back to mm.
+
+[1] https://lore.kernel.org/linux-mm/56865e57-c250-44da-9713-cf1404595bcc@amd.com/
+[2] https://lore.kernel.org/linux-mm/d2841226-e27b-4d3d-a578-63587a3aa4f3@amd.com/
+
+Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
+Link: https://lore.kernel.org/r/20240715071324.265879-1-mjguzik@gmail.com
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/inode.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/fs/inode.c b/fs/inode.c
+index 551ba352072fa..30d42ab137f0a 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1578,9 +1578,7 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
+       struct hlist_head *head = inode_hashtable + hash(sb, ino);
+       struct inode *inode;
+ again:
+-      spin_lock(&inode_hash_lock);
+-      inode = find_inode_fast(sb, head, ino, true);
+-      spin_unlock(&inode_hash_lock);
++      inode = find_inode_fast(sb, head, ino, false);
+       if (inode) {
+               if (IS_ERR(inode))
+-- 
+2.43.0
+
diff --git a/queue-6.11/virt-sev-guest-ensure-the-snp-guest-messages-do-not-.patch b/queue-6.11/virt-sev-guest-ensure-the-snp-guest-messages-do-not-.patch
new file mode 100644 (file)
index 0000000..0697cc8
--- /dev/null
@@ -0,0 +1,62 @@
+From 59bcb5e3f059b41e30d8be6cc9517e9bd6d4d605 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 20:37:55 +0530
+Subject: virt: sev-guest: Ensure the SNP guest messages do not exceed a page
+
+From: Nikunj A Dadhania <nikunj@amd.com>
+
+[ Upstream commit 2b9ac0b84c2cae91bbaceab62df4de6d503421ec ]
+
+Currently, struct snp_guest_msg includes a message header (96 bytes) and
+a payload (4000 bytes). There is an implicit assumption here that the
+SNP message header will always be 96 bytes, and with that assumption the
+payload array size has been set to 4000 bytes - a magic number. If any
+new member is added to the SNP message header, the SNP guest message
+will span more than a page.
+
+Instead of using a magic number for the payload, declare struct
+snp_guest_msg in a way that payload plus the message header do not
+exceed a page.
+
+  [ bp: Massage. ]
+
+Suggested-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Nikunj A Dadhania <nikunj@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20240731150811.156771-5-nikunj@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/sev.h              | 2 +-
+ drivers/virt/coco/sev-guest/sev-guest.c | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
+index 79bbe2be900eb..ee34ab00a8d6d 100644
+--- a/arch/x86/include/asm/sev.h
++++ b/arch/x86/include/asm/sev.h
+@@ -164,7 +164,7 @@ struct snp_guest_msg_hdr {
+ struct snp_guest_msg {
+       struct snp_guest_msg_hdr hdr;
+-      u8 payload[4000];
++      u8 payload[PAGE_SIZE - sizeof(struct snp_guest_msg_hdr)];
+ } __packed;
+ struct sev_guest_platform_data {
+diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c
+index 6fc7884ea0a11..c86be0cd8ecd2 100644
+--- a/drivers/virt/coco/sev-guest/sev-guest.c
++++ b/drivers/virt/coco/sev-guest/sev-guest.c
+@@ -1090,6 +1090,8 @@ static int __init sev_guest_probe(struct platform_device *pdev)
+       void __iomem *mapping;
+       int ret;
++      BUILD_BUG_ON(sizeof(struct snp_guest_msg) > PAGE_SIZE);
++
+       if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+               return -ENODEV;
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-ath11k-fix-array-out-of-bound-access-in-soc-sta.patch b/queue-6.11/wifi-ath11k-fix-array-out-of-bound-access-in-soc-sta.patch
new file mode 100644 (file)
index 0000000..36e6d25
--- /dev/null
@@ -0,0 +1,43 @@
+From 070b27f1116934e04edb131f2f4a4657dddab44f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jul 2024 12:38:11 +0530
+Subject: wifi: ath11k: fix array out-of-bound access in SoC stats
+
+From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
+
+[ Upstream commit 69f253e46af98af17e3efa3e5dfa72fcb7d1983d ]
+
+Currently, the ath11k_soc_dp_stats::hal_reo_error array is defined with a
+maximum size of DP_REO_DST_RING_MAX. However, the ath11k_dp_process_rx()
+function access ath11k_soc_dp_stats::hal_reo_error using the REO
+destination SRNG ring ID, which is incorrect. SRNG ring ID differ from
+normal ring ID, and this usage leads to out-of-bounds array access. To fix
+this issue, modify ath11k_dp_process_rx() to use the normal ring ID
+directly instead of the SRNG ring ID to avoid out-of-bounds array access.
+
+Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://patch.msgid.link/20240704070811.4186543-3-quic_periyasa@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
+index 86485580dd895..c087d8a0f5b25 100644
+--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
+@@ -2697,7 +2697,7 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
+               if (unlikely(push_reason !=
+                            HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION)) {
+                       dev_kfree_skb_any(msdu);
+-                      ab->soc_stats.hal_reo_error[dp->reo_dst_ring[ring_id].ring_id]++;
++                      ab->soc_stats.hal_reo_error[ring_id]++;
+                       continue;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-ath12k-fix-array-out-of-bound-access-in-soc-sta.patch b/queue-6.11/wifi-ath12k-fix-array-out-of-bound-access-in-soc-sta.patch
new file mode 100644 (file)
index 0000000..e57a64a
--- /dev/null
@@ -0,0 +1,43 @@
+From 170c844d60d86f6fe2b52ead603796f256f90db4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jul 2024 12:38:10 +0530
+Subject: wifi: ath12k: fix array out-of-bound access in SoC stats
+
+From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
+
+[ Upstream commit e106b7ad13c1d246adaa57df73edb8f8b8acb240 ]
+
+Currently, the ath12k_soc_dp_stats::hal_reo_error array is defined with a
+maximum size of DP_REO_DST_RING_MAX. However, the ath12k_dp_rx_process()
+function access ath12k_soc_dp_stats::hal_reo_error using the REO
+destination SRNG ring ID, which is incorrect. SRNG ring ID differ from
+normal ring ID, and this usage leads to out-of-bounds array access. To
+fix this issue, modify ath12k_dp_rx_process() to use the normal ring ID
+directly instead of the SRNG ring ID to avoid out-of-bounds array access.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://patch.msgid.link/20240704070811.4186543-2-quic_periyasa@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/dp_rx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
+index 14236d0a0c89d..91e3393f7b5f4 100644
+--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
+@@ -2681,7 +2681,7 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
+               if (push_reason !=
+                   HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) {
+                       dev_kfree_skb_any(msdu);
+-                      ab->soc_stats.hal_reo_error[dp->reo_dst_ring[ring_id].ring_id]++;
++                      ab->soc_stats.hal_reo_error[ring_id]++;
+                       continue;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-ath9k-fix-possible-integer-overflow-in-ath9k_ge.patch b/queue-6.11/wifi-ath9k-fix-possible-integer-overflow-in-ath9k_ge.patch
new file mode 100644 (file)
index 0000000..ce9727d
--- /dev/null
@@ -0,0 +1,47 @@
+From 1bb1f8f29a9b009ab46a953bdfb22da409188bd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jul 2024 14:17:43 +0300
+Subject: wifi: ath9k: fix possible integer overflow in ath9k_get_et_stats()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dmitry Kandybka <d.kandybka@gmail.com>
+
+[ Upstream commit 3f66f26703093886db81f0610b97a6794511917c ]
+
+In 'ath9k_get_et_stats()', promote TX stats counters to 'u64'
+to avoid possible integer overflow. Compile tested only.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Signed-off-by: Dmitry Kandybka <d.kandybka@gmail.com>
+Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://patch.msgid.link/20240725111743.14422-1-d.kandybka@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath9k/debug.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
+index bf3da631c69fd..51abc470125b3 100644
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1325,11 +1325,11 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
+       struct ath_softc *sc = hw->priv;
+       int i = 0;
+-      data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all +
++      data[i++] = ((u64)sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all +
+                    sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all +
+                    sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all +
+                    sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all);
+-      data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all +
++      data[i++] = ((u64)sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all +
+                    sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all +
+                    sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all +
+                    sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all);
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-ath9k_htc-use-__skb_set_length-for-resetting-ur.patch b/queue-6.11/wifi-ath9k_htc-use-__skb_set_length-for-resetting-ur.patch
new file mode 100644 (file)
index 0000000..f5b8e46
--- /dev/null
@@ -0,0 +1,59 @@
+From 6a0d6f901691307d062ca3d49d7793c7e8b85dc4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Aug 2024 16:24:46 +0200
+Subject: wifi: ath9k_htc: Use __skb_set_length() for resetting urb before
+ resubmit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@redhat.com>
+
+[ Upstream commit 94745807f3ebd379f23865e6dab196f220664179 ]
+
+Syzbot points out that skb_trim() has a sanity check on the existing length of
+the skb, which can be uninitialised in some error paths. The intent here is
+clearly just to reset the length to zero before resubmitting, so switch to
+calling __skb_set_length(skb, 0) directly. In addition, __skb_set_length()
+already contains a call to skb_reset_tail_pointer(), so remove the redundant
+call.
+
+The syzbot report came from ath9k_hif_usb_reg_in_cb(), but there's a similar
+usage of skb_trim() in ath9k_hif_usb_rx_cb(), change both while we're at it.
+
+Reported-by: syzbot+98afa303be379af6cdb2@syzkaller.appspotmail.com
+Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://patch.msgid.link/20240812142447.12328-1-toke@toke.dk
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath9k/hif_usb.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
+index 0c7841f952287..a3733c9b484e4 100644
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -716,8 +716,7 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
+       }
+ resubmit:
+-      skb_reset_tail_pointer(skb);
+-      skb_trim(skb, 0);
++      __skb_set_length(skb, 0);
+       usb_anchor_urb(urb, &hif_dev->rx_submitted);
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+@@ -754,8 +753,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
+       case -ESHUTDOWN:
+               goto free_skb;
+       default:
+-              skb_reset_tail_pointer(skb);
+-              skb_trim(skb, 0);
++              __skb_set_length(skb, 0);
+               goto resubmit;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-cfg80211-set-correct-chandef-when-starting-cac.patch b/queue-6.11/wifi-cfg80211-set-correct-chandef-when-starting-cac.patch
new file mode 100644 (file)
index 0000000..e27b532
--- /dev/null
@@ -0,0 +1,77 @@
+From d86f527a60feb6d741a208e9614c41d76c735601 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Aug 2024 16:24:18 +0200
+Subject: wifi: cfg80211: Set correct chandef when starting CAC
+
+From: Issam Hamdi <ih@simonwunderlich.de>
+
+[ Upstream commit 20361712880396e44ce80aaeec2d93d182035651 ]
+
+When starting CAC in a mode other than AP mode, it return a
+"WARNING: CPU: 0 PID: 63 at cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]"
+caused by the chandef.chan being null at the end of CAC.
+
+Solution: Ensure the channel definition is set for the different modes
+when starting CAC to avoid getting a NULL 'chan' at the end of CAC.
+
+ Call Trace:
+  ? show_regs.part.0+0x14/0x16
+  ? __warn+0x67/0xc0
+  ? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]
+  ? report_bug+0xa7/0x130
+  ? exc_overflow+0x30/0x30
+  ? handle_bug+0x27/0x50
+  ? exc_invalid_op+0x18/0x60
+  ? handle_exception+0xf6/0xf6
+  ? exc_overflow+0x30/0x30
+  ? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]
+  ? exc_overflow+0x30/0x30
+  ? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]
+  ? regulatory_propagate_dfs_state.cold+0x1b/0x4c [cfg80211]
+  ? cfg80211_propagate_cac_done_wk+0x1a/0x30 [cfg80211]
+  ? process_one_work+0x165/0x280
+  ? worker_thread+0x120/0x3f0
+  ? kthread+0xc2/0xf0
+  ? process_one_work+0x280/0x280
+  ? kthread_complete_and_exit+0x20/0x20
+  ? ret_from_fork+0x19/0x24
+
+Reported-by: Kretschmer Mathias <mathias.kretschmer@fit.fraunhofer.de>
+Signed-off-by: Issam Hamdi <ih@simonwunderlich.de>
+Link: https://patch.msgid.link/20240816142418.3381951-1-ih@simonwunderlich.de
+[shorten subject, remove OCB, reorder cases to match previous list]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/nl80211.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 1d83bc3de5ca5..f18e1716339e0 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -10144,7 +10144,20 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+       err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
+       if (!err) {
+-              wdev->links[0].ap.chandef = chandef;
++              switch (wdev->iftype) {
++              case NL80211_IFTYPE_AP:
++              case NL80211_IFTYPE_P2P_GO:
++                      wdev->links[0].ap.chandef = chandef;
++                      break;
++              case NL80211_IFTYPE_ADHOC:
++                      wdev->u.ibss.chandef = chandef;
++                      break;
++              case NL80211_IFTYPE_MESH_POINT:
++                      wdev->u.mesh.chandef = chandef;
++                      break;
++              default:
++                      break;
++              }
+               wdev->cac_started = true;
+               wdev->cac_start_time = jiffies;
+               wdev->cac_time_ms = cac_time_ms;
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-iwlwifi-allow-only-cn-mcc-from-wrdd.patch b/queue-6.11/wifi-iwlwifi-allow-only-cn-mcc-from-wrdd.patch
new file mode 100644 (file)
index 0000000..a08b1ab
--- /dev/null
@@ -0,0 +1,81 @@
+From 12ca2abf7742e34a1bf5c5027e322fc5ccd97525 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Aug 2024 23:22:49 +0300
+Subject: wifi: iwlwifi: allow only CN mcc from WRDD
+
+From: Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
+
+[ Upstream commit ff5aabe7c2a4a4b089a9ced0cb3d0e284963a7dd ]
+
+Block other mcc expect CN from WRDD ACPI.
+
+Signed-off-by: Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20240808232017.fe6ea7aa4b39.I86004687a2963fe26f990770aca103e2f5cb1628@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/fw/acpi.c       | 5 +++++
+ drivers/net/wireless/intel/iwlwifi/fw/regulatory.h | 2 ++
+ drivers/net/wireless/intel/iwlwifi/fw/uefi.c       | 2 +-
+ drivers/net/wireless/intel/iwlwifi/fw/uefi.h       | 2 --
+ 4 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+index 8c8880b448270..a7cea0a55b35a 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+@@ -357,6 +357,11 @@ int iwl_acpi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc)
+       }
+       mcc_val = wifi_pkg->package.elements[1].integer.value;
++      if (mcc_val != BIOS_MCC_CHINA) {
++              ret = -EINVAL;
++              IWL_DEBUG_RADIO(fwrt, "ACPI WRDD is supported only for CN\n");
++              goto out_free;
++      }
+       mcc[0] = (mcc_val >> 8) & 0xff;
+       mcc[1] = mcc_val & 0xff;
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
+index e2c056f483c1c..c5bd89e61d4a8 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
+@@ -45,6 +45,8 @@
+ #define IWL_WTAS_ENABLE_IEC_MSK       0x4
+ #define IWL_WTAS_USA_UHB_MSK          BIT(16)
++#define BIOS_MCC_CHINA 0x434e
++
+ /*
+  * The profile for revision 2 is a superset of revision 1, which is in
+  * turn a superset of revision 0.  So we can store all revisions
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+index fb982d4fe8510..2cf878f237ac6 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+@@ -638,7 +638,7 @@ int iwl_uefi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc)
+               goto out;
+       }
+-      if (data->mcc != UEFI_MCC_CHINA) {
++      if (data->mcc != BIOS_MCC_CHINA) {
+               ret = -EINVAL;
+               IWL_DEBUG_RADIO(fwrt, "UEFI WRDD is supported only for CN\n");
+               goto out;
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+index 1f8884ca8997c..e0ef981cd8f28 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+@@ -149,8 +149,6 @@ struct uefi_cnv_var_splc {
+       u32 default_pwr_limit;
+ } __packed;
+-#define UEFI_MCC_CHINA 0x434e
+-
+ /* struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI
+  * @revision: the revision of the table
+  * @mcc: country identifier as defined in ISO/IEC 3166-1 Alpha 2 code
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-iwlwifi-mvm-avoid-null-pointer-dereference.patch b/queue-6.11/wifi-iwlwifi-mvm-avoid-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..f5140bc
--- /dev/null
@@ -0,0 +1,76 @@
+From 011ecd0d59ccf2ab274fa6dbb3e7b708dd25d256 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 25 Aug 2024 19:17:09 +0300
+Subject: wifi: iwlwifi: mvm: avoid NULL pointer dereference
+
+From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+
+[ Upstream commit 557a6cd847645e667f3b362560bd7e7c09aac284 ]
+
+iwl_mvm_tx_skb_sta() and iwl_mvm_tx_mpdu() verify that the mvmvsta
+pointer is not NULL.
+It retrieves this pointer using iwl_mvm_sta_from_mac80211, which is
+dereferencing the ieee80211_sta pointer.
+If sta is NULL, iwl_mvm_sta_from_mac80211 will dereference a NULL
+pointer.
+Fix this by checking the sta pointer before retrieving the mvmsta
+from it. If sta is not NULL, then mvmsta isn't either.
+
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Reviewed-by: Johannes Berg <johannes.berg@intel.com>
+Link: https://patch.msgid.link/20240825191257.880921ce23b7.I340052d70ab6d3410724ce955eb00da10e08188f@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+index 7ff5ea5e7aca5..db926b2f4d8d5 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+@@ -1203,6 +1203,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
+       bool is_ampdu = false;
+       int hdrlen;
++      if (WARN_ON_ONCE(!sta))
++              return -1;
++
+       mvmsta = iwl_mvm_sta_from_mac80211(sta);
+       fc = hdr->frame_control;
+       hdrlen = ieee80211_hdrlen(fc);
+@@ -1210,9 +1213,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
+       if (IWL_MVM_NON_TRANSMITTING_AP && ieee80211_is_probe_resp(fc))
+               return -1;
+-      if (WARN_ON_ONCE(!mvmsta))
+-              return -1;
+-
+       if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
+               return -1;
+@@ -1343,7 +1343,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
+ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
+                      struct ieee80211_sta *sta)
+ {
+-      struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
++      struct iwl_mvm_sta *mvmsta;
+       struct ieee80211_tx_info info;
+       struct sk_buff_head mpdus_skbs;
+       struct ieee80211_vif *vif;
+@@ -1352,9 +1352,11 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
+       struct sk_buff *orig_skb = skb;
+       const u8 *addr3;
+-      if (WARN_ON_ONCE(!mvmsta))
++      if (WARN_ON_ONCE(!sta))
+               return -1;
++      mvmsta = iwl_mvm_sta_from_mac80211(sta);
++
+       if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
+               return -1;
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-iwlwifi-mvm-drop-wrong-sta-selection-in-tx.patch b/queue-6.11/wifi-iwlwifi-mvm-drop-wrong-sta-selection-in-tx.patch
new file mode 100644 (file)
index 0000000..1014c38
--- /dev/null
@@ -0,0 +1,64 @@
+From c50f0c9636c2c066325a51ad5cd8a9df658b7831 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Aug 2024 23:22:48 +0300
+Subject: wifi: iwlwifi: mvm: drop wrong STA selection in TX
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 1c7e1068a7c9c39ed27636db93e71911e0045419 ]
+
+This shouldn't happen at all, since in station mode all MMPDUs
+go through the TXQ for the STA, and not this function. There
+may or may not be a race in mac80211 through which this might
+happen for some frames while a station is being added, but in
+that case we can also just drop the frame and pretend the STA
+didn't exist yet.
+
+Also, the code is simply wrong since it uses deflink, and it's
+not easy to fix it since the mvmvif->ap_sta pointer cannot be
+used without the mutex, and perhaps the right link might not
+even be known.
+
+Just drop the frame at that point instead of trying to fix it
+up.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20240808232017.45ad105dc7fe.I6d45c82e5758395d9afb8854057ded03c7dc81d7@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/wireless/intel/iwlwifi/mvm/mac80211.c    | 16 +++-------------
+ 1 file changed, 3 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+index 625ccf566e1c2..1ebcc6417ecef 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+@@ -838,20 +838,10 @@ void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
+       if (ieee80211_is_mgmt(hdr->frame_control))
+               sta = NULL;
+-      /* If there is no sta, and it's not offchannel - send through AP */
++      /* this shouldn't even happen: just drop */
+       if (!sta && info->control.vif->type == NL80211_IFTYPE_STATION &&
+-          !offchannel) {
+-              struct iwl_mvm_vif *mvmvif =
+-                      iwl_mvm_vif_from_mac80211(info->control.vif);
+-              u8 ap_sta_id = READ_ONCE(mvmvif->deflink.ap_sta_id);
+-
+-              if (ap_sta_id < mvm->fw->ucode_capa.num_stations) {
+-                      /* mac80211 holds rcu read lock */
+-                      sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
+-                      if (IS_ERR_OR_NULL(sta))
+-                              goto drop;
+-              }
+-      }
++          !offchannel)
++              goto drop;
+       if (tmp_sta && !sta && link_id != IEEE80211_LINK_UNSPECIFIED &&
+           !ieee80211_is_probe_resp(hdr->frame_control)) {
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-iwlwifi-mvm-fix-a-race-in-scan-abort-flow.patch b/queue-6.11/wifi-iwlwifi-mvm-fix-a-race-in-scan-abort-flow.patch
new file mode 100644 (file)
index 0000000..0a2c9b1
--- /dev/null
@@ -0,0 +1,153 @@
+From 067d2b3f24c0c2fcbed4343edcbed0e7f0129695 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 25 Aug 2024 08:56:37 +0300
+Subject: wifi: iwlwifi: mvm: Fix a race in scan abort flow
+
+From: Ilan Peer <ilan.peer@intel.com>
+
+[ Upstream commit 87c1c28a9aa149489e1667f5754fc24f4973d2d0 ]
+
+When the upper layer requests to cancel an ongoing scan, a race
+is possible in which by the time the driver starts to handle the
+upper layers scan cancel flow, the FW already completed handling
+the scan request and the driver received the scan complete
+notification but still did not handle the notification. In such a
+case the FW will simply ignore the scan abort request coming from
+the driver, no notification would arrive from the FW and the entire
+abort flow would be considered a failure.
+
+To better handle this, check the status code returned by the FW for
+the scan abort command. In case the status indicates that
+no scan was aborted, complete the scan abort flow with success, i.e.,
+the scan was aborted, as the flow is expected to consume the scan
+complete notification.
+
+Signed-off-by: Ilan Peer <ilan.peer@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20240825085558.483989d3baef.I3340556a222388504c6330b333360bf77d10f9e2@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/wireless/intel/iwlwifi/fw/api/scan.h  | 13 ++++++
+ drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 42 +++++++++++++++----
+ 2 files changed, 47 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+index 8598031567bba..0aefdf353b214 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+@@ -1132,6 +1132,19 @@ struct iwl_umac_scan_abort {
+       __le32 flags;
+ } __packed; /* SCAN_ABORT_CMD_UMAC_API_S_VER_1 */
++/**
++ * enum iwl_umac_scan_abort_status
++ *
++ * @IWL_UMAC_SCAN_ABORT_STATUS_SUCCESS: scan was successfully aborted
++ * @IWL_UMAC_SCAN_ABORT_STATUS_IN_PROGRESS: scan abort is in progress
++ * @IWL_UMAC_SCAN_ABORT_STATUS_NOT_FOUND: nothing to abort
++ */
++enum iwl_umac_scan_abort_status {
++      IWL_UMAC_SCAN_ABORT_STATUS_SUCCESS = 0,
++      IWL_UMAC_SCAN_ABORT_STATUS_IN_PROGRESS,
++      IWL_UMAC_SCAN_ABORT_STATUS_NOT_FOUND,
++};
++
+ /**
+  * struct iwl_umac_scan_complete
+  * @uid: scan id, &enum iwl_umac_scan_uid_offsets
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+index 1cc9c426bb159..3a9018595ea90 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+@@ -3313,13 +3313,23 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
+                      mvm->scan_start);
+ }
+-static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type)
++static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type, bool *wait)
+ {
+-      struct iwl_umac_scan_abort cmd = {};
++      struct iwl_umac_scan_abort abort_cmd = {};
++      struct iwl_host_cmd cmd = {
++              .id = WIDE_ID(IWL_ALWAYS_LONG_GROUP, SCAN_ABORT_UMAC),
++              .len = { sizeof(abort_cmd), },
++              .data = { &abort_cmd, },
++              .flags = CMD_SEND_IN_RFKILL,
++      };
++
+       int uid, ret;
++      u32 status = IWL_UMAC_SCAN_ABORT_STATUS_NOT_FOUND;
+       lockdep_assert_held(&mvm->mutex);
++      *wait = true;
++
+       /* We should always get a valid index here, because we already
+        * checked that this type of scan was running in the generic
+        * code.
+@@ -3328,17 +3338,28 @@ static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type)
+       if (WARN_ON_ONCE(uid < 0))
+               return uid;
+-      cmd.uid = cpu_to_le32(uid);
++      abort_cmd.uid = cpu_to_le32(uid);
+       IWL_DEBUG_SCAN(mvm, "Sending scan abort, uid %u\n", uid);
+-      ret = iwl_mvm_send_cmd_pdu(mvm,
+-                                 WIDE_ID(IWL_ALWAYS_LONG_GROUP, SCAN_ABORT_UMAC),
+-                                 CMD_SEND_IN_RFKILL, sizeof(cmd), &cmd);
++      ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);
++
++      IWL_DEBUG_SCAN(mvm, "Scan abort: ret=%d, status=%u\n", ret, status);
+       if (!ret)
+               mvm->scan_uid_status[uid] = type << IWL_MVM_SCAN_STOPPING_SHIFT;
+-      IWL_DEBUG_SCAN(mvm, "Scan abort: ret=%d\n", ret);
++      /* Handle the case that the FW is no longer familiar with the scan that
++       * is to be stopped. In such a case, it is expected that the scan
++       * complete notification was already received but not yet processed.
++       * In such a case, there is no need to wait for a scan complete
++       * notification and the flow should continue similar to the case that
++       * the scan was really aborted.
++       */
++      if (status == IWL_UMAC_SCAN_ABORT_STATUS_NOT_FOUND) {
++              mvm->scan_uid_status[uid] = type << IWL_MVM_SCAN_STOPPING_SHIFT;
++              *wait = false;
++      }
++
+       return ret;
+ }
+@@ -3348,6 +3369,7 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
+       static const u16 scan_done_notif[] = { SCAN_COMPLETE_UMAC,
+                                             SCAN_OFFLOAD_COMPLETE, };
+       int ret;
++      bool wait = true;
+       lockdep_assert_held(&mvm->mutex);
+@@ -3359,7 +3381,7 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
+       IWL_DEBUG_SCAN(mvm, "Preparing to stop scan, type %x\n", type);
+       if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
+-              ret = iwl_mvm_umac_scan_abort(mvm, type);
++              ret = iwl_mvm_umac_scan_abort(mvm, type, &wait);
+       else
+               ret = iwl_mvm_lmac_scan_abort(mvm);
+@@ -3367,6 +3389,10 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
+               IWL_DEBUG_SCAN(mvm, "couldn't stop scan type %d\n", type);
+               iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
+               return ret;
++      } else if (!wait) {
++              IWL_DEBUG_SCAN(mvm, "no need to wait for scan type %d\n", type);
++              iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
++              return 0;
+       }
+       return iwl_wait_notification(&mvm->notif_wait, &wait_scan_done,
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-iwlwifi-mvm-use-correct-key-iteration.patch b/queue-6.11/wifi-iwlwifi-mvm-use-correct-key-iteration.patch
new file mode 100644 (file)
index 0000000..93338ec
--- /dev/null
@@ -0,0 +1,61 @@
+From 33676494d534d068b6d960647e82b70478a5aee6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 20:20:05 +0300
+Subject: wifi: iwlwifi: mvm: use correct key iteration
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 4f1591d292277eec51d027405a92f0d4ef5e299e ]
+
+In the cases changed here, key iteration isn't done from
+an RCU critical section, but rather using the wiphy lock
+as protection. Therefore, just use ieee80211_iter_keys().
+The link switch case can therefore also use sync commands.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20240729201718.69a2d18580c1.I2148e04d4b467d0b100beac8f7e449bfaaf775a5@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+index 8a38fc4b0b0f9..455f5f4175064 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+@@ -144,7 +144,7 @@ static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw,
+       if (sta != data->sta || key->link_id >= 0)
+               return;
+-      err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cmd), &cmd);
++      err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
+       if (err)
+               data->err = err;
+@@ -162,8 +162,8 @@ int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
+               .new_sta_mask = new_sta_mask,
+       };
+-      ieee80211_iter_keys_rcu(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
+-                              &data);
++      ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
++                          &data);
+       return data.err;
+ }
+@@ -402,7 +402,7 @@ void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
+       if (!sec_key_ver)
+               return;
+-      ieee80211_iter_keys_rcu(mvm->hw, vif,
+-                              iwl_mvm_sec_key_remove_ap_iter,
+-                              (void *)(uintptr_t)link_id);
++      ieee80211_iter_keys(mvm->hw, vif,
++                          iwl_mvm_sec_key_remove_ap_iter,
++                          (void *)(uintptr_t)link_id);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-mac80211-fix-rcu-list-iterations.patch b/queue-6.11/wifi-mac80211-fix-rcu-list-iterations.patch
new file mode 100644 (file)
index 0000000..ffc4505
--- /dev/null
@@ -0,0 +1,84 @@
+From c30be334578c31dc63556d37186bf5b12985bcfd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 09:49:40 +0200
+Subject: wifi: mac80211: fix RCU list iterations
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit ac35180032fbc5d80b29af00ba4881815ceefcb6 ]
+
+There are a number of places where RCU list iteration is
+used, but that aren't (always) called with RCU held. Use
+just list_for_each_entry() in most, and annotate iface
+iteration with the required locks.
+
+Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20240827094939.ed8ac0b2f897.I8443c9c3c0f8051841353491dae758021b53115e@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/chan.c | 4 +++-
+ net/mac80211/mlme.c | 2 +-
+ net/mac80211/scan.c | 2 +-
+ net/mac80211/util.c | 4 +++-
+ 4 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
+index e8567723e94d5..b72e4036526bf 100644
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -286,7 +286,9 @@ ieee80211_get_max_required_bw(struct ieee80211_link_data *link)
+       enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
+       struct sta_info *sta;
+-      list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
++      lockdep_assert_wiphy(sdata->local->hw.wiphy);
++
++      list_for_each_entry(sta, &sdata->local->sta_list, list) {
+               if (sdata != sta->sdata &&
+                   !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
+                       continue;
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 9e3d2ed9cf678..746f51ac03068 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1231,7 +1231,7 @@ static bool ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
+               bool disable_mu_mimo = false;
+               struct ieee80211_sub_if_data *other;
+-              list_for_each_entry_rcu(other, &local->interfaces, list) {
++              list_for_each_entry(other, &local->interfaces, list) {
+                       if (other->vif.bss_conf.mu_mimo_owner) {
+                               disable_mu_mimo = true;
+                               break;
+diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
+index 1c5d99975ad04..3b2bde6360bcb 100644
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -504,7 +504,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
+        * the scan was in progress; if there was none this will
+        * just be a no-op for the particular interface.
+        */
+-      list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++      list_for_each_entry(sdata, &local->interfaces, list) {
+               if (ieee80211_sdata_running(sdata))
+                       wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+       }
+diff --git a/net/mac80211/util.c b/net/mac80211/util.c
+index c7ad9bc5973a0..aed72794d9fe3 100644
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -751,7 +751,9 @@ static void __iterate_interfaces(struct ieee80211_local *local,
+       struct ieee80211_sub_if_data *sdata;
+       bool active_only = iter_flags & IEEE80211_IFACE_ITER_ACTIVE;
+-      list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++      list_for_each_entry_rcu(sdata, &local->interfaces, list,
++                              lockdep_is_held(&local->iflist_mtx) ||
++                              lockdep_is_held(&local->hw.wiphy->mtx)) {
+               switch (sdata->vif.type) {
+               case NL80211_IFTYPE_MONITOR:
+                       if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-mt76-mt7915-add-dummy-hw-offload-of-ieee-802.11.patch b/queue-6.11/wifi-mt76-mt7915-add-dummy-hw-offload-of-ieee-802.11.patch
new file mode 100644 (file)
index 0000000..2240834
--- /dev/null
@@ -0,0 +1,62 @@
+From 2c2665f81f8800ec49bc712bd7edbb200543b262 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 11:30:03 +0200
+Subject: wifi: mt76: mt7915: add dummy HW offload of IEEE 802.11 fragmentation
+
+From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+
+[ Upstream commit f2cc859149240d910fdc6405717673e0b84bfda8 ]
+
+Currently, CONNAC2 series do not support encryption for fragmented Tx frames.
+Therefore, add dummy function mt7915_set_frag_threshold() to prevent SW
+IEEE 802.11 fragmentation.
+
+Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
+Link: https://patch.msgid.link/20240827093011.18621-16-nbd@nbd.name
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 +
+ drivers/net/wireless/mediatek/mt76/mt7915/main.c | 7 +++++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+index 7bc3b4cd35925..6bef96e3d2a3d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+@@ -400,6 +400,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
+       ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
+       ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
+       ieee80211_hw_set(hw, WANT_MONITOR_VIF);
++      ieee80211_hw_set(hw, SUPPORTS_TX_FRAG);
+       hw->max_tx_fragments = 4;
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+index efbb8b23e4719..e094358005799 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+@@ -1577,6 +1577,12 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw,
+       mutex_unlock(&dev->mt76.mutex);
+ }
++static int
++mt7915_set_frag_threshold(struct ieee80211_hw *hw, u32 val)
++{
++      return 0;
++}
++
+ static int
+ mt7915_set_radar_background(struct ieee80211_hw *hw,
+                           struct cfg80211_chan_def *chandef)
+@@ -1707,6 +1713,7 @@ const struct ieee80211_ops mt7915_ops = {
+       .sta_set_decap_offload = mt7915_sta_set_decap_offload,
+       .add_twt_setup = mt7915_mac_add_twt_setup,
+       .twt_teardown_request = mt7915_twt_teardown_request,
++      .set_frag_threshold = mt7915_set_frag_threshold,
+       CFG80211_TESTMODE_CMD(mt76_testmode_cmd)
+       CFG80211_TESTMODE_DUMP(mt76_testmode_dump)
+ #ifdef CONFIG_MAC80211_DEBUGFS
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-mt76-mt7915-disable-tx-worker-during-tx-ba-sess.patch b/queue-6.11/wifi-mt76-mt7915-disable-tx-worker-during-tx-ba-sess.patch
new file mode 100644 (file)
index 0000000..69f588d
--- /dev/null
@@ -0,0 +1,47 @@
+From 376952ee27f877fa3068e52ea2285b67c04076a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 11:29:54 +0200
+Subject: wifi: mt76: mt7915: disable tx worker during tx BA session
+ enable/disable
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit 256cbd26fbafb30ba3314339106e5c594e9bd5f9 ]
+
+Avoids firmware race condition.
+
+Link: https://patch.msgid.link/20240827093011.18621-7-nbd@nbd.name
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+index 2185cd24e2e1c..2f4755820b3cd 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+@@ -690,13 +690,17 @@ int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev,
+ {
+       struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv;
+       struct mt7915_vif *mvif = msta->vif;
++      int ret;
++      mt76_worker_disable(&dev->mt76.tx_worker);
+       if (enable && !params->amsdu)
+               msta->wcid.amsdu = false;
++      ret = mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
++                                   MCU_EXT_CMD(STA_REC_UPDATE),
++                                   enable, true);
++      mt76_worker_enable(&dev->mt76.tx_worker);
+-      return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
+-                                    MCU_EXT_CMD(STA_REC_UPDATE),
+-                                    enable, true);
++      return ret;
+ }
+ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-mt76-mt7915-hold-dev-mt76.mutex-while-disabling.patch b/queue-6.11/wifi-mt76-mt7915-hold-dev-mt76.mutex-while-disabling.patch
new file mode 100644 (file)
index 0000000..f11c57b
--- /dev/null
@@ -0,0 +1,41 @@
+From 8955cb96d6e7b3fbeb10595e22bedb95f04b4cef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 11:30:04 +0200
+Subject: wifi: mt76: mt7915: hold dev->mt76.mutex while disabling tx worker
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit 8f7152f10cb434f954aeff85ca1be9cd4d01912b ]
+
+Prevent racing against other functions disabling the same worker
+
+Link: https://patch.msgid.link/20240827093011.18621-17-nbd@nbd.name
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+index 8008ce3fa6c7e..387d47e9fcd38 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+@@ -1537,12 +1537,14 @@ void mt7915_mac_reset_work(struct work_struct *work)
+               set_bit(MT76_RESET, &phy2->mt76->state);
+               cancel_delayed_work_sync(&phy2->mt76->mac_work);
+       }
++
++      mutex_lock(&dev->mt76.mutex);
++
+       mt76_worker_disable(&dev->mt76.tx_worker);
+       mt76_for_each_q_rx(&dev->mt76, i)
+               napi_disable(&dev->mt76.napi[i]);
+       napi_disable(&dev->mt76.tx_napi);
+-      mutex_lock(&dev->mt76.mutex);
+       if (mtk_wed_device_active(&dev->mt76.mmio.wed))
+               mtk_wed_device_stop(&dev->mt76.mmio.wed);
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch b/queue-6.11/wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch
new file mode 100644 (file)
index 0000000..9d4a1ed
--- /dev/null
@@ -0,0 +1,62 @@
+From e54de896818fd74802f06d3d0ef16cc7e8c394a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 15:23:51 -0600
+Subject: wifi: mwifiex: Fix memcpy() field-spanning write warning in
+ mwifiex_cmd_802_11_scan_ext()
+
+From: Gustavo A. R. Silva <gustavoars@kernel.org>
+
+[ Upstream commit 498365e52bebcbc36a93279fe7e9d6aec8479cee ]
+
+Replace one-element array with a flexible-array member in
+`struct host_cmd_ds_802_11_scan_ext`.
+
+With this, fix the following warning:
+
+elo 16 17:51:58 surfacebook kernel: ------------[ cut here ]------------
+elo 16 17:51:58 surfacebook kernel: memcpy: detected field-spanning write (size 243) of single field "ext_scan->tlv_buffer" at drivers/net/wireless/marvell/mwifiex/scan.c:2239 (size 1)
+elo 16 17:51:58 surfacebook kernel: WARNING: CPU: 0 PID: 498 at drivers/net/wireless/marvell/mwifiex/scan.c:2239 mwifiex_cmd_802_11_scan_ext+0x83/0x90 [mwifiex]
+
+Reported-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Closes: https://lore.kernel.org/linux-hardening/ZsZNgfnEwOcPdCly@black.fi.intel.com/
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Acked-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://patch.msgid.link/ZsZa5xRcsLq9D+RX@elsanto
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/marvell/mwifiex/fw.h   | 2 +-
+ drivers/net/wireless/marvell/mwifiex/scan.c | 3 +--
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
+index 3adc447b715f6..5b072120e3f21 100644
+--- a/drivers/net/wireless/marvell/mwifiex/fw.h
++++ b/drivers/net/wireless/marvell/mwifiex/fw.h
+@@ -1587,7 +1587,7 @@ struct host_cmd_ds_802_11_scan_rsp {
+ struct host_cmd_ds_802_11_scan_ext {
+       u32   reserved;
+-      u8    tlv_buffer[1];
++      u8    tlv_buffer[];
+ } __packed;
+ struct mwifiex_ie_types_bss_mode {
+diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
+index 0326b121747cb..17ce84f5207e3 100644
+--- a/drivers/net/wireless/marvell/mwifiex/scan.c
++++ b/drivers/net/wireless/marvell/mwifiex/scan.c
+@@ -2530,8 +2530,7 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
+       ext_scan_resp = &resp->params.ext_scan;
+       tlv = (void *)ext_scan_resp->tlv_buffer;
+-      buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
+-                                            - 1);
++      buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN);
+       while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
+               type = le16_to_cpu(tlv->type);
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-rtw88-select-want_dev_coredump.patch b/queue-6.11/wifi-rtw88-select-want_dev_coredump.patch
new file mode 100644 (file)
index 0000000..64a4b8f
--- /dev/null
@@ -0,0 +1,35 @@
+From 65ff41724ac860018044a858d5174e418d9e3a70 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jul 2024 15:06:15 +0800
+Subject: wifi: rtw88: select WANT_DEV_COREDUMP
+
+From: Zong-Zhe Yang <kevin_yang@realtek.com>
+
+[ Upstream commit 7e989b0c1e33210c07340bf5228aa83ea52515b5 ]
+
+We have invoked device coredump when fw crash.
+Should select WANT_DEV_COREDUMP by ourselves.
+
+Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240718070616.42217-1-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw88/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
+index 22838ede03cd8..02b0d698413be 100644
+--- a/drivers/net/wireless/realtek/rtw88/Kconfig
++++ b/drivers/net/wireless/realtek/rtw88/Kconfig
+@@ -12,6 +12,7 @@ if RTW88
+ config RTW88_CORE
+       tristate
++      select WANT_DEV_COREDUMP
+ config RTW88_PCI
+       tristate
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-rtw89-885xb-reset-idmem-mode-to-prevent-downloa.patch b/queue-6.11/wifi-rtw89-885xb-reset-idmem-mode-to-prevent-downloa.patch
new file mode 100644 (file)
index 0000000..3591dc2
--- /dev/null
@@ -0,0 +1,62 @@
+From 64a1c6dfbc3d1aaad9ec85287a6d09d10fc4d9d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jul 2024 13:26:25 +0800
+Subject: wifi: rtw89: 885xb: reset IDMEM mode to prevent download firmware
+ failure
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 80fb81bb46a57daedd5decbcc253ea48428a254e ]
+
+For different firmware type, it could change IDMEM mode, so reset it to
+default to avoid encountering error for RTL8851B/RTL8852B/RTL8852BT
+if that kind of firmware was downloaded before.
+
+    rtw89_8851be 0000:02:00.0: Firmware version 0.29.41.3, cmd version 0, type 5
+    rtw89_8851be 0000:02:00.0: Firmware version 0.29.41.3, cmd version 0, type 3
+    rtw89_8851be 0000:02:00.0: MAC has already powered on
+    rtw89_8851be 0000:02:00.0: fw security fail
+    rtw89_8851be 0000:02:00.0: download firmware fail
+    rtw89_8851be 0000:02:00.0: [ERR]fwdl 0x1E0 = 0x62
+    rtw89_8851be 0000:02:00.0: [ERR]fwdl 0x83F2 = 0x8
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f51c
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f524
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f51c
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f500
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f51c
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f53c
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f520
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f520
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f508
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f534
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f520
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f534
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f508
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f53c
+    rtw89_8851be 0000:02:00.0: [ERR]fw PC = 0xb892f524
+    rtw89_8851be 0000:02:00.0: failed to setup chip information
+    rtw89_8851be: probe of 0000:02:00.0 failed with error -16
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240724052626.12774-4-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/mac.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
+index 9a4f23d83bf2a..5c07db4f471d6 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac.c
++++ b/drivers/net/wireless/realtek/rtw89/mac.c
+@@ -3788,7 +3788,7 @@ static int rtw89_mac_enable_cpu_ax(struct rtw89_dev *rtwdev, u8 boot_reason,
+       rtw89_write32(rtwdev, R_AX_WCPU_FW_CTRL, val);
+-      if (rtwdev->chip->chip_id == RTL8852B)
++      if (rtw89_is_rtl885xb(rtwdev))
+               rtw89_write32_mask(rtwdev, R_AX_SEC_CTRL,
+                                  B_AX_SEC_IDMEM_SIZE_CONFIG_MASK, 0x2);
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-rtw89-avoid-reading-out-of-bounds-when-loading-.patch b/queue-6.11/wifi-rtw89-avoid-reading-out-of-bounds-when-loading-.patch
new file mode 100644 (file)
index 0000000..34179f1
--- /dev/null
@@ -0,0 +1,60 @@
+From e2da386fc9eeeb7f8d037964018908ede89c0e19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Sep 2024 09:58:03 +0800
+Subject: wifi: rtw89: avoid reading out of bounds when loading TX power FW
+ elements
+
+From: Zong-Zhe Yang <kevin_yang@realtek.com>
+
+[ Upstream commit ed2e4bb17a4884cf29c3347353d8aabb7265b46c ]
+
+Because the loop-expression will do one more time before getting false from
+cond-expression, the original code copied one more entry size beyond valid
+region.
+
+Fix it by moving the entry copy to loop-body.
+
+Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240902015803.20420-1-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/core.h | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
+index 9c282d84743b9..46dfb0b294db9 100644
+--- a/drivers/net/wireless/realtek/rtw89/core.h
++++ b/drivers/net/wireless/realtek/rtw89/core.h
+@@ -3909,16 +3909,22 @@ struct rtw89_txpwr_conf {
+       const void *data;
+ };
++static inline bool rtw89_txpwr_entcpy(void *entry, const void *cursor, u8 size,
++                                    const struct rtw89_txpwr_conf *conf)
++{
++      u8 valid_size = min(size, conf->ent_sz);
++
++      memcpy(entry, cursor, valid_size);
++      return true;
++}
++
+ #define rtw89_txpwr_conf_valid(conf) (!!(conf)->data)
+ #define rtw89_for_each_in_txpwr_conf(entry, cursor, conf) \
+-      for (typecheck(const void *, cursor), (cursor) = (conf)->data, \
+-           memcpy(&(entry), cursor, \
+-                  min_t(u8, sizeof(entry), (conf)->ent_sz)); \
++      for (typecheck(const void *, cursor), (cursor) = (conf)->data; \
+            (cursor) < (conf)->data + (conf)->num_ents * (conf)->ent_sz; \
+-           (cursor) += (conf)->ent_sz, \
+-           memcpy(&(entry), cursor, \
+-                  min_t(u8, sizeof(entry), (conf)->ent_sz)))
++           (cursor) += (conf)->ent_sz) \
++              if (rtw89_txpwr_entcpy(&(entry), cursor, sizeof(entry), conf))
+ struct rtw89_txpwr_byrate_data {
+       struct rtw89_txpwr_conf conf;
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-rtw89-avoid-to-add-interface-to-list-twice-when.patch b/queue-6.11/wifi-rtw89-avoid-to-add-interface-to-list-twice-when.patch
new file mode 100644 (file)
index 0000000..02e084f
--- /dev/null
@@ -0,0 +1,124 @@
+From 19213e05cb809d6d01b51bcde96b52c7cf472ddd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 15:05:04 +0800
+Subject: wifi: rtw89: avoid to add interface to list twice when SER
+
+From: Chih-Kang Chang <gary.chang@realtek.com>
+
+[ Upstream commit 7dd5d2514a8ea58f12096e888b0bd050d7eae20a ]
+
+If SER L2 occurs during the WoWLAN resume flow, the add interface flow
+is triggered by ieee80211_reconfig(). However, due to
+rtw89_wow_resume() return failure, it will cause the add interface flow
+to be executed again, resulting in a double add list and causing a kernel
+panic. Therefore, we have added a check to prevent double adding of the
+list.
+
+list_add double add: new=ffff99d6992e2010, prev=ffff99d6992e2010, next=ffff99d695302628.
+------------[ cut here ]------------
+kernel BUG at lib/list_debug.c:37!
+invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
+CPU: 0 PID: 9 Comm: kworker/0:1 Tainted: G        W  O       6.6.30-02659-gc18865c4dfbd #1 770df2933251a0e3c888ba69d1053a817a6376a7
+Hardware name: HP Grunt/Grunt, BIOS Google_Grunt.11031.169.0 06/24/2021
+Workqueue: events_freezable ieee80211_restart_work [mac80211]
+RIP: 0010:__list_add_valid_or_report+0x5e/0xb0
+Code: c7 74 18 48 39 ce 74 13 b0 01 59 5a 5e 5f 41 58 41 59 41 5a 5d e9 e2 d6 03 00 cc 48 c7 c7 8d 4f 17 83 48 89 c2 e8 02 c0 00 00 <0f> 0b 48 c7 c7 aa 8c 1c 83 e8 f4 bf 00 00 0f 0b 48 c7 c7 c8 bc 12
+RSP: 0018:ffffa91b8007bc50 EFLAGS: 00010246
+RAX: 0000000000000058 RBX: ffff99d6992e0900 RCX: a014d76c70ef3900
+RDX: ffffa91b8007bae8 RSI: 00000000ffffdfff RDI: 0000000000000001
+RBP: ffffa91b8007bc88 R08: 0000000000000000 R09: ffffa91b8007bae0
+R10: 00000000ffffdfff R11: ffffffff83a79800 R12: ffff99d695302060
+R13: ffff99d695300900 R14: ffff99d6992e1be0 R15: ffff99d6992e2010
+FS:  0000000000000000(0000) GS:ffff99d6aac00000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 000078fbdba43480 CR3: 000000010e464000 CR4: 00000000001506f0
+Call Trace:
+ <TASK>
+ ? __die_body+0x1f/0x70
+ ? die+0x3d/0x60
+ ? do_trap+0xa4/0x110
+ ? __list_add_valid_or_report+0x5e/0xb0
+ ? do_error_trap+0x6d/0x90
+ ? __list_add_valid_or_report+0x5e/0xb0
+ ? handle_invalid_op+0x30/0x40
+ ? __list_add_valid_or_report+0x5e/0xb0
+ ? exc_invalid_op+0x3c/0x50
+ ? asm_exc_invalid_op+0x16/0x20
+ ? __list_add_valid_or_report+0x5e/0xb0
+ rtw89_ops_add_interface+0x309/0x310 [rtw89_core 7c32b1ee6854761c0321027c8a58c5160e41f48f]
+ drv_add_interface+0x5c/0x130 [mac80211 83e989e6e616bd5b4b8a2b0a9f9352a2c385a3bc]
+ ieee80211_reconfig+0x241/0x13d0 [mac80211 83e989e6e616bd5b4b8a2b0a9f9352a2c385a3bc]
+ ? finish_wait+0x3e/0x90
+ ? synchronize_rcu_expedited+0x174/0x260
+ ? sync_rcu_exp_done_unlocked+0x50/0x50
+ ? wake_bit_function+0x40/0x40
+ ieee80211_restart_work+0xf0/0x140 [mac80211 83e989e6e616bd5b4b8a2b0a9f9352a2c385a3bc]
+ process_scheduled_works+0x1e5/0x480
+ worker_thread+0xea/0x1e0
+ kthread+0xdb/0x110
+ ? move_linked_works+0x90/0x90
+ ? kthread_associate_blkcg+0xa0/0xa0
+ ret_from_fork+0x3b/0x50
+ ? kthread_associate_blkcg+0xa0/0xa0
+ ret_from_fork_asm+0x11/0x20
+ </TASK>
+Modules linked in: dm_integrity async_xor xor async_tx lz4 lz4_compress zstd zstd_compress zram zsmalloc rfcomm cmac uinput algif_hash algif_skcipher af_alg btusb btrtl iio_trig_hrtimer industrialio_sw_trigger btmtk industrialio_configfs btbcm btintel uvcvideo videobuf2_vmalloc iio_trig_sysfs videobuf2_memops videobuf2_v4l2 videobuf2_common uvc snd_hda_codec_hdmi veth snd_hda_intel snd_intel_dspcfg acpi_als snd_hda_codec industrialio_triggered_buffer kfifo_buf snd_hwdep industrialio i2c_piix4 snd_hda_core designware_i2s ip6table_nat snd_soc_max98357a xt_MASQUERADE xt_cgroup snd_soc_acp_rt5682_mach fuse rtw89_8922ae(O) rtw89_8922a(O) rtw89_pci(O) rtw89_core(O) 8021q mac80211(O) bluetooth ecdh_generic ecc cfg80211 r8152 mii joydev
+gsmi: Log Shutdown Reason 0x03
+---[ end trace 0000000000000000 ]---
+
+Signed-off-by: Chih-Kang Chang <gary.chang@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240731070506.46100-4-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/mac80211.c |  4 +++-
+ drivers/net/wireless/realtek/rtw89/util.h     | 18 ++++++++++++++++++
+ 2 files changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
+index 1508693032cb2..de3e7e4c6e76b 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
+@@ -126,7 +126,9 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
+       rtwvif->rtwdev = rtwdev;
+       rtwvif->roc.state = RTW89_ROC_IDLE;
+       rtwvif->offchan = false;
+-      list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
++      if (!rtw89_rtwvif_in_list(rtwdev, rtwvif))
++              list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
++
+       INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work);
+       INIT_DELAYED_WORK(&rtwvif->roc.roc_work, rtw89_roc_work);
+       rtw89_leave_ps_mode(rtwdev);
+diff --git a/drivers/net/wireless/realtek/rtw89/util.h b/drivers/net/wireless/realtek/rtw89/util.h
+index e82e7df052d88..e669544cafd3f 100644
+--- a/drivers/net/wireless/realtek/rtw89/util.h
++++ b/drivers/net/wireless/realtek/rtw89/util.h
+@@ -16,6 +16,24 @@
+ #define rtw89_for_each_rtwvif(rtwdev, rtwvif)                                \
+       list_for_each_entry(rtwvif, &(rtwdev)->rtwvifs_list, list)
++/* Before adding rtwvif to list, we need to check if it already exist, beacase
++ * in some case such as SER L2 happen during WoWLAN flow, calling reconfig
++ * twice cause the list to be added twice.
++ */
++static inline bool rtw89_rtwvif_in_list(struct rtw89_dev *rtwdev,
++                                      struct rtw89_vif *new)
++{
++      struct rtw89_vif *rtwvif;
++
++      lockdep_assert_held(&rtwdev->mutex);
++
++      rtw89_for_each_rtwvif(rtwdev, rtwvif)
++              if (rtwvif == new)
++                      return true;
++
++      return false;
++}
++
+ /* The result of negative dividend and positive divisor is undefined, but it
+  * should be one case of round-down or round-up. So, make it round-down if the
+  * result is round-up.
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-rtw89-correct-base-ht-rate-mask-for-firmware.patch b/queue-6.11/wifi-rtw89-correct-base-ht-rate-mask-for-firmware.patch
new file mode 100644 (file)
index 0000000..2772f5b
--- /dev/null
@@ -0,0 +1,53 @@
+From 83f4867c5d33bdcd8150bc5deb3ea2cb75a60699 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Aug 2024 15:20:10 +0800
+Subject: wifi: rtw89: correct base HT rate mask for firmware
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 45742881f9eee2a4daeb6008e648a460dd3742cd ]
+
+Coverity reported that u8 rx_mask << 24 will become signed 32 bits, which
+casting to unsigned 64 bits will do sign extension. For example,
+putting 0x80000000 (signed 32 bits) to a u64 variable will become
+0xFFFFFFFF_80000000.
+
+The real case we meet is:
+  rx_mask[0...3] = ff ff 00 00
+  ra_mask = 0xffffffff_ff0ff000
+
+After this fix:
+  rx_mask[0...3] = ff ff 00 00
+  ra_mask = 0x00000000_ff0ff000
+
+Fortunately driver does bitwise-AND with incorrect ra_mask and supported
+rates (1ss and 2ss rate only) afterward, so the final rate mask of
+original code is still correct.
+
+Addresses-Coverity-ID: 1504762 ("Unintended sign extension")
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240809072012.84152-5-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/phy.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
+index ad11d1414874a..c038e5ca3e45a 100644
+--- a/drivers/net/wireless/realtek/rtw89/phy.c
++++ b/drivers/net/wireless/realtek/rtw89/phy.c
+@@ -353,8 +353,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
+               csi_mode = RTW89_RA_RPT_MODE_HT;
+               ra_mask |= ((u64)sta->deflink.ht_cap.mcs.rx_mask[3] << 48) |
+                          ((u64)sta->deflink.ht_cap.mcs.rx_mask[2] << 36) |
+-                         (sta->deflink.ht_cap.mcs.rx_mask[1] << 24) |
+-                         (sta->deflink.ht_cap.mcs.rx_mask[0] << 12);
++                         ((u64)sta->deflink.ht_cap.mcs.rx_mask[1] << 24) |
++                         ((u64)sta->deflink.ht_cap.mcs.rx_mask[0] << 12);
+               high_rate_masks = rtw89_ra_mask_ht_rates;
+               if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
+                       stbc_en = 1;
+-- 
+2.43.0
+
diff --git a/queue-6.11/wifi-wilc1000-do-not-operate-uninitialized-hardware-.patch b/queue-6.11/wifi-wilc1000-do-not-operate-uninitialized-hardware-.patch
new file mode 100644 (file)
index 0000000..6f45849
--- /dev/null
@@ -0,0 +1,59 @@
+From 81f1e1044d82f43e0283f02d1f5cd4fa2fa66265 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 20:36:03 +0200
+Subject: wifi: wilc1000: Do not operate uninitialized hardware during
+ suspend/resume
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit b0dc7018477e8fbb7e40c908c29cf663d06b17a7 ]
+
+In case the hardware is not initialized, do not operate it during
+suspend/resume cycle, the hardware is already off so there is no
+reason to access it.
+
+In fact, wilc_sdio_enable_interrupt() in the resume callback does
+interfere with the same call when initializing the hardware after
+resume and makes such initialization after resume fail. Fix this
+by not operating uninitialized hardware during suspend/resume.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Alexis Lothoré <alexis.lothore@bootlin.com>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://patch.msgid.link/20240821183639.163187-1-marex@denx.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/microchip/wilc1000/sdio.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c
+index 0043f7a0fdf97..7999aeb76901f 100644
+--- a/drivers/net/wireless/microchip/wilc1000/sdio.c
++++ b/drivers/net/wireless/microchip/wilc1000/sdio.c
+@@ -977,6 +977,9 @@ static int wilc_sdio_suspend(struct device *dev)
+       dev_info(dev, "sdio suspend\n");
++      if (!wilc->initialized)
++              return 0;
++
+       if (!IS_ERR(wilc->rtc_clk))
+               clk_disable_unprepare(wilc->rtc_clk);
+@@ -999,6 +1002,10 @@ static int wilc_sdio_resume(struct device *dev)
+       struct wilc *wilc = sdio_get_drvdata(func);
+       dev_info(dev, "sdio resume\n");
++
++      if (!wilc->initialized)
++              return 0;
++
+       wilc_sdio_init(wilc, true);
+       wilc_sdio_enable_interrupt(wilc);
+-- 
+2.43.0
+
diff --git a/queue-6.11/x86-apic-remove-logical-destination-mode-for-64-bit.patch b/queue-6.11/x86-apic-remove-logical-destination-mode-for-64-bit.patch
new file mode 100644 (file)
index 0000000..474dc24
--- /dev/null
@@ -0,0 +1,229 @@
+From aeea671f4643b1cf44eeadb5a8064fe9aa2bb456 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 28 Jul 2024 13:06:10 +0200
+Subject: x86/apic: Remove logical destination mode for 64-bit
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 838ba7733e4e3a94a928e8d0a058de1811a58621 ]
+
+Logical destination mode of the local APIC is used for systems with up to
+8 CPUs. It has an advantage over physical destination mode as it allows to
+target multiple CPUs at once with IPIs.
+
+That advantage was definitely worth it when systems with up to 8 CPUs
+were state of the art for servers and workstations, but that's history.
+
+Aside of that there are systems which fail to work with logical destination
+mode as the ACPI/DMI quirks show and there are AMD Zen1 systems out there
+which fail when interrupt remapping is enabled as reported by Rob and
+Christian. The latter problem can be cured by firmware updates, but not all
+OEMs distribute the required changes.
+
+Physical destination mode is guaranteed to work because it is the only way
+to get a CPU up and running via the INIT/INIT/STARTUP sequence.
+
+As the number of CPUs keeps increasing, logical destination mode becomes a
+less used code path so there is no real good reason to keep it around.
+
+Therefore remove logical destination mode support for 64-bit and default to
+physical destination mode.
+
+Reported-by: Rob Newcater <rob@durendal.co.uk>
+Reported-by: Christian Heusel <christian@heusel.eu>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Borislav Petkov (AMD) <bp@alien8.de>
+Tested-by: Rob Newcater <rob@durendal.co.uk>
+Link: https://lore.kernel.org/all/877cd5u671.ffs@tglx
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/apic.h         |   8 --
+ arch/x86/kernel/apic/apic_flat_64.c | 119 ++--------------------------
+ 2 files changed, 7 insertions(+), 120 deletions(-)
+
+diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
+index 9327eb00e96d0..be2045a18e69b 100644
+--- a/arch/x86/include/asm/apic.h
++++ b/arch/x86/include/asm/apic.h
+@@ -345,20 +345,12 @@ extern struct apic *apic;
+  * APIC drivers are probed based on how they are listed in the .apicdrivers
+  * section. So the order is important and enforced by the ordering
+  * of different apic driver files in the Makefile.
+- *
+- * For the files having two apic drivers, we use apic_drivers()
+- * to enforce the order with in them.
+  */
+ #define apic_driver(sym)                                      \
+       static const struct apic *__apicdrivers_##sym __used            \
+       __aligned(sizeof(struct apic *))                        \
+       __section(".apicdrivers") = { &sym }
+-#define apic_drivers(sym1, sym2)                                      \
+-      static struct apic *__apicdrivers_##sym1##sym2[2] __used        \
+-      __aligned(sizeof(struct apic *))                                \
+-      __section(".apicdrivers") = { &sym1, &sym2 }
+-
+ extern struct apic *__apicdrivers[], *__apicdrivers_end[];
+ /*
+diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
+index f37ad3392fec9..e0308d8c4e6c2 100644
+--- a/arch/x86/kernel/apic/apic_flat_64.c
++++ b/arch/x86/kernel/apic/apic_flat_64.c
+@@ -8,129 +8,25 @@
+  * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+  * James Cleverdon.
+  */
+-#include <linux/cpumask.h>
+ #include <linux/export.h>
+-#include <linux/acpi.h>
+-#include <asm/jailhouse_para.h>
+ #include <asm/apic.h>
+ #include "local.h"
+-static struct apic apic_physflat;
+-static struct apic apic_flat;
+-
+-struct apic *apic __ro_after_init = &apic_flat;
+-EXPORT_SYMBOL_GPL(apic);
+-
+-static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+-{
+-      return 1;
+-}
+-
+-static void _flat_send_IPI_mask(unsigned long mask, int vector)
+-{
+-      unsigned long flags;
+-
+-      local_irq_save(flags);
+-      __default_send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL);
+-      local_irq_restore(flags);
+-}
+-
+-static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
+-{
+-      unsigned long mask = cpumask_bits(cpumask)[0];
+-
+-      _flat_send_IPI_mask(mask, vector);
+-}
+-
+-static void
+-flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
+-{
+-      unsigned long mask = cpumask_bits(cpumask)[0];
+-      int cpu = smp_processor_id();
+-
+-      if (cpu < BITS_PER_LONG)
+-              __clear_bit(cpu, &mask);
+-
+-      _flat_send_IPI_mask(mask, vector);
+-}
+-
+-static u32 flat_get_apic_id(u32 x)
++static u32 physflat_get_apic_id(u32 x)
+ {
+       return (x >> 24) & 0xFF;
+ }
+-static int flat_probe(void)
++static int physflat_probe(void)
+ {
+       return 1;
+ }
+-static struct apic apic_flat __ro_after_init = {
+-      .name                           = "flat",
+-      .probe                          = flat_probe,
+-      .acpi_madt_oem_check            = flat_acpi_madt_oem_check,
+-
+-      .dest_mode_logical              = true,
+-
+-      .disable_esr                    = 0,
+-
+-      .init_apic_ldr                  = default_init_apic_ldr,
+-      .cpu_present_to_apicid          = default_cpu_present_to_apicid,
+-
+-      .max_apic_id                    = 0xFE,
+-      .get_apic_id                    = flat_get_apic_id,
+-
+-      .calc_dest_apicid               = apic_flat_calc_apicid,
+-
+-      .send_IPI                       = default_send_IPI_single,
+-      .send_IPI_mask                  = flat_send_IPI_mask,
+-      .send_IPI_mask_allbutself       = flat_send_IPI_mask_allbutself,
+-      .send_IPI_allbutself            = default_send_IPI_allbutself,
+-      .send_IPI_all                   = default_send_IPI_all,
+-      .send_IPI_self                  = default_send_IPI_self,
+-      .nmi_to_offline_cpu             = true,
+-
+-      .read                           = native_apic_mem_read,
+-      .write                          = native_apic_mem_write,
+-      .eoi                            = native_apic_mem_eoi,
+-      .icr_read                       = native_apic_icr_read,
+-      .icr_write                      = native_apic_icr_write,
+-      .wait_icr_idle                  = apic_mem_wait_icr_idle,
+-      .safe_wait_icr_idle             = apic_mem_wait_icr_idle_timeout,
+-};
+-
+-/*
+- * Physflat mode is used when there are more than 8 CPUs on a system.
+- * We cannot use logical delivery in this case because the mask
+- * overflows, so use physical mode.
+- */
+ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+ {
+-#ifdef CONFIG_ACPI
+-      /*
+-       * Quirk: some x86_64 machines can only use physical APIC mode
+-       * regardless of how many processors are present (x86_64 ES7000
+-       * is an example).
+-       */
+-      if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
+-              (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
+-              printk(KERN_DEBUG "system APIC only can use physical flat");
+-              return 1;
+-      }
+-
+-      if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) {
+-              printk(KERN_DEBUG "IBM Summit detected, will use apic physical");
+-              return 1;
+-      }
+-#endif
+-
+-      return 0;
+-}
+-
+-static int physflat_probe(void)
+-{
+-      return apic == &apic_physflat || num_possible_cpus() > 8 || jailhouse_paravirt();
++      return 1;
+ }
+ static struct apic apic_physflat __ro_after_init = {
+@@ -146,7 +42,7 @@ static struct apic apic_physflat __ro_after_init = {
+       .cpu_present_to_apicid          = default_cpu_present_to_apicid,
+       .max_apic_id                    = 0xFE,
+-      .get_apic_id                    = flat_get_apic_id,
++      .get_apic_id                    = physflat_get_apic_id,
+       .calc_dest_apicid               = apic_default_calc_apicid,
+@@ -166,8 +62,7 @@ static struct apic apic_physflat __ro_after_init = {
+       .wait_icr_idle                  = apic_mem_wait_icr_idle,
+       .safe_wait_icr_idle             = apic_mem_wait_icr_idle_timeout,
+ };
++apic_driver(apic_physflat);
+-/*
+- * We need to check for physflat first, so this order is important.
+- */
+-apic_drivers(apic_physflat, apic_flat);
++struct apic *apic __ro_after_init = &apic_physflat;
++EXPORT_SYMBOL_GPL(apic);
+-- 
+2.43.0
+
diff --git a/queue-6.11/x86-bugs-add-missing-no_ssb-flag.patch b/queue-6.11/x86-bugs-add-missing-no_ssb-flag.patch
new file mode 100644 (file)
index 0000000..e78bc35
--- /dev/null
@@ -0,0 +1,46 @@
+From b43592d7bde7258ba16cd5a2f30c3f598c64ca4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Aug 2024 12:24:37 -0700
+Subject: x86/bugs: Add missing NO_SSB flag
+
+From: Daniel Sneddon <daniel.sneddon@linux.intel.com>
+
+[ Upstream commit 23e12b54acf621f4f03381dca91cc5f1334f21fd ]
+
+The Moorefield and Lightning Mountain Atom processors are
+missing the NO_SSB flag in the vulnerabilities whitelist.
+This will cause unaffected parts to incorrectly be reported
+as vulnerable. Add the missing flag.
+
+These parts are currently out of service and were verified
+internally with archived documentation that they need the
+NO_SSB flag.
+
+Closes: https://lore.kernel.org/lkml/CAEJ9NQdhh+4GxrtG1DuYgqYhvc0hi-sKZh-2niukJ-MyFLntAA@mail.gmail.com/
+Reported-by: Shanavas.K.S <shanavasks@gmail.com>
+Signed-off-by: Daniel Sneddon <daniel.sneddon@linux.intel.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20240829192437.4074196-1-daniel.sneddon@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/cpu/common.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index d4e539d4e158c..be307c9ef263d 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -1165,8 +1165,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
+       VULNWL_INTEL(INTEL_CORE_YONAH,          NO_SSB),
+-      VULNWL_INTEL(INTEL_ATOM_AIRMONT_MID,    NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
+-      VULNWL_INTEL(INTEL_ATOM_AIRMONT_NP,     NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
++      VULNWL_INTEL(INTEL_ATOM_AIRMONT_MID,    NO_SSB | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | MSBDS_ONLY),
++      VULNWL_INTEL(INTEL_ATOM_AIRMONT_NP,     NO_SSB | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
+       VULNWL_INTEL(INTEL_ATOM_GOLDMONT,       NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_INTEL(INTEL_ATOM_GOLDMONT_D,     NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+-- 
+2.43.0
+
diff --git a/queue-6.11/x86-bugs-fix-handling-when-srso-mitigation-is-disabl.patch b/queue-6.11/x86-bugs-fix-handling-when-srso-mitigation-is-disabl.patch
new file mode 100644 (file)
index 0000000..446959a
--- /dev/null
@@ -0,0 +1,69 @@
+From 9b271adfa5bbc75940e3a760ca087df61fc35716 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Sep 2024 10:07:11 -0500
+Subject: x86/bugs: Fix handling when SRSO mitigation is disabled
+
+From: David Kaplan <david.kaplan@amd.com>
+
+[ Upstream commit 1dbb6b1495d472806fef1f4c94f5b3e4c89a3c1d ]
+
+When the SRSO mitigation is disabled, either via mitigations=off or
+spec_rstack_overflow=off, the warning about the lack of IBPB-enhancing
+microcode is printed anyway.
+
+This is unnecessary since the user has turned off the mitigation.
+
+  [ bp: Massage, drop SBPB rationale as it doesn't matter because when
+    mitigations are disabled x86_pred_cmd is not being used anyway. ]
+
+Signed-off-by: David Kaplan <david.kaplan@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
+Link: https://lore.kernel.org/r/20240904150711.193022-1-david.kaplan@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/cpu/bugs.c | 14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index 45675da354f33..468449f73a957 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -2551,10 +2551,9 @@ static void __init srso_select_mitigation(void)
+ {
+       bool has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE);
+-      if (cpu_mitigations_off())
+-              return;
+-
+-      if (!boot_cpu_has_bug(X86_BUG_SRSO)) {
++      if (!boot_cpu_has_bug(X86_BUG_SRSO) ||
++          cpu_mitigations_off() ||
++          srso_cmd == SRSO_CMD_OFF) {
+               if (boot_cpu_has(X86_FEATURE_SBPB))
+                       x86_pred_cmd = PRED_CMD_SBPB;
+               return;
+@@ -2585,11 +2584,6 @@ static void __init srso_select_mitigation(void)
+       }
+       switch (srso_cmd) {
+-      case SRSO_CMD_OFF:
+-              if (boot_cpu_has(X86_FEATURE_SBPB))
+-                      x86_pred_cmd = PRED_CMD_SBPB;
+-              return;
+-
+       case SRSO_CMD_MICROCODE:
+               if (has_microcode) {
+                       srso_mitigation = SRSO_MITIGATION_MICROCODE;
+@@ -2643,6 +2637,8 @@ static void __init srso_select_mitigation(void)
+                       pr_err("WARNING: kernel not compiled with MITIGATION_SRSO.\n");
+                 }
+               break;
++      default:
++              break;
+       }
+ out:
+-- 
+2.43.0
+
diff --git a/queue-6.11/x86-ioapic-handle-allocation-failures-gracefully.patch b/queue-6.11/x86-ioapic-handle-allocation-failures-gracefully.patch
new file mode 100644 (file)
index 0000000..2cbecc9
--- /dev/null
@@ -0,0 +1,153 @@
+From e020be5099db357588786237df6acba4ca989296 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 18:15:34 +0200
+Subject: x86/ioapic: Handle allocation failures gracefully
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 830802a0fea8fb39d3dc9fb7d6b5581e1343eb1f ]
+
+Breno observed panics when using failslab under certain conditions during
+runtime:
+
+   can not alloc irq_pin_list (-1,0,20)
+   Kernel panic - not syncing: IO-APIC: failed to add irq-pin. Can not proceed
+
+   panic+0x4e9/0x590
+   mp_irqdomain_alloc+0x9ab/0xa80
+   irq_domain_alloc_irqs_locked+0x25d/0x8d0
+   __irq_domain_alloc_irqs+0x80/0x110
+   mp_map_pin_to_irq+0x645/0x890
+   acpi_register_gsi_ioapic+0xe6/0x150
+   hpet_open+0x313/0x480
+
+That's a pointless panic which is a leftover of the historic IO/APIC code
+which panic'ed during early boot when the interrupt allocation failed.
+
+The only place which might justify panic is the PIT/HPET timer_check() code
+which tries to figure out whether the timer interrupt is delivered through
+the IO/APIC. But that code does not require to handle interrupt allocation
+failures. If the interrupt cannot be allocated then timer delivery fails
+and it either panics due to that or falls back to legacy mode.
+
+Cure this by removing the panic wrapper around __add_pin_to_irq_node() and
+making mp_irqdomain_alloc() aware of the failure condition and handle it as
+any other failure in this function gracefully.
+
+Reported-by: Breno Leitao <leitao@debian.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Breno Leitao <leitao@debian.org>
+Tested-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Link: https://lore.kernel.org/all/ZqfJmUF8sXIyuSHN@gmail.com
+Link: https://lore.kernel.org/all/20240802155440.275200843@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/apic/io_apic.c | 46 ++++++++++++++++------------------
+ 1 file changed, 22 insertions(+), 24 deletions(-)
+
+diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
+index 477b740b2f267..d1ec1dcb637af 100644
+--- a/arch/x86/kernel/apic/io_apic.c
++++ b/arch/x86/kernel/apic/io_apic.c
+@@ -352,27 +352,26 @@ static void ioapic_mask_entry(int apic, int pin)
+  * shared ISA-space IRQs, so we have to support them. We are super
+  * fast in the common case, and fast for shared ISA-space IRQs.
+  */
+-static int __add_pin_to_irq_node(struct mp_chip_data *data,
+-                               int node, int apic, int pin)
++static bool add_pin_to_irq_node(struct mp_chip_data *data, int node, int apic, int pin)
+ {
+       struct irq_pin_list *entry;
+-      /* don't allow duplicates */
+-      for_each_irq_pin(entry, data->irq_2_pin)
++      /* Don't allow duplicates */
++      for_each_irq_pin(entry, data->irq_2_pin) {
+               if (entry->apic == apic && entry->pin == pin)
+-                      return 0;
++                      return true;
++      }
+       entry = kzalloc_node(sizeof(struct irq_pin_list), GFP_ATOMIC, node);
+       if (!entry) {
+-              pr_err("can not alloc irq_pin_list (%d,%d,%d)\n",
+-                     node, apic, pin);
+-              return -ENOMEM;
++              pr_err("Cannot allocate irq_pin_list (%d,%d,%d)\n", node, apic, pin);
++              return false;
+       }
++
+       entry->apic = apic;
+       entry->pin = pin;
+       list_add_tail(&entry->list, &data->irq_2_pin);
+-
+-      return 0;
++      return true;
+ }
+ static void __remove_pin_from_irq(struct mp_chip_data *data, int apic, int pin)
+@@ -387,13 +386,6 @@ static void __remove_pin_from_irq(struct mp_chip_data *data, int apic, int pin)
+               }
+ }
+-static void add_pin_to_irq_node(struct mp_chip_data *data,
+-                              int node, int apic, int pin)
+-{
+-      if (__add_pin_to_irq_node(data, node, apic, pin))
+-              panic("IO-APIC: failed to add irq-pin. Can not proceed\n");
+-}
+-
+ /*
+  * Reroute an IRQ to a different pin.
+  */
+@@ -1002,8 +994,7 @@ static int alloc_isa_irq_from_domain(struct irq_domain *domain,
+       if (irq_data && irq_data->parent_data) {
+               if (!mp_check_pin_attr(irq, info))
+                       return -EBUSY;
+-              if (__add_pin_to_irq_node(irq_data->chip_data, node, ioapic,
+-                                        info->ioapic.pin))
++              if (!add_pin_to_irq_node(irq_data->chip_data, node, ioapic, info->ioapic.pin))
+                       return -ENOMEM;
+       } else {
+               info->flags |= X86_IRQ_ALLOC_LEGACY;
+@@ -3017,10 +3008,8 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
+               return -ENOMEM;
+       ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info);
+-      if (ret < 0) {
+-              kfree(data);
+-              return ret;
+-      }
++      if (ret < 0)
++              goto free_data;
+       INIT_LIST_HEAD(&data->irq_2_pin);
+       irq_data->hwirq = info->ioapic.pin;
+@@ -3029,7 +3018,10 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
+       irq_data->chip_data = data;
+       mp_irqdomain_get_attr(mp_pin_to_gsi(ioapic, pin), data, info);
+-      add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin);
++      if (!add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin)) {
++              ret = -ENOMEM;
++              goto free_irqs;
++      }
+       mp_preconfigure_entry(data);
+       mp_register_handler(virq, data->is_level);
+@@ -3044,6 +3036,12 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
+                   ioapic, mpc_ioapic_id(ioapic), pin, virq,
+                   data->is_level, data->active_low);
+       return 0;
++
++free_irqs:
++      irq_domain_free_irqs_parent(domain, virq, nr_irqs);
++free_data:
++      kfree(data);
++      return ret;
+ }
+ void mp_irqdomain_free(struct irq_domain *domain, unsigned int virq,
+-- 
+2.43.0
+
diff --git a/queue-6.11/x86-kexec-add-efi-config-table-identity-mapping-for-.patch b/queue-6.11/x86-kexec-add-efi-config-table-identity-mapping-for-.patch
new file mode 100644 (file)
index 0000000..86a2304
--- /dev/null
@@ -0,0 +1,116 @@
+From a732b23228c27ebf818d19f7a33bc3374f8ea925 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jul 2024 16:31:20 -0500
+Subject: x86/kexec: Add EFI config table identity mapping for kexec kernel
+
+From: Tao Liu <ltao@redhat.com>
+
+[ Upstream commit 5760929f6545c651682de3c2c6c6786816b17bb1 ]
+
+A kexec kernel boot failure is sometimes observed on AMD CPUs due to an
+unmapped EFI config table array.  This can be seen when "nogbpages" is on
+the kernel command line, and has been observed as a full BIOS reboot rather
+than a successful kexec.
+
+This was also the cause of reported regressions attributed to Commit
+7143c5f4cf20 ("x86/mm/ident_map: Use gbpages only where full GB page should
+be mapped.") which was subsequently reverted.
+
+To avoid this page fault, explicitly include the EFI config table array in
+the kexec identity map.
+
+Further explanation:
+
+The following 2 commits caused the EFI config table array to be
+accessed when enabling sev at kernel startup.
+
+    commit ec1c66af3a30 ("x86/compressed/64: Detect/setup SEV/SME features
+                          earlier during boot")
+    commit c01fce9cef84 ("x86/compressed: Add SEV-SNP feature
+                          detection/setup")
+
+This is in the code that examines whether SEV should be enabled or not, so
+it can even affect systems that are not SEV capable.
+
+This may result in a page fault if the EFI config table array's address is
+unmapped. Since the page fault occurs before the new kernel establishes its
+own identity map and page fault routines, it is unrecoverable and kexec
+fails.
+
+Most often, this problem is not seen because the EFI config table array
+gets included in the map by the luck of being placed at a memory address
+close enough to other memory areas that *are* included in the map created
+by kexec.
+
+Both the "nogbpages" command line option and the "use gpbages only where
+full GB page should be mapped" change greatly reduce the chance of being
+included in the map by luck, which is why the problem appears.
+
+Signed-off-by: Tao Liu <ltao@redhat.com>
+Signed-off-by: Steve Wahl <steve.wahl@hpe.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Pavin Joseph <me@pavinjoseph.com>
+Tested-by: Sarah Brofeldt <srhb@dbc.dk>
+Tested-by: Eric Hagberg <ehagberg@gmail.com>
+Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
+Link: https://lore.kernel.org/all/20240717213121.3064030-2-steve.wahl@hpe.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/machine_kexec_64.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
+index cc0f7f70b17ba..9c9ac606893e9 100644
+--- a/arch/x86/kernel/machine_kexec_64.c
++++ b/arch/x86/kernel/machine_kexec_64.c
+@@ -28,6 +28,7 @@
+ #include <asm/setup.h>
+ #include <asm/set_memory.h>
+ #include <asm/cpu.h>
++#include <asm/efi.h>
+ #ifdef CONFIG_ACPI
+ /*
+@@ -87,6 +88,8 @@ map_efi_systab(struct x86_mapping_info *info, pgd_t *level4p)
+ {
+ #ifdef CONFIG_EFI
+       unsigned long mstart, mend;
++      void *kaddr;
++      int ret;
+       if (!efi_enabled(EFI_BOOT))
+               return 0;
+@@ -102,6 +105,30 @@ map_efi_systab(struct x86_mapping_info *info, pgd_t *level4p)
+       if (!mstart)
+               return 0;
++      ret = kernel_ident_mapping_init(info, level4p, mstart, mend);
++      if (ret)
++              return ret;
++
++      kaddr = memremap(mstart, mend - mstart, MEMREMAP_WB);
++      if (!kaddr) {
++              pr_err("Could not map UEFI system table\n");
++              return -ENOMEM;
++      }
++
++      mstart = efi_config_table;
++
++      if (efi_enabled(EFI_64BIT)) {
++              efi_system_table_64_t *stbl = (efi_system_table_64_t *)kaddr;
++
++              mend = mstart + sizeof(efi_config_table_64_t) * stbl->nr_tables;
++      } else {
++              efi_system_table_32_t *stbl = (efi_system_table_32_t *)kaddr;
++
++              mend = mstart + sizeof(efi_config_table_32_t) * stbl->nr_tables;
++      }
++
++      memunmap(kaddr);
++
+       return kernel_ident_mapping_init(info, level4p, mstart, mend);
+ #endif
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-6.11/x86-mm-ident_map-use-gbpages-only-where-full-gb-page.patch b/queue-6.11/x86-mm-ident_map-use-gbpages-only-where-full-gb-page.patch
new file mode 100644 (file)
index 0000000..4d6e440
--- /dev/null
@@ -0,0 +1,83 @@
+From c051b7e69bbf2fa0e3e6d4f8dff3e7bdff021fa0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jul 2024 16:31:21 -0500
+Subject: x86/mm/ident_map: Use gbpages only where full GB page should be
+ mapped.
+
+From: Steve Wahl <steve.wahl@hpe.com>
+
+[ Upstream commit cc31744a294584a36bf764a0ffa3255a8e69f036 ]
+
+When ident_pud_init() uses only GB pages to create identity maps, large
+ranges of addresses not actually requested can be included in the resulting
+table; a 4K request will map a full GB.  This can include a lot of extra
+address space past that requested, including areas marked reserved by the
+BIOS.  That allows processor speculation into reserved regions, that on UV
+systems can cause system halts.
+
+Only use GB pages when map creation requests include the full GB page of
+space.  Fall back to using smaller 2M pages when only portions of a GB page
+are included in the request.
+
+No attempt is made to coalesce mapping requests. If a request requires a
+map entry at the 2M (pmd) level, subsequent mapping requests within the
+same 1G region will also be at the pmd level, even if adjacent or
+overlapping such requests could have been combined to map a full GB page.
+Existing usage starts with larger regions and then adds smaller regions, so
+this should not have any great consequence.
+
+Signed-off-by: Steve Wahl <steve.wahl@hpe.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Pavin Joseph <me@pavinjoseph.com>
+Tested-by: Sarah Brofeldt <srhb@dbc.dk>
+Tested-by: Eric Hagberg <ehagberg@gmail.com>
+Link: https://lore.kernel.org/all/20240717213121.3064030-3-steve.wahl@hpe.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/ident_map.c | 23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
+index c45127265f2fa..437e96fb49773 100644
+--- a/arch/x86/mm/ident_map.c
++++ b/arch/x86/mm/ident_map.c
+@@ -99,18 +99,31 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
+       for (; addr < end; addr = next) {
+               pud_t *pud = pud_page + pud_index(addr);
+               pmd_t *pmd;
++              bool use_gbpage;
+               next = (addr & PUD_MASK) + PUD_SIZE;
+               if (next > end)
+                       next = end;
+-              if (info->direct_gbpages) {
+-                      pud_t pudval;
++              /* if this is already a gbpage, this portion is already mapped */
++              if (pud_leaf(*pud))
++                      continue;
++
++              /* Is using a gbpage allowed? */
++              use_gbpage = info->direct_gbpages;
+-                      if (pud_present(*pud))
+-                              continue;
++              /* Don't use gbpage if it maps more than the requested region. */
++              /* at the begining: */
++              use_gbpage &= ((addr & ~PUD_MASK) == 0);
++              /* ... or at the end: */
++              use_gbpage &= ((next & ~PUD_MASK) == 0);
++
++              /* Never overwrite existing mappings */
++              use_gbpage &= !pud_present(*pud);
++
++              if (use_gbpage) {
++                      pud_t pudval;
+-                      addr &= PUD_MASK;
+                       pudval = __pud((addr - info->offset) | info->page_flag);
+                       set_pud(pud, pudval);
+                       continue;
+-- 
+2.43.0
+
diff --git a/queue-6.11/x86-pkeys-add-pkru-as-a-parameter-in-signal-handling.patch b/queue-6.11/x86-pkeys-add-pkru-as-a-parameter-in-signal-handling.patch
new file mode 100644 (file)
index 0000000..2bf7453
--- /dev/null
@@ -0,0 +1,128 @@
+From 7c856a525eba2b5be27b56d740d9fa76e349841a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 06:13:14 +0000
+Subject: x86/pkeys: Add PKRU as a parameter in signal handling functions
+
+From: Aruna Ramakrishna <aruna.ramakrishna@oracle.com>
+
+[ Upstream commit 24cf2bc982ffe02aeffb4a3885c71751a2c7023b ]
+
+Assume there's a multithreaded application that runs untrusted user
+code. Each thread has its stack/code protected by a non-zero PKEY, and the
+PKRU register is set up such that only that particular non-zero PKEY is
+enabled. Each thread also sets up an alternate signal stack to handle
+signals, which is protected by PKEY zero. The PKEYs man page documents that
+the PKRU will be reset to init_pkru when the signal handler is invoked,
+which means that PKEY zero access will be enabled.  But this reset happens
+after the kernel attempts to push fpu state to the alternate stack, which
+is not (yet) accessible by the kernel, which leads to a new SIGSEGV being
+sent to the application, terminating it.
+
+Enabling both the non-zero PKEY (for the thread) and PKEY zero in
+userspace will not work for this use case. It cannot have the alt stack
+writeable by all - the rationale here is that the code running in that
+thread (using a non-zero PKEY) is untrusted and should not have access
+to the alternate signal stack (that uses PKEY zero), to prevent the
+return address of a function from being changed. The expectation is that
+kernel should be able to set up the alternate signal stack and deliver
+the signal to the application even if PKEY zero is explicitly disabled
+by the application. The signal handler accessibility should not be
+dictated by whatever PKRU value the thread sets up.
+
+The PKRU register is managed by XSAVE, which means the sigframe contents
+must match the register contents - which is not the case here. It's
+required that the signal frame contains the user-defined PKRU value (so
+that it is restored correctly from sigcontext) but the actual register must
+be reset to init_pkru so that the alt stack is accessible and the signal
+can be delivered to the application. It seems that the proper fix here
+would be to remove PKRU from the XSAVE framework and manage it separately,
+which is quite complicated. As a workaround, do this:
+
+        orig_pkru = rdpkru();
+        wrpkru(orig_pkru & init_pkru_value);
+        xsave_to_user_sigframe();
+        put_user(pkru_sigframe_addr, orig_pkru)
+
+In preparation for writing PKRU to sigframe, pass PKRU as an additional
+parameter down the call chain from get_sigframe().
+
+No functional change.
+
+Signed-off-by: Aruna Ramakrishna <aruna.ramakrishna@oracle.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/all/20240802061318.2140081-2-aruna.ramakrishna@oracle.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/fpu/signal.h | 2 +-
+ arch/x86/kernel/fpu/signal.c      | 6 +++---
+ arch/x86/kernel/signal.c          | 3 ++-
+ 3 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/include/asm/fpu/signal.h b/arch/x86/include/asm/fpu/signal.h
+index 611fa41711aff..eccc75bc9c4f3 100644
+--- a/arch/x86/include/asm/fpu/signal.h
++++ b/arch/x86/include/asm/fpu/signal.h
+@@ -29,7 +29,7 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame,
+ unsigned long fpu__get_fpstate_size(void);
+-extern bool copy_fpstate_to_sigframe(void __user *buf, void __user *fp, int size);
++extern bool copy_fpstate_to_sigframe(void __user *buf, void __user *fp, int size, u32 pkru);
+ extern void fpu__clear_user_states(struct fpu *fpu);
+ extern bool fpu__restore_sig(void __user *buf, int ia32_frame);
+diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
+index 247f2225aa9f3..2b3b9e140dd41 100644
+--- a/arch/x86/kernel/fpu/signal.c
++++ b/arch/x86/kernel/fpu/signal.c
+@@ -156,7 +156,7 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame,
+       return !err;
+ }
+-static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)
++static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf, u32 pkru)
+ {
+       if (use_xsave())
+               return xsave_to_user_sigframe(buf);
+@@ -185,7 +185,7 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)
+  * For [f]xsave state, update the SW reserved fields in the [f]xsave frame
+  * indicating the absence/presence of the extended state to the user.
+  */
+-bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
++bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size, u32 pkru)
+ {
+       struct task_struct *tsk = current;
+       struct fpstate *fpstate = tsk->thread.fpu.fpstate;
+@@ -228,7 +228,7 @@ bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
+               fpregs_restore_userregs();
+       pagefault_disable();
+-      ret = copy_fpregs_to_sigframe(buf_fx);
++      ret = copy_fpregs_to_sigframe(buf_fx, pkru);
+       pagefault_enable();
+       fpregs_unlock();
+diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
+index 31b6f5dddfc27..1f1e8e0ac5a34 100644
+--- a/arch/x86/kernel/signal.c
++++ b/arch/x86/kernel/signal.c
+@@ -84,6 +84,7 @@ get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size,
+       unsigned long math_size = 0;
+       unsigned long sp = regs->sp;
+       unsigned long buf_fx = 0;
++      u32 pkru = read_pkru();
+       /* redzone */
+       if (!ia32_frame)
+@@ -139,7 +140,7 @@ get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size,
+       }
+       /* save i387 and extended state */
+-      if (!copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size))
++      if (!copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size, pkru))
+               return (void __user *)-1L;
+       return (void __user *)sp;
+-- 
+2.43.0
+
diff --git a/queue-6.11/x86-pkeys-restore-altstack-access-in-sigreturn.patch b/queue-6.11/x86-pkeys-restore-altstack-access-in-sigreturn.patch
new file mode 100644 (file)
index 0000000..fbc600e
--- /dev/null
@@ -0,0 +1,53 @@
+From d9421c6e2c53c2a92ff356c06b54fd31825f4206 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 06:13:17 +0000
+Subject: x86/pkeys: Restore altstack access in sigreturn()
+
+From: Aruna Ramakrishna <aruna.ramakrishna@oracle.com>
+
+[ Upstream commit d10b554919d4cc8fa8fe2e95b57ad2624728c8e4 ]
+
+A process can disable access to the alternate signal stack by not
+enabling the altstack's PKEY in the PKRU register.
+
+Nevertheless, the kernel updates the PKRU temporarily for signal
+handling. However, in sigreturn(), restore_sigcontext() will restore the
+PKRU to the user-defined PKRU value.
+
+This will cause restore_altstack() to fail with a SIGSEGV as it needs read
+access to the altstack which is prohibited by the user-defined PKRU value.
+
+Fix this by restoring altstack before restoring PKRU.
+
+Signed-off-by: Aruna Ramakrishna <aruna.ramakrishna@oracle.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/all/20240802061318.2140081-5-aruna.ramakrishna@oracle.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/signal_64.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
+index 8a94053c54446..ee9453891901b 100644
+--- a/arch/x86/kernel/signal_64.c
++++ b/arch/x86/kernel/signal_64.c
+@@ -260,13 +260,13 @@ SYSCALL_DEFINE0(rt_sigreturn)
+       set_current_blocked(&set);
+-      if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
++      if (restore_altstack(&frame->uc.uc_stack))
+               goto badframe;
+-      if (restore_signal_shadow_stack())
++      if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
+               goto badframe;
+-      if (restore_altstack(&frame->uc.uc_stack))
++      if (restore_signal_shadow_stack())
+               goto badframe;
+       return regs->ax;
+-- 
+2.43.0
+
diff --git a/queue-6.11/x86-syscall-avoid-memcpy-for-ia32-syscall_get_argume.patch b/queue-6.11/x86-syscall-avoid-memcpy-for-ia32-syscall_get_argume.patch
new file mode 100644 (file)
index 0000000..9bd760b
--- /dev/null
@@ -0,0 +1,71 @@
+From c10990e3735c4ec007bc5cc68b829a0056b50a2d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Jul 2024 13:22:06 -0700
+Subject: x86/syscall: Avoid memcpy() for ia32 syscall_get_arguments()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kees Cook <kees@kernel.org>
+
+[ Upstream commit d19d638b1e6cf746263ef60b7d0dee0204d8216a ]
+
+Modern (fortified) memcpy() prefers to avoid writing (or reading) beyond
+the end of the addressed destination (or source) struct member:
+
+In function ‘fortify_memcpy_chk’,
+    inlined from ‘syscall_get_arguments’ at ./arch/x86/include/asm/syscall.h:85:2,
+    inlined from ‘populate_seccomp_data’ at kernel/seccomp.c:258:2,
+    inlined from ‘__seccomp_filter’ at kernel/seccomp.c:1231:3:
+./include/linux/fortify-string.h:580:25: error: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror=attribute-warning]
+  580 |                         __read_overflow2_field(q_size_field, size);
+      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As already done for x86_64 and compat mode, do not use memcpy() to
+extract syscall arguments from struct pt_regs but rather just perform
+direct assignments. Binary output differences are negligible, and actually
+ends up using less stack space:
+
+-       sub    $0x84,%esp
++       sub    $0x6c,%esp
+
+and less text size:
+
+   text    data     bss     dec     hex filename
+  10794     252       0   11046    2b26 gcc-32b/kernel/seccomp.o.stock
+  10714     252       0   10966    2ad6 gcc-32b/kernel/seccomp.o.after
+
+Closes: https://lore.kernel.org/lkml/9b69fb14-df89-4677-9c82-056ea9e706f5@gmail.com/
+Reported-by: Mirsad Todorovac <mtodorovac69@gmail.com>
+Signed-off-by: Kees Cook <kees@kernel.org>
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
+Tested-by: Mirsad Todorovac <mtodorovac69@gmail.com>
+Link: https://lore.kernel.org/all/20240708202202.work.477-kees%40kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/syscall.h | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
+index 2fc7bc3863ff6..7c488ff0c7641 100644
+--- a/arch/x86/include/asm/syscall.h
++++ b/arch/x86/include/asm/syscall.h
+@@ -82,7 +82,12 @@ static inline void syscall_get_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned long *args)
+ {
+-      memcpy(args, &regs->bx, 6 * sizeof(args[0]));
++      args[0] = regs->bx;
++      args[1] = regs->cx;
++      args[2] = regs->dx;
++      args[3] = regs->si;
++      args[4] = regs->di;
++      args[5] = regs->bp;
+ }
+ static inline int syscall_get_arch(struct task_struct *task)
+-- 
+2.43.0
+