From 0fcddade9a86e459f80f3d13fa604c72b71c3c2d Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 28 Jul 2023 10:38:01 -0400 Subject: [PATCH] Fixes for 6.1 Signed-off-by: Sasha Levin --- ...igate-ampere1-erratum-ac03_cpu_38-at.patch | 141 ++ ...ix-stall-due-to-recursive-flush-plug.patch | 80 ++ ...between-quota-disable-and-relocation.patch | 97 ++ ...add-fams-validation-before-trying-to.patch | 89 ++ ...-display-add-fb_damage_clips-support.patch | 227 ++++ ...add-odm-case-when-looking-for-first-.patch | 151 +++ ...add-pixel-rate-based-crb-allocation-.patch | 391 ++++++ ...display-check-if-link-state-is-valid.patch | 40 + ...copy-dc-context-in-the-commit-stream.patch | 122 ++ ...enable-new-commit-sequence-only-for-.patch | 120 ++ ...-display-fix-dc-core-dc.c-kernel-doc.patch | 169 +++ ...fix-dcn315-single-stream-crb-allocat.patch | 78 ++ ...fix-possible-underflow-for-displays-.patch | 77 ++ ...fix-unbounded-requesting-for-high-pi.patch | 68 + ...include-surface-of-unaffected-stream.patch | 112 ++ ...y-prevent-vtotal-from-being-set-to-0.patch | 51 + ...d-display-rework-comments-on-dc-file.patch | 377 ++++++ ...-display-rework-context-change-check.patch | 67 + ...set-minimum-requirement-for-using-ps.patch | 153 +++ ...nimum-requirement-for-using-ps.patch-26244 | 68 + ...update-correct-dcn314-register-heade.patch | 177 +++ ...update-extended-blank-for-dcn314-onw.patch | 288 ++++ ...-use-low-clocks-for-no-plane-configs.patch | 110 ++ ...use-min-transition-for-all-subvp-pla.patch | 96 ++ ...-t-leak-a-resource-on-eviction-error.patch | 72 + ...int-error-message-if-eviction-was-in.patch | 42 + ...onsider-pinned-bos-for-eviction-swap.patch | 46 + ...-unchangable-mount-option-in-f2fs_re.patch | 141 ++ ...flush_merge-opt-and-show-noflush_mer.patch | 66 + .../gpio-mvebu-fix-irq-domain-leak.patch | 77 ++ ...o-mvebu-make-use-of-devm_pwmchip_add.patch | 61 + ...ke-tps68470_gpio_output-always-set-t.patch | 50 + ...-messages-for-failed-memory-allocati.patch | 81 ++ .../i2c-improve-size-determinations.patch | 54 + ...ve-a-useless-call-in-the-remove-func.patch | 49 + ...omadik-remove-unnecessary-goto-label.patch | 85 ++ ...i2c-nomadik-use-devm_clk_get_enabled.patch | 76 ++ ...udit-the-capability-check-in-io_urin.patch | 47 + ...when-checking-checkpoint-buffer-busy.patch | 150 +++ ...-judgement-for-buffer-head-removing-.patch | 106 ++ ...bd2-remove-journal_clean_one_cp_list.patch | 235 ++++ .../jbd2-remove-t_checkpoint_io_list.patch | 146 +++ ...ition-hw-af-updates-on-config-option.patch | 47 + ...-pv-fix-index-value-of-replaced-asce.patch | 46 + ...add-__init-and-__exit-to-test-module.patch | 1166 +++++++++++++++++ ...ple_tree-fix-32-bit-mas_next-testing.patch | 62 + ...x-build-error-when-make-modules_inst.patch | 75 ++ ...ve-arch-cflags-to-mips-top-level-mak.patch | 146 +++ ...y-on-implicit-state-check-in-mptcp_l.patch | 60 + ...sk-to-replace-sock-sk-in-mptcp_liste.patch | 66 + ...ename-tail-to-old_tail-in-n_tty_read.patch | 60 + .../pci-aspm-avoid-link-retraining-race.patch | 64 + ...spm-factor-out-pcie_wait_for_retrain.patch | 79 ++ ...0-or-etimedout-from-pcie_retrain_lin.patch | 72 + ...-t-advertise-msi-x-in-pcie-capabilit.patch | 103 ++ ...-window-mapping-and-address-translat.patch | 340 +++++ ...ip-remove-writes-to-unused-registers.patch | 55 + ...vas-hold-mmap_mutex-after-mmap-lock-.patch | 88 ++ ...dd-fault-name-injection-to-kernel-pr.patch | 135 ++ queue-6.1/series | 65 + ...e-test-modifications-while-iterating.patch | 114 ++ ...nthetic-events-to-pass-around-stackt.patch | 282 ++++ ...s-add-symstr-type-for-dynamic-events.patch | 313 +++++ ...ix-to-avoid-double-count-of-the-stri.patch | 49 + ...ix-to-record-0-length-data_loc-in-fe.patch | 109 ++ ...-hang-on-tty-device-with-no_room-set.patch | 116 ++ 66 files changed, 8645 insertions(+) create mode 100644 queue-6.1/arm64-errata-mitigate-ampere1-erratum-ac03_cpu_38-at.patch create mode 100644 queue-6.1/blk-mq-fix-stall-due-to-recursive-flush-plug.patch create mode 100644 queue-6.1/btrfs-fix-race-between-quota-disable-and-relocation.patch create mode 100644 queue-6.1/drm-amd-display-add-fams-validation-before-trying-to.patch create mode 100644 queue-6.1/drm-amd-display-add-fb_damage_clips-support.patch create mode 100644 queue-6.1/drm-amd-display-add-odm-case-when-looking-for-first-.patch create mode 100644 queue-6.1/drm-amd-display-add-pixel-rate-based-crb-allocation-.patch create mode 100644 queue-6.1/drm-amd-display-check-if-link-state-is-valid.patch create mode 100644 queue-6.1/drm-amd-display-copy-dc-context-in-the-commit-stream.patch create mode 100644 queue-6.1/drm-amd-display-enable-new-commit-sequence-only-for-.patch create mode 100644 queue-6.1/drm-amd-display-fix-dc-core-dc.c-kernel-doc.patch create mode 100644 queue-6.1/drm-amd-display-fix-dcn315-single-stream-crb-allocat.patch create mode 100644 queue-6.1/drm-amd-display-fix-possible-underflow-for-displays-.patch create mode 100644 queue-6.1/drm-amd-display-fix-unbounded-requesting-for-high-pi.patch create mode 100644 queue-6.1/drm-amd-display-include-surface-of-unaffected-stream.patch create mode 100644 queue-6.1/drm-amd-display-prevent-vtotal-from-being-set-to-0.patch create mode 100644 queue-6.1/drm-amd-display-rework-comments-on-dc-file.patch create mode 100644 queue-6.1/drm-amd-display-rework-context-change-check.patch create mode 100644 queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch create mode 100644 queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch-26244 create mode 100644 queue-6.1/drm-amd-display-update-correct-dcn314-register-heade.patch create mode 100644 queue-6.1/drm-amd-display-update-extended-blank-for-dcn314-onw.patch create mode 100644 queue-6.1/drm-amd-display-use-low-clocks-for-no-plane-configs.patch create mode 100644 queue-6.1/drm-amd-display-use-min-transition-for-all-subvp-pla.patch create mode 100644 queue-6.1/drm-ttm-don-t-leak-a-resource-on-eviction-error.patch create mode 100644 queue-6.1/drm-ttm-don-t-print-error-message-if-eviction-was-in.patch create mode 100644 queue-6.1/drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch create mode 100644 queue-6.1/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch create mode 100644 queue-6.1/f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch create mode 100644 queue-6.1/gpio-mvebu-fix-irq-domain-leak.patch create mode 100644 queue-6.1/gpio-mvebu-make-use-of-devm_pwmchip_add.patch create mode 100644 queue-6.1/gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch create mode 100644 queue-6.1/i2c-delete-error-messages-for-failed-memory-allocati.patch create mode 100644 queue-6.1/i2c-improve-size-determinations.patch create mode 100644 queue-6.1/i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch create mode 100644 queue-6.1/i2c-nomadik-remove-unnecessary-goto-label.patch create mode 100644 queue-6.1/i2c-nomadik-use-devm_clk_get_enabled.patch create mode 100644 queue-6.1/io_uring-don-t-audit-the-capability-check-in-io_urin.patch create mode 100644 queue-6.1/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch create mode 100644 queue-6.1/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch create mode 100644 queue-6.1/jbd2-remove-journal_clean_one_cp_list.patch create mode 100644 queue-6.1/jbd2-remove-t_checkpoint_io_list.patch create mode 100644 queue-6.1/kvm-arm64-condition-hw-af-updates-on-config-option.patch create mode 100644 queue-6.1/kvm-s390-pv-fix-index-value-of-replaced-asce.patch create mode 100644 queue-6.1/maple_tree-add-__init-and-__exit-to-test-module.patch create mode 100644 queue-6.1/maple_tree-fix-32-bit-mas_next-testing.patch create mode 100644 queue-6.1/mips-loongson-fix-build-error-when-make-modules_inst.patch create mode 100644 queue-6.1/mips-loongson-move-arch-cflags-to-mips-top-level-mak.patch create mode 100644 queue-6.1/mptcp-do-not-rely-on-implicit-state-check-in-mptcp_l.patch create mode 100644 queue-6.1/mptcp-introduce-sk-to-replace-sock-sk-in-mptcp_liste.patch create mode 100644 queue-6.1/n_tty-rename-tail-to-old_tail-in-n_tty_read.patch create mode 100644 queue-6.1/pci-aspm-avoid-link-retraining-race.patch create mode 100644 queue-6.1/pci-aspm-factor-out-pcie_wait_for_retrain.patch create mode 100644 queue-6.1/pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch create mode 100644 queue-6.1/pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch create mode 100644 queue-6.1/pci-rockchip-fix-window-mapping-and-address-translat.patch create mode 100644 queue-6.1/pci-rockchip-remove-writes-to-unused-registers.patch create mode 100644 queue-6.1/powerpc-pseries-vas-hold-mmap_mutex-after-mmap-lock-.patch create mode 100644 queue-6.1/revert-tracing-add-fault-name-injection-to-kernel-pr.patch create mode 100644 queue-6.1/test_maple_tree-test-modifications-while-iterating.patch create mode 100644 queue-6.1/tracing-allow-synthetic-events-to-pass-around-stackt.patch create mode 100644 queue-6.1/tracing-probes-add-symstr-type-for-dynamic-events.patch create mode 100644 queue-6.1/tracing-probes-fix-to-avoid-double-count-of-the-stri.patch create mode 100644 queue-6.1/tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch create mode 100644 queue-6.1/tty-fix-hang-on-tty-device-with-no_room-set.patch diff --git a/queue-6.1/arm64-errata-mitigate-ampere1-erratum-ac03_cpu_38-at.patch b/queue-6.1/arm64-errata-mitigate-ampere1-erratum-ac03_cpu_38-at.patch new file mode 100644 index 00000000000..31df26931f5 --- /dev/null +++ b/queue-6.1/arm64-errata-mitigate-ampere1-erratum-ac03_cpu_38-at.patch @@ -0,0 +1,141 @@ +From 8829ccb3b9c4bcfd84dfaecb9a49ea18101de3f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Jun 2023 22:01:02 +0000 +Subject: arm64: errata: Mitigate Ampere1 erratum AC03_CPU_38 at stage-2 + +From: Oliver Upton + +[ Upstream commit 6df696cd9bc1ceed0e92e36908f88bbd16d18255 ] + +AmpereOne has an erratum in its implementation of FEAT_HAFDBS that +required disabling the feature on the design. This was done by reporting +the feature as not implemented in the ID register, although the +corresponding control bits were not actually RES0. This does not align +well with the requirements of the architecture, which mandates these +bits be RES0 if HAFDBS isn't implemented. + +The kernel's use of stage-1 is unaffected, as the HA and HD bits are +only set if HAFDBS is detected in the ID register. KVM, on the other +hand, relies on the RES0 behavior at stage-2 to use the same value for +VTCR_EL2 on any cpu in the system. Mitigate the non-RES0 behavior by +leaving VTCR_EL2.HA clear on affected systems. + +Cc: stable@vger.kernel.org +Cc: D Scott Phillips +Cc: Darren Hart +Acked-by: D Scott Phillips +Acked-by: Catalin Marinas +Link: https://lore.kernel.org/r/20230609220104.1836988-2-oliver.upton@linux.dev +Signed-off-by: Oliver Upton +Signed-off-by: Sasha Levin +--- + Documentation/arm64/silicon-errata.rst | 3 +++ + arch/arm64/Kconfig | 19 +++++++++++++++++++ + arch/arm64/kernel/cpu_errata.c | 7 +++++++ + arch/arm64/kvm/hyp/pgtable.c | 14 +++++++++++--- + arch/arm64/tools/cpucaps | 1 + + 5 files changed, 41 insertions(+), 3 deletions(-) + +diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst +index 55492fea44276..bbc80eff03f98 100644 +--- a/Documentation/arm64/silicon-errata.rst ++++ b/Documentation/arm64/silicon-errata.rst +@@ -52,6 +52,9 @@ stable kernels. + | Allwinner | A64/R18 | UNKNOWN1 | SUN50I_ERRATUM_UNKNOWN1 | + +----------------+-----------------+-----------------+-----------------------------+ + +----------------+-----------------+-----------------+-----------------------------+ ++| Ampere | AmpereOne | AC03_CPU_38 | AMPERE_ERRATUM_AC03_CPU_38 | +++----------------+-----------------+-----------------+-----------------------------+ +++----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-A510 | #2457168 | ARM64_ERRATUM_2457168 | + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-A510 | #2064142 | ARM64_ERRATUM_2064142 | +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 20ee745c118ae..d5eb2fbab473e 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -376,6 +376,25 @@ menu "Kernel Features" + + menu "ARM errata workarounds via the alternatives framework" + ++config AMPERE_ERRATUM_AC03_CPU_38 ++ bool "AmpereOne: AC03_CPU_38: Certain bits in the Virtualization Translation Control Register and Translation Control Registers do not follow RES0 semantics" ++ default y ++ help ++ This option adds an alternative code sequence to work around Ampere ++ erratum AC03_CPU_38 on AmpereOne. ++ ++ The affected design reports FEAT_HAFDBS as not implemented in ++ ID_AA64MMFR1_EL1.HAFDBS, but (V)TCR_ELx.{HA,HD} are not RES0 ++ as required by the architecture. The unadvertised HAFDBS ++ implementation suffers from an additional erratum where hardware ++ A/D updates can occur after a PTE has been marked invalid. ++ ++ The workaround forces KVM to explicitly set VTCR_EL2.HA to 0, ++ which avoids enabling unadvertised hardware Access Flag management ++ at stage-2. ++ ++ If unsure, say Y. ++ + config ARM64_WORKAROUND_CLEAN_CACHE + bool + +diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c +index 89ac00084f38a..8dbf3c21ea22a 100644 +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -722,6 +722,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = { + MIDR_FIXED(MIDR_CPU_VAR_REV(1,1), BIT(25)), + .cpu_enable = cpu_clear_bf16_from_user_emulation, + }, ++#endif ++#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38 ++ { ++ .desc = "AmpereOne erratum AC03_CPU_38", ++ .capability = ARM64_WORKAROUND_AMPERE_AC03_CPU_38, ++ ERRATA_MIDR_ALL_VERSIONS(MIDR_AMPERE1), ++ }, + #endif + { + } +diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c +index 8f37e65c23eea..ae5f6b5ac80fd 100644 +--- a/arch/arm64/kvm/hyp/pgtable.c ++++ b/arch/arm64/kvm/hyp/pgtable.c +@@ -598,10 +598,18 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift) + #ifdef CONFIG_ARM64_HW_AFDBM + /* + * Enable the Hardware Access Flag management, unconditionally +- * on all CPUs. The features is RES0 on CPUs without the support +- * and must be ignored by the CPUs. ++ * on all CPUs. In systems that have asymmetric support for the feature ++ * this allows KVM to leverage hardware support on the subset of cores ++ * that implement the feature. ++ * ++ * The architecture requires VTCR_EL2.HA to be RES0 (thus ignored by ++ * hardware) on implementations that do not advertise support for the ++ * feature. As such, setting HA unconditionally is safe, unless you ++ * happen to be running on a design that has unadvertised support for ++ * HAFDBS. Here be dragons. + */ +- vtcr |= VTCR_EL2_HA; ++ if (!cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) ++ vtcr |= VTCR_EL2_HA; + #endif /* CONFIG_ARM64_HW_AFDBM */ + + /* Set the vmid bits */ +diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps +index f1c0347ec31a8..14d31d1b2ff02 100644 +--- a/arch/arm64/tools/cpucaps ++++ b/arch/arm64/tools/cpucaps +@@ -71,6 +71,7 @@ WORKAROUND_2064142 + WORKAROUND_2077057 + WORKAROUND_2457168 + WORKAROUND_2658417 ++WORKAROUND_AMPERE_AC03_CPU_38 + WORKAROUND_TRBE_OVERWRITE_FILL_MODE + WORKAROUND_TSB_FLUSH_FAILURE + WORKAROUND_TRBE_WRITE_OUT_OF_RANGE +-- +2.39.2 + diff --git a/queue-6.1/blk-mq-fix-stall-due-to-recursive-flush-plug.patch b/queue-6.1/blk-mq-fix-stall-due-to-recursive-flush-plug.patch new file mode 100644 index 00000000000..8fd9420ccb5 --- /dev/null +++ b/queue-6.1/blk-mq-fix-stall-due-to-recursive-flush-plug.patch @@ -0,0 +1,80 @@ +From c3a51ba545cbc4880bf6f3f8b7dc163a0fc54df3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Jul 2023 11:11:06 +0100 +Subject: blk-mq: Fix stall due to recursive flush plug + +From: Ross Lagerwall + +[ Upstream commit 70904263512a74a3b8941dd9e6e515ca6fc57821 ] + +We have seen rare IO stalls as follows: + +* blk_mq_plug_issue_direct() is entered with an mq_list containing two +requests. +* For the first request, it sets last == false and enters the driver's +queue_rq callback. +* The driver queue_rq callback indirectly calls schedule() which calls +blk_flush_plug(). This may happen if the driver has the +BLK_MQ_F_BLOCKING flag set and is allowed to sleep in ->queue_rq. +* blk_flush_plug() handles the remaining request in the mq_list. mq_list +is now empty. +* The original call to queue_rq resumes (with last == false). +* The loop in blk_mq_plug_issue_direct() terminates because there are no +remaining requests in mq_list. + +The IO is now stalled because the last request submitted to the driver +had last == false and there was no subsequent call to commit_rqs(). + +Fix this by returning early in blk_mq_flush_plug_list() if rq_count is 0 +which it will be in the recursive case, rather than checking if the +mq_list is empty. At the same time, adjust one of the callers to skip +the mq_list empty check as it is not necessary. + +Fixes: dc5fc361d891 ("block: attempt direct issue of plug list") +Signed-off-by: Ross Lagerwall +Reviewed-by: Bart Van Assche +Link: https://lore.kernel.org/r/20230714101106.3635611-1-ross.lagerwall@citrix.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-core.c | 3 +-- + block/blk-mq.c | 9 ++++++++- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/block/blk-core.c b/block/blk-core.c +index 24ee7785a5ad5..ebb7a1689b261 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -1140,8 +1140,7 @@ void __blk_flush_plug(struct blk_plug *plug, bool from_schedule) + { + if (!list_empty(&plug->cb_list)) + flush_plug_callbacks(plug, from_schedule); +- if (!rq_list_empty(plug->mq_list)) +- blk_mq_flush_plug_list(plug, from_schedule); ++ blk_mq_flush_plug_list(plug, from_schedule); + /* + * Unconditionally flush out cached requests, even if the unplug + * event came from schedule. Since we know hold references to the +diff --git a/block/blk-mq.c b/block/blk-mq.c +index add013d5bbdab..100fb0c3114f8 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2749,7 +2749,14 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) + { + struct request *rq; + +- if (rq_list_empty(plug->mq_list)) ++ /* ++ * We may have been called recursively midway through handling ++ * plug->mq_list via a schedule() in the driver's queue_rq() callback. ++ * To avoid mq_list changing under our feet, clear rq_count early and ++ * bail out specifically if rq_count is 0 rather than checking ++ * whether the mq_list is empty. ++ */ ++ if (plug->rq_count == 0) + return; + plug->rq_count = 0; + +-- +2.39.2 + diff --git a/queue-6.1/btrfs-fix-race-between-quota-disable-and-relocation.patch b/queue-6.1/btrfs-fix-race-between-quota-disable-and-relocation.patch new file mode 100644 index 00000000000..1b8e0b14568 --- /dev/null +++ b/queue-6.1/btrfs-fix-race-between-quota-disable-and-relocation.patch @@ -0,0 +1,97 @@ +From 3da0e92b6cff7fd7c7f87a1078af35a7ead86c1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Jun 2023 17:21:50 +0100 +Subject: btrfs: fix race between quota disable and relocation + +From: Filipe Manana + +[ Upstream commit 8a4a0b2a3eaf75ca8854f856ef29690c12b2f531 ] + +If we disable quotas while we have a relocation of a metadata block group +that has extents belonging to the quota root, we can cause the relocation +to fail with -ENOENT. This is because relocation builds backref nodes for +extents of the quota root and later needs to walk the backrefs and access +the quota root - however if in between a task disables quotas, it results +in deleting the quota root from the root tree (with btrfs_del_root(), +called from btrfs_quota_disable(). + +This can be sporadically triggered by test case btrfs/255 from fstests: + + $ ./check btrfs/255 + FSTYP -- btrfs + PLATFORM -- Linux/x86_64 debian0 6.4.0-rc6-btrfs-next-134+ #1 SMP PREEMPT_DYNAMIC Thu Jun 15 11:59:28 WEST 2023 + MKFS_OPTIONS -- /dev/sdc + MOUNT_OPTIONS -- /dev/sdc /home/fdmanana/btrfs-tests/scratch_1 + + btrfs/255 6s ... _check_dmesg: something found in dmesg (see /home/fdmanana/git/hub/xfstests/results//btrfs/255.dmesg) + - output mismatch (see /home/fdmanana/git/hub/xfstests/results//btrfs/255.out.bad) + --- tests/btrfs/255.out 2023-03-02 21:47:53.876609426 +0000 + +++ /home/fdmanana/git/hub/xfstests/results//btrfs/255.out.bad 2023-06-16 10:20:39.267563212 +0100 + @@ -1,2 +1,4 @@ + QA output created by 255 + +ERROR: error during balancing '/home/fdmanana/btrfs-tests/scratch_1': No such file or directory + +There may be more info in syslog - try dmesg | tail + Silence is golden + ... + (Run 'diff -u /home/fdmanana/git/hub/xfstests/tests/btrfs/255.out /home/fdmanana/git/hub/xfstests/results//btrfs/255.out.bad' to see the entire diff) + Ran: btrfs/255 + Failures: btrfs/255 + Failed 1 of 1 tests + +To fix this make the quota disable operation take the cleaner mutex, as +relocation of a block group also takes this mutex. This is also what we +do when deleting a subvolume/snapshot, we take the cleaner mutex in the +cleaner kthread (at cleaner_kthread()) and then we call btrfs_del_root() +at btrfs_drop_snapshot() while under the protection of the cleaner mutex. + +Fixes: bed92eae26cc ("Btrfs: qgroup implementation and prototypes") +CC: stable@vger.kernel.org # 5.4+ +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/qgroup.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c +index cacdb2c5d1528..26cabffd59710 100644 +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -1227,12 +1227,23 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) + int ret = 0; + + /* +- * We need to have subvol_sem write locked, to prevent races between +- * concurrent tasks trying to disable quotas, because we will unlock +- * and relock qgroup_ioctl_lock across BTRFS_FS_QUOTA_ENABLED changes. ++ * We need to have subvol_sem write locked to prevent races with ++ * snapshot creation. + */ + lockdep_assert_held_write(&fs_info->subvol_sem); + ++ /* ++ * Lock the cleaner mutex to prevent races with concurrent relocation, ++ * because relocation may be building backrefs for blocks of the quota ++ * root while we are deleting the root. This is like dropping fs roots ++ * of deleted snapshots/subvolumes, we need the same protection. ++ * ++ * This also prevents races between concurrent tasks trying to disable ++ * quotas, because we will unlock and relock qgroup_ioctl_lock across ++ * BTRFS_FS_QUOTA_ENABLED changes. ++ */ ++ mutex_lock(&fs_info->cleaner_mutex); ++ + mutex_lock(&fs_info->qgroup_ioctl_lock); + if (!fs_info->quota_root) + goto out; +@@ -1314,6 +1325,7 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) + btrfs_end_transaction(trans); + else if (trans) + ret = btrfs_end_transaction(trans); ++ mutex_unlock(&fs_info->cleaner_mutex); + + return ret; + } +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-add-fams-validation-before-trying-to.patch b/queue-6.1/drm-amd-display-add-fams-validation-before-trying-to.patch new file mode 100644 index 00000000000..c06f6a1e2a0 --- /dev/null +++ b/queue-6.1/drm-amd-display-add-fams-validation-before-trying-to.patch @@ -0,0 +1,89 @@ +From c05420e425e8ef800827c2814c6bec4cc5ea510d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Mar 2023 14:29:52 -0600 +Subject: drm/amd/display: Add FAMS validation before trying to use it + +From: Rodrigo Siqueira + +[ Upstream commit e3416e872f84086667df21daf166506fab97358d ] + +To ensure that FAMS can be used, DC must check if there is VRR support. +This commit adds the required configuration to ensure FAMS can be executed in the target system. + +Reviewed-by: Alvin Lee +Acked-by: Qingqing Zhuo +Signed-off-by: Rodrigo Siqueira +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++++++ + drivers/gpu/drm/amd/display/dc/dc_stream.h | 1 + + drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c | 7 ++++++- + drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 2 +- + 4 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 6e2220e2e5ba3..27cec123cb06f 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -2588,6 +2588,12 @@ static enum surface_update_type check_update_surfaces_for_stream( + + if (stream_update->mst_bw_update) + su_flags->bits.mst_bw = 1; ++ ++ if (stream_update->stream && stream_update->stream->freesync_on_desktop && ++ (stream_update->vrr_infopacket || stream_update->allow_freesync || ++ stream_update->vrr_active_variable)) ++ su_flags->bits.fams_changed = 1; ++ + if (stream_update->crtc_timing_adjust && dc_extended_blank_supported(dc)) + su_flags->bits.crtc_timing_adjust = 1; + +diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h +index 73dccd485895d..364ff913527d8 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h +@@ -131,6 +131,7 @@ union stream_update_flags { + uint32_t dsc_changed : 1; + uint32_t mst_bw : 1; + uint32_t crtc_timing_adjust : 1; ++ uint32_t fams_changed : 1; + } bits; + + uint32_t raw; +diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c +index 25749f7d88366..94894fd6c9062 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c +@@ -292,7 +292,12 @@ void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc) + + void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max) + { +- optc1_set_vtotal_min_max(optc, vtotal_min, vtotal_max); ++ struct dc *dc = optc->ctx->dc; ++ ++ if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams) ++ dc_dmub_srv_drr_update_cmd(dc, optc->inst, vtotal_min, vtotal_max); ++ else ++ optc1_set_vtotal_min_max(optc, vtotal_min, vtotal_max); + } + + void optc3_tg_init(struct timing_generator *optc) +diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +index 27a4ea7dc74ec..d8c05bc45957b 100644 +--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h ++++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +@@ -345,7 +345,7 @@ union dmub_fw_boot_status { + uint32_t optimized_init_done : 1; /**< 1 if optimized init done */ + uint32_t restore_required : 1; /**< 1 if driver should call restore */ + uint32_t defer_load : 1; /**< 1 if VBIOS data is deferred programmed */ +- uint32_t reserved : 1; ++ uint32_t fams_enabled : 1; /**< 1 if VBIOS data is deferred programmed */ + uint32_t detection_required: 1; /**< if detection need to be triggered by driver */ + + } bits; /**< status bits */ +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-add-fb_damage_clips-support.patch b/queue-6.1/drm-amd-display-add-fb_damage_clips-support.patch new file mode 100644 index 00000000000..4c892802fb3 --- /dev/null +++ b/queue-6.1/drm-amd-display-add-fb_damage_clips-support.patch @@ -0,0 +1,227 @@ +From cf62a5e8b5cb62c024d7339eeff9d3fc385dd6c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 11:58:45 -0500 +Subject: drm/amd/display: add FB_DAMAGE_CLIPS support + +From: Hamza Mahfooz + +[ Upstream commit 30ebe41582d1ea5a7de990319f9e593dad4886f7 ] + +Currently, userspace doesn't have a way to communicate selective updates +to displays. So, enable support for FB_DAMAGE_CLIPS for DCN ASICs newer +than DCN301, convert DRM damage clips to dc dirty rectangles and fill +them into dirty_rects in fill_dc_dirty_rects(). + +Reviewed-by: Leo Li +Signed-off-by: Hamza Mahfooz +Signed-off-by: Alex Deucher +Stable-dep-of: 72f1de49ffb9 ("drm/dp_mst: Clear MSG_RDY flag before sending new message") +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 130 +++++++++++------- + .../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 4 + + 2 files changed, 88 insertions(+), 46 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 ce5df7927c21f..f6165edc6c433 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -4948,6 +4948,35 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev, + return 0; + } + ++static inline void fill_dc_dirty_rect(struct drm_plane *plane, ++ struct rect *dirty_rect, int32_t x, ++ int32_t y, int32_t width, int32_t height, ++ int *i, bool ffu) ++{ ++ if (*i > DC_MAX_DIRTY_RECTS) ++ return; ++ ++ if (*i == DC_MAX_DIRTY_RECTS) ++ goto out; ++ ++ dirty_rect->x = x; ++ dirty_rect->y = y; ++ dirty_rect->width = width; ++ dirty_rect->height = height; ++ ++ if (ffu) ++ drm_dbg(plane->dev, ++ "[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n", ++ plane->base.id, width, height); ++ else ++ drm_dbg(plane->dev, ++ "[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)", ++ plane->base.id, x, y, width, height); ++ ++out: ++ (*i)++; ++} ++ + /** + * fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates + * +@@ -4968,10 +4997,6 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev, + * addition, certain use cases - such as cursor and multi-plane overlay (MPO) - + * implicitly provide damage clips without any client support via the plane + * bounds. +- * +- * Today, amdgpu_dm only supports the MPO and cursor usecase. +- * +- * TODO: Also enable for FB_DAMAGE_CLIPS + */ + static void fill_dc_dirty_rects(struct drm_plane *plane, + struct drm_plane_state *old_plane_state, +@@ -4982,12 +5007,11 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, + struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state); + struct rect *dirty_rects = flip_addrs->dirty_rects; + uint32_t num_clips; ++ struct drm_mode_rect *clips; + bool bb_changed; + bool fb_changed; + u32 i = 0; + +- flip_addrs->dirty_rect_count = 0; +- + /* + * Cursor plane has it's own dirty rect update interface. See + * dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data +@@ -4995,20 +5019,20 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, + if (plane->type == DRM_PLANE_TYPE_CURSOR) + return; + +- /* +- * Today, we only consider MPO use-case for PSR SU. If MPO not +- * requested, and there is a plane update, do FFU. +- */ ++ num_clips = drm_plane_get_damage_clips_count(new_plane_state); ++ clips = drm_plane_get_damage_clips(new_plane_state); ++ + if (!dm_crtc_state->mpo_requested) { +- dirty_rects[0].x = 0; +- dirty_rects[0].y = 0; +- dirty_rects[0].width = dm_crtc_state->base.mode.crtc_hdisplay; +- dirty_rects[0].height = dm_crtc_state->base.mode.crtc_vdisplay; +- flip_addrs->dirty_rect_count = 1; +- DRM_DEBUG_DRIVER("[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n", +- new_plane_state->plane->base.id, +- dm_crtc_state->base.mode.crtc_hdisplay, +- dm_crtc_state->base.mode.crtc_vdisplay); ++ if (!num_clips || num_clips > DC_MAX_DIRTY_RECTS) ++ goto ffu; ++ ++ for (; flip_addrs->dirty_rect_count < num_clips; clips++) ++ fill_dc_dirty_rect(new_plane_state->plane, ++ &dirty_rects[i], clips->x1, ++ clips->y1, clips->x2 - clips->x1, ++ clips->y2 - clips->y1, ++ &flip_addrs->dirty_rect_count, ++ false); + return; + } + +@@ -5019,7 +5043,6 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, + * If plane is moved or resized, also add old bounding box to dirty + * rects. + */ +- num_clips = drm_plane_get_damage_clips_count(new_plane_state); + fb_changed = old_plane_state->fb->base.id != + new_plane_state->fb->base.id; + bb_changed = (old_plane_state->crtc_x != new_plane_state->crtc_x || +@@ -5027,36 +5050,51 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, + old_plane_state->crtc_w != new_plane_state->crtc_w || + old_plane_state->crtc_h != new_plane_state->crtc_h); + +- DRM_DEBUG_DRIVER("[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n", +- new_plane_state->plane->base.id, +- bb_changed, fb_changed, num_clips); +- +- if (num_clips || fb_changed || bb_changed) { +- dirty_rects[i].x = new_plane_state->crtc_x; +- dirty_rects[i].y = new_plane_state->crtc_y; +- dirty_rects[i].width = new_plane_state->crtc_w; +- dirty_rects[i].height = new_plane_state->crtc_h; +- DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n", +- new_plane_state->plane->base.id, +- dirty_rects[i].x, dirty_rects[i].y, +- dirty_rects[i].width, dirty_rects[i].height); +- i += 1; +- } ++ drm_dbg(plane->dev, ++ "[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n", ++ new_plane_state->plane->base.id, ++ bb_changed, fb_changed, num_clips); + +- /* Add old plane bounding-box if plane is moved or resized */ + if (bb_changed) { +- dirty_rects[i].x = old_plane_state->crtc_x; +- dirty_rects[i].y = old_plane_state->crtc_y; +- dirty_rects[i].width = old_plane_state->crtc_w; +- dirty_rects[i].height = old_plane_state->crtc_h; +- DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n", +- old_plane_state->plane->base.id, +- dirty_rects[i].x, dirty_rects[i].y, +- dirty_rects[i].width, dirty_rects[i].height); +- i += 1; +- } ++ fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i], ++ new_plane_state->crtc_x, ++ new_plane_state->crtc_y, ++ new_plane_state->crtc_w, ++ new_plane_state->crtc_h, &i, false); ++ ++ /* Add old plane bounding-box if plane is moved or resized */ ++ fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i], ++ old_plane_state->crtc_x, ++ old_plane_state->crtc_y, ++ old_plane_state->crtc_w, ++ old_plane_state->crtc_h, &i, false); ++ } ++ ++ if (num_clips) { ++ for (; i < num_clips; clips++) ++ fill_dc_dirty_rect(new_plane_state->plane, ++ &dirty_rects[i], clips->x1, ++ clips->y1, clips->x2 - clips->x1, ++ clips->y2 - clips->y1, &i, false); ++ } else if (fb_changed && !bb_changed) { ++ fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i], ++ new_plane_state->crtc_x, ++ new_plane_state->crtc_y, ++ new_plane_state->crtc_w, ++ new_plane_state->crtc_h, &i, false); ++ } ++ ++ if (i > DC_MAX_DIRTY_RECTS) ++ goto ffu; + + flip_addrs->dirty_rect_count = i; ++ return; ++ ++ffu: ++ fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[0], 0, 0, ++ dm_crtc_state->base.mode.crtc_hdisplay, ++ dm_crtc_state->base.mode.crtc_vdisplay, ++ &flip_addrs->dirty_rect_count, true); + } + + static void update_stream_scaling_settings(const struct drm_display_mode *mode, +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 e6854f7270a66..3c50b3ff79541 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 +@@ -1600,6 +1600,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, + supported_rotations); + ++ if (dm->adev->ip_versions[DCE_HWIP][0] > IP_VERSION(3, 0, 1) && ++ plane->type != DRM_PLANE_TYPE_CURSOR) ++ drm_plane_enable_fb_damage_clips(plane); ++ + drm_plane_helper_add(plane, &dm_plane_helper_funcs); + + #ifdef CONFIG_DRM_AMD_DC_HDR +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-add-odm-case-when-looking-for-first-.patch b/queue-6.1/drm-amd-display-add-odm-case-when-looking-for-first-.patch new file mode 100644 index 00000000000..f7353ea9ed3 --- /dev/null +++ b/queue-6.1/drm-amd-display-add-odm-case-when-looking-for-first-.patch @@ -0,0 +1,151 @@ +From d2a46a3778836d36889ee76462a0ccf47ca8db73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 May 2023 16:40:19 -0400 +Subject: drm/amd/display: add ODM case when looking for first split pipe + +From: Samson Tam + +[ Upstream commit 59de751e3845d699e02dc4da47322b92d83a41e2 ] + +[Why] +When going from ODM 2:1 single display case to max displays, second +odm pipe needs to be repurposed for one of the new single displays. +However, acquire_first_split_pipe() only handles MPC case and not +ODM case + +[How] +Add ODM conditions in acquire_first_split_pipe() +Add commit_minimal_transition_state() in commit_streams() to handle +odm 2:1 exit first, and then process new streams +Handle ODM condition in commit_minimal_transition_state() + +Cc: Mario Limonciello +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Acked-by: Stylon Wang +Signed-off-by: Samson Tam +Reviewed-by: Alvin Lee +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 36 ++++++++++++++++++- + .../gpu/drm/amd/display/dc/core/dc_resource.c | 20 +++++++++++ + 2 files changed, 55 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 c429748c86cdb..629bc53f61877 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -1913,6 +1913,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c + return result; + } + ++static bool commit_minimal_transition_state(struct dc *dc, ++ struct dc_state *transition_base_context); ++ + /** + * dc_commit_streams - Commit current stream state + * +@@ -1934,6 +1937,8 @@ enum dc_status dc_commit_streams(struct dc *dc, + struct dc_state *context; + enum dc_status res = DC_OK; + struct dc_validation_set set[MAX_STREAMS] = {0}; ++ struct pipe_ctx *pipe; ++ bool handle_exit_odm2to1 = false; + + if (!streams_changed(dc, streams, stream_count)) + return res; +@@ -1955,6 +1960,22 @@ enum dc_status dc_commit_streams(struct dc *dc, + } + } + ++ /* Check for case where we are going from odm 2:1 to max ++ * pipe scenario. For these cases, we will call ++ * commit_minimal_transition_state() to exit out of odm 2:1 ++ * first before processing new streams ++ */ ++ if (stream_count == dc->res_pool->pipe_count) { ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ pipe = &dc->current_state->res_ctx.pipe_ctx[i]; ++ if (pipe->next_odm_pipe) ++ handle_exit_odm2to1 = true; ++ } ++ } ++ ++ if (handle_exit_odm2to1) ++ res = commit_minimal_transition_state(dc, dc->current_state); ++ + context = dc_create_state(dc); + if (!context) + goto context_alloc_fail; +@@ -3759,6 +3780,7 @@ static bool commit_minimal_transition_state(struct dc *dc, + unsigned int i, j; + unsigned int pipe_in_use = 0; + bool subvp_in_use = false; ++ bool odm_in_use = false; + + if (!transition_context) + return false; +@@ -3783,6 +3805,18 @@ static bool commit_minimal_transition_state(struct dc *dc, + } + } + ++ /* If ODM is enabled and we are adding or removing planes from any ODM ++ * pipe, we must use the minimal transition. ++ */ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; ++ ++ if (pipe->stream && pipe->next_odm_pipe) { ++ odm_in_use = true; ++ break; ++ } ++ } ++ + /* When the OS add a new surface if we have been used all of pipes with odm combine + * and mpc split feature, it need use commit_minimal_transition_state to transition safely. + * After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need +@@ -3791,7 +3825,7 @@ static bool commit_minimal_transition_state(struct dc *dc, + * Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially + * enter/exit MPO when DCN still have enough resources. + */ +- if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use) { ++ if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use && !odm_in_use) { + dc_release_state(transition_context); + return true; + } +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 f0d05829288bd..a26e52abc9898 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -1444,6 +1444,26 @@ static int acquire_first_split_pipe( + split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; + split_pipe->pipe_idx = i; + ++ split_pipe->stream = stream; ++ return i; ++ } else if (split_pipe->prev_odm_pipe && ++ split_pipe->prev_odm_pipe->plane_state == split_pipe->plane_state) { ++ split_pipe->prev_odm_pipe->next_odm_pipe = split_pipe->next_odm_pipe; ++ if (split_pipe->next_odm_pipe) ++ split_pipe->next_odm_pipe->prev_odm_pipe = split_pipe->prev_odm_pipe; ++ ++ if (split_pipe->prev_odm_pipe->plane_state) ++ resource_build_scaling_params(split_pipe->prev_odm_pipe); ++ ++ memset(split_pipe, 0, sizeof(*split_pipe)); ++ split_pipe->stream_res.tg = pool->timing_generators[i]; ++ split_pipe->plane_res.hubp = pool->hubps[i]; ++ split_pipe->plane_res.ipp = pool->ipps[i]; ++ split_pipe->plane_res.dpp = pool->dpps[i]; ++ split_pipe->stream_res.opp = pool->opps[i]; ++ split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; ++ split_pipe->pipe_idx = i; ++ + split_pipe->stream = stream; + return i; + } +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-add-pixel-rate-based-crb-allocation-.patch b/queue-6.1/drm-amd-display-add-pixel-rate-based-crb-allocation-.patch new file mode 100644 index 00000000000..42afb119a62 --- /dev/null +++ b/queue-6.1/drm-amd-display-add-pixel-rate-based-crb-allocation-.patch @@ -0,0 +1,391 @@ +From 6d013ad79120cadd7270b91da6a78a7177ee26e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 15:13:18 -0500 +Subject: drm/amd/display: add pixel rate based CRB allocation support + +From: Dmytro Laktyushkin + +[ Upstream commit 9ba90d760e9354c124fa9bbea08017d96699a82c ] + +This feature is meant to unblock PSTATE for certain high end display +configs on dcn315. This is achieved by allocating CRB to detile buffer +based on display requirements to meet pstate latency hiding needs. + +Tested-by: Daniel Wheeler +Reviewed-by: Charlene Liu +Acked-by: Rodrigo Siqueira +Signed-off-by: Dmytro Laktyushkin +Signed-off-by: Alex Deucher +Stable-dep-of: 49f26218c344 ("drm/amd/display: fix dcn315 single stream crb allocation") +Signed-off-by: Sasha Levin +--- + .../drm/amd/display/dc/dcn31/dcn31_hubbub.c | 1 + + .../amd/display/dc/dcn315/dcn315_resource.c | 97 ++++++++++++++++++- + .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.c | 25 ++++- + .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.h | 3 + + .../dc/dml/dcn31/display_mode_vba_31.c | 39 +++++--- + .../drm/amd/display/dc/dml/display_mode_vba.c | 6 ++ + 6 files changed, 154 insertions(+), 17 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c +index 6360dc9502e70..0f231e42e4206 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c +@@ -103,6 +103,7 @@ static void dcn31_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigne + default: + break; + } ++ DC_LOG_DEBUG("Set DET%d to %d segments\n", hubp_inst, det_size_segments); + /* Should never be hit, if it is we have an erroneous hw config*/ + ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size + + hubbub2->det3_size + hubbub2->compbuf_size_segments <= hubbub2->crb_size_segs); +diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +index 19f2025cb7907..88c4a378daa12 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +@@ -136,6 +136,9 @@ + + #define DCN3_15_MAX_DET_SIZE 384 + #define DCN3_15_CRB_SEGMENT_SIZE_KB 64 ++#define DCN3_15_MAX_DET_SEGS (DCN3_15_MAX_DET_SIZE / DCN3_15_CRB_SEGMENT_SIZE_KB) ++/* Minimum 2 extra segments need to be in compbuf and claimable to guarantee seamless mpo transitions */ ++#define MIN_RESERVED_DET_SEGS 2 + + enum dcn31_clk_src_array_id { + DCN31_CLK_SRC_PLL0, +@@ -1636,21 +1639,57 @@ static bool is_dual_plane(enum surface_pixel_format format) + return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; + } + ++static int source_format_to_bpp (enum source_format_class SourcePixelFormat) ++{ ++ if (SourcePixelFormat == dm_444_64) ++ return 8; ++ else if (SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16) ++ return 2; ++ else if (SourcePixelFormat == dm_444_8) ++ return 1; ++ else if (SourcePixelFormat == dm_rgbe_alpha) ++ return 5; ++ else if (SourcePixelFormat == dm_420_8) ++ return 3; ++ else if (SourcePixelFormat == dm_420_12) ++ return 6; ++ else ++ return 4; ++} ++ ++static bool allow_pixel_rate_crb(struct dc *dc, struct dc_state *context) ++{ ++ int i; ++ struct resource_context *res_ctx = &context->res_ctx; ++ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ if (!res_ctx->pipe_ctx[i].stream) ++ continue; ++ ++ /*Don't apply if MPO to avoid transition issues*/ ++ if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state != res_ctx->pipe_ctx[i].plane_state) ++ return false; ++ } ++ return true; ++} ++ + static int dcn315_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) + { +- int i, pipe_cnt; ++ int i, pipe_cnt, crb_idx, crb_pipes; + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *pipe; + const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB; ++ int remaining_det_segs = max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB; ++ bool pixel_rate_crb = allow_pixel_rate_crb(dc, context); + + DC_FP_START(); + dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); + +- for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { ++ for (i = 0, pipe_cnt = 0, crb_pipes = 0; i < dc->res_pool->pipe_count; i++) { + struct dc_crtc_timing *timing; + + if (!res_ctx->pipe_ctx[i].stream) +@@ -1672,6 +1711,23 @@ static int dcn315_populate_dml_pipes_from_context( + pipes[pipe_cnt].dout.dsc_input_bpc = 0; + DC_FP_START(); + dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt); ++ if (pixel_rate_crb && !pipe->top_pipe && !pipe->prev_odm_pipe) { ++ int bpp = source_format_to_bpp(pipes[pipe_cnt].pipe.src.source_format); ++ /* Ceil to crb segment size */ ++ int approx_det_segs_required_for_pstate = dcn_get_approx_det_segs_required_for_pstate( ++ &context->bw_ctx.dml.soc, timing->pix_clk_100hz, bpp, DCN3_15_CRB_SEGMENT_SIZE_KB); ++ if (approx_det_segs_required_for_pstate <= 2 * DCN3_15_MAX_DET_SEGS) { ++ bool split_required = approx_det_segs_required_for_pstate > DCN3_15_MAX_DET_SEGS; ++ split_required = split_required || timing->pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc); ++ split_required = split_required || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); ++ if (split_required) ++ approx_det_segs_required_for_pstate += approx_det_segs_required_for_pstate % 2; ++ pipes[pipe_cnt].pipe.src.det_size_override = approx_det_segs_required_for_pstate; ++ remaining_det_segs -= approx_det_segs_required_for_pstate; ++ } else ++ remaining_det_segs = -1; ++ crb_pipes++; ++ } + DC_FP_END(); + + if (pipes[pipe_cnt].dout.dsc_enable) { +@@ -1690,16 +1746,49 @@ static int dcn315_populate_dml_pipes_from_context( + break; + } + } +- + pipe_cnt++; + } + ++ /* Spread remaining unreserved crb evenly among all pipes, use default policy if not enough det or single pipe */ ++ if (pixel_rate_crb) { ++ for (i = 0, pipe_cnt = 0, crb_idx = 0; i < dc->res_pool->pipe_count; i++) { ++ pipe = &res_ctx->pipe_ctx[i]; ++ if (!pipe->stream) ++ continue; ++ ++ if (!pipe->top_pipe && !pipe->prev_odm_pipe) { ++ bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc) ++ || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); ++ ++ if (remaining_det_segs < 0 || crb_pipes == 1) ++ pipes[pipe_cnt].pipe.src.det_size_override = 0; ++ if (remaining_det_segs > MIN_RESERVED_DET_SEGS) ++ pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes + ++ (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0); ++ if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) { ++ /* Clamp to 2 pipe split max det segments */ ++ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS); ++ pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS; ++ } ++ if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) { ++ /* If we are splitting we must have an even number of segments */ ++ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2; ++ pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2; ++ } ++ /* Convert segments into size for DML use */ ++ pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB; ++ crb_idx++; ++ } ++ pipe_cnt++; ++ } ++ } ++ + if (pipe_cnt) + context->bw_ctx.dml.ip.det_buffer_size_kbytes = + (max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / pipe_cnt) * DCN3_15_CRB_SEGMENT_SIZE_KB; + if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_15_MAX_DET_SIZE) + context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_15_MAX_DET_SIZE; +- ASSERT(context->bw_ctx.dml.ip.det_buffer_size_kbytes >= DCN3_15_DEFAULT_DET_SIZE); ++ + dc->config.enable_4to1MPC = false; + if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { + if (is_dual_plane(pipe->plane_state->format) +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +index e48923f314b36..0c0feec88e4f1 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +@@ -483,7 +483,7 @@ void dcn31_calculate_wm_and_dlg_fp( + int pipe_cnt, + int vlevel) + { +- int i, pipe_idx, active_hubp_count = 0; ++ int i, pipe_idx, total_det = 0, active_hubp_count = 0; + double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; + + dc_assert_fp_enabled(); +@@ -560,6 +560,18 @@ void dcn31_calculate_wm_and_dlg_fp( + context->bw_ctx.bw.dcn.clk.fclk_khz = 0; + context->bw_ctx.bw.dcn.clk.p_state_change_support = true; + } ++ for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { ++ if (!context->res_ctx.pipe_ctx[i].stream) ++ continue; ++ ++ context->res_ctx.pipe_ctx[i].det_buffer_size_kb = ++ get_det_buffer_size_kbytes(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); ++ if (context->res_ctx.pipe_ctx[i].det_buffer_size_kb > 384) ++ context->res_ctx.pipe_ctx[i].det_buffer_size_kb /= 2; ++ total_det += context->res_ctx.pipe_ctx[i].det_buffer_size_kb; ++ pipe_idx++; ++ } ++ context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - total_det; + } + + void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +@@ -812,3 +824,14 @@ int dcn_get_max_non_odm_pix_rate_100hz(struct _vcs_dpi_soc_bounding_box_st *soc) + { + return soc->clock_limits[0].dispclk_mhz * 10000.0 / (1.0 + soc->dcn_downspread_percent / 100.0); + } ++ ++int dcn_get_approx_det_segs_required_for_pstate( ++ struct _vcs_dpi_soc_bounding_box_st *soc, ++ int pix_clk_100hz, int bpp, int seg_size_kb) ++{ ++ /* Roughly calculate required crb to hide latency. In practice there is slightly ++ * more buffer available for latency hiding ++ */ ++ return (int)(soc->dram_clock_change_latency_us * pix_clk_100hz * bpp ++ / 10240000 + seg_size_kb - 1) / seg_size_kb; ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h +index ab8c48b8b7e05..99518f64d83dd 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h +@@ -47,5 +47,8 @@ void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params + void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + int dcn_get_max_non_odm_pix_rate_100hz(struct _vcs_dpi_soc_bounding_box_st *soc); ++int dcn_get_approx_det_segs_required_for_pstate( ++ struct _vcs_dpi_soc_bounding_box_st *soc, ++ int pix_clk_100hz, int bpp, int seg_size_kb); + + #endif /* __DCN31_FPU_H__*/ +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +index cf8f3d690fa66..ebc04b72b284b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +@@ -533,7 +533,8 @@ static void CalculateStutterEfficiency( + static void CalculateSwathAndDETConfiguration( + bool ForceSingleDPP, + int NumberOfActivePlanes, +- unsigned int DETBufferSizeInKByte, ++ bool DETSharedByAllDPP, ++ unsigned int DETBufferSizeInKByte[], + double MaximumSwathWidthLuma[], + double MaximumSwathWidthChroma[], + enum scan_direction_class SourceScan[], +@@ -3116,7 +3117,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman + v->SurfaceWidthC[k], + v->SurfaceHeightY[k], + v->SurfaceHeightC[k], +- v->DETBufferSizeInKByte[0] * 1024, ++ v->DETBufferSizeInKByte[k] * 1024, + v->BlockHeight256BytesY[k], + v->BlockHeight256BytesC[k], + v->SurfaceTiling[k], +@@ -3311,7 +3312,8 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) + CalculateSwathAndDETConfiguration( + false, + v->NumberOfActivePlanes, +- v->DETBufferSizeInKByte[0], ++ mode_lib->project == DML_PROJECT_DCN315 && v->DETSizeOverride[0], ++ v->DETBufferSizeInKByte, + dummy1, + dummy2, + v->SourceScan, +@@ -3777,14 +3779,16 @@ static noinline void CalculatePrefetchSchedulePerPlane( + &v->VReadyOffsetPix[k]); + } + +-static void PatchDETBufferSizeInKByte(unsigned int NumberOfActivePlanes, int NoOfDPPThisState[], unsigned int config_return_buffer_size_in_kbytes, unsigned int *DETBufferSizeInKByte) ++static void PatchDETBufferSizeInKByte(unsigned int NumberOfActivePlanes, int NoOfDPPThisState[], unsigned int config_return_buffer_size_in_kbytes, unsigned int DETBufferSizeInKByte[]) + { + int i, total_pipes = 0; + for (i = 0; i < NumberOfActivePlanes; i++) + total_pipes += NoOfDPPThisState[i]; +- *DETBufferSizeInKByte = ((config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB) / 64 / total_pipes) * 64; +- if (*DETBufferSizeInKByte > DCN3_15_MAX_DET_SIZE) +- *DETBufferSizeInKByte = DCN3_15_MAX_DET_SIZE; ++ DETBufferSizeInKByte[0] = ((config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB) / 64 / total_pipes) * 64; ++ if (DETBufferSizeInKByte[0] > DCN3_15_MAX_DET_SIZE) ++ DETBufferSizeInKByte[0] = DCN3_15_MAX_DET_SIZE; ++ for (i = 1; i < NumberOfActivePlanes; i++) ++ DETBufferSizeInKByte[i] = DETBufferSizeInKByte[0]; + } + + +@@ -4024,7 +4028,8 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l + CalculateSwathAndDETConfiguration( + true, + v->NumberOfActivePlanes, +- v->DETBufferSizeInKByte[0], ++ mode_lib->project == DML_PROJECT_DCN315 && v->DETSizeOverride[0], ++ v->DETBufferSizeInKByte, + v->MaximumSwathWidthLuma, + v->MaximumSwathWidthChroma, + v->SourceScan, +@@ -4164,6 +4169,10 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l + || (v->PlaneRequiredDISPCLK > v->MaxDispclkRoundedDownToDFSGranularity)) { + v->DISPCLK_DPPCLK_Support[i][j] = false; + } ++ if (mode_lib->project == DML_PROJECT_DCN315 && v->DETSizeOverride[k] > DCN3_15_MAX_DET_SIZE && v->NoOfDPP[i][j][k] < 2) { ++ v->MPCCombine[i][j][k] = true; ++ v->NoOfDPP[i][j][k] = 2; ++ } + } + v->TotalNumberOfActiveDPP[i][j] = 0; + v->TotalNumberOfSingleDPPPlanes[i][j] = 0; +@@ -4640,12 +4649,13 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l + v->ODMCombineEnableThisState[k] = v->ODMCombineEnablePerState[i][k]; + } + +- if (v->NumberOfActivePlanes > 1 && mode_lib->project == DML_PROJECT_DCN315) +- PatchDETBufferSizeInKByte(v->NumberOfActivePlanes, v->NoOfDPPThisState, v->ip.config_return_buffer_size_in_kbytes, &v->DETBufferSizeInKByte[0]); ++ if (v->NumberOfActivePlanes > 1 && mode_lib->project == DML_PROJECT_DCN315 && !v->DETSizeOverride[0]) ++ PatchDETBufferSizeInKByte(v->NumberOfActivePlanes, v->NoOfDPPThisState, v->ip.config_return_buffer_size_in_kbytes, v->DETBufferSizeInKByte); + CalculateSwathAndDETConfiguration( + false, + v->NumberOfActivePlanes, +- v->DETBufferSizeInKByte[0], ++ mode_lib->project == DML_PROJECT_DCN315 && v->DETSizeOverride[0], ++ v->DETBufferSizeInKByte, + v->MaximumSwathWidthLuma, + v->MaximumSwathWidthChroma, + v->SourceScan, +@@ -6557,7 +6567,8 @@ static void CalculateStutterEfficiency( + static void CalculateSwathAndDETConfiguration( + bool ForceSingleDPP, + int NumberOfActivePlanes, +- unsigned int DETBufferSizeInKByte, ++ bool DETSharedByAllDPP, ++ unsigned int DETBufferSizeInKByteA[], + double MaximumSwathWidthLuma[], + double MaximumSwathWidthChroma[], + enum scan_direction_class SourceScan[], +@@ -6641,6 +6652,10 @@ static void CalculateSwathAndDETConfiguration( + + *ViewportSizeSupport = true; + for (k = 0; k < NumberOfActivePlanes; ++k) { ++ unsigned int DETBufferSizeInKByte = DETBufferSizeInKByteA[k]; ++ ++ if (DETSharedByAllDPP && DPPPerPlane[k]) ++ DETBufferSizeInKByte /= DPPPerPlane[k]; + if ((SourcePixelFormat[k] == dm_444_64 || SourcePixelFormat[k] == dm_444_32 || SourcePixelFormat[k] == dm_444_16 || SourcePixelFormat[k] == dm_mono_16 + || SourcePixelFormat[k] == dm_mono_8 || SourcePixelFormat[k] == dm_rgbe)) { + if (SurfaceTiling[k] == dm_sw_linear +diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +index 8e6585dab20ef..1070cf8701960 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +@@ -569,6 +569,10 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) + mode_lib->vba.OutputLinkDPRate[mode_lib->vba.NumberOfActivePlanes] = dout->dp_rate; + mode_lib->vba.ODMUse[mode_lib->vba.NumberOfActivePlanes] = dst->odm_combine_policy; + mode_lib->vba.DETSizeOverride[mode_lib->vba.NumberOfActivePlanes] = src->det_size_override; ++ if (src->det_size_override) ++ mode_lib->vba.DETBufferSizeInKByte[mode_lib->vba.NumberOfActivePlanes] = src->det_size_override; ++ else ++ mode_lib->vba.DETBufferSizeInKByte[mode_lib->vba.NumberOfActivePlanes] = ip->det_buffer_size_kbytes; + //TODO: Need to assign correct values to dp_multistream vars + mode_lib->vba.OutputMultistreamEn[mode_lib->vba.NumberOfActiveSurfaces] = dout->dp_multistream_en; + mode_lib->vba.OutputMultistreamId[mode_lib->vba.NumberOfActiveSurfaces] = dout->dp_multistream_id; +@@ -783,6 +787,8 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) + mode_lib->vba.pipe_plane[k] = + mode_lib->vba.NumberOfActivePlanes; + mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++; ++ if (src_k->det_size_override) ++ mode_lib->vba.DETBufferSizeInKByte[mode_lib->vba.NumberOfActivePlanes] = src_k->det_size_override; + if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] + == dm_horz) { + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] += +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-check-if-link-state-is-valid.patch b/queue-6.1/drm-amd-display-check-if-link-state-is-valid.patch new file mode 100644 index 00000000000..cdb4a2328e5 --- /dev/null +++ b/queue-6.1/drm-amd-display-check-if-link-state-is-valid.patch @@ -0,0 +1,40 @@ +From 1c10da1197f03165f82ea759fa6c2bcee6523cd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 08:28:15 -0400 +Subject: drm/amd/display: Check if link state is valid + +From: Rodrigo Siqueira + +[ Upstream commit 03ce7b387e8b0f4a1dc97a878545bdf7c7f23251 ] + +The link state is set to false if there is no link and local sink. Even +though the stream state may not change, it is desirable to commit the +new stream when HPD goes low to high. + +Reviewed-by: Harry Wentland +Signed-off-by: Rodrigo Siqueira +Co-developed-by: Aurabindo Pillai +Signed-off-by: Aurabindo Pillai +Signed-off-by: Alex Deucher +Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index cca0143444164..beb2d7f103c58 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -1517,6 +1517,8 @@ static bool context_changed( + for (i = 0; i < dc->current_state->stream_count; i++) { + if (dc->current_state->streams[i] != context->streams[i]) + return true; ++ if (!context->streams[i]->link->link_state_valid) ++ return true; + } + + return false; +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-copy-dc-context-in-the-commit-stream.patch b/queue-6.1/drm-amd-display-copy-dc-context-in-the-commit-stream.patch new file mode 100644 index 00000000000..ed907b8bd0a --- /dev/null +++ b/queue-6.1/drm-amd-display-copy-dc-context-in-the-commit-stream.patch @@ -0,0 +1,122 @@ +From 9f5de78e3f4fbe0b8c0b26bb0e55c155b2ff668e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 08:28:18 -0400 +Subject: drm/amd/display: Copy DC context in the commit streams + +From: Rodrigo Siqueira + +[ Upstream commit 0e986cea0347902b2c72b09c8fe9c0f30d7decb4 ] + +DC adds an instance of DML (which contains VBA) to each context, and +multiple threads might write back to the global VBA resulting in data +overwriting. To keep the consistency with other parts of the DC code, +this commit changes dc_commit_streams to copy the current DC state, and +as a result, it also changes the function signature to expect streams +instead of a context. + +Reviewed-by: Harry Wentland +Signed-off-by: Rodrigo Siqueira +Co-developed-by: Aurabindo Pillai +Signed-off-by: Aurabindo Pillai +Signed-off-by: Alex Deucher +Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 41 +++++++++++++++++++----- + drivers/gpu/drm/amd/display/dc/dc.h | 4 ++- + 2 files changed, 36 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index a457b87d23c41..31791c557c8f8 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -1913,23 +1913,44 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c + return result; + } + +-enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context) ++/** ++ * dc_commit_streams - Commit current stream state ++ * ++ * @dc: DC object with the commit state to be configured in the hardware ++ * @streams: Array with a list of stream state ++ * @stream_count: Total of streams ++ * ++ * Function responsible for commit streams change to the hardware. ++ * ++ * Return: ++ * Return DC_OK if everything work as expected, otherwise, return a dc_status ++ * code. ++ */ ++enum dc_status dc_commit_streams(struct dc *dc, ++ struct dc_stream_state *streams[], ++ uint8_t stream_count) + { +- enum dc_status res = DC_OK; + int i; ++ struct dc_state *context; ++ enum dc_status res = DC_OK; + +- if (!streams_changed(dc, context->streams, context->stream_count)) ++ if (!streams_changed(dc, streams, stream_count)) + return res; + +- DC_LOG_DC("%s: %d streams\n", +- __func__, context->stream_count); ++ DC_LOG_DC("%s: %d streams\n", __func__, stream_count); + +- for (i = 0; i < context->stream_count; i++) { +- struct dc_stream_state *stream = context->streams[i]; ++ for (i = 0; i < stream_count; i++) { ++ struct dc_stream_state *stream = streams[i]; + + dc_stream_log(dc, stream); + } + ++ context = dc_create_state(dc); ++ if (!context) ++ goto context_alloc_fail; ++ ++ dc_resource_state_copy_construct_current(dc, context); ++ + /* + * Previous validation was perfomred with fast_validation = true and + * the full DML state required for hardware programming was skipped. +@@ -1945,6 +1966,10 @@ enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context) + + res = dc_commit_state_no_check(dc, context); + ++context_alloc_fail: ++ ++ DC_LOG_DC("%s Finished.\n", __func__); ++ + return (res == DC_OK); + } + +@@ -1960,7 +1985,7 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context) + * we get more confident about this change we'll need to enable + * the new sequence for all ASICs. */ + if (dc->ctx->dce_version >= DCN_VERSION_3_2) { +- result = dc_commit_streams(dc, context); ++ result = dc_commit_streams(dc, context->streams, context->stream_count); + return result == DC_OK; + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index 3db3554c289b4..78b7dbd23a3b7 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -1326,7 +1326,9 @@ void dc_resource_state_destruct(struct dc_state *context); + + bool dc_resource_is_dsc_encoding_supported(const struct dc *dc); + +-enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context); ++enum dc_status dc_commit_streams(struct dc *dc, ++ struct dc_stream_state *streams[], ++ uint8_t stream_count); + + /* TODO: When the transition to the new commit sequence is done, remove this + * function in favor of dc_commit_streams. */ +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-enable-new-commit-sequence-only-for-.patch b/queue-6.1/drm-amd-display-enable-new-commit-sequence-only-for-.patch new file mode 100644 index 00000000000..f2b76130b48 --- /dev/null +++ b/queue-6.1/drm-amd-display-enable-new-commit-sequence-only-for-.patch @@ -0,0 +1,120 @@ +From 4f5d90251965e0a6282d2742cc054482de4be588 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 08:28:17 -0400 +Subject: drm/amd/display: Enable new commit sequence only for DCN32x + +From: Rodrigo Siqueira + +[ Upstream commit 7b36f4d18e3e4941d12fe027ad6ad6123c257027 ] + +Change commit sequence will impact all ASICs. It is prudent to run this +update in small steps to keep issues under control and avoid any +potential regression. With this idea in mind, this commit is preparation +work for the complete transition to the new commit sequence. To maintain +this change manageable across multiple ASICs, this commit adds a new +function named dc_commit_streams which is a copy of the dc_commit_state +with some minor changes. Finally, inside the dc_commit_state, we check +if we are using DCN32x or above and enable the new sequence only for +those devices. + +Reviewed-by: Harry Wentland +Signed-off-by: Rodrigo Siqueira +Co-developed-by: Aurabindo Pillai +Signed-off-by: Aurabindo Pillai +Signed-off-by: Alex Deucher +Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 46 ++++++++++++++++++++++++ + drivers/gpu/drm/amd/display/dc/dc.h | 13 +++---- + 2 files changed, 50 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 226c17e78d3e1..a457b87d23c41 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -1913,11 +1913,57 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c + return result; + } + ++enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context) ++{ ++ enum dc_status res = DC_OK; ++ int i; ++ ++ if (!streams_changed(dc, context->streams, context->stream_count)) ++ return res; ++ ++ DC_LOG_DC("%s: %d streams\n", ++ __func__, context->stream_count); ++ ++ for (i = 0; i < context->stream_count; i++) { ++ struct dc_stream_state *stream = context->streams[i]; ++ ++ dc_stream_log(dc, stream); ++ } ++ ++ /* ++ * Previous validation was perfomred with fast_validation = true and ++ * the full DML state required for hardware programming was skipped. ++ * ++ * Re-validate here to calculate these parameters / watermarks. ++ */ ++ res = dc_validate_global_state(dc, context, false); ++ if (res != DC_OK) { ++ DC_LOG_ERROR("DC commit global validation failure: %s (%d)", ++ dc_status_to_str(res), res); ++ return res; ++ } ++ ++ res = dc_commit_state_no_check(dc, context); ++ ++ return (res == DC_OK); ++} ++ ++/* TODO: When the transition to the new commit sequence is done, remove this ++ * function in favor of dc_commit_streams. */ + bool dc_commit_state(struct dc *dc, struct dc_state *context) + { + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + ++ /* TODO: Since change commit sequence can have a huge impact, ++ * we decided to only enable it for DCN3x. However, as soon as ++ * we get more confident about this change we'll need to enable ++ * the new sequence for all ASICs. */ ++ if (dc->ctx->dce_version >= DCN_VERSION_3_2) { ++ result = dc_commit_streams(dc, context); ++ return result == DC_OK; ++ } ++ + if (!streams_changed(dc, context->streams, context->stream_count)) + return DC_OK; + +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index 3f277009075fd..3db3554c289b4 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -1326,15 +1326,10 @@ void dc_resource_state_destruct(struct dc_state *context); + + bool dc_resource_is_dsc_encoding_supported(const struct dc *dc); + +-/* +- * TODO update to make it about validation sets +- * Set up streams and links associated to drive sinks +- * The streams parameter is an absolute set of all active streams. +- * +- * After this call: +- * Phy, Encoder, Timing Generator are programmed and enabled. +- * New streams are enabled with blank stream; no memory read. +- */ ++enum dc_status dc_commit_streams(struct dc *dc, struct dc_state *context); ++ ++/* TODO: When the transition to the new commit sequence is done, remove this ++ * function in favor of dc_commit_streams. */ + bool dc_commit_state(struct dc *dc, struct dc_state *context); + + struct dc_state *dc_create_state(struct dc *dc); +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-fix-dc-core-dc.c-kernel-doc.patch b/queue-6.1/drm-amd-display-fix-dc-core-dc.c-kernel-doc.patch new file mode 100644 index 00000000000..e8c048d4c6f --- /dev/null +++ b/queue-6.1/drm-amd-display-fix-dc-core-dc.c-kernel-doc.patch @@ -0,0 +1,169 @@ +From 5fd182401f71804be81cee4cecf6f4e2f169e2a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Dec 2022 17:00:51 -0800 +Subject: drm/amd/display: fix dc/core/dc.c kernel-doc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Randy Dunlap + +[ Upstream commit db4107e92a817502ad19fdd30250f87dcb6f6331 ] + +Fix all kernel-doc warnings in dc/core/dc.c: + +dc.c:385: warning: missing initial short description on line: + * dc_stream_adjust_vmin_vmax: +dc.c:392: warning: contents before sections +dc.c:399: warning: No description found for return value of 'dc_stream_adjust_vmin_vmax' +dc.c:434: warning: Excess function parameter 'adjust' description in 'dc_stream_get_last_used_drr_vtotal' +dc.c:434: warning: No description found for return value of 'dc_stream_get_last_used_drr_vtotal' +dc.c:574: warning: No description found for return value of 'dc_stream_configure_crc' +dc.c:1746: warning: No description found for return value of 'dc_commit_state_no_check' +dc.c:4991: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst + * dc_extended_blank_supported 0 Decide whether extended blank is supported +dc.c:4991: warning: missing initial short description on line: + * dc_extended_blank_supported 0 Decide whether extended blank is supported +dc.c:4723: warning: Function parameter or member 'dc' not described in 'dc_enable_dmub_outbox' +dc.c:4926: warning: Function parameter or member 'dc' not described in 'dc_process_dmub_dpia_hpd_int_enable' +dc.c:4926: warning: Function parameter or member 'hpd_int_enable' not described in 'dc_process_dmub_dpia_hpd_int_enable' +12 warnings + +Signed-off-by: Randy Dunlap +Reported-by: kernel test robot +Cc: Rodrigo Siqueira +Cc: Alex Deucher +Cc: Hamza Mahfooz +Cc: Harry Wentland +Cc: Leo Li +Cc: Christian König +Cc: "Pan, Xinhui" +Cc: amd-gfx@lists.freedesktop.org +Signed-off-by: Hamza Mahfooz +Signed-off-by: Alex Deucher +Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 40 +++++++++++++++--------- + 1 file changed, 25 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 85ed1c7cdeaa9..6e2220e2e5ba3 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -382,16 +382,18 @@ static void dc_perf_trace_destroy(struct dc_perf_trace **perf_trace) + } + + /** +- * dc_stream_adjust_vmin_vmax: ++ * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR ++ * @dc: dc reference ++ * @stream: Initial dc stream state ++ * @adjust: Updated parameters for vertical_total_min and vertical_total_max + * + * Looks up the pipe context of dc_stream_state and updates the + * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh + * Rate, which is a power-saving feature that targets reducing panel + * refresh rate while the screen is static + * +- * @dc: dc reference +- * @stream: Initial dc stream state +- * @adjust: Updated parameters for vertical_total_min and vertical_total_max ++ * Return: %true if the pipe context is found and adjusted; ++ * %false if the pipe context is not found. + */ + bool dc_stream_adjust_vmin_vmax(struct dc *dc, + struct dc_stream_state *stream, +@@ -427,14 +429,17 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, + } + + /** +- * dc_stream_get_last_used_drr_vtotal - dc_stream_get_last_vrr_vtotal ++ * dc_stream_get_last_used_drr_vtotal - Looks up the pipe context of ++ * dc_stream_state and gets the last VTOTAL used by DRR (Dynamic Refresh Rate) + * + * @dc: [in] dc reference + * @stream: [in] Initial dc stream state +- * @adjust: [in] Updated parameters for vertical_total_min and ++ * @refresh_rate: [in] new refresh_rate + * +- * Looks up the pipe context of dc_stream_state and gets the last VTOTAL used +- * by DRR (Dynamic Refresh Rate) ++ * Return: %true if the pipe context is found and there is an associated ++ * timing_generator for the DC; ++ * %false if the pipe context is not found or there is no ++ * timing_generator for the DC. + */ + bool dc_stream_get_last_used_drr_vtotal(struct dc *dc, + struct dc_stream_state *stream, +@@ -581,7 +586,10 @@ bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc, struct dc_stream_state *s + * once. + * + * By default, only CRC0 is configured, and the entire frame is used to +- * calculate the crc. ++ * calculate the CRC. ++ * ++ * Return: %false if the stream is not found or CRC capture is not supported; ++ * %true if the stream has been configured. + */ + bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, + struct crc_params *crc_window, bool enable, bool continuous) +@@ -650,7 +658,7 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, + * dc_stream_configure_crc needs to be called beforehand to enable CRCs. + * + * Return: +- * false if stream is not found, or if CRCs are not enabled. ++ * %false if stream is not found, or if CRCs are not enabled. + */ + bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, + uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) +@@ -1739,6 +1747,8 @@ void dc_z10_save_init(struct dc *dc) + /* + * Applies given context to HW and copy it into current context. + * It's up to the user to release the src context afterwards. ++ * ++ * Return: an enum dc_status result code for the operation + */ + static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context) + { +@@ -4600,7 +4610,7 @@ bool dc_enable_dmub_notifications(struct dc *dc) + /** + * dc_enable_dmub_outbox - Enables DMUB unsolicited notification + * +- * dc: [in] dc structure ++ * @dc: [in] dc structure + * + * Enables DMUB unsolicited notifications to x86 via outbox. + */ +@@ -4801,8 +4811,8 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, + /** + * dc_process_dmub_dpia_hpd_int_enable - Submits DPIA DPD interruption + * +- * @dc [in]: dc structure +- * @hpd_int_enable [in]: 1 for hpd int enable, 0 to disable ++ * @dc: [in] dc structure ++ * @hpd_int_enable: [in] 1 for hpd int enable, 0 to disable + * + * Submits dpia hpd int enable command to dmub via inbox message + */ +@@ -4883,7 +4893,7 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo + } + + /** +- * dc_extended_blank_supported 0 Decide whether extended blank is supported ++ * dc_extended_blank_supported - Decide whether extended blank is supported + * + * @dc: [in] Current DC state + * +@@ -4892,7 +4902,7 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo + * ability to enter z9/z10. + * + * Return: +- * Indicate whether extended blank is supported (true or false) ++ * Indicate whether extended blank is supported (%true or %false) + */ + bool dc_extended_blank_supported(struct dc *dc) + { +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-fix-dcn315-single-stream-crb-allocat.patch b/queue-6.1/drm-amd-display-fix-dcn315-single-stream-crb-allocat.patch new file mode 100644 index 00000000000..993eb74d209 --- /dev/null +++ b/queue-6.1/drm-amd-display-fix-dcn315-single-stream-crb-allocat.patch @@ -0,0 +1,78 @@ +From 902df244de409cc229c1e962472d1abb7267bbcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 May 2023 15:50:40 -0400 +Subject: drm/amd/display: fix dcn315 single stream crb allocation + +From: Dmytro Laktyushkin + +[ Upstream commit 49f26218c344741cb3eaa740b1e44e960551a87f ] + +Change to improve avoiding asymetric crb calculations for single stream +scenarios. + +Cc: Mario Limonciello +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Acked-by: Stylon Wang +Signed-off-by: Dmytro Laktyushkin +Reviewed-by: Charlene Liu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/display/dc/dcn315/dcn315_resource.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +index 88c4a378daa12..b9b1e5ac4f538 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +@@ -1662,6 +1662,10 @@ static bool allow_pixel_rate_crb(struct dc *dc, struct dc_state *context) + int i; + struct resource_context *res_ctx = &context->res_ctx; + ++ /*Don't apply for single stream*/ ++ if (context->stream_count < 2) ++ return false; ++ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (!res_ctx->pipe_ctx[i].stream) + continue; +@@ -1749,19 +1753,23 @@ static int dcn315_populate_dml_pipes_from_context( + pipe_cnt++; + } + +- /* Spread remaining unreserved crb evenly among all pipes, use default policy if not enough det or single pipe */ ++ /* Spread remaining unreserved crb evenly among all pipes*/ + if (pixel_rate_crb) { + for (i = 0, pipe_cnt = 0, crb_idx = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &res_ctx->pipe_ctx[i]; + if (!pipe->stream) + continue; + ++ /* Do not use asymetric crb if not enough for pstate support */ ++ if (remaining_det_segs < 0) { ++ pipes[pipe_cnt].pipe.src.det_size_override = 0; ++ continue; ++ } ++ + if (!pipe->top_pipe && !pipe->prev_odm_pipe) { + bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc) + || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); + +- if (remaining_det_segs < 0 || crb_pipes == 1) +- pipes[pipe_cnt].pipe.src.det_size_override = 0; + if (remaining_det_segs > MIN_RESERVED_DET_SEGS) + pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes + + (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0); +@@ -1777,6 +1785,7 @@ static int dcn315_populate_dml_pipes_from_context( + } + /* Convert segments into size for DML use */ + pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB; ++ + crb_idx++; + } + pipe_cnt++; +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-fix-possible-underflow-for-displays-.patch b/queue-6.1/drm-amd-display-fix-possible-underflow-for-displays-.patch new file mode 100644 index 00000000000..9a915e98082 --- /dev/null +++ b/queue-6.1/drm-amd-display-fix-possible-underflow-for-displays-.patch @@ -0,0 +1,77 @@ +From be2cf4aa4b228854ea43ceb55bb4d205cb2ef1ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Apr 2023 14:29:48 -0400 +Subject: drm/amd/display: Fix possible underflow for displays with large + vblank + +From: Daniel Miess + +[ Upstream commit 1a4bcdbea4319efeb26cc4b05be859a7867e02dc ] + +[Why] +Underflow observed when using a display with a large vblank region +and low refresh rate + +[How] +Simplify calculation of vblank_nom + +Increase value for VBlankNomDefaultUS to 800us + +Reviewed-by: Jun Lei +Acked-by: Aurabindo Pillai +Signed-off-by: Daniel Miess +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0") +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/dml/dcn314/dcn314_fpu.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +index 395eed9f6b1be..a2a32cb9d5710 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +@@ -32,7 +32,7 @@ + #include "dml/display_mode_vba.h" + + struct _vcs_dpi_ip_params_st dcn3_14_ip = { +- .VBlankNomDefaultUS = 668, ++ .VBlankNomDefaultUS = 800, + .gpuvm_enable = 1, + .gpuvm_max_page_table_levels = 1, + .hostvm_enable = 1, +@@ -288,7 +288,7 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *pipe; + bool upscaled = false; +- bool isFreesyncVideo = false; ++ const unsigned int max_allowed_vblank_nom = 1023; + + dc_assert_fp_enabled(); + +@@ -302,16 +302,11 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c + pipe = &res_ctx->pipe_ctx[i]; + timing = &pipe->stream->timing; + +- isFreesyncVideo = pipe->stream->adjust.v_total_max == pipe->stream->adjust.v_total_min; +- isFreesyncVideo = isFreesyncVideo && pipe->stream->adjust.v_total_min > timing->v_total; +- +- if (!isFreesyncVideo) { +- pipes[pipe_cnt].pipe.dest.vblank_nom = +- dcn3_14_ip.VBlankNomDefaultUS / (timing->h_total / (timing->pix_clk_100hz / 10000.0)); +- } else { +- pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min; +- pipes[pipe_cnt].pipe.dest.vblank_nom = timing->v_total - pipes[pipe_cnt].pipe.dest.vactive; +- } ++ pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min; ++ pipes[pipe_cnt].pipe.dest.vblank_nom = timing->v_total - pipes[pipe_cnt].pipe.dest.vactive; ++ pipes[pipe_cnt].pipe.dest.vblank_nom = min(pipes[pipe_cnt].pipe.dest.vblank_nom, dcn3_14_ip.VBlankNomDefaultUS); ++ pipes[pipe_cnt].pipe.dest.vblank_nom = max(pipes[pipe_cnt].pipe.dest.vblank_nom, timing->v_sync_width); ++ pipes[pipe_cnt].pipe.dest.vblank_nom = min(pipes[pipe_cnt].pipe.dest.vblank_nom, max_allowed_vblank_nom); + + if (pipe->plane_state && + (pipe->plane_state->src_rect.height < pipe->plane_state->dst_rect.height || +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-fix-unbounded-requesting-for-high-pi.patch b/queue-6.1/drm-amd-display-fix-unbounded-requesting-for-high-pi.patch new file mode 100644 index 00000000000..c4b7cbfb881 --- /dev/null +++ b/queue-6.1/drm-amd-display-fix-unbounded-requesting-for-high-pi.patch @@ -0,0 +1,68 @@ +From 8afb1be5e8773495b47113618466983efeee3b5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 17:09:11 -0400 +Subject: drm/amd/display: fix unbounded requesting for high pixel rate modes + on dcn315 + +From: Dmytro Laktyushkin + +[ Upstream commit 655435df0936ce2fda0d5ced7e50101179a3acfd ] + +Unbounded requesting is getting configured for odm mode calculations which +is incorrect. This change checks whether mode requires odm ahead of time. + +Reviewed-by: Jun Lei +Acked-by: Tom Chung +Signed-off-by: Dmytro Laktyushkin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 49f26218c344 ("drm/amd/display: fix dcn315 single stream crb allocation") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c | 4 +++- + drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c | 5 +++++ + drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h | 1 + + 3 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +index 31cbc5762eab3..19f2025cb7907 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +@@ -1707,7 +1707,9 @@ static int dcn315_populate_dml_pipes_from_context( + dc->config.enable_4to1MPC = true; + context->bw_ctx.dml.ip.det_buffer_size_kbytes = + (max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / 4) * DCN3_15_CRB_SEGMENT_SIZE_KB; +- } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { ++ } else if (!is_dual_plane(pipe->plane_state->format) ++ && pipe->plane_state->src_rect.width <= 5120 ++ && pipe->stream->timing.pix_clk_100hz < dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc)) { + /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ + context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; + pipes[0].pipe.src.unbounded_req_mode = true; +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +index aa1c2917a4a1d..e48923f314b36 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +@@ -807,3 +807,8 @@ void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param + else + dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31_FPGA); + } ++ ++int dcn_get_max_non_odm_pix_rate_100hz(struct _vcs_dpi_soc_bounding_box_st *soc) ++{ ++ return soc->clock_limits[0].dispclk_mhz * 10000.0 / (1.0 + soc->dcn_downspread_percent / 100.0); ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h +index fd58b2561ec9e..ab8c48b8b7e05 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h +@@ -46,5 +46,6 @@ void dcn31_calculate_wm_and_dlg_fp( + void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); ++int dcn_get_max_non_odm_pix_rate_100hz(struct _vcs_dpi_soc_bounding_box_st *soc); + + #endif /* __DCN31_FPU_H__*/ +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-include-surface-of-unaffected-stream.patch b/queue-6.1/drm-amd-display-include-surface-of-unaffected-stream.patch new file mode 100644 index 00000000000..8f3a3d8556d --- /dev/null +++ b/queue-6.1/drm-amd-display-include-surface-of-unaffected-stream.patch @@ -0,0 +1,112 @@ +From 2563a7dc444a6d78de8fdc29672e31e27e5e8214 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 08:28:19 -0400 +Subject: drm/amd/display: Include surface of unaffected streams + +From: Rodrigo Siqueira + +[ Upstream commit f6ae69f49fcf697b6ffa93d58eb3746897f61cf8 ] + +The commit stream function does not include surfaces of unaffected +streams, which may lead to some blank screens during mode change in some +edge cases. This commit adds surfaces of unaffected streams followed by +kernel-doc for documenting some of the fields that participate in this +change. + +v2: squash in kerneldoc warning fix (Alex) + +Reviewed-by: Harry Wentland +Signed-off-by: Rodrigo Siqueira +Co-developed-by: Aurabindo Pillai +Signed-off-by: Aurabindo Pillai +Signed-off-by: Alex Deucher +Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +++++++++++- + drivers/gpu/drm/amd/display/dc/dc.h | 15 +++++++++++++-- + drivers/gpu/drm/amd/display/dc/dc_stream.h | 4 ++++ + 3 files changed, 28 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 31791c557c8f8..cbbad496cfc63 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -1930,9 +1930,10 @@ enum dc_status dc_commit_streams(struct dc *dc, + struct dc_stream_state *streams[], + uint8_t stream_count) + { +- int i; ++ int i, j; + struct dc_state *context; + enum dc_status res = DC_OK; ++ struct dc_validation_set set[MAX_STREAMS] = {0}; + + if (!streams_changed(dc, streams, stream_count)) + return res; +@@ -1941,8 +1942,17 @@ enum dc_status dc_commit_streams(struct dc *dc, + + for (i = 0; i < stream_count; i++) { + struct dc_stream_state *stream = streams[i]; ++ struct dc_stream_status *status = dc_stream_get_status(stream); + + dc_stream_log(dc, stream); ++ ++ set[i].stream = stream; ++ ++ if (status) { ++ set[i].plane_count = status->plane_count; ++ for (j = 0; j < status->plane_count; j++) ++ set[i].plane_states[j] = status->plane_states[j]; ++ } + } + + context = dc_create_state(dc); +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index 78b7dbd23a3b7..e2c5a68bbc807 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -1274,12 +1274,23 @@ void dc_post_update_surfaces_to_stream( + + #include "dc_stream.h" + +-/* +- * Structure to store surface/stream associations for validation ++/** ++ * struct dc_validation_set - Struct to store surface/stream associations for validation + */ + struct dc_validation_set { ++ /** ++ * @stream: Stream state properties ++ */ + struct dc_stream_state *stream; ++ ++ /** ++ * @plane_state: Surface state ++ */ + struct dc_plane_state *plane_states[MAX_SURFACES]; ++ ++ /** ++ * @plane_count: Total of active planes ++ */ + uint8_t plane_count; + }; + +diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h +index 9e6025c98db91..73dccd485895d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h +@@ -41,6 +41,10 @@ struct timing_sync_info { + struct dc_stream_status { + int primary_otg_inst; + int stream_enc_inst; ++ ++ /** ++ * @plane_count: Total of planes attached to a single stream ++ */ + int plane_count; + int audio_inst; + struct timing_sync_info timing_sync_info; +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-prevent-vtotal-from-being-set-to-0.patch b/queue-6.1/drm-amd-display-prevent-vtotal-from-being-set-to-0.patch new file mode 100644 index 00000000000..b0afe47b1b0 --- /dev/null +++ b/queue-6.1/drm-amd-display-prevent-vtotal-from-being-set-to-0.patch @@ -0,0 +1,51 @@ +From bb47b85a5460e6ccf91865c40d3a70501b375b67 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Jun 2023 08:11:48 -0400 +Subject: drm/amd/display: Prevent vtotal from being set to 0 + +From: Daniel Miess + +[ Upstream commit 2a9482e55968ed7368afaa9c2133404069117320 ] + +[Why] +In dcn314 DML the destination pipe vtotal was being set +to the crtc adjustment vtotal_min value even in cases +where that value is 0. + +[How] +Only set vtotal to the crtc adjustment vtotal_min value +in cases where the value is non-zero. + +Cc: Mario Limonciello +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Reviewed-by: Nicholas Kazlauskas +Acked-by: Alan Liu +Signed-off-by: Daniel Miess +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +index a2a32cb9d5710..8a88605827a84 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +@@ -302,7 +302,11 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c + pipe = &res_ctx->pipe_ctx[i]; + timing = &pipe->stream->timing; + +- pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min; ++ if (pipe->stream->adjust.v_total_min != 0) ++ pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min; ++ else ++ pipes[pipe_cnt].pipe.dest.vtotal = timing->v_total; ++ + pipes[pipe_cnt].pipe.dest.vblank_nom = timing->v_total - pipes[pipe_cnt].pipe.dest.vactive; + pipes[pipe_cnt].pipe.dest.vblank_nom = min(pipes[pipe_cnt].pipe.dest.vblank_nom, dcn3_14_ip.VBlankNomDefaultUS); + pipes[pipe_cnt].pipe.dest.vblank_nom = max(pipes[pipe_cnt].pipe.dest.vblank_nom, timing->v_sync_width); +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-rework-comments-on-dc-file.patch b/queue-6.1/drm-amd-display-rework-comments-on-dc-file.patch new file mode 100644 index 00000000000..dbf03727631 --- /dev/null +++ b/queue-6.1/drm-amd-display-rework-comments-on-dc-file.patch @@ -0,0 +1,377 @@ +From bfaa2af68d7ac9bc043db1c7088c445b69687b85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 16:27:59 -0400 +Subject: drm/amd/display: Rework comments on dc file + +From: Rodrigo Siqueira + +[ Upstream commit e366f36958f60c431a7430c8c421c9db0ec6738d ] + +The file dc.c has multiple comments that do not follow the kernel-doc or +are made in a distracting way. This commit alleviates part of this issue +by reorganizing some comments inside the dc file. + +Signed-off-by: Rodrigo Siqueira +Reviewed-by: Hamza Mahfooz +Signed-off-by: Alex Deucher +Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 161 +++++++++-------------- + drivers/gpu/drm/amd/display/dc/dc.h | 32 ++--- + 2 files changed, 70 insertions(+), 123 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 629bc53f61877..85ed1c7cdeaa9 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -135,9 +135,7 @@ static const char DC_BUILD_ID[] = "production-build"; + * one or two (in the pipe-split case). + */ + +-/******************************************************************************* +- * Private functions +- ******************************************************************************/ ++/* Private functions */ + + static inline void elevate_update_type(enum surface_update_type *original, enum surface_update_type new) + { +@@ -429,18 +427,14 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, + } + + /** +- ***************************************************************************** +- * Function: dc_stream_get_last_vrr_vtotal ++ * dc_stream_get_last_used_drr_vtotal - dc_stream_get_last_vrr_vtotal + * +- * @brief +- * Looks up the pipe context of dc_stream_state and gets the +- * last VTOTAL used by DRR (Dynamic Refresh Rate) ++ * @dc: [in] dc reference ++ * @stream: [in] Initial dc stream state ++ * @adjust: [in] Updated parameters for vertical_total_min and + * +- * @param [in] dc: dc reference +- * @param [in] stream: Initial dc stream state +- * @param [in] adjust: Updated parameters for vertical_total_min and +- * vertical_total_max +- ***************************************************************************** ++ * Looks up the pipe context of dc_stream_state and gets the last VTOTAL used ++ * by DRR (Dynamic Refresh Rate) + */ + bool dc_stream_get_last_used_drr_vtotal(struct dc *dc, + struct dc_stream_state *stream, +@@ -1236,9 +1230,7 @@ static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context) + PERF_TRACE(); + } + +-/******************************************************************************* +- * Public functions +- ******************************************************************************/ ++/* Public functions */ + + struct dc *dc_create(const struct dc_init_data *init_params) + { +@@ -4560,21 +4552,17 @@ void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc) + dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down = true; + } + +-/* +- ***************************************************************************** +- * Function: dc_is_dmub_outbox_supported - ++/** ++ * dc_is_dmub_outbox_supported - Check if DMUB firmware support outbox notification + * +- * @brief +- * Checks whether DMUB FW supports outbox notifications, if supported +- * DM should register outbox interrupt prior to actually enabling interrupts +- * via dc_enable_dmub_outbox ++ * @dc: [in] dc structure + * +- * @param +- * [in] dc: dc structure ++ * Checks whether DMUB FW supports outbox notifications, if supported DM ++ * should register outbox interrupt prior to actually enabling interrupts ++ * via dc_enable_dmub_outbox + * +- * @return +- * True if DMUB FW supports outbox notifications, False otherwise +- ***************************************************************************** ++ * Return: ++ * True if DMUB FW supports outbox notifications, False otherwise + */ + bool dc_is_dmub_outbox_supported(struct dc *dc) + { +@@ -4592,21 +4580,17 @@ bool dc_is_dmub_outbox_supported(struct dc *dc) + return dc->debug.enable_dmub_aux_for_legacy_ddc; + } + +-/* +- ***************************************************************************** +- * Function: dc_enable_dmub_notifications ++/** ++ * dc_enable_dmub_notifications - Check if dmub fw supports outbox + * +- * @brief +- * Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox +- * notifications. All DMs shall switch to dc_is_dmub_outbox_supported. +- * This API shall be removed after switching. ++ * @dc: [in] dc structure + * +- * @param +- * [in] dc: dc structure ++ * Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox ++ * notifications. All DMs shall switch to dc_is_dmub_outbox_supported. This ++ * API shall be removed after switching. + * +- * @return +- * True if DMUB FW supports outbox notifications, False otherwise +- ***************************************************************************** ++ * Return: ++ * True if DMUB FW supports outbox notifications, False otherwise + */ + bool dc_enable_dmub_notifications(struct dc *dc) + { +@@ -4614,18 +4598,11 @@ bool dc_enable_dmub_notifications(struct dc *dc) + } + + /** +- ***************************************************************************** +- * Function: dc_enable_dmub_outbox ++ * dc_enable_dmub_outbox - Enables DMUB unsolicited notification + * +- * @brief +- * Enables DMUB unsolicited notifications to x86 via outbox ++ * dc: [in] dc structure + * +- * @param +- * [in] dc: dc structure +- * +- * @return +- * None +- ***************************************************************************** ++ * Enables DMUB unsolicited notifications to x86 via outbox. + */ + void dc_enable_dmub_outbox(struct dc *dc) + { +@@ -4726,21 +4703,17 @@ uint8_t get_link_index_from_dpia_port_index(const struct dc *dc, + } + + /** +- ***************************************************************************** +- * Function: dc_process_dmub_set_config_async ++ * dc_process_dmub_set_config_async - Submits set_config command + * +- * @brief +- * Submits set_config command to dmub via inbox message ++ * @dc: [in] dc structure ++ * @link_index: [in] link_index: link index ++ * @payload: [in] aux payload ++ * @notify: [out] set_config immediate reply + * +- * @param +- * [in] dc: dc structure +- * [in] link_index: link index +- * [in] payload: aux payload +- * [out] notify: set_config immediate reply ++ * Submits set_config command to dmub via inbox message. + * +- * @return +- * True if successful, False if failure +- ***************************************************************************** ++ * Return: ++ * True if successful, False if failure + */ + bool dc_process_dmub_set_config_async(struct dc *dc, + uint32_t link_index, +@@ -4776,21 +4749,17 @@ bool dc_process_dmub_set_config_async(struct dc *dc, + } + + /** +- ***************************************************************************** +- * Function: dc_process_dmub_set_mst_slots ++ * dc_process_dmub_set_mst_slots - Submits MST solt allocation + * +- * @brief +- * Submits mst slot allocation command to dmub via inbox message ++ * @dc: [in] dc structure ++ * @link_index: [in] link index ++ * @mst_alloc_slots: [in] mst slots to be allotted ++ * @mst_slots_in_use: [out] mst slots in use returned in failure case + * +- * @param +- * [in] dc: dc structure +- * [in] link_index: link index +- * [in] mst_alloc_slots: mst slots to be allotted +- * [out] mst_slots_in_use: mst slots in use returned in failure case ++ * Submits mst slot allocation command to dmub via inbox message + * +- * @return +- * DC_OK if successful, DC_ERROR if failure +- ***************************************************************************** ++ * Return: ++ * DC_OK if successful, DC_ERROR if failure + */ + enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, + uint32_t link_index, +@@ -4830,19 +4799,12 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, + } + + /** +- ***************************************************************************** +- * Function: dc_process_dmub_dpia_hpd_int_enable +- * +- * @brief +- * Submits dpia hpd int enable command to dmub via inbox message ++ * dc_process_dmub_dpia_hpd_int_enable - Submits DPIA DPD interruption + * +- * @param +- * [in] dc: dc structure +- * [in] hpd_int_enable: 1 for hpd int enable, 0 to disable ++ * @dc [in]: dc structure ++ * @hpd_int_enable [in]: 1 for hpd int enable, 0 to disable + * +- * @return +- * None +- ***************************************************************************** ++ * Submits dpia hpd int enable command to dmub via inbox message + */ + void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc, + uint32_t hpd_int_enable) +@@ -4871,16 +4833,13 @@ void dc_disable_accelerated_mode(struct dc *dc) + + + /** +- ***************************************************************************** +- * dc_notify_vsync_int_state() - notifies vsync enable/disable state ++ * dc_notify_vsync_int_state - notifies vsync enable/disable state + * @dc: dc structure +- * @stream: stream where vsync int state changed +- * @enable: whether vsync is enabled or disabled ++ * @stream: stream where vsync int state changed ++ * @enable: whether vsync is enabled or disabled + * +- * Called when vsync is enabled/disabled +- * Will notify DMUB to start/stop ABM interrupts after steady state is reached +- * +- ***************************************************************************** ++ * Called when vsync is enabled/disabled Will notify DMUB to start/stop ABM ++ * interrupts after steady state is reached. + */ + void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable) + { +@@ -4922,14 +4881,18 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo + if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause) + pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst); + } +-/* +- * dc_extended_blank_supported: Decide whether extended blank is supported ++ ++/** ++ * dc_extended_blank_supported 0 Decide whether extended blank is supported + * +- * Extended blank is a freesync optimization feature to be enabled in the future. +- * During the extra vblank period gained from freesync, we have the ability to enter z9/z10. ++ * @dc: [in] Current DC state + * +- * @param [in] dc: Current DC state +- * @return: Indicate whether extended blank is supported (true or false) ++ * Extended blank is a freesync optimization feature to be enabled in the ++ * future. During the extra vblank period gained from freesync, we have the ++ * ability to enter z9/z10. ++ * ++ * Return: ++ * Indicate whether extended blank is supported (true or false) + */ + bool dc_extended_blank_supported(struct dc *dc) + { +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index e2c5a68bbc807..178d410183631 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -56,9 +56,7 @@ struct dmub_notification; + #define MIN_VIEWPORT_SIZE 12 + #define MAX_NUM_EDP 2 + +-/******************************************************************************* +- * Display Core Interfaces +- ******************************************************************************/ ++/* Display Core Interfaces */ + struct dc_versions { + const char *dc_ver; + struct dmcu_version dmcu_version; +@@ -993,9 +991,7 @@ void dc_init_callbacks(struct dc *dc, + void dc_deinit_callbacks(struct dc *dc); + void dc_destroy(struct dc **dc); + +-/******************************************************************************* +- * Surface Interfaces +- ******************************************************************************/ ++/* Surface Interfaces */ + + enum { + TRANSFER_FUNC_POINTS = 1025 +@@ -1350,9 +1346,7 @@ struct dc_state *dc_copy_state(struct dc_state *src_ctx); + void dc_retain_state(struct dc_state *context); + void dc_release_state(struct dc_state *context); + +-/******************************************************************************* +- * Link Interfaces +- ******************************************************************************/ ++/* Link Interfaces */ + + struct dpcd_caps { + union dpcd_rev dpcd_rev; +@@ -1454,9 +1448,7 @@ struct hdcp_caps { + + uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane); + +-/******************************************************************************* +- * Sink Interfaces - A sink corresponds to a display output device +- ******************************************************************************/ ++/* Sink Interfaces - A sink corresponds to a display output device */ + + struct dc_container_id { + // 128bit GUID in binary form +@@ -1539,9 +1531,7 @@ struct dc_cursor { + }; + + +-/******************************************************************************* +- * Interrupt interfaces +- ******************************************************************************/ ++/* Interrupt interfaces */ + enum dc_irq_source dc_interrupt_to_irq_source( + struct dc *dc, + uint32_t src_id, +@@ -1553,9 +1543,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index( + + void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable); + +-/******************************************************************************* +- * Power Interfaces +- ******************************************************************************/ ++/* Power Interfaces */ + + void dc_set_power_state( + struct dc *dc, +@@ -1628,14 +1616,10 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, + void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc, + uint32_t hpd_int_enable); + +-/******************************************************************************* +- * DSC Interfaces +- ******************************************************************************/ ++/* DSC Interfaces */ + #include "dc_dsc.h" + +-/******************************************************************************* +- * Disable acc mode Interfaces +- ******************************************************************************/ ++/* Disable acc mode Interfaces */ + void dc_disable_accelerated_mode(struct dc *dc); + + #endif /* DC_INTERFACE_H_ */ +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-rework-context-change-check.patch b/queue-6.1/drm-amd-display-rework-context-change-check.patch new file mode 100644 index 00000000000..d95b93de7c2 --- /dev/null +++ b/queue-6.1/drm-amd-display-rework-context-change-check.patch @@ -0,0 +1,67 @@ +From 4a51f0b34a3f301fcecc041a7c308bc9c8f8c226 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 08:28:16 -0400 +Subject: drm/amd/display: Rework context change check + +From: Rodrigo Siqueira + +[ Upstream commit 10fdb0a11c555e0d6f7698d2874581d06e99ee71 ] + +Context change is all about streams; for this reason, this commit +renames context_changed to streams_changed. Additionally, to make this +function more flexible, this commit changes the function signature to +receive the stream array and the stream count as a parameter. + +Reviewed-by: Harry Wentland +Signed-off-by: Rodrigo Siqueira +Co-developed-by: Aurabindo Pillai +Signed-off-by: Aurabindo Pillai +Signed-off-by: Alex Deucher +Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index beb2d7f103c58..226c17e78d3e1 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -1505,19 +1505,19 @@ static void program_timing_sync( + } + } + +-static bool context_changed( +- struct dc *dc, +- struct dc_state *context) ++static bool streams_changed(struct dc *dc, ++ struct dc_stream_state *streams[], ++ uint8_t stream_count) + { + uint8_t i; + +- if (context->stream_count != dc->current_state->stream_count) ++ if (stream_count != dc->current_state->stream_count) + return true; + + for (i = 0; i < dc->current_state->stream_count; i++) { +- if (dc->current_state->streams[i] != context->streams[i]) ++ if (dc->current_state->streams[i] != streams[i]) + return true; +- if (!context->streams[i]->link->link_state_valid) ++ if (!streams[i]->link->link_state_valid) + return true; + } + +@@ -1918,7 +1918,7 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context) + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + +- if (!context_changed(dc, context)) ++ if (!streams_changed(dc, context->streams, context->stream_count)) + return DC_OK; + + DC_LOG_DC("%s: %d streams\n", +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch b/queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch new file mode 100644 index 00000000000..5e28fca4041 --- /dev/null +++ b/queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch @@ -0,0 +1,153 @@ +From a771acaa89c3903963de8496fa1c50e7a9f0e815 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Jun 2023 10:05:20 -0500 +Subject: drm/amd/display: Set minimum requirement for using PSR-SU on + Rembrandt + +From: Mario Limonciello + +[ Upstream commit c35b6ea8f2ecfa9d775530b70d4e727869099a9c ] + +A number of parade TCONs are causing system hangs when utilized with +older DMUB firmware and PSR-SU. Some changes have been introduced into +DMUB firmware to add resilience against these failures. + +Don't allow running PSR-SU unless on the newer firmware. + +Cc: stable@vger.kernel.org +Cc: Sean Wang +Cc: Marc Rossi +Cc: Hamza Mahfooz +Cc: Tsung-hua (Ryan) Lin +Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2443 +Signed-off-by: Mario Limonciello +Reviewed-by: Leo Li +Signed-off-by: Alex Deucher +Stable-dep-of: cd2e31a9ab93 ("drm/amd/display: Set minimum requirement for using PSR-SU on Phoenix") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c | 3 ++- + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 7 +++++++ + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 1 + + drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 ++ + drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 5 +++++ + drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h | 2 ++ + drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 10 ++++++---- + 7 files changed, 25 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +index 872d06fe14364..3eb8794807d2b 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +@@ -24,6 +24,7 @@ + */ + + #include "amdgpu_dm_psr.h" ++#include "dc_dmub_srv.h" + #include "dc.h" + #include "dm_helpers.h" + #include "amdgpu_dm.h" +@@ -50,7 +51,7 @@ static bool link_supports_psrsu(struct dc_link *link) + !link->dpcd_caps.psr_info.psr2_su_y_granularity_cap) + return false; + +- return true; ++ return dc_dmub_check_min_version(dc->ctx->dmub_srv->dmub); + } + + /* +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +index a461e9463534b..31bb7e782c6b1 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +@@ -1026,3 +1026,10 @@ void dc_send_update_cursor_info_to_dmu( + dc_send_cmd_to_dmu(pCtx->stream->ctx->dmub_srv, &cmd); + } + } ++ ++bool dc_dmub_check_min_version(struct dmub_srv *srv) ++{ ++ if (!srv->hw_funcs.is_psrsu_supported) ++ return true; ++ return srv->hw_funcs.is_psrsu_supported(srv); ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +index d34f5563df2ec..9a248ced03b9c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +@@ -89,4 +89,5 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc, struct dc_state *context, b + void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv); + + void dc_send_update_cursor_info_to_dmu(struct pipe_ctx *pCtx, uint8_t pipe_idx); ++bool dc_dmub_check_min_version(struct dmub_srv *srv); + #endif /* _DMUB_DC_SRV_H_ */ +diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +index b53468aca4a9b..5f17b252e9be4 100644 +--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h ++++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +@@ -350,6 +350,8 @@ struct dmub_srv_hw_funcs { + + bool (*is_supported)(struct dmub_srv *dmub); + ++ bool (*is_psrsu_supported)(struct dmub_srv *dmub); ++ + bool (*is_hw_init)(struct dmub_srv *dmub); + + bool (*is_phy_init)(struct dmub_srv *dmub); +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +index c90b9ee42e126..89d24fb7024e2 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +@@ -297,6 +297,11 @@ bool dmub_dcn31_is_supported(struct dmub_srv *dmub) + return supported; + } + ++bool dmub_dcn31_is_psrsu_supported(struct dmub_srv *dmub) ++{ ++ return dmub->fw_version >= DMUB_FW_VERSION(4, 0, 59); ++} ++ + void dmub_dcn31_set_gpint(struct dmub_srv *dmub, + union dmub_gpint_data_register reg) + { +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h +index f6db6f89d45dc..eb62410941473 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h +@@ -219,6 +219,8 @@ bool dmub_dcn31_is_hw_init(struct dmub_srv *dmub); + + bool dmub_dcn31_is_supported(struct dmub_srv *dmub); + ++bool dmub_dcn31_is_psrsu_supported(struct dmub_srv *dmub); ++ + void dmub_dcn31_set_gpint(struct dmub_srv *dmub, + union dmub_gpint_data_register reg); + +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +index 6d76ce327d69f..0f43a05a41874 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +@@ -227,14 +227,16 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) + case DMUB_ASIC_DCN314: + case DMUB_ASIC_DCN315: + case DMUB_ASIC_DCN316: +- if (asic == DMUB_ASIC_DCN314) ++ if (asic == DMUB_ASIC_DCN314) { + dmub->regs_dcn31 = &dmub_srv_dcn314_regs; +- else if (asic == DMUB_ASIC_DCN315) ++ } else if (asic == DMUB_ASIC_DCN315) { + dmub->regs_dcn31 = &dmub_srv_dcn315_regs; +- else if (asic == DMUB_ASIC_DCN316) ++ } else if (asic == DMUB_ASIC_DCN316) { + dmub->regs_dcn31 = &dmub_srv_dcn316_regs; +- else ++ } else { + dmub->regs_dcn31 = &dmub_srv_dcn31_regs; ++ funcs->is_psrsu_supported = dmub_dcn31_is_psrsu_supported; ++ } + funcs->reset = dmub_dcn31_reset; + funcs->reset_release = dmub_dcn31_reset_release; + funcs->backdoor_load = dmub_dcn31_backdoor_load; +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch-26244 b/queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch-26244 new file mode 100644 index 00000000000..02f2335ce01 --- /dev/null +++ b/queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch-26244 @@ -0,0 +1,68 @@ +From 58736d0e0fc2ab8a19aa9226d60baed3d196390c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Jun 2023 10:05:21 -0500 +Subject: drm/amd/display: Set minimum requirement for using PSR-SU on Phoenix + +From: Mario Limonciello + +[ Upstream commit cd2e31a9ab93d13c412a36c6e26811e0f830985b ] + +The same parade TCON issue can potentially happen on Phoenix, and the same +PSR resilience changes have been ported into the DMUB firmware. + +Don't allow running PSR-SU unless on the newer firmware. + +Cc: stable@vger.kernel.org +Cc: Sean Wang +Cc: Marc Rossi +Cc: Hamza Mahfooz +Cc: Tsung-hua (Ryan) Lin +Signed-off-by: Mario Limonciello +Reviewed-by: Leo Li +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c | 5 +++++ + drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h | 2 ++ + drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 1 + + 3 files changed, 8 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c +index 48a06dbd9be78..f161aeb7e7c4a 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c +@@ -60,3 +60,8 @@ const struct dmub_srv_dcn31_regs dmub_srv_dcn314_regs = { + { DMUB_DCN31_FIELDS() }, + #undef DMUB_SF + }; ++ ++bool dmub_dcn314_is_psrsu_supported(struct dmub_srv *dmub) ++{ ++ return dmub->fw_version >= DMUB_FW_VERSION(8, 0, 16); ++} +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h +index 674267a2940e9..f213bd82c9110 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h +@@ -30,4 +30,6 @@ + + extern const struct dmub_srv_dcn31_regs dmub_srv_dcn314_regs; + ++bool dmub_dcn314_is_psrsu_supported(struct dmub_srv *dmub); ++ + #endif /* _DMUB_DCN314_H_ */ +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +index 0f43a05a41874..0dab22d794808 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +@@ -229,6 +229,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) + case DMUB_ASIC_DCN316: + if (asic == DMUB_ASIC_DCN314) { + dmub->regs_dcn31 = &dmub_srv_dcn314_regs; ++ funcs->is_psrsu_supported = dmub_dcn314_is_psrsu_supported; + } else if (asic == DMUB_ASIC_DCN315) { + dmub->regs_dcn31 = &dmub_srv_dcn315_regs; + } else if (asic == DMUB_ASIC_DCN316) { +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-update-correct-dcn314-register-heade.patch b/queue-6.1/drm-amd-display-update-correct-dcn314-register-heade.patch new file mode 100644 index 00000000000..4984b49b866 --- /dev/null +++ b/queue-6.1/drm-amd-display-update-correct-dcn314-register-heade.patch @@ -0,0 +1,177 @@ +From 72339513bf1743628f689083a07a1be7f34f027c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 May 2023 23:33:46 +0800 +Subject: drm/amd/display: Update correct DCN314 register header + +From: Cruise Hung + +[ Upstream commit 268182606f26434c5d3ebd0e86efcb0418dec487 ] + +[Why] +The register header for DCN314 is not correct. + +[How] +Update correct DCN314 register header. + +Reviewed-by: Nicholas Kazlauskas +Acked-by: Tom Chung +Signed-off-by: Cruise Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: cd2e31a9ab93 ("drm/amd/display: Set minimum requirement for using PSR-SU on Phoenix") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dmub/src/Makefile | 2 +- + .../drm/amd/display/dmub/src/dmub_dcn314.c | 62 +++++++++++++++++++ + .../drm/amd/display/dmub/src/dmub_dcn314.h | 33 ++++++++++ + .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 5 +- + 4 files changed, 100 insertions(+), 2 deletions(-) + create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c + create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h + +diff --git a/drivers/gpu/drm/amd/display/dmub/src/Makefile b/drivers/gpu/drm/amd/display/dmub/src/Makefile +index 0589ad4778eea..caf095aca8f3f 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/Makefile ++++ b/drivers/gpu/drm/amd/display/dmub/src/Makefile +@@ -22,7 +22,7 @@ + + DMUB = dmub_srv.o dmub_srv_stat.o dmub_reg.o dmub_dcn20.o dmub_dcn21.o + DMUB += dmub_dcn30.o dmub_dcn301.o dmub_dcn302.o dmub_dcn303.o +-DMUB += dmub_dcn31.o dmub_dcn315.o dmub_dcn316.o ++DMUB += dmub_dcn31.o dmub_dcn314.o dmub_dcn315.o dmub_dcn316.o + DMUB += dmub_dcn32.o + + AMD_DAL_DMUB = $(addprefix $(AMDDALPATH)/dmub/src/,$(DMUB)) +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c +new file mode 100644 +index 0000000000000..48a06dbd9be78 +--- /dev/null ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c +@@ -0,0 +1,62 @@ ++/* ++ * Copyright 2021 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: AMD ++ * ++ */ ++ ++#include "../dmub_srv.h" ++#include "dmub_reg.h" ++#include "dmub_dcn314.h" ++ ++#include "dcn/dcn_3_1_4_offset.h" ++#include "dcn/dcn_3_1_4_sh_mask.h" ++ ++#define DCN_BASE__INST0_SEG0 0x00000012 ++#define DCN_BASE__INST0_SEG1 0x000000C0 ++#define DCN_BASE__INST0_SEG2 0x000034C0 ++#define DCN_BASE__INST0_SEG3 0x00009000 ++#define DCN_BASE__INST0_SEG4 0x02403C00 ++#define DCN_BASE__INST0_SEG5 0 ++ ++#define BASE_INNER(seg) DCN_BASE__INST0_SEG##seg ++#define CTX dmub ++#define REGS dmub->regs_dcn31 ++#define REG_OFFSET_EXP(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name) ++ ++/* Registers. */ ++ ++const struct dmub_srv_dcn31_regs dmub_srv_dcn314_regs = { ++#define DMUB_SR(reg) REG_OFFSET_EXP(reg), ++ { ++ DMUB_DCN31_REGS() ++ DMCUB_INTERNAL_REGS() ++ }, ++#undef DMUB_SR ++ ++#define DMUB_SF(reg, field) FD_MASK(reg, field), ++ { DMUB_DCN31_FIELDS() }, ++#undef DMUB_SF ++ ++#define DMUB_SF(reg, field) FD_SHIFT(reg, field), ++ { DMUB_DCN31_FIELDS() }, ++#undef DMUB_SF ++}; +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h +new file mode 100644 +index 0000000000000..674267a2940e9 +--- /dev/null ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright 2021 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: AMD ++ * ++ */ ++ ++#ifndef _DMUB_DCN314_H_ ++#define _DMUB_DCN314_H_ ++ ++#include "dmub_dcn31.h" ++ ++extern const struct dmub_srv_dcn31_regs dmub_srv_dcn314_regs; ++ ++#endif /* _DMUB_DCN314_H_ */ +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +index 92c18bfb98b3b..6d76ce327d69f 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +@@ -32,6 +32,7 @@ + #include "dmub_dcn302.h" + #include "dmub_dcn303.h" + #include "dmub_dcn31.h" ++#include "dmub_dcn314.h" + #include "dmub_dcn315.h" + #include "dmub_dcn316.h" + #include "dmub_dcn32.h" +@@ -226,7 +227,9 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) + case DMUB_ASIC_DCN314: + case DMUB_ASIC_DCN315: + case DMUB_ASIC_DCN316: +- if (asic == DMUB_ASIC_DCN315) ++ if (asic == DMUB_ASIC_DCN314) ++ dmub->regs_dcn31 = &dmub_srv_dcn314_regs; ++ else if (asic == DMUB_ASIC_DCN315) + dmub->regs_dcn31 = &dmub_srv_dcn315_regs; + else if (asic == DMUB_ASIC_DCN316) + dmub->regs_dcn31 = &dmub_srv_dcn316_regs; +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-update-extended-blank-for-dcn314-onw.patch b/queue-6.1/drm-amd-display-update-extended-blank-for-dcn314-onw.patch new file mode 100644 index 00000000000..888c2b0a566 --- /dev/null +++ b/queue-6.1/drm-amd-display-update-extended-blank-for-dcn314-onw.patch @@ -0,0 +1,288 @@ +From 1b07b3413ad27cefd26944b1ca1663f8286cdbdc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Apr 2023 17:03:06 -0400 +Subject: drm/amd/display: update extended blank for dcn314 onwards + +From: Gabe Teeger + +[ Upstream commit 469a62938a45ef382c9cb7b9fec6c6c1fcd781c0 ] + +[Why] +Flickering and underflow was observed when testing extended +blank on dcn314. + +[What] +Vstartup is contrainted by vblank_nom, so adjusting it to include +non-adjusted vtotal in its calculation during freesync video +means that Vstartup is not changed when vtotal changes. +This fixed the flickering + underflow. + +dc_extended_blank_supported function was removed +because extended blank is only relevant to when +zstate is supported. The increased vtotal during +freesync can be passed to dml regardless of whether +extended blank is supported or not, so this function is +not needed. + +Updates were made recently in dml to the calculation of +min_dst_y_next_start. Dml input for dcn314 will now +always use the newer calculation for min_dst_y_next_start. +Dml input for older dcn versions remains untouched. + +The variable optimized_min_dst_y_next_start +is replaced everywhere with min_dst_y_next_start, +and the updated dml allows min_dst_y_next_start to +increase to an optimized value during freesync video, +then return to default when freesync is disengaged. + +Also removed registry key for controlling +extended blank feature. + +Tested-by: Daniel Wheeler +Reviewed-by: Nicholas Kazlauskas +Acked-by: Rodrigo Siqueira +Signed-off-by: Gabe Teeger +Signed-off-by: Alex Deucher +Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 21 ----------------- + drivers/gpu/drm/amd/display/dc/dc.h | 2 -- + .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 4 ++-- + .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 23 +++++++++---------- + .../dc/dml/dcn31/display_rq_dlg_calc_31.c | 3 +-- + .../amd/display/dc/dml/dcn314/dcn314_fpu.c | 14 +++++++---- + .../dc/dml/dcn314/display_rq_dlg_calc_314.c | 16 ++++--------- + .../amd/display/dc/dml/display_mode_structs.h | 3 +-- + 8 files changed, 29 insertions(+), 57 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 27cec123cb06f..8f9c60ed6f8b8 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -2594,9 +2594,6 @@ static enum surface_update_type check_update_surfaces_for_stream( + stream_update->vrr_active_variable)) + su_flags->bits.fams_changed = 1; + +- if (stream_update->crtc_timing_adjust && dc_extended_blank_supported(dc)) +- su_flags->bits.crtc_timing_adjust = 1; +- + if (su_flags->raw != 0) + overall_type = UPDATE_TYPE_FULL; + +@@ -4897,21 +4894,3 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo + if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause) + pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst); + } +- +-/** +- * dc_extended_blank_supported - Decide whether extended blank is supported +- * +- * @dc: [in] Current DC state +- * +- * Extended blank is a freesync optimization feature to be enabled in the +- * future. During the extra vblank period gained from freesync, we have the +- * ability to enter z9/z10. +- * +- * Return: +- * Indicate whether extended blank is supported (%true or %false) +- */ +-bool dc_extended_blank_supported(struct dc *dc) +-{ +- return dc->debug.extended_blank_optimization && !dc->debug.disable_z10 +- && dc->caps.zstate_support && dc->caps.is_apu; +-} +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index 178d410183631..6409b8d8ff71e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -1520,8 +1520,6 @@ struct dc_sink_init_data { + bool converter_disable_audio; + }; + +-bool dc_extended_blank_supported(struct dc *dc); +- + struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); + + /* Newer interfaces */ +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +index 622efa556e7ad..4ef632864948e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +@@ -2036,7 +2036,7 @@ void dcn20_optimize_bandwidth( + dc->clk_mgr, + context, + true); +- if (dc_extended_blank_supported(dc) && context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) { ++ if (context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) { + for (i = 0; i < dc->res_pool->pipe_count; ++i) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + +@@ -2044,7 +2044,7 @@ void dcn20_optimize_bandwidth( + && pipe_ctx->stream->adjust.v_total_min == pipe_ctx->stream->adjust.v_total_max + && pipe_ctx->stream->adjust.v_total_max > pipe_ctx->stream->timing.v_total) + pipe_ctx->plane_res.hubp->funcs->program_extended_blank(pipe_ctx->plane_res.hubp, +- pipe_ctx->dlg_regs.optimized_min_dst_y_next_start); ++ pipe_ctx->dlg_regs.min_dst_y_next_start); + } + } + } +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +index 186538e3e3c0c..dbe5d2efa4a30 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +@@ -948,10 +948,10 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc + { + int plane_count; + int i; +- unsigned int optimized_min_dst_y_next_start_us; ++ unsigned int min_dst_y_next_start_us; + + plane_count = 0; +- optimized_min_dst_y_next_start_us = 0; ++ min_dst_y_next_start_us = 0; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].plane_state) + plane_count++; +@@ -973,19 +973,18 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc + else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { + struct dc_link *link = context->streams[0]->sink->link; + struct dc_stream_status *stream_status = &context->stream_status[0]; ++ struct dc_stream_state *current_stream = context->streams[0]; + int minmum_z8_residency = dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000; + bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency; + bool is_pwrseq0 = link->link_index == 0; ++ bool isFreesyncVideo; + +- if (dc_extended_blank_supported(dc)) { +- for (i = 0; i < dc->res_pool->pipe_count; i++) { +- if (context->res_ctx.pipe_ctx[i].stream == context->streams[0] +- && context->res_ctx.pipe_ctx[i].stream->adjust.v_total_min == context->res_ctx.pipe_ctx[i].stream->adjust.v_total_max +- && context->res_ctx.pipe_ctx[i].stream->adjust.v_total_min > context->res_ctx.pipe_ctx[i].stream->timing.v_total) { +- optimized_min_dst_y_next_start_us = +- context->res_ctx.pipe_ctx[i].dlg_regs.optimized_min_dst_y_next_start_us; +- break; +- } ++ isFreesyncVideo = current_stream->adjust.v_total_min == current_stream->adjust.v_total_max; ++ isFreesyncVideo = isFreesyncVideo && current_stream->timing.v_total < current_stream->adjust.v_total_min; ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ if (context->res_ctx.pipe_ctx[i].stream == current_stream && isFreesyncVideo) { ++ min_dst_y_next_start_us = context->res_ctx.pipe_ctx[i].dlg_regs.min_dst_y_next_start_us; ++ break; + } + } + +@@ -993,7 +992,7 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc + if (stream_status->plane_count > 1) + return DCN_ZSTATE_SUPPORT_DISALLOW; + +- if (is_pwrseq0 && (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || optimized_min_dst_y_next_start_us > 5000)) ++ if (is_pwrseq0 && (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || min_dst_y_next_start_us > 5000)) + return DCN_ZSTATE_SUPPORT_ALLOW; + else if (is_pwrseq0 && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr) + return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +index 35d10b4d018bf..d7ee26b62a5eb 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +@@ -988,8 +988,7 @@ static void dml_rq_dlg_get_dlg_params( + + dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; + disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start) * dml_pow(2, 2)); +- disp_dlg_regs->optimized_min_dst_y_next_start_us = 0; +- disp_dlg_regs->optimized_min_dst_y_next_start = disp_dlg_regs->min_dst_y_next_start; ++ disp_dlg_regs->min_dst_y_next_start_us = 0; + ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int)dml_pow(2, 18)); + + dml_print("DML_DLG: %s: min_ttu_vblank (us) = %3.2f\n", __func__, min_ttu_vblank); +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +index bf77e56c3f3ef..395eed9f6b1be 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +@@ -288,6 +288,7 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *pipe; + bool upscaled = false; ++ bool isFreesyncVideo = false; + + dc_assert_fp_enabled(); + +@@ -301,9 +302,16 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c + pipe = &res_ctx->pipe_ctx[i]; + timing = &pipe->stream->timing; + +- if (dc_extended_blank_supported(dc) && pipe->stream->adjust.v_total_max == pipe->stream->adjust.v_total_min +- && pipe->stream->adjust.v_total_min > timing->v_total) ++ isFreesyncVideo = pipe->stream->adjust.v_total_max == pipe->stream->adjust.v_total_min; ++ isFreesyncVideo = isFreesyncVideo && pipe->stream->adjust.v_total_min > timing->v_total; ++ ++ if (!isFreesyncVideo) { ++ pipes[pipe_cnt].pipe.dest.vblank_nom = ++ dcn3_14_ip.VBlankNomDefaultUS / (timing->h_total / (timing->pix_clk_100hz / 10000.0)); ++ } else { + pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min; ++ pipes[pipe_cnt].pipe.dest.vblank_nom = timing->v_total - pipes[pipe_cnt].pipe.dest.vactive; ++ } + + if (pipe->plane_state && + (pipe->plane_state->src_rect.height < pipe->plane_state->dst_rect.height || +@@ -327,8 +335,6 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c + pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0; + pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0; + pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; +- pipes[pipe_cnt].pipe.dest.vblank_nom = +- dcn3_14_ip.VBlankNomDefaultUS / (timing->h_total / (timing->pix_clk_100hz / 10000.0)); + pipes[pipe_cnt].pipe.src.dcc_rate = 3; + pipes[pipe_cnt].dout.dsc_input_bpc = 0; + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c +index 61ee9ba063a78..26561c0f5fbb6 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c +@@ -1053,7 +1053,6 @@ static void dml_rq_dlg_get_dlg_params( + + float vba__refcyc_per_req_delivery_pre_l = get_refcyc_per_req_delivery_pre_l_in_us(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; // From VBA + float vba__refcyc_per_req_delivery_l = get_refcyc_per_req_delivery_l_in_us(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; // From VBA +- int blank_lines = 0; + + memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); + memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); +@@ -1077,17 +1076,10 @@ static void dml_rq_dlg_get_dlg_params( + min_ttu_vblank = get_min_ttu_vblank_in_us(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); // From VBA + + dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; +- disp_dlg_regs->optimized_min_dst_y_next_start = disp_dlg_regs->min_dst_y_next_start; +- disp_dlg_regs->optimized_min_dst_y_next_start_us = 0; +- disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start) * dml_pow(2, 2)); +- blank_lines = (dst->vblank_end + dst->vtotal_min - dst->vblank_start - dst->vstartup_start - 1); +- if (blank_lines < 0) +- blank_lines = 0; +- if (blank_lines != 0) { +- disp_dlg_regs->optimized_min_dst_y_next_start = vba__min_dst_y_next_start; +- disp_dlg_regs->optimized_min_dst_y_next_start_us = (disp_dlg_regs->optimized_min_dst_y_next_start * dst->hactive) / (unsigned int) dst->pixel_rate_mhz; +- disp_dlg_regs->min_dst_y_next_start = disp_dlg_regs->optimized_min_dst_y_next_start; +- } ++ disp_dlg_regs->min_dst_y_next_start_us = ++ (vba__min_dst_y_next_start * dst->hactive) / (unsigned int) dst->pixel_rate_mhz; ++ disp_dlg_regs->min_dst_y_next_start = vba__min_dst_y_next_start * dml_pow(2, 2); ++ + ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int)dml_pow(2, 18)); + + dml_print("DML_DLG: %s: min_ttu_vblank (us) = %3.2f\n", __func__, min_ttu_vblank); +diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +index 64d602e6412f1..6af0d5f469aeb 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +@@ -618,8 +618,7 @@ struct _vcs_dpi_display_dlg_regs_st { + unsigned int refcyc_h_blank_end; + unsigned int dlg_vblank_end; + unsigned int min_dst_y_next_start; +- unsigned int optimized_min_dst_y_next_start; +- unsigned int optimized_min_dst_y_next_start_us; ++ unsigned int min_dst_y_next_start_us; + unsigned int refcyc_per_htotal; + unsigned int refcyc_x_after_scaler; + unsigned int dst_y_after_scaler; +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-use-low-clocks-for-no-plane-configs.patch b/queue-6.1/drm-amd-display-use-low-clocks-for-no-plane-configs.patch new file mode 100644 index 00000000000..63038c4ff65 --- /dev/null +++ b/queue-6.1/drm-amd-display-use-low-clocks-for-no-plane-configs.patch @@ -0,0 +1,110 @@ +From f3958a879409f4e2a9259f1f533c59e2ce86c67c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Oct 2022 11:01:08 -0400 +Subject: drm/amd/display: use low clocks for no plane configs + +From: Dmytro Laktyushkin + +[ Upstream commit 2641c7b7808191cba25ba28b82bb73ca294924cc ] + +Stream only configurations do not require DCFCLK, SOCCLK, DPPCLK +or FCLK. They also always allow pstate change. + +Reviewed-by: Charlene Liu +Acked-by: Tom Chung +Signed-off-by: Dmytro Laktyushkin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 49f26218c344 ("drm/amd/display: fix dcn315 single stream crb allocation") +Signed-off-by: Sasha Levin +--- + .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.c | 18 ++++++++++++++---- + .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 14 +++++++++++++- + 2 files changed, 27 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +index 8e416433184cf..aa1c2917a4a1d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +@@ -483,7 +483,7 @@ void dcn31_calculate_wm_and_dlg_fp( + int pipe_cnt, + int vlevel) + { +- int i, pipe_idx, active_dpp_count = 0; ++ int i, pipe_idx, active_hubp_count = 0; + double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; + + dc_assert_fp_enabled(); +@@ -529,7 +529,7 @@ void dcn31_calculate_wm_and_dlg_fp( + continue; + + if (context->res_ctx.pipe_ctx[i].plane_state) +- active_dpp_count++; ++ active_hubp_count++; + + pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt); + pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); +@@ -547,9 +547,19 @@ void dcn31_calculate_wm_and_dlg_fp( + } + + dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); +- /* For 31x apu pstate change is only supported if possible in vactive or if there are no active dpps */ ++ /* For 31x apu pstate change is only supported if possible in vactive*/ + context->bw_ctx.bw.dcn.clk.p_state_change_support = +- context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_dram_clock_change_vactive || !active_dpp_count; ++ context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_dram_clock_change_vactive; ++ /* If DCN isn't making memory requests we can allow pstate change and lower clocks */ ++ if (!active_hubp_count) { ++ context->bw_ctx.bw.dcn.clk.socclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.dcfclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = 0; ++ context->bw_ctx.bw.dcn.clk.dramclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.fclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.p_state_change_support = true; ++ } + } + + void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +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 f28caece5f901..f88c80594bd7e 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 +@@ -1237,7 +1237,7 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, int vlevel) + { +- int i, pipe_idx; ++ int i, pipe_idx, active_hubp_count = 0; + bool usr_retraining_support = false; + bool unbounded_req_enabled = false; + +@@ -1282,6 +1282,8 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + if (!context->res_ctx.pipe_ctx[i].stream) + continue; ++ if (context->res_ctx.pipe_ctx[i].plane_state) ++ active_hubp_count++; + pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, + pipe_idx); + pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, +@@ -1307,6 +1309,16 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, + context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest; + pipe_idx++; + } ++ /* If DCN isn't making memory requests we can allow pstate change and lower clocks */ ++ if (!active_hubp_count) { ++ context->bw_ctx.bw.dcn.clk.socclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.dcfclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = 0; ++ context->bw_ctx.bw.dcn.clk.dramclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.fclk_khz = 0; ++ context->bw_ctx.bw.dcn.clk.p_state_change_support = true; ++ } + /*save a original dppclock copy*/ + context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz; + context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz; +-- +2.39.2 + diff --git a/queue-6.1/drm-amd-display-use-min-transition-for-all-subvp-pla.patch b/queue-6.1/drm-amd-display-use-min-transition-for-all-subvp-pla.patch new file mode 100644 index 00000000000..f14b4f60d7b --- /dev/null +++ b/queue-6.1/drm-amd-display-use-min-transition-for-all-subvp-pla.patch @@ -0,0 +1,96 @@ +From a34b055c769326a98ff7028954075429d314182a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 12:38:12 -0400 +Subject: drm/amd/display: Use min transition for all SubVP plane add/remove + +From: Alvin Lee + +[ Upstream commit e4c1b01bc35b04e15782608165aa85b9e1724f7b ] + +[Description] +- Whenever disabling a phantom pipe, we must run through the + minimal transition sequence +- In the case where SetVisibility = false for the main pipe, + we also need to run through the min transtion when disabling + the phantom pipes + +Reviewed-by: Jun Lei +Acked-by: Tom Chung +Signed-off-by: Alvin Lee +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 31 +++++++++++++++++------- + 1 file changed, 22 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index cbbad496cfc63..c429748c86cdb 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -3731,17 +3731,17 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, + } + } + +- /* For SubVP when adding MPO video we need to add a minimal transition. ++ /* For SubVP when adding or removing planes we need to add a minimal transition ++ * (even when disabling all planes). Whenever disabling a phantom pipe, we ++ * must use the minimal transition path to disable the pipe correctly. + */ + if (cur_stream_status && stream->mall_stream_config.type == SUBVP_MAIN) { + /* determine if minimal transition is required due to SubVP*/ +- if (surface_count > 0) { +- if (cur_stream_status->plane_count > surface_count) { +- force_minimal_pipe_splitting = true; +- } else if (cur_stream_status->plane_count < surface_count) { +- force_minimal_pipe_splitting = true; +- *is_plane_addition = true; +- } ++ if (cur_stream_status->plane_count > surface_count) { ++ force_minimal_pipe_splitting = true; ++ } else if (cur_stream_status->plane_count < surface_count) { ++ force_minimal_pipe_splitting = true; ++ *is_plane_addition = true; + } + } + +@@ -3758,6 +3758,7 @@ static bool commit_minimal_transition_state(struct dc *dc, + enum dc_status ret = DC_ERROR_UNEXPECTED; + unsigned int i, j; + unsigned int pipe_in_use = 0; ++ bool subvp_in_use = false; + + if (!transition_context) + return false; +@@ -3770,6 +3771,18 @@ static bool commit_minimal_transition_state(struct dc *dc, + pipe_in_use++; + } + ++ /* If SubVP is enabled and we are adding or removing planes from any main subvp ++ * pipe, we must use the minimal transition. ++ */ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; ++ ++ if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { ++ subvp_in_use = true; ++ break; ++ } ++ } ++ + /* When the OS add a new surface if we have been used all of pipes with odm combine + * and mpc split feature, it need use commit_minimal_transition_state to transition safely. + * After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need +@@ -3778,7 +3791,7 @@ static bool commit_minimal_transition_state(struct dc *dc, + * Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially + * enter/exit MPO when DCN still have enough resources. + */ +- if (pipe_in_use != dc->res_pool->pipe_count) { ++ if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use) { + dc_release_state(transition_context); + return true; + } +-- +2.39.2 + diff --git a/queue-6.1/drm-ttm-don-t-leak-a-resource-on-eviction-error.patch b/queue-6.1/drm-ttm-don-t-leak-a-resource-on-eviction-error.patch new file mode 100644 index 00000000000..902d173d3d9 --- /dev/null +++ b/queue-6.1/drm-ttm-don-t-leak-a-resource-on-eviction-error.patch @@ -0,0 +1,72 @@ +From 99d94688444cdb626d5aaf6f8f0f86aabb032d26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jun 2023 11:14:49 +0200 +Subject: drm/ttm: Don't leak a resource on eviction error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Hellström + +[ Upstream commit e8188c461ee015ba0b9ab2fc82dbd5ebca5a5532 ] + +On eviction errors other than -EMULTIHOP we were leaking a resource. +Fix. + +v2: +- Avoid yet another goto (Andi Shyti) + +Fixes: 403797925768 ("drm/ttm: Fix multihop assert on eviction.") +Cc: Andrey Grodzovsky +Cc: Christian König +Cc: Christian Koenig +Cc: Huang Rui +Cc: dri-devel@lists.freedesktop.org +Cc: # v5.15+ +Signed-off-by: Thomas Hellström +Reviewed-by: Nirmoy Das #v1 +Reviewed-by: Andi Shyti +Reviewed-by: Christian König +Link: https://patchwork.freedesktop.org/patch/msgid/20230626091450.14757-4-thomas.hellstrom@linux.intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ttm/ttm_bo.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index 85f7f5cd4589a..1c891b5839316 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -499,18 +499,18 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, + goto out; + } + +-bounce: +- ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); +- if (ret == -EMULTIHOP) { ++ do { ++ ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); ++ if (ret != -EMULTIHOP) ++ break; ++ + ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop); +- if (ret) { +- if (ret != -ERESTARTSYS && ret != -EINTR) +- pr_err("Buffer eviction failed\n"); +- ttm_resource_free(bo, &evict_mem); +- goto out; +- } +- /* try and move to final place now. */ +- goto bounce; ++ } while (!ret); ++ ++ if (ret) { ++ ttm_resource_free(bo, &evict_mem); ++ if (ret != -ERESTARTSYS && ret != -EINTR) ++ pr_err("Buffer eviction failed\n"); + } + out: + return ret; +-- +2.39.2 + diff --git a/queue-6.1/drm-ttm-don-t-print-error-message-if-eviction-was-in.patch b/queue-6.1/drm-ttm-don-t-print-error-message-if-eviction-was-in.patch new file mode 100644 index 00000000000..0436f57e494 --- /dev/null +++ b/queue-6.1/drm-ttm-don-t-print-error-message-if-eviction-was-in.patch @@ -0,0 +1,42 @@ +From 7d6910a9d6ec779bcc2b5864130ded7b8dafad62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Mar 2023 15:46:19 +0100 +Subject: drm/ttm: Don't print error message if eviction was interrupted +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Hellström + +[ Upstream commit 8ab3b0663e279ab550bc2c0b5d602960e8b94e02 ] + +Avoid printing an error message if eviction was interrupted by, +for example, the user pressing CTRL-C. That may happen if eviction +is waiting for something, like for example a free batch-buffer. + +Signed-off-by: Thomas Hellström +Reviewed-by: Christian König +Link: https://patchwork.freedesktop.org/patch/msgid/20230307144621.10748-6-thomas.hellstrom@linux.intel.com +Stable-dep-of: e8188c461ee0 ("drm/ttm: Don't leak a resource on eviction error") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ttm/ttm_bo.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index f2c4e9037d6e0..85f7f5cd4589a 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -504,7 +504,8 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, + if (ret == -EMULTIHOP) { + ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop); + if (ret) { +- pr_err("Buffer eviction failed\n"); ++ if (ret != -ERESTARTSYS && ret != -EINTR) ++ pr_err("Buffer eviction failed\n"); + ttm_resource_free(bo, &evict_mem); + goto out; + } +-- +2.39.2 + diff --git a/queue-6.1/drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch b/queue-6.1/drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch new file mode 100644 index 00000000000..a4d03a60229 --- /dev/null +++ b/queue-6.1/drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch @@ -0,0 +1,46 @@ +From 674d706e905f0ee200ed03c47e98f8f9c8792299 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jul 2023 11:25:00 +0200 +Subject: drm/ttm: never consider pinned BOs for eviction&swap +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian König + +[ Upstream commit a2848d08742c8e8494675892c02c0d22acbe3cf8 ] + +There is a small window where we have already incremented the pin count +but not yet moved the bo from the lru to the pinned list. + +Signed-off-by: Christian König +Reported-by: Pelloux-Prayer, Pierre-Eric +Tested-by: Pelloux-Prayer, Pierre-Eric +Acked-by: Alex Deucher +Cc: stable@vger.kernel.org +Link: https://patchwork.freedesktop.org/patch/msgid/20230707120826.3701-1-christian.koenig@amd.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ttm/ttm_bo.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index 1c891b5839316..f7aeeee6f5266 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -550,6 +550,12 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, + { + bool ret = false; + ++ if (bo->pin_count) { ++ *locked = false; ++ *busy = false; ++ return false; ++ } ++ + if (bo->base.resv == ctx->resv) { + dma_resv_assert_held(bo->base.resv); + if (ctx->allow_res_evict) +-- +2.39.2 + diff --git a/queue-6.1/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch b/queue-6.1/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch new file mode 100644 index 00000000000..4c1b3730d37 --- /dev/null +++ b/queue-6.1/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch @@ -0,0 +1,141 @@ +From 190a3e3cce2680c50605abdac3275b70415585fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 May 2023 11:58:22 +0800 +Subject: f2fs: don't reset unchangable mount option in f2fs_remount() + +From: Chao Yu + +[ Upstream commit 458c15dfbce62c35fefd9ca637b20a051309c9f1 ] + +syzbot reports a bug as below: + +general protection fault, probably for non-canonical address 0xdffffc0000000009: 0000 [#1] PREEMPT SMP KASAN +RIP: 0010:__lock_acquire+0x69/0x2000 kernel/locking/lockdep.c:4942 +Call Trace: + lock_acquire+0x1e3/0x520 kernel/locking/lockdep.c:5691 + __raw_write_lock include/linux/rwlock_api_smp.h:209 [inline] + _raw_write_lock+0x2e/0x40 kernel/locking/spinlock.c:300 + __drop_extent_tree+0x3ac/0x660 fs/f2fs/extent_cache.c:1100 + f2fs_drop_extent_tree+0x17/0x30 fs/f2fs/extent_cache.c:1116 + f2fs_insert_range+0x2d5/0x3c0 fs/f2fs/file.c:1664 + f2fs_fallocate+0x4e4/0x6d0 fs/f2fs/file.c:1838 + vfs_fallocate+0x54b/0x6b0 fs/open.c:324 + ksys_fallocate fs/open.c:347 [inline] + __do_sys_fallocate fs/open.c:355 [inline] + __se_sys_fallocate fs/open.c:353 [inline] + __x64_sys_fallocate+0xbd/0x100 fs/open.c:353 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +The root cause is race condition as below: +- since it tries to remount rw filesystem, so that do_remount won't +call sb_prepare_remount_readonly to block fallocate, there may be race +condition in between remount and fallocate. +- in f2fs_remount(), default_options() will reset mount option to default +one, and then update it based on result of parse_options(), so there is +a hole which race condition can happen. + +Thread A Thread B +- f2fs_fill_super + - parse_options + - clear_opt(READ_EXTENT_CACHE) + +- f2fs_remount + - default_options + - set_opt(READ_EXTENT_CACHE) + - f2fs_fallocate + - f2fs_insert_range + - f2fs_drop_extent_tree + - __drop_extent_tree + - __may_extent_tree + - test_opt(READ_EXTENT_CACHE) return true + - write_lock(&et->lock) access NULL pointer + - parse_options + - clear_opt(READ_EXTENT_CACHE) + +Cc: +Reported-by: syzbot+d015b6c2fbb5c383bf08@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-f2fs-devel/20230522124203.3838360-1-chao@kernel.org +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/super.c | 30 ++++++++++++++++++------------ + 1 file changed, 18 insertions(+), 12 deletions(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 36bb1c969e8bb..ff47aad636e5b 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -2040,9 +2040,22 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) + return 0; + } + +-static void default_options(struct f2fs_sb_info *sbi) ++static void default_options(struct f2fs_sb_info *sbi, bool remount) + { + /* init some FS parameters */ ++ if (!remount) { ++ set_opt(sbi, READ_EXTENT_CACHE); ++ clear_opt(sbi, DISABLE_CHECKPOINT); ++ ++ if (f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) ++ set_opt(sbi, DISCARD); ++ ++ if (f2fs_sb_has_blkzoned(sbi)) ++ F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_SECTION; ++ else ++ F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_BLOCK; ++ } ++ + if (f2fs_sb_has_readonly(sbi)) + F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE; + else +@@ -2065,23 +2078,16 @@ static void default_options(struct f2fs_sb_info *sbi) + set_opt(sbi, INLINE_XATTR); + set_opt(sbi, INLINE_DATA); + set_opt(sbi, INLINE_DENTRY); +- set_opt(sbi, READ_EXTENT_CACHE); + set_opt(sbi, NOHEAP); +- clear_opt(sbi, DISABLE_CHECKPOINT); + set_opt(sbi, MERGE_CHECKPOINT); + F2FS_OPTION(sbi).unusable_cap = 0; + sbi->sb->s_flags |= SB_LAZYTIME; + if (!f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) + set_opt(sbi, FLUSH_MERGE); +- if (f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) +- set_opt(sbi, DISCARD); +- if (f2fs_sb_has_blkzoned(sbi)) { ++ if (f2fs_sb_has_blkzoned(sbi)) + F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS; +- F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_SECTION; +- } else { ++ else + F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE; +- F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_BLOCK; +- } + + #ifdef CONFIG_F2FS_FS_XATTR + set_opt(sbi, XATTR_USER); +@@ -2253,7 +2259,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) + clear_sbi_flag(sbi, SBI_NEED_SB_WRITE); + } + +- default_options(sbi); ++ default_options(sbi, true); + + /* parse mount options */ + err = parse_options(sb, data, true); +@@ -4150,7 +4156,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) + sbi->s_chksum_seed = f2fs_chksum(sbi, ~0, raw_super->uuid, + sizeof(raw_super->uuid)); + +- default_options(sbi); ++ default_options(sbi, false); + /* parse mount options */ + options = kstrdup((const char *)data, GFP_KERNEL); + if (data && !options) { +-- +2.39.2 + diff --git a/queue-6.1/f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch b/queue-6.1/f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch new file mode 100644 index 00000000000..a590d2d032e --- /dev/null +++ b/queue-6.1/f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch @@ -0,0 +1,66 @@ +From 3345346778c41ffe5a9c6e5e52a99632d6c1518d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 17:15:01 +0800 +Subject: f2fs: fix to set flush_merge opt and show noflush_merge + +From: Yangtao Li + +[ Upstream commit 967eaad1fed5f6335ea97a47d45214744dc57925 ] + +Some minor modifications to flush_merge and related parameters: + + 1.The FLUSH_MERGE opt is set by default only in non-ro mode. + 2.When ro and merge are set at the same time, an error is reported. + 3.Display noflush_merge mount opt. + +Suggested-by: Chao Yu +Signed-off-by: Yangtao Li +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 458c15dfbce6 ("f2fs: don't reset unchangable mount option in f2fs_remount()") +Signed-off-by: Sasha Levin +--- + fs/f2fs/super.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index b6dad389fa144..36bb1c969e8bb 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -1347,6 +1347,12 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) + return -EINVAL; + } + ++ if ((f2fs_sb_has_readonly(sbi) || f2fs_readonly(sbi->sb)) && ++ test_opt(sbi, FLUSH_MERGE)) { ++ f2fs_err(sbi, "FLUSH_MERGE not compatible with readonly mode"); ++ return -EINVAL; ++ } ++ + if (f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) { + f2fs_err(sbi, "Allow to mount readonly mode only"); + return -EROFS; +@@ -1933,8 +1939,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) + seq_puts(seq, ",inline_dentry"); + else + seq_puts(seq, ",noinline_dentry"); +- if (!f2fs_readonly(sbi->sb) && test_opt(sbi, FLUSH_MERGE)) ++ if (test_opt(sbi, FLUSH_MERGE)) + seq_puts(seq, ",flush_merge"); ++ else ++ seq_puts(seq, ",noflush_merge"); + if (test_opt(sbi, NOBARRIER)) + seq_puts(seq, ",nobarrier"); + if (test_opt(sbi, FASTBOOT)) +@@ -2063,7 +2071,8 @@ static void default_options(struct f2fs_sb_info *sbi) + set_opt(sbi, MERGE_CHECKPOINT); + F2FS_OPTION(sbi).unusable_cap = 0; + sbi->sb->s_flags |= SB_LAZYTIME; +- set_opt(sbi, FLUSH_MERGE); ++ if (!f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) ++ set_opt(sbi, FLUSH_MERGE); + if (f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) + set_opt(sbi, DISCARD); + if (f2fs_sb_has_blkzoned(sbi)) { +-- +2.39.2 + diff --git a/queue-6.1/gpio-mvebu-fix-irq-domain-leak.patch b/queue-6.1/gpio-mvebu-fix-irq-domain-leak.patch new file mode 100644 index 00000000000..0d08c6dab36 --- /dev/null +++ b/queue-6.1/gpio-mvebu-fix-irq-domain-leak.patch @@ -0,0 +1,77 @@ +From b4b7441e6d0f89aff513d68625c65e735b1aa4f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Jul 2023 13:41:01 +0200 +Subject: gpio: mvebu: fix irq domain leak +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bartosz Golaszewski + +[ Upstream commit 644ee70267a934be27370f9aa618b29af7290544 ] + +Uwe Kleine-König pointed out we still have one resource leak in the mvebu +driver triggered on driver detach. Let's address it with a custom devm +action. + +Fixes: 812d47889a8e ("gpio/mvebu: Use irq_domain_add_linear") +Signed-off-by: Bartosz Golaszewski +Reviewed-by: Andy Shevchenko +Reviewed-by: Uwe Kleine-König +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-mvebu.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index f86b6c3bc1604..0ba9d04183a60 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -1112,6 +1112,13 @@ static int mvebu_gpio_probe_syscon(struct platform_device *pdev, + return 0; + } + ++static void mvebu_gpio_remove_irq_domain(void *data) ++{ ++ struct irq_domain *domain = data; ++ ++ irq_domain_remove(domain); ++} ++ + static int mvebu_gpio_probe(struct platform_device *pdev) + { + struct mvebu_gpio_chip *mvchip; +@@ -1246,13 +1253,18 @@ static int mvebu_gpio_probe(struct platform_device *pdev) + return -ENODEV; + } + ++ err = devm_add_action_or_reset(&pdev->dev, mvebu_gpio_remove_irq_domain, ++ mvchip->domain); ++ if (err) ++ return err; ++ + err = irq_alloc_domain_generic_chips( + mvchip->domain, ngpios, 2, np->name, handle_level_irq, + IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0); + if (err) { + dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n", + mvchip->chip.label); +- goto err_domain; ++ return err; + } + + /* +@@ -1292,10 +1304,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) + } + + return 0; +- +-err_domain: +- irq_domain_remove(mvchip->domain); +- return err; + } + + static struct platform_driver mvebu_gpio_driver = { +-- +2.39.2 + diff --git a/queue-6.1/gpio-mvebu-make-use-of-devm_pwmchip_add.patch b/queue-6.1/gpio-mvebu-make-use-of-devm_pwmchip_add.patch new file mode 100644 index 00000000000..84a2149ba7f --- /dev/null +++ b/queue-6.1/gpio-mvebu-make-use-of-devm_pwmchip_add.patch @@ -0,0 +1,61 @@ +From 224ebe66f38e1aa60d7929c9a9c16028fc64e0d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Jul 2023 16:27:43 +0200 +Subject: gpio: mvebu: Make use of devm_pwmchip_add +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 1945063eb59e64d2919cb14d54d081476d9e53bb ] + +This allows to get rid of a call to pwmchip_remove() in the error path. There +is no .remove function for this driver, so this change fixes a resource leak +when a gpio-mvebu device is unbound. + +Fixes: 757642f9a584 ("gpio: mvebu: Add limited PWM support") +Signed-off-by: Uwe Kleine-König +Reviewed-by: Andy Shevchenko +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-mvebu.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index 91a4232ee58c2..f86b6c3bc1604 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -874,7 +874,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + + spin_lock_init(&mvpwm->lock); + +- return pwmchip_add(&mvpwm->chip); ++ return devm_pwmchip_add(dev, &mvpwm->chip); + } + + #ifdef CONFIG_DEBUG_FS +@@ -1243,8 +1243,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) + if (!mvchip->domain) { + dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", + mvchip->chip.label); +- err = -ENODEV; +- goto err_pwm; ++ return -ENODEV; + } + + err = irq_alloc_domain_generic_chips( +@@ -1296,9 +1295,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) + + err_domain: + irq_domain_remove(mvchip->domain); +-err_pwm: +- pwmchip_remove(&mvchip->mvpwm->chip); +- + return err; + } + +-- +2.39.2 + diff --git a/queue-6.1/gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch b/queue-6.1/gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch new file mode 100644 index 00000000000..4797d5146c6 --- /dev/null +++ b/queue-6.1/gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch @@ -0,0 +1,50 @@ +From 0308b3f35c5282b1daa1fd5bcbdaa4e26e8b228b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Jul 2023 14:34:25 +0200 +Subject: gpio: tps68470: Make tps68470_gpio_output() always set the initial + value + +From: Hans de Goede + +[ Upstream commit 5a7adc6c1069ce31ef4f606ae9c05592c80a6ab5 ] + +Make tps68470_gpio_output() call tps68470_gpio_set() for output-only pins +too, so that the initial value passed to gpiod_direction_output() is +honored for these pins too. + +Fixes: 275b13a65547 ("gpio: Add support for TPS68470 GPIOs") +Reviewed-by: Andy Shevchenko +Reviewed-by: Daniel Scally +Tested-by: Daniel Scally +Reviewed-by: Sakari Ailus +Signed-off-by: Hans de Goede +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-tps68470.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c +index aaddcabe9b359..532deaddfd4e2 100644 +--- a/drivers/gpio/gpio-tps68470.c ++++ b/drivers/gpio/gpio-tps68470.c +@@ -91,13 +91,13 @@ static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset, + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + ++ /* Set the initial value */ ++ tps68470_gpio_set(gc, offset, value); ++ + /* rest are always outputs */ + if (offset >= TPS68470_N_REGULAR_GPIO) + return 0; + +- /* Set the initial value */ +- tps68470_gpio_set(gc, offset, value); +- + return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), + TPS68470_GPIO_MODE_MASK, + TPS68470_GPIO_MODE_OUT_CMOS); +-- +2.39.2 + diff --git a/queue-6.1/i2c-delete-error-messages-for-failed-memory-allocati.patch b/queue-6.1/i2c-delete-error-messages-for-failed-memory-allocati.patch new file mode 100644 index 00000000000..f53e450ceac --- /dev/null +++ b/queue-6.1/i2c-delete-error-messages-for-failed-memory-allocati.patch @@ -0,0 +1,81 @@ +From 73c7cd9244a510e68456a92b13483fba660cc2d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Feb 2018 17:24:57 +0100 +Subject: i2c: Delete error messages for failed memory allocations + +From: Markus Elfring + +[ Upstream commit 6b3b21a8542fd2fb6ffc61bc13b9419f0c58ebad ] + +These issues were detected by using the Coccinelle software. + +Signed-off-by: Markus Elfring +Signed-off-by: Wolfram Sang +Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-ibm_iic.c | 4 +--- + drivers/i2c/busses/i2c-nomadik.c | 1 - + drivers/i2c/busses/i2c-sh7760.c | 1 - + drivers/i2c/busses/i2c-tiny-usb.c | 4 +--- + 4 files changed, 2 insertions(+), 8 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c +index eeb80e34f9ad7..de3b609515e08 100644 +--- a/drivers/i2c/busses/i2c-ibm_iic.c ++++ b/drivers/i2c/busses/i2c-ibm_iic.c +@@ -694,10 +694,8 @@ static int iic_probe(struct platform_device *ofdev) + int ret; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); +- if (!dev) { +- dev_err(&ofdev->dev, "failed to allocate device data\n"); ++ if (!dev) + return -ENOMEM; +- } + + platform_set_drvdata(ofdev, dev); + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index a2d12a5b1c34c..05eaae5aeb180 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -972,7 +972,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + dev = devm_kzalloc(&adev->dev, sizeof(struct nmk_i2c_dev), GFP_KERNEL); + if (!dev) { +- dev_err(&adev->dev, "cannot allocate memory\n"); + ret = -ENOMEM; + goto err_no_mem; + } +diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c +index 319d1fa617c88..a0ccc5d009874 100644 +--- a/drivers/i2c/busses/i2c-sh7760.c ++++ b/drivers/i2c/busses/i2c-sh7760.c +@@ -445,7 +445,6 @@ static int sh7760_i2c_probe(struct platform_device *pdev) + + id = kzalloc(sizeof(struct cami2c), GFP_KERNEL); + if (!id) { +- dev_err(&pdev->dev, "no mem for private data\n"); + ret = -ENOMEM; + goto out0; + } +diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c +index 7279ca0eaa2d0..d1fa9ff5aeab4 100644 +--- a/drivers/i2c/busses/i2c-tiny-usb.c ++++ b/drivers/i2c/busses/i2c-tiny-usb.c +@@ -226,10 +226,8 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); +- if (dev == NULL) { +- dev_err(&interface->dev, "Out of memory\n"); ++ if (!dev) + goto error; +- } + + dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; +-- +2.39.2 + diff --git a/queue-6.1/i2c-improve-size-determinations.patch b/queue-6.1/i2c-improve-size-determinations.patch new file mode 100644 index 00000000000..8a8cfb58c81 --- /dev/null +++ b/queue-6.1/i2c-improve-size-determinations.patch @@ -0,0 +1,54 @@ +From 76391e4d78f23ae740ef7f07b6e4c2731628ec4d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Feb 2018 14:50:09 +0100 +Subject: i2c: Improve size determinations + +From: Markus Elfring + +[ Upstream commit 06e989578232da33a7fe96b04191b862af8b2cec ] + +Replace the specification of a data structure by a pointer dereference +as the parameter for the operator "sizeof" to make the corresponding +size determination a bit safer according to the Linux coding style +convention. + +This issue was detected by using the Coccinelle software. + +Signed-off-by: Markus Elfring +Signed-off-by: Wolfram Sang +Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-nomadik.c | 2 +- + drivers/i2c/busses/i2c-sh7760.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index 05eaae5aeb180..5004b9dd98563 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -970,7 +970,7 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + struct i2c_vendor_data *vendor = id->data; + u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; + +- dev = devm_kzalloc(&adev->dev, sizeof(struct nmk_i2c_dev), GFP_KERNEL); ++ dev = devm_kzalloc(&adev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) { + ret = -ENOMEM; + goto err_no_mem; +diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c +index a0ccc5d009874..051b904cb35f6 100644 +--- a/drivers/i2c/busses/i2c-sh7760.c ++++ b/drivers/i2c/busses/i2c-sh7760.c +@@ -443,7 +443,7 @@ static int sh7760_i2c_probe(struct platform_device *pdev) + goto out0; + } + +- id = kzalloc(sizeof(struct cami2c), GFP_KERNEL); ++ id = kzalloc(sizeof(*id), GFP_KERNEL); + if (!id) { + ret = -ENOMEM; + goto out0; +-- +2.39.2 + diff --git a/queue-6.1/i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch b/queue-6.1/i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch new file mode 100644 index 00000000000..2922bc4b9f4 --- /dev/null +++ b/queue-6.1/i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch @@ -0,0 +1,49 @@ +From edaaa54c28b5b792b3cd932bd38511c4e67412a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jul 2023 21:50:28 +0200 +Subject: i2c: nomadik: Remove a useless call in the remove function + +From: Christophe JAILLET + +[ Upstream commit 05f933d5f7318b03ff2028c1704dc867ac16f2c7 ] + +Since commit 235602146ec9 ("i2c-nomadik: turn the platform driver to an amba +driver"), there is no more request_mem_region() call in this driver. + +So remove the release_mem_region() call from the remove function which is +likely a left over. + +Fixes: 235602146ec9 ("i2c-nomadik: turn the platform driver to an amba driver") +Cc: # v3.6+ +Acked-by: Linus Walleij +Reviewed-by: Andi Shyti +Signed-off-by: Christophe JAILLET +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-nomadik.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index 2141ba05dfece..9c5d66bd6dc1c 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -1040,7 +1040,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + static void nmk_i2c_remove(struct amba_device *adev) + { +- struct resource *res = &adev->res; + struct nmk_i2c_dev *dev = amba_get_drvdata(adev); + + i2c_del_adapter(&dev->adap); +@@ -1049,7 +1048,6 @@ static void nmk_i2c_remove(struct amba_device *adev) + clear_all_interrupts(dev); + /* disable the controller */ + i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); +- release_mem_region(res->start, resource_size(res)); + } + + static struct i2c_vendor_data vendor_stn8815 = { +-- +2.39.2 + diff --git a/queue-6.1/i2c-nomadik-remove-unnecessary-goto-label.patch b/queue-6.1/i2c-nomadik-remove-unnecessary-goto-label.patch new file mode 100644 index 00000000000..8777d36b687 --- /dev/null +++ b/queue-6.1/i2c-nomadik-remove-unnecessary-goto-label.patch @@ -0,0 +1,85 @@ +From f0fec396cc9dadd1f61b1af9d6f04ebdd0d473f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Jun 2023 03:36:59 +0200 +Subject: i2c: nomadik: Remove unnecessary goto label + +From: Andi Shyti + +[ Upstream commit 1c5d33fff0d375e4ab7c4261dc62a286babbb4c6 ] + +The err_no_mem goto label doesn't do anything. Remove it. + +Signed-off-by: Andi Shyti +Reviewed-by: Linus Walleij +Signed-off-by: Wolfram Sang +Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-nomadik.c | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index 5004b9dd98563..8b9577318388e 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -971,10 +971,9 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; + + dev = devm_kzalloc(&adev->dev, sizeof(*dev), GFP_KERNEL); +- if (!dev) { +- ret = -ENOMEM; +- goto err_no_mem; +- } ++ if (!dev) ++ return -ENOMEM; ++ + dev->vendor = vendor; + dev->adev = adev; + nmk_i2c_of_probe(np, dev); +@@ -995,30 +994,27 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + dev->virtbase = devm_ioremap(&adev->dev, adev->res.start, + resource_size(&adev->res)); +- if (!dev->virtbase) { +- ret = -ENOMEM; +- goto err_no_mem; +- } ++ if (!dev->virtbase) ++ return -ENOMEM; + + dev->irq = adev->irq[0]; + ret = devm_request_irq(&adev->dev, dev->irq, i2c_irq_handler, 0, + DRIVER_NAME, dev); + if (ret) { + dev_err(&adev->dev, "cannot claim the irq %d\n", dev->irq); +- goto err_no_mem; ++ return ret; + } + + dev->clk = devm_clk_get(&adev->dev, NULL); + if (IS_ERR(dev->clk)) { + dev_err(&adev->dev, "could not get i2c clock\n"); +- ret = PTR_ERR(dev->clk); +- goto err_no_mem; ++ return PTR_ERR(dev->clk); + } + + ret = clk_prepare_enable(dev->clk); + if (ret) { + dev_err(&adev->dev, "can't prepare_enable clock\n"); +- goto err_no_mem; ++ return ret; + } + + init_hw(dev); +@@ -1049,7 +1045,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + err_no_adap: + clk_disable_unprepare(dev->clk); +- err_no_mem: + + return ret; + } +-- +2.39.2 + diff --git a/queue-6.1/i2c-nomadik-use-devm_clk_get_enabled.patch b/queue-6.1/i2c-nomadik-use-devm_clk_get_enabled.patch new file mode 100644 index 00000000000..462dc641832 --- /dev/null +++ b/queue-6.1/i2c-nomadik-use-devm_clk_get_enabled.patch @@ -0,0 +1,76 @@ +From 09d2f0f15de6abcfb5022e067b36b1d196396dee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Jun 2023 03:37:00 +0200 +Subject: i2c: nomadik: Use devm_clk_get_enabled() + +From: Andi Shyti + +[ Upstream commit 9c7174db4cdd111e10d19eed5c36fd978a14c8a2 ] + +Replace the pair of functions, devm_clk_get() and +clk_prepare_enable(), with a single function +devm_clk_get_enabled(). + +Signed-off-by: Andi Shyti +Reviewed-by: Linus Walleij +Signed-off-by: Wolfram Sang +Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-nomadik.c | 18 +++--------------- + 1 file changed, 3 insertions(+), 15 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index 8b9577318388e..2141ba05dfece 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -1005,18 +1005,12 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + return ret; + } + +- dev->clk = devm_clk_get(&adev->dev, NULL); ++ dev->clk = devm_clk_get_enabled(&adev->dev, NULL); + if (IS_ERR(dev->clk)) { +- dev_err(&adev->dev, "could not get i2c clock\n"); ++ dev_err(&adev->dev, "could enable i2c clock\n"); + return PTR_ERR(dev->clk); + } + +- ret = clk_prepare_enable(dev->clk); +- if (ret) { +- dev_err(&adev->dev, "can't prepare_enable clock\n"); +- return ret; +- } +- + init_hw(dev); + + adap = &dev->adap; +@@ -1037,16 +1031,11 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + ret = i2c_add_adapter(adap); + if (ret) +- goto err_no_adap; ++ return ret; + + pm_runtime_put(&adev->dev); + + return 0; +- +- err_no_adap: +- clk_disable_unprepare(dev->clk); +- +- return ret; + } + + static void nmk_i2c_remove(struct amba_device *adev) +@@ -1060,7 +1049,6 @@ static void nmk_i2c_remove(struct amba_device *adev) + clear_all_interrupts(dev); + /* disable the controller */ + i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); +- clk_disable_unprepare(dev->clk); + release_mem_region(res->start, resource_size(res)); + } + +-- +2.39.2 + diff --git a/queue-6.1/io_uring-don-t-audit-the-capability-check-in-io_urin.patch b/queue-6.1/io_uring-don-t-audit-the-capability-check-in-io_urin.patch new file mode 100644 index 00000000000..b8c1d6e76e1 --- /dev/null +++ b/queue-6.1/io_uring-don-t-audit-the-capability-check-in-io_urin.patch @@ -0,0 +1,47 @@ +From 1324feea7eaba5e6c48fca0af8b85fdc28a0cdcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Jul 2023 13:56:07 +0200 +Subject: io_uring: don't audit the capability check in io_uring_create() + +From: Ondrej Mosnacek + +[ Upstream commit 6adc2272aaaf84f34b652cf77f770c6fcc4b8336 ] + +The check being unconditional may lead to unwanted denials reported by +LSMs when a process has the capability granted by DAC, but denied by an +LSM. In the case of SELinux such denials are a problem, since they can't +be effectively filtered out via the policy and when not silenced, they +produce noise that may hide a true problem or an attack. + +Since not having the capability merely means that the created io_uring +context will be accounted against the current user's RLIMIT_MEMLOCK +limit, we can disable auditing of denials for this check by using +ns_capable_noaudit() instead of capable(). + +Fixes: 2b188cc1bb85 ("Add io_uring IO interface") +Link: https://bugzilla.redhat.com/show_bug.cgi?id=2193317 +Signed-off-by: Ondrej Mosnacek +Reviewed-by: Jeff Moyer +Link: https://lore.kernel.org/r/20230718115607.65652-1-omosnace@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index bd7b8cf8bc677..f091153bc8540 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -3477,7 +3477,7 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p, + ctx->syscall_iopoll = 1; + + ctx->compat = in_compat_syscall(); +- if (!capable(CAP_IPC_LOCK)) ++ if (!ns_capable_noaudit(&init_user_ns, CAP_IPC_LOCK)) + ctx->user = get_uid(current_user()); + + /* +-- +2.39.2 + diff --git a/queue-6.1/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch b/queue-6.1/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch new file mode 100644 index 00000000000..6dc28c30675 --- /dev/null +++ b/queue-6.1/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch @@ -0,0 +1,150 @@ +From 4925d566f7e303289ee5d4aabcf8e2f24544331b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:27 +0800 +Subject: jbd2: fix a race when checking checkpoint buffer busy + +From: Zhang Yi + +[ Upstream commit 46f881b5b1758dc4a35fba4a643c10717d0cf427 ] + +Before removing checkpoint buffer from the t_checkpoint_list, we have to +check both BH_Dirty and BH_Lock bits together to distinguish buffers +have not been or were being written back. But __cp_buffer_busy() checks +them separately, it first check lock state and then check dirty, the +window between these two checks could be raced by writing back +procedure, which locks buffer and clears buffer dirty before I/O +completes. So it cannot guarantee checkpointing buffers been written +back to disk if some error happens later. Finally, it may clean +checkpoint transactions and lead to inconsistent filesystem. + +jbd2_journal_forget() and __journal_try_to_free_buffer() also have the +same problem (journal_unmap_buffer() escape from this issue since it's +running under the buffer lock), so fix them through introducing a new +helper to try holding the buffer lock and remove really clean buffer. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217490 +Cc: stable@vger.kernel.org +Suggested-by: Jan Kara +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-6-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 38 +++++++++++++++++++++++++++++++++++--- + fs/jbd2/transaction.c | 17 +++++------------ + include/linux/jbd2.h | 1 + + 3 files changed, 41 insertions(+), 15 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index 42b34cab64fbd..9ec91017a7f3c 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -376,11 +376,15 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, + jh = next_jh; + next_jh = jh->b_cpnext; + +- if (!destroy && __cp_buffer_busy(jh)) +- continue; ++ if (destroy) { ++ ret = __jbd2_journal_remove_checkpoint(jh); ++ } else { ++ ret = jbd2_journal_try_remove_checkpoint(jh); ++ if (ret < 0) ++ continue; ++ } + + nr_freed++; +- ret = __jbd2_journal_remove_checkpoint(jh); + if (ret) { + *released = true; + break; +@@ -616,6 +620,34 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) + return 1; + } + ++/* ++ * Check the checkpoint buffer and try to remove it from the checkpoint ++ * list if it's clean. Returns -EBUSY if it is not clean, returns 1 if ++ * it frees the transaction, 0 otherwise. ++ * ++ * This function is called with j_list_lock held. ++ */ ++int jbd2_journal_try_remove_checkpoint(struct journal_head *jh) ++{ ++ struct buffer_head *bh = jh2bh(jh); ++ ++ if (!trylock_buffer(bh)) ++ return -EBUSY; ++ if (buffer_dirty(bh)) { ++ unlock_buffer(bh); ++ return -EBUSY; ++ } ++ unlock_buffer(bh); ++ ++ /* ++ * Buffer is clean and the IO has finished (we held the buffer ++ * lock) so the checkpoint is done. We can safely remove the ++ * buffer from this transaction. ++ */ ++ JBUFFER_TRACE(jh, "remove from checkpoint list"); ++ return __jbd2_journal_remove_checkpoint(jh); ++} ++ + /* + * journal_insert_checkpoint: put a committed buffer onto a checkpoint + * list so that we know when it is safe to clean the transaction out of +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index 18611241f4513..6ef5022949c46 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1784,8 +1784,7 @@ int jbd2_journal_forget(handle_t *handle, struct buffer_head *bh) + * Otherwise, if the buffer has been written to disk, + * it is safe to remove the checkpoint and drop it. + */ +- if (!buffer_dirty(bh)) { +- __jbd2_journal_remove_checkpoint(jh); ++ if (jbd2_journal_try_remove_checkpoint(jh) >= 0) { + spin_unlock(&journal->j_list_lock); + goto drop; + } +@@ -2112,20 +2111,14 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh) + + jh = bh2jh(bh); + +- if (buffer_locked(bh) || buffer_dirty(bh)) +- goto out; +- + if (jh->b_next_transaction != NULL || jh->b_transaction != NULL) +- goto out; ++ return; + + spin_lock(&journal->j_list_lock); +- if (jh->b_cp_transaction != NULL) { +- /* written-back checkpointed metadata buffer */ +- JBUFFER_TRACE(jh, "remove from checkpoint list"); +- __jbd2_journal_remove_checkpoint(jh); +- } ++ /* Remove written-back checkpointed metadata buffer */ ++ if (jh->b_cp_transaction != NULL) ++ jbd2_journal_try_remove_checkpoint(jh); + spin_unlock(&journal->j_list_lock); +-out: + return; + } + +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index 67912fe08fbbd..ebb1608d9dcd2 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1435,6 +1435,7 @@ extern void jbd2_journal_commit_transaction(journal_t *); + void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy); + unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, unsigned long *nr_to_scan); + int __jbd2_journal_remove_checkpoint(struct journal_head *); ++int jbd2_journal_try_remove_checkpoint(struct journal_head *jh); + void jbd2_journal_destroy_checkpoint(journal_t *journal); + void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *); + +-- +2.39.2 + diff --git a/queue-6.1/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch b/queue-6.1/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch new file mode 100644 index 00000000000..474f6ebeb6b --- /dev/null +++ b/queue-6.1/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch @@ -0,0 +1,106 @@ +From 25cc3f564e96e47e88122e7e0f0f885003315344 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:26 +0800 +Subject: jbd2: Fix wrongly judgement for buffer head removing while doing + checkpoint + +From: Zhihao Cheng + +[ Upstream commit e34c8dd238d0c9368b746480f313055f5bab5040 ] + +Following process, + +jbd2_journal_commit_transaction +// there are several dirty buffer heads in transaction->t_checkpoint_list + P1 wb_workfn +jbd2_log_do_checkpoint + if (buffer_locked(bh)) // false + __block_write_full_page + trylock_buffer(bh) + test_clear_buffer_dirty(bh) + if (!buffer_dirty(bh)) + __jbd2_journal_remove_checkpoint(jh) + if (buffer_write_io_error(bh)) // false + >> bh IO error occurs << + jbd2_cleanup_journal_tail + __jbd2_update_log_tail + jbd2_write_superblock + // The bh won't be replayed in next mount. +, which could corrupt the ext4 image, fetch a reproducer in [Link]. + +Since writeback process clears buffer dirty after locking buffer head, +we can fix it by try locking buffer and check dirtiness while buffer is +locked, the buffer head can be removed if it is neither dirty nor locked. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217490 +Fixes: 470decc613ab ("[PATCH] jbd2: initial copy of files from jbd") +Signed-off-by: Zhihao Cheng +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-5-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index 25e3c20eb19f6..c4e0da6db7195 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -221,20 +221,6 @@ int jbd2_log_do_checkpoint(journal_t *journal) + jh = transaction->t_checkpoint_list; + bh = jh2bh(jh); + +- /* +- * The buffer may be writing back, or flushing out in the +- * last couple of cycles, or re-adding into a new transaction, +- * need to check it again until it's unlocked. +- */ +- if (buffer_locked(bh)) { +- get_bh(bh); +- spin_unlock(&journal->j_list_lock); +- wait_on_buffer(bh); +- /* the journal_head may have gone by now */ +- BUFFER_TRACE(bh, "brelse"); +- __brelse(bh); +- goto retry; +- } + if (jh->b_transaction != NULL) { + transaction_t *t = jh->b_transaction; + tid_t tid = t->t_tid; +@@ -269,7 +255,22 @@ int jbd2_log_do_checkpoint(journal_t *journal) + spin_lock(&journal->j_list_lock); + goto restart; + } +- if (!buffer_dirty(bh)) { ++ if (!trylock_buffer(bh)) { ++ /* ++ * The buffer is locked, it may be writing back, or ++ * flushing out in the last couple of cycles, or ++ * re-adding into a new transaction, need to check ++ * it again until it's unlocked. ++ */ ++ get_bh(bh); ++ spin_unlock(&journal->j_list_lock); ++ wait_on_buffer(bh); ++ /* the journal_head may have gone by now */ ++ BUFFER_TRACE(bh, "brelse"); ++ __brelse(bh); ++ goto retry; ++ } else if (!buffer_dirty(bh)) { ++ unlock_buffer(bh); + BUFFER_TRACE(bh, "remove from checkpoint"); + /* + * If the transaction was released or the checkpoint +@@ -279,6 +280,7 @@ int jbd2_log_do_checkpoint(journal_t *journal) + !transaction->t_checkpoint_list) + goto out; + } else { ++ unlock_buffer(bh); + /* + * We are about to write the buffer, it could be + * raced by some other transaction shrink or buffer +-- +2.39.2 + diff --git a/queue-6.1/jbd2-remove-journal_clean_one_cp_list.patch b/queue-6.1/jbd2-remove-journal_clean_one_cp_list.patch new file mode 100644 index 00000000000..222f59bc977 --- /dev/null +++ b/queue-6.1/jbd2-remove-journal_clean_one_cp_list.patch @@ -0,0 +1,235 @@ +From 7f2e7e3be85c2c0af0b6cd4c8b69de00ec06408c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:25 +0800 +Subject: jbd2: remove journal_clean_one_cp_list() + +From: Zhang Yi + +[ Upstream commit b98dba273a0e47dbfade89c9af73c5b012a4eabb ] + +journal_clean_one_cp_list() and journal_shrink_one_cp_list() are almost +the same, so merge them into journal_shrink_one_cp_list(), remove the +nr_to_scan parameter, always scan and try to free the whole checkpoint +list. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-4-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 75 +++++++++---------------------------- + include/trace/events/jbd2.h | 12 ++---- + 2 files changed, 21 insertions(+), 66 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index 723b4eb112828..42b34cab64fbd 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -349,50 +349,10 @@ int jbd2_cleanup_journal_tail(journal_t *journal) + + /* Checkpoint list management */ + +-/* +- * journal_clean_one_cp_list +- * +- * Find all the written-back checkpoint buffers in the given list and +- * release them. If 'destroy' is set, clean all buffers unconditionally. +- * +- * Called with j_list_lock held. +- * Returns 1 if we freed the transaction, 0 otherwise. +- */ +-static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) +-{ +- struct journal_head *last_jh; +- struct journal_head *next_jh = jh; +- +- if (!jh) +- return 0; +- +- last_jh = jh->b_cpprev; +- do { +- jh = next_jh; +- next_jh = jh->b_cpnext; +- +- if (!destroy && __cp_buffer_busy(jh)) +- return 0; +- +- if (__jbd2_journal_remove_checkpoint(jh)) +- return 1; +- /* +- * This function only frees up some memory +- * if possible so we dont have an obligation +- * to finish processing. Bail out if preemption +- * requested: +- */ +- if (need_resched()) +- return 0; +- } while (jh != last_jh); +- +- return 0; +-} +- + /* + * journal_shrink_one_cp_list + * +- * Find 'nr_to_scan' written-back checkpoint buffers in the given list ++ * Find all the written-back checkpoint buffers in the given list + * and try to release them. If the whole transaction is released, set + * the 'released' parameter. Return the number of released checkpointed + * buffers. +@@ -400,15 +360,15 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) + * Called with j_list_lock held. + */ + static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, +- unsigned long *nr_to_scan, +- bool *released) ++ bool destroy, bool *released) + { + struct journal_head *last_jh; + struct journal_head *next_jh = jh; + unsigned long nr_freed = 0; + int ret; + +- if (!jh || *nr_to_scan == 0) ++ *released = false; ++ if (!jh) + return 0; + + last_jh = jh->b_cpprev; +@@ -416,8 +376,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, + jh = next_jh; + next_jh = jh->b_cpnext; + +- (*nr_to_scan)--; +- if (__cp_buffer_busy(jh)) ++ if (!destroy && __cp_buffer_busy(jh)) + continue; + + nr_freed++; +@@ -429,7 +388,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, + + if (need_resched()) + break; +- } while (jh != last_jh && *nr_to_scan); ++ } while (jh != last_jh); + + return nr_freed; + } +@@ -447,11 +406,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + unsigned long *nr_to_scan) + { + transaction_t *transaction, *last_transaction, *next_transaction; +- bool released; ++ bool __maybe_unused released; + tid_t first_tid = 0, last_tid = 0, next_tid = 0; + tid_t tid = 0; + unsigned long nr_freed = 0; +- unsigned long nr_scanned = *nr_to_scan; ++ unsigned long freed; + + again: + spin_lock(&journal->j_list_lock); +@@ -480,10 +439,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + transaction = next_transaction; + next_transaction = transaction->t_cpnext; + tid = transaction->t_tid; +- released = false; + +- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_list, +- nr_to_scan, &released); ++ freed = journal_shrink_one_cp_list(transaction->t_checkpoint_list, ++ false, &released); ++ nr_freed += freed; ++ (*nr_to_scan) -= min(*nr_to_scan, freed); + if (*nr_to_scan == 0) + break; + if (need_resched() || spin_needbreak(&journal->j_list_lock)) +@@ -504,9 +464,8 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + if (*nr_to_scan && next_tid) + goto again; + out: +- nr_scanned -= *nr_to_scan; + trace_jbd2_shrink_checkpoint_list(journal, first_tid, tid, last_tid, +- nr_freed, nr_scanned, next_tid); ++ nr_freed, next_tid); + + return nr_freed; + } +@@ -522,7 +481,7 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) + { + transaction_t *transaction, *last_transaction, *next_transaction; +- int ret; ++ bool released; + + transaction = journal->j_checkpoint_transactions; + if (!transaction) +@@ -533,8 +492,8 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) + do { + transaction = next_transaction; + next_transaction = transaction->t_cpnext; +- ret = journal_clean_one_cp_list(transaction->t_checkpoint_list, +- destroy); ++ journal_shrink_one_cp_list(transaction->t_checkpoint_list, ++ destroy, &released); + /* + * This function only frees up some memory if possible so we + * dont have an obligation to finish processing. Bail out if +@@ -547,7 +506,7 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) + * avoids pointless scanning of transactions which still + * weren't checkpointed. + */ +- if (!ret) ++ if (!released) + return; + } while (transaction != last_transaction); + } +diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h +index 8f5ee380d3093..5646ae15a957a 100644 +--- a/include/trace/events/jbd2.h ++++ b/include/trace/events/jbd2.h +@@ -462,11 +462,9 @@ TRACE_EVENT(jbd2_shrink_scan_exit, + TRACE_EVENT(jbd2_shrink_checkpoint_list, + + TP_PROTO(journal_t *journal, tid_t first_tid, tid_t tid, tid_t last_tid, +- unsigned long nr_freed, unsigned long nr_scanned, +- tid_t next_tid), ++ unsigned long nr_freed, tid_t next_tid), + +- TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, +- nr_scanned, next_tid), ++ TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, next_tid), + + TP_STRUCT__entry( + __field(dev_t, dev) +@@ -474,7 +472,6 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, + __field(tid_t, tid) + __field(tid_t, last_tid) + __field(unsigned long, nr_freed) +- __field(unsigned long, nr_scanned) + __field(tid_t, next_tid) + ), + +@@ -484,15 +481,14 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, + __entry->tid = tid; + __entry->last_tid = last_tid; + __entry->nr_freed = nr_freed; +- __entry->nr_scanned = nr_scanned; + __entry->next_tid = next_tid; + ), + + TP_printk("dev %d,%d shrink transaction %u-%u(%u) freed %lu " +- "scanned %lu next transaction %u", ++ "next transaction %u", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->first_tid, __entry->tid, __entry->last_tid, +- __entry->nr_freed, __entry->nr_scanned, __entry->next_tid) ++ __entry->nr_freed, __entry->next_tid) + ); + + #endif /* _TRACE_JBD2_H */ +-- +2.39.2 + diff --git a/queue-6.1/jbd2-remove-t_checkpoint_io_list.patch b/queue-6.1/jbd2-remove-t_checkpoint_io_list.patch new file mode 100644 index 00000000000..1a5ecd82264 --- /dev/null +++ b/queue-6.1/jbd2-remove-t_checkpoint_io_list.patch @@ -0,0 +1,146 @@ +From 0c9838fba04567f1905865f0b3a659724945c8a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:24 +0800 +Subject: jbd2: remove t_checkpoint_io_list + +From: Zhang Yi + +[ Upstream commit be22255360f80d3af789daad00025171a65424a5 ] + +Since t_checkpoint_io_list was stop using in jbd2_log_do_checkpoint() +now, it's time to remove the whole t_checkpoint_io_list logic. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-3-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 42 ++---------------------------------------- + fs/jbd2/commit.c | 3 +-- + include/linux/jbd2.h | 6 ------ + 3 files changed, 3 insertions(+), 48 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index c4e0da6db7195..723b4eb112828 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -27,7 +27,7 @@ + * + * Called with j_list_lock held. + */ +-static inline void __buffer_unlink_first(struct journal_head *jh) ++static inline void __buffer_unlink(struct journal_head *jh) + { + transaction_t *transaction = jh->b_cp_transaction; + +@@ -40,23 +40,6 @@ static inline void __buffer_unlink_first(struct journal_head *jh) + } + } + +-/* +- * Unlink a buffer from a transaction checkpoint(io) list. +- * +- * Called with j_list_lock held. +- */ +-static inline void __buffer_unlink(struct journal_head *jh) +-{ +- transaction_t *transaction = jh->b_cp_transaction; +- +- __buffer_unlink_first(jh); +- if (transaction->t_checkpoint_io_list == jh) { +- transaction->t_checkpoint_io_list = jh->b_cpnext; +- if (transaction->t_checkpoint_io_list == jh) +- transaction->t_checkpoint_io_list = NULL; +- } +-} +- + /* + * Check a checkpoint buffer could be release or not. + * +@@ -505,15 +488,6 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + break; + if (need_resched() || spin_needbreak(&journal->j_list_lock)) + break; +- if (released) +- continue; +- +- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_io_list, +- nr_to_scan, &released); +- if (*nr_to_scan == 0) +- break; +- if (need_resched() || spin_needbreak(&journal->j_list_lock)) +- break; + } while (transaction != last_transaction); + + if (transaction != last_transaction) { +@@ -568,17 +542,6 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) + */ + if (need_resched()) + return; +- if (ret) +- continue; +- /* +- * It is essential that we are as careful as in the case of +- * t_checkpoint_list with removing the buffer from the list as +- * we can possibly see not yet submitted buffers on io_list +- */ +- ret = journal_clean_one_cp_list(transaction-> +- t_checkpoint_io_list, destroy); +- if (need_resched()) +- return; + /* + * Stop scanning if we couldn't free the transaction. This + * avoids pointless scanning of transactions which still +@@ -663,7 +626,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) + jbd2_journal_put_journal_head(jh); + + /* Is this transaction empty? */ +- if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list) ++ if (transaction->t_checkpoint_list) + return 0; + + /* +@@ -755,7 +718,6 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact + J_ASSERT(transaction->t_forget == NULL); + J_ASSERT(transaction->t_shadow_list == NULL); + J_ASSERT(transaction->t_checkpoint_list == NULL); +- J_ASSERT(transaction->t_checkpoint_io_list == NULL); + J_ASSERT(atomic_read(&transaction->t_updates) == 0); + J_ASSERT(journal->j_committing_transaction != transaction); + J_ASSERT(journal->j_running_transaction != transaction); +diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c +index 885a7a6cc53e6..f1d9db6686e31 100644 +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -1171,8 +1171,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) + spin_lock(&journal->j_list_lock); + commit_transaction->t_state = T_FINISHED; + /* Check if the transaction can be dropped now that we are finished */ +- if (commit_transaction->t_checkpoint_list == NULL && +- commit_transaction->t_checkpoint_io_list == NULL) { ++ if (commit_transaction->t_checkpoint_list == NULL) { + __jbd2_journal_drop_transaction(journal, commit_transaction); + jbd2_journal_free_transaction(commit_transaction); + } +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index 0b7242370b567..67912fe08fbbd 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -622,12 +622,6 @@ struct transaction_s + */ + struct journal_head *t_checkpoint_list; + +- /* +- * Doubly-linked circular list of all buffers submitted for IO while +- * checkpointing. [j_list_lock] +- */ +- struct journal_head *t_checkpoint_io_list; +- + /* + * Doubly-linked circular list of metadata buffers being + * shadowed by log IO. The IO buffers on the iobuf list and +-- +2.39.2 + diff --git a/queue-6.1/kvm-arm64-condition-hw-af-updates-on-config-option.patch b/queue-6.1/kvm-arm64-condition-hw-af-updates-on-config-option.patch new file mode 100644 index 00000000000..58bb9396118 --- /dev/null +++ b/queue-6.1/kvm-arm64-condition-hw-af-updates-on-config-option.patch @@ -0,0 +1,47 @@ +From bdcdd5243d15a72a4d07901861d1b23f21cd8420 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 18:51:56 +0000 +Subject: KVM: arm64: Condition HW AF updates on config option + +From: Oliver Upton + +[ Upstream commit 1dfc3e905089a0bcada268fb5691a605655e0319 ] + +As it currently stands, KVM makes use of FEAT_HAFDBS unconditionally. +Use of the feature in the rest of the kernel is guarded by an associated +Kconfig option. + +Align KVM with the rest of the kernel and only enable VTCR_HA when +ARM64_HW_AFDBM is enabled. This can be helpful for testing changes to +the stage-2 access fault path on Armv8.1+ implementations. + +Link: https://lore.kernel.org/r/20221202185156.696189-7-oliver.upton@linux.dev +Signed-off-by: Oliver Upton +Stable-dep-of: 6df696cd9bc1 ("arm64: errata: Mitigate Ampere1 erratum AC03_CPU_38 at stage-2") +Signed-off-by: Sasha Levin +--- + arch/arm64/kvm/hyp/pgtable.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c +index cdf8e76b0be14..8f37e65c23eea 100644 +--- a/arch/arm64/kvm/hyp/pgtable.c ++++ b/arch/arm64/kvm/hyp/pgtable.c +@@ -595,12 +595,14 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift) + lvls = 2; + vtcr |= VTCR_EL2_LVLS_TO_SL0(lvls); + ++#ifdef CONFIG_ARM64_HW_AFDBM + /* + * Enable the Hardware Access Flag management, unconditionally + * on all CPUs. The features is RES0 on CPUs without the support + * and must be ignored by the CPUs. + */ + vtcr |= VTCR_EL2_HA; ++#endif /* CONFIG_ARM64_HW_AFDBM */ + + /* Set the vmid bits */ + vtcr |= (get_vmid_bits(mmfr1) == 16) ? +-- +2.39.2 + diff --git a/queue-6.1/kvm-s390-pv-fix-index-value-of-replaced-asce.patch b/queue-6.1/kvm-s390-pv-fix-index-value-of-replaced-asce.patch new file mode 100644 index 00000000000..c2e28c3fcbc --- /dev/null +++ b/queue-6.1/kvm-s390-pv-fix-index-value-of-replaced-asce.patch @@ -0,0 +1,46 @@ +From cb7919a0732e71660bd810bf4580506730834ad6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jul 2023 13:19:37 +0200 +Subject: KVM: s390: pv: fix index value of replaced ASCE +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Claudio Imbrenda + +[ Upstream commit c2fceb59bbda16468bda82b002383bff59de89ab ] + +The index field of the struct page corresponding to a guest ASCE should +be 0. When replacing the ASCE in s390_replace_asce(), the index of the +new ASCE should also be set to 0. + +Having the wrong index might lead to the wrong addresses being passed +around when notifying pte invalidations, and eventually to validity +intercepts (VM crash) if the prefix gets unmapped and the notifier gets +called with the wrong address. + +Reviewed-by: Philippe Mathieu-Daudé +Fixes: faa2f72cb356 ("KVM: s390: pv: leak the topmost page table when destroy fails") +Reviewed-by: Janosch Frank +Signed-off-by: Claudio Imbrenda +Message-ID: <20230705111937.33472-3-imbrenda@linux.ibm.com> +Signed-off-by: Sasha Levin +--- + arch/s390/mm/gmap.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c +index 02d15c8dc92e9..243f673fa6515 100644 +--- a/arch/s390/mm/gmap.c ++++ b/arch/s390/mm/gmap.c +@@ -2843,6 +2843,7 @@ int s390_replace_asce(struct gmap *gmap) + page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); + if (!page) + return -ENOMEM; ++ page->index = 0; + table = page_to_virt(page); + memcpy(table, gmap->table, 1UL << (CRST_ALLOC_ORDER + PAGE_SHIFT)); + +-- +2.39.2 + diff --git a/queue-6.1/maple_tree-add-__init-and-__exit-to-test-module.patch b/queue-6.1/maple_tree-add-__init-and-__exit-to-test-module.patch new file mode 100644 index 00000000000..321d2b18b3b --- /dev/null +++ b/queue-6.1/maple_tree-add-__init-and-__exit-to-test-module.patch @@ -0,0 +1,1166 @@ +From a0afdf577dc92d040266faac2179cd28a94fb1b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 May 2023 10:55:28 -0400 +Subject: maple_tree: add __init and __exit to test module + +From: Liam R. Howlett + +[ Upstream commit eaf9790d3bc6e157a2134c01c7d707a5a712fab1 ] + +The test functions are not needed after the module is removed, so mark +them as such. Add __exit to the module removal function. Some other +variables have been marked as const static as well. + +Link: https://lkml.kernel.org/r/20230518145544.1722059-20-Liam.Howlett@oracle.com +Signed-off-by: Liam R. Howlett +Suggested-by: Andrew Morton +Cc: David Binderman +Cc: Peng Zhang +Cc: Sergey Senozhatsky +Cc: Vernon Yang +Cc: Wei Yang +Signed-off-by: Andrew Morton +Stable-dep-of: 7a93c71a6714 ("maple_tree: fix 32 bit mas_next testing") +Signed-off-by: Sasha Levin +--- + lib/test_maple_tree.c | 158 +++++++++++++------------- + tools/testing/radix-tree/linux/init.h | 1 + + tools/testing/radix-tree/maple.c | 147 ++++++++++++------------ + 3 files changed, 155 insertions(+), 151 deletions(-) + +diff --git a/lib/test_maple_tree.c b/lib/test_maple_tree.c +index f1db333270e9f..261bad680f81d 100644 +--- a/lib/test_maple_tree.c ++++ b/lib/test_maple_tree.c +@@ -30,54 +30,54 @@ + #else + #define cond_resched() do {} while (0) + #endif +-static +-int mtree_insert_index(struct maple_tree *mt, unsigned long index, gfp_t gfp) ++static int __init mtree_insert_index(struct maple_tree *mt, ++ unsigned long index, gfp_t gfp) + { + return mtree_insert(mt, index, xa_mk_value(index & LONG_MAX), gfp); + } + +-static void mtree_erase_index(struct maple_tree *mt, unsigned long index) ++static void __init mtree_erase_index(struct maple_tree *mt, unsigned long index) + { + MT_BUG_ON(mt, mtree_erase(mt, index) != xa_mk_value(index & LONG_MAX)); + MT_BUG_ON(mt, mtree_load(mt, index) != NULL); + } + +-static int mtree_test_insert(struct maple_tree *mt, unsigned long index, ++static int __init mtree_test_insert(struct maple_tree *mt, unsigned long index, + void *ptr) + { + return mtree_insert(mt, index, ptr, GFP_KERNEL); + } + +-static int mtree_test_store_range(struct maple_tree *mt, unsigned long start, +- unsigned long end, void *ptr) ++static int __init mtree_test_store_range(struct maple_tree *mt, ++ unsigned long start, unsigned long end, void *ptr) + { + return mtree_store_range(mt, start, end, ptr, GFP_KERNEL); + } + +-static int mtree_test_store(struct maple_tree *mt, unsigned long start, ++static int __init mtree_test_store(struct maple_tree *mt, unsigned long start, + void *ptr) + { + return mtree_test_store_range(mt, start, start, ptr); + } + +-static int mtree_test_insert_range(struct maple_tree *mt, unsigned long start, +- unsigned long end, void *ptr) ++static int __init mtree_test_insert_range(struct maple_tree *mt, ++ unsigned long start, unsigned long end, void *ptr) + { + return mtree_insert_range(mt, start, end, ptr, GFP_KERNEL); + } + +-static void *mtree_test_load(struct maple_tree *mt, unsigned long index) ++static void __init *mtree_test_load(struct maple_tree *mt, unsigned long index) + { + return mtree_load(mt, index); + } + +-static void *mtree_test_erase(struct maple_tree *mt, unsigned long index) ++static void __init *mtree_test_erase(struct maple_tree *mt, unsigned long index) + { + return mtree_erase(mt, index); + } + + #if defined(CONFIG_64BIT) +-static noinline void check_mtree_alloc_range(struct maple_tree *mt, ++static noinline void __init check_mtree_alloc_range(struct maple_tree *mt, + unsigned long start, unsigned long end, unsigned long size, + unsigned long expected, int eret, void *ptr) + { +@@ -94,7 +94,7 @@ static noinline void check_mtree_alloc_range(struct maple_tree *mt, + MT_BUG_ON(mt, result != expected); + } + +-static noinline void check_mtree_alloc_rrange(struct maple_tree *mt, ++static noinline void __init check_mtree_alloc_rrange(struct maple_tree *mt, + unsigned long start, unsigned long end, unsigned long size, + unsigned long expected, int eret, void *ptr) + { +@@ -112,8 +112,8 @@ static noinline void check_mtree_alloc_rrange(struct maple_tree *mt, + } + #endif + +-static noinline void check_load(struct maple_tree *mt, unsigned long index, +- void *ptr) ++static noinline void __init check_load(struct maple_tree *mt, ++ unsigned long index, void *ptr) + { + void *ret = mtree_test_load(mt, index); + +@@ -122,7 +122,7 @@ static noinline void check_load(struct maple_tree *mt, unsigned long index, + MT_BUG_ON(mt, ret != ptr); + } + +-static noinline void check_store_range(struct maple_tree *mt, ++static noinline void __init check_store_range(struct maple_tree *mt, + unsigned long start, unsigned long end, void *ptr, int expected) + { + int ret = -EINVAL; +@@ -138,7 +138,7 @@ static noinline void check_store_range(struct maple_tree *mt, + check_load(mt, i, ptr); + } + +-static noinline void check_insert_range(struct maple_tree *mt, ++static noinline void __init check_insert_range(struct maple_tree *mt, + unsigned long start, unsigned long end, void *ptr, int expected) + { + int ret = -EINVAL; +@@ -154,8 +154,8 @@ static noinline void check_insert_range(struct maple_tree *mt, + check_load(mt, i, ptr); + } + +-static noinline void check_insert(struct maple_tree *mt, unsigned long index, +- void *ptr) ++static noinline void __init check_insert(struct maple_tree *mt, ++ unsigned long index, void *ptr) + { + int ret = -EINVAL; + +@@ -163,7 +163,7 @@ static noinline void check_insert(struct maple_tree *mt, unsigned long index, + MT_BUG_ON(mt, ret != 0); + } + +-static noinline void check_dup_insert(struct maple_tree *mt, ++static noinline void __init check_dup_insert(struct maple_tree *mt, + unsigned long index, void *ptr) + { + int ret = -EINVAL; +@@ -173,13 +173,13 @@ static noinline void check_dup_insert(struct maple_tree *mt, + } + + +-static noinline +-void check_index_load(struct maple_tree *mt, unsigned long index) ++static noinline void __init check_index_load(struct maple_tree *mt, ++ unsigned long index) + { + return check_load(mt, index, xa_mk_value(index & LONG_MAX)); + } + +-static inline int not_empty(struct maple_node *node) ++static inline __init int not_empty(struct maple_node *node) + { + int i; + +@@ -194,8 +194,8 @@ static inline int not_empty(struct maple_node *node) + } + + +-static noinline void check_rev_seq(struct maple_tree *mt, unsigned long max, +- bool verbose) ++static noinline void __init check_rev_seq(struct maple_tree *mt, ++ unsigned long max, bool verbose) + { + unsigned long i = max, j; + +@@ -227,7 +227,7 @@ static noinline void check_rev_seq(struct maple_tree *mt, unsigned long max, + #endif + } + +-static noinline void check_seq(struct maple_tree *mt, unsigned long max, ++static noinline void __init check_seq(struct maple_tree *mt, unsigned long max, + bool verbose) + { + unsigned long i, j; +@@ -256,7 +256,7 @@ static noinline void check_seq(struct maple_tree *mt, unsigned long max, + #endif + } + +-static noinline void check_lb_not_empty(struct maple_tree *mt) ++static noinline void __init check_lb_not_empty(struct maple_tree *mt) + { + unsigned long i, j; + unsigned long huge = 4000UL * 1000 * 1000; +@@ -275,13 +275,13 @@ static noinline void check_lb_not_empty(struct maple_tree *mt) + mtree_destroy(mt); + } + +-static noinline void check_lower_bound_split(struct maple_tree *mt) ++static noinline void __init check_lower_bound_split(struct maple_tree *mt) + { + MT_BUG_ON(mt, !mtree_empty(mt)); + check_lb_not_empty(mt); + } + +-static noinline void check_upper_bound_split(struct maple_tree *mt) ++static noinline void __init check_upper_bound_split(struct maple_tree *mt) + { + unsigned long i, j; + unsigned long huge; +@@ -306,7 +306,7 @@ static noinline void check_upper_bound_split(struct maple_tree *mt) + mtree_destroy(mt); + } + +-static noinline void check_mid_split(struct maple_tree *mt) ++static noinline void __init check_mid_split(struct maple_tree *mt) + { + unsigned long huge = 8000UL * 1000 * 1000; + +@@ -315,7 +315,7 @@ static noinline void check_mid_split(struct maple_tree *mt) + check_lb_not_empty(mt); + } + +-static noinline void check_rev_find(struct maple_tree *mt) ++static noinline void __init check_rev_find(struct maple_tree *mt) + { + int i, nr_entries = 200; + void *val; +@@ -354,7 +354,7 @@ static noinline void check_rev_find(struct maple_tree *mt) + rcu_read_unlock(); + } + +-static noinline void check_find(struct maple_tree *mt) ++static noinline void __init check_find(struct maple_tree *mt) + { + unsigned long val = 0; + unsigned long count; +@@ -571,7 +571,7 @@ static noinline void check_find(struct maple_tree *mt) + mtree_destroy(mt); + } + +-static noinline void check_find_2(struct maple_tree *mt) ++static noinline void __init check_find_2(struct maple_tree *mt) + { + unsigned long i, j; + void *entry; +@@ -616,7 +616,7 @@ static noinline void check_find_2(struct maple_tree *mt) + + + #if defined(CONFIG_64BIT) +-static noinline void check_alloc_rev_range(struct maple_tree *mt) ++static noinline void __init check_alloc_rev_range(struct maple_tree *mt) + { + /* + * Generated by: +@@ -624,7 +624,7 @@ static noinline void check_alloc_rev_range(struct maple_tree *mt) + * awk -F "-" '{printf "0x%s, 0x%s, ", $1, $2}' + */ + +- unsigned long range[] = { ++ static const unsigned long range[] = { + /* Inclusive , Exclusive. */ + 0x565234af2000, 0x565234af4000, + 0x565234af4000, 0x565234af9000, +@@ -652,7 +652,7 @@ static noinline void check_alloc_rev_range(struct maple_tree *mt) + 0x7fff58791000, 0x7fff58793000, + }; + +- unsigned long holes[] = { ++ static const unsigned long holes[] = { + /* + * Note: start of hole is INCLUSIVE + * end of hole is EXCLUSIVE +@@ -672,7 +672,7 @@ static noinline void check_alloc_rev_range(struct maple_tree *mt) + * 4. number that should be returned. + * 5. return value + */ +- unsigned long req_range[] = { ++ static const unsigned long req_range[] = { + 0x565234af9000, /* Min */ + 0x7fff58791000, /* Max */ + 0x1000, /* Size */ +@@ -783,7 +783,7 @@ static noinline void check_alloc_rev_range(struct maple_tree *mt) + mtree_destroy(mt); + } + +-static noinline void check_alloc_range(struct maple_tree *mt) ++static noinline void __init check_alloc_range(struct maple_tree *mt) + { + /* + * Generated by: +@@ -791,7 +791,7 @@ static noinline void check_alloc_range(struct maple_tree *mt) + * awk -F "-" '{printf "0x%s, 0x%s, ", $1, $2}' + */ + +- unsigned long range[] = { ++ static const unsigned long range[] = { + /* Inclusive , Exclusive. */ + 0x565234af2000, 0x565234af4000, + 0x565234af4000, 0x565234af9000, +@@ -818,7 +818,7 @@ static noinline void check_alloc_range(struct maple_tree *mt) + 0x7fff5878e000, 0x7fff58791000, + 0x7fff58791000, 0x7fff58793000, + }; +- unsigned long holes[] = { ++ static const unsigned long holes[] = { + /* Start of hole, end of hole, size of hole (+1) */ + 0x565234afb000, 0x565234afc000, 0x1000, + 0x565234afe000, 0x565235def000, 0x12F1000, +@@ -833,7 +833,7 @@ static noinline void check_alloc_range(struct maple_tree *mt) + * 4. number that should be returned. + * 5. return value + */ +- unsigned long req_range[] = { ++ static const unsigned long req_range[] = { + 0x565234af9000, /* Min */ + 0x7fff58791000, /* Max */ + 0x1000, /* Size */ +@@ -942,10 +942,10 @@ static noinline void check_alloc_range(struct maple_tree *mt) + } + #endif + +-static noinline void check_ranges(struct maple_tree *mt) ++static noinline void __init check_ranges(struct maple_tree *mt) + { + int i, val, val2; +- unsigned long r[] = { ++ static const unsigned long r[] = { + 10, 15, + 20, 25, + 17, 22, /* Overlaps previous range. */ +@@ -1210,7 +1210,7 @@ static noinline void check_ranges(struct maple_tree *mt) + MT_BUG_ON(mt, mt_height(mt) != 4); + } + +-static noinline void check_next_entry(struct maple_tree *mt) ++static noinline void __init check_next_entry(struct maple_tree *mt) + { + void *entry = NULL; + unsigned long limit = 30, i = 0; +@@ -1234,7 +1234,7 @@ static noinline void check_next_entry(struct maple_tree *mt) + mtree_destroy(mt); + } + +-static noinline void check_prev_entry(struct maple_tree *mt) ++static noinline void __init check_prev_entry(struct maple_tree *mt) + { + unsigned long index = 16; + void *value; +@@ -1278,7 +1278,7 @@ static noinline void check_prev_entry(struct maple_tree *mt) + mas_unlock(&mas); + } + +-static noinline void check_root_expand(struct maple_tree *mt) ++static noinline void __init check_root_expand(struct maple_tree *mt) + { + MA_STATE(mas, mt, 0, 0); + void *ptr; +@@ -1367,13 +1367,13 @@ static noinline void check_root_expand(struct maple_tree *mt) + mas_unlock(&mas); + } + +-static noinline void check_gap_combining(struct maple_tree *mt) ++static noinline void __init check_gap_combining(struct maple_tree *mt) + { + struct maple_enode *mn1, *mn2; + void *entry; + unsigned long singletons = 100; +- unsigned long *seq100; +- unsigned long seq100_64[] = { ++ static const unsigned long *seq100; ++ static const unsigned long seq100_64[] = { + /* 0-5 */ + 74, 75, 76, + 50, 100, 2, +@@ -1387,7 +1387,7 @@ static noinline void check_gap_combining(struct maple_tree *mt) + 76, 2, 79, 85, 4, + }; + +- unsigned long seq100_32[] = { ++ static const unsigned long seq100_32[] = { + /* 0-5 */ + 61, 62, 63, + 50, 100, 2, +@@ -1401,11 +1401,11 @@ static noinline void check_gap_combining(struct maple_tree *mt) + 76, 2, 79, 85, 4, + }; + +- unsigned long seq2000[] = { ++ static const unsigned long seq2000[] = { + 1152, 1151, + 1100, 1200, 2, + }; +- unsigned long seq400[] = { ++ static const unsigned long seq400[] = { + 286, 318, + 256, 260, 266, 270, 275, 280, 290, 398, + 286, 310, +@@ -1564,7 +1564,7 @@ static noinline void check_gap_combining(struct maple_tree *mt) + mt_set_non_kernel(0); + mtree_destroy(mt); + } +-static noinline void check_node_overwrite(struct maple_tree *mt) ++static noinline void __init check_node_overwrite(struct maple_tree *mt) + { + int i, max = 4000; + +@@ -1577,7 +1577,7 @@ static noinline void check_node_overwrite(struct maple_tree *mt) + } + + #if defined(BENCH_SLOT_STORE) +-static noinline void bench_slot_store(struct maple_tree *mt) ++static noinline void __init bench_slot_store(struct maple_tree *mt) + { + int i, brk = 105, max = 1040, brk_start = 100, count = 20000000; + +@@ -1593,7 +1593,7 @@ static noinline void bench_slot_store(struct maple_tree *mt) + #endif + + #if defined(BENCH_NODE_STORE) +-static noinline void bench_node_store(struct maple_tree *mt) ++static noinline void __init bench_node_store(struct maple_tree *mt) + { + int i, overwrite = 76, max = 240, count = 20000000; + +@@ -1612,7 +1612,7 @@ static noinline void bench_node_store(struct maple_tree *mt) + #endif + + #if defined(BENCH_AWALK) +-static noinline void bench_awalk(struct maple_tree *mt) ++static noinline void __init bench_awalk(struct maple_tree *mt) + { + int i, max = 2500, count = 50000000; + MA_STATE(mas, mt, 1470, 1470); +@@ -1629,7 +1629,7 @@ static noinline void bench_awalk(struct maple_tree *mt) + } + #endif + #if defined(BENCH_WALK) +-static noinline void bench_walk(struct maple_tree *mt) ++static noinline void __init bench_walk(struct maple_tree *mt) + { + int i, max = 2500, count = 550000000; + MA_STATE(mas, mt, 1470, 1470); +@@ -1646,7 +1646,7 @@ static noinline void bench_walk(struct maple_tree *mt) + #endif + + #if defined(BENCH_MT_FOR_EACH) +-static noinline void bench_mt_for_each(struct maple_tree *mt) ++static noinline void __init bench_mt_for_each(struct maple_tree *mt) + { + int i, count = 1000000; + unsigned long max = 2500, index = 0; +@@ -1670,7 +1670,7 @@ static noinline void bench_mt_for_each(struct maple_tree *mt) + #endif + + /* check_forking - simulate the kernel forking sequence with the tree. */ +-static noinline void check_forking(struct maple_tree *mt) ++static noinline void __init check_forking(struct maple_tree *mt) + { + + struct maple_tree newmt; +@@ -1709,7 +1709,7 @@ static noinline void check_forking(struct maple_tree *mt) + mtree_destroy(&newmt); + } + +-static noinline void check_iteration(struct maple_tree *mt) ++static noinline void __init check_iteration(struct maple_tree *mt) + { + int i, nr_entries = 125; + void *val; +@@ -1777,7 +1777,7 @@ static noinline void check_iteration(struct maple_tree *mt) + mt_set_non_kernel(0); + } + +-static noinline void check_mas_store_gfp(struct maple_tree *mt) ++static noinline void __init check_mas_store_gfp(struct maple_tree *mt) + { + + struct maple_tree newmt; +@@ -1810,7 +1810,7 @@ static noinline void check_mas_store_gfp(struct maple_tree *mt) + } + + #if defined(BENCH_FORK) +-static noinline void bench_forking(struct maple_tree *mt) ++static noinline void __init bench_forking(struct maple_tree *mt) + { + + struct maple_tree newmt; +@@ -1852,15 +1852,17 @@ static noinline void bench_forking(struct maple_tree *mt) + } + #endif + +-static noinline void next_prev_test(struct maple_tree *mt) ++static noinline void __init next_prev_test(struct maple_tree *mt) + { + int i, nr_entries; + void *val; + MA_STATE(mas, mt, 0, 0); + struct maple_enode *mn; +- unsigned long *level2; +- unsigned long level2_64[] = {707, 1000, 710, 715, 720, 725}; +- unsigned long level2_32[] = {1747, 2000, 1750, 1755, 1760, 1765}; ++ static const unsigned long *level2; ++ static const unsigned long level2_64[] = { 707, 1000, 710, 715, 720, ++ 725}; ++ static const unsigned long level2_32[] = { 1747, 2000, 1750, 1755, ++ 1760, 1765}; + + if (MAPLE_32BIT) { + nr_entries = 500; +@@ -2028,7 +2030,7 @@ static noinline void next_prev_test(struct maple_tree *mt) + + + /* Test spanning writes that require balancing right sibling or right cousin */ +-static noinline void check_spanning_relatives(struct maple_tree *mt) ++static noinline void __init check_spanning_relatives(struct maple_tree *mt) + { + + unsigned long i, nr_entries = 1000; +@@ -2041,7 +2043,7 @@ static noinline void check_spanning_relatives(struct maple_tree *mt) + mtree_store_range(mt, 9365, 9955, NULL, GFP_KERNEL); + } + +-static noinline void check_fuzzer(struct maple_tree *mt) ++static noinline void __init check_fuzzer(struct maple_tree *mt) + { + /* + * 1. Causes a spanning rebalance of a single root node. +@@ -2438,7 +2440,7 @@ static noinline void check_fuzzer(struct maple_tree *mt) + } + + /* duplicate the tree with a specific gap */ +-static noinline void check_dup_gaps(struct maple_tree *mt, ++static noinline void __init check_dup_gaps(struct maple_tree *mt, + unsigned long nr_entries, bool zero_start, + unsigned long gap) + { +@@ -2478,7 +2480,7 @@ static noinline void check_dup_gaps(struct maple_tree *mt, + } + + /* Duplicate many sizes of trees. Mainly to test expected entry values */ +-static noinline void check_dup(struct maple_tree *mt) ++static noinline void __init check_dup(struct maple_tree *mt) + { + int i; + int big_start = 100010; +@@ -2566,7 +2568,7 @@ static noinline void check_dup(struct maple_tree *mt) + } + } + +-static noinline void check_bnode_min_spanning(struct maple_tree *mt) ++static noinline void __init check_bnode_min_spanning(struct maple_tree *mt) + { + int i = 50; + MA_STATE(mas, mt, 0, 0); +@@ -2585,7 +2587,7 @@ static noinline void check_bnode_min_spanning(struct maple_tree *mt) + mt_set_non_kernel(0); + } + +-static noinline void check_empty_area_window(struct maple_tree *mt) ++static noinline void __init check_empty_area_window(struct maple_tree *mt) + { + unsigned long i, nr_entries = 20; + MA_STATE(mas, mt, 0, 0); +@@ -2670,7 +2672,7 @@ static noinline void check_empty_area_window(struct maple_tree *mt) + rcu_read_unlock(); + } + +-static noinline void check_empty_area_fill(struct maple_tree *mt) ++static noinline void __init check_empty_area_fill(struct maple_tree *mt) + { + const unsigned long max = 0x25D78000; + unsigned long size; +@@ -2714,11 +2716,11 @@ static noinline void check_empty_area_fill(struct maple_tree *mt) + } + + static DEFINE_MTREE(tree); +-static int maple_tree_seed(void) ++static int __init maple_tree_seed(void) + { +- unsigned long set[] = {5015, 5014, 5017, 25, 1000, +- 1001, 1002, 1003, 1005, 0, +- 5003, 5002}; ++ unsigned long set[] = { 5015, 5014, 5017, 25, 1000, ++ 1001, 1002, 1003, 1005, 0, ++ 5003, 5002}; + void *ptr = &set; + + pr_info("\nTEST STARTING\n\n"); +@@ -2988,7 +2990,7 @@ static int maple_tree_seed(void) + return -EINVAL; + } + +-static void maple_tree_harvest(void) ++static void __exit maple_tree_harvest(void) + { + + } +diff --git a/tools/testing/radix-tree/linux/init.h b/tools/testing/radix-tree/linux/init.h +index 1bb0afc213099..81563c3dfce79 100644 +--- a/tools/testing/radix-tree/linux/init.h ++++ b/tools/testing/radix-tree/linux/init.h +@@ -1 +1,2 @@ + #define __init ++#define __exit +diff --git a/tools/testing/radix-tree/maple.c b/tools/testing/radix-tree/maple.c +index d1ab5f23f4e4c..cd96a3ee7bb89 100644 +--- a/tools/testing/radix-tree/maple.c ++++ b/tools/testing/radix-tree/maple.c +@@ -13,6 +13,7 @@ + #include "test.h" + #include + #include ++#include "linux/init.h" + + #define module_init(x) + #define module_exit(x) +@@ -58,7 +59,7 @@ struct rcu_reader_struct { + * check_new_node() - Check the creation of new nodes and error path + * verification. + */ +-static noinline void check_new_node(struct maple_tree *mt) ++static noinline void __init check_new_node(struct maple_tree *mt) + { + + struct maple_node *mn, *mn2, *mn3; +@@ -430,7 +431,7 @@ static noinline void check_new_node(struct maple_tree *mt) + /* + * Check erasing including RCU. + */ +-static noinline void check_erase(struct maple_tree *mt, unsigned long index, ++static noinline void __init check_erase(struct maple_tree *mt, unsigned long index, + void *ptr) + { + MT_BUG_ON(mt, mtree_test_erase(mt, index) != ptr); +@@ -440,24 +441,24 @@ static noinline void check_erase(struct maple_tree *mt, unsigned long index, + #define erase_check_insert(mt, i) check_insert(mt, set[i], entry[i%2]) + #define erase_check_erase(mt, i) check_erase(mt, set[i], entry[i%2]) + +-static noinline void check_erase_testset(struct maple_tree *mt) ++static noinline void __init check_erase_testset(struct maple_tree *mt) + { +- unsigned long set[] = { 5015, 5014, 5017, 25, 1000, +- 1001, 1002, 1003, 1005, 0, +- 6003, 6002, 6008, 6012, 6015, +- 7003, 7002, 7008, 7012, 7015, +- 8003, 8002, 8008, 8012, 8015, +- 9003, 9002, 9008, 9012, 9015, +- 10003, 10002, 10008, 10012, 10015, +- 11003, 11002, 11008, 11012, 11015, +- 12003, 12002, 12008, 12012, 12015, +- 13003, 13002, 13008, 13012, 13015, +- 14003, 14002, 14008, 14012, 14015, +- 15003, 15002, 15008, 15012, 15015, +- }; +- +- +- void *ptr = &set; ++ static const unsigned long set[] = { 5015, 5014, 5017, 25, 1000, ++ 1001, 1002, 1003, 1005, 0, ++ 6003, 6002, 6008, 6012, 6015, ++ 7003, 7002, 7008, 7012, 7015, ++ 8003, 8002, 8008, 8012, 8015, ++ 9003, 9002, 9008, 9012, 9015, ++ 10003, 10002, 10008, 10012, 10015, ++ 11003, 11002, 11008, 11012, 11015, ++ 12003, 12002, 12008, 12012, 12015, ++ 13003, 13002, 13008, 13012, 13015, ++ 14003, 14002, 14008, 14012, 14015, ++ 15003, 15002, 15008, 15012, 15015, ++ }; ++ ++ ++ void *ptr = &check_erase_testset; + void *entry[2] = { ptr, mt }; + void *root_node; + +@@ -714,7 +715,7 @@ static noinline void check_erase_testset(struct maple_tree *mt) + int mas_ce2_over_count(struct ma_state *mas_start, struct ma_state *mas_end, + void *s_entry, unsigned long s_min, + void *e_entry, unsigned long e_max, +- unsigned long *set, int i, bool null_entry) ++ const unsigned long *set, int i, bool null_entry) + { + int count = 0, span = 0; + unsigned long retry = 0; +@@ -944,8 +945,8 @@ static inline void *mas_range_load(struct ma_state *mas, + } + + #if defined(CONFIG_64BIT) +-static noinline void check_erase2_testset(struct maple_tree *mt, +- unsigned long *set, unsigned long size) ++static noinline void __init check_erase2_testset(struct maple_tree *mt, ++ const unsigned long *set, unsigned long size) + { + int entry_count = 0; + int check = 0; +@@ -1089,11 +1090,11 @@ static noinline void check_erase2_testset(struct maple_tree *mt, + + + /* These tests were pulled from KVM tree modifications which failed. */ +-static noinline void check_erase2_sets(struct maple_tree *mt) ++static noinline void __init check_erase2_sets(struct maple_tree *mt) + { + void *entry; + unsigned long start = 0; +- unsigned long set[] = { ++ static const unsigned long set[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140721266458624, 140737488351231, + ERASE, 140721266458624, 140737488351231, +@@ -1111,7 +1112,7 @@ ERASE, 140253902692352, 140253902864383, + STORE, 140253902692352, 140253902696447, + STORE, 140253902696448, 140253902864383, + }; +- unsigned long set2[] = { ++ static const unsigned long set2[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140735933583360, 140737488351231, + ERASE, 140735933583360, 140737488351231, +@@ -1135,7 +1136,7 @@ STORE, 140277094813696, 140277094821887, + STORE, 140277094821888, 140277094825983, + STORE, 140735933906944, 140735933911039, + }; +- unsigned long set3[] = { ++ static const unsigned long set3[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140735790264320, 140737488351231, + ERASE, 140735790264320, 140737488351231, +@@ -1178,7 +1179,7 @@ STORE, 47135835840512, 47135835885567, + STORE, 47135835885568, 47135835893759, + }; + +- unsigned long set4[] = { ++ static const unsigned long set4[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140728251703296, 140737488351231, + ERASE, 140728251703296, 140737488351231, +@@ -1199,7 +1200,7 @@ ERASE, 47646523277312, 47646523445247, + STORE, 47646523277312, 47646523400191, + }; + +- unsigned long set5[] = { ++ static const unsigned long set5[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140726874062848, 140737488351231, + ERASE, 140726874062848, 140737488351231, +@@ -1332,7 +1333,7 @@ STORE, 47884791619584, 47884791623679, + STORE, 47884791623680, 47884791627775, + }; + +- unsigned long set6[] = { ++ static const unsigned long set6[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140722999021568, 140737488351231, + ERASE, 140722999021568, 140737488351231, +@@ -1464,7 +1465,7 @@ ERASE, 47430432014336, 47430432022527, + STORE, 47430432014336, 47430432018431, + STORE, 47430432018432, 47430432022527, + }; +- unsigned long set7[] = { ++ static const unsigned long set7[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140729808330752, 140737488351231, + ERASE, 140729808330752, 140737488351231, +@@ -1596,7 +1597,7 @@ ERASE, 47439987130368, 47439987138559, + STORE, 47439987130368, 47439987134463, + STORE, 47439987134464, 47439987138559, + }; +- unsigned long set8[] = { ++ static const unsigned long set8[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140722482974720, 140737488351231, + ERASE, 140722482974720, 140737488351231, +@@ -1729,7 +1730,7 @@ STORE, 47708488638464, 47708488642559, + STORE, 47708488642560, 47708488646655, + }; + +- unsigned long set9[] = { ++ static const unsigned long set9[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140736427839488, 140737488351231, + ERASE, 140736427839488, 140736427839488, +@@ -5595,7 +5596,7 @@ ERASE, 47906195480576, 47906195480576, + STORE, 94641242615808, 94641242750975, + }; + +- unsigned long set10[] = { ++ static const unsigned long set10[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140736427839488, 140737488351231, + ERASE, 140736427839488, 140736427839488, +@@ -9459,7 +9460,7 @@ STORE, 139726599680000, 139726599684095, + ERASE, 47906195480576, 47906195480576, + STORE, 94641242615808, 94641242750975, + }; +- unsigned long set11[] = { ++ static const unsigned long set11[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140732658499584, 140737488351231, + ERASE, 140732658499584, 140732658499584, +@@ -9485,7 +9486,7 @@ STORE, 140732658565120, 140732658569215, + STORE, 140732658552832, 140732658565119, + }; + +- unsigned long set12[] = { /* contains 12 values. */ ++ static const unsigned long set12[] = { /* contains 12 values. */ + STORE, 140737488347136, 140737488351231, + STORE, 140732658499584, 140737488351231, + ERASE, 140732658499584, 140732658499584, +@@ -9512,7 +9513,7 @@ STORE, 140732658552832, 140732658565119, + STORE, 140014592741375, 140014592741375, /* contrived */ + STORE, 140014592733184, 140014592741376, /* creates first entry retry. */ + }; +- unsigned long set13[] = { ++ static const unsigned long set13[] = { + STORE, 140373516247040, 140373516251135,/*: ffffa2e7b0e10d80 */ + STORE, 140373516251136, 140373516255231,/*: ffffa2e7b1195d80 */ + STORE, 140373516255232, 140373516443647,/*: ffffa2e7b0e109c0 */ +@@ -9525,7 +9526,7 @@ STORE, 140373518684160, 140373518688254,/*: ffffa2e7b05fec00 */ + STORE, 140373518688256, 140373518692351,/*: ffffa2e7bfbdcd80 */ + STORE, 140373518692352, 140373518696447,/*: ffffa2e7b0749e40 */ + }; +- unsigned long set14[] = { ++ static const unsigned long set14[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140731667996672, 140737488351231, + SNULL, 140731668000767, 140737488351231, +@@ -9809,7 +9810,7 @@ SNULL, 139826136543232, 139826136809471, + STORE, 139826136809472, 139826136842239, + STORE, 139826136543232, 139826136809471, + }; +- unsigned long set15[] = { ++ static const unsigned long set15[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140722061451264, 140737488351231, + SNULL, 140722061455359, 140737488351231, +@@ -10094,7 +10095,7 @@ STORE, 139906808958976, 139906808991743, + STORE, 139906808692736, 139906808958975, + }; + +- unsigned long set16[] = { ++ static const unsigned long set16[] = { + STORE, 94174808662016, 94174809321471, + STORE, 94174811414528, 94174811426815, + STORE, 94174811426816, 94174811430911, +@@ -10305,7 +10306,7 @@ STORE, 139921865613312, 139921865617407, + STORE, 139921865547776, 139921865564159, + }; + +- unsigned long set17[] = { ++ static const unsigned long set17[] = { + STORE, 94397057224704, 94397057646591, + STORE, 94397057650688, 94397057691647, + STORE, 94397057691648, 94397057695743, +@@ -10367,7 +10368,7 @@ STORE, 140720477511680, 140720477646847, + STORE, 140720478302208, 140720478314495, + STORE, 140720478314496, 140720478318591, + }; +- unsigned long set18[] = { ++ static const unsigned long set18[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140724953673728, 140737488351231, + SNULL, 140724953677823, 140737488351231, +@@ -10400,7 +10401,7 @@ STORE, 140222970597376, 140222970605567, + ERASE, 140222970597376, 140222970605567, + STORE, 140222970597376, 140222970605567, + }; +- unsigned long set19[] = { ++ static const unsigned long set19[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140725182459904, 140737488351231, + SNULL, 140725182463999, 140737488351231, +@@ -10669,7 +10670,7 @@ STORE, 140656836775936, 140656836780031, + STORE, 140656787476480, 140656791920639, + ERASE, 140656774639616, 140656779083775, + }; +- unsigned long set20[] = { ++ static const unsigned long set20[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140735952392192, 140737488351231, + SNULL, 140735952396287, 140737488351231, +@@ -10825,7 +10826,7 @@ STORE, 140590386819072, 140590386823167, + STORE, 140590386823168, 140590386827263, + SNULL, 140590376591359, 140590376595455, + }; +- unsigned long set21[] = { ++ static const unsigned long set21[] = { + STORE, 93874710941696, 93874711363583, + STORE, 93874711367680, 93874711408639, + STORE, 93874711408640, 93874711412735, +@@ -10895,7 +10896,7 @@ ERASE, 140708393312256, 140708393316351, + ERASE, 140708393308160, 140708393312255, + ERASE, 140708393291776, 140708393308159, + }; +- unsigned long set22[] = { ++ static const unsigned long set22[] = { + STORE, 93951397134336, 93951397183487, + STORE, 93951397183488, 93951397728255, + STORE, 93951397728256, 93951397826559, +@@ -11022,7 +11023,7 @@ STORE, 140551361253376, 140551361519615, + ERASE, 140551361253376, 140551361519615, + }; + +- unsigned long set23[] = { ++ static const unsigned long set23[] = { + STORE, 94014447943680, 94014448156671, + STORE, 94014450253824, 94014450257919, + STORE, 94014450257920, 94014450266111, +@@ -14346,7 +14347,7 @@ SNULL, 140175956627455, 140175985139711, + STORE, 140175927242752, 140175956627455, + STORE, 140175956627456, 140175985139711, + }; +- unsigned long set24[] = { ++ static const unsigned long set24[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140735281639424, 140737488351231, + SNULL, 140735281643519, 140737488351231, +@@ -15508,7 +15509,7 @@ ERASE, 139635393024000, 139635401412607, + ERASE, 139635384627200, 139635384631295, + ERASE, 139635384631296, 139635393019903, + }; +- unsigned long set25[] = { ++ static const unsigned long set25[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140737488343040, 140737488351231, + STORE, 140722547441664, 140737488351231, +@@ -22296,7 +22297,7 @@ STORE, 140249652703232, 140249682087935, + STORE, 140249682087936, 140249710600191, + }; + +- unsigned long set26[] = { ++ static const unsigned long set26[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140729464770560, 140737488351231, + SNULL, 140729464774655, 140737488351231, +@@ -22320,7 +22321,7 @@ ERASE, 140109040951296, 140109040959487, + STORE, 140109040955392, 140109040959487, + ERASE, 140109040955392, 140109040959487, + }; +- unsigned long set27[] = { ++ static const unsigned long set27[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140726128070656, 140737488351231, + SNULL, 140726128074751, 140737488351231, +@@ -22716,7 +22717,7 @@ STORE, 140415509696512, 140415535910911, + ERASE, 140415537422336, 140415562588159, + STORE, 140415482433536, 140415509696511, + }; +- unsigned long set28[] = { ++ static const unsigned long set28[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140722475622400, 140737488351231, + SNULL, 140722475626495, 140737488351231, +@@ -22784,7 +22785,7 @@ STORE, 139918413348864, 139918413352959, + ERASE, 139918413316096, 139918413344767, + STORE, 93865848528896, 93865848664063, + }; +- unsigned long set29[] = { ++ static const unsigned long set29[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140734467944448, 140737488351231, + SNULL, 140734467948543, 140737488351231, +@@ -23659,7 +23660,7 @@ ERASE, 140143079972864, 140143088361471, + ERASE, 140143205793792, 140143205797887, + ERASE, 140143205797888, 140143214186495, + }; +- unsigned long set30[] = { ++ static const unsigned long set30[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140733436743680, 140737488351231, + SNULL, 140733436747775, 140737488351231, +@@ -24541,7 +24542,7 @@ ERASE, 140165225893888, 140165225897983, + ERASE, 140165225897984, 140165234286591, + ERASE, 140165058105344, 140165058109439, + }; +- unsigned long set31[] = { ++ static const unsigned long set31[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140730890784768, 140737488351231, + SNULL, 140730890788863, 140737488351231, +@@ -25354,7 +25355,7 @@ ERASE, 140623906590720, 140623914979327, + ERASE, 140622950277120, 140622950281215, + ERASE, 140622950281216, 140622958669823, + }; +- unsigned long set32[] = { ++ static const unsigned long set32[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140731244212224, 140737488351231, + SNULL, 140731244216319, 140737488351231, +@@ -26150,7 +26151,7 @@ ERASE, 140400417288192, 140400425676799, + ERASE, 140400283066368, 140400283070463, + ERASE, 140400283070464, 140400291459071, + }; +- unsigned long set33[] = { ++ static const unsigned long set33[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140734562918400, 140737488351231, + SNULL, 140734562922495, 140737488351231, +@@ -26292,7 +26293,7 @@ STORE, 140582961786880, 140583003750399, + ERASE, 140582961786880, 140583003750399, + }; + +- unsigned long set34[] = { ++ static const unsigned long set34[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140731327180800, 140737488351231, + SNULL, 140731327184895, 140737488351231, +@@ -27173,7 +27174,7 @@ ERASE, 140012522094592, 140012530483199, + ERASE, 140012033142784, 140012033146879, + ERASE, 140012033146880, 140012041535487, + }; +- unsigned long set35[] = { ++ static const unsigned long set35[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140730536939520, 140737488351231, + SNULL, 140730536943615, 140737488351231, +@@ -27930,7 +27931,7 @@ ERASE, 140474471936000, 140474480324607, + ERASE, 140474396430336, 140474396434431, + ERASE, 140474396434432, 140474404823039, + }; +- unsigned long set36[] = { ++ static const unsigned long set36[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140723893125120, 140737488351231, + SNULL, 140723893129215, 140737488351231, +@@ -28791,7 +28792,7 @@ ERASE, 140121890357248, 140121898745855, + ERASE, 140121269587968, 140121269592063, + ERASE, 140121269592064, 140121277980671, + }; +- unsigned long set37[] = { ++ static const unsigned long set37[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140722404016128, 140737488351231, + SNULL, 140722404020223, 140737488351231, +@@ -28917,7 +28918,7 @@ STORE, 139759821246464, 139759888355327, + ERASE, 139759821246464, 139759888355327, + ERASE, 139759888355328, 139759955464191, + }; +- unsigned long set38[] = { ++ static const unsigned long set38[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140730666221568, 140737488351231, + SNULL, 140730666225663, 140737488351231, +@@ -29727,7 +29728,7 @@ ERASE, 140613504712704, 140613504716799, + ERASE, 140613504716800, 140613513105407, + }; + +- unsigned long set39[] = { ++ static const unsigned long set39[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140736271417344, 140737488351231, + SNULL, 140736271421439, 140737488351231, +@@ -30099,7 +30100,7 @@ STORE, 140325364428800, 140325372821503, + STORE, 140325356036096, 140325364428799, + SNULL, 140325364432895, 140325372821503, + }; +- unsigned long set40[] = { ++ static const unsigned long set40[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140734309167104, 140737488351231, + SNULL, 140734309171199, 140737488351231, +@@ -30850,7 +30851,7 @@ ERASE, 140320289300480, 140320289304575, + ERASE, 140320289304576, 140320297693183, + ERASE, 140320163409920, 140320163414015, + }; +- unsigned long set41[] = { ++ static const unsigned long set41[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140728157171712, 140737488351231, + SNULL, 140728157175807, 140737488351231, +@@ -31160,7 +31161,7 @@ STORE, 94376135090176, 94376135094271, + STORE, 94376135094272, 94376135098367, + SNULL, 94376135094272, 94377208836095, + }; +- unsigned long set42[] = { ++ static const unsigned long set42[] = { + STORE, 314572800, 1388314623, + STORE, 1462157312, 1462169599, + STORE, 1462169600, 1462185983, +@@ -33837,7 +33838,7 @@ SNULL, 3798999040, 3799101439, + */ + }; + +- unsigned long set43[] = { ++ static const unsigned long set43[] = { + STORE, 140737488347136, 140737488351231, + STORE, 140734187720704, 140737488351231, + SNULL, 140734187724800, 140737488351231, +@@ -34971,7 +34972,7 @@ void run_check_rcu_slowread(struct maple_tree *mt, struct rcu_test_struct *vals) + MT_BUG_ON(mt, !vals->seen_entry3); + MT_BUG_ON(mt, !vals->seen_both); + } +-static noinline void check_rcu_simulated(struct maple_tree *mt) ++static noinline void __init check_rcu_simulated(struct maple_tree *mt) + { + unsigned long i, nr_entries = 1000; + unsigned long target = 4320; +@@ -35132,7 +35133,7 @@ static noinline void check_rcu_simulated(struct maple_tree *mt) + rcu_unregister_thread(); + } + +-static noinline void check_rcu_threaded(struct maple_tree *mt) ++static noinline void __init check_rcu_threaded(struct maple_tree *mt) + { + unsigned long i, nr_entries = 1000; + struct rcu_test_struct vals; +@@ -35341,7 +35342,7 @@ static void check_dfs_preorder(struct maple_tree *mt) + /* End of depth first search tests */ + + /* Preallocation testing */ +-static noinline void check_prealloc(struct maple_tree *mt) ++static noinline void __init check_prealloc(struct maple_tree *mt) + { + unsigned long i, max = 100; + unsigned long allocated; +@@ -35469,7 +35470,7 @@ static noinline void check_prealloc(struct maple_tree *mt) + /* End of preallocation testing */ + + /* Spanning writes, writes that span nodes and layers of the tree */ +-static noinline void check_spanning_write(struct maple_tree *mt) ++static noinline void __init check_spanning_write(struct maple_tree *mt) + { + unsigned long i, max = 5000; + MA_STATE(mas, mt, 1200, 2380); +@@ -35637,7 +35638,7 @@ static noinline void check_spanning_write(struct maple_tree *mt) + /* End of spanning write testing */ + + /* Writes to a NULL area that are adjacent to other NULLs */ +-static noinline void check_null_expand(struct maple_tree *mt) ++static noinline void __init check_null_expand(struct maple_tree *mt) + { + unsigned long i, max = 100; + unsigned char data_end; +@@ -35698,7 +35699,7 @@ static noinline void check_null_expand(struct maple_tree *mt) + /* End of NULL area expansions */ + + /* Checking for no memory is best done outside the kernel */ +-static noinline void check_nomem(struct maple_tree *mt) ++static noinline void __init check_nomem(struct maple_tree *mt) + { + MA_STATE(ms, mt, 1, 1); + +@@ -35733,7 +35734,7 @@ static noinline void check_nomem(struct maple_tree *mt) + mtree_destroy(mt); + } + +-static noinline void check_locky(struct maple_tree *mt) ++static noinline void __init check_locky(struct maple_tree *mt) + { + MA_STATE(ms, mt, 2, 2); + MA_STATE(reader, mt, 2, 2); +-- +2.39.2 + diff --git a/queue-6.1/maple_tree-fix-32-bit-mas_next-testing.patch b/queue-6.1/maple_tree-fix-32-bit-mas_next-testing.patch new file mode 100644 index 00000000000..a24956e1a52 --- /dev/null +++ b/queue-6.1/maple_tree-fix-32-bit-mas_next-testing.patch @@ -0,0 +1,62 @@ +From d650f4d3fb494487e315e028161beb0c7227cbd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Jul 2023 13:39:15 -0400 +Subject: maple_tree: fix 32 bit mas_next testing + +From: Liam R. Howlett + +[ Upstream commit 7a93c71a6714ca1a9c03d70432dac104b0cfb815 ] + +The test setup of mas_next is dependent on node entry size to create a 2 +level tree, but the tests did not account for this in the expected value +when shifting beyond the scope of the tree. + +Fix this by setting up the test to succeed depending on the node entries +which is dependent on the 32/64 bit setup. + +Link: https://lkml.kernel.org/r/20230712173916.168805-1-Liam.Howlett@oracle.com +Fixes: 120b116208a0 ("maple_tree: reorganize testing to restore module testing") +Signed-off-by: Liam R. Howlett +Reported-by: Geert Uytterhoeven + Closes: https://lore.kernel.org/linux-mm/CAMuHMdV4T53fOw7VPoBgPR7fP6RYqf=CBhD_y_vOg53zZX_DnA@mail.gmail.com/ +Tested-by: Geert Uytterhoeven +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + lib/test_maple_tree.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/lib/test_maple_tree.c b/lib/test_maple_tree.c +index 261bad680f81d..fad668042f3e7 100644 +--- a/lib/test_maple_tree.c ++++ b/lib/test_maple_tree.c +@@ -1863,13 +1863,16 @@ static noinline void __init next_prev_test(struct maple_tree *mt) + 725}; + static const unsigned long level2_32[] = { 1747, 2000, 1750, 1755, + 1760, 1765}; ++ unsigned long last_index; + + if (MAPLE_32BIT) { + nr_entries = 500; + level2 = level2_32; ++ last_index = 0x138e; + } else { + nr_entries = 200; + level2 = level2_64; ++ last_index = 0x7d6; + } + + for (i = 0; i <= nr_entries; i++) +@@ -1976,7 +1979,7 @@ static noinline void __init next_prev_test(struct maple_tree *mt) + + val = mas_next(&mas, ULONG_MAX); + MT_BUG_ON(mt, val != NULL); +- MT_BUG_ON(mt, mas.index != ULONG_MAX); ++ MT_BUG_ON(mt, mas.index != last_index); + MT_BUG_ON(mt, mas.last != ULONG_MAX); + + val = mas_prev(&mas, 0); +-- +2.39.2 + diff --git a/queue-6.1/mips-loongson-fix-build-error-when-make-modules_inst.patch b/queue-6.1/mips-loongson-fix-build-error-when-make-modules_inst.patch new file mode 100644 index 00000000000..f9e9b313fd3 --- /dev/null +++ b/queue-6.1/mips-loongson-fix-build-error-when-make-modules_inst.patch @@ -0,0 +1,75 @@ +From 54d5cfc029cd677f65031d4bde4a177435b03366 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Jun 2023 19:08:47 +0800 +Subject: MIPS: Loongson: Fix build error when make modules_install + +From: Huacai Chen + +[ Upstream commit 531b3d1195d096f14e030c4b01ec3a53b80276bf ] + +After commit 0e96ea5c3eb5904e5dc2f ("MIPS: Loongson64: Clean up use of +cc-ifversion") we get a build error when make modules_install: + +cc1: error: '-mloongson-mmi' must be used with '-mhard-float' + +The reason is when make modules_install, 'call cc-option' doesn't work +in $(KBUILD_CFLAGS) of 'CHECKFLAGS'. Then there is no -mno-loongson-mmi +applied and -march=loongson3a enable MMI instructions. + +To be detail, the error message comes from the CHECKFLAGS invocation of +$(CC) but it has no impact on the final result of make modules_install, +it is purely a cosmetic issue. The error occurs because cc-option is +defined in scripts/Makefile.compiler, which is not included in Makefile +when running 'make modules_install', as install targets are not supposed +to require the compiler; see commit 805b2e1d427aab4b ("kbuild: include +Makefile.compiler only when compiler is needed"). As a result, the call +to check for '-mno-loongson-mmi' just never happens. + +Fix this by partially reverting to the old logic, use 'call cc-option' +to conditionally apply -march=loongson3a and -march=mips64r2. + +By the way, Loongson-2E/2F is also broken in commit 13ceb48bc19c563e05f4 +("MIPS: Loongson2ef: Remove unnecessary {as,cc}-option calls") so fix it +together. + +Fixes: 13ceb48bc19c563e05f4 ("MIPS: Loongson2ef: Remove unnecessary {as,cc}-option calls") +Fixes: 0e96ea5c3eb5904e5dc2 ("MIPS: Loongson64: Clean up use of cc-ifversion") +Cc: stable@vger.kernel.org +Cc: Feiyang Chen +Cc: Nathan Chancellor +Cc: Nick Desaulniers +Signed-off-by: Huacai Chen +Reviewed-by: Nathan Chancellor +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/Makefile | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/arch/mips/Makefile b/arch/mips/Makefile +index ca457f19f7fe0..fe64ad43ba882 100644 +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -190,16 +190,12 @@ endif + cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1 + cflags-$(CONFIG_CPU_BMIPS) += -march=mips32 -Wa,-mips32 -Wa,--trap + +-cflags-$(CONFIG_CPU_LOONGSON2E) += -march=loongson2e -Wa,--trap +-cflags-$(CONFIG_CPU_LOONGSON2F) += -march=loongson2f -Wa,--trap ++cflags-$(CONFIG_CPU_LOONGSON2E) += $(call cc-option,-march=loongson2e) -Wa,--trap ++cflags-$(CONFIG_CPU_LOONGSON2F) += $(call cc-option,-march=loongson2f) -Wa,--trap ++cflags-$(CONFIG_CPU_LOONGSON64) += $(call cc-option,-march=loongson3a,-march=mips64r2) -Wa,--trap + # Some -march= flags enable MMI instructions, and GCC complains about that + # support being enabled alongside -msoft-float. Thus explicitly disable MMI. + cflags-$(CONFIG_CPU_LOONGSON2EF) += $(call cc-option,-mno-loongson-mmi) +-ifdef CONFIG_CPU_LOONGSON64 +-cflags-$(CONFIG_CPU_LOONGSON64) += -Wa,--trap +-cflags-$(CONFIG_CC_IS_GCC) += -march=loongson3a +-cflags-$(CONFIG_CC_IS_CLANG) += -march=mips64r2 +-endif + cflags-$(CONFIG_CPU_LOONGSON64) += $(call cc-option,-mno-loongson-mmi) + + cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,) +-- +2.39.2 + diff --git a/queue-6.1/mips-loongson-move-arch-cflags-to-mips-top-level-mak.patch b/queue-6.1/mips-loongson-move-arch-cflags-to-mips-top-level-mak.patch new file mode 100644 index 00000000000..93b19dc3470 --- /dev/null +++ b/queue-6.1/mips-loongson-move-arch-cflags-to-mips-top-level-mak.patch @@ -0,0 +1,146 @@ +From 3ab187b9e6b8f79e31a15d3fc5332a244400de1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Apr 2023 10:33:47 +0100 +Subject: MIPS: Loongson: Move arch cflags to MIPS top level Makefile + +From: Jiaxun Yang + +[ Upstream commit 194a835210521282ad31e8f7047556318611f596 ] + +Arch cflags should be independent to Platform. + +Signed-off-by: Jiaxun Yang +Signed-off-by: Thomas Bogendoerfer +Stable-dep-of: 531b3d1195d0 ("MIPS: Loongson: Fix build error when make modules_install") +Signed-off-by: Sasha Levin +--- + arch/mips/Makefile | 38 ++++++++++++++++++++++++++++++++++ + arch/mips/loongson2ef/Platform | 35 ------------------------------- + arch/mips/loongson64/Platform | 16 -------------- + 3 files changed, 38 insertions(+), 51 deletions(-) + +diff --git a/arch/mips/Makefile b/arch/mips/Makefile +index 85d3c3b4b7bdc..ca457f19f7fe0 100644 +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -190,9 +190,47 @@ endif + cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1 + cflags-$(CONFIG_CPU_BMIPS) += -march=mips32 -Wa,-mips32 -Wa,--trap + ++cflags-$(CONFIG_CPU_LOONGSON2E) += -march=loongson2e -Wa,--trap ++cflags-$(CONFIG_CPU_LOONGSON2F) += -march=loongson2f -Wa,--trap ++# Some -march= flags enable MMI instructions, and GCC complains about that ++# support being enabled alongside -msoft-float. Thus explicitly disable MMI. ++cflags-$(CONFIG_CPU_LOONGSON2EF) += $(call cc-option,-mno-loongson-mmi) ++ifdef CONFIG_CPU_LOONGSON64 ++cflags-$(CONFIG_CPU_LOONGSON64) += -Wa,--trap ++cflags-$(CONFIG_CC_IS_GCC) += -march=loongson3a ++cflags-$(CONFIG_CC_IS_CLANG) += -march=mips64r2 ++endif ++cflags-$(CONFIG_CPU_LOONGSON64) += $(call cc-option,-mno-loongson-mmi) ++ + cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,) + cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,) + cflags-$(CONFIG_CPU_DADDI_WORKAROUNDS) += $(call cc-option,-mno-daddi,) ++ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS ++cflags-$(CONFIG_CPU_NOP_WORKAROUNDS) += -Wa,-mfix-loongson2f-nop ++cflags-$(CONFIG_CPU_JUMP_WORKAROUNDS) += -Wa,-mfix-loongson2f-jump ++endif ++ ++# ++# Some versions of binutils, not currently mainline as of 2019/02/04, support ++# an -mfix-loongson3-llsc flag which emits a sync prior to each ll instruction ++# to work around a CPU bug (see __SYNC_loongson3_war in asm/sync.h for a ++# description). ++# ++# We disable this in order to prevent the assembler meddling with the ++# instruction that labels refer to, ie. if we label an ll instruction: ++# ++# 1: ll v0, 0(a0) ++# ++# ...then with the assembler fix applied the label may actually point at a sync ++# instruction inserted by the assembler, and if we were using the label in an ++# exception table the table would no longer contain the address of the ll ++# instruction. ++# ++# Avoid this by explicitly disabling that assembler behaviour. If upstream ++# binutils does not merge support for the flag then we can revisit & remove ++# this later - for now it ensures vendor toolchains don't cause problems. ++# ++cflags-$(CONFIG_CPU_LOONGSON64) += $(call as-option,-Wa$(comma)-mno-fix-loongson3-llsc,) + + # For smartmips configurations, there are hundreds of warnings due to ISA overrides + # in assembly and header files. smartmips is only supported for MIPS32r1 onwards +diff --git a/arch/mips/loongson2ef/Platform b/arch/mips/loongson2ef/Platform +index c6f7a4b959978..d446b705fba47 100644 +--- a/arch/mips/loongson2ef/Platform ++++ b/arch/mips/loongson2ef/Platform +@@ -2,41 +2,6 @@ + # Loongson Processors' Support + # + +-cflags-$(CONFIG_CPU_LOONGSON2EF) += -Wa,--trap +-cflags-$(CONFIG_CPU_LOONGSON2E) += -march=loongson2e +-cflags-$(CONFIG_CPU_LOONGSON2F) += -march=loongson2f +-# +-# Some versions of binutils, not currently mainline as of 2019/02/04, support +-# an -mfix-loongson3-llsc flag which emits a sync prior to each ll instruction +-# to work around a CPU bug (see __SYNC_loongson3_war in asm/sync.h for a +-# description). +-# +-# We disable this in order to prevent the assembler meddling with the +-# instruction that labels refer to, ie. if we label an ll instruction: +-# +-# 1: ll v0, 0(a0) +-# +-# ...then with the assembler fix applied the label may actually point at a sync +-# instruction inserted by the assembler, and if we were using the label in an +-# exception table the table would no longer contain the address of the ll +-# instruction. +-# +-# Avoid this by explicitly disabling that assembler behaviour. If upstream +-# binutils does not merge support for the flag then we can revisit & remove +-# this later - for now it ensures vendor toolchains don't cause problems. +-# +-cflags-$(CONFIG_CPU_LOONGSON2EF) += $(call cc-option,-Wa$(comma)-mno-fix-loongson3-llsc,) +- +-# Enable the workarounds for Loongson2f +-ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS +-cflags-$(CONFIG_CPU_NOP_WORKAROUNDS) += -Wa,-mfix-loongson2f-nop +-cflags-$(CONFIG_CPU_JUMP_WORKAROUNDS) += -Wa,-mfix-loongson2f-jump +-endif +- +-# Some -march= flags enable MMI instructions, and GCC complains about that +-# support being enabled alongside -msoft-float. Thus explicitly disable MMI. +-cflags-y += $(call cc-option,-mno-loongson-mmi) +- + # + # Loongson Machines' Support + # +diff --git a/arch/mips/loongson64/Platform b/arch/mips/loongson64/Platform +index 473404cae1c44..49c9889e3d563 100644 +--- a/arch/mips/loongson64/Platform ++++ b/arch/mips/loongson64/Platform +@@ -1,19 +1,3 @@ +-# +-# Loongson Processors' Support +-# +- +- +-cflags-$(CONFIG_CPU_LOONGSON64) += -Wa,--trap +- +-ifdef CONFIG_CPU_LOONGSON64 +-cflags-$(CONFIG_CC_IS_GCC) += -march=loongson3a +-cflags-$(CONFIG_CC_IS_CLANG) += -march=mips64r2 +-endif +- +-# Some -march= flags enable MMI instructions, and GCC complains about that +-# support being enabled alongside -msoft-float. Thus explicitly disable MMI. +-cflags-y += $(call cc-option,-mno-loongson-mmi) +- + # + # Loongson Machines' Support + # +-- +2.39.2 + diff --git a/queue-6.1/mptcp-do-not-rely-on-implicit-state-check-in-mptcp_l.patch b/queue-6.1/mptcp-do-not-rely-on-implicit-state-check-in-mptcp_l.patch new file mode 100644 index 00000000000..b6be4d0aff5 --- /dev/null +++ b/queue-6.1/mptcp-do-not-rely-on-implicit-state-check-in-mptcp_l.patch @@ -0,0 +1,60 @@ +From 07ac84cfbb62721380cca3bd9b5be0c4281e59ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jul 2023 22:44:34 +0200 +Subject: mptcp: do not rely on implicit state check in mptcp_listen() + +From: Paolo Abeni + +[ Upstream commit 0226436acf2495cde4b93e7400e5a87305c26054 ] + +Since the blamed commit, closing the first subflow resets the first +subflow socket state to SS_UNCONNECTED. + +The current mptcp listen implementation relies only on such +state to prevent touching not-fully-disconnected sockets. + +Incoming mptcp fastclose (or paired endpoint removal) unconditionally +closes the first subflow. + +All the above allows an incoming fastclose followed by a listen() call +to successfully race with a blocking recvmsg(), potentially causing the +latter to hit a divide by zero bug in cleanup_rbuf/__tcp_select_window(). + +Address the issue explicitly checking the msk socket state in +mptcp_listen(). An alternative solution would be moving the first +subflow socket state update into mptcp_disconnect(), but in the long +term the first subflow socket should be removed: better avoid relaying +on it for internal consistency check. + +Fixes: b29fcfb54cd7 ("mptcp: full disconnect implementation") +Cc: stable@vger.kernel.org +Reported-by: Christoph Paasch +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/414 +Signed-off-by: Paolo Abeni +Reviewed-by: Matthieu Baerts +Signed-off-by: Matthieu Baerts +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/mptcp/protocol.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index 208da9a9909c2..37ff6766fd526 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -3753,6 +3753,11 @@ static int mptcp_listen(struct socket *sock, int backlog) + pr_debug("msk=%p", msk); + + lock_sock(sk); ++ ++ err = -EINVAL; ++ if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM) ++ goto unlock; ++ + ssock = __mptcp_nmpc_socket(msk); + if (!ssock) { + err = -EINVAL; +-- +2.39.2 + diff --git a/queue-6.1/mptcp-introduce-sk-to-replace-sock-sk-in-mptcp_liste.patch b/queue-6.1/mptcp-introduce-sk-to-replace-sock-sk-in-mptcp_liste.patch new file mode 100644 index 00000000000..383bf8239e5 --- /dev/null +++ b/queue-6.1/mptcp-introduce-sk-to-replace-sock-sk-in-mptcp_liste.patch @@ -0,0 +1,66 @@ +From 3ee3877812262cf4e97cac8ecf4088abdd83b250 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Jan 2023 10:57:20 -0800 +Subject: mptcp: introduce 'sk' to replace 'sock->sk' in mptcp_listen() + +From: Menglong Dong + +[ Upstream commit cfdcfeed6449d702825d249cb85346ecf56236fc ] + +'sock->sk' is used frequently in mptcp_listen(). Therefore, we can +introduce the 'sk' and replace 'sock->sk' with it. + +Acked-by: Paolo Abeni +Signed-off-by: Menglong Dong +Signed-off-by: Mat Martineau +Signed-off-by: David S. Miller +Stable-dep-of: 0226436acf24 ("mptcp: do not rely on implicit state check in mptcp_listen()") +Signed-off-by: Sasha Levin +--- + net/mptcp/protocol.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index 4ca61e80f4bb2..208da9a9909c2 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -3746,12 +3746,13 @@ static int mptcp_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) + static int mptcp_listen(struct socket *sock, int backlog) + { + struct mptcp_sock *msk = mptcp_sk(sock->sk); ++ struct sock *sk = sock->sk; + struct socket *ssock; + int err; + + pr_debug("msk=%p", msk); + +- lock_sock(sock->sk); ++ lock_sock(sk); + ssock = __mptcp_nmpc_socket(msk); + if (!ssock) { + err = -EINVAL; +@@ -3759,16 +3760,16 @@ static int mptcp_listen(struct socket *sock, int backlog) + } + + mptcp_token_destroy(msk); +- inet_sk_state_store(sock->sk, TCP_LISTEN); +- sock_set_flag(sock->sk, SOCK_RCU_FREE); ++ inet_sk_state_store(sk, TCP_LISTEN); ++ sock_set_flag(sk, SOCK_RCU_FREE); + + err = ssock->ops->listen(ssock, backlog); +- inet_sk_state_store(sock->sk, inet_sk_state_load(ssock->sk)); ++ inet_sk_state_store(sk, inet_sk_state_load(ssock->sk)); + if (!err) +- mptcp_copy_inaddrs(sock->sk, ssock->sk); ++ mptcp_copy_inaddrs(sk, ssock->sk); + + unlock: +- release_sock(sock->sk); ++ release_sock(sk); + return err; + } + +-- +2.39.2 + diff --git a/queue-6.1/n_tty-rename-tail-to-old_tail-in-n_tty_read.patch b/queue-6.1/n_tty-rename-tail-to-old_tail-in-n_tty_read.patch new file mode 100644 index 00000000000..f84a23e5b19 --- /dev/null +++ b/queue-6.1/n_tty-rename-tail-to-old_tail-in-n_tty_read.patch @@ -0,0 +1,60 @@ +From 70ca5d0f3e30d10e739672853e4e9dcaf123e2a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 16:25:02 +0200 +Subject: n_tty: Rename tail to old_tail in n_tty_read() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 947d66b68f3c4e7cf8f3f3500807b9d2a0de28ce ] + +The local tail variable in n_tty_read() is used for one purpose, it +keeps the old tail. Thus, rename it appropriately to improve code +readability. + +Signed-off-by: Ilpo Järvinen +Reviewed-by: Jiri Slaby +Link: https://lore.kernel.org/r/22b37499-ff9a-7fc1-f6e0-58411328d122@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 4903fde8047a ("tty: fix hang on tty device with no_room set") +Signed-off-by: Sasha Levin +--- + drivers/tty/n_tty.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 597019690ae62..c8f56c9b1a1c8 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -2130,7 +2130,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, + ssize_t retval = 0; + long timeout; + bool packet; +- size_t tail; ++ size_t old_tail; + + /* + * Is this a continuation of a read started earler? +@@ -2193,7 +2193,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, + } + + packet = tty->ctrl.packet; +- tail = ldata->read_tail; ++ old_tail = ldata->read_tail; + + add_wait_queue(&tty->read_wait, &wait); + while (nr) { +@@ -2282,7 +2282,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, + if (time) + timeout = time; + } +- if (tail != ldata->read_tail) ++ if (old_tail != ldata->read_tail) + n_tty_kick_worker(tty); + up_read(&tty->termios_rwsem); + +-- +2.39.2 + diff --git a/queue-6.1/pci-aspm-avoid-link-retraining-race.patch b/queue-6.1/pci-aspm-avoid-link-retraining-race.patch new file mode 100644 index 00000000000..39f9acd7259 --- /dev/null +++ b/queue-6.1/pci-aspm-avoid-link-retraining-race.patch @@ -0,0 +1,64 @@ +From a21b55e0babbdd7552c35a62c909c6392a749bb1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 May 2023 11:39:23 +0300 +Subject: PCI/ASPM: Avoid link retraining race +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit e7e39756363ad5bd83ddeae1063193d0f13870fd ] + +PCIe r6.0.1, sec 7.5.3.7, recommends setting the link control parameters, +then waiting for the Link Training bit to be clear before setting the +Retrain Link bit. + +This avoids a race where the LTSSM may not use the updated parameters if it +is already in the midst of link training because of other normal link +activity. + +Wait for the Link Training bit to be clear before toggling the Retrain Link +bit to ensure that the LTSSM uses the updated link control parameters. + +[bhelgaas: commit log, return 0 (success)/-ETIMEDOUT instead of bool for +both pcie_wait_for_retrain() and the existing pcie_retrain_link()] +Suggested-by: Lukas Wunner +Fixes: 7d715a6c1ae5 ("PCI: add PCI Express ASPM support") +Link: https://lore.kernel.org/r/20230502083923.34562-1-ilpo.jarvinen@linux.intel.com +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Reviewed-by: Lukas Wunner +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/aspm.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index f6b91252bebc2..07166a4ec27ad 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -213,8 +213,19 @@ static int pcie_wait_for_retrain(struct pci_dev *pdev) + static int pcie_retrain_link(struct pcie_link_state *link) + { + struct pci_dev *parent = link->pdev; ++ int rc; + u16 reg16; + ++ /* ++ * Ensure the updated LNKCTL parameters are used during link ++ * training by checking that there is no ongoing link training to ++ * avoid LTSSM race as recommended in Implementation Note at the ++ * end of PCIe r6.0.1 sec 7.5.3.7. ++ */ ++ rc = pcie_wait_for_retrain(parent); ++ if (rc) ++ return rc; ++ + pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); + reg16 |= PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); +-- +2.39.2 + diff --git a/queue-6.1/pci-aspm-factor-out-pcie_wait_for_retrain.patch b/queue-6.1/pci-aspm-factor-out-pcie_wait_for_retrain.patch new file mode 100644 index 00000000000..00fb895b6f1 --- /dev/null +++ b/queue-6.1/pci-aspm-factor-out-pcie_wait_for_retrain.patch @@ -0,0 +1,79 @@ +From cdab9306ee0388e9c438dd815e47561c0710420f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Jun 2023 14:49:33 -0500 +Subject: PCI/ASPM: Factor out pcie_wait_for_retrain() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 9c7f136433d26592cb4d9cd00b4e15c33d9797c6 ] + +Factor pcie_wait_for_retrain() out from pcie_retrain_link(). No functional +change intended. + +[bhelgaas: split out from +https: //lore.kernel.org/r/20230502083923.34562-1-ilpo.jarvinen@linux.intel.com] +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Stable-dep-of: e7e39756363a ("PCI/ASPM: Avoid link retraining race") +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/aspm.c | 30 ++++++++++++++++++------------ + 1 file changed, 18 insertions(+), 12 deletions(-) + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index 96e7031a3b56f..f6b91252bebc2 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -193,10 +193,26 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) + link->clkpm_disable = blacklist ? 1 : 0; + } + ++static int pcie_wait_for_retrain(struct pci_dev *pdev) ++{ ++ unsigned long end_jiffies; ++ u16 reg16; ++ ++ /* Wait for Link Training to be cleared by hardware */ ++ end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; ++ do { ++ pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, ®16); ++ if (!(reg16 & PCI_EXP_LNKSTA_LT)) ++ return 0; ++ msleep(1); ++ } while (time_before(jiffies, end_jiffies)); ++ ++ return -ETIMEDOUT; ++} ++ + static int pcie_retrain_link(struct pcie_link_state *link) + { + struct pci_dev *parent = link->pdev; +- unsigned long end_jiffies; + u16 reg16; + + pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); +@@ -212,17 +228,7 @@ static int pcie_retrain_link(struct pcie_link_state *link) + pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); + } + +- /* Wait for link training end. Break out after waiting for timeout */ +- end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; +- do { +- pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); +- if (!(reg16 & PCI_EXP_LNKSTA_LT)) +- break; +- msleep(1); +- } while (time_before(jiffies, end_jiffies)); +- if (reg16 & PCI_EXP_LNKSTA_LT) +- return -ETIMEDOUT; +- return 0; ++ return pcie_wait_for_retrain(parent); + } + + /* +-- +2.39.2 + diff --git a/queue-6.1/pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch b/queue-6.1/pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch new file mode 100644 index 00000000000..5bb87b01b7d --- /dev/null +++ b/queue-6.1/pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch @@ -0,0 +1,72 @@ +From 573a17f54e442153ae8efba3f21a9a6d375a9020 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Jun 2023 14:44:55 -0500 +Subject: PCI/ASPM: Return 0 or -ETIMEDOUT from pcie_retrain_link() + +From: Bjorn Helgaas + +[ Upstream commit f5297a01ee805d7fa569d288ed65fc0f9ac9b03d ] + +"pcie_retrain_link" is not a question with a true/false answer, so "bool" +isn't quite the right return type. Return 0 for success or -ETIMEDOUT if +the retrain failed. No functional change intended. + +[bhelgaas: based on Ilpo's patch below] +Link: https://lore.kernel.org/r/20230502083923.34562-1-ilpo.jarvinen@linux.intel.com +Signed-off-by: Bjorn Helgaas +Stable-dep-of: e7e39756363a ("PCI/ASPM: Avoid link retraining race") +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/aspm.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index 74b8183c305df..96e7031a3b56f 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -193,7 +193,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) + link->clkpm_disable = blacklist ? 1 : 0; + } + +-static bool pcie_retrain_link(struct pcie_link_state *link) ++static int pcie_retrain_link(struct pcie_link_state *link) + { + struct pci_dev *parent = link->pdev; + unsigned long end_jiffies; +@@ -220,7 +220,9 @@ static bool pcie_retrain_link(struct pcie_link_state *link) + break; + msleep(1); + } while (time_before(jiffies, end_jiffies)); +- return !(reg16 & PCI_EXP_LNKSTA_LT); ++ if (reg16 & PCI_EXP_LNKSTA_LT) ++ return -ETIMEDOUT; ++ return 0; + } + + /* +@@ -289,15 +291,15 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) + reg16 &= ~PCI_EXP_LNKCTL_CCC; + pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); + +- if (pcie_retrain_link(link)) +- return; ++ if (pcie_retrain_link(link)) { + +- /* Training failed. Restore common clock configurations */ +- pci_err(parent, "ASPM: Could not configure common clock\n"); +- list_for_each_entry(child, &linkbus->devices, bus_list) +- pcie_capability_write_word(child, PCI_EXP_LNKCTL, ++ /* Training failed. Restore common clock configurations */ ++ pci_err(parent, "ASPM: Could not configure common clock\n"); ++ list_for_each_entry(child, &linkbus->devices, bus_list) ++ pcie_capability_write_word(child, PCI_EXP_LNKCTL, + child_reg[PCI_FUNC(child->devfn)]); +- pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); ++ pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); ++ } + } + + /* Convert L0s latency encoding to ns */ +-- +2.39.2 + diff --git a/queue-6.1/pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch b/queue-6.1/pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch new file mode 100644 index 00000000000..4014cf81a2a --- /dev/null +++ b/queue-6.1/pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch @@ -0,0 +1,103 @@ +From 39ddd3b7581fff5dab5a7abd8af41a54903addcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Apr 2023 09:46:57 +0200 +Subject: PCI: rockchip: Don't advertise MSI-X in PCIe capabilities + +From: Rick Wertenbroek + +[ Upstream commit a52587e0bee14cbeeadf48a24013828cb04b8df8 ] + +The RK3399 PCIe endpoint controller cannot generate MSI-X IRQs. +This is documented in the RK3399 technical reference manual (TRM) +section 17.5.9 "Interrupt Support". + +MSI-X capability should therefore not be advertised. Remove the +MSI-X capability by editing the capability linked-list. The +previous entry is the MSI capability, therefore get the next +entry from the MSI-X capability entry and set it as next entry +for the MSI capability. This in effect removes MSI-X from the list. + +Linked list before : MSI cap -> MSI-X cap -> PCIe Device cap -> ... +Linked list now : MSI cap -> PCIe Device cap -> ... + +Link: https://lore.kernel.org/r/20230418074700.1083505-11-rick.wertenbroek@gmail.com +Fixes: cf590b078391 ("PCI: rockchip: Add EP driver for Rockchip PCIe controller") +Tested-by: Damien Le Moal +Signed-off-by: Rick Wertenbroek +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Damien Le Moal +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-rockchip-ep.c | 24 +++++++++++++++++++++++ + drivers/pci/controller/pcie-rockchip.h | 5 +++++ + 2 files changed, 29 insertions(+) + +diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c +index 3d6f828d29fc2..0af0e965fb57e 100644 +--- a/drivers/pci/controller/pcie-rockchip-ep.c ++++ b/drivers/pci/controller/pcie-rockchip-ep.c +@@ -508,6 +508,7 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) + size_t max_regions; + struct pci_epc_mem_window *windows = NULL; + int err, i; ++ u32 cfg_msi, cfg_msix_cp; + + ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); + if (!ep) +@@ -583,6 +584,29 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) + + ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR; + ++ /* ++ * MSI-X is not supported but the controller still advertises the MSI-X ++ * capability by default, which can lead to the Root Complex side ++ * allocating MSI-X vectors which cannot be used. Avoid this by skipping ++ * the MSI-X capability entry in the PCIe capabilities linked-list: get ++ * the next pointer from the MSI-X entry and set that in the MSI ++ * capability entry (which is the previous entry). This way the MSI-X ++ * entry is skipped (left out of the linked-list) and not advertised. ++ */ ++ cfg_msi = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + ++ ROCKCHIP_PCIE_EP_MSI_CTRL_REG); ++ ++ cfg_msi &= ~ROCKCHIP_PCIE_EP_MSI_CP1_MASK; ++ ++ cfg_msix_cp = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + ++ ROCKCHIP_PCIE_EP_MSIX_CAP_REG) & ++ ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK; ++ ++ cfg_msi |= cfg_msix_cp; ++ ++ rockchip_pcie_write(rockchip, cfg_msi, ++ PCIE_EP_CONFIG_BASE + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); ++ + rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE, + PCIE_CLIENT_CONFIG); + +diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h +index 501d859420b4c..fe0333778fd93 100644 +--- a/drivers/pci/controller/pcie-rockchip.h ++++ b/drivers/pci/controller/pcie-rockchip.h +@@ -227,6 +227,8 @@ + #define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4 + #define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19) + #define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90 ++#define ROCKCHIP_PCIE_EP_MSI_CP1_OFFSET 8 ++#define ROCKCHIP_PCIE_EP_MSI_CP1_MASK GENMASK(15, 8) + #define ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET 16 + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17 + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17) +@@ -234,6 +236,9 @@ + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK GENMASK(22, 20) + #define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16) + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24) ++#define ROCKCHIP_PCIE_EP_MSIX_CAP_REG 0xb0 ++#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_OFFSET 8 ++#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK GENMASK(15, 8) + #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 + #define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3 + #define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) \ +-- +2.39.2 + diff --git a/queue-6.1/pci-rockchip-fix-window-mapping-and-address-translat.patch b/queue-6.1/pci-rockchip-fix-window-mapping-and-address-translat.patch new file mode 100644 index 00000000000..c4863c469a7 --- /dev/null +++ b/queue-6.1/pci-rockchip-fix-window-mapping-and-address-translat.patch @@ -0,0 +1,340 @@ +From 87f26488d8e5089d8df8a93d3f347d31f62dfd8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Apr 2023 09:46:55 +0200 +Subject: PCI: rockchip: Fix window mapping and address translation for + endpoint + +From: Rick Wertenbroek + +[ Upstream commit dc73ed0f1b8bddd7f2bf70d123e68ffc99ad71ce ] + +The RK3399 PCI endpoint core has 33 windows for PCIe space, now in the +driver up to 32 fixed size (1M) windows are used and pages are allocated +and mapped accordingly. The driver first used a single window and allocated +space inside which caused translation issues (between CPU space and PCI +space) because a window can only have a single translation at a given +time, which if multiple pages are allocated inside will cause conflicts. +Now each window is a single region of 1M which will always guarantee that +the translation is not in conflict. + +Set the translation register addresses for physical function. As documented +in the technical reference manual (TRM) section 17.5.5 "PCIe Address +Translation" and section 17.6.8 "Address Translation Registers Description" + +Link: https://lore.kernel.org/r/20230418074700.1083505-9-rick.wertenbroek@gmail.com +Fixes: cf590b078391 ("PCI: rockchip: Add EP driver for Rockchip PCIe controller") +Tested-by: Damien Le Moal +Signed-off-by: Rick Wertenbroek +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Damien Le Moal +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-rockchip-ep.c | 128 ++++++++++------------ + drivers/pci/controller/pcie-rockchip.h | 35 +++--- + 2 files changed, 75 insertions(+), 88 deletions(-) + +diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c +index 9e17f3dba743a..3d6f828d29fc2 100644 +--- a/drivers/pci/controller/pcie-rockchip-ep.c ++++ b/drivers/pci/controller/pcie-rockchip-ep.c +@@ -64,52 +64,29 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip, + } + + static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, +- u32 r, u32 type, u64 cpu_addr, +- u64 pci_addr, size_t size) ++ u32 r, u64 cpu_addr, u64 pci_addr, ++ size_t size) + { +- u64 sz = 1ULL << fls64(size - 1); +- int num_pass_bits = ilog2(sz); +- u32 addr0, addr1, desc0, desc1; +- bool is_nor_msg = (type == AXI_WRAPPER_NOR_MSG); ++ int num_pass_bits = fls64(size - 1); ++ u32 addr0, addr1, desc0; + +- /* The minimal region size is 1MB */ + if (num_pass_bits < 8) + num_pass_bits = 8; + +- cpu_addr -= rockchip->mem_res->start; +- addr0 = ((is_nor_msg ? 0x10 : (num_pass_bits - 1)) & +- PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | +- (lower_32_bits(cpu_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); +- addr1 = upper_32_bits(is_nor_msg ? cpu_addr : pci_addr); +- desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | type; +- desc1 = 0; +- +- if (is_nor_msg) { +- rockchip_pcie_write(rockchip, 0, +- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); +- rockchip_pcie_write(rockchip, 0, +- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); +- rockchip_pcie_write(rockchip, desc0, +- ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); +- rockchip_pcie_write(rockchip, desc1, +- ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); +- } else { +- /* PCI bus address region */ +- rockchip_pcie_write(rockchip, addr0, +- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); +- rockchip_pcie_write(rockchip, addr1, +- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); +- rockchip_pcie_write(rockchip, desc0, +- ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); +- rockchip_pcie_write(rockchip, desc1, +- ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); +- +- addr0 = +- ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | +- (lower_32_bits(cpu_addr) & +- PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); +- addr1 = upper_32_bits(cpu_addr); +- } ++ addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | ++ (lower_32_bits(pci_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); ++ addr1 = upper_32_bits(pci_addr); ++ desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | AXI_WRAPPER_MEM_WRITE; ++ ++ /* PCI bus address region */ ++ rockchip_pcie_write(rockchip, addr0, ++ ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); ++ rockchip_pcie_write(rockchip, addr1, ++ ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); ++ rockchip_pcie_write(rockchip, desc0, ++ ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); ++ rockchip_pcie_write(rockchip, 0, ++ ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); + } + + static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, +@@ -248,26 +225,20 @@ static void rockchip_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn, u8 vfn, + ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar)); + } + ++static inline u32 rockchip_ob_region(phys_addr_t addr) ++{ ++ return (addr >> ilog2(SZ_1M)) & 0x1f; ++} ++ + static int rockchip_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn, + phys_addr_t addr, u64 pci_addr, + size_t size) + { + struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); + struct rockchip_pcie *pcie = &ep->rockchip; +- u32 r; ++ u32 r = rockchip_ob_region(addr); + +- r = find_first_zero_bit(&ep->ob_region_map, BITS_PER_LONG); +- /* +- * Region 0 is reserved for configuration space and shouldn't +- * be used elsewhere per TRM, so leave it out. +- */ +- if (r >= ep->max_regions - 1) { +- dev_err(&epc->dev, "no free outbound region\n"); +- return -EINVAL; +- } +- +- rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, AXI_WRAPPER_MEM_WRITE, addr, +- pci_addr, size); ++ rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, addr, pci_addr, size); + + set_bit(r, &ep->ob_region_map); + ep->ob_addr[r] = addr; +@@ -282,15 +253,11 @@ static void rockchip_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn, + struct rockchip_pcie *rockchip = &ep->rockchip; + u32 r; + +- for (r = 0; r < ep->max_regions - 1; r++) ++ for (r = 0; r < ep->max_regions; r++) + if (ep->ob_addr[r] == addr) + break; + +- /* +- * Region 0 is reserved for configuration space and shouldn't +- * be used elsewhere per TRM, so leave it out. +- */ +- if (r == ep->max_regions - 1) ++ if (r == ep->max_regions) + return; + + rockchip_pcie_clear_ep_ob_atu(rockchip, r); +@@ -387,7 +354,8 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, + struct rockchip_pcie *rockchip = &ep->rockchip; + u32 flags, mme, data, data_mask; + u8 msi_count; +- u64 pci_addr, pci_addr_mask = 0xff; ++ u64 pci_addr; ++ u32 r; + + /* Check MSI enable bit */ + flags = rockchip_pcie_read(&ep->rockchip, +@@ -421,21 +389,20 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, + ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + + ROCKCHIP_PCIE_EP_MSI_CTRL_REG + + PCI_MSI_ADDRESS_LO); +- pci_addr &= GENMASK_ULL(63, 2); + + /* Set the outbound region if needed. */ +- if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) || ++ if (unlikely(ep->irq_pci_addr != (pci_addr & PCIE_ADDR_MASK) || + ep->irq_pci_fn != fn)) { +- rockchip_pcie_prog_ep_ob_atu(rockchip, fn, ep->max_regions - 1, +- AXI_WRAPPER_MEM_WRITE, ++ r = rockchip_ob_region(ep->irq_phys_addr); ++ rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r, + ep->irq_phys_addr, +- pci_addr & ~pci_addr_mask, +- pci_addr_mask + 1); +- ep->irq_pci_addr = (pci_addr & ~pci_addr_mask); ++ pci_addr & PCIE_ADDR_MASK, ++ ~PCIE_ADDR_MASK + 1); ++ ep->irq_pci_addr = (pci_addr & PCIE_ADDR_MASK); + ep->irq_pci_fn = fn; + } + +- writew(data, ep->irq_cpu_addr + (pci_addr & pci_addr_mask)); ++ writew(data, ep->irq_cpu_addr + (pci_addr & ~PCIE_ADDR_MASK)); + return 0; + } + +@@ -517,6 +484,8 @@ static int rockchip_pcie_parse_ep_dt(struct rockchip_pcie *rockchip, + if (err < 0 || ep->max_regions > MAX_REGION_LIMIT) + ep->max_regions = MAX_REGION_LIMIT; + ++ ep->ob_region_map = 0; ++ + err = of_property_read_u8(dev->of_node, "max-functions", + &ep->epc->max_functions); + if (err < 0) +@@ -537,7 +506,8 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) + struct rockchip_pcie *rockchip; + struct pci_epc *epc; + size_t max_regions; +- int err; ++ struct pci_epc_mem_window *windows = NULL; ++ int err, i; + + ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); + if (!ep) +@@ -584,15 +554,27 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) + /* Only enable function 0 by default */ + rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG); + +- err = pci_epc_mem_init(epc, rockchip->mem_res->start, +- resource_size(rockchip->mem_res), PAGE_SIZE); ++ windows = devm_kcalloc(dev, ep->max_regions, ++ sizeof(struct pci_epc_mem_window), GFP_KERNEL); ++ if (!windows) { ++ err = -ENOMEM; ++ goto err_uninit_port; ++ } ++ for (i = 0; i < ep->max_regions; i++) { ++ windows[i].phys_base = rockchip->mem_res->start + (SZ_1M * i); ++ windows[i].size = SZ_1M; ++ windows[i].page_size = SZ_1M; ++ } ++ err = pci_epc_multi_mem_init(epc, windows, ep->max_regions); ++ devm_kfree(dev, windows); ++ + if (err < 0) { + dev_err(dev, "failed to initialize the memory space\n"); + goto err_uninit_port; + } + + ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr, +- SZ_128K); ++ SZ_1M); + if (!ep->irq_cpu_addr) { + dev_err(dev, "failed to reserve memory space for MSI\n"); + err = -ENOMEM; +diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h +index 8e92dc3339ecc..501d859420b4c 100644 +--- a/drivers/pci/controller/pcie-rockchip.h ++++ b/drivers/pci/controller/pcie-rockchip.h +@@ -139,6 +139,7 @@ + + #define PCIE_RC_RP_ATS_BASE 0x400000 + #define PCIE_RC_CONFIG_NORMAL_BASE 0x800000 ++#define PCIE_EP_PF_CONFIG_REGS_BASE 0x800000 + #define PCIE_RC_CONFIG_BASE 0xa00000 + #define PCIE_EP_CONFIG_BASE 0xa00000 + #define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) +@@ -157,10 +158,11 @@ + #define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274) + #define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20) + ++#define PCIE_ADDR_MASK 0xffffff00 + #define PCIE_CORE_AXI_CONF_BASE 0xc00000 + #define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0) + #define PCIE_CORE_OB_REGION_ADDR0_NUM_BITS 0x3f +-#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR 0xffffff00 ++#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK + #define PCIE_CORE_OB_REGION_ADDR1 (PCIE_CORE_AXI_CONF_BASE + 0x4) + #define PCIE_CORE_OB_REGION_DESC0 (PCIE_CORE_AXI_CONF_BASE + 0x8) + #define PCIE_CORE_OB_REGION_DESC1 (PCIE_CORE_AXI_CONF_BASE + 0xc) +@@ -168,7 +170,7 @@ + #define PCIE_CORE_AXI_INBOUND_BASE 0xc00800 + #define PCIE_RP_IB_ADDR0 (PCIE_CORE_AXI_INBOUND_BASE + 0x0) + #define PCIE_CORE_IB_REGION_ADDR0_NUM_BITS 0x3f +-#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR 0xffffff00 ++#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK + #define PCIE_RP_IB_ADDR1 (PCIE_CORE_AXI_INBOUND_BASE + 0x4) + + /* Size of one AXI Region (not Region 0) */ +@@ -233,13 +235,15 @@ + #define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16) + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24) + #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 +-#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) (((fn) << 12) & GENMASK(19, 12)) ++#define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3 ++#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) \ ++ (PCIE_EP_PF_CONFIG_REGS_BASE + (((fn) << 12) & GENMASK(19, 12))) ++#define ROCKCHIP_PCIE_EP_VIRT_FUNC_BASE(fn) \ ++ (PCIE_EP_PF_CONFIG_REGS_BASE + 0x10000 + (((fn) << 12) & GENMASK(19, 12))) + #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \ +- (PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008) ++ (PCIE_CORE_AXI_CONF_BASE + 0x0828 + (fn) * 0x0040 + (bar) * 0x0008) + #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \ +- (PCIE_RC_RP_ATS_BASE + 0x0844 + (fn) * 0x0040 + (bar) * 0x0008) +-#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x0000 + ((r) & 0x1f) * 0x0020) ++ (PCIE_CORE_AXI_CONF_BASE + 0x082c + (fn) * 0x0040 + (bar) * 0x0008) + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK GENMASK(19, 12) + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) \ + (((devfn) << 12) & \ +@@ -247,20 +251,21 @@ + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK GENMASK(27, 20) + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(bus) \ + (((bus) << 20) & ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK) ++#define PCIE_RC_EP_ATR_OB_REGIONS_1_32 (PCIE_CORE_AXI_CONF_BASE + 0x0020) ++#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \ ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0000 + ((r) & 0x1f) * 0x0020) + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x0004 + ((r) & 0x1f) * 0x0020) ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0004 + ((r) & 0x1f) * 0x0020) + #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID BIT(23) + #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK GENMASK(31, 24) + #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(devfn) \ + (((devfn) << 24) & ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK) + #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x0008 + ((r) & 0x1f) * 0x0020) +-#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x000c + ((r) & 0x1f) * 0x0020) +-#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x0018 + ((r) & 0x1f) * 0x0020) +-#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x001c + ((r) & 0x1f) * 0x0020) ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0008 + ((r) & 0x1f) * 0x0020) ++#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \ ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x000c + ((r) & 0x1f) * 0x0020) ++#define ROCKCHIP_PCIE_AT_OB_REGION_DESC2(r) \ ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0010 + ((r) & 0x1f) * 0x0020) + + #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG0(fn) \ + (PCIE_CORE_CTRL_MGMT_BASE + 0x0240 + (fn) * 0x0008) +-- +2.39.2 + diff --git a/queue-6.1/pci-rockchip-remove-writes-to-unused-registers.patch b/queue-6.1/pci-rockchip-remove-writes-to-unused-registers.patch new file mode 100644 index 00000000000..a7112fab912 --- /dev/null +++ b/queue-6.1/pci-rockchip-remove-writes-to-unused-registers.patch @@ -0,0 +1,55 @@ +From ef042f7fd761e3d021d6e9fcc3664bfa2f359e33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Apr 2023 09:46:48 +0200 +Subject: PCI: rockchip: Remove writes to unused registers + +From: Rick Wertenbroek + +[ Upstream commit 92a9c57c325dd51682d428ba960d961fec3c8a08 ] + +Remove write accesses to registers that are marked "unused" (and +therefore read-only) in the technical reference manual (TRM) +(see RK3399 TRM 17.6.8.1) + +Link: https://lore.kernel.org/r/20230418074700.1083505-2-rick.wertenbroek@gmail.com +Tested-by: Damien Le Moal +Signed-off-by: Rick Wertenbroek +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Damien Le Moal +Stable-dep-of: dc73ed0f1b8b ("PCI: rockchip: Fix window mapping and address translation for endpoint") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-rockchip-ep.c | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c +index 827d91e73efab..9e17f3dba743a 100644 +--- a/drivers/pci/controller/pcie-rockchip-ep.c ++++ b/drivers/pci/controller/pcie-rockchip-ep.c +@@ -61,10 +61,6 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip, + ROCKCHIP_PCIE_AT_OB_REGION_DESC0(region)); + rockchip_pcie_write(rockchip, 0, + ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region)); +- rockchip_pcie_write(rockchip, 0, +- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(region)); +- rockchip_pcie_write(rockchip, 0, +- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(region)); + } + + static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, +@@ -114,12 +110,6 @@ static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, + PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); + addr1 = upper_32_bits(cpu_addr); + } +- +- /* CPU bus address region */ +- rockchip_pcie_write(rockchip, addr0, +- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r)); +- rockchip_pcie_write(rockchip, addr1, +- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r)); + } + + static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, +-- +2.39.2 + diff --git a/queue-6.1/powerpc-pseries-vas-hold-mmap_mutex-after-mmap-lock-.patch b/queue-6.1/powerpc-pseries-vas-hold-mmap_mutex-after-mmap-lock-.patch new file mode 100644 index 00000000000..1a4a64d280f --- /dev/null +++ b/queue-6.1/powerpc-pseries-vas-hold-mmap_mutex-after-mmap-lock-.patch @@ -0,0 +1,88 @@ +From 92eef53a4b8f140cbbda7fb1f9f886145fd8d44d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Jul 2023 03:05:06 -0700 +Subject: powerpc/pseries/vas: Hold mmap_mutex after mmap lock during window + close + +From: Haren Myneni + +[ Upstream commit b59c9dc4d9d47b3c4572d826603fde507055b656 ] + +Commit 8ef7b9e1765a ("powerpc/pseries/vas: Close windows with DLPAR +core removal") unmaps the window paste address and issues HCALL to +close window in the hypervisor for migration or DLPAR core removal +events. So holds mmap_mutex and then mmap lock before unmap the +paste address. But if the user space issue mmap paste address at +the same time with the migration event, coproc_mmap() is called +after holding the mmap lock which can trigger deadlock when trying +to acquire mmap_mutex in coproc_mmap(). + +t1: mmap() call to mmap t2: Migration event + window paste address + +do_mmap2() migration_store() + ksys_mmap_pgoff() pseries_migrate_partition() + vm_mmap_pgoff() vas_migration_handler() + Acquire mmap lock reconfig_close_windows() + do_mmap() lock mmap_mutex + mmap_region() Acquire mmap lock + call_mmap() //Wait for mmap lock + coproc_mmap() unmap vma + lock mmap_mutex update window status + //wait for mmap_mutex Release mmap lock + mmap vma unlock mmap_mutex + update window status + unlock mmap_mutex + ... + Release mmap lock + +Fix this deadlock issue by holding mmap lock first before mmap_mutex +in reconfig_close_windows(). + +Fixes: 8ef7b9e1765a ("powerpc/pseries/vas: Close windows with DLPAR core removal") +Signed-off-by: Haren Myneni +Signed-off-by: Michael Ellerman +Link: https://msgid.link/20230716100506.7833-1-haren@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/pseries/vas.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c +index 880b962afc057..041a25c08066b 100644 +--- a/arch/powerpc/platforms/pseries/vas.c ++++ b/arch/powerpc/platforms/pseries/vas.c +@@ -744,6 +744,12 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds, + } + + task_ref = &win->vas_win.task_ref; ++ /* ++ * VAS mmap (coproc_mmap()) and its fault handler ++ * (vas_mmap_fault()) are called after holding mmap lock. ++ * So hold mmap mutex after mmap_lock to avoid deadlock. ++ */ ++ mmap_write_lock(task_ref->mm); + mutex_lock(&task_ref->mmap_mutex); + vma = task_ref->vma; + /* +@@ -752,7 +758,6 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds, + */ + win->vas_win.status |= flag; + +- mmap_write_lock(task_ref->mm); + /* + * vma is set in the original mapping. But this mapping + * is done with mmap() after the window is opened with ioctl. +@@ -763,8 +768,8 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds, + zap_page_range(vma, vma->vm_start, + vma->vm_end - vma->vm_start); + +- mmap_write_unlock(task_ref->mm); + mutex_unlock(&task_ref->mmap_mutex); ++ mmap_write_unlock(task_ref->mm); + /* + * Close VAS window in the hypervisor, but do not + * free vas_window struct since it may be reused +-- +2.39.2 + diff --git a/queue-6.1/revert-tracing-add-fault-name-injection-to-kernel-pr.patch b/queue-6.1/revert-tracing-add-fault-name-injection-to-kernel-pr.patch new file mode 100644 index 00000000000..bec03ae5507 --- /dev/null +++ b/queue-6.1/revert-tracing-add-fault-name-injection-to-kernel-pr.patch @@ -0,0 +1,135 @@ +From d9f3f3f51b37dea174f11d920827dc2b3657873f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jul 2023 23:15:57 +0900 +Subject: Revert "tracing: Add "(fault)" name injection to kernel probes" + +From: Masami Hiramatsu (Google) + +[ Upstream commit 4ed8f337dee32df71435689c19d22e4ee846e15a ] + +This reverts commit 2e9906f84fc7c99388bb7123ade167250d50f1c0. + +It was turned out that commit 2e9906f84fc7 ("tracing: Add "(fault)" +name injection to kernel probes") did not work correctly and probe +events still show just '(fault)' (instead of '"(fault)"'). Also, +current '(fault)' is more explicit that it faulted. + +This also moves FAULT_STRING macro to trace.h so that synthetic +event can keep using it, and uses it in trace_probe.c too. + +Link: https://lore.kernel.org/all/168908495772.123124.1250788051922100079.stgit@devnote2/ +Link: https://lore.kernel.org/all/20230706230642.3793a593@rorschach.local.home/ + +Cc: stable@vger.kernel.org +Cc: Andrew Morton +Cc: Tom Zanussi +Signed-off-by: Masami Hiramatsu (Google) +Reviewed-by: Steven Rostedt (Google) +Stable-dep-of: 797311bce5c2 ("tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails") +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.h | 2 ++ + kernel/trace/trace_probe.c | 2 +- + kernel/trace/trace_probe_kernel.h | 31 ++++++------------------------- + 3 files changed, 9 insertions(+), 26 deletions(-) + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index e90c7e840320d..3d3505286aa7f 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -113,6 +113,8 @@ enum trace_type { + #define MEM_FAIL(condition, fmt, ...) \ + DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__) + ++#define FAULT_STRING "(fault)" ++ + #define HIST_STACKTRACE_DEPTH 16 + #define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) + #define HIST_STACKTRACE_SKIP 5 +diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c +index c3852180bbb61..eef9806bb9b14 100644 +--- a/kernel/trace/trace_probe.c ++++ b/kernel/trace/trace_probe.c +@@ -64,7 +64,7 @@ int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, void *data, void *ent) + int len = *(u32 *)data >> 16; + + if (!len) +- trace_seq_puts(s, "(fault)"); ++ trace_seq_puts(s, FAULT_STRING); + else + trace_seq_printf(s, "\"%s\"", + (const char *)get_loc_data(data, ent)); +diff --git a/kernel/trace/trace_probe_kernel.h b/kernel/trace/trace_probe_kernel.h +index 77dbd9ff97826..1d43df29a1f8e 100644 +--- a/kernel/trace/trace_probe_kernel.h ++++ b/kernel/trace/trace_probe_kernel.h +@@ -2,8 +2,6 @@ + #ifndef __TRACE_PROBE_KERNEL_H_ + #define __TRACE_PROBE_KERNEL_H_ + +-#define FAULT_STRING "(fault)" +- + /* + * This depends on trace_probe.h, but can not include it due to + * the way trace_probe_tmpl.h is used by trace_kprobe.c and trace_eprobe.c. +@@ -15,16 +13,8 @@ static nokprobe_inline int + kern_fetch_store_strlen_user(unsigned long addr) + { + const void __user *uaddr = (__force const void __user *)addr; +- int ret; + +- ret = strnlen_user_nofault(uaddr, MAX_STRING_SIZE); +- /* +- * strnlen_user_nofault returns zero on fault, insert the +- * FAULT_STRING when that occurs. +- */ +- if (ret <= 0) +- return strlen(FAULT_STRING) + 1; +- return ret; ++ return strnlen_user_nofault(uaddr, MAX_STRING_SIZE); + } + + /* Return the length of string -- including null terminal byte */ +@@ -44,18 +34,7 @@ kern_fetch_store_strlen(unsigned long addr) + len++; + } while (c && ret == 0 && len < MAX_STRING_SIZE); + +- /* For faults, return enough to hold the FAULT_STRING */ +- return (ret < 0) ? strlen(FAULT_STRING) + 1 : len; +-} +- +-static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base, int len) +-{ +- if (ret >= 0) { +- *(u32 *)dest = make_data_loc(ret, __dest - base); +- } else { +- strscpy(__dest, FAULT_STRING, len); +- ret = strlen(__dest) + 1; +- } ++ return (ret < 0) ? ret : len; + } + + /* +@@ -76,7 +55,8 @@ kern_fetch_store_string_user(unsigned long addr, void *dest, void *base) + __dest = get_loc_data(dest, base); + + ret = strncpy_from_user_nofault(__dest, uaddr, maxlen); +- set_data_loc(ret, dest, __dest, base, maxlen); ++ if (ret >= 0) ++ *(u32 *)dest = make_data_loc(ret, __dest - base); + + return ret; + } +@@ -107,7 +87,8 @@ kern_fetch_store_string(unsigned long addr, void *dest, void *base) + * probing. + */ + ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen); +- set_data_loc(ret, dest, __dest, base, maxlen); ++ if (ret >= 0) ++ *(u32 *)dest = make_data_loc(ret, __dest - base); + + return ret; + } +-- +2.39.2 + diff --git a/queue-6.1/series b/queue-6.1/series index 5ca43b3a80d..86cd355f120 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -6,3 +6,68 @@ drm-amd-display-keep-phy-active-for-dp-config.patch ovl-fix-null-pointer-dereference-in-ovl_permission.patch drm-amd-move-helper-for-dynamic-speed-switch-check-out-of-smu13.patch drm-amd-align-smu11-smu_msg_overridepcieparameters-implementation-with-smu13.patch +jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch +blk-mq-fix-stall-due-to-recursive-flush-plug.patch +powerpc-pseries-vas-hold-mmap_mutex-after-mmap-lock-.patch +kvm-s390-pv-fix-index-value-of-replaced-asce.patch +io_uring-don-t-audit-the-capability-check-in-io_urin.patch +gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch +gpio-mvebu-make-use-of-devm_pwmchip_add.patch +gpio-mvebu-fix-irq-domain-leak.patch +btrfs-fix-race-between-quota-disable-and-relocation.patch +f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch +f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch +i2c-delete-error-messages-for-failed-memory-allocati.patch +i2c-improve-size-determinations.patch +i2c-nomadik-remove-unnecessary-goto-label.patch +i2c-nomadik-use-devm_clk_get_enabled.patch +i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch +mips-loongson-move-arch-cflags-to-mips-top-level-mak.patch +mips-loongson-fix-build-error-when-make-modules_inst.patch +pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch +pci-aspm-factor-out-pcie_wait_for_retrain.patch +pci-aspm-avoid-link-retraining-race.patch +pci-rockchip-remove-writes-to-unused-registers.patch +pci-rockchip-fix-window-mapping-and-address-translat.patch +pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch +drm-amd-display-add-fb_damage_clips-support.patch +drm-amd-display-check-if-link-state-is-valid.patch +drm-amd-display-rework-context-change-check.patch +drm-amd-display-enable-new-commit-sequence-only-for-.patch +drm-amd-display-copy-dc-context-in-the-commit-stream.patch +drm-amd-display-include-surface-of-unaffected-stream.patch +drm-amd-display-use-min-transition-for-all-subvp-pla.patch +drm-amd-display-add-odm-case-when-looking-for-first-.patch +drm-amd-display-use-low-clocks-for-no-plane-configs.patch +drm-amd-display-fix-unbounded-requesting-for-high-pi.patch +drm-amd-display-add-pixel-rate-based-crb-allocation-.patch +drm-amd-display-fix-dcn315-single-stream-crb-allocat.patch +drm-amd-display-update-correct-dcn314-register-heade.patch +drm-amd-display-set-minimum-requirement-for-using-ps.patch +drm-amd-display-set-minimum-requirement-for-using-ps.patch-26244 +drm-ttm-don-t-print-error-message-if-eviction-was-in.patch +drm-ttm-don-t-leak-a-resource-on-eviction-error.patch +n_tty-rename-tail-to-old_tail-in-n_tty_read.patch +tty-fix-hang-on-tty-device-with-no_room-set.patch +drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch +kvm-arm64-condition-hw-af-updates-on-config-option.patch +arm64-errata-mitigate-ampere1-erratum-ac03_cpu_38-at.patch +mptcp-introduce-sk-to-replace-sock-sk-in-mptcp_liste.patch +mptcp-do-not-rely-on-implicit-state-check-in-mptcp_l.patch +tracing-probes-add-symstr-type-for-dynamic-events.patch +tracing-probes-fix-to-avoid-double-count-of-the-stri.patch +tracing-allow-synthetic-events-to-pass-around-stackt.patch +revert-tracing-add-fault-name-injection-to-kernel-pr.patch +tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch +test_maple_tree-test-modifications-while-iterating.patch +maple_tree-add-__init-and-__exit-to-test-module.patch +maple_tree-fix-32-bit-mas_next-testing.patch +drm-amd-display-rework-comments-on-dc-file.patch +drm-amd-display-fix-dc-core-dc.c-kernel-doc.patch +drm-amd-display-add-fams-validation-before-trying-to.patch +drm-amd-display-update-extended-blank-for-dcn314-onw.patch +drm-amd-display-fix-possible-underflow-for-displays-.patch +drm-amd-display-prevent-vtotal-from-being-set-to-0.patch +jbd2-remove-t_checkpoint_io_list.patch +jbd2-remove-journal_clean_one_cp_list.patch +jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch diff --git a/queue-6.1/test_maple_tree-test-modifications-while-iterating.patch b/queue-6.1/test_maple_tree-test-modifications-while-iterating.patch new file mode 100644 index 00000000000..b2d37dc7495 --- /dev/null +++ b/queue-6.1/test_maple_tree-test-modifications-while-iterating.patch @@ -0,0 +1,114 @@ +From d8d4821234c35de1c1ae1c6863d75aff9e2043aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Jan 2023 11:26:05 -0500 +Subject: test_maple_tree: test modifications while iterating + +From: Liam R. Howlett + +[ Upstream commit 5159d64b335401fa83f18c27e2267f1eafc41bd3 ] + +Add a testcase to ensure the iterator detects bad states on modifications +and does what the user expects + +Link: https://lkml.kernel.org/r/20230120162650.984577-5-Liam.Howlett@oracle.com +Signed-off-by: Liam R. Howlett +Signed-off-by: Andrew Morton +Stable-dep-of: 7a93c71a6714 ("maple_tree: fix 32 bit mas_next testing") +Signed-off-by: Sasha Levin +--- + lib/test_maple_tree.c | 72 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +diff --git a/lib/test_maple_tree.c b/lib/test_maple_tree.c +index f7364b9fee939..f1db333270e9f 100644 +--- a/lib/test_maple_tree.c ++++ b/lib/test_maple_tree.c +@@ -1709,6 +1709,74 @@ static noinline void check_forking(struct maple_tree *mt) + mtree_destroy(&newmt); + } + ++static noinline void check_iteration(struct maple_tree *mt) ++{ ++ int i, nr_entries = 125; ++ void *val; ++ MA_STATE(mas, mt, 0, 0); ++ ++ for (i = 0; i <= nr_entries; i++) ++ mtree_store_range(mt, i * 10, i * 10 + 9, ++ xa_mk_value(i), GFP_KERNEL); ++ ++ mt_set_non_kernel(99999); ++ ++ i = 0; ++ mas_lock(&mas); ++ mas_for_each(&mas, val, 925) { ++ MT_BUG_ON(mt, mas.index != i * 10); ++ MT_BUG_ON(mt, mas.last != i * 10 + 9); ++ /* Overwrite end of entry 92 */ ++ if (i == 92) { ++ mas.index = 925; ++ mas.last = 929; ++ mas_store(&mas, val); ++ } ++ i++; ++ } ++ /* Ensure mas_find() gets the next value */ ++ val = mas_find(&mas, ULONG_MAX); ++ MT_BUG_ON(mt, val != xa_mk_value(i)); ++ ++ mas_set(&mas, 0); ++ i = 0; ++ mas_for_each(&mas, val, 785) { ++ MT_BUG_ON(mt, mas.index != i * 10); ++ MT_BUG_ON(mt, mas.last != i * 10 + 9); ++ /* Overwrite start of entry 78 */ ++ if (i == 78) { ++ mas.index = 780; ++ mas.last = 785; ++ mas_store(&mas, val); ++ } else { ++ i++; ++ } ++ } ++ val = mas_find(&mas, ULONG_MAX); ++ MT_BUG_ON(mt, val != xa_mk_value(i)); ++ ++ mas_set(&mas, 0); ++ i = 0; ++ mas_for_each(&mas, val, 765) { ++ MT_BUG_ON(mt, mas.index != i * 10); ++ MT_BUG_ON(mt, mas.last != i * 10 + 9); ++ /* Overwrite end of entry 76 and advance to the end */ ++ if (i == 76) { ++ mas.index = 760; ++ mas.last = 765; ++ mas_store(&mas, val); ++ mas_next(&mas, ULONG_MAX); ++ } ++ i++; ++ } ++ /* Make sure the next find returns the one after 765, 766-769 */ ++ val = mas_find(&mas, ULONG_MAX); ++ MT_BUG_ON(mt, val != xa_mk_value(76)); ++ mas_unlock(&mas); ++ mas_destroy(&mas); ++ mt_set_non_kernel(0); ++} ++ + static noinline void check_mas_store_gfp(struct maple_tree *mt) + { + +@@ -2702,6 +2770,10 @@ static int maple_tree_seed(void) + goto skip; + #endif + ++ mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE); ++ check_iteration(&tree); ++ mtree_destroy(&tree); ++ + mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE); + check_forking(&tree); + mtree_destroy(&tree); +-- +2.39.2 + diff --git a/queue-6.1/tracing-allow-synthetic-events-to-pass-around-stackt.patch b/queue-6.1/tracing-allow-synthetic-events-to-pass-around-stackt.patch new file mode 100644 index 00000000000..111a3d52397 --- /dev/null +++ b/queue-6.1/tracing-allow-synthetic-events-to-pass-around-stackt.patch @@ -0,0 +1,282 @@ +From 98dbd287cf8b627361419f174c25886ce13b2636 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Jan 2023 10:21:28 -0500 +Subject: tracing: Allow synthetic events to pass around stacktraces + +From: Steven Rostedt (Google) + +[ Upstream commit 00cf3d672a9dd409418647e9f98784c339c3ff63 ] + +Allow a stacktrace from one event to be displayed by the end event of a +synthetic event. This is very useful when looking for the longest latency +of a sleep or something blocked on I/O. + + # cd /sys/kernel/tracing/ + # echo 's:block_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events + # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace if prev_state == 1||prev_state == 2' > events/sched/sched_switch/trigger + # echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(block_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger + +The above creates a "block_lat" synthetic event that take the stacktrace of +when a task schedules out in either the interruptible or uninterruptible +states, and on a new per process max $delta (the time it was scheduled +out), will print the process id and the stacktrace. + + # echo 1 > events/synthetic/block_lat/enable + # cat trace + # TASK-PID CPU# ||||| TIMESTAMP FUNCTION + # | | | ||||| | | + kworker/u16:0-767 [006] d..4. 560.645045: block_lat: pid=767 delta=66 stack=STACK: + => __schedule + => schedule + => pipe_read + => vfs_read + => ksys_read + => do_syscall_64 + => 0x966000aa + + -0 [003] d..4. 561.132117: block_lat: pid=0 delta=413787 stack=STACK: + => __schedule + => schedule + => schedule_hrtimeout_range_clock + => do_sys_poll + => __x64_sys_poll + => do_syscall_64 + => 0x966000aa + + <...>-153 [006] d..4. 562.068407: block_lat: pid=153 delta=54 stack=STACK: + => __schedule + => schedule + => io_schedule + => rq_qos_wait + => wbt_wait + => __rq_qos_throttle + => blk_mq_submit_bio + => submit_bio_noacct_nocheck + => ext4_bio_write_page + => mpage_submit_page + => mpage_process_page_bufs + => mpage_prepare_extent_to_map + => ext4_do_writepages + => ext4_writepages + => do_writepages + => __writeback_single_inode + +Link: https://lkml.kernel.org/r/20230117152236.010941267@goodmis.org + +Cc: Masami Hiramatsu +Cc: Andrew Morton +Cc: Tom Zanussi +Cc: Ross Zwisler +Cc: Ching-lin Yu +Signed-off-by: Steven Rostedt (Google) +Stable-dep-of: 797311bce5c2 ("tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails") +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.h | 4 ++ + kernel/trace/trace_events_hist.c | 7 ++- + kernel/trace/trace_events_synth.c | 80 ++++++++++++++++++++++++++++++- + kernel/trace/trace_synth.h | 1 + + 4 files changed, 87 insertions(+), 5 deletions(-) + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index ac7af03ce8372..e90c7e840320d 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -113,6 +113,10 @@ enum trace_type { + #define MEM_FAIL(condition, fmt, ...) \ + DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__) + ++#define HIST_STACKTRACE_DEPTH 16 ++#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) ++#define HIST_STACKTRACE_SKIP 5 ++ + /* + * syscalls are special, and need special handling, this is why + * they are not included in trace_entries.h +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index 0f5d16eabd3b0..1470af2190735 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -479,10 +479,6 @@ DEFINE_HIST_FIELD_FN(u8); + #define for_each_hist_key_field(i, hist_data) \ + for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++) + +-#define HIST_STACKTRACE_DEPTH 16 +-#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) +-#define HIST_STACKTRACE_SKIP 5 +- + #define HITCOUNT_IDX 0 + #define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + HIST_STACKTRACE_SIZE) + +@@ -3843,6 +3839,9 @@ static int check_synth_field(struct synth_event *event, + && field->is_dynamic) + return 0; + ++ if (strstr(hist_field->type, "long[") && field->is_stack) ++ return 0; ++ + if (strcmp(field->type, hist_field->type) != 0) { + if (field->size != hist_field->size || + (!field->is_string && field->is_signed != hist_field->is_signed)) +diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c +index 89083ae1aebe3..3c18e7bd40189 100644 +--- a/kernel/trace/trace_events_synth.c ++++ b/kernel/trace/trace_events_synth.c +@@ -184,6 +184,14 @@ static int synth_field_is_string(char *type) + return false; + } + ++static int synth_field_is_stack(char *type) ++{ ++ if (strstr(type, "long[") != NULL) ++ return true; ++ ++ return false; ++} ++ + static int synth_field_string_size(char *type) + { + char buf[4], *end, *start; +@@ -259,6 +267,8 @@ static int synth_field_size(char *type) + size = sizeof(gfp_t); + else if (synth_field_is_string(type)) + size = synth_field_string_size(type); ++ else if (synth_field_is_stack(type)) ++ size = 0; + + return size; + } +@@ -303,6 +313,8 @@ static const char *synth_field_fmt(char *type) + fmt = "%x"; + else if (synth_field_is_string(type)) + fmt = "%.*s"; ++ else if (synth_field_is_stack(type)) ++ fmt = "%s"; + + return fmt; + } +@@ -382,6 +394,23 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter, + i == se->n_fields - 1 ? "" : " "); + n_u64 += STR_VAR_LEN_MAX / sizeof(u64); + } ++ } else if (se->fields[i]->is_stack) { ++ u32 offset, data_offset, len; ++ unsigned long *p, *end; ++ ++ offset = (u32)entry->fields[n_u64]; ++ data_offset = offset & 0xffff; ++ len = offset >> 16; ++ ++ p = (void *)entry + data_offset; ++ end = (void *)p + len - (sizeof(long) - 1); ++ ++ trace_seq_printf(s, "%s=STACK:\n", se->fields[i]->name); ++ ++ for (; *p && p < end; p++) ++ trace_seq_printf(s, "=> %pS\n", (void *)*p); ++ n_u64++; ++ + } else { + struct trace_print_flags __flags[] = { + __def_gfpflag_names, {-1, NULL} }; +@@ -458,6 +487,43 @@ static unsigned int trace_string(struct synth_trace_event *entry, + return len; + } + ++static unsigned int trace_stack(struct synth_trace_event *entry, ++ struct synth_event *event, ++ long *stack, ++ unsigned int data_size, ++ unsigned int *n_u64) ++{ ++ unsigned int len; ++ u32 data_offset; ++ void *data_loc; ++ ++ data_offset = struct_size(entry, fields, event->n_u64); ++ data_offset += data_size; ++ ++ for (len = 0; len < HIST_STACKTRACE_DEPTH; len++) { ++ if (!stack[len]) ++ break; ++ } ++ ++ /* Include the zero'd element if it fits */ ++ if (len < HIST_STACKTRACE_DEPTH) ++ len++; ++ ++ len *= sizeof(long); ++ ++ /* Find the dynamic section to copy the stack into. */ ++ data_loc = (void *)entry + data_offset; ++ memcpy(data_loc, stack, len); ++ ++ /* Fill in the field that holds the offset/len combo */ ++ data_offset |= len << 16; ++ *(u32 *)&entry->fields[*n_u64] = data_offset; ++ ++ (*n_u64)++; ++ ++ return len; ++} ++ + static notrace void trace_event_raw_event_synth(void *__data, + u64 *var_ref_vals, + unsigned int *var_ref_idx) +@@ -510,6 +576,12 @@ static notrace void trace_event_raw_event_synth(void *__data, + event->fields[i]->is_dynamic, + data_size, &n_u64); + data_size += len; /* only dynamic string increments */ ++ } if (event->fields[i]->is_stack) { ++ long *stack = (long *)(long)var_ref_vals[val_idx]; ++ ++ len = trace_stack(entry, event, stack, ++ data_size, &n_u64); ++ data_size += len; + } else { + struct synth_field *field = event->fields[i]; + u64 val = var_ref_vals[val_idx]; +@@ -572,6 +644,9 @@ static int __set_synth_event_print_fmt(struct synth_event *event, + event->fields[i]->is_dynamic) + pos += snprintf(buf + pos, LEN_OR_ZERO, + ", __get_str(%s)", event->fields[i]->name); ++ else if (event->fields[i]->is_stack) ++ pos += snprintf(buf + pos, LEN_OR_ZERO, ++ ", __get_stacktrace(%s)", event->fields[i]->name); + else + pos += snprintf(buf + pos, LEN_OR_ZERO, + ", REC->%s", event->fields[i]->name); +@@ -708,7 +783,8 @@ static struct synth_field *parse_synth_field(int argc, char **argv, + ret = -EINVAL; + goto free; + } else if (size == 0) { +- if (synth_field_is_string(field->type)) { ++ if (synth_field_is_string(field->type) || ++ synth_field_is_stack(field->type)) { + char *type; + + len = sizeof("__data_loc ") + strlen(field->type) + 1; +@@ -739,6 +815,8 @@ static struct synth_field *parse_synth_field(int argc, char **argv, + + if (synth_field_is_string(field->type)) + field->is_string = true; ++ else if (synth_field_is_stack(field->type)) ++ field->is_stack = true; + + field->is_signed = synth_field_signed(field->type); + out: +diff --git a/kernel/trace/trace_synth.h b/kernel/trace/trace_synth.h +index b29595fe3ac5a..43f6fb6078dbf 100644 +--- a/kernel/trace/trace_synth.h ++++ b/kernel/trace/trace_synth.h +@@ -18,6 +18,7 @@ struct synth_field { + bool is_signed; + bool is_string; + bool is_dynamic; ++ bool is_stack; + }; + + struct synth_event { +-- +2.39.2 + diff --git a/queue-6.1/tracing-probes-add-symstr-type-for-dynamic-events.patch b/queue-6.1/tracing-probes-add-symstr-type-for-dynamic-events.patch new file mode 100644 index 00000000000..b89892fafdd --- /dev/null +++ b/queue-6.1/tracing-probes-add-symstr-type-for-dynamic-events.patch @@ -0,0 +1,313 @@ +From f1afb8269358befddf9704b4cd16157fbb66afd4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 13:47:56 +0900 +Subject: tracing/probes: Add symstr type for dynamic events + +From: Masami Hiramatsu (Google) + +[ Upstream commit b26a124cbfa80f42bfc4e63e1d5643ca98159d66 ] + +Add 'symstr' type for storing the kernel symbol as a string data +instead of the symbol address. This allows us to filter the +events by wildcard symbol name. + +e.g. + # echo 'e:wqfunc workqueue.workqueue_execute_start symname=$function:symstr' >> dynamic_events + # cat events/eprobes/wqfunc/format + name: wqfunc + ID: 2110 + format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:__data_loc char[] symname; offset:8; size:4; signed:1; + + print fmt: " symname=\"%s\"", __get_str(symname) + +Note that there is already 'symbol' type which just change the +print format (so it still stores the symbol address in the tracing +ring buffer.) On the other hand, 'symstr' type stores the actual +"symbol+offset/size" data as a string. + +Link: https://lore.kernel.org/all/166679930847.1528100.4124308529180235965.stgit@devnote3/ + +Signed-off-by: Masami Hiramatsu (Google) +Stable-dep-of: 66bcf65d6cf0 ("tracing/probes: Fix to avoid double count of the string length on the array") +Signed-off-by: Sasha Levin +--- + Documentation/trace/kprobetrace.rst | 8 +++-- + kernel/trace/trace.c | 2 +- + kernel/trace/trace_probe.c | 44 ++++++++++++++++++--------- + kernel/trace/trace_probe.h | 16 +++++++--- + kernel/trace/trace_probe_tmpl.h | 47 +++++++++++++++++++++++++++-- + 5 files changed, 91 insertions(+), 26 deletions(-) + +diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst +index 4274cc6a2f94f..08a2a6a3782f0 100644 +--- a/Documentation/trace/kprobetrace.rst ++++ b/Documentation/trace/kprobetrace.rst +@@ -58,8 +58,8 @@ Synopsis of kprobe_events + NAME=FETCHARG : Set NAME as the argument name of FETCHARG. + FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types + (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types +- (x8/x16/x32/x64), "string", "ustring" and bitfield +- are supported. ++ (x8/x16/x32/x64), "string", "ustring", "symbol", "symstr" ++ and bitfield are supported. + + (\*1) only for the probe on function entry (offs == 0). + (\*2) only for return probe. +@@ -96,6 +96,10 @@ offset, and container-size (usually 32). The syntax is:: + + Symbol type('symbol') is an alias of u32 or u64 type (depends on BITS_PER_LONG) + which shows given pointer in "symbol+offset" style. ++On the other hand, symbol-string type ('symstr') converts the given address to ++"symbol+offset/symbolsize" style and stores it as a null-terminated string. ++With 'symstr' type, you can filter the event with wildcard pattern of the ++symbols, and you don't need to solve symbol name by yourself. + For $comm, the default type is "string"; any other type is invalid. + + .. _user_mem_access: +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 27bbe180a2ef2..709af9631be45 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -5627,7 +5627,7 @@ static const char readme_msg[] = + "\t +|-[u](), \\imm-value, \\\"imm-string\"\n" + "\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n" + "\t b@/, ustring,\n" +- "\t \\[\\]\n" ++ "\t symstr, \\[\\]\n" + #ifdef CONFIG_HIST_TRIGGERS + "\t field: ;\n" + "\t stype: u8/u16/u32/u64, s8/s16/s32/s64, pid_t,\n" +diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c +index bb2f95d7175c2..c3852180bbb61 100644 +--- a/kernel/trace/trace_probe.c ++++ b/kernel/trace/trace_probe.c +@@ -76,9 +76,11 @@ const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; + /* Fetch type information table */ + static const struct fetch_type probe_fetch_types[] = { + /* Special types */ +- __ASSIGN_FETCH_TYPE("string", string, string, sizeof(u32), 1, ++ __ASSIGN_FETCH_TYPE("string", string, string, sizeof(u32), 1, 1, + "__data_loc char[]"), +- __ASSIGN_FETCH_TYPE("ustring", string, string, sizeof(u32), 1, ++ __ASSIGN_FETCH_TYPE("ustring", string, string, sizeof(u32), 1, 1, ++ "__data_loc char[]"), ++ __ASSIGN_FETCH_TYPE("symstr", string, string, sizeof(u32), 1, 1, + "__data_loc char[]"), + /* Basic types */ + ASSIGN_FETCH_TYPE(u8, u8, 0), +@@ -662,16 +664,26 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, + + ret = -EINVAL; + /* Store operation */ +- if (!strcmp(parg->type->name, "string") || +- !strcmp(parg->type->name, "ustring")) { +- if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF && +- code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM && +- code->op != FETCH_OP_DATA && code->op != FETCH_OP_TP_ARG) { +- trace_probe_log_err(offset + (t ? (t - arg) : 0), +- BAD_STRING); +- goto fail; ++ if (parg->type->is_string) { ++ if (!strcmp(parg->type->name, "symstr")) { ++ if (code->op != FETCH_OP_REG && code->op != FETCH_OP_STACK && ++ code->op != FETCH_OP_RETVAL && code->op != FETCH_OP_ARG && ++ code->op != FETCH_OP_DEREF && code->op != FETCH_OP_TP_ARG) { ++ trace_probe_log_err(offset + (t ? (t - arg) : 0), ++ BAD_SYMSTRING); ++ goto fail; ++ } ++ } else { ++ if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF && ++ code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM && ++ code->op != FETCH_OP_DATA && code->op != FETCH_OP_TP_ARG) { ++ trace_probe_log_err(offset + (t ? (t - arg) : 0), ++ BAD_STRING); ++ goto fail; ++ } + } +- if ((code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM || ++ if (!strcmp(parg->type->name, "symstr") || ++ (code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM || + code->op == FETCH_OP_DATA) || code->op == FETCH_OP_TP_ARG || + parg->count) { + /* +@@ -679,6 +691,8 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, + * must be kept, and if parg->count != 0, this is an + * array of string pointers instead of string address + * itself. ++ * For the symstr, it doesn't need to dereference, thus ++ * it just get the value. + */ + code++; + if (code->op != FETCH_OP_NOP) { +@@ -690,6 +704,8 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, + if (!strcmp(parg->type->name, "ustring") || + code->op == FETCH_OP_UDEREF) + code->op = FETCH_OP_ST_USTRING; ++ else if (!strcmp(parg->type->name, "symstr")) ++ code->op = FETCH_OP_ST_SYMSTR; + else + code->op = FETCH_OP_ST_STRING; + code->size = parg->type->size; +@@ -919,8 +935,7 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, + for (i = 0; i < tp->nr_args; i++) { + parg = tp->args + i; + if (parg->count) { +- if ((strcmp(parg->type->name, "string") == 0) || +- (strcmp(parg->type->name, "ustring") == 0)) ++ if (parg->type->is_string) + fmt = ", __get_str(%s[%d])"; + else + fmt = ", REC->%s[%d]"; +@@ -928,8 +943,7 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, + pos += snprintf(buf + pos, LEN_OR_ZERO, + fmt, parg->name, j); + } else { +- if ((strcmp(parg->type->name, "string") == 0) || +- (strcmp(parg->type->name, "ustring") == 0)) ++ if (parg->type->is_string) + fmt = ", __get_str(%s)"; + else + fmt = ", REC->%s"; +diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h +index 3d731aac94d49..f41c330bd60f1 100644 +--- a/kernel/trace/trace_probe.h ++++ b/kernel/trace/trace_probe.h +@@ -98,6 +98,7 @@ enum fetch_op { + FETCH_OP_ST_UMEM, /* Mem: .offset, .size */ + FETCH_OP_ST_STRING, /* String: .offset, .size */ + FETCH_OP_ST_USTRING, /* User String: .offset, .size */ ++ FETCH_OP_ST_SYMSTR, /* Kernel Symbol String: .offset, .size */ + // Stage 4 (modify) op + FETCH_OP_MOD_BF, /* Bitfield: .basesize, .lshift, .rshift */ + // Stage 5 (loop) op +@@ -133,7 +134,8 @@ struct fetch_insn { + struct fetch_type { + const char *name; /* Name of type */ + size_t size; /* Byte size of type */ +- int is_signed; /* Signed flag */ ++ bool is_signed; /* Signed flag */ ++ bool is_string; /* String flag */ + print_type_func_t print; /* Print functions */ + const char *fmt; /* Format string */ + const char *fmttype; /* Name in format file */ +@@ -177,16 +179,19 @@ DECLARE_BASIC_PRINT_TYPE_FUNC(symbol); + #define _ADDR_FETCH_TYPE(t) __ADDR_FETCH_TYPE(t) + #define ADDR_FETCH_TYPE _ADDR_FETCH_TYPE(BITS_PER_LONG) + +-#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ +- {.name = _name, \ ++#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, str, _fmttype) \ ++ {.name = _name, \ + .size = _size, \ +- .is_signed = sign, \ ++ .is_signed = (bool)sign, \ ++ .is_string = (bool)str, \ + .print = PRINT_TYPE_FUNC_NAME(ptype), \ + .fmt = PRINT_TYPE_FMT_NAME(ptype), \ + .fmttype = _fmttype, \ + } ++ ++/* Non string types can use these macros */ + #define _ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ +- __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, #_fmttype) ++ __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, 0, #_fmttype) + #define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ + _ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, ptype) + +@@ -431,6 +436,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call, + C(ARRAY_TOO_BIG, "Array number is too big"), \ + C(BAD_TYPE, "Unknown type is specified"), \ + C(BAD_STRING, "String accepts only memory argument"), \ ++ C(BAD_SYMSTRING, "Symbol String doesn't accept data/userdata"), \ + C(BAD_BITFIELD, "Invalid bitfield"), \ + C(ARG_NAME_TOO_LONG, "Argument name is too long"), \ + C(NO_ARG_NAME, "Argument name is not specified"), \ +diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h +index c293a607d5366..21799fa813ca8 100644 +--- a/kernel/trace/trace_probe_tmpl.h ++++ b/kernel/trace/trace_probe_tmpl.h +@@ -67,6 +67,37 @@ probe_mem_read(void *dest, void *src, size_t size); + static nokprobe_inline int + probe_mem_read_user(void *dest, void *src, size_t size); + ++static nokprobe_inline int ++fetch_store_symstrlen(unsigned long addr) ++{ ++ char namebuf[KSYM_SYMBOL_LEN]; ++ int ret; ++ ++ ret = sprint_symbol(namebuf, addr); ++ if (ret < 0) ++ return 0; ++ ++ return ret + 1; ++} ++ ++/* ++ * Fetch a null-terminated symbol string + offset. Caller MUST set *(u32 *)buf ++ * with max length and relative data location. ++ */ ++static nokprobe_inline int ++fetch_store_symstring(unsigned long addr, void *dest, void *base) ++{ ++ int maxlen = get_loc_len(*(u32 *)dest); ++ void *__dest; ++ ++ if (unlikely(!maxlen)) ++ return -ENOMEM; ++ ++ __dest = get_loc_data(dest, base); ++ ++ return sprint_symbol(__dest, addr); ++} ++ + /* From the 2nd stage, routine is same */ + static nokprobe_inline int + process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, +@@ -99,16 +130,22 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, + stage3: + /* 3rd stage: store value to buffer */ + if (unlikely(!dest)) { +- if (code->op == FETCH_OP_ST_STRING) { ++ switch (code->op) { ++ case FETCH_OP_ST_STRING: + ret = fetch_store_strlen(val + code->offset); + code++; + goto array; +- } else if (code->op == FETCH_OP_ST_USTRING) { ++ case FETCH_OP_ST_USTRING: + ret += fetch_store_strlen_user(val + code->offset); + code++; + goto array; +- } else ++ case FETCH_OP_ST_SYMSTR: ++ ret += fetch_store_symstrlen(val + code->offset); ++ code++; ++ goto array; ++ default: + return -EILSEQ; ++ } + } + + switch (code->op) { +@@ -129,6 +166,10 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, + loc = *(u32 *)dest; + ret = fetch_store_string_user(val + code->offset, dest, base); + break; ++ case FETCH_OP_ST_SYMSTR: ++ loc = *(u32 *)dest; ++ ret = fetch_store_symstring(val + code->offset, dest, base); ++ break; + default: + return -EILSEQ; + } +-- +2.39.2 + diff --git a/queue-6.1/tracing-probes-fix-to-avoid-double-count-of-the-stri.patch b/queue-6.1/tracing-probes-fix-to-avoid-double-count-of-the-stri.patch new file mode 100644 index 00000000000..1c3e9a5278f --- /dev/null +++ b/queue-6.1/tracing-probes-fix-to-avoid-double-count-of-the-stri.patch @@ -0,0 +1,49 @@ +From 4631295e4a3bf6c42f4305ed5939670b4a393777 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jul 2023 23:15:29 +0900 +Subject: tracing/probes: Fix to avoid double count of the string length on the + array + +From: Masami Hiramatsu (Google) + +[ Upstream commit 66bcf65d6cf0ca6540e2341e88ee7ef02dbdda08 ] + +If an array is specified with the ustring or symstr, the length of the +strings are accumlated on both of 'ret' and 'total', which means the +length is double counted. +Just set the length to the 'ret' value for avoiding double counting. + +Link: https://lore.kernel.org/all/168908492917.123124.15076463491122036025.stgit@devnote2/ + +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/all/8819b154-2ba1-43c3-98a2-cbde20892023@moroto.mountain/ +Fixes: 88903c464321 ("tracing/probe: Add ustring type for user-space string") +Cc: stable@vger.kernel.org +Signed-off-by: Masami Hiramatsu (Google) +Reviewed-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace_probe_tmpl.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h +index 21799fa813ca8..98ac09052fea4 100644 +--- a/kernel/trace/trace_probe_tmpl.h ++++ b/kernel/trace/trace_probe_tmpl.h +@@ -136,11 +136,11 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, + code++; + goto array; + case FETCH_OP_ST_USTRING: +- ret += fetch_store_strlen_user(val + code->offset); ++ ret = fetch_store_strlen_user(val + code->offset); + code++; + goto array; + case FETCH_OP_ST_SYMSTR: +- ret += fetch_store_symstrlen(val + code->offset); ++ ret = fetch_store_symstrlen(val + code->offset); + code++; + goto array; + default: +-- +2.39.2 + diff --git a/queue-6.1/tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch b/queue-6.1/tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch new file mode 100644 index 00000000000..e531ca37e90 --- /dev/null +++ b/queue-6.1/tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch @@ -0,0 +1,109 @@ +From f59ea2be49600590e034dc4800482b66bd3c5b7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jul 2023 23:16:07 +0900 +Subject: tracing/probes: Fix to record 0-length data_loc in + fetch_store_string*() if fails + +From: Masami Hiramatsu (Google) + +[ Upstream commit 797311bce5c2ac90b8d65e357603cfd410d36ebb ] + +Fix to record 0-length data to data_loc in fetch_store_string*() if it fails +to get the string data. +Currently those expect that the data_loc is updated by store_trace_args() if +it returns the error code. However, that does not work correctly if the +argument is an array of strings. In that case, store_trace_args() only clears +the first entry of the array (which may have no error) and leaves other +entries. So it should be cleared by fetch_store_string*() itself. +Also, 'dyndata' and 'maxlen' in store_trace_args() should be updated +only if it is used (ret > 0 and argument is a dynamic data.) + +Link: https://lore.kernel.org/all/168908496683.123124.4761206188794205601.stgit@devnote2/ + +Fixes: 40b53b771806 ("tracing: probeevent: Add array type support") +Cc: stable@vger.kernel.org +Reviewed-by: Steven Rostedt (Google) +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace_probe_kernel.h | 13 +++++++++---- + kernel/trace/trace_probe_tmpl.h | 10 +++------- + kernel/trace/trace_uprobe.c | 3 ++- + 3 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/kernel/trace/trace_probe_kernel.h b/kernel/trace/trace_probe_kernel.h +index 1d43df29a1f8e..2da70be83831c 100644 +--- a/kernel/trace/trace_probe_kernel.h ++++ b/kernel/trace/trace_probe_kernel.h +@@ -37,6 +37,13 @@ kern_fetch_store_strlen(unsigned long addr) + return (ret < 0) ? ret : len; + } + ++static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base) ++{ ++ if (ret < 0) ++ ret = 0; ++ *(u32 *)dest = make_data_loc(ret, __dest - base); ++} ++ + /* + * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf + * with max length and relative data location. +@@ -55,8 +62,7 @@ kern_fetch_store_string_user(unsigned long addr, void *dest, void *base) + __dest = get_loc_data(dest, base); + + ret = strncpy_from_user_nofault(__dest, uaddr, maxlen); +- if (ret >= 0) +- *(u32 *)dest = make_data_loc(ret, __dest - base); ++ set_data_loc(ret, dest, __dest, base); + + return ret; + } +@@ -87,8 +93,7 @@ kern_fetch_store_string(unsigned long addr, void *dest, void *base) + * probing. + */ + ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen); +- if (ret >= 0) +- *(u32 *)dest = make_data_loc(ret, __dest - base); ++ set_data_loc(ret, dest, __dest, base); + + return ret; + } +diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h +index 98ac09052fea4..3e2f5a43b974c 100644 +--- a/kernel/trace/trace_probe_tmpl.h ++++ b/kernel/trace/trace_probe_tmpl.h +@@ -247,13 +247,9 @@ store_trace_args(void *data, struct trace_probe *tp, void *rec, + if (unlikely(arg->dynamic)) + *dl = make_data_loc(maxlen, dyndata - base); + ret = process_fetch_insn(arg->code, rec, dl, base); +- if (arg->dynamic) { +- if (unlikely(ret < 0)) { +- *dl = make_data_loc(0, dyndata - base); +- } else { +- dyndata += ret; +- maxlen -= ret; +- } ++ if (arg->dynamic && likely(ret > 0)) { ++ dyndata += ret; ++ maxlen -= ret; + } + } + } +diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c +index fb58e86dd1178..2ac06a642863a 100644 +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -170,7 +170,8 @@ fetch_store_string(unsigned long addr, void *dest, void *base) + */ + ret++; + *(u32 *)dest = make_data_loc(ret, (void *)dst - base); +- } ++ } else ++ *(u32 *)dest = make_data_loc(0, (void *)dst - base); + + return ret; + } +-- +2.39.2 + diff --git a/queue-6.1/tty-fix-hang-on-tty-device-with-no_room-set.patch b/queue-6.1/tty-fix-hang-on-tty-device-with-no_room-set.patch new file mode 100644 index 00000000000..e2372167e8c --- /dev/null +++ b/queue-6.1/tty-fix-hang-on-tty-device-with-no_room-set.patch @@ -0,0 +1,116 @@ +From bf4955264cc7b148c2f51b5c5e075471a8116236 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Apr 2023 10:44:50 +0800 +Subject: tty: fix hang on tty device with no_room set +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hui Li + +[ Upstream commit 4903fde8047a28299d1fc79c1a0dcc255e928f12 ] + +It is possible to hang pty devices in this case, the reader was +blocking at epoll on master side, the writer was sleeping at +wait_woken inside n_tty_write on slave side, and the write buffer +on tty_port was full, we found that the reader and writer would +never be woken again and blocked forever. + +The problem was caused by a race between reader and kworker: +n_tty_read(reader): n_tty_receive_buf_common(kworker): +copy_from_read_buf()| + |room = N_TTY_BUF_SIZE - (ldata->read_head - tail) + |room <= 0 +n_tty_kick_worker() | + |ldata->no_room = true + +After writing to slave device, writer wakes up kworker to flush +data on tty_port to reader, and the kworker finds that reader +has no room to store data so room <= 0 is met. At this moment, +reader consumes all the data on reader buffer and calls +n_tty_kick_worker to check ldata->no_room which is false and +reader quits reading. Then kworker sets ldata->no_room=true +and quits too. + +If write buffer is not full, writer will wake kworker to flush data +again after following writes, but if write buffer is full and writer +goes to sleep, kworker will never be woken again and tty device is +blocked. + +This problem can be solved with a check for read buffer size inside +n_tty_receive_buf_common, if read buffer is empty and ldata->no_room +is true, a call to n_tty_kick_worker is necessary to keep flushing +data to reader. + +Cc: +Fixes: 42458f41d08f ("n_tty: Ensure reader restarts worker for next reader") +Reviewed-by: Ilpo Järvinen +Signed-off-by: Hui Li +Message-ID: <1680749090-14106-1-git-send-email-caelli@tencent.com> +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/n_tty.c | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index c8f56c9b1a1c8..4dff2f34e2d06 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -204,8 +204,8 @@ static void n_tty_kick_worker(struct tty_struct *tty) + struct n_tty_data *ldata = tty->disc_data; + + /* Did the input worker stop? Restart it */ +- if (unlikely(ldata->no_room)) { +- ldata->no_room = 0; ++ if (unlikely(READ_ONCE(ldata->no_room))) { ++ WRITE_ONCE(ldata->no_room, 0); + + WARN_RATELIMIT(tty->port->itty == NULL, + "scheduling with invalid itty\n"); +@@ -1698,7 +1698,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + if (overflow && room < 0) + ldata->read_head--; + room = overflow; +- ldata->no_room = flow && !room; ++ WRITE_ONCE(ldata->no_room, flow && !room); + } else + overflow = 0; + +@@ -1729,6 +1729,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + } else + n_tty_check_throttle(tty); + ++ if (unlikely(ldata->no_room)) { ++ /* ++ * Barrier here is to ensure to read the latest read_tail in ++ * chars_in_buffer() and to make sure that read_tail is not loaded ++ * before ldata->no_room is set. ++ */ ++ smp_mb(); ++ if (!chars_in_buffer(tty)) ++ n_tty_kick_worker(tty); ++ } ++ + up_read(&tty->termios_rwsem); + + return rcvd; +@@ -2282,8 +2293,14 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, + if (time) + timeout = time; + } +- if (old_tail != ldata->read_tail) ++ if (old_tail != ldata->read_tail) { ++ /* ++ * Make sure no_room is not read in n_tty_kick_worker() ++ * before setting ldata->read_tail in copy_from_read_buf(). ++ */ ++ smp_mb(); + n_tty_kick_worker(tty); ++ } + up_read(&tty->termios_rwsem); + + remove_wait_queue(&tty->read_wait, &wait); +-- +2.39.2 + -- 2.47.3