]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Fri, 28 Jul 2023 14:38:01 +0000 (10:38 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 28 Jul 2023 14:38:01 +0000 (10:38 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
66 files changed:
queue-6.1/arm64-errata-mitigate-ampere1-erratum-ac03_cpu_38-at.patch [new file with mode: 0644]
queue-6.1/blk-mq-fix-stall-due-to-recursive-flush-plug.patch [new file with mode: 0644]
queue-6.1/btrfs-fix-race-between-quota-disable-and-relocation.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-add-fams-validation-before-trying-to.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-add-fb_damage_clips-support.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-add-odm-case-when-looking-for-first-.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-add-pixel-rate-based-crb-allocation-.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-check-if-link-state-is-valid.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-copy-dc-context-in-the-commit-stream.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-enable-new-commit-sequence-only-for-.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-fix-dc-core-dc.c-kernel-doc.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-fix-dcn315-single-stream-crb-allocat.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-fix-possible-underflow-for-displays-.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-fix-unbounded-requesting-for-high-pi.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-include-surface-of-unaffected-stream.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-prevent-vtotal-from-being-set-to-0.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-rework-comments-on-dc-file.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-rework-context-change-check.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-set-minimum-requirement-for-using-ps.patch-26244 [new file with mode: 0644]
queue-6.1/drm-amd-display-update-correct-dcn314-register-heade.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-update-extended-blank-for-dcn314-onw.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-use-low-clocks-for-no-plane-configs.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-use-min-transition-for-all-subvp-pla.patch [new file with mode: 0644]
queue-6.1/drm-ttm-don-t-leak-a-resource-on-eviction-error.patch [new file with mode: 0644]
queue-6.1/drm-ttm-don-t-print-error-message-if-eviction-was-in.patch [new file with mode: 0644]
queue-6.1/drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch [new file with mode: 0644]
queue-6.1/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_re.patch [new file with mode: 0644]
queue-6.1/f2fs-fix-to-set-flush_merge-opt-and-show-noflush_mer.patch [new file with mode: 0644]
queue-6.1/gpio-mvebu-fix-irq-domain-leak.patch [new file with mode: 0644]
queue-6.1/gpio-mvebu-make-use-of-devm_pwmchip_add.patch [new file with mode: 0644]
queue-6.1/gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch [new file with mode: 0644]
queue-6.1/i2c-delete-error-messages-for-failed-memory-allocati.patch [new file with mode: 0644]
queue-6.1/i2c-improve-size-determinations.patch [new file with mode: 0644]
queue-6.1/i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch [new file with mode: 0644]
queue-6.1/i2c-nomadik-remove-unnecessary-goto-label.patch [new file with mode: 0644]
queue-6.1/i2c-nomadik-use-devm_clk_get_enabled.patch [new file with mode: 0644]
queue-6.1/io_uring-don-t-audit-the-capability-check-in-io_urin.patch [new file with mode: 0644]
queue-6.1/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch [new file with mode: 0644]
queue-6.1/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch [new file with mode: 0644]
queue-6.1/jbd2-remove-journal_clean_one_cp_list.patch [new file with mode: 0644]
queue-6.1/jbd2-remove-t_checkpoint_io_list.patch [new file with mode: 0644]
queue-6.1/kvm-arm64-condition-hw-af-updates-on-config-option.patch [new file with mode: 0644]
queue-6.1/kvm-s390-pv-fix-index-value-of-replaced-asce.patch [new file with mode: 0644]
queue-6.1/maple_tree-add-__init-and-__exit-to-test-module.patch [new file with mode: 0644]
queue-6.1/maple_tree-fix-32-bit-mas_next-testing.patch [new file with mode: 0644]
queue-6.1/mips-loongson-fix-build-error-when-make-modules_inst.patch [new file with mode: 0644]
queue-6.1/mips-loongson-move-arch-cflags-to-mips-top-level-mak.patch [new file with mode: 0644]
queue-6.1/mptcp-do-not-rely-on-implicit-state-check-in-mptcp_l.patch [new file with mode: 0644]
queue-6.1/mptcp-introduce-sk-to-replace-sock-sk-in-mptcp_liste.patch [new file with mode: 0644]
queue-6.1/n_tty-rename-tail-to-old_tail-in-n_tty_read.patch [new file with mode: 0644]
queue-6.1/pci-aspm-avoid-link-retraining-race.patch [new file with mode: 0644]
queue-6.1/pci-aspm-factor-out-pcie_wait_for_retrain.patch [new file with mode: 0644]
queue-6.1/pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch [new file with mode: 0644]
queue-6.1/pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch [new file with mode: 0644]
queue-6.1/pci-rockchip-fix-window-mapping-and-address-translat.patch [new file with mode: 0644]
queue-6.1/pci-rockchip-remove-writes-to-unused-registers.patch [new file with mode: 0644]
queue-6.1/powerpc-pseries-vas-hold-mmap_mutex-after-mmap-lock-.patch [new file with mode: 0644]
queue-6.1/revert-tracing-add-fault-name-injection-to-kernel-pr.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/test_maple_tree-test-modifications-while-iterating.patch [new file with mode: 0644]
queue-6.1/tracing-allow-synthetic-events-to-pass-around-stackt.patch [new file with mode: 0644]
queue-6.1/tracing-probes-add-symstr-type-for-dynamic-events.patch [new file with mode: 0644]
queue-6.1/tracing-probes-fix-to-avoid-double-count-of-the-stri.patch [new file with mode: 0644]
queue-6.1/tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch [new file with mode: 0644]
queue-6.1/tty-fix-hang-on-tty-device-with-no_room-set.patch [new file with mode: 0644]

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 (file)
index 0000000..31df269
--- /dev/null
@@ -0,0 +1,141 @@
+From 8829ccb3b9c4bcfd84dfaecb9a49ea18101de3f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Jun 2023 22:01:02 +0000
+Subject: arm64: errata: Mitigate Ampere1 erratum AC03_CPU_38 at stage-2
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+[ 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 <scott@os.amperecomputing.com>
+Cc: Darren Hart <darren@os.amperecomputing.com>
+Acked-by: D Scott Phillips <scott@os.amperecomputing.com>
+Acked-by: Catalin Marinas <catalin.marinas@arm.com>
+Link: https://lore.kernel.org/r/20230609220104.1836988-2-oliver.upton@linux.dev
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..8fd9420
--- /dev/null
@@ -0,0 +1,80 @@
+From c3a51ba545cbc4880bf6f3f8b7dc163a0fc54df3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jul 2023 11:11:06 +0100
+Subject: blk-mq: Fix stall due to recursive flush plug
+
+From: Ross Lagerwall <ross.lagerwall@citrix.com>
+
+[ 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 <ross.lagerwall@citrix.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://lore.kernel.org/r/20230714101106.3635611-1-ross.lagerwall@citrix.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1b8e0b1
--- /dev/null
@@ -0,0 +1,97 @@
+From 3da0e92b6cff7fd7c7f87a1078af35a7ead86c1e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Jun 2023 17:21:50 +0100
+Subject: btrfs: fix race between quota disable and relocation
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ 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 <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c06f6a1
--- /dev/null
@@ -0,0 +1,89 @@
+From c05420e425e8ef800827c2814c6bec4cc5ea510d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Mar 2023 14:29:52 -0600
+Subject: drm/amd/display: Add FAMS validation before trying to use it
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ 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 <Alvin.Lee2@amd.com>
+Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..4c89280
--- /dev/null
@@ -0,0 +1,227 @@
+From cf62a5e8b5cb62c024d7339eeff9d3fc385dd6c6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Nov 2022 11:58:45 -0500
+Subject: drm/amd/display: add FB_DAMAGE_CLIPS support
+
+From: Hamza Mahfooz <hamza.mahfooz@amd.com>
+
+[ 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 <sunpeng.li@amd.com>
+Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 72f1de49ffb9 ("drm/dp_mst: Clear MSG_RDY flag before sending new message")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..f7353ea
--- /dev/null
@@ -0,0 +1,151 @@
+From d2a46a3778836d36889ee76462a0ccf47ca8db73 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <samson.tam@amd.com>
+
+[ 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 <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Acked-by: Stylon Wang <stylon.wang@amd.com>
+Signed-off-by: Samson Tam <samson.tam@amd.com>
+Reviewed-by: Alvin Lee <Alvin.Lee2@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c      | 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 (file)
index 0000000..42afb11
--- /dev/null
@@ -0,0 +1,391 @@
+From 6d013ad79120cadd7270b91da6a78a7177ee26e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Dec 2022 15:13:18 -0500
+Subject: drm/amd/display: add pixel rate based CRB allocation support
+
+From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+
+[ 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 <daniel.wheeler@amd.com>
+Reviewed-by: Charlene Liu <Charlene.Liu@amd.com>
+Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 49f26218c344 ("drm/amd/display: fix dcn315 single stream crb allocation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..cdb4a23
--- /dev/null
@@ -0,0 +1,40 @@
+From 1c10da1197f03165f82ea759fa6c2bcee6523cd9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Oct 2022 08:28:15 -0400
+Subject: drm/amd/display: Check if link state is valid
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ 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 <harry.wentland@amd.com>
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Co-developed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..ed907b8
--- /dev/null
@@ -0,0 +1,122 @@
+From 9f5de78e3f4fbe0b8c0b26bb0e55c155b2ff668e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Oct 2022 08:28:18 -0400
+Subject: drm/amd/display: Copy DC context in the commit streams
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ 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 <harry.wentland@amd.com>
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Co-developed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..f2b7613
--- /dev/null
@@ -0,0 +1,120 @@
+From 4f5d90251965e0a6282d2742cc054482de4be588 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Oct 2022 08:28:17 -0400
+Subject: drm/amd/display: Enable new commit sequence only for DCN32x
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ 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 <harry.wentland@amd.com>
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Co-developed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..e8c048d
--- /dev/null
@@ -0,0 +1,169 @@
+From 5fd182401f71804be81cee4cecf6f4e2f169e2a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <rdunlap@infradead.org>
+
+[ 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 <rdunlap@infradead.org>
+Reported-by: kernel test robot <lkp@intel.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Leo Li <sunpeng.li@amd.com>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: "Pan, Xinhui" <Xinhui.Pan@amd.com>
+Cc: amd-gfx@lists.freedesktop.org
+Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..993eb74
--- /dev/null
@@ -0,0 +1,78 @@
+From 902df244de409cc229c1e962472d1abb7267bbcb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 May 2023 15:50:40 -0400
+Subject: drm/amd/display: fix dcn315 single stream crb allocation
+
+From: Dmytro Laktyushkin <dmytro.laktyushkin@amd.com>
+
+[ Upstream commit 49f26218c344741cb3eaa740b1e44e960551a87f ]
+
+Change to improve avoiding asymetric crb calculations for single stream
+scenarios.
+
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Acked-by: Stylon Wang <stylon.wang@amd.com>
+Signed-off-by: Dmytro Laktyushkin <dmytro.laktyushkin@amd.com>
+Reviewed-by: Charlene Liu <Charlene.Liu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..9a915e9
--- /dev/null
@@ -0,0 +1,77 @@
+From be2cf4aa4b228854ea43ceb55bb4d205cb2ef1ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Apr 2023 14:29:48 -0400
+Subject: drm/amd/display: Fix possible underflow for displays with large
+ vblank
+
+From: Daniel Miess <daniel.miess@amd.com>
+
+[ 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 <jun.lei@amd.com>
+Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Daniel Miess <daniel.miess@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..c4b7cbf
--- /dev/null
@@ -0,0 +1,68 @@
+From 8afb1be5e8773495b47113618466983efeee3b5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <Dmytro.Laktyushkin@amd.com>
+
+[ 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 <Jun.Lei@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 49f26218c344 ("drm/amd/display: fix dcn315 single stream crb allocation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..8f3a3d8
--- /dev/null
@@ -0,0 +1,112 @@
+From 2563a7dc444a6d78de8fdc29672e31e27e5e8214 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Oct 2022 08:28:19 -0400
+Subject: drm/amd/display: Include surface of unaffected streams
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ 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 <harry.wentland@amd.com>
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Co-developed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b0afe47
--- /dev/null
@@ -0,0 +1,51 @@
+From bb47b85a5460e6ccf91865c40d3a70501b375b67 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Jun 2023 08:11:48 -0400
+Subject: drm/amd/display: Prevent vtotal from being set to 0
+
+From: Daniel Miess <daniel.miess@amd.com>
+
+[ 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 <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Acked-by: Alan Liu <haoping.liu@amd.com>
+Signed-off-by: Daniel Miess <daniel.miess@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/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 (file)
index 0000000..dbf0372
--- /dev/null
@@ -0,0 +1,377 @@
+From bfaa2af68d7ac9bc043db1c7088c445b69687b85 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Oct 2022 16:27:59 -0400
+Subject: drm/amd/display: Rework comments on dc file
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ 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 <Rodrigo.Siqueira@amd.com>
+Reviewed-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..d95b93d
--- /dev/null
@@ -0,0 +1,67 @@
+From 4a51f0b34a3f301fcecc041a7c308bc9c8f8c226 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Oct 2022 08:28:16 -0400
+Subject: drm/amd/display: Rework context change check
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ 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 <harry.wentland@amd.com>
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Co-developed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..5e28fca
--- /dev/null
@@ -0,0 +1,153 @@
+From a771acaa89c3903963de8496fa1c50e7a9f0e815 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <mario.limonciello@amd.com>
+
+[ 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 <sean.ns.wang@amd.com>
+Cc: Marc Rossi <Marc.Rossi@amd.com>
+Cc: Hamza Mahfooz <Hamza.Mahfooz@amd.com>
+Cc: Tsung-hua (Ryan) Lin <Tsung-hua.Lin@amd.com>
+Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2443
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Leo Li <sunpeng.li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: cd2e31a9ab93 ("drm/amd/display: Set minimum requirement for using PSR-SU on Phoenix")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..02f2335
--- /dev/null
@@ -0,0 +1,68 @@
+From 58736d0e0fc2ab8a19aa9226d60baed3d196390c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <mario.limonciello@amd.com>
+
+[ 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 <sean.ns.wang@amd.com>
+Cc: Marc Rossi <Marc.Rossi@amd.com>
+Cc: Hamza Mahfooz <Hamza.Mahfooz@amd.com>
+Cc: Tsung-hua (Ryan) Lin <Tsung-hua.Lin@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Leo Li <sunpeng.li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..4984b49
--- /dev/null
@@ -0,0 +1,177 @@
+From 72339513bf1743628f689083a07a1be7f34f027c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 May 2023 23:33:46 +0800
+Subject: drm/amd/display: Update correct DCN314 register header
+
+From: Cruise Hung <cruise.hung@amd.com>
+
+[ Upstream commit 268182606f26434c5d3ebd0e86efcb0418dec487 ]
+
+[Why]
+The register header for DCN314 is not correct.
+
+[How]
+Update correct DCN314 register header.
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Cruise Hung <cruise.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: cd2e31a9ab93 ("drm/amd/display: Set minimum requirement for using PSR-SU on Phoenix")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..888c2b0
--- /dev/null
@@ -0,0 +1,288 @@
+From 1b07b3413ad27cefd26944b1ca1663f8286cdbdc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Apr 2023 17:03:06 -0400
+Subject: drm/amd/display: update extended blank for dcn314 onwards
+
+From: Gabe Teeger <gabe.teeger@amd.com>
+
+[ 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 <daniel.wheeler@amd.com>
+Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
+Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Gabe Teeger <gabe.teeger@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 2a9482e55968 ("drm/amd/display: Prevent vtotal from being set to 0")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..63038c4
--- /dev/null
@@ -0,0 +1,110 @@
+From f3958a879409f4e2a9259f1f533c59e2ce86c67c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Oct 2022 11:01:08 -0400
+Subject: drm/amd/display: use low clocks for no plane configs
+
+From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+
+[ Upstream commit 2641c7b7808191cba25ba28b82bb73ca294924cc ]
+
+Stream only configurations do not require DCFCLK, SOCCLK, DPPCLK
+or FCLK. They also always allow pstate change.
+
+Reviewed-by: Charlene Liu <Charlene.Liu@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 49f26218c344 ("drm/amd/display: fix dcn315 single stream crb allocation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..f14b4f6
--- /dev/null
@@ -0,0 +1,96 @@
+From a34b055c769326a98ff7028954075429d314182a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <Alvin.Lee2@amd.com>
+
+[ 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 <Jun.Lei@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 59de751e3845 ("drm/amd/display: add ODM case when looking for first split pipe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..902d173
--- /dev/null
@@ -0,0 +1,72 @@
+From 99d94688444cdb626d5aaf6f8f0f86aabb032d26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <thomas.hellstrom@linux.intel.com>
+
+[ 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 <andrey.grodzovsky@amd.com>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Christian Koenig <christian.koenig@amd.com>
+Cc: Huang Rui <ray.huang@amd.com>
+Cc: dri-devel@lists.freedesktop.org
+Cc: <stable@vger.kernel.org> # v5.15+
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Nirmoy Das <nirmoy.das@intel.com> #v1
+Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230626091450.14757-4-thomas.hellstrom@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..0436f57
--- /dev/null
@@ -0,0 +1,42 @@
+From 7d6910a9d6ec779bcc2b5864130ded7b8dafad62 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <thomas.hellstrom@linux.intel.com>
+
+[ 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 <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..a4d03a6
--- /dev/null
@@ -0,0 +1,46 @@
+From 674d706e905f0ee200ed03c47e98f8f9c8792299 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <christian.koenig@amd.com>
+
+[ 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 <christian.koenig@amd.com>
+Reported-by: Pelloux-Prayer, Pierre-Eric <Pierre-eric.Pelloux-prayer@amd.com>
+Tested-by: Pelloux-Prayer, Pierre-Eric <Pierre-eric.Pelloux-prayer@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Link: https://patchwork.freedesktop.org/patch/msgid/20230707120826.3701-1-christian.koenig@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..4c1b373
--- /dev/null
@@ -0,0 +1,141 @@
+From 190a3e3cce2680c50605abdac3275b70415585fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 May 2023 11:58:22 +0800
+Subject: f2fs: don't reset unchangable mount option in f2fs_remount()
+
+From: Chao Yu <chao@kernel.org>
+
+[ 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: <stable@vger.kernel.org>
+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 <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..a590d2d
--- /dev/null
@@ -0,0 +1,66 @@
+From 3345346778c41ffe5a9c6e5e52a99632d6c1518d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Nov 2022 17:15:01 +0800
+Subject: f2fs: fix to set flush_merge opt and show noflush_merge
+
+From: Yangtao Li <frank.li@vivo.com>
+
+[ 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 <chao@kernel.org>
+Signed-off-by: Yangtao Li <frank.li@vivo.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 458c15dfbce6 ("f2fs: don't reset unchangable mount option in f2fs_remount()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..0d08c6d
--- /dev/null
@@ -0,0 +1,77 @@
+From b4b7441e6d0f89aff513d68625c65e735b1aa4f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <bartosz.golaszewski@linaro.org>
+
+[ 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 <bartosz.golaszewski@linaro.org>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..84a2149
--- /dev/null
@@ -0,0 +1,61 @@
+From 224ebe66f38e1aa60d7929c9a9c16028fc64e0d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <u.kleine-koenig@pengutronix.de>
+
+[ 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 <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Andy Shevchenko <andy@kernel.org>
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..4797d51
--- /dev/null
@@ -0,0 +1,50 @@
+From 0308b3f35c5282b1daa1fd5bcbdaa4e26e8b228b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <hdegoede@redhat.com>
+
+[ 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 <andy.shevchenko@gmail.com>
+Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
+Tested-by: Daniel Scally <dan.scally@ideasonboard.com>
+Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..f53e450
--- /dev/null
@@ -0,0 +1,81 @@
+From 73c7cd9244a510e68456a92b13483fba660cc2d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Feb 2018 17:24:57 +0100
+Subject: i2c: Delete error messages for failed memory allocations
+
+From: Markus Elfring <elfring@users.sourceforge.net>
+
+[ Upstream commit 6b3b21a8542fd2fb6ffc61bc13b9419f0c58ebad ]
+
+These issues were detected by using the Coccinelle software.
+
+Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..8a8cfb5
--- /dev/null
@@ -0,0 +1,54 @@
+From 76391e4d78f23ae740ef7f07b6e4c2731628ec4d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Feb 2018 14:50:09 +0100
+Subject: i2c: Improve size determinations
+
+From: Markus Elfring <elfring@users.sourceforge.net>
+
+[ 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 <elfring@users.sourceforge.net>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..2922bc4
--- /dev/null
@@ -0,0 +1,49 @@
+From edaaa54c28b5b792b3cd932bd38511c4e67412a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jul 2023 21:50:28 +0200
+Subject: i2c: nomadik: Remove a useless call in the remove function
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ 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: <stable@vger.kernel.org> # v3.6+
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Reviewed-by: Andi Shyti <andi.shyti@kernel.org>
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..8777d36
--- /dev/null
@@ -0,0 +1,85 @@
+From f0fec396cc9dadd1f61b1af9d6f04ebdd0d473f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 11 Jun 2023 03:36:59 +0200
+Subject: i2c: nomadik: Remove unnecessary goto label
+
+From: Andi Shyti <andi.shyti@kernel.org>
+
+[ Upstream commit 1c5d33fff0d375e4ab7c4261dc62a286babbb4c6 ]
+
+The err_no_mem goto label doesn't do anything. Remove it.
+
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..462dc64
--- /dev/null
@@ -0,0 +1,76 @@
+From 09d2f0f15de6abcfb5022e067b36b1d196396dee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 11 Jun 2023 03:37:00 +0200
+Subject: i2c: nomadik: Use devm_clk_get_enabled()
+
+From: Andi Shyti <andi.shyti@kernel.org>
+
+[ 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 <andi.shyti@kernel.org>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b8c1d6e
--- /dev/null
@@ -0,0 +1,47 @@
+From 1324feea7eaba5e6c48fca0af8b85fdc28a0cdcc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <omosnace@redhat.com>
+
+[ 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 <omosnace@redhat.com>
+Reviewed-by: Jeff Moyer <jmoyer@redhat.com>
+Link: https://lore.kernel.org/r/20230718115607.65652-1-omosnace@redhat.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..6dc28c3
--- /dev/null
@@ -0,0 +1,150 @@
+From 4925d566f7e303289ee5d4aabcf8e2f24544331b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Jun 2023 21:59:27 +0800
+Subject: jbd2: fix a race when checking checkpoint buffer busy
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ 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 <jack@suse.cz>
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20230606135928.434610-6-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..474f6eb
--- /dev/null
@@ -0,0 +1,106 @@
+From 25cc3f564e96e47e88122e7e0f0f885003315344 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Jun 2023 21:59:26 +0800
+Subject: jbd2: Fix wrongly judgement for buffer head removing while doing
+ checkpoint
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+[ 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 <chengzhihao1@huawei.com>
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20230606135928.434610-5-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..222f59b
--- /dev/null
@@ -0,0 +1,235 @@
+From 7f2e7e3be85c2c0af0b6cd4c8b69de00ec06408c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Jun 2023 21:59:25 +0800
+Subject: jbd2: remove journal_clean_one_cp_list()
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ 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 <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20230606135928.434610-4-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1a5ecd8
--- /dev/null
@@ -0,0 +1,146 @@
+From 0c9838fba04567f1905865f0b3a659724945c8a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Jun 2023 21:59:24 +0800
+Subject: jbd2: remove t_checkpoint_io_list
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ 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 <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20230606135928.434610-3-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..58bb939
--- /dev/null
@@ -0,0 +1,47 @@
+From bdcdd5243d15a72a4d07901861d1b23f21cd8420 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Dec 2022 18:51:56 +0000
+Subject: KVM: arm64: Condition HW AF updates on config option
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+[ 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 <oliver.upton@linux.dev>
+Stable-dep-of: 6df696cd9bc1 ("arm64: errata: Mitigate Ampere1 erratum AC03_CPU_38 at stage-2")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c2e28c3
--- /dev/null
@@ -0,0 +1,46 @@
+From cb7919a0732e71660bd810bf4580506730834ad6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <imbrenda@linux.ibm.com>
+
+[ 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é <philmd@linaro.org>
+Fixes: faa2f72cb356 ("KVM: s390: pv: leak the topmost page table when destroy fails")
+Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
+Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
+Message-ID: <20230705111937.33472-3-imbrenda@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..321d2b1
--- /dev/null
@@ -0,0 +1,1166 @@
+From a0afdf577dc92d040266faac2179cd28a94fb1b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 May 2023 10:55:28 -0400
+Subject: maple_tree: add __init and __exit to test module
+
+From: Liam R. Howlett <Liam.Howlett@oracle.com>
+
+[ 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 <Liam.Howlett@oracle.com>
+Suggested-by: Andrew Morton <akpm@linux-foundation.org>
+Cc: David Binderman <dcb314@hotmail.com>
+Cc: Peng Zhang <zhangpeng.00@bytedance.com>
+Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
+Cc: Vernon Yang <vernon2gm@gmail.com>
+Cc: Wei Yang <richard.weiyang@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 7a93c71a6714 ("maple_tree: fix 32 bit mas_next testing")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <stdlib.h>
+ #include <time.h>
++#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 (file)
index 0000000..a24956e
--- /dev/null
@@ -0,0 +1,62 @@
+From d650f4d3fb494487e315e028161beb0c7227cbd0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jul 2023 13:39:15 -0400
+Subject: maple_tree: fix 32 bit mas_next testing
+
+From: Liam R. Howlett <Liam.Howlett@oracle.com>
+
+[ 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 <Liam.Howlett@oracle.com>
+Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
+  Closes: https://lore.kernel.org/linux-mm/CAMuHMdV4T53fOw7VPoBgPR7fP6RYqf=CBhD_y_vOg53zZX_DnA@mail.gmail.com/
+Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..f9e9b31
--- /dev/null
@@ -0,0 +1,75 @@
+From 54d5cfc029cd677f65031d4bde4a177435b03366 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jun 2023 19:08:47 +0800
+Subject: MIPS: Loongson: Fix build error when make modules_install
+
+From: Huacai Chen <chenhuacai@loongson.cn>
+
+[ 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 <chenfeiyang@loongson.cn>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Reviewed-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..93b19dc
--- /dev/null
@@ -0,0 +1,146 @@
+From 3ab187b9e6b8f79e31a15d3fc5332a244400de1b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Apr 2023 10:33:47 +0100
+Subject: MIPS: Loongson: Move arch cflags to MIPS top level Makefile
+
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+
+[ Upstream commit 194a835210521282ad31e8f7047556318611f596 ]
+
+Arch cflags should be independent to Platform.
+
+Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Stable-dep-of: 531b3d1195d0 ("MIPS: Loongson: Fix build error when make modules_install")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b6be4d0
--- /dev/null
@@ -0,0 +1,60 @@
+From 07ac84cfbb62721380cca3bd9b5be0c4281e59ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jul 2023 22:44:34 +0200
+Subject: mptcp: do not rely on implicit state check in mptcp_listen()
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+[ 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 <cpaasch@apple.com>
+Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/414
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..383bf82
--- /dev/null
@@ -0,0 +1,66 @@
+From 3ee3877812262cf4e97cac8ecf4088abdd83b250 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jan 2023 10:57:20 -0800
+Subject: mptcp: introduce 'sk' to replace 'sock->sk' in mptcp_listen()
+
+From: Menglong Dong <imagedong@tencent.com>
+
+[ 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 <pabeni@redhat.com>
+Signed-off-by: Menglong Dong <imagedong@tencent.com>
+Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 0226436acf24 ("mptcp: do not rely on implicit state check in mptcp_listen()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..f84a23e
--- /dev/null
@@ -0,0 +1,60 @@
+From 70ca5d0f3e30d10e739672853e4e9dcaf123e2a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <ilpo.jarvinen@linux.intel.com>
+
+[ 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 <ilpo.jarvinen@linux.intel.com>
+Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/22b37499-ff9a-7fc1-f6e0-58411328d122@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 4903fde8047a ("tty: fix hang on tty device with no_room set")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..39f9acd
--- /dev/null
@@ -0,0 +1,64 @@
+From a21b55e0babbdd7552c35a62c909c6392a749bb1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <ilpo.jarvinen@linux.intel.com>
+
+[ 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 <lukas@wunner.de>
+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 <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Lukas Wunner <lukas@wunner.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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, &reg16);
+       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 (file)
index 0000000..00fb895
--- /dev/null
@@ -0,0 +1,79 @@
+From cdab9306ee0388e9c438dd815e47561c0710420f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <ilpo.jarvinen@linux.intel.com>
+
+[ 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 <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Stable-dep-of: e7e39756363a ("PCI/ASPM: Avoid link retraining race")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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, &reg16);
++              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, &reg16);
+@@ -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, &reg16);
+-              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 (file)
index 0000000..5bb87b0
--- /dev/null
@@ -0,0 +1,72 @@
+From 573a17f54e442153ae8efba3f21a9a6d375a9020 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jun 2023 14:44:55 -0500
+Subject: PCI/ASPM: Return 0 or -ETIMEDOUT from pcie_retrain_link()
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+[ 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 <bhelgaas@google.com>
+Stable-dep-of: e7e39756363a ("PCI/ASPM: Avoid link retraining race")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..4014cf8
--- /dev/null
@@ -0,0 +1,103 @@
+From 39ddd3b7581fff5dab5a7abd8af41a54903addcb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Apr 2023 09:46:57 +0200
+Subject: PCI: rockchip: Don't advertise MSI-X in PCIe capabilities
+
+From: Rick Wertenbroek <rick.wertenbroek@gmail.com>
+
+[ 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 <dlemoal@kernel.org>
+Signed-off-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
+Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c4863c4
--- /dev/null
@@ -0,0 +1,340 @@
+From 87f26488d8e5089d8df8a93d3f347d31f62dfd8e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Apr 2023 09:46:55 +0200
+Subject: PCI: rockchip: Fix window mapping and address translation for
+ endpoint
+
+From: Rick Wertenbroek <rick.wertenbroek@gmail.com>
+
+[ 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 <dlemoal@kernel.org>
+Signed-off-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
+Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..a7112fa
--- /dev/null
@@ -0,0 +1,55 @@
+From ef042f7fd761e3d021d6e9fcc3664bfa2f359e33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Apr 2023 09:46:48 +0200
+Subject: PCI: rockchip: Remove writes to unused registers
+
+From: Rick Wertenbroek <rick.wertenbroek@gmail.com>
+
+[ 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 <dlemoal@kernel.org>
+Signed-off-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
+Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Stable-dep-of: dc73ed0f1b8b ("PCI: rockchip: Fix window mapping and address translation for endpoint")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1a4a64d
--- /dev/null
@@ -0,0 +1,88 @@
+From 92eef53a4b8f140cbbda7fb1f9f886145fd8d44d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <haren@linux.ibm.com>
+
+[ 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 <haren@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20230716100506.7833-1-haren@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..bec03ae
--- /dev/null
@@ -0,0 +1,135 @@
+From d9f3f3f51b37dea174f11d920827dc2b3657873f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jul 2023 23:15:57 +0900
+Subject: Revert "tracing: Add "(fault)" name injection to kernel probes"
+
+From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+
+[ 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 <akpm@linux-foundation.org>
+Cc: Tom Zanussi <zanussi@kernel.org>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Stable-dep-of: 797311bce5c2 ("tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
index 5ca43b3a80d75c483c504f4bf184b90c3478d13a..86cd355f120c53640e1f54aceb346505c83032e5 100644 (file)
@@ -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 (file)
index 0000000..b2d37dc
--- /dev/null
@@ -0,0 +1,114 @@
+From d8d4821234c35de1c1ae1c6863d75aff9e2043aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Jan 2023 11:26:05 -0500
+Subject: test_maple_tree: test modifications while iterating
+
+From: Liam R. Howlett <Liam.Howlett@Oracle.com>
+
+[ 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 <Liam.Howlett@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 7a93c71a6714 ("maple_tree: fix 32 bit mas_next testing")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..111a3d5
--- /dev/null
@@ -0,0 +1,282 @@
+From 98dbd287cf8b627361419f174c25886ce13b2636 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Jan 2023 10:21:28 -0500
+Subject: tracing: Allow synthetic events to pass around stacktraces
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ 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
+
+           <idle>-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 <mhiramat@kernel.org>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Tom Zanussi <zanussi@kernel.org>
+Cc: Ross Zwisler <zwisler@google.com>
+Cc: Ching-lin Yu <chinglinyu@google.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Stable-dep-of: 797311bce5c2 ("tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b89892f
--- /dev/null
@@ -0,0 +1,313 @@
+From f1afb8269358befddf9704b4cd16157fbb66afd4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Nov 2022 13:47:56 +0900
+Subject: tracing/probes: Add symstr type for dynamic events
+
+From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+
+[ 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) <mhiramat@kernel.org>
+Stable-dep-of: 66bcf65d6cf0 ("tracing/probes: Fix to avoid double count of the string length on the array")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n"
+       "\t     type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n"
+       "\t           b<bit-width>@<bit-offset>/<container-size>, ustring,\n"
+-      "\t           <type>\\[<array-size>\\]\n"
++      "\t           symstr, <type>\\[<array-size>\\]\n"
+ #ifdef CONFIG_HIST_TRIGGERS
+       "\t    field: <stype> <name>;\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 (file)
index 0000000..1c3e9a5
--- /dev/null
@@ -0,0 +1,49 @@
+From 4631295e4a3bf6c42f4305ed5939670b4a393777 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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) <mhiramat@kernel.org>
+
+[ 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 <dan.carpenter@linaro.org>
+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) <mhiramat@kernel.org>
+Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..e531ca3
--- /dev/null
@@ -0,0 +1,109 @@
+From f59ea2be49600590e034dc4800482b66bd3c5b7e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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) <mhiramat@kernel.org>
+
+[ 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) <rostedt@goodmis.org>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..e237216
--- /dev/null
@@ -0,0 +1,116 @@
+From bf4955264cc7b148c2f51b5c5e075471a8116236 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <caelli@tencent.com>
+
+[ 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: <stable@vger.kernel.org>
+Fixes: 42458f41d08f ("n_tty: Ensure reader restarts worker for next reader")
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Hui Li <caelli@tencent.com>
+Message-ID: <1680749090-14106-1-git-send-email-caelli@tencent.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+