]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 9 Nov 2024 15:08:45 +0000 (16:08 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 9 Nov 2024 15:08:45 +0000 (16:08 +0100)
added patches:
alsa-usb-audio-add-quirk-for-hp-320-fhd-webcam.patch
dm-cache-correct-the-number-of-origin-blocks-to-match-the-target-length.patch
dm-cache-fix-flushing-uninitialized-delayed_work-on-cache_ctr-error.patch
dm-cache-fix-out-of-bounds-access-to-the-dirty-bitset-when-resizing.patch
dm-cache-fix-potential-out-of-bounds-access-on-the-first-resume.patch
dm-cache-optimize-dirty-bit-checking-with-find_next_bit-when-resizing.patch
dm-fix-a-crash-if-blk_alloc_disk-fails.patch
dm-unstriped-cast-an-operand-to-sector_t-to-prevent-potential-uint32_t-overflow.patch
drm-amd-display-fix-brightness-level-not-retained-over-reboot.patch
drm-amd-display-parse-umc_info-or-vram_info-based-on-asic.patch
drm-amd-pm-always-pick-the-pptable-from-ifwi.patch
drm-amd-pm-correct-the-workload-setting.patch
drm-amdgpu-add-missing-size-check-in-amdgpu_debugfs_gprwave_read.patch
drm-amdgpu-adjust-debugfs-eviction-and-ib-access-permissions.patch
drm-amdgpu-adjust-debugfs-register-access-permissions.patch
drm-amdgpu-fix-dpx-valid-mode-check-on-gc-9.4.3.patch
drm-amdgpu-prevent-null-pointer-dereference-if-atif-is-not-supported.patch
drm-imagination-add-a-per-file-pvr-context-list.patch
drm-imagination-break-an-object-reference-loop.patch
drm-panthor-be-stricter-about-io-mapping-flags.patch
drm-panthor-lock-xarray-when-getting-entries-for-the-vm.patch
keys-trusted-dcp-fix-null-dereference-in-aead-crypto-operation.patch
mptcp-no-admin-perm-to-list-endpoints.patch
pwm-imx-tpm-use-correct-modulo-value-for-epwm-mode.patch
rpmsg-glink-handle-rejected-intent-request-better.patch
thermal-drivers-qcom-lmh-remove-false-lockdep-backtrace.patch
tpm-lock-tpm-chip-in-tpm_pm_suspend-first.patch

28 files changed:
queue-6.11/alsa-usb-audio-add-quirk-for-hp-320-fhd-webcam.patch [new file with mode: 0644]
queue-6.11/dm-cache-correct-the-number-of-origin-blocks-to-match-the-target-length.patch [new file with mode: 0644]
queue-6.11/dm-cache-fix-flushing-uninitialized-delayed_work-on-cache_ctr-error.patch [new file with mode: 0644]
queue-6.11/dm-cache-fix-out-of-bounds-access-to-the-dirty-bitset-when-resizing.patch [new file with mode: 0644]
queue-6.11/dm-cache-fix-potential-out-of-bounds-access-on-the-first-resume.patch [new file with mode: 0644]
queue-6.11/dm-cache-optimize-dirty-bit-checking-with-find_next_bit-when-resizing.patch [new file with mode: 0644]
queue-6.11/dm-fix-a-crash-if-blk_alloc_disk-fails.patch [new file with mode: 0644]
queue-6.11/dm-unstriped-cast-an-operand-to-sector_t-to-prevent-potential-uint32_t-overflow.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-fix-brightness-level-not-retained-over-reboot.patch [new file with mode: 0644]
queue-6.11/drm-amd-display-parse-umc_info-or-vram_info-based-on-asic.patch [new file with mode: 0644]
queue-6.11/drm-amd-pm-always-pick-the-pptable-from-ifwi.patch [new file with mode: 0644]
queue-6.11/drm-amd-pm-correct-the-workload-setting.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-add-missing-size-check-in-amdgpu_debugfs_gprwave_read.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-adjust-debugfs-eviction-and-ib-access-permissions.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-adjust-debugfs-register-access-permissions.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-fix-dpx-valid-mode-check-on-gc-9.4.3.patch [new file with mode: 0644]
queue-6.11/drm-amdgpu-prevent-null-pointer-dereference-if-atif-is-not-supported.patch [new file with mode: 0644]
queue-6.11/drm-imagination-add-a-per-file-pvr-context-list.patch [new file with mode: 0644]
queue-6.11/drm-imagination-break-an-object-reference-loop.patch [new file with mode: 0644]
queue-6.11/drm-panthor-be-stricter-about-io-mapping-flags.patch [new file with mode: 0644]
queue-6.11/drm-panthor-lock-xarray-when-getting-entries-for-the-vm.patch [new file with mode: 0644]
queue-6.11/keys-trusted-dcp-fix-null-dereference-in-aead-crypto-operation.patch [new file with mode: 0644]
queue-6.11/mptcp-no-admin-perm-to-list-endpoints.patch [new file with mode: 0644]
queue-6.11/pwm-imx-tpm-use-correct-modulo-value-for-epwm-mode.patch [new file with mode: 0644]
queue-6.11/rpmsg-glink-handle-rejected-intent-request-better.patch [new file with mode: 0644]
queue-6.11/series
queue-6.11/thermal-drivers-qcom-lmh-remove-false-lockdep-backtrace.patch [new file with mode: 0644]
queue-6.11/tpm-lock-tpm-chip-in-tpm_pm_suspend-first.patch [new file with mode: 0644]

diff --git a/queue-6.11/alsa-usb-audio-add-quirk-for-hp-320-fhd-webcam.patch b/queue-6.11/alsa-usb-audio-add-quirk-for-hp-320-fhd-webcam.patch
new file mode 100644 (file)
index 0000000..cf6dab8
--- /dev/null
@@ -0,0 +1,45 @@
+From dabc44c28f118910dea96244d903f0c270225669 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 5 Nov 2024 13:02:17 +0100
+Subject: ALSA: usb-audio: Add quirk for HP 320 FHD Webcam
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit dabc44c28f118910dea96244d903f0c270225669 upstream.
+
+HP 320 FHD Webcam (03f0:654a) seems to have flaky firmware like other
+webcam devices that don't like the frequency inquiries.  Also, Mic
+Capture Volume has an invalid resolution, hence fix it to be 16 (as a
+blind shot).
+
+Link: https://bugzilla.suse.com/show_bug.cgi?id=1232768
+Cc: <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20241105120220.5740-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer.c  |    1 +
+ sound/usb/quirks.c |    2 ++
+ 2 files changed, 3 insertions(+)
+
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -1205,6 +1205,7 @@ static void volume_control_quirks(struct
+               }
+               break;
+       case USB_ID(0x1bcf, 0x2283): /* NexiGo N930AF FHD Webcam */
++      case USB_ID(0x03f0, 0x654a): /* HP 320 FHD Webcam */
+               if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+                       usb_audio_info(chip,
+                               "set resolution quirk: cval->res = 16\n");
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2114,6 +2114,8 @@ struct usb_audio_quirk_flags_table {
+ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+       /* Device matches */
++      DEVICE_FLG(0x03f0, 0x654a, /* HP 320 FHD Webcam */
++                 QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
diff --git a/queue-6.11/dm-cache-correct-the-number-of-origin-blocks-to-match-the-target-length.patch b/queue-6.11/dm-cache-correct-the-number-of-origin-blocks-to-match-the-target-length.patch
new file mode 100644 (file)
index 0000000..49538b5
--- /dev/null
@@ -0,0 +1,100 @@
+From 235d2e739fcbe964c9ce179b4c991025662dcdb6 Mon Sep 17 00:00:00 2001
+From: Ming-Hung Tsai <mtsai@redhat.com>
+Date: Tue, 22 Oct 2024 15:12:22 +0800
+Subject: dm cache: correct the number of origin blocks to match the target length
+
+From: Ming-Hung Tsai <mtsai@redhat.com>
+
+commit 235d2e739fcbe964c9ce179b4c991025662dcdb6 upstream.
+
+When creating a cache device, the actual size of the cache origin might
+be greater than the specified cache target length. In such case, the
+number of origin blocks should match the cache target length, not the
+full size of the origin device, since access beyond the cache target is
+not possible. This issue occurs when reducing the origin device size
+using lvm, as lvreduce preloads the new cache table before resuming the
+cache origin, which can result in incorrect sizes for the discard bitset
+and smq hotspot blocks.
+
+Reproduce steps:
+
+1. create a cache device consists of 4096 origin blocks
+
+dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
+dmsetup create cdata --table "0 65536 linear /dev/sdc 8192"
+dmsetup create corig --table "0 524288 linear /dev/sdc 262144"
+dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct
+dmsetup create cache --table "0 524288 cache /dev/mapper/cmeta \
+/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"
+
+2. reduce the cache origin to 2048 oblocks, in lvreduce's approach
+
+dmsetup reload corig --table "0 262144 linear /dev/sdc 262144"
+dmsetup reload cache --table "0 262144 cache /dev/mapper/cmeta \
+/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"
+dmsetup suspend cache
+dmsetup suspend corig
+dmsetup suspend cdata
+dmsetup suspend cmeta
+dmsetup resume corig
+dmsetup resume cdata
+dmsetup resume cmeta
+dmsetup resume cache
+
+3. shutdown the cache, and check the number of discard blocks in
+   superblock. The value is expected to be 2048, but actually is 4096.
+
+dmsetup remove cache corig cdata cmeta
+dd if=/dev/sdc bs=1c count=8 skip=224 2>/dev/null | hexdump -e '1/8 "%u\n"'
+
+Fix by correcting the origin_blocks initialization in cache_create and
+removing the unused origin_sectors from struct cache_args accordingly.
+
+Signed-off-by: Ming-Hung Tsai <mtsai@redhat.com>
+Fixes: c6b4fcbad044 ("dm: add cache target")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Acked-by: Joe Thornber <thornber@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-cache-target.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/md/dm-cache-target.c
++++ b/drivers/md/dm-cache-target.c
+@@ -2003,7 +2003,6 @@ struct cache_args {
+       sector_t cache_sectors;
+       struct dm_dev *origin_dev;
+-      sector_t origin_sectors;
+       uint32_t block_size;
+@@ -2084,6 +2083,7 @@ static int parse_cache_dev(struct cache_
+ static int parse_origin_dev(struct cache_args *ca, struct dm_arg_set *as,
+                           char **error)
+ {
++      sector_t origin_sectors;
+       int r;
+       if (!at_least_one_arg(as, error))
+@@ -2096,8 +2096,8 @@ static int parse_origin_dev(struct cache
+               return r;
+       }
+-      ca->origin_sectors = get_dev_size(ca->origin_dev);
+-      if (ca->ti->len > ca->origin_sectors) {
++      origin_sectors = get_dev_size(ca->origin_dev);
++      if (ca->ti->len > origin_sectors) {
+               *error = "Device size larger than cached device";
+               return -EINVAL;
+       }
+@@ -2407,7 +2407,7 @@ static int cache_create(struct cache_arg
+       ca->metadata_dev = ca->origin_dev = ca->cache_dev = NULL;
+-      origin_blocks = cache->origin_sectors = ca->origin_sectors;
++      origin_blocks = cache->origin_sectors = ti->len;
+       origin_blocks = block_div(origin_blocks, ca->block_size);
+       cache->origin_blocks = to_oblock(origin_blocks);
diff --git a/queue-6.11/dm-cache-fix-flushing-uninitialized-delayed_work-on-cache_ctr-error.patch b/queue-6.11/dm-cache-fix-flushing-uninitialized-delayed_work-on-cache_ctr-error.patch
new file mode 100644 (file)
index 0000000..4e0f1ed
--- /dev/null
@@ -0,0 +1,107 @@
+From 135496c208ba26fd68cdef10b64ed7a91ac9a7ff Mon Sep 17 00:00:00 2001
+From: Ming-Hung Tsai <mtsai@redhat.com>
+Date: Tue, 22 Oct 2024 15:12:49 +0800
+Subject: dm cache: fix flushing uninitialized delayed_work on cache_ctr error
+
+From: Ming-Hung Tsai <mtsai@redhat.com>
+
+commit 135496c208ba26fd68cdef10b64ed7a91ac9a7ff upstream.
+
+An unexpected WARN_ON from flush_work() may occur when cache creation
+fails, caused by destroying the uninitialized delayed_work waker in the
+error path of cache_create(). For example, the warning appears on the
+superblock checksum error.
+
+Reproduce steps:
+
+dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
+dmsetup create cdata --table "0 65536 linear /dev/sdc 8192"
+dmsetup create corig --table "0 524288 linear /dev/sdc 262144"
+dd if=/dev/urandom of=/dev/mapper/cmeta bs=4k count=1 oflag=direct
+dmsetup create cache --table "0 524288 cache /dev/mapper/cmeta \
+/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"
+
+Kernel logs:
+
+(snip)
+WARNING: CPU: 0 PID: 84 at kernel/workqueue.c:4178 __flush_work+0x5d4/0x890
+
+Fix by pulling out the cancel_delayed_work_sync() from the constructor's
+error path. This patch doesn't affect the use-after-free fix for
+concurrent dm_resume and dm_destroy (commit 6a459d8edbdb ("dm cache: Fix
+UAF in destroy()")) as cache_dtr is not changed.
+
+Signed-off-by: Ming-Hung Tsai <mtsai@redhat.com>
+Fixes: 6a459d8edbdb ("dm cache: Fix UAF in destroy()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Acked-by: Joe Thornber <thornber@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-cache-target.c |   24 +++++++++++++++---------
+ 1 file changed, 15 insertions(+), 9 deletions(-)
+
+--- a/drivers/md/dm-cache-target.c
++++ b/drivers/md/dm-cache-target.c
+@@ -1905,16 +1905,13 @@ static void check_migrations(struct work
+  * This function gets called on the error paths of the constructor, so we
+  * have to cope with a partially initialised struct.
+  */
+-static void destroy(struct cache *cache)
++static void __destroy(struct cache *cache)
+ {
+-      unsigned int i;
+-
+       mempool_exit(&cache->migration_pool);
+       if (cache->prison)
+               dm_bio_prison_destroy_v2(cache->prison);
+-      cancel_delayed_work_sync(&cache->waker);
+       if (cache->wq)
+               destroy_workqueue(cache->wq);
+@@ -1942,13 +1939,22 @@ static void destroy(struct cache *cache)
+       if (cache->policy)
+               dm_cache_policy_destroy(cache->policy);
++      bioset_exit(&cache->bs);
++
++      kfree(cache);
++}
++
++static void destroy(struct cache *cache)
++{
++      unsigned int i;
++
++      cancel_delayed_work_sync(&cache->waker);
++
+       for (i = 0; i < cache->nr_ctr_args ; i++)
+               kfree(cache->ctr_args[i]);
+       kfree(cache->ctr_args);
+-      bioset_exit(&cache->bs);
+-
+-      kfree(cache);
++      __destroy(cache);
+ }
+ static void cache_dtr(struct dm_target *ti)
+@@ -2561,7 +2567,7 @@ static int cache_create(struct cache_arg
+       *result = cache;
+       return 0;
+ bad:
+-      destroy(cache);
++      __destroy(cache);
+       return r;
+ }
+@@ -2612,7 +2618,7 @@ static int cache_ctr(struct dm_target *t
+       r = copy_ctr_args(cache, argc - 3, (const char **)argv + 3);
+       if (r) {
+-              destroy(cache);
++              __destroy(cache);
+               goto out;
+       }
diff --git a/queue-6.11/dm-cache-fix-out-of-bounds-access-to-the-dirty-bitset-when-resizing.patch b/queue-6.11/dm-cache-fix-out-of-bounds-access-to-the-dirty-bitset-when-resizing.patch
new file mode 100644 (file)
index 0000000..a055f93
--- /dev/null
@@ -0,0 +1,80 @@
+From 792227719725497ce10a8039803bec13f89f8910 Mon Sep 17 00:00:00 2001
+From: Ming-Hung Tsai <mtsai@redhat.com>
+Date: Tue, 22 Oct 2024 15:13:16 +0800
+Subject: dm cache: fix out-of-bounds access to the dirty bitset when resizing
+
+From: Ming-Hung Tsai <mtsai@redhat.com>
+
+commit 792227719725497ce10a8039803bec13f89f8910 upstream.
+
+dm-cache checks the dirty bits of the cache blocks to be dropped when
+shrinking the fast device, but an index bug in bitset iteration causes
+out-of-bounds access.
+
+Reproduce steps:
+
+1. create a cache device of 1024 cache blocks (128 bytes dirty bitset)
+
+dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
+dmsetup create cdata --table "0 131072 linear /dev/sdc 8192"
+dmsetup create corig --table "0 524288 linear /dev/sdc 262144"
+dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct
+dmsetup create cache --table "0 524288 cache /dev/mapper/cmeta \
+/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"
+
+2. shrink the fast device to 512 cache blocks, triggering out-of-bounds
+   access to the dirty bitset (offset 0x80)
+
+dmsetup suspend cache
+dmsetup reload cdata --table "0 65536 linear /dev/sdc 8192"
+dmsetup resume cdata
+dmsetup resume cache
+
+KASAN reports:
+
+  BUG: KASAN: vmalloc-out-of-bounds in cache_preresume+0x269/0x7b0
+  Read of size 8 at addr ffffc900000f3080 by task dmsetup/131
+
+  (...snip...)
+  The buggy address belongs to the virtual mapping at
+   [ffffc900000f3000, ffffc900000f5000) created by:
+   cache_ctr+0x176a/0x35f0
+
+  (...snip...)
+  Memory state around the buggy address:
+   ffffc900000f2f80: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+   ffffc900000f3000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  >ffffc900000f3080: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+                     ^
+   ffffc900000f3100: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+   ffffc900000f3180: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+
+Fix by making the index post-incremented.
+
+Signed-off-by: Ming-Hung Tsai <mtsai@redhat.com>
+Fixes: f494a9c6b1b6 ("dm cache: cache shrinking support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Acked-by: Joe Thornber <thornber@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-cache-target.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/md/dm-cache-target.c
++++ b/drivers/md/dm-cache-target.c
+@@ -2912,13 +2912,13 @@ static bool can_resize(struct cache *cac
+        * We can't drop a dirty block when shrinking the cache.
+        */
+       while (from_cblock(new_size) < from_cblock(cache->cache_size)) {
+-              new_size = to_cblock(from_cblock(new_size) + 1);
+               if (is_dirty(cache, new_size)) {
+                       DMERR("%s: unable to shrink cache; cache block %llu is dirty",
+                             cache_device_name(cache),
+                             (unsigned long long) from_cblock(new_size));
+                       return false;
+               }
++              new_size = to_cblock(from_cblock(new_size) + 1);
+       }
+       return true;
diff --git a/queue-6.11/dm-cache-fix-potential-out-of-bounds-access-on-the-first-resume.patch b/queue-6.11/dm-cache-fix-potential-out-of-bounds-access-on-the-first-resume.patch
new file mode 100644 (file)
index 0000000..c993874
--- /dev/null
@@ -0,0 +1,137 @@
+From c0ade5d98979585d4f5a93e4514c2e9a65afa08d Mon Sep 17 00:00:00 2001
+From: Ming-Hung Tsai <mtsai@redhat.com>
+Date: Tue, 22 Oct 2024 15:13:54 +0800
+Subject: dm cache: fix potential out-of-bounds access on the first resume
+
+From: Ming-Hung Tsai <mtsai@redhat.com>
+
+commit c0ade5d98979585d4f5a93e4514c2e9a65afa08d upstream.
+
+Out-of-bounds access occurs if the fast device is expanded unexpectedly
+before the first-time resume of the cache table. This happens because
+expanding the fast device requires reloading the cache table for
+cache_create to allocate new in-core data structures that fit the new
+size, and the check in cache_preresume is not performed during the
+first resume, leading to the issue.
+
+Reproduce steps:
+
+1. prepare component devices:
+
+dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
+dmsetup create cdata --table "0 65536 linear /dev/sdc 8192"
+dmsetup create corig --table "0 524288 linear /dev/sdc 262144"
+dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct
+
+2. load a cache table of 512 cache blocks, and deliberately expand the
+   fast device before resuming the cache, making the in-core data
+   structures inadequate.
+
+dmsetup create cache --notable
+dmsetup reload cache --table "0 524288 cache /dev/mapper/cmeta \
+/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"
+dmsetup reload cdata --table "0 131072 linear /dev/sdc 8192"
+dmsetup resume cdata
+dmsetup resume cache
+
+3. suspend the cache to write out the in-core dirty bitset and hint
+   array, leading to out-of-bounds access to the dirty bitset at offset
+   0x40:
+
+dmsetup suspend cache
+
+KASAN reports:
+
+  BUG: KASAN: vmalloc-out-of-bounds in is_dirty_callback+0x2b/0x80
+  Read of size 8 at addr ffffc90000085040 by task dmsetup/90
+
+  (...snip...)
+  The buggy address belongs to the virtual mapping at
+   [ffffc90000085000, ffffc90000087000) created by:
+   cache_ctr+0x176a/0x35f0
+
+  (...snip...)
+  Memory state around the buggy address:
+   ffffc90000084f00: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+   ffffc90000084f80: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+  >ffffc90000085000: 00 00 00 00 00 00 00 00 f8 f8 f8 f8 f8 f8 f8 f8
+                                             ^
+   ffffc90000085080: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+   ffffc90000085100: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
+
+Fix by checking the size change on the first resume.
+
+Signed-off-by: Ming-Hung Tsai <mtsai@redhat.com>
+Fixes: f494a9c6b1b6 ("dm cache: cache shrinking support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Acked-by: Joe Thornber <thornber@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-cache-target.c |   37 ++++++++++++++++---------------------
+ 1 file changed, 16 insertions(+), 21 deletions(-)
+
+--- a/drivers/md/dm-cache-target.c
++++ b/drivers/md/dm-cache-target.c
+@@ -2901,24 +2901,24 @@ static dm_cblock_t get_cache_dev_size(st
+ static bool can_resize(struct cache *cache, dm_cblock_t new_size)
+ {
+       if (from_cblock(new_size) > from_cblock(cache->cache_size)) {
+-              if (cache->sized) {
+-                      DMERR("%s: unable to extend cache due to missing cache table reload",
+-                            cache_device_name(cache));
+-                      return false;
+-              }
++              DMERR("%s: unable to extend cache due to missing cache table reload",
++                    cache_device_name(cache));
++              return false;
+       }
+       /*
+        * We can't drop a dirty block when shrinking the cache.
+        */
+-      new_size = to_cblock(find_next_bit(cache->dirty_bitset,
+-                                         from_cblock(cache->cache_size),
+-                                         from_cblock(new_size)));
+-      if (new_size != cache->cache_size) {
+-              DMERR("%s: unable to shrink cache; cache block %llu is dirty",
+-                    cache_device_name(cache),
+-                    (unsigned long long) from_cblock(new_size));
+-              return false;
++      if (cache->loaded_mappings) {
++              new_size = to_cblock(find_next_bit(cache->dirty_bitset,
++                                                 from_cblock(cache->cache_size),
++                                                 from_cblock(new_size)));
++              if (new_size != cache->cache_size) {
++                      DMERR("%s: unable to shrink cache; cache block %llu is dirty",
++                            cache_device_name(cache),
++                            (unsigned long long) from_cblock(new_size));
++                      return false;
++              }
+       }
+       return true;
+@@ -2949,20 +2949,15 @@ static int cache_preresume(struct dm_tar
+       /*
+        * Check to see if the cache has resized.
+        */
+-      if (!cache->sized) {
+-              r = resize_cache_dev(cache, csize);
+-              if (r)
+-                      return r;
+-
+-              cache->sized = true;
+-
+-      } else if (csize != cache->cache_size) {
++      if (!cache->sized || csize != cache->cache_size) {
+               if (!can_resize(cache, csize))
+                       return -EINVAL;
+               r = resize_cache_dev(cache, csize);
+               if (r)
+                       return r;
++
++              cache->sized = true;
+       }
+       if (!cache->loaded_mappings) {
diff --git a/queue-6.11/dm-cache-optimize-dirty-bit-checking-with-find_next_bit-when-resizing.patch b/queue-6.11/dm-cache-optimize-dirty-bit-checking-with-find_next_bit-when-resizing.patch
new file mode 100644 (file)
index 0000000..facd550
--- /dev/null
@@ -0,0 +1,49 @@
+From f484697e619a83ecc370443a34746379ad99d204 Mon Sep 17 00:00:00 2001
+From: Ming-Hung Tsai <mtsai@redhat.com>
+Date: Tue, 22 Oct 2024 15:13:39 +0800
+Subject: dm cache: optimize dirty bit checking with find_next_bit when resizing
+
+From: Ming-Hung Tsai <mtsai@redhat.com>
+
+commit f484697e619a83ecc370443a34746379ad99d204 upstream.
+
+When shrinking the fast device, dm-cache iteratively searches for a
+dirty bit among the cache blocks to be dropped, which is less efficient.
+Use find_next_bit instead, as it is twice as fast as the iterative
+approach with test_bit.
+
+Signed-off-by: Ming-Hung Tsai <mtsai@redhat.com>
+Fixes: f494a9c6b1b6 ("dm cache: cache shrinking support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Acked-by: Joe Thornber <thornber@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-cache-target.c |   16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/md/dm-cache-target.c
++++ b/drivers/md/dm-cache-target.c
+@@ -2911,14 +2911,14 @@ static bool can_resize(struct cache *cac
+       /*
+        * We can't drop a dirty block when shrinking the cache.
+        */
+-      while (from_cblock(new_size) < from_cblock(cache->cache_size)) {
+-              if (is_dirty(cache, new_size)) {
+-                      DMERR("%s: unable to shrink cache; cache block %llu is dirty",
+-                            cache_device_name(cache),
+-                            (unsigned long long) from_cblock(new_size));
+-                      return false;
+-              }
+-              new_size = to_cblock(from_cblock(new_size) + 1);
++      new_size = to_cblock(find_next_bit(cache->dirty_bitset,
++                                         from_cblock(cache->cache_size),
++                                         from_cblock(new_size)));
++      if (new_size != cache->cache_size) {
++              DMERR("%s: unable to shrink cache; cache block %llu is dirty",
++                    cache_device_name(cache),
++                    (unsigned long long) from_cblock(new_size));
++              return false;
+       }
+       return true;
diff --git a/queue-6.11/dm-fix-a-crash-if-blk_alloc_disk-fails.patch b/queue-6.11/dm-fix-a-crash-if-blk_alloc_disk-fails.patch
new file mode 100644 (file)
index 0000000..c0b7a70
--- /dev/null
@@ -0,0 +1,38 @@
+From fed13a5478680614ba97fc87e71f16e2e197912e Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 7 Oct 2024 13:38:12 +0200
+Subject: dm: fix a crash if blk_alloc_disk fails
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit fed13a5478680614ba97fc87e71f16e2e197912e upstream.
+
+If blk_alloc_disk fails, the variable md->disk is set to an error value.
+cleanup_mapped_device will see that md->disk is non-NULL and it will
+attempt to access it, causing a crash on this statement
+"md->disk->private_data = NULL;".
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Reported-by: Chenyuan Yang <chenyuan0y@gmail.com>
+Closes: https://marc.info/?l=dm-devel&m=172824125004329&w=2
+Cc: stable@vger.kernel.org
+Reviewed-by: Nitesh Shetty <nj.shetty@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -2290,8 +2290,10 @@ static struct mapped_device *alloc_dev(i
+        * override accordingly.
+        */
+       md->disk = blk_alloc_disk(NULL, md->numa_node_id);
+-      if (IS_ERR(md->disk))
++      if (IS_ERR(md->disk)) {
++              md->disk = NULL;
+               goto bad;
++      }
+       md->queue = md->disk->queue;
+       init_waitqueue_head(&md->wait);
diff --git a/queue-6.11/dm-unstriped-cast-an-operand-to-sector_t-to-prevent-potential-uint32_t-overflow.patch b/queue-6.11/dm-unstriped-cast-an-operand-to-sector_t-to-prevent-potential-uint32_t-overflow.patch
new file mode 100644 (file)
index 0000000..a62061e
--- /dev/null
@@ -0,0 +1,41 @@
+From 5a4510c762fc04c74cff264cd4d9e9f5bf364bae Mon Sep 17 00:00:00 2001
+From: Zichen Xie <zichenxie0106@gmail.com>
+Date: Mon, 21 Oct 2024 14:54:45 -0500
+Subject: dm-unstriped: cast an operand to sector_t to prevent potential uint32_t overflow
+
+From: Zichen Xie <zichenxie0106@gmail.com>
+
+commit 5a4510c762fc04c74cff264cd4d9e9f5bf364bae upstream.
+
+This was found by a static analyzer.
+There may be a potential integer overflow issue in
+unstripe_ctr(). uc->unstripe_offset and uc->unstripe_width are
+defined as "sector_t"(uint64_t), while uc->unstripe,
+uc->chunk_size and uc->stripes are all defined as "uint32_t".
+The result of the calculation will be limited to "uint32_t"
+without correct casting.
+So, we recommend adding an extra cast to prevent potential
+integer overflow.
+
+Fixes: 18a5bf270532 ("dm: add unstriped target")
+Signed-off-by: Zichen Xie <zichenxie0106@gmail.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-unstripe.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/dm-unstripe.c
++++ b/drivers/md/dm-unstripe.c
+@@ -85,8 +85,8 @@ static int unstripe_ctr(struct dm_target
+       }
+       uc->physical_start = start;
+-      uc->unstripe_offset = uc->unstripe * uc->chunk_size;
+-      uc->unstripe_width = (uc->stripes - 1) * uc->chunk_size;
++      uc->unstripe_offset = (sector_t)uc->unstripe * uc->chunk_size;
++      uc->unstripe_width = (sector_t)(uc->stripes - 1) * uc->chunk_size;
+       uc->chunk_shift = is_power_of_2(uc->chunk_size) ? fls(uc->chunk_size) - 1 : 0;
+       tmp_len = ti->len;
diff --git a/queue-6.11/drm-amd-display-fix-brightness-level-not-retained-over-reboot.patch b/queue-6.11/drm-amd-display-fix-brightness-level-not-retained-over-reboot.patch
new file mode 100644 (file)
index 0000000..b70668e
--- /dev/null
@@ -0,0 +1,74 @@
+From 4f26c95ffc21a91281429ed60180619bae19ae92 Mon Sep 17 00:00:00 2001
+From: Tom Chung <chiahsuan.chung@amd.com>
+Date: Wed, 9 Oct 2024 17:09:38 +0800
+Subject: drm/amd/display: Fix brightness level not retained over reboot
+
+From: Tom Chung <chiahsuan.chung@amd.com>
+
+commit 4f26c95ffc21a91281429ed60180619bae19ae92 upstream.
+
+[Why]
+During boot up and resume the DC layer will reset the panel
+brightness to fix a flicker issue.
+
+It will cause the dm->actual_brightness is not the current panel
+brightness level. (the dm->brightness is the correct panel level)
+
+[How]
+Set the backlight level after do the set mode.
+
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Fixes: d9e865826c20 ("drm/amd/display: Simplify brightness initialization")
+Reported-by: Mark Herbert <mark.herbert42@gmail.com>
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3655
+Reviewed-by: Sun peng Li <sunpeng.li@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 7875afafba84817b791be6d2282b836695146060)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -9384,6 +9384,7 @@ static void amdgpu_dm_commit_streams(str
+       bool mode_set_reset_required = false;
+       u32 i;
+       struct dc_commit_streams_params params = {dc_state->streams, dc_state->stream_count};
++      bool set_backlight_level = false;
+       /* Disable writeback */
+       for_each_old_connector_in_state(state, connector, old_con_state, i) {
+@@ -9503,6 +9504,7 @@ static void amdgpu_dm_commit_streams(str
+                       acrtc->hw_mode = new_crtc_state->mode;
+                       crtc->hwmode = new_crtc_state->mode;
+                       mode_set_reset_required = true;
++                      set_backlight_level = true;
+               } else if (modereset_required(new_crtc_state)) {
+                       drm_dbg_atomic(dev,
+                                      "Atomic commit: RESET. crtc id %d:[%p]\n",
+@@ -9554,6 +9556,19 @@ static void amdgpu_dm_commit_streams(str
+                               acrtc->otg_inst = status->primary_otg_inst;
+               }
+       }
++
++      /* During boot up and resume the DC layer will reset the panel brightness
++       * to fix a flicker issue.
++       * It will cause the dm->actual_brightness is not the current panel brightness
++       * level. (the dm->brightness is the correct panel level)
++       * So we set the backlight level with dm->brightness value after set mode
++       */
++      if (set_backlight_level) {
++              for (i = 0; i < dm->num_of_edps; i++) {
++                      if (dm->backlight_dev[i])
++                              amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
++              }
++      }
+ }
+ static void dm_set_writeback(struct amdgpu_display_manager *dm,
diff --git a/queue-6.11/drm-amd-display-parse-umc_info-or-vram_info-based-on-asic.patch b/queue-6.11/drm-amd-display-parse-umc_info-or-vram_info-based-on-asic.patch
new file mode 100644 (file)
index 0000000..438b93a
--- /dev/null
@@ -0,0 +1,46 @@
+From 694c79769cb384bca8b1ec1d1e84156e726bd106 Mon Sep 17 00:00:00 2001
+From: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Date: Fri, 18 Oct 2024 10:52:16 -0400
+Subject: drm/amd/display: parse umc_info or vram_info based on ASIC
+
+From: Aurabindo Pillai <aurabindo.pillai@amd.com>
+
+commit 694c79769cb384bca8b1ec1d1e84156e726bd106 upstream.
+
+An upstream bug report suggests that there are production dGPUs that are
+older than DCN401 but still have a umc_info in VBIOS tables with the
+same version as expected for a DCN401 product. Hence, reading this
+tables should be guarded with a version check.
+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3678
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 2551b4a321a68134360b860113dd460133e856e5)
+Fixes: 00c391102abc ("drm/amd/display: Add misc DC changes for DCN401")
+Cc: stable@vger.kernel.org # 6.11.x
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+index 0d8498ab9b23..be8fbb04ad98 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+@@ -3127,7 +3127,9 @@ static enum bp_result bios_parser_get_vram_info(
+       struct atom_data_revision revision;
+       // vram info moved to umc_info for DCN4x
+-      if (info && DATA_TABLES(umc_info)) {
++      if (dcb->ctx->dce_version >= DCN_VERSION_4_01 &&
++              dcb->ctx->dce_version < DCN_VERSION_MAX &&
++              info && DATA_TABLES(umc_info)) {
+               header = GET_IMAGE(struct atom_common_table_header,
+                                       DATA_TABLES(umc_info));
+-- 
+2.47.0
+
diff --git a/queue-6.11/drm-amd-pm-always-pick-the-pptable-from-ifwi.patch b/queue-6.11/drm-amd-pm-always-pick-the-pptable-from-ifwi.patch
new file mode 100644 (file)
index 0000000..8256b9a
--- /dev/null
@@ -0,0 +1,121 @@
+From 1356bfc54c8d4c8e7c9fb8553dc8c28e9714b07b Mon Sep 17 00:00:00 2001
+From: Kenneth Feng <kenneth.feng@amd.com>
+Date: Fri, 1 Nov 2024 11:55:25 +0800
+Subject: drm/amd/pm: always pick the pptable from IFWI
+
+From: Kenneth Feng <kenneth.feng@amd.com>
+
+commit 1356bfc54c8d4c8e7c9fb8553dc8c28e9714b07b upstream.
+
+always pick the pptable from IFWI on smu v14.0.2/3
+
+Signed-off-by: Kenneth Feng <kenneth.feng@amd.com>
+Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 136ce12bd5907388cb4e9aa63ee5c9c8c441640b)
+Cc: stable@vger.kernel.org # 6.11.x
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c |   65 -------------------
+ 1 file changed, 1 insertion(+), 64 deletions(-)
+
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+@@ -354,54 +354,6 @@ static int smu_v14_0_2_store_powerplay_t
+       return 0;
+ }
+-#ifndef atom_smc_dpm_info_table_14_0_0
+-struct atom_smc_dpm_info_table_14_0_0 {
+-      struct atom_common_table_header table_header;
+-      BoardTable_t BoardTable;
+-};
+-#endif
+-
+-static int smu_v14_0_2_append_powerplay_table(struct smu_context *smu)
+-{
+-      struct smu_table_context *table_context = &smu->smu_table;
+-      PPTable_t *smc_pptable = table_context->driver_pptable;
+-      struct atom_smc_dpm_info_table_14_0_0 *smc_dpm_table;
+-      BoardTable_t *BoardTable = &smc_pptable->BoardTable;
+-      int index, ret;
+-
+-      index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+-                                          smc_dpm_info);
+-
+-      ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
+-                                           (uint8_t **)&smc_dpm_table);
+-      if (ret)
+-              return ret;
+-
+-      memcpy(BoardTable, &smc_dpm_table->BoardTable, sizeof(BoardTable_t));
+-
+-      return 0;
+-}
+-
+-#if 0
+-static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu,
+-                                           void **table,
+-                                           uint32_t *size)
+-{
+-      struct smu_table_context *smu_table = &smu->smu_table;
+-      void *combo_pptable = smu_table->combo_pptable;
+-      int ret = 0;
+-
+-      ret = smu_cmn_get_combo_pptable(smu);
+-      if (ret)
+-              return ret;
+-
+-      *table = combo_pptable;
+-      *size = sizeof(struct smu_14_0_powerplay_table);
+-
+-      return 0;
+-}
+-#endif
+-
+ static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu,
+                                            void **table,
+                                            uint32_t *size)
+@@ -423,16 +375,12 @@ static int smu_v14_0_2_get_pptable_from_
+ static int smu_v14_0_2_setup_pptable(struct smu_context *smu)
+ {
+       struct smu_table_context *smu_table = &smu->smu_table;
+-      struct amdgpu_device *adev = smu->adev;
+       int ret = 0;
+       if (amdgpu_sriov_vf(smu->adev))
+               return 0;
+-      if (!adev->scpm_enabled)
+-              ret = smu_v14_0_setup_pptable(smu);
+-      else
+-              ret = smu_v14_0_2_get_pptable_from_pmfw(smu,
++      ret = smu_v14_0_2_get_pptable_from_pmfw(smu,
+                                                       &smu_table->power_play_table,
+                                                       &smu_table->power_play_table_size);
+       if (ret)
+@@ -442,16 +390,6 @@ static int smu_v14_0_2_setup_pptable(str
+       if (ret)
+               return ret;
+-      /*
+-       * With SCPM enabled, the operation below will be handled
+-       * by PSP. Driver involvment is unnecessary and useless.
+-       */
+-      if (!adev->scpm_enabled) {
+-              ret = smu_v14_0_2_append_powerplay_table(smu);
+-              if (ret)
+-                      return ret;
+-      }
+-
+       ret = smu_v14_0_2_check_powerplay_table(smu);
+       if (ret)
+               return ret;
+@@ -1938,7 +1876,6 @@ static const struct pptable_funcs smu_v1
+       .check_fw_status = smu_v14_0_check_fw_status,
+       .setup_pptable = smu_v14_0_2_setup_pptable,
+       .check_fw_version = smu_v14_0_check_fw_version,
+-      .write_pptable = smu_cmn_write_pptable,
+       .set_driver_table_location = smu_v14_0_set_driver_table_location,
+       .system_features_control = smu_v14_0_system_features_control,
+       .set_allowed_mask = smu_v14_0_set_allowed_mask,
diff --git a/queue-6.11/drm-amd-pm-correct-the-workload-setting.patch b/queue-6.11/drm-amd-pm-correct-the-workload-setting.patch
new file mode 100644 (file)
index 0000000..78cf488
--- /dev/null
@@ -0,0 +1,369 @@
+From 74e1006430a5377228e49310f6d915628609929e Mon Sep 17 00:00:00 2001
+From: Kenneth Feng <kenneth.feng@amd.com>
+Date: Wed, 30 Oct 2024 13:22:44 +0800
+Subject: drm/amd/pm: correct the workload setting
+
+From: Kenneth Feng <kenneth.feng@amd.com>
+
+commit 74e1006430a5377228e49310f6d915628609929e upstream.
+
+Correct the workload setting in order not to mix the setting
+with the end user. Update the workload mask accordingly.
+
+v2: changes as below:
+1. the end user can not erase the workload from driver except default workload.
+2. always shows the real highest priority workoad to the end user.
+3. the real workload mask is combined with driver workload mask and end user workload mask.
+
+v3: apply this to the other ASICs as well.
+v4: simplify the code
+v5: refine the code based on the review comments.
+
+Signed-off-by: Kenneth Feng <kenneth.feng@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 8cc438be5d49b8326b2fcade0bdb7e6a97df9e0b)
+Cc: stable@vger.kernel.org # 6.11.x
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c               |   49 +++++++++++-----
+ drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h           |    4 -
+ drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c       |    5 -
+ drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c         |    5 +
+ drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c |    5 +
+ drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c        |    4 -
+ drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c         |    4 -
+ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c    |   20 ++++--
+ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c    |    5 -
+ drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c    |    9 +-
+ drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c                  |    8 ++
+ drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h                  |    2 
+ 12 files changed, 84 insertions(+), 36 deletions(-)
+
+--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+@@ -1259,26 +1259,33 @@ static int smu_sw_init(void *handle)
+       smu->watermarks_bitmap = 0;
+       smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
++      smu->user_dpm_profile.user_workload_mask = 0;
+       atomic_set(&smu->smu_power.power_gate.vcn_gated, 1);
+       atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1);
+       atomic_set(&smu->smu_power.power_gate.vpe_gated, 1);
+       atomic_set(&smu->smu_power.power_gate.umsch_mm_gated, 1);
+-      smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
+-      smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
+-      smu->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
+-      smu->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
+-      smu->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
+-      smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
+-      smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
++      smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
++      smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
++      smu->workload_priority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
++      smu->workload_priority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
++      smu->workload_priority[PP_SMC_POWER_PROFILE_VR] = 4;
++      smu->workload_priority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
++      smu->workload_priority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
+       if (smu->is_apu ||
+-          !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D))
+-              smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+-      else
+-              smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
++          !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) {
++              smu->driver_workload_mask =
++                      1 << smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
++      } else {
++              smu->driver_workload_mask =
++                      1 << smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
++              smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
++      }
++      smu->workload_mask = smu->driver_workload_mask |
++                                                      smu->user_dpm_profile.user_workload_mask;
+       smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+       smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
+@@ -2348,17 +2355,20 @@ static int smu_switch_power_profile(void
+               return -EINVAL;
+       if (!en) {
+-              smu->workload_mask &= ~(1 << smu->workload_prority[type]);
++              smu->driver_workload_mask &= ~(1 << smu->workload_priority[type]);
+               index = fls(smu->workload_mask);
+               index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+               workload[0] = smu->workload_setting[index];
+       } else {
+-              smu->workload_mask |= (1 << smu->workload_prority[type]);
++              smu->driver_workload_mask |= (1 << smu->workload_priority[type]);
+               index = fls(smu->workload_mask);
+               index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+               workload[0] = smu->workload_setting[index];
+       }
++      smu->workload_mask = smu->driver_workload_mask |
++                                               smu->user_dpm_profile.user_workload_mask;
++
+       if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
+               smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
+               smu_bump_power_profile_mode(smu, workload, 0);
+@@ -3049,12 +3059,23 @@ static int smu_set_power_profile_mode(vo
+                                     uint32_t param_size)
+ {
+       struct smu_context *smu = handle;
++      int ret;
+       if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled ||
+           !smu->ppt_funcs->set_power_profile_mode)
+               return -EOPNOTSUPP;
+-      return smu_bump_power_profile_mode(smu, param, param_size);
++      if (smu->user_dpm_profile.user_workload_mask &
++         (1 << smu->workload_priority[param[param_size]]))
++         return 0;
++
++      smu->user_dpm_profile.user_workload_mask =
++              (1 << smu->workload_priority[param[param_size]]);
++      smu->workload_mask = smu->user_dpm_profile.user_workload_mask |
++              smu->driver_workload_mask;
++      ret = smu_bump_power_profile_mode(smu, param, param_size);
++
++      return ret;
+ }
+ static int smu_get_fan_control_mode(void *handle, u32 *fan_mode)
+--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
++++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+@@ -240,6 +240,7 @@ struct smu_user_dpm_profile {
+       /* user clock state information */
+       uint32_t clk_mask[SMU_CLK_COUNT];
+       uint32_t clk_dependency;
++      uint32_t user_workload_mask;
+ };
+ #define SMU_TABLE_INIT(tables, table_id, s, a, d)     \
+@@ -557,7 +558,8 @@ struct smu_context {
+       bool disable_uclk_switch;
+       uint32_t workload_mask;
+-      uint32_t workload_prority[WORKLOAD_POLICY_MAX];
++      uint32_t driver_workload_mask;
++      uint32_t workload_priority[WORKLOAD_POLICY_MAX];
+       uint32_t workload_setting[WORKLOAD_POLICY_MAX];
+       uint32_t power_profile_mode;
+       uint32_t default_power_profile_mode;
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+@@ -1455,7 +1455,6 @@ static int arcturus_set_power_profile_mo
+               return -EINVAL;
+       }
+-
+       if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
+            (smu->smc_fw_version >= 0x360d00)) {
+               if (size != 10)
+@@ -1523,14 +1522,14 @@ static int arcturus_set_power_profile_mo
+       ret = smu_cmn_send_smc_msg_with_param(smu,
+                                         SMU_MSG_SetWorkloadMask,
+-                                        1 << workload_type,
++                                        smu->workload_mask,
+                                         NULL);
+       if (ret) {
+               dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
+               return ret;
+       }
+-      smu->power_profile_mode = profile_mode;
++      smu_cmn_assign_power_profile(smu);
+       return 0;
+ }
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+@@ -2081,10 +2081,13 @@ static int navi10_set_power_profile_mode
+                                                      smu->power_profile_mode);
+       if (workload_type < 0)
+               return -EINVAL;
++
+       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
+-                                  1 << workload_type, NULL);
++                                  smu->workload_mask, NULL);
+       if (ret)
+               dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
++      else
++              smu_cmn_assign_power_profile(smu);
+       return ret;
+ }
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+@@ -1786,10 +1786,13 @@ static int sienna_cichlid_set_power_prof
+                                                      smu->power_profile_mode);
+       if (workload_type < 0)
+               return -EINVAL;
++
+       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
+-                                  1 << workload_type, NULL);
++                                  smu->workload_mask, NULL);
+       if (ret)
+               dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
++      else
++              smu_cmn_assign_power_profile(smu);
+       return ret;
+ }
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
+@@ -1079,7 +1079,7 @@ static int vangogh_set_power_profile_mod
+       }
+       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
+-                                  1 << workload_type,
++                                  smu->workload_mask,
+                                   NULL);
+       if (ret) {
+               dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
+@@ -1087,7 +1087,7 @@ static int vangogh_set_power_profile_mod
+               return ret;
+       }
+-      smu->power_profile_mode = profile_mode;
++      smu_cmn_assign_power_profile(smu);
+       return 0;
+ }
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
+@@ -890,14 +890,14 @@ static int renoir_set_power_profile_mode
+       }
+       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
+-                                  1 << workload_type,
++                                  smu->workload_mask,
+                                   NULL);
+       if (ret) {
+               dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
+               return ret;
+       }
+-      smu->power_profile_mode = profile_mode;
++      smu_cmn_assign_power_profile(smu);
+       return 0;
+ }
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+@@ -2485,7 +2485,7 @@ static int smu_v13_0_0_set_power_profile
+       DpmActivityMonitorCoeffInt_t *activity_monitor =
+               &(activity_monitor_external.DpmActivityMonitorCoeffInt);
+       int workload_type, ret = 0;
+-      u32 workload_mask, selected_workload_mask;
++      u32 workload_mask;
+       smu->power_profile_mode = input[size];
+@@ -2552,7 +2552,7 @@ static int smu_v13_0_0_set_power_profile
+       if (workload_type < 0)
+               return -EINVAL;
+-      selected_workload_mask = workload_mask = 1 << workload_type;
++      workload_mask = 1 << workload_type;
+       /* Add optimizations for SMU13.0.0/10.  Reuse the power saving profile */
+       if ((amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 0) &&
+@@ -2567,12 +2567,22 @@ static int smu_v13_0_0_set_power_profile
+                       workload_mask |= 1 << workload_type;
+       }
++      smu->workload_mask |= workload_mask;
+       ret = smu_cmn_send_smc_msg_with_param(smu,
+                                              SMU_MSG_SetWorkloadMask,
+-                                             workload_mask,
++                                             smu->workload_mask,
+                                              NULL);
+-      if (!ret)
+-              smu->workload_mask = selected_workload_mask;
++      if (!ret) {
++              smu_cmn_assign_power_profile(smu);
++              if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING) {
++                      workload_type = smu_cmn_to_asic_specific_index(smu,
++                                                             CMN2ASIC_MAPPING_WORKLOAD,
++                                                             PP_SMC_POWER_PROFILE_FULLSCREEN3D);
++                      smu->power_profile_mode = smu->workload_mask & (1 << workload_type)
++                                                                              ? PP_SMC_POWER_PROFILE_FULLSCREEN3D
++                                                                              : PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
++              }
++      }
+       return ret;
+ }
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+@@ -2499,13 +2499,14 @@ static int smu_v13_0_7_set_power_profile
+                                                      smu->power_profile_mode);
+       if (workload_type < 0)
+               return -EINVAL;
++
+       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
+-                                  1 << workload_type, NULL);
++                                  smu->workload_mask, NULL);
+       if (ret)
+               dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
+       else
+-              smu->workload_mask = (1 << workload_type);
++              smu_cmn_assign_power_profile(smu);
+       return ret;
+ }
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+@@ -1508,12 +1508,11 @@ static int smu_v14_0_2_set_power_profile
+       if (workload_type < 0)
+               return -EINVAL;
+-      ret = smu_cmn_send_smc_msg_with_param(smu,
+-                                             SMU_MSG_SetWorkloadMask,
+-                                             1 << workload_type,
+-                                             NULL);
++      ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
++                                                                                smu->workload_mask, NULL);
++
+       if (!ret)
+-              smu->workload_mask = 1 << workload_type;
++              smu_cmn_assign_power_profile(smu);
+       return ret;
+ }
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+@@ -1138,6 +1138,14 @@ int smu_cmn_set_mp1_state(struct smu_con
+       return ret;
+ }
++void smu_cmn_assign_power_profile(struct smu_context *smu)
++{
++      uint32_t index;
++      index = fls(smu->workload_mask);
++      index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
++      smu->power_profile_mode = smu->workload_setting[index];
++}
++
+ bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev)
+ {
+       struct pci_dev *p = NULL;
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+@@ -130,6 +130,8 @@ void smu_cmn_init_soft_gpu_metrics(void
+ int smu_cmn_set_mp1_state(struct smu_context *smu,
+                         enum pp_mp1_state mp1_state);
++void smu_cmn_assign_power_profile(struct smu_context *smu);
++
+ /*
+  * Helper function to make sysfs_emit_at() happy. Align buf to
+  * the current page boundary and record the offset.
diff --git a/queue-6.11/drm-amdgpu-add-missing-size-check-in-amdgpu_debugfs_gprwave_read.patch b/queue-6.11/drm-amdgpu-add-missing-size-check-in-amdgpu_debugfs_gprwave_read.patch
new file mode 100644 (file)
index 0000000..d7fd0f5
--- /dev/null
@@ -0,0 +1,31 @@
+From 4d75b9468021c73108b4439794d69e892b1d24e3 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Wed, 23 Oct 2024 16:52:08 -0400
+Subject: drm/amdgpu: add missing size check in amdgpu_debugfs_gprwave_read()
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 4d75b9468021c73108b4439794d69e892b1d24e3 upstream.
+
+Avoid a possible buffer overflow if size is larger than 4K.
+
+Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit f5d873f5825b40d886d03bd2aede91d4cf002434)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+@@ -402,7 +402,7 @@ static ssize_t amdgpu_debugfs_gprwave_re
+       int r;
+       uint32_t *data, x;
+-      if (size & 0x3 || *pos & 0x3)
++      if (size > 4096 || size & 0x3 || *pos & 0x3)
+               return -EINVAL;
+       r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
diff --git a/queue-6.11/drm-amdgpu-adjust-debugfs-eviction-and-ib-access-permissions.patch b/queue-6.11/drm-amdgpu-adjust-debugfs-eviction-and-ib-access-permissions.patch
new file mode 100644 (file)
index 0000000..45aedf3
--- /dev/null
@@ -0,0 +1,37 @@
+From f790a2c494c4ef587eeeb9fca20124de76a1646f Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Wed, 23 Oct 2024 16:39:36 -0400
+Subject: drm/amdgpu: Adjust debugfs eviction and IB access permissions
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit f790a2c494c4ef587eeeb9fca20124de76a1646f upstream.
+
+Users should not be able to run these.
+
+Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 7ba9395430f611cfc101b1c2687732baafa239d5)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+@@ -2194,11 +2194,11 @@ int amdgpu_debugfs_init(struct amdgpu_de
+       amdgpu_securedisplay_debugfs_init(adev);
+       amdgpu_fw_attestation_debugfs_init(adev);
+-      debugfs_create_file("amdgpu_evict_vram", 0444, root, adev,
++      debugfs_create_file("amdgpu_evict_vram", 0400, root, adev,
+                           &amdgpu_evict_vram_fops);
+-      debugfs_create_file("amdgpu_evict_gtt", 0444, root, adev,
++      debugfs_create_file("amdgpu_evict_gtt", 0400, root, adev,
+                           &amdgpu_evict_gtt_fops);
+-      debugfs_create_file("amdgpu_test_ib", 0444, root, adev,
++      debugfs_create_file("amdgpu_test_ib", 0400, root, adev,
+                           &amdgpu_debugfs_test_ib_fops);
+       debugfs_create_file("amdgpu_vm_info", 0444, root, adev,
+                           &amdgpu_debugfs_vm_info_fops);
diff --git a/queue-6.11/drm-amdgpu-adjust-debugfs-register-access-permissions.patch b/queue-6.11/drm-amdgpu-adjust-debugfs-register-access-permissions.patch
new file mode 100644 (file)
index 0000000..c0eba71
--- /dev/null
@@ -0,0 +1,31 @@
+From b46dadf7e3cfe26d0b109c9c3d81b278d6c75361 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Wed, 23 Oct 2024 16:37:52 -0400
+Subject: drm/amdgpu: Adjust debugfs register access permissions
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit b46dadf7e3cfe26d0b109c9c3d81b278d6c75361 upstream.
+
+Regular users shouldn't have read access.
+
+Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit c0cfd2e652553d607b910be47d0cc5a7f3a78641)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+@@ -1648,7 +1648,7 @@ int amdgpu_debugfs_regs_init(struct amdg
+       for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) {
+               ent = debugfs_create_file(debugfs_regs_names[i],
+-                                        S_IFREG | 0444, root,
++                                        S_IFREG | 0400, root,
+                                         adev, debugfs_regs[i]);
+               if (!i && !IS_ERR_OR_NULL(ent))
+                       i_size_write(ent->d_inode, adev->rmmio_size);
diff --git a/queue-6.11/drm-amdgpu-fix-dpx-valid-mode-check-on-gc-9.4.3.patch b/queue-6.11/drm-amdgpu-fix-dpx-valid-mode-check-on-gc-9.4.3.patch
new file mode 100644 (file)
index 0000000..3b28ce7
--- /dev/null
@@ -0,0 +1,34 @@
+From 3ce3f85787352fa48fc02ef6cbd7a5e5aba93347 Mon Sep 17 00:00:00 2001
+From: Lijo Lazar <lijo.lazar@amd.com>
+Date: Mon, 4 Nov 2024 10:36:13 +0530
+Subject: drm/amdgpu: Fix DPX valid mode check on GC 9.4.3
+
+From: Lijo Lazar <lijo.lazar@amd.com>
+
+commit 3ce3f85787352fa48fc02ef6cbd7a5e5aba93347 upstream.
+
+For DPX mode, the number of memory partitions supported should be less
+than or equal to 2.
+
+Fixes: 1589c82a1085 ("drm/amdgpu: Check memory ranges for valid xcp mode")
+Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
+Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 990c4f580742de7bb78fa57420ffd182fc3ab4cd)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
++++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
+@@ -484,7 +484,7 @@ static bool __aqua_vanjaram_is_valid_mod
+       case AMDGPU_SPX_PARTITION_MODE:
+               return adev->gmc.num_mem_partitions == 1 && num_xcc > 0;
+       case AMDGPU_DPX_PARTITION_MODE:
+-              return adev->gmc.num_mem_partitions != 8 && (num_xcc % 4) == 0;
++              return adev->gmc.num_mem_partitions <= 2 && (num_xcc % 4) == 0;
+       case AMDGPU_TPX_PARTITION_MODE:
+               return (adev->gmc.num_mem_partitions == 1 ||
+                       adev->gmc.num_mem_partitions == 3) &&
diff --git a/queue-6.11/drm-amdgpu-prevent-null-pointer-dereference-if-atif-is-not-supported.patch b/queue-6.11/drm-amdgpu-prevent-null-pointer-dereference-if-atif-is-not-supported.patch
new file mode 100644 (file)
index 0000000..57b3801
--- /dev/null
@@ -0,0 +1,46 @@
+From a6dd15981c03f2cdc9a351a278f09b5479d53d2e Mon Sep 17 00:00:00 2001
+From: Antonio Quartulli <antonio@mandelbit.com>
+Date: Thu, 31 Oct 2024 16:28:48 +0100
+Subject: drm/amdgpu: prevent NULL pointer dereference if ATIF is not supported
+
+From: Antonio Quartulli <antonio@mandelbit.com>
+
+commit a6dd15981c03f2cdc9a351a278f09b5479d53d2e upstream.
+
+acpi_evaluate_object() may return AE_NOT_FOUND (failure), which
+would result in dereferencing buffer.pointer (obj) while being NULL.
+
+Although this case may be unrealistic for the current code, it is
+still better to protect against possible bugs.
+
+Bail out also when status is AE_NOT_FOUND.
+
+This fixes 1 FORWARD_NULL issue reported by Coverity
+Report: CID 1600951:  Null pointer dereferences  (FORWARD_NULL)
+
+Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
+Fixes: c9b7c809b89f ("drm/amd: Guard against bad data for ATIF ACPI method")
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Link: https://lore.kernel.org/r/20241031152848.4716-1-antonio@mandelbit.com
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 91c9e221fe2553edf2db71627d8453f083de87a1)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+@@ -172,8 +172,8 @@ static union acpi_object *amdgpu_atif_ca
+                                     &buffer);
+       obj = (union acpi_object *)buffer.pointer;
+-      /* Fail if calling the method fails and ATIF is supported */
+-      if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
++      /* Fail if calling the method fails */
++      if (ACPI_FAILURE(status)) {
+               DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
+                                acpi_format_exception(status));
+               kfree(obj);
diff --git a/queue-6.11/drm-imagination-add-a-per-file-pvr-context-list.patch b/queue-6.11/drm-imagination-add-a-per-file-pvr-context-list.patch
new file mode 100644 (file)
index 0000000..927f7a7
--- /dev/null
@@ -0,0 +1,140 @@
+From b0ef514bc6bbdeb8cc7492c0f473e14cb06b14d4 Mon Sep 17 00:00:00 2001
+From: Brendan King <brendan.king@imgtec.com>
+Date: Fri, 18 Oct 2024 15:41:36 +0000
+Subject: drm/imagination: Add a per-file PVR context list
+
+From: Brendan King <brendan.king@imgtec.com>
+
+commit b0ef514bc6bbdeb8cc7492c0f473e14cb06b14d4 upstream.
+
+This adds a linked list of VM contexts which is needed for the next patch
+to be able to correctly track VM contexts for destruction on file close.
+
+It is only safe for VM contexts to be removed from the list and destroyed
+when not in interrupt context.
+
+Signed-off-by: Brendan King <brendan.king@imgtec.com>
+Signed-off-by: Matt Coster <matt.coster@imgtec.com>
+Reviewed-by: Frank Binns <frank.binns@imgtec.com>
+Cc: stable@vger.kernel.org
+Link: https://patchwork.freedesktop.org/patch/msgid/e57128ea-f0ce-4e93-a9d4-3f033a8b06fa@imgtec.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/imagination/pvr_context.c |   14 ++++++++++++++
+ drivers/gpu/drm/imagination/pvr_context.h |    3 +++
+ drivers/gpu/drm/imagination/pvr_device.h  |   10 ++++++++++
+ drivers/gpu/drm/imagination/pvr_drv.c     |    3 +++
+ 4 files changed, 30 insertions(+)
+
+--- a/drivers/gpu/drm/imagination/pvr_context.c
++++ b/drivers/gpu/drm/imagination/pvr_context.c
+@@ -17,10 +17,14 @@
+ #include <drm/drm_auth.h>
+ #include <drm/drm_managed.h>
++
++#include <linux/bug.h>
+ #include <linux/errno.h>
+ #include <linux/kernel.h>
++#include <linux/list.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
++#include <linux/spinlock.h>
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include <linux/xarray.h>
+@@ -354,6 +358,10 @@ int pvr_context_create(struct pvr_file *
+               return err;
+       }
++      spin_lock(&pvr_dev->ctx_list_lock);
++      list_add_tail(&ctx->file_link, &pvr_file->contexts);
++      spin_unlock(&pvr_dev->ctx_list_lock);
++
+       return 0;
+ err_destroy_fw_obj:
+@@ -380,6 +388,11 @@ pvr_context_release(struct kref *ref_cou
+               container_of(ref_count, struct pvr_context, ref_count);
+       struct pvr_device *pvr_dev = ctx->pvr_dev;
++      WARN_ON(in_interrupt());
++      spin_lock(&pvr_dev->ctx_list_lock);
++      list_del(&ctx->file_link);
++      spin_unlock(&pvr_dev->ctx_list_lock);
++
+       xa_erase(&pvr_dev->ctx_ids, ctx->ctx_id);
+       pvr_context_destroy_queues(ctx);
+       pvr_fw_object_destroy(ctx->fw_obj);
+@@ -451,6 +464,7 @@ void pvr_destroy_contexts_for_file(struc
+ void pvr_context_device_init(struct pvr_device *pvr_dev)
+ {
+       xa_init_flags(&pvr_dev->ctx_ids, XA_FLAGS_ALLOC1);
++      spin_lock_init(&pvr_dev->ctx_list_lock);
+ }
+ /**
+--- a/drivers/gpu/drm/imagination/pvr_context.h
++++ b/drivers/gpu/drm/imagination/pvr_context.h
+@@ -85,6 +85,9 @@ struct pvr_context {
+               /** @compute: Transfer queue. */
+               struct pvr_queue *transfer;
+       } queues;
++
++      /** @file_link: pvr_file PVR context list link. */
++      struct list_head file_link;
+ };
+ static __always_inline struct pvr_queue *
+--- a/drivers/gpu/drm/imagination/pvr_device.h
++++ b/drivers/gpu/drm/imagination/pvr_device.h
+@@ -23,6 +23,7 @@
+ #include <linux/kernel.h>
+ #include <linux/math.h>
+ #include <linux/mutex.h>
++#include <linux/spinlock_types.h>
+ #include <linux/timer.h>
+ #include <linux/types.h>
+ #include <linux/wait.h>
+@@ -293,6 +294,12 @@ struct pvr_device {
+       /** @sched_wq: Workqueue for schedulers. */
+       struct workqueue_struct *sched_wq;
++
++      /**
++       * @ctx_list_lock: Lock to be held when accessing the context list in
++       *  struct pvr_file.
++       */
++      spinlock_t ctx_list_lock;
+ };
+ /**
+@@ -344,6 +351,9 @@ struct pvr_file {
+        * This array is used to allocate handles returned to userspace.
+        */
+       struct xarray vm_ctx_handles;
++
++      /** @contexts: PVR context list. */
++      struct list_head contexts;
+ };
+ /**
+--- a/drivers/gpu/drm/imagination/pvr_drv.c
++++ b/drivers/gpu/drm/imagination/pvr_drv.c
+@@ -28,6 +28,7 @@
+ #include <linux/export.h>
+ #include <linux/fs.h>
+ #include <linux/kernel.h>
++#include <linux/list.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+@@ -1326,6 +1327,8 @@ pvr_drm_driver_open(struct drm_device *d
+        */
+       pvr_file->pvr_dev = pvr_dev;
++      INIT_LIST_HEAD(&pvr_file->contexts);
++
+       xa_init_flags(&pvr_file->ctx_handles, XA_FLAGS_ALLOC1);
+       xa_init_flags(&pvr_file->free_list_handles, XA_FLAGS_ALLOC1);
+       xa_init_flags(&pvr_file->hwrt_handles, XA_FLAGS_ALLOC1);
diff --git a/queue-6.11/drm-imagination-break-an-object-reference-loop.patch b/queue-6.11/drm-imagination-break-an-object-reference-loop.patch
new file mode 100644 (file)
index 0000000..ec5be90
--- /dev/null
@@ -0,0 +1,167 @@
+From b04ce1e718bd55302b52d05d6873e233cb3ec7a1 Mon Sep 17 00:00:00 2001
+From: Brendan King <brendan.king@imgtec.com>
+Date: Fri, 18 Oct 2024 15:41:40 +0000
+Subject: drm/imagination: Break an object reference loop
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Brendan King <brendan.king@imgtec.com>
+
+commit b04ce1e718bd55302b52d05d6873e233cb3ec7a1 upstream.
+
+When remaining resources are being cleaned up on driver close,
+outstanding VM mappings may result in resources being leaked, due
+to an object reference loop, as shown below, with each object (or
+set of objects) referencing the object below it:
+
+    PVR GEM Object
+    GPU scheduler "finished" fence
+    GPU scheduler “scheduled” fence
+    PVR driver “done” fence
+    PVR Context
+    PVR VM Context
+    PVR VM Mappings
+    PVR GEM Object
+
+The reference that the PVR VM Context has on the VM mappings is a
+soft one, in the sense that the freeing of outstanding VM mappings
+is done as part of VM context destruction; no reference counts are
+involved, as is the case for all the other references in the loop.
+
+To break the reference loop during cleanup, free the outstanding
+VM mappings before destroying the PVR Context associated with the
+VM context.
+
+Signed-off-by: Brendan King <brendan.king@imgtec.com>
+Signed-off-by: Matt Coster <matt.coster@imgtec.com>
+Reviewed-by: Frank Binns <frank.binns@imgtec.com>
+Cc: stable@vger.kernel.org
+Link: https://patchwork.freedesktop.org/patch/msgid/8a25924f-1bb7-4d9a-a346-58e871dfb1d1@imgtec.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/imagination/pvr_context.c |   19 +++++++++++++++++++
+ drivers/gpu/drm/imagination/pvr_context.h |   18 ++++++++++++++++++
+ drivers/gpu/drm/imagination/pvr_vm.c      |   22 ++++++++++++++++++----
+ drivers/gpu/drm/imagination/pvr_vm.h      |    1 +
+ 4 files changed, 56 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/imagination/pvr_context.c
++++ b/drivers/gpu/drm/imagination/pvr_context.c
+@@ -450,11 +450,30 @@ pvr_context_destroy(struct pvr_file *pvr
+  */
+ void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
+ {
++      struct pvr_device *pvr_dev = pvr_file->pvr_dev;
+       struct pvr_context *ctx;
+       unsigned long handle;
+       xa_for_each(&pvr_file->ctx_handles, handle, ctx)
+               pvr_context_destroy(pvr_file, handle);
++
++      spin_lock(&pvr_dev->ctx_list_lock);
++      ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
++
++      while (!list_entry_is_head(ctx, &pvr_file->contexts, file_link)) {
++              list_del_init(&ctx->file_link);
++
++              if (pvr_context_get_if_referenced(ctx)) {
++                      spin_unlock(&pvr_dev->ctx_list_lock);
++
++                      pvr_vm_unmap_all(ctx->vm_ctx);
++
++                      pvr_context_put(ctx);
++                      spin_lock(&pvr_dev->ctx_list_lock);
++              }
++              ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
++      }
++      spin_unlock(&pvr_dev->ctx_list_lock);
+ }
+ /**
+--- a/drivers/gpu/drm/imagination/pvr_context.h
++++ b/drivers/gpu/drm/imagination/pvr_context.h
+@@ -127,6 +127,24 @@ pvr_context_get(struct pvr_context *ctx)
+ }
+ /**
++ * pvr_context_get_if_referenced() - Take an additional reference on a still
++ * referenced context.
++ * @ctx: Context pointer.
++ *
++ * Call pvr_context_put() to release.
++ *
++ * Returns:
++ *  * True on success, or
++ *  * false if no context pointer passed, or the context wasn't still
++ *  * referenced.
++ */
++static __always_inline bool
++pvr_context_get_if_referenced(struct pvr_context *ctx)
++{
++      return ctx != NULL && kref_get_unless_zero(&ctx->ref_count) != 0;
++}
++
++/**
+  * pvr_context_lookup() - Lookup context pointer from handle and file.
+  * @pvr_file: Pointer to pvr_file structure.
+  * @handle: Context handle.
+--- a/drivers/gpu/drm/imagination/pvr_vm.c
++++ b/drivers/gpu/drm/imagination/pvr_vm.c
+@@ -14,6 +14,7 @@
+ #include <drm/drm_gem.h>
+ #include <drm/drm_gpuvm.h>
++#include <linux/bug.h>
+ #include <linux/container_of.h>
+ #include <linux/err.h>
+ #include <linux/errno.h>
+@@ -597,12 +598,26 @@ err_free:
+ }
+ /**
+- * pvr_vm_context_release() - Teardown a VM context.
+- * @ref_count: Pointer to reference counter of the VM context.
++ * pvr_vm_unmap_all() - Unmap all mappings associated with a VM context.
++ * @vm_ctx: Target VM context.
+  *
+  * This function ensures that no mappings are left dangling by unmapping them
+  * all in order of ascending device-virtual address.
+  */
++void
++pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx)
++{
++      WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start,
++                           vm_ctx->gpuvm_mgr.mm_range));
++}
++
++/**
++ * pvr_vm_context_release() - Teardown a VM context.
++ * @ref_count: Pointer to reference counter of the VM context.
++ *
++ * This function also ensures that no mappings are left dangling by calling
++ * pvr_vm_unmap_all.
++ */
+ static void
+ pvr_vm_context_release(struct kref *ref_count)
+ {
+@@ -612,8 +627,7 @@ pvr_vm_context_release(struct kref *ref_
+       if (vm_ctx->fw_mem_ctx_obj)
+               pvr_fw_object_destroy(vm_ctx->fw_mem_ctx_obj);
+-      WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start,
+-                           vm_ctx->gpuvm_mgr.mm_range));
++      pvr_vm_unmap_all(vm_ctx);
+       pvr_mmu_context_destroy(vm_ctx->mmu_ctx);
+       drm_gem_private_object_fini(&vm_ctx->dummy_gem);
+--- a/drivers/gpu/drm/imagination/pvr_vm.h
++++ b/drivers/gpu/drm/imagination/pvr_vm.h
+@@ -39,6 +39,7 @@ int pvr_vm_map(struct pvr_vm_context *vm
+              struct pvr_gem_object *pvr_obj, u64 pvr_obj_offset,
+              u64 device_addr, u64 size);
+ int pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size);
++void pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx);
+ dma_addr_t pvr_vm_get_page_table_root_addr(struct pvr_vm_context *vm_ctx);
+ struct dma_resv *pvr_vm_get_dma_resv(struct pvr_vm_context *vm_ctx);
diff --git a/queue-6.11/drm-panthor-be-stricter-about-io-mapping-flags.patch b/queue-6.11/drm-panthor-be-stricter-about-io-mapping-flags.patch
new file mode 100644 (file)
index 0000000..bfa7f65
--- /dev/null
@@ -0,0 +1,82 @@
+From f432a1621f049bb207e78363d9d0e3c6fa2da5db Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Tue, 5 Nov 2024 00:17:13 +0100
+Subject: drm/panthor: Be stricter about IO mapping flags
+
+From: Jann Horn <jannh@google.com>
+
+commit f432a1621f049bb207e78363d9d0e3c6fa2da5db upstream.
+
+The current panthor_device_mmap_io() implementation has two issues:
+
+1. For mapping DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET,
+   panthor_device_mmap_io() bails if VM_WRITE is set, but does not clear
+   VM_MAYWRITE. That means userspace can use mprotect() to make the mapping
+   writable later on. This is a classic Linux driver gotcha.
+   I don't think this actually has any impact in practice:
+   When the GPU is powered, writes to the FLUSH_ID seem to be ignored; and
+   when the GPU is not powered, the dummy_latest_flush page provided by the
+   driver is deliberately designed to not do any flushes, so the only thing
+   writing to the dummy_latest_flush could achieve would be to make *more*
+   flushes happen.
+
+2. panthor_device_mmap_io() does not block MAP_PRIVATE mappings (which are
+   mappings without the VM_SHARED flag).
+   MAP_PRIVATE in combination with VM_MAYWRITE indicates that the VMA has
+   copy-on-write semantics, which for VM_PFNMAP are semi-supported but
+   fairly cursed.
+   In particular, in such a mapping, the driver can only install PTEs
+   during mmap() by calling remap_pfn_range() (because remap_pfn_range()
+   wants to **store the physical address of the mapped physical memory into
+   the vm_pgoff of the VMA**); installing PTEs later on with a fault
+   handler (as panthor does) is not supported in private mappings, and so
+   if you try to fault in such a mapping, vmf_insert_pfn_prot() splats when
+   it hits a BUG() check.
+
+Fix it by clearing the VM_MAYWRITE flag (userspace writing to the FLUSH_ID
+doesn't make sense) and requiring VM_SHARED (copy-on-write semantics for
+the FLUSH_ID don't make sense).
+
+Reproducers for both scenarios are in the notes of my patch on the mailing
+list; I tested that these bugs exist on a Rock 5B machine.
+
+Note that I only compile-tested the patch, I haven't tested it; I don't
+have a working kernel build setup for the test machine yet. Please test it
+before applying it.
+
+Cc: stable@vger.kernel.org
+Fixes: 5fe909cae118 ("drm/panthor: Add the device logical block")
+Signed-off-by: Jann Horn <jannh@google.com>
+Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
+Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
+Reviewed-by: Steven Price <steven.price@arm.com>
+Signed-off-by: Steven Price <steven.price@arm.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241105-panthor-flush-page-fixes-v1-1-829aaf37db93@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/panthor/panthor_device.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
+index 4082c8f2951d..6fbff516c1c1 100644
+--- a/drivers/gpu/drm/panthor/panthor_device.c
++++ b/drivers/gpu/drm/panthor/panthor_device.c
+@@ -390,11 +390,15 @@ int panthor_device_mmap_io(struct panthor_device *ptdev, struct vm_area_struct *
+ {
+       u64 offset = (u64)vma->vm_pgoff << PAGE_SHIFT;
++      if ((vma->vm_flags & VM_SHARED) == 0)
++              return -EINVAL;
++
+       switch (offset) {
+       case DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET:
+               if (vma->vm_end - vma->vm_start != PAGE_SIZE ||
+                   (vma->vm_flags & (VM_WRITE | VM_EXEC)))
+                       return -EINVAL;
++              vm_flags_clear(vma, VM_MAYWRITE);
+               break;
+-- 
+2.47.0
+
diff --git a/queue-6.11/drm-panthor-lock-xarray-when-getting-entries-for-the-vm.patch b/queue-6.11/drm-panthor-lock-xarray-when-getting-entries-for-the-vm.patch
new file mode 100644 (file)
index 0000000..dc592ac
--- /dev/null
@@ -0,0 +1,42 @@
+From 444fa5b100e5c90550d6bccfe4476efb0391b3ca Mon Sep 17 00:00:00 2001
+From: Liviu Dudau <liviu.dudau@arm.com>
+Date: Wed, 6 Nov 2024 18:58:06 +0000
+Subject: drm/panthor: Lock XArray when getting entries for the VM
+
+From: Liviu Dudau <liviu.dudau@arm.com>
+
+commit 444fa5b100e5c90550d6bccfe4476efb0391b3ca upstream.
+
+Similar to commit cac075706f29 ("drm/panthor: Fix race when converting
+group handle to group object") we need to use the XArray's internal
+locking when retrieving a vm pointer from there.
+
+v2: Removed part of the patch that was trying to protect fetching
+the heap pointer from XArray, as that operation is protected by
+the @pool->lock.
+
+Fixes: 647810ec2476 ("drm/panthor: Add the MMU/VM logical block")
+Reported-by: Jann Horn <jannh@google.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
+Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
+Reviewed-by: Steven Price <steven.price@arm.com>
+Signed-off-by: Steven Price <steven.price@arm.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241106185806.389089-1-liviu.dudau@arm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/panthor/panthor_mmu.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/panthor/panthor_mmu.c
++++ b/drivers/gpu/drm/panthor/panthor_mmu.c
+@@ -1580,7 +1580,9 @@ panthor_vm_pool_get_vm(struct panthor_vm
+ {
+       struct panthor_vm *vm;
++      xa_lock(&pool->xa);
+       vm = panthor_vm_get(xa_load(&pool->xa, handle));
++      xa_unlock(&pool->xa);
+       return vm;
+ }
diff --git a/queue-6.11/keys-trusted-dcp-fix-null-dereference-in-aead-crypto-operation.patch b/queue-6.11/keys-trusted-dcp-fix-null-dereference-in-aead-crypto-operation.patch
new file mode 100644 (file)
index 0000000..5e171e3
--- /dev/null
@@ -0,0 +1,64 @@
+From 04de7589e0a95167d803ecadd115235ba2c14997 Mon Sep 17 00:00:00 2001
+From: David Gstir <david@sigma-star.at>
+Date: Tue, 29 Oct 2024 12:34:01 +0100
+Subject: KEYS: trusted: dcp: fix NULL dereference in AEAD crypto operation
+
+From: David Gstir <david@sigma-star.at>
+
+commit 04de7589e0a95167d803ecadd115235ba2c14997 upstream.
+
+When sealing or unsealing a key blob we currently do not wait for
+the AEAD cipher operation to finish and simply return after submitting
+the request. If there is some load on the system we can exit before
+the cipher operation is done and the buffer we read from/write to
+is already removed from the stack. This will e.g. result in NULL
+pointer dereference errors in the DCP driver during blob creation.
+
+Fix this by waiting for the AEAD cipher operation to finish before
+resuming the seal and unseal calls.
+
+Cc: stable@vger.kernel.org # v6.10+
+Fixes: 0e28bf61a5f9 ("KEYS: trusted: dcp: fix leak of blob encryption key")
+Reported-by: Parthiban N <parthiban@linumiz.com>
+Closes: https://lore.kernel.org/keyrings/254d3bb1-6dbc-48b4-9c08-77df04baee2f@linumiz.com/
+Signed-off-by: David Gstir <david@sigma-star.at>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/keys/trusted-keys/trusted_dcp.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/security/keys/trusted-keys/trusted_dcp.c
++++ b/security/keys/trusted-keys/trusted_dcp.c
+@@ -133,6 +133,7 @@ static int do_aead_crypto(u8 *in, u8 *ou
+       struct scatterlist src_sg, dst_sg;
+       struct crypto_aead *aead;
+       int ret;
++      DECLARE_CRYPTO_WAIT(wait);
+       aead = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(aead)) {
+@@ -163,8 +164,8 @@ static int do_aead_crypto(u8 *in, u8 *ou
+       }
+       aead_request_set_crypt(aead_req, &src_sg, &dst_sg, len, nonce);
+-      aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL,
+-                                NULL);
++      aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP,
++                                crypto_req_done, &wait);
+       aead_request_set_ad(aead_req, 0);
+       if (crypto_aead_setkey(aead, key, AES_KEYSIZE_128)) {
+@@ -174,9 +175,9 @@ static int do_aead_crypto(u8 *in, u8 *ou
+       }
+       if (do_encrypt)
+-              ret = crypto_aead_encrypt(aead_req);
++              ret = crypto_wait_req(crypto_aead_encrypt(aead_req), &wait);
+       else
+-              ret = crypto_aead_decrypt(aead_req);
++              ret = crypto_wait_req(crypto_aead_decrypt(aead_req), &wait);
+ free_req:
+       aead_request_free(aead_req);
diff --git a/queue-6.11/mptcp-no-admin-perm-to-list-endpoints.patch b/queue-6.11/mptcp-no-admin-perm-to-list-endpoints.patch
new file mode 100644 (file)
index 0000000..cbcb752
--- /dev/null
@@ -0,0 +1,58 @@
+From cfbbd4859882a5469f6f4945937a074ee78c4b46 Mon Sep 17 00:00:00 2001
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Mon, 4 Nov 2024 13:31:41 +0100
+Subject: mptcp: no admin perm to list endpoints
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+commit cfbbd4859882a5469f6f4945937a074ee78c4b46 upstream.
+
+During the switch to YNL, the command to list all endpoints has been
+accidentally restricted to users with admin permissions.
+
+It looks like there are no reasons to have this restriction which makes
+it harder for a user to quickly check if the endpoint list has been
+correctly populated by an automated tool. Best to go back to the
+previous behaviour then.
+
+mptcp_pm_gen.c has been modified using ynl-gen-c.py:
+
+   $ ./tools/net/ynl/ynl-gen-c.py --mode kernel \
+     --spec Documentation/netlink/specs/mptcp_pm.yaml --source \
+     -o net/mptcp/mptcp_pm_gen.c
+
+The header file doesn't need to be regenerated.
+
+Fixes: 1d0507f46843 ("net: mptcp: convert netlink from small_ops to ops")
+Cc: stable@vger.kernel.org
+Reviewed-by: Davide Caratti <dcaratti@redhat.com>
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20241104-net-mptcp-misc-6-12-v1-1-c13f2ff1656f@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/netlink/specs/mptcp_pm.yaml |    1 -
+ net/mptcp/mptcp_pm_gen.c                  |    1 -
+ 2 files changed, 2 deletions(-)
+
+--- a/Documentation/netlink/specs/mptcp_pm.yaml
++++ b/Documentation/netlink/specs/mptcp_pm.yaml
+@@ -293,7 +293,6 @@ operations:
+       doc: Get endpoint information
+       attribute-set: attr
+       dont-validate: [ strict ]
+-      flags: [ uns-admin-perm ]
+       do: &get-addr-attrs
+         request:
+           attributes:
+--- a/net/mptcp/mptcp_pm_gen.c
++++ b/net/mptcp/mptcp_pm_gen.c
+@@ -112,7 +112,6 @@ const struct genl_ops mptcp_pm_nl_ops[11
+               .dumpit         = mptcp_pm_nl_get_addr_dumpit,
+               .policy         = mptcp_pm_get_addr_nl_policy,
+               .maxattr        = MPTCP_PM_ATTR_TOKEN,
+-              .flags          = GENL_UNS_ADMIN_PERM,
+       },
+       {
+               .cmd            = MPTCP_PM_CMD_FLUSH_ADDRS,
diff --git a/queue-6.11/pwm-imx-tpm-use-correct-modulo-value-for-epwm-mode.patch b/queue-6.11/pwm-imx-tpm-use-correct-modulo-value-for-epwm-mode.patch
new file mode 100644 (file)
index 0000000..92822d5
--- /dev/null
@@ -0,0 +1,44 @@
+From cc6a931d1f3b412263d515fd93b21fc0ca5147fe Mon Sep 17 00:00:00 2001
+From: Erik Schumacher <erik.schumacher@iris-sensing.com>
+Date: Fri, 25 Oct 2024 08:37:00 +0000
+Subject: pwm: imx-tpm: Use correct MODULO value for EPWM mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Erik Schumacher <erik.schumacher@iris-sensing.com>
+
+commit cc6a931d1f3b412263d515fd93b21fc0ca5147fe upstream.
+
+The modulo register defines the period of the edge-aligned PWM mode
+(which is the only mode implemented). The reference manual states:
+"The EPWM period is determined by (MOD + 0001h) ..." So the value that
+is written to the MOD register must therefore be one less than the
+calculated period length. Return -EINVAL if the calculated length is
+already zero.
+A correct MODULO value is particularly relevant if the PWM has to output
+a high frequency due to a low period value.
+
+Fixes: 738a1cfec2ed ("pwm: Add i.MX TPM PWM driver support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Erik Schumacher <erik.schumacher@iris-sensing.com>
+Link: https://lore.kernel.org/r/1a3890966d68b9f800d457cbf095746627495e18.camel@iris-sensing.com
+Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pwm/pwm-imx-tpm.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/pwm/pwm-imx-tpm.c
++++ b/drivers/pwm/pwm-imx-tpm.c
+@@ -106,7 +106,9 @@ static int pwm_imx_tpm_round_state(struc
+       p->prescale = prescale;
+       period_count = (clock_unit + ((1 << prescale) >> 1)) >> prescale;
+-      p->mod = period_count;
++      if (period_count == 0)
++              return -EINVAL;
++      p->mod = period_count - 1;
+       /* calculate real period HW can support */
+       tmp = (u64)period_count << prescale;
diff --git a/queue-6.11/rpmsg-glink-handle-rejected-intent-request-better.patch b/queue-6.11/rpmsg-glink-handle-rejected-intent-request-better.patch
new file mode 100644 (file)
index 0000000..d6378c6
--- /dev/null
@@ -0,0 +1,99 @@
+From a387e73fedd6307c0e194deaa53c42b153ff0bd6 Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Date: Wed, 23 Oct 2024 17:24:32 +0000
+Subject: rpmsg: glink: Handle rejected intent request better
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+commit a387e73fedd6307c0e194deaa53c42b153ff0bd6 upstream.
+
+GLINK operates using pre-allocated buffers, aka intents, where incoming
+messages are aggregated before being passed up the stack. In the case
+that no suitable intents have been announced by the receiver, the sender
+can request an intent to be allocated.
+
+The initial implementation of the response to such request dealt
+with two outcomes; granted allocations, and all other cases being
+considered -ECANCELLED (likely from "cancelling the operation as the
+remote is going down").
+
+But on some channels intent allocation is not supported, instead the
+remote will pre-allocate and announce a fixed number of intents for the
+sender to use. If for such channels an rpmsg_send() is being invoked
+before any channels have been announced, an intent request will be
+issued and as this comes back rejected the call fails with -ECANCELED.
+
+Given that this is reported in the same way as the remote being shut
+down, there's no way for the client to differentiate the two cases.
+
+In line with the original GLINK design, change the return value to
+-EAGAIN for the case where the remote rejects an intent allocation
+request.
+
+It's tempting to handle this case in the GLINK core, as we expect
+intents to show up in this case. But there's no way to distinguish
+between this case and a rejection for a too big allocation, nor is it
+possible to predict if a currently used (and seemingly suitable) intent
+will be returned for reuse or not. As such, returning the error to the
+client and allow it to react seems to be the only sensible solution.
+
+In addition to this, commit 'c05dfce0b89e ("rpmsg: glink: Wait for
+intent, not just request ack")' changed the logic such that the code
+always wait for an intent request response and an intent. This works out
+in most cases, but in the event that an intent request is rejected and no
+further intent arrives (e.g. client asks for a too big intent), the code
+will stall for 10 seconds and then return -ETIMEDOUT; instead of a more
+suitable error.
+
+This change also resulted in intent requests racing with the shutdown of
+the remote would be exposed to this same problem, unless some intent
+happens to arrive. A patch for this was developed and posted by Sarannya
+S [1], and has been incorporated here.
+
+To summarize, the intent request can end in 4 ways:
+- Timeout, no response arrived => return -ETIMEDOUT
+- Abort TX, the edge is going away => return -ECANCELLED
+- Intent request was rejected => return -EAGAIN
+- Intent request was accepted, and an intent arrived => return 0
+
+This patch was developed with input from Sarannya S, Deepak Kumar Singh,
+and Chris Lew.
+
+[1] https://lore.kernel.org/all/20240925072328.1163183-1-quic_deesin@quicinc.com/
+
+Fixes: c05dfce0b89e ("rpmsg: glink: Wait for intent, not just request ack")
+Cc: stable@vger.kernel.org
+Tested-by: Johan Hovold <johan+linaro@kernel.org>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Link: https://lore.kernel.org/r/20241023-pmic-glink-ecancelled-v2-1-ebc268129407@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/rpmsg/qcom_glink_native.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/rpmsg/qcom_glink_native.c
++++ b/drivers/rpmsg/qcom_glink_native.c
+@@ -1354,14 +1354,18 @@ static int qcom_glink_request_intent(str
+               goto unlock;
+       ret = wait_event_timeout(channel->intent_req_wq,
+-                               READ_ONCE(channel->intent_req_result) >= 0 &&
+-                               READ_ONCE(channel->intent_received),
++                               READ_ONCE(channel->intent_req_result) == 0 ||
++                               (READ_ONCE(channel->intent_req_result) > 0 &&
++                                READ_ONCE(channel->intent_received)) ||
++                               glink->abort_tx,
+                                10 * HZ);
+       if (!ret) {
+               dev_err(glink->dev, "intent request timed out\n");
+               ret = -ETIMEDOUT;
++      } else if (glink->abort_tx) {
++              ret = -ECANCELED;
+       } else {
+-              ret = READ_ONCE(channel->intent_req_result) ? 0 : -ECANCELED;
++              ret = READ_ONCE(channel->intent_req_result) ? 0 : -EAGAIN;
+       }
+ unlock:
index ed42b9298857517423e7c3480994950170ac704c..424a4cd280b39f7dfeadf3af6b03d2bf0520d84b 100644 (file)
@@ -93,3 +93,30 @@ ksmbd-fix-slab-use-after-free-in-smb3_preauth_hash_rsp.patch
 drm-xe-fix-possible-exec-queue-leak-in-exec-ioctl.patch
 drm-xe-drop-vm-dma-resv-lock-on-xe_sync_in_fence_get-failure-in-exec-ioctl.patch
 drm-xe-set-mask-bits-for-ccs_mode-register.patch
+pwm-imx-tpm-use-correct-modulo-value-for-epwm-mode.patch
+tpm-lock-tpm-chip-in-tpm_pm_suspend-first.patch
+rpmsg-glink-handle-rejected-intent-request-better.patch
+drm-amd-pm-always-pick-the-pptable-from-ifwi.patch
+drm-amd-display-fix-brightness-level-not-retained-over-reboot.patch
+drm-imagination-add-a-per-file-pvr-context-list.patch
+drm-imagination-break-an-object-reference-loop.patch
+drm-amd-pm-correct-the-workload-setting.patch
+drm-amd-display-parse-umc_info-or-vram_info-based-on-asic.patch
+drm-panthor-lock-xarray-when-getting-entries-for-the-vm.patch
+drm-panthor-be-stricter-about-io-mapping-flags.patch
+drm-amdgpu-adjust-debugfs-eviction-and-ib-access-permissions.patch
+drm-amdgpu-add-missing-size-check-in-amdgpu_debugfs_gprwave_read.patch
+drm-amdgpu-adjust-debugfs-register-access-permissions.patch
+drm-amdgpu-fix-dpx-valid-mode-check-on-gc-9.4.3.patch
+drm-amdgpu-prevent-null-pointer-dereference-if-atif-is-not-supported.patch
+thermal-drivers-qcom-lmh-remove-false-lockdep-backtrace.patch
+keys-trusted-dcp-fix-null-dereference-in-aead-crypto-operation.patch
+dm-cache-correct-the-number-of-origin-blocks-to-match-the-target-length.patch
+dm-cache-fix-flushing-uninitialized-delayed_work-on-cache_ctr-error.patch
+dm-cache-fix-out-of-bounds-access-to-the-dirty-bitset-when-resizing.patch
+dm-cache-optimize-dirty-bit-checking-with-find_next_bit-when-resizing.patch
+dm-cache-fix-potential-out-of-bounds-access-on-the-first-resume.patch
+dm-unstriped-cast-an-operand-to-sector_t-to-prevent-potential-uint32_t-overflow.patch
+dm-fix-a-crash-if-blk_alloc_disk-fails.patch
+mptcp-no-admin-perm-to-list-endpoints.patch
+alsa-usb-audio-add-quirk-for-hp-320-fhd-webcam.patch
diff --git a/queue-6.11/thermal-drivers-qcom-lmh-remove-false-lockdep-backtrace.patch b/queue-6.11/thermal-drivers-qcom-lmh-remove-false-lockdep-backtrace.patch
new file mode 100644 (file)
index 0000000..4af5abd
--- /dev/null
@@ -0,0 +1,86 @@
+From f16beaaee248eaa37ad40b5905924fcf70ae02e3 Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Fri, 11 Oct 2024 08:48:39 +0300
+Subject: thermal/drivers/qcom/lmh: Remove false lockdep backtrace
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+commit f16beaaee248eaa37ad40b5905924fcf70ae02e3 upstream.
+
+Annotate LMH IRQs with lockdep classes so that the lockdep doesn't
+report possible recursive locking issue between LMH and GIC interrupts.
+
+For the reference:
+
+       CPU0
+       ----
+  lock(&irq_desc_lock_class);
+  lock(&irq_desc_lock_class);
+
+ *** DEADLOCK ***
+
+Call trace:
+ dump_backtrace+0x98/0xf0
+ show_stack+0x18/0x24
+ dump_stack_lvl+0x90/0xd0
+ dump_stack+0x18/0x24
+ print_deadlock_bug+0x258/0x348
+ __lock_acquire+0x1078/0x1f44
+ lock_acquire+0x1fc/0x32c
+ _raw_spin_lock_irqsave+0x60/0x88
+ __irq_get_desc_lock+0x58/0x98
+ enable_irq+0x38/0xa0
+ lmh_enable_interrupt+0x2c/0x38
+ irq_enable+0x40/0x8c
+ __irq_startup+0x78/0xa4
+ irq_startup+0x78/0x168
+ __enable_irq+0x70/0x7c
+ enable_irq+0x4c/0xa0
+ qcom_cpufreq_ready+0x20/0x2c
+ cpufreq_online+0x2a8/0x988
+ cpufreq_add_dev+0x80/0x98
+ subsys_interface_register+0x104/0x134
+ cpufreq_register_driver+0x150/0x234
+ qcom_cpufreq_hw_driver_probe+0x2a8/0x388
+ platform_probe+0x68/0xc0
+ really_probe+0xbc/0x298
+ __driver_probe_device+0x78/0x12c
+ driver_probe_device+0x3c/0x160
+ __device_attach_driver+0xb8/0x138
+ bus_for_each_drv+0x84/0xe0
+ __device_attach+0x9c/0x188
+ device_initial_probe+0x14/0x20
+ bus_probe_device+0xac/0xb0
+ deferred_probe_work_func+0x8c/0xc8
+ process_one_work+0x20c/0x62c
+ worker_thread+0x1bc/0x36c
+ kthread+0x120/0x124
+ ret_from_fork+0x10/0x20
+
+Fixes: 53bca371cdf7 ("thermal/drivers/qcom: Add support for LMh driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20241011-lmh-lockdep-v1-1-495cbbe6fef1@linaro.org
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thermal/qcom/lmh.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/thermal/qcom/lmh.c
++++ b/drivers/thermal/qcom/lmh.c
+@@ -73,7 +73,14 @@ static struct irq_chip lmh_irq_chip = {
+ static int lmh_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+ {
+       struct lmh_hw_data *lmh_data = d->host_data;
++      static struct lock_class_key lmh_lock_key;
++      static struct lock_class_key lmh_request_key;
++      /*
++       * This lock class tells lockdep that GPIO irqs are in a different
++       * category than their parents, so it won't report false recursion.
++       */
++      irq_set_lockdep_class(irq, &lmh_lock_key, &lmh_request_key);
+       irq_set_chip_and_handler(irq, &lmh_irq_chip, handle_simple_irq);
+       irq_set_chip_data(irq, lmh_data);
diff --git a/queue-6.11/tpm-lock-tpm-chip-in-tpm_pm_suspend-first.patch b/queue-6.11/tpm-lock-tpm-chip-in-tpm_pm_suspend-first.patch
new file mode 100644 (file)
index 0000000..f4c8294
--- /dev/null
@@ -0,0 +1,110 @@
+From 9265fed6db601ee2ec47577815387458ef4f047a Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko@kernel.org>
+Date: Thu, 31 Oct 2024 02:16:09 +0200
+Subject: tpm: Lock TPM chip in tpm_pm_suspend() first
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+commit 9265fed6db601ee2ec47577815387458ef4f047a upstream.
+
+Setting TPM_CHIP_FLAG_SUSPENDED in the end of tpm_pm_suspend() can be racy
+according, as this leaves window for tpm_hwrng_read() to be called while
+the operation is in progress. The recent bug report gives also evidence of
+this behaviour.
+
+Aadress this by locking the TPM chip before checking any chip->flags both
+in tpm_pm_suspend() and tpm_hwrng_read(). Move TPM_CHIP_FLAG_SUSPENDED
+check inside tpm_get_random() so that it will be always checked only when
+the lock is reserved.
+
+Cc: stable@vger.kernel.org # v6.4+
+Fixes: 99d464506255 ("tpm: Prevent hwrng from activating during resume")
+Reported-by: Mike Seo <mikeseohyungjin@gmail.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219383
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Tested-by: Mike Seo <mikeseohyungjin@gmail.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm-chip.c      |    4 ----
+ drivers/char/tpm/tpm-interface.c |   32 ++++++++++++++++++++++----------
+ 2 files changed, 22 insertions(+), 14 deletions(-)
+
+--- a/drivers/char/tpm/tpm-chip.c
++++ b/drivers/char/tpm/tpm-chip.c
+@@ -525,10 +525,6 @@ static int tpm_hwrng_read(struct hwrng *
+ {
+       struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
+-      /* Give back zero bytes, as TPM chip has not yet fully resumed: */
+-      if (chip->flags & TPM_CHIP_FLAG_SUSPENDED)
+-              return 0;
+-
+       return tpm_get_random(chip, data, max);
+ }
+--- a/drivers/char/tpm/tpm-interface.c
++++ b/drivers/char/tpm/tpm-interface.c
+@@ -370,6 +370,13 @@ int tpm_pm_suspend(struct device *dev)
+       if (!chip)
+               return -ENODEV;
++      rc = tpm_try_get_ops(chip);
++      if (rc) {
++              /* Can be safely set out of locks, as no action cannot race: */
++              chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
++              goto out;
++      }
++
+       if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
+               goto suspended;
+@@ -377,21 +384,19 @@ int tpm_pm_suspend(struct device *dev)
+           !pm_suspend_via_firmware())
+               goto suspended;
+-      rc = tpm_try_get_ops(chip);
+-      if (!rc) {
+-              if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+-                      tpm2_end_auth_session(chip);
+-                      tpm2_shutdown(chip, TPM2_SU_STATE);
+-              } else {
+-                      rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
+-              }
+-
+-              tpm_put_ops(chip);
++      if (chip->flags & TPM_CHIP_FLAG_TPM2) {
++              tpm2_end_auth_session(chip);
++              tpm2_shutdown(chip, TPM2_SU_STATE);
++              goto suspended;
+       }
++      rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
++
+ suspended:
+       chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
++      tpm_put_ops(chip);
++out:
+       if (rc)
+               dev_err(dev, "Ignoring error %d while suspending\n", rc);
+       return 0;
+@@ -440,11 +445,18 @@ int tpm_get_random(struct tpm_chip *chip
+       if (!chip)
+               return -ENODEV;
++      /* Give back zero bytes, as TPM chip has not yet fully resumed: */
++      if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) {
++              rc = 0;
++              goto out;
++      }
++
+       if (chip->flags & TPM_CHIP_FLAG_TPM2)
+               rc = tpm2_get_random(chip, out, max);
+       else
+               rc = tpm1_get_random(chip, out, max);
++out:
+       tpm_put_ops(chip);
+       return rc;
+ }